A clone of btpd with my configuration changes.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

255 satır
6.2 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. 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. }