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.

228 lignes
7.5 KiB

  1. #include "btcli.h"
  2. #include "utils.h"
  3. void
  4. usage_list(void)
  5. {
  6. printf(
  7. "List torrents.\n"
  8. "\n"
  9. "Usage: list [-a] [-i] [-f <format>]\n"
  10. " list torrent ...\n"
  11. "\n"
  12. "Arguments:\n"
  13. "torrent ...\n"
  14. "\tThe torrents to list. Running 'btcli list' without any arguments\n"
  15. "\tor options is equivalent to running 'btcli list -ai'.\n"
  16. "\n"
  17. "Options:\n"
  18. "-a\n"
  19. "\tList active torrents.\n"
  20. "\n"
  21. "-i\n"
  22. "\tList inactive torrents.\n"
  23. "\n"
  24. );
  25. exit(1);
  26. }
  27. struct item {
  28. unsigned num, peers;
  29. char *name, *dir;
  30. char hash[SHAHEXSIZE];
  31. char st;
  32. long long cgot, csize, totup, downloaded, uploaded, rate_up, rate_down;
  33. uint32_t torrent_pieces, pieces_have, pieces_seen;
  34. BTPDQ_ENTRY(item) entry;
  35. };
  36. struct items {
  37. int count;
  38. char **argv;
  39. int ntps;
  40. struct ipc_torrent *tps;
  41. BTPDQ_HEAD(item_tq, item) hd;
  42. };
  43. void
  44. itm_insert(struct items *itms, struct item *itm)
  45. {
  46. struct item *p;
  47. BTPDQ_FOREACH(p, &itms->hd, entry)
  48. if (strcmp(itm->name, p->name) < 0)
  49. break;
  50. if (p != NULL)
  51. BTPDQ_INSERT_BEFORE(p, itm, entry);
  52. else
  53. BTPDQ_INSERT_TAIL(&itms->hd, itm, entry);
  54. }
  55. static void
  56. list_cb(int obji, enum ipc_err objerr, struct ipc_get_res *res, void *arg)
  57. {
  58. struct items *itms = arg;
  59. struct item *itm = calloc(1, sizeof(*itm));
  60. if (objerr != IPC_OK)
  61. diemsg("list failed for '%s' (%s).\n", itms->argv[obji],
  62. ipc_strerror(objerr));
  63. itms->count++;
  64. itm->num = (unsigned)res[IPC_TVAL_NUM].v.num;
  65. itm->peers = (unsigned)res[IPC_TVAL_PCOUNT].v.num;
  66. itm->st = tstate_char(res[IPC_TVAL_STATE].v.num);
  67. if (res[IPC_TVAL_NAME].type == IPC_TYPE_ERR)
  68. asprintf(&itm->name, "%s", ipc_strerror(res[IPC_TVAL_NAME].v.num));
  69. else
  70. asprintf(&itm->name, "%.*s", (int)res[IPC_TVAL_NAME].v.str.l,
  71. res[IPC_TVAL_NAME].v.str.p);
  72. if (res[IPC_TVAL_DIR].type == IPC_TYPE_ERR)
  73. asprintf(&itm->dir, "%s", ipc_strerror(res[IPC_TVAL_DIR].v.num));
  74. else
  75. asprintf(&itm->dir, "%.*s", (int)res[IPC_TVAL_DIR].v.str.l,
  76. res[IPC_TVAL_DIR].v.str.p);
  77. bin2hex(res[IPC_TVAL_IHASH].v.str.p, itm->hash, 20);
  78. itm->cgot = res[IPC_TVAL_CGOT].v.num;
  79. itm->csize = res[IPC_TVAL_CSIZE].v.num;
  80. itm->totup = res[IPC_TVAL_TOTUP].v.num;
  81. itm->downloaded = res[IPC_TVAL_SESSDWN].v.num;
  82. itm->uploaded = res[IPC_TVAL_SESSUP].v.num;
  83. itm->rate_up = res[IPC_TVAL_RATEUP].v.num;
  84. itm->rate_down = res[IPC_TVAL_RATEDWN].v.num;
  85. itm->torrent_pieces = (uint32_t)res[IPC_TVAL_PCCOUNT].v.num;
  86. itm->pieces_seen = (uint32_t)res[IPC_TVAL_PCSEEN].v.num;
  87. itm->pieces_have = (uint32_t)res[IPC_TVAL_PCGOT].v.num;
  88. itm_insert(itms, itm);
  89. }
  90. void
  91. print_items(struct items* itms, char *format)
  92. {
  93. struct item *p;
  94. char *it;
  95. BTPDQ_FOREACH(p, &itms->hd, entry) {
  96. if(format) {
  97. for (it = format; *it; ++it) {
  98. switch (*it) {
  99. case '%':
  100. ++it;
  101. switch (*it) {
  102. case '%': putchar('%'); break;
  103. case '#': printf("%u", p->num); break;
  104. case '^': printf("%lld", p->rate_up); break;
  105. case 'A': printf("%u", p->pieces_seen); break;
  106. case 'D': printf("%lld", p->downloaded); break;
  107. case 'H': printf("%u", p->pieces_have); break;
  108. case 'P': printf("%u", p->peers); break;
  109. case 'S': printf("%lld", p->csize); break;
  110. case 'U': printf("%lld", p->uploaded); break;
  111. case 'T': printf("%u", p->torrent_pieces); break;
  112. case 'd': printf("%s", p->dir); break;
  113. case 'g': printf("%lld", p->cgot); break;
  114. case 'h': printf("%s", p->hash); break;
  115. case 'n': printf("%s", p->name); break;
  116. case 'p': print_percent(p->cgot, p->csize); break;
  117. case 'r': print_ratio(p->totup, p->csize); break;
  118. case 's': print_size(p->csize); break;
  119. case 't': printf("%c", p->st); break;
  120. case 'u': printf("%lld", p->totup); break;
  121. case 'v': printf("%lld", p->rate_down); break;
  122. case '\0': continue;
  123. }
  124. break;
  125. case '\\':
  126. ++it;
  127. switch (*it) {
  128. case 'n': putchar('\n'); break;
  129. case 't': putchar('\t'); break;
  130. case '\0': continue;
  131. }
  132. break;
  133. default: putchar(*it); break;
  134. }
  135. }
  136. } else {
  137. printf("%-40.40s %4u %c. ", p->name, p->num, p->st);
  138. print_percent(p->cgot, p->csize);
  139. print_size(p->csize);
  140. print_ratio(p->totup, p->csize);
  141. printf("\n");
  142. }
  143. }
  144. }
  145. static struct option list_opts [] = {
  146. { "format", required_argument, NULL, 'f' },
  147. { "help", no_argument, NULL, 'H' },
  148. {NULL, 0, NULL, 0}
  149. };
  150. void
  151. cmd_list(int argc, char **argv)
  152. {
  153. int ch, inactive = 0, active = 0;
  154. char *format = NULL;
  155. enum ipc_err code;
  156. enum ipc_twc twc;
  157. enum ipc_tval keys[] = { IPC_TVAL_NUM, IPC_TVAL_STATE, IPC_TVAL_NAME,
  158. IPC_TVAL_TOTUP, IPC_TVAL_CSIZE, IPC_TVAL_CGOT, IPC_TVAL_PCOUNT,
  159. IPC_TVAL_PCCOUNT, IPC_TVAL_PCSEEN, IPC_TVAL_PCGOT, IPC_TVAL_SESSUP,
  160. IPC_TVAL_SESSDWN, IPC_TVAL_RATEUP, IPC_TVAL_RATEDWN, IPC_TVAL_IHASH,
  161. IPC_TVAL_DIR };
  162. size_t nkeys = ARRAY_COUNT(keys);
  163. struct items itms;
  164. while ((ch = getopt_long(argc, argv, "aif:", list_opts, NULL)) != -1) {
  165. switch (ch) {
  166. case 'a':
  167. active = 1;
  168. break;
  169. case 'f':
  170. format = optarg;
  171. break;
  172. case 'i':
  173. inactive = 1;
  174. break;
  175. default:
  176. usage_list();
  177. }
  178. }
  179. argc -= optind;
  180. argv += optind;
  181. if (argc > 0) {
  182. if (inactive || active)
  183. usage_list();
  184. itms.tps = malloc(argc * sizeof(*itms.tps));
  185. for (itms.ntps = 0; itms.ntps < argc; itms.ntps++) {
  186. if (!torrent_spec(argv[itms.ntps], &itms.tps[itms.ntps]))
  187. exit(1);
  188. }
  189. } else {
  190. itms.ntps = 0;
  191. itms.tps = NULL;
  192. }
  193. if (inactive == active)
  194. twc = IPC_TWC_ALL;
  195. else if (inactive)
  196. twc = IPC_TWC_INACTIVE;
  197. else
  198. twc = IPC_TWC_ACTIVE;
  199. btpd_connect();
  200. itms.count = 0;
  201. itms.argv = argv;
  202. BTPDQ_INIT(&itms.hd);
  203. if (itms.tps == NULL)
  204. code = btpd_tget_wc(ipc, twc, keys, nkeys, list_cb, &itms);
  205. else
  206. code = btpd_tget(ipc, itms.tps, itms.ntps, keys, nkeys, list_cb, &itms);
  207. if (code != IPC_OK)
  208. diemsg("command failed (%s).\n", ipc_strerror(code));
  209. if (format == NULL)
  210. printf("%-40.40s NUM ST HAVE SIZE RATIO\n", "NAME");
  211. print_items(&itms, format);
  212. }