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.

211 lignes
4.8 KiB

  1. #include <assert.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <inttypes.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. int
  12. bts_open(struct bt_stream **res, struct metainfo *meta, fdcb_t fd_cb,
  13. void *fd_arg)
  14. {
  15. struct bt_stream *bts = calloc(1, sizeof(*bts));
  16. if (bts == NULL)
  17. return ENOMEM;
  18. bts->meta = meta;
  19. bts->fd_cb = fd_cb;
  20. bts->fd_arg = fd_arg;
  21. bts->fd = -1;
  22. *res = bts;
  23. return 0;
  24. }
  25. int
  26. bts_close(struct bt_stream *bts)
  27. {
  28. int err = 0;
  29. if (bts->fd != -1 && close(bts->fd) == -1)
  30. err = errno;
  31. free(bts);
  32. return err;
  33. }
  34. int
  35. bts_seek(struct bt_stream *bts, off_t off)
  36. {
  37. if (bts->t_off == off)
  38. return 0;
  39. bts->t_off = off;
  40. struct fileinfo *files = bts->meta->files;
  41. unsigned i;
  42. for (i = 0; off >= files[i].length; i++)
  43. off -= files[i].length;
  44. if (i != bts->index) {
  45. if (bts->fd != -1) {
  46. if (close(bts->fd) == -1)
  47. return errno;
  48. bts->fd = -1;
  49. }
  50. } else if (bts->fd != -1)
  51. lseek(bts->fd, off, SEEK_SET);
  52. bts->index = i;
  53. bts->f_off = off;
  54. return 0;
  55. }
  56. int
  57. bts_get(struct bt_stream *bts, off_t off, uint8_t *buf, size_t len)
  58. {
  59. struct fileinfo *files = bts->meta->files;
  60. size_t boff, wantread;
  61. ssize_t didread;
  62. int err;
  63. assert(off + len <= bts->meta->total_length);
  64. if ((err = bts_seek(bts, off)) != 0)
  65. return err;
  66. boff = 0;
  67. while (boff < len) {
  68. if (bts->fd == -1) {
  69. err = bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
  70. if (err != 0)
  71. return err;
  72. if (bts->f_off != 0)
  73. lseek(bts->fd, bts->f_off, SEEK_SET);
  74. }
  75. wantread = min(len - boff, files[bts->index].length - bts->f_off);
  76. didread = read(bts->fd, buf + boff, wantread);
  77. if (didread == -1)
  78. return errno;
  79. boff += didread;
  80. bts->f_off += didread;
  81. bts->t_off += didread;
  82. if (bts->f_off == files[bts->index].length) {
  83. close(bts->fd);
  84. bts->fd = -1;
  85. bts->f_off = 0;
  86. bts->index++;
  87. }
  88. if (didread != wantread)
  89. return ENOENT;
  90. }
  91. return 0;
  92. }
  93. int
  94. bts_put(struct bt_stream *bts, off_t off, const uint8_t *buf, size_t len)
  95. {
  96. struct fileinfo *files = bts->meta->files;
  97. size_t boff, wantwrite;
  98. ssize_t didwrite;
  99. int err;
  100. assert(off + len <= bts->meta->total_length);
  101. if ((err = bts_seek(bts, off)) != 0)
  102. return err;
  103. boff = 0;
  104. while (boff < len) {
  105. if (bts->fd == -1) {
  106. err = bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
  107. if (err != 0)
  108. return err;
  109. if (bts->f_off != 0)
  110. lseek(bts->fd, bts->f_off, SEEK_SET);
  111. }
  112. wantwrite = min(len - boff, files[bts->index].length - bts->f_off);
  113. didwrite = write(bts->fd, buf + boff, wantwrite);
  114. if (didwrite == -1)
  115. return errno;
  116. boff += didwrite;
  117. bts->f_off += didwrite;
  118. bts->t_off += didwrite;
  119. if (bts->f_off == files[bts->index].length) {
  120. if (fsync(bts->fd) == -1) {
  121. int err = errno;
  122. close(bts->fd);
  123. return err;
  124. }
  125. if (close(bts->fd) == -1)
  126. return errno;
  127. bts->fd = -1;
  128. bts->f_off = 0;
  129. bts->index++;
  130. }
  131. }
  132. return 0;
  133. }
  134. #define SHAFILEBUF (1 << 15)
  135. int
  136. bts_sha(struct bt_stream *bts, off_t start, off_t length, uint8_t *hash)
  137. {
  138. SHA_CTX ctx;
  139. char buf[SHAFILEBUF];
  140. size_t wantread;
  141. int err = 0;
  142. SHA1_Init(&ctx);
  143. while (length > 0) {
  144. wantread = min(length, SHAFILEBUF);
  145. if ((err = bts_get(bts, start, buf, wantread)) != 0)
  146. break;
  147. length -= wantread;
  148. start += wantread;
  149. SHA1_Update(&ctx, buf, wantread);
  150. }
  151. SHA1_Final(hash, &ctx);
  152. return err;
  153. }
  154. int
  155. bts_hashes(struct metainfo *meta, fdcb_t fd_cb, hashcb_t cb, void *arg)
  156. {
  157. int err = 0;
  158. uint8_t hash[SHA_DIGEST_LENGTH];
  159. uint32_t piece;
  160. struct bt_stream *bts;
  161. off_t plen = meta->piece_length;
  162. off_t llen = meta->total_length % plen;
  163. if ((err = bts_open(&bts, meta, fd_cb, arg)) != 0)
  164. return err;
  165. for (piece = 0; piece < meta->npieces; piece++) {
  166. off_t start = piece * plen;
  167. if (piece < meta->npieces - 1)
  168. err = bts_sha(bts, start, plen, hash);
  169. else
  170. err = bts_sha(bts, start, llen, hash);
  171. if (err == 0)
  172. cb(piece, hash, arg);
  173. else if (err == ENOENT) {
  174. cb(piece, NULL, arg);
  175. err = 0;
  176. } else
  177. break;
  178. }
  179. bts_close(bts);
  180. return err;
  181. }