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.

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