A clone of btpd with my configuration changes.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

182 Zeilen
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. }