A clone of btpd with my configuration changes.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

237 行
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. 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. didread = read(bts->fd, buf + boff, wantread);
  63. if (didread == -1)
  64. return errno;
  65. boff += didread;
  66. bts->f_off += didread;
  67. bts->t_off += didread;
  68. if (bts->f_off == files[bts->index].length) {
  69. close(bts->fd);
  70. bts->fd = -1;
  71. bts->f_off = 0;
  72. bts->index++;
  73. }
  74. if (didread != wantread)
  75. return ENOENT;
  76. }
  77. return 0;
  78. }
  79. void
  80. bts_close_ro(struct bt_stream_ro *bts)
  81. {
  82. if (bts->fd != -1)
  83. close(bts->fd);
  84. free(bts);
  85. }
  86. #define SHAFILEBUF (1 << 15)
  87. int
  88. bts_sha(struct bt_stream_ro *bts, off_t length, uint8_t *hash)
  89. {
  90. SHA_CTX ctx;
  91. char buf[SHAFILEBUF];
  92. size_t wantread;
  93. int err = 0;
  94. SHA1_Init(&ctx);
  95. while (length > 0) {
  96. wantread = min(length, SHAFILEBUF);
  97. if ((err = bts_read_ro(bts, buf, wantread)) != 0)
  98. break;
  99. length -= wantread;
  100. SHA1_Update(&ctx, buf, wantread);
  101. }
  102. SHA1_Final(hash, &ctx);
  103. return err;
  104. }
  105. int
  106. bts_hashes(struct metainfo *meta,
  107. F_fdcb fd_cb,
  108. void (*cb)(uint32_t, uint8_t *, void *),
  109. void *arg)
  110. {
  111. int err = 0;
  112. uint8_t hash[SHA_DIGEST_LENGTH];
  113. uint32_t piece;
  114. struct bt_stream_ro *bts;
  115. off_t plen = meta->piece_length;
  116. off_t llen = meta->total_length % plen;
  117. if ((bts = bts_open_ro(meta, 0, fd_cb, arg)) == NULL)
  118. return ENOMEM;
  119. for (piece = 0; piece < meta->npieces; piece++) {
  120. if (piece < meta->npieces - 1)
  121. err = bts_sha(bts, plen, hash);
  122. else
  123. err = bts_sha(bts, llen, hash);
  124. if (err == 0)
  125. cb(piece, hash, arg);
  126. else if (err == ENOENT) {
  127. cb(piece, NULL, arg);
  128. if (piece < meta->npieces - 1)
  129. bts_seek_ro(bts, (piece + 1) * plen);
  130. err = 0;
  131. } else
  132. break;
  133. }
  134. bts_close_ro(bts);
  135. return err;
  136. }
  137. struct bt_stream_wo *
  138. bts_open_wo(struct metainfo *meta, off_t off, F_fdcb fd_cb, void *fd_arg)
  139. {
  140. struct bt_stream_wo *bts = malloc(sizeof(*bts));
  141. if (bts == NULL)
  142. return NULL;
  143. bts->meta = meta;
  144. bts->fd_cb = fd_cb;
  145. bts->fd_arg = fd_arg;
  146. bts->t_off = 0;
  147. bts->f_off = 0;
  148. bts->index = 0;
  149. bts->fd = -1;
  150. bts_seek_ro((struct bt_stream_ro *)bts, off);
  151. return bts;
  152. }
  153. int
  154. bts_write_wo(struct bt_stream_wo *bts, const char *buf, size_t len)
  155. {
  156. struct fileinfo *files = bts->meta->files;
  157. size_t boff, wantwrite;
  158. ssize_t didwrite;
  159. assert(bts->t_off + len <= bts->meta->total_length);
  160. boff = 0;
  161. while (boff < len) {
  162. if (bts->fd == -1) {
  163. int err =
  164. bts->fd_cb(files[bts->index].path, &bts->fd, bts->fd_arg);
  165. if (err != 0)
  166. return err;
  167. if (bts->f_off != 0)
  168. lseek(bts->fd, bts->f_off, SEEK_SET);
  169. }
  170. wantwrite = min(len - boff, files[bts->index].length - bts->f_off);
  171. didwrite = write(bts->fd, buf + boff, wantwrite);
  172. if (didwrite == -1)
  173. return errno;
  174. boff += didwrite;
  175. bts->f_off += didwrite;
  176. bts->t_off += didwrite;
  177. if (bts->f_off == files[bts->index].length) {
  178. if (fsync(bts->fd) == -1) {
  179. int err = errno;
  180. close(bts->fd);
  181. return err;
  182. }
  183. if (close(bts->fd) == -1)
  184. return errno;
  185. bts->fd = -1;
  186. bts->f_off = 0;
  187. bts->index++;
  188. }
  189. }
  190. return 0;
  191. }
  192. int
  193. bts_close_wo(struct bt_stream_wo *bts)
  194. {
  195. int err = 0;
  196. if (bts->fd != -1) {
  197. if (fsync(bts->fd) == -1) {
  198. err = errno;
  199. close(bts->fd);
  200. } else if (close(bts->fd) == -1)
  201. err = errno;
  202. }
  203. free(bts);
  204. return err;
  205. }