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.

227 lignes
7.5 KiB

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