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.

276 lignes
5.6 KiB

  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. #ifndef PRId64
  29. #define PRId64 "lld"
  30. #endif
  31. #ifndef PRIu32
  32. #define PRIu32 "u"
  33. #endif
  34. void
  35. print_metainfo(struct metainfo *tp)
  36. {
  37. unsigned i;
  38. printf("Info hash: ");
  39. for (i = 0; i < 20; i++)
  40. printf("%.2x", tp->info_hash[i]);
  41. printf("\n");
  42. printf("Tracker URL: %s\n", tp->announce);
  43. printf("Piece length: %" PRId64 "\n", (int64_t)tp->piece_length);
  44. printf("Number of pieces: %" PRIu32 "\n", tp->npieces);
  45. printf("Number of files: %u\n", tp->nfiles);
  46. printf("Advisory name: %s\n", tp->name);
  47. printf("Files:\n");
  48. for (i = 0; i < tp->nfiles; i++) {
  49. printf("%s (%" PRId64 ")\n",
  50. tp->files[i].path, (int64_t)tp->files[i].length);
  51. }
  52. printf("Total length: %" PRId64 "\n\n", (int64_t)tp->total_length);
  53. }
  54. static int
  55. check_path(const char *path, size_t len)
  56. {
  57. if (len == 0)
  58. return 0;
  59. else if (len == 1 && path[0] == '.')
  60. return 0;
  61. else if (len == 2 && path[0] == '.' && path[1] == '.')
  62. return 0;
  63. else if (memchr(path, '/', len) != NULL)
  64. return 0;
  65. return 1;
  66. }
  67. int
  68. fill_fileinfo(const char *fdct, struct fileinfo *tfp)
  69. {
  70. int err;
  71. size_t npath, plen, len;
  72. const char *plst, *iter, *str;
  73. if ((err = benc_dget_off(fdct, "length", &tfp->length)) != 0)
  74. return err;
  75. if ((err = benc_dget_lst(fdct, "path", &plst)) != 0)
  76. return err;
  77. npath = plen = 0;
  78. iter = benc_first(plst);
  79. while (iter != NULL) {
  80. if (!benc_isstr(iter))
  81. return EINVAL;
  82. benc_str(iter, &str, &len, &iter);
  83. if (!check_path(str, len))
  84. return EINVAL;
  85. npath++;
  86. plen += len;
  87. }
  88. if (npath == 0)
  89. return EINVAL;
  90. if ((tfp->path = malloc(plen + (npath - 1) + 1)) == NULL)
  91. return ENOMEM;
  92. iter = benc_first(plst);
  93. benc_str(iter, &str, &len, &iter);
  94. memcpy(tfp->path, str, len);
  95. plen = len;
  96. npath--;
  97. while (npath > 0) {
  98. tfp->path[plen++] = '/';
  99. benc_str(iter, &str, &len, &iter);
  100. memcpy(tfp->path + plen, str, len);
  101. plen += len;
  102. npath--;
  103. }
  104. tfp->path[plen] = '\0';
  105. return 0;
  106. }
  107. void
  108. clear_metainfo(struct metainfo *mip)
  109. {
  110. int i;
  111. if (mip->piece_hash != NULL)
  112. free(mip->piece_hash);
  113. if (mip->announce != NULL)
  114. free(mip->announce);
  115. if (mip->files != NULL) {
  116. for (i = 0; i < mip->nfiles; i++) {
  117. if (mip->files[i].path != NULL)
  118. free(mip->files[i].path);
  119. }
  120. free(mip->files);
  121. }
  122. if (mip->name != NULL)
  123. free(mip->name);
  124. }
  125. int
  126. fill_metainfo(const char *bep, struct metainfo *tp, int mem_hashes)
  127. {
  128. size_t len;
  129. int err;
  130. const char *base_addr = bep;
  131. const char *hash_addr;
  132. if (!benc_isdct(bep))
  133. return EINVAL;
  134. if ((err = benc_dget_strz(bep, "announce", &tp->announce, NULL)) != 0)
  135. goto out;
  136. if ((err = benc_dget_dct(bep, "info", &bep)) != 0)
  137. goto out;
  138. SHA1(bep, benc_length(bep), tp->info_hash);
  139. if ((err = benc_dget_off(bep, "piece length", &tp->piece_length)) != 0)
  140. goto out;
  141. if ((err = benc_dget_str(bep, "pieces", &hash_addr, &len)) != 0)
  142. goto out;
  143. if (len % 20 != 0) {
  144. err = EINVAL;
  145. goto out;
  146. }
  147. tp->npieces = len / 20;
  148. tp->pieces_off = hash_addr - base_addr;
  149. if (mem_hashes) {
  150. if ((tp->piece_hash = malloc(len)) == NULL) {
  151. err = ENOMEM;
  152. goto out;
  153. }
  154. bcopy(hash_addr, tp->piece_hash, len);
  155. }
  156. if ((err = benc_dget_strz(bep, "name", &tp->name, NULL)) != 0)
  157. goto out;
  158. err = benc_dget_off(bep, "length", &tp->total_length);
  159. if (err == 0) {
  160. tp->nfiles = 1;
  161. tp->files = calloc(1, sizeof(struct fileinfo));
  162. if (tp->files != NULL) {
  163. tp->files[0].length = tp->total_length;
  164. tp->files[0].path = strdup(tp->name);
  165. if (tp->files[0].path == NULL) {
  166. err = ENOMEM;
  167. goto out;
  168. }
  169. } else {
  170. err = ENOMEM;
  171. goto out;
  172. }
  173. }
  174. else if (err == ENOENT) {
  175. int i;
  176. const char *flst, *fdct;
  177. if ((err = benc_dget_lst(bep, "files", &flst)) != 0)
  178. goto out;
  179. tp->nfiles = benc_nelems(flst);
  180. if (tp->nfiles < 1) {
  181. err = EINVAL;
  182. goto out;
  183. }
  184. tp->files = calloc(tp->nfiles, sizeof(struct fileinfo));
  185. tp->total_length = 0;
  186. i = 0;
  187. for (fdct = benc_first(flst); fdct != NULL; fdct = benc_next(fdct)) {
  188. if (!benc_isdct(fdct)) {
  189. err = EINVAL;
  190. goto out;
  191. }
  192. if ((err = fill_fileinfo(fdct, &tp->files[i])) != 0)
  193. goto out;
  194. tp->total_length += tp->files[i].length;
  195. i++;
  196. }
  197. }
  198. else
  199. goto out;
  200. out:
  201. if (err != 0)
  202. clear_metainfo(tp);
  203. return err;
  204. }
  205. int
  206. load_metainfo(const char *path, off_t size, int mem_hashes,
  207. struct metainfo **res)
  208. {
  209. char *buf;
  210. int fd, err = 0;
  211. if ((fd = open(path, O_RDONLY)) == -1)
  212. return errno;
  213. if (size <= 0) {
  214. struct stat sb;
  215. if (fstat(fd, &sb) == -1) {
  216. close(fd);
  217. return errno;
  218. } else
  219. size = sb.st_size;
  220. }
  221. if ((buf = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
  222. err = errno;
  223. close(fd);
  224. if (err == 0)
  225. err = benc_validate(buf, size);
  226. if (err == 0)
  227. if ((*res = calloc(1, sizeof(**res))) == NULL)
  228. err = ENOMEM;
  229. if (err == 0)
  230. if ((err = fill_metainfo(buf, *res, mem_hashes)) != 0)
  231. free(*res);
  232. munmap(buf, size);
  233. return err;
  234. }