A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

242 lignes
4.9 KiB

  1. #include <assert.h>
  2. #include <errno.h>
  3. #include <inttypes.h>
  4. #include <fcntl.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <openssl/sha.h>
  8. #include "metainfo.h"
  9. #include "subr.h"
  10. #include "stream.h"
  11. struct bt_stream_ro *
  12. bts_open_ro(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg)
  13. {
  14. struct bt_stream_ro *bts = malloc(sizeof(*bts));
  15. if (bts == NULL)
  16. return NULL;
  17. bts->meta = meta;
  18. bts->fd_cb = fd_cb;
  19. bts->fd_arg = fd_arg;
  20. bts->t_off = 0;
  21. bts->f_off = 0;
  22. bts->index = 0;
  23. bts->fd = -1;
  24. bts_seek_ro(bts, off);
  25. return bts;
  26. }
  27. void
  28. bts_seek_ro(struct bt_stream_ro *bts, off_t off)
  29. {
  30. struct fileinfo *files = bts->meta->files;
  31. assert(off >= 0 && off <= bts->meta->total_length);
  32. if (bts->fd != -1) {
  33. close(bts->fd);
  34. bts->fd = -1;
  35. }
  36. bts->t_off = off;
  37. bts->index = 0;
  38. while (off >= files[bts->index].length) {
  39. off -= files[bts->index].length;
  40. bts->index++;
  41. }
  42. bts->f_off = off;
  43. }
  44. int
  45. bts_read_ro(struct bt_stream_ro *bts, char *buf, size_t len)
  46. {
  47. struct fileinfo *files = bts->meta->files;
  48. size_t boff, wantread;
  49. ssize_t didread;
  50. assert(bts->t_off + len <= bts->meta->total_length);
  51. boff = 0;
  52. while (boff < len) {
  53. if (bts->fd == -1) {
  54. int err =
  55. bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
  56. if (err != 0)
  57. return err;
  58. if (bts->f_off != 0)
  59. lseek(bts->fd, bts->f_off, SEEK_SET);
  60. }
  61. wantread = min(len - boff, files[bts->index].length - bts->f_off);
  62. again:
  63. didread = read(bts->fd, buf + boff, wantread);
  64. if (didread == -1) {
  65. if (errno == EINTR)
  66. goto again;
  67. else
  68. return errno;
  69. }
  70. boff += didread;
  71. bts->f_off += didread;
  72. bts->t_off += didread;
  73. if (bts->f_off == files[bts->index].length) {
  74. close(bts->fd);
  75. bts->fd = -1;
  76. bts->f_off = 0;
  77. bts->index++;
  78. }
  79. if (didread != wantread)
  80. return ENOENT;
  81. }
  82. return 0;
  83. }
  84. void
  85. bts_close_ro(struct bt_stream_ro *bts)
  86. {
  87. if (bts->fd != -1)
  88. close(bts->fd);
  89. free(bts);
  90. }
  91. #define SHAFILEBUF (1 << 15)
  92. int
  93. bts_sha(struct bt_stream_ro *bts, off_t length, uint8_t *hash)
  94. {
  95. SHA_CTX ctx;
  96. char buf[SHAFILEBUF];
  97. size_t wantread;
  98. int err = 0;
  99. SHA1_Init(&ctx);
  100. while (length > 0) {
  101. wantread = min(length, SHAFILEBUF);
  102. if ((err = bts_read_ro(bts, buf, wantread)) != 0)
  103. break;
  104. length -= wantread;
  105. SHA1_Update(&ctx, buf, wantread);
  106. }
  107. SHA1_Final(hash, &ctx);
  108. return err;
  109. }
  110. int
  111. bts_hashes(struct metainfo *meta,
  112. F_fdcb fd_cb,
  113. void (*cb)(uint32_t, uint8_t *, void *),
  114. void *arg)
  115. {
  116. int err = 0;
  117. uint8_t hash[SHA_DIGEST_LENGTH];
  118. uint32_t piece;
  119. struct bt_stream_ro *bts;
  120. off_t plen = meta->piece_length;
  121. off_t llen = meta->total_length % plen;
  122. if ((bts = bts_open_ro(meta, 0, fd_cb, arg)) == NULL)
  123. return ENOMEM;
  124. for (piece = 0; piece < meta->npieces; piece++) {
  125. if (piece < meta->npieces - 1)
  126. err = bts_sha(bts, plen, hash);
  127. else
  128. err = bts_sha(bts, llen, hash);
  129. if (err == 0)
  130. cb(piece, hash, arg);
  131. else if (err == ENOENT) {
  132. cb(piece, NULL, arg);
  133. if (piece < meta->npieces - 1)
  134. bts_seek_ro(bts, (piece + 1) * plen);
  135. err = 0;
  136. } else
  137. break;
  138. }
  139. bts_close_ro(bts);
  140. return err;
  141. }
  142. struct bt_stream_wo *
  143. bts_open_wo(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg)
  144. {
  145. struct bt_stream_wo *bts = malloc(sizeof(*bts));
  146. if (bts == NULL)
  147. return NULL;
  148. bts->meta = meta;
  149. bts->fd_cb = fd_cb;
  150. bts->fd_arg = fd_arg;
  151. bts->t_off = 0;
  152. bts->f_off = 0;
  153. bts->index = 0;
  154. bts->fd = -1;
  155. bts_seek_ro((struct bt_stream_ro *)bts, off);
  156. return bts;
  157. }
  158. int
  159. bts_write_wo(struct bt_stream_wo *bts, const char *buf, size_t len)
  160. {
  161. struct fileinfo *files = bts->meta->files;
  162. size_t boff, wantwrite;
  163. ssize_t didwrite;
  164. assert(bts->t_off + len <= bts->meta->total_length);
  165. boff = 0;
  166. while (boff < len) {
  167. if (bts->fd == -1) {
  168. int err =
  169. bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
  170. if (err != 0)
  171. return err;
  172. if (bts->f_off != 0)
  173. lseek(bts->fd, bts->f_off, SEEK_SET);
  174. }
  175. wantwrite = min(len - boff, files[bts->index].length - bts->f_off);
  176. didwrite = write(bts->fd, buf + boff, wantwrite);
  177. if (didwrite == -1)
  178. return errno;
  179. boff += didwrite;
  180. bts->f_off += didwrite;
  181. bts->t_off += didwrite;
  182. if (bts->f_off == files[bts->index].length) {
  183. if (fsync(bts->fd) == -1) {
  184. int err = errno;
  185. close(bts->fd);
  186. return err;
  187. }
  188. if (close(bts->fd) == -1)
  189. return errno;
  190. bts->fd = -1;
  191. bts->f_off = 0;
  192. bts->index++;
  193. }
  194. }
  195. return 0;
  196. }
  197. int
  198. bts_close_wo(struct bt_stream_wo *bts)
  199. {
  200. int err = 0;
  201. if (bts->fd != -1) {
  202. if (fsync(bts->fd) == -1) {
  203. err = errno;
  204. close(bts->fd);
  205. } else if (close(bts->fd) == -1)
  206. err = errno;
  207. }
  208. free(bts);
  209. return err;
  210. }