static char * mi_filepath(const char *plst) { char *res = NULL; const char *str; size_t npaths = 0, plen = 0, len; const char *iter = benc_first(plst); while (iter != NULL) { benc_mem(iter, &len, &iter); npaths++; plen += len; } if ((res = malloc(plen + (npaths - 1) + 1)) == NULL) return NULL; iter = benc_first(plst); str = benc_mem(iter, &len, &iter); bcopy(str, res, len); plen = len; npaths--; while (npaths > 0) { res[plen] = '/'; plen++; str = benc_mem(iter, &len, &iter); bcopy(str, res + plen, len); plen += len; npaths--; } res[plen] = '\0'; return res; }
static int cmd_stop(struct cli *cli, int argc, const char *args) { if (argc != 1) return IPC_COMMERR; struct tlib *tl; if (benc_isstr(args) && benc_strlen(args) == 20) tl = tlib_by_hash(benc_mem(args, NULL, NULL)); else if (benc_isint(args)) tl = tlib_by_num(benc_int(args, NULL)); else return IPC_COMMERR; if (tl == NULL || torrent_haunting(tl)) return write_code_buffer(cli, IPC_ENOTENT); else if (!torrent_active(tl)) return write_code_buffer(cli, IPC_ETINACTIVE); else { /* Stopping a torrent may trigger exit so we need to reply before. */ int ret = write_code_buffer(cli, IPC_OK); active_del(tl->hash); torrent_stop(tl->tp, 0); return ret; } }
static int cmd_start(struct cli *cli, int argc, const char *args) { if (argc != 1) return IPC_COMMERR; if (btpd_is_stopping()) return write_code_buffer(cli, IPC_ESHUTDOWN); struct tlib *tl; enum ipc_err code = IPC_OK; if (benc_isstr(args) && benc_strlen(args) == 20) tl = tlib_by_hash(benc_mem(args, NULL, NULL)); else if (benc_isint(args)) tl = tlib_by_num(benc_int(args, NULL)); else return IPC_COMMERR; if (tl == NULL || torrent_haunting(tl)) code = IPC_ENOTENT; else if (!torrent_startable(tl)) code = IPC_ETACTIVE; else if ((code = torrent_start(tl)) == IPC_OK) active_add(tl->hash); return write_code_buffer(cli, code); }
static int cmd_del(struct cli *cli, int argc, const char *args) { if (argc != 1) return IPC_COMMERR; int ret; struct tlib *tl; if (benc_isstr(args) && benc_strlen(args) == 20) tl = tlib_by_hash(benc_mem(args, NULL, NULL)); else if (benc_isint(args)) tl = tlib_by_num(benc_int(args, NULL)); else return IPC_COMMERR; if (tl == NULL || torrent_haunting(tl)) ret = write_code_buffer(cli, IPC_ENOTENT); else { ret = write_code_buffer(cli, IPC_OK); if (tl->tp != NULL) torrent_stop(tl->tp, 1); else tlib_del(tl); } return ret; }
static int mi_test_files(const char *files) { int fcount = 0; const char *fdct = benc_first(files); while (fdct != NULL) { const char *plst; const char *path; int pcount = 0; if (!benc_isdct(fdct)) return 0; if (benc_dget_int(fdct, "length") < 0) return 0; if ((plst = benc_dget_lst(fdct, "path")) == NULL) return 0; path = benc_first(plst); while (path != NULL) { size_t plen; const char *pstr = benc_mem(path, &plen, &path); if (pstr == NULL || !mi_test_path(pstr, plen)) return 0; pcount++; } if (pcount == 0) return 0; fcount++; fdct = benc_next(fdct); } return fcount > 0 ? 1 : 0; }
static int cmd_dispatch(struct cli *cli, const char *buf) { size_t cmdlen; const char *cmd; const char *args; cmd = benc_mem(benc_first(buf), &cmdlen, &args); for (int i = 0; i < ARRAY_COUNT(cmd_table); i++) { if ((cmdlen == cmd_table[i].nlen && strncmp(cmd_table[i].name, cmd, cmdlen) == 0)) { return cmd_table[i].fun(cli, benc_nelems(buf) - 1, args); } } return ENOENT; }
static int cmd_tget(struct cli *cli, int argc, const char *args) { if (argc != 1 || !benc_isdct(args)) return IPC_COMMERR; size_t nkeys; const char *keys, *p; enum ipc_tval *opts; struct iobuf iob; if ((keys = benc_dget_lst(args, "keys")) == NULL) return IPC_COMMERR; nkeys = benc_nelems(keys); opts = btpd_calloc(nkeys, sizeof(*opts)); p = benc_first(keys); for (int i = 0; i < nkeys; i++) opts[i] = benc_int(p, &p); iob = iobuf_init(1 << 15); iobuf_swrite(&iob, "d4:codei0e6:resultl"); p = benc_dget_any(args, "from"); if (benc_isint(p)) { enum ipc_twc from = benc_int(p, NULL); struct htbl_iter it; struct tlib *tl; for (tl = tlib_iter_first(&it); tl != NULL; tl = tlib_iter_next(&it)) { if (!torrent_haunting(tl) && ( from == IPC_TWC_ALL || (!torrent_active(tl) && from == IPC_TWC_INACTIVE) || (torrent_active(tl) && from == IPC_TWC_ACTIVE))) { iobuf_swrite(&iob, "l"); for (int k = 0; k < nkeys; k++) write_ans(&iob, tl, opts[k]); iobuf_swrite(&iob, "e"); } } } else if (benc_islst(p)) { for (p = benc_first(p); p != NULL; p = benc_next(p)) { struct tlib *tl = NULL; if (benc_isint(p)) tl = tlib_by_num(benc_int(p, NULL)); else if (benc_isstr(p) && benc_strlen(p) == 20) tl = tlib_by_hash(benc_mem(p, NULL, NULL)); else { iobuf_free(&iob); free(opts); return IPC_COMMERR; } if (tl != NULL && !torrent_haunting(tl)) { iobuf_swrite(&iob, "l"); for (int i = 0; i < nkeys; i++) write_ans(&iob, tl, opts[i]); iobuf_swrite(&iob, "e"); } else iobuf_print(&iob, "i%de", IPC_ENOTENT); } } iobuf_swrite(&iob, "ee"); free(opts); return write_buffer(cli, &iob); }