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.

456 lignes
11 KiB

  1. #include "btpd.h"
  2. #include <sys/mman.h>
  3. #include <dirent.h>
  4. #include <iobuf.h>
  5. HTBL_TYPE(numtbl, tlib, unsigned, num, nchain);
  6. HTBL_TYPE(hashtbl, tlib, uint8_t, hash, hchain);
  7. static unsigned m_nextnum;
  8. static unsigned m_ntlibs;
  9. static struct numtbl *m_numtbl;
  10. static struct hashtbl *m_hashtbl;
  11. unsigned
  12. tlib_count(void)
  13. {
  14. return m_ntlibs;
  15. }
  16. struct tlib *
  17. tlib_by_num(unsigned num)
  18. {
  19. return numtbl_find(m_numtbl, &num);
  20. }
  21. struct tlib *
  22. tlib_by_hash(const uint8_t *hash)
  23. {
  24. return hashtbl_find(m_hashtbl, hash);
  25. }
  26. void
  27. tlib_kill(struct tlib *tl)
  28. {
  29. numtbl_remove(m_numtbl, &tl->num);
  30. hashtbl_remove(m_hashtbl, tl->hash);
  31. if (tl->name != NULL)
  32. free(tl->name);
  33. if (tl->dir != NULL)
  34. free(tl->dir);
  35. free(tl);
  36. m_ntlibs--;
  37. }
  38. struct tlib *
  39. tlib_create(const uint8_t *hash)
  40. {
  41. struct tlib *tl = btpd_calloc(1, sizeof(*tl));
  42. char hex[SHAHEXSIZE];
  43. bin2hex(hash, hex, 20);
  44. tl->num = m_nextnum;
  45. bcopy(hash, tl->hash, 20);
  46. m_nextnum++;
  47. m_ntlibs++;
  48. numtbl_insert(m_numtbl, tl);
  49. hashtbl_insert(m_hashtbl, tl);
  50. return tl;
  51. }
  52. int
  53. tlib_del(struct tlib *tl)
  54. {
  55. char relpath[RELPATH_SIZE];
  56. char cmd[PATH_MAX];
  57. assert(tl->tp == NULL);
  58. snprintf(cmd, PATH_MAX, "rm -r torrents/%s",
  59. bin2hex(tl->hash, relpath, 20));
  60. system(cmd);
  61. tlib_kill(tl);
  62. return 0;
  63. }
  64. static void
  65. dct_subst_save(FILE *fp, const char *dct1, const char *dct2)
  66. {
  67. fprintf(fp, "d");
  68. const char *k1 = benc_first(dct1), *k2 = benc_first(dct2);
  69. const char *val, *str, *rest;
  70. size_t len;
  71. while (k1 != NULL && k2 != NULL) {
  72. int test = benc_strcmp(k1, k2);
  73. if (test < 0) {
  74. str = benc_mem(k1, &len, &val);
  75. fprintf(fp, "%d:%.*s", (int)len, (int)len, str);
  76. fwrite(val, 1, benc_length(val), fp);
  77. k1 = benc_next(val);
  78. } else {
  79. str = benc_mem(k2, &len, &val);
  80. fprintf(fp, "%d:%.*s", (int)len, (int)len, str);
  81. fwrite(val, 1, benc_length(val), fp);
  82. k2 = benc_next(val);
  83. if (test == 0)
  84. k1 = benc_next(benc_next(k1));
  85. }
  86. }
  87. rest = k1 != NULL ? k1 : k2;
  88. while (rest != NULL) {
  89. str = benc_mem(rest, &len, &val);
  90. fprintf(fp, "%d:%.*s", (int)len, (int)len, str);
  91. fwrite(val, 1, benc_length(val), fp);
  92. rest = benc_next(val);
  93. }
  94. fprintf(fp, "e");
  95. }
  96. static int
  97. valid_info(char *buf, size_t len)
  98. {
  99. size_t slen;
  100. const char *info;
  101. if (benc_validate(buf, len) != 0)
  102. return 0;
  103. if ((info = benc_dget_dct(buf, "info")) == NULL)
  104. return 0;
  105. if (benc_dget_mem(info, "name", &slen) == NULL || slen == 0)
  106. return 0;
  107. if ((benc_dget_mem(info, "dir", &slen) == NULL ||
  108. (slen == 0 || slen >= PATH_MAX)))
  109. return 0;
  110. return 1;
  111. }
  112. static void
  113. load_info(struct tlib *tl, const char *path)
  114. {
  115. size_t size = 1 << 14;
  116. char buf[size];
  117. const char *info;
  118. if (read_file(path, buf, &size) == NULL) {
  119. btpd_log(BTPD_L_ERROR, "couldn't load '%s' (%s).\n", path,
  120. strerror(errno));
  121. return;
  122. }
  123. if (!valid_info(buf, size)) {
  124. btpd_log(BTPD_L_ERROR, "bad info file '%s'.\n", path);
  125. return;
  126. }
  127. info = benc_dget_dct(buf, "info");
  128. tl->name = benc_dget_str(info, "name", NULL);
  129. tl->dir = benc_dget_str(info, "dir", NULL);
  130. tl->tot_up = benc_dget_int(info, "total upload");
  131. tl->tot_down = benc_dget_int(info, "total download");
  132. tl->content_size = benc_dget_int(info, "content size");
  133. tl->content_have = benc_dget_int(info, "content have");
  134. if (tl->name == NULL || tl->dir == NULL)
  135. btpd_err("Out of memory.\n");
  136. }
  137. static void
  138. save_info(struct tlib *tl)
  139. {
  140. FILE *fp;
  141. char relpath[SHAHEXSIZE], path[PATH_MAX], wpath[PATH_MAX];
  142. struct io_buffer iob = buf_init(1 << 10);
  143. buf_print(&iob,
  144. "d4:infod"
  145. "12:content havei%llde12:content sizei%llde"
  146. "3:dir%d:%s4:name%d:%s"
  147. "14:total downloadi%llde12:total uploadi%llde"
  148. "ee",
  149. (long long)tl->content_have, (long long)tl->content_size,
  150. (int)strlen(tl->dir), tl->dir, (int)strlen(tl->name), tl->name,
  151. tl->tot_down, tl->tot_up);
  152. if (iob.error)
  153. btpd_err("Out of memory.\n");
  154. bin2hex(tl->hash, relpath, 20);
  155. snprintf(path, PATH_MAX, "torrents/%s/info", relpath);
  156. snprintf(wpath, PATH_MAX, "%s.write", path);
  157. if ((fp = fopen(wpath, "w")) == NULL)
  158. btpd_err("failed to open '%s' (%s).\n", wpath, strerror(errno));
  159. dct_subst_save(fp, "de", iob.buf);
  160. buf_free(&iob);
  161. if ((fflush(fp) == EOF || fsync(fileno(fp)) != 0
  162. || ferror(fp) || fclose(fp) != 0))
  163. btpd_err("failed to write '%s'.\n", wpath);
  164. if (rename(wpath, path) != 0)
  165. btpd_err("failed to rename: '%s' -> '%s' (%s).\n", wpath, path,
  166. strerror(errno));
  167. }
  168. void
  169. tlib_update_info(struct tlib *tl, int only_file)
  170. {
  171. struct tlib tmp;
  172. assert(tl->tp != NULL);
  173. if (only_file) {
  174. tmp = *tl;
  175. tl = &tmp;
  176. }
  177. tl->tot_down += tl->tp->net->downloaded;
  178. tl->tot_up += tl->tp->net->uploaded;
  179. tl->content_have = cm_content(tl->tp);
  180. tl->content_size = tl->tp->total_length;
  181. save_info(tl);
  182. }
  183. static void
  184. write_torrent(const char *mi, size_t mi_size, const char *path)
  185. {
  186. FILE *fp;
  187. if ((fp = fopen(path, "w")) == NULL)
  188. goto err;
  189. if (fwrite(mi, mi_size, 1, fp) != 1) {
  190. errno = EIO;
  191. goto err;
  192. }
  193. if (fclose(fp) != 0)
  194. goto err;
  195. return;
  196. err:
  197. btpd_err("failed to write metainfo '%s' (%s).\n", path, strerror(errno));
  198. }
  199. struct tlib *
  200. tlib_add(const uint8_t *hash, const char *mi, size_t mi_size,
  201. const char *content, char *name)
  202. {
  203. struct tlib *tl = tlib_create(hash);
  204. char relpath[RELPATH_SIZE], file[PATH_MAX];
  205. bin2hex(hash, relpath, 20);
  206. if (name == NULL)
  207. if ((name = mi_name(mi)) == NULL)
  208. btpd_err("out of memory.\n");
  209. tl->content_size = mi_total_length(mi);
  210. tl->name = name;
  211. tl->dir = strdup(content);
  212. if (tl->name == NULL || tl->dir == NULL)
  213. btpd_err("out of memory.\n");
  214. snprintf(file, PATH_MAX, "torrents/%s", relpath);
  215. if (mkdir(file, 0777) != 0)
  216. btpd_err("failed to create dir '%s' (%s).\n", file, strerror(errno));
  217. snprintf(file, PATH_MAX, "torrents/%s/torrent", relpath);
  218. write_torrent(mi, mi_size, file);
  219. save_info(tl);
  220. return tl;
  221. }
  222. static int
  223. num_test(const void *k1, const void *k2)
  224. {
  225. return *(const unsigned *)k1 == *(const unsigned *)k2;
  226. }
  227. static uint32_t
  228. num_hash(const void *k)
  229. {
  230. return *(const unsigned *)k;
  231. }
  232. static int
  233. id_test(const void *k1, const void *k2)
  234. {
  235. return bcmp(k1, k2, 20) == 0;
  236. }
  237. static uint32_t
  238. id_hash(const void *k)
  239. {
  240. return dec_be32(k + 16);
  241. }
  242. void
  243. tlib_put_all(struct tlib **v)
  244. {
  245. hashtbl_tov(m_hashtbl, v);
  246. }
  247. void
  248. tlib_init(void)
  249. {
  250. DIR *dirp;
  251. struct dirent *dp;
  252. uint8_t hash[20];
  253. char file[PATH_MAX];
  254. m_numtbl = numtbl_create(num_test, num_hash);
  255. m_hashtbl = hashtbl_create(id_test, id_hash);
  256. if (m_numtbl == NULL || m_hashtbl == NULL)
  257. btpd_err("Out of memory.\n");
  258. if ((dirp = opendir("torrents")) == NULL)
  259. btpd_err("couldn't open the torrents directory.\n");
  260. while ((dp = readdir(dirp)) != NULL) {
  261. if (strlen(dp->d_name) == 40 && ishex(dp->d_name)) {
  262. struct tlib * tl = tlib_create(hex2bin(dp->d_name, hash, 20));
  263. snprintf(file, PATH_MAX, "torrents/%s/info", dp->d_name);
  264. load_info(tl, file);
  265. }
  266. }
  267. closedir(dirp);
  268. }
  269. void
  270. tlib_read_hash(struct tlib *tl, size_t off, uint32_t piece, uint8_t *hash)
  271. {
  272. int fd;
  273. ssize_t nread;
  274. char relpath[RELPATH_SIZE];
  275. bin2hex(tl->hash, relpath, 20);
  276. if ((errno = vopen(&fd, O_RDONLY, "torrents/%s/torrent", relpath)) != 0)
  277. btpd_err("failed to open 'torrents/%s/torrent' (%s).\n",
  278. relpath, strerror(errno));
  279. lseek(fd, off + piece * 20, SEEK_SET);
  280. if ((nread = read(fd, hash, 20)) != 20) {
  281. if (nread == -1)
  282. btpd_err("failed to read 'torrents/%s/torrent' (%s).\n", relpath,
  283. strerror(errno));
  284. else
  285. btpd_err("corrupt file: 'torrents/%s/torrent'.\n", relpath);
  286. }
  287. close(fd);
  288. }
  289. int
  290. tlib_load_mi(struct tlib *tl, char **res)
  291. {
  292. char file[PATH_MAX];
  293. char relpath[RELPATH_SIZE];
  294. char *mi;
  295. bin2hex(tl->hash, relpath, 20);
  296. snprintf(file, sizeof(file), "torrents/%s/torrent", relpath);
  297. if ((mi = mi_load(file, NULL)) == NULL) {
  298. btpd_log(BTPD_L_ERROR,
  299. "torrent '%s': failed to load metainfo (%s).\n",
  300. tl->name, strerror(errno));
  301. return errno;
  302. }
  303. *res = mi;
  304. return 0;
  305. }
  306. struct resume_data {
  307. void *base;
  308. size_t size;
  309. uint8_t *pc_field;
  310. uint8_t *blk_field;
  311. };
  312. static void *
  313. resume_file_size(struct resume_data *resd, int i)
  314. {
  315. return resd->base + 8 + 16 * i;
  316. }
  317. static void *
  318. resume_file_time(struct resume_data *resd, int i)
  319. {
  320. return resd->base + 16 + 16 * i;
  321. }
  322. static void
  323. init_resume(int fd, size_t size)
  324. {
  325. char buf[1024];
  326. uint32_t ver;
  327. bzero(buf, sizeof(buf));
  328. enc_be32(&ver, 2);
  329. if (write(fd, "RESD", 4) == -1 || write(fd, &ver, 4) == -1)
  330. goto fatal;
  331. size -= 8;
  332. while (size > 0) {
  333. ssize_t nw = write(fd, buf, min(sizeof(buf), size));
  334. if (nw < 1)
  335. goto fatal;
  336. size -= nw;
  337. }
  338. return;
  339. fatal:
  340. btpd_err("failed to initialize resume file (%s).\n", strerror(errno));
  341. }
  342. struct resume_data *
  343. tlib_open_resume(struct tlib *tl, unsigned nfiles, size_t pfsize,
  344. size_t bfsize)
  345. {
  346. int fd;
  347. char relpath[RELPATH_SIZE];
  348. struct stat sb;
  349. struct resume_data *resd = btpd_calloc(1, sizeof(*resd));
  350. bin2hex(tl->hash, relpath, 20);
  351. resd->size = 8 + nfiles * 16 + pfsize + bfsize;
  352. if ((errno =
  353. vopen(&fd, O_RDWR|O_CREAT, "torrents/%s/resume", relpath)) != 0)
  354. goto fatal;
  355. if (fstat(fd, &sb) != 0)
  356. goto fatal;
  357. if (sb.st_size != resd->size) {
  358. if (sb.st_size != 0 && ftruncate(fd, 0) != 0)
  359. goto fatal;
  360. init_resume(fd, resd->size);
  361. }
  362. resd->base =
  363. mmap(NULL, resd->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  364. if (resd->base == MAP_FAILED)
  365. goto fatal;
  366. if (bcmp(resd->base, "RESD", 4) != 0 || dec_be32(resd->base + 4) != 2)
  367. init_resume(fd, resd->size);
  368. close(fd);
  369. resd->pc_field = resd->base + 8 + nfiles * 16;
  370. resd->blk_field = resd->pc_field + pfsize;
  371. return resd;
  372. fatal:
  373. btpd_err("file operation failed on 'torrents/%s/resume' (%s).\n",
  374. relpath, strerror(errno));
  375. }
  376. uint8_t *
  377. resume_piece_field(struct resume_data *resd)
  378. {
  379. return resd->pc_field;
  380. }
  381. uint8_t *
  382. resume_block_field(struct resume_data *resd)
  383. {
  384. return resd->blk_field;
  385. }
  386. void
  387. resume_set_fts(struct resume_data *resd, int i, struct file_time_size *fts)
  388. {
  389. enc_be64(resume_file_size(resd, i), (uint64_t)fts->size);
  390. enc_be64(resume_file_time(resd, i), (uint64_t)fts->mtime);
  391. }
  392. void
  393. resume_get_fts(struct resume_data *resd, int i, struct file_time_size *fts)
  394. {
  395. fts->size = dec_be64(resume_file_size(resd, i));
  396. fts->mtime = dec_be64(resume_file_time(resd, i));
  397. }
  398. void
  399. tlib_close_resume(struct resume_data *resd)
  400. {
  401. munmap(resd->base, resd->size);
  402. free(resd);
  403. }