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.

stream.c 4.8 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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. }