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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include <sys/types.h>
  2. #include <sys/mman.h>
  3. #include <sys/stat.h>
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <inttypes.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <unistd.h>
  11. #include <openssl/sha.h>
  12. #include "benc.h"
  13. #include "metainfo.h"
  14. #include "subr.h"
  15. /*
  16. * d
  17. * announce = url
  18. * info = d
  19. * name = advisory file/dir save name
  20. * piece length = power of two length of each block
  21. * pieces = 20b of sha1-hash * num of pieces
  22. * length = length of file in bytes in single file download
  23. * files = l d
  24. * length = length of file in bytes
  25. * path = l path components
  26. *
  27. */
  28. void
  29. print_metainfo(struct metainfo *tp)
  30. {
  31. unsigned i;
  32. printf("Info hash: ");
  33. for (i = 0; i < 20; i++)
  34. printf("%.2x", tp->info_hash[i]);
  35. printf("\n");
  36. printf("Tracker URL: %s\n", tp->announce);
  37. printf("Piece length: %jd\n", (intmax_t)tp->piece_length);
  38. printf("Number of pieces: %u\n", tp->npieces);
  39. printf("Number of files: %u\n", tp->nfiles);
  40. printf("Advisory name: %s\n", tp->name);
  41. printf("Files:\n");
  42. for (i = 0; i < tp->nfiles; i++) {
  43. printf("%s (%jd)\n",
  44. tp->files[i].path, (intmax_t)tp->files[i].length);
  45. }
  46. printf("Total length: %jd\n\n", (intmax_t)tp->total_length);
  47. }
  48. static int
  49. check_path(const char *path, size_t len)
  50. {
  51. if (len == 0)
  52. return 0;
  53. else if (len == 1 && path[0] == '.')
  54. return 0;
  55. else if (len == 2 && path[0] == '.' && path[1] == '.')
  56. return 0;
  57. else if (memchr(path, '/', len) != NULL)
  58. return 0;
  59. return 1;
  60. }
  61. int
  62. fill_fileinfo(const char *fdct, struct fileinfo *tfp)
  63. {
  64. //int err;
  65. size_t npath, plen, len;
  66. const char *plst, *iter, *str;
  67. if (!benc_dct_chk(fdct, 2, BE_INT, 1, "length", BE_LST, 1, "path"))
  68. return EINVAL;
  69. tfp->length = benc_dget_int(fdct, "length");
  70. plst = benc_dget_lst(fdct, "path");
  71. npath = plen = 0;
  72. iter = benc_first(plst);
  73. while (iter != NULL) {
  74. if (!benc_isstr(iter))
  75. return EINVAL;
  76. str = benc_mem(iter, &len, &iter);
  77. if (!check_path(str, len))
  78. return EINVAL;
  79. npath++;
  80. plen += len;
  81. }
  82. if (npath == 0)
  83. return EINVAL;
  84. if ((tfp->path = malloc(plen + (npath - 1) + 1)) == NULL)
  85. return ENOMEM;
  86. iter = benc_first(plst);
  87. str = benc_mem(iter, &len, &iter);
  88. memcpy(tfp->path, str, len);
  89. plen = len;
  90. npath--;
  91. while (npath > 0) {
  92. tfp->path[plen++] = '/';
  93. str = benc_mem(iter, &len, &iter);
  94. memcpy(tfp->path + plen, str, len);
  95. plen += len;
  96. npath--;
  97. }
  98. tfp->path[plen] = '\0';
  99. return 0;
  100. }
  101. void
  102. clear_metainfo(struct metainfo *mip)
  103. {
  104. int i;
  105. if (mip->piece_hash != NULL)
  106. free(mip->piece_hash);
  107. if (mip->announce != NULL)
  108. free(mip->announce);
  109. if (mip->files != NULL) {
  110. for (i = 0; i < mip->nfiles; i++) {
  111. if (mip->files[i].path != NULL)
  112. free(mip->files[i].path);
  113. }
  114. free(mip->files);
  115. }
  116. if (mip->name != NULL)
  117. free(mip->name);
  118. }
  119. int
  120. fill_metainfo(const char *bep, struct metainfo *tp, int mem_hashes)
  121. {
  122. size_t len;
  123. int err = 0;
  124. const char *base_addr = bep;
  125. const char *hash_addr;
  126. if (!benc_dct_chk(bep, 5,
  127. BE_STR, 1, "announce",
  128. BE_DCT, 1, "info",
  129. BE_INT, 2, "info", "piece length",
  130. BE_STR, 2, "info", "pieces",
  131. BE_STR, 2, "info", "name"))
  132. return EINVAL;
  133. tp->announce = benc_dget_str(bep, "announce", NULL);
  134. bep = benc_dget_dct(bep, "info");
  135. SHA1(bep, benc_length(bep), tp->info_hash);
  136. tp->piece_length = benc_dget_int(bep, "piece length");
  137. hash_addr = benc_dget_mem(bep, "pieces", &len);
  138. tp->npieces = len / 20;
  139. tp->pieces_off = hash_addr - base_addr;
  140. if (mem_hashes) {
  141. if ((tp->piece_hash = malloc(len)) == NULL) {
  142. err = ENOMEM;
  143. goto out;
  144. }
  145. bcopy(hash_addr, tp->piece_hash, len);
  146. }
  147. tp->name = benc_dget_str(bep, "name", NULL);
  148. if (benc_dct_chk(bep, 1, BE_INT, 1, "length")) {
  149. tp->total_length = benc_dget_int(bep, "length");
  150. tp->nfiles = 1;
  151. tp->files = calloc(1, sizeof(struct fileinfo));
  152. if (tp->files != NULL) {
  153. tp->files[0].length = tp->total_length;
  154. tp->files[0].path = strdup(tp->name);
  155. if (tp->files[0].path == NULL) {
  156. err = ENOMEM;
  157. goto out;
  158. }
  159. } else {
  160. err = ENOMEM;
  161. goto out;
  162. }
  163. } else if (benc_dct_chk(bep, 1, BE_LST, 1, "files")) {
  164. int i;
  165. const char *flst, *fdct;
  166. flst = benc_dget_lst(bep, "files");
  167. tp->nfiles = benc_nelems(flst);
  168. if (tp->nfiles < 1) {
  169. err = EINVAL;
  170. goto out;
  171. }
  172. tp->files = calloc(tp->nfiles, sizeof(struct fileinfo));
  173. tp->total_length = 0;
  174. i = 0;
  175. for (fdct = benc_first(flst); fdct != NULL; fdct = benc_next(fdct)) {
  176. if (!benc_isdct(fdct)) {
  177. err = EINVAL;
  178. goto out;
  179. }
  180. if ((err = fill_fileinfo(fdct, &tp->files[i])) != 0)
  181. goto out;
  182. tp->total_length += tp->files[i].length;
  183. i++;
  184. }
  185. }
  186. else
  187. goto out;
  188. out:
  189. if (err != 0)
  190. clear_metainfo(tp);
  191. return err;
  192. }
  193. int
  194. load_metainfo(const char *path, off_t size, int mem_hashes,
  195. struct metainfo **res)
  196. {
  197. char *buf;
  198. int fd, err = 0;
  199. if ((fd = open(path, O_RDONLY)) == -1)
  200. return errno;
  201. if (size <= 0) {
  202. struct stat sb;
  203. if (fstat(fd, &sb) == -1) {
  204. close(fd);
  205. return errno;
  206. } else
  207. size = sb.st_size;
  208. }
  209. if ((buf = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
  210. err = errno;
  211. close(fd);
  212. if (err == 0)
  213. err = benc_validate(buf, size);
  214. if (err == 0)
  215. if ((*res = calloc(1, sizeof(**res))) == NULL)
  216. err = ENOMEM;
  217. if (err == 0)
  218. if ((err = fill_metainfo(buf, *res, mem_hashes)) != 0)
  219. free(*res);
  220. munmap(buf, size);
  221. return err;
  222. }