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.

metainfo.c 6.2 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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. size_t npath, plen, len;
  65. const char *plst, *iter, *str;
  66. if (!benc_dct_chk(fdct, 2, BE_INT, 1, "length", BE_LST, 1, "path"))
  67. return EINVAL;
  68. tfp->length = benc_dget_int(fdct, "length");
  69. plst = benc_dget_lst(fdct, "path");
  70. npath = plen = 0;
  71. iter = benc_first(plst);
  72. while (iter != NULL) {
  73. if (!benc_isstr(iter))
  74. return EINVAL;
  75. str = benc_mem(iter, &len, &iter);
  76. if (!check_path(str, len))
  77. return EINVAL;
  78. npath++;
  79. plen += len;
  80. }
  81. if (npath == 0)
  82. return EINVAL;
  83. if ((tfp->path = malloc(plen + (npath - 1) + 1)) == NULL)
  84. return ENOMEM;
  85. iter = benc_first(plst);
  86. str = benc_mem(iter, &len, &iter);
  87. memcpy(tfp->path, str, len);
  88. plen = len;
  89. npath--;
  90. while (npath > 0) {
  91. tfp->path[plen++] = '/';
  92. str = benc_mem(iter, &len, &iter);
  93. memcpy(tfp->path + plen, str, len);
  94. plen += len;
  95. npath--;
  96. }
  97. tfp->path[plen] = '\0';
  98. return 0;
  99. }
  100. void
  101. clear_metainfo(struct metainfo *mip)
  102. {
  103. int i;
  104. if (mip->piece_hash != NULL)
  105. free(mip->piece_hash);
  106. if (mip->announce != NULL)
  107. free(mip->announce);
  108. if (mip->files != NULL) {
  109. for (i = 0; i < mip->nfiles; i++) {
  110. if (mip->files[i].path != NULL)
  111. free(mip->files[i].path);
  112. }
  113. free(mip->files);
  114. }
  115. if (mip->name != NULL)
  116. free(mip->name);
  117. }
  118. int
  119. fill_metainfo(const char *bep, struct metainfo *tp, int mem_hashes)
  120. {
  121. size_t len;
  122. int err = 0;
  123. const char *base_addr = bep;
  124. const char *hash_addr;
  125. if (!benc_dct_chk(bep, 5,
  126. BE_STR, 1, "announce",
  127. BE_DCT, 1, "info",
  128. BE_INT, 2, "info", "piece length",
  129. BE_STR, 2, "info", "pieces",
  130. BE_STR, 2, "info", "name"))
  131. return EINVAL;
  132. if ((tp->announce = benc_dget_str(bep, "announce", NULL)) == NULL) {
  133. err = ENOMEM;
  134. goto out;
  135. }
  136. bep = benc_dget_dct(bep, "info");
  137. SHA1(bep, benc_length(bep), tp->info_hash);
  138. tp->piece_length = benc_dget_int(bep, "piece length");
  139. hash_addr = benc_dget_mem(bep, "pieces", &len);
  140. tp->npieces = len / 20;
  141. tp->pieces_off = hash_addr - base_addr;
  142. if (mem_hashes) {
  143. tp->piece_hash = (uint8_t (*)[20])benc_dget_mema(bep, "pieces", NULL);
  144. if (tp->piece_hash == NULL) {
  145. err = ENOMEM;
  146. goto out;
  147. }
  148. }
  149. tp->name = benc_dget_str(bep, "name", NULL);
  150. if (benc_dct_chk(bep, 1, BE_INT, 1, "length")) {
  151. tp->total_length = benc_dget_int(bep, "length");
  152. tp->nfiles = 1;
  153. tp->files = calloc(1, sizeof(struct fileinfo));
  154. if (tp->files != NULL) {
  155. tp->files[0].length = tp->total_length;
  156. tp->files[0].path = strdup(tp->name);
  157. if (tp->files[0].path == NULL) {
  158. err = ENOMEM;
  159. goto out;
  160. }
  161. } else {
  162. err = ENOMEM;
  163. goto out;
  164. }
  165. } else if (benc_dct_chk(bep, 1, BE_LST, 1, "files")) {
  166. int i;
  167. const char *flst, *fdct;
  168. flst = benc_dget_lst(bep, "files");
  169. tp->nfiles = benc_nelems(flst);
  170. if (tp->nfiles < 1) {
  171. err = EINVAL;
  172. goto out;
  173. }
  174. tp->files = calloc(tp->nfiles, sizeof(struct fileinfo));
  175. tp->total_length = 0;
  176. i = 0;
  177. for (fdct = benc_first(flst); fdct != NULL; fdct = benc_next(fdct)) {
  178. if (!benc_isdct(fdct)) {
  179. err = EINVAL;
  180. goto out;
  181. }
  182. if ((err = fill_fileinfo(fdct, &tp->files[i])) != 0)
  183. goto out;
  184. tp->total_length += tp->files[i].length;
  185. i++;
  186. }
  187. }
  188. else
  189. goto out;
  190. out:
  191. if (err != 0)
  192. clear_metainfo(tp);
  193. return err;
  194. }
  195. int
  196. load_metainfo(const char *path, off_t size, int mem_hashes,
  197. struct metainfo **res)
  198. {
  199. char *buf;
  200. int fd, err = 0;
  201. if ((fd = open(path, O_RDONLY)) == -1)
  202. return errno;
  203. if (size <= 0) {
  204. struct stat sb;
  205. if (fstat(fd, &sb) == -1) {
  206. close(fd);
  207. return errno;
  208. } else
  209. size = sb.st_size;
  210. }
  211. if ((buf = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
  212. err = errno;
  213. close(fd);
  214. if (err == 0)
  215. err = benc_validate(buf, size);
  216. if (err == 0)
  217. if ((*res = calloc(1, sizeof(**res))) == NULL)
  218. err = ENOMEM;
  219. if (err == 0)
  220. if ((err = fill_metainfo(buf, *res, mem_hashes)) != 0)
  221. free(*res);
  222. munmap(buf, size);
  223. return err;
  224. }