diff --git a/btpd/Makefile.am b/btpd/Makefile.am index 72ae36a..cb72911 100644 --- a/btpd/Makefile.am +++ b/btpd/Makefile.am @@ -1,5 +1,6 @@ bin_PROGRAMS=btpd btpd_SOURCES=\ + active.c active.h\ btpd.c btpd.h\ cli_if.c content.c content.h\ download.c download_subr.c download.h\ diff --git a/btpd/active.c b/btpd/active.c new file mode 100644 index 0000000..8a2b0aa --- /dev/null +++ b/btpd/active.c @@ -0,0 +1,101 @@ +#include +#include + +#include +#include + +#include "btpd.h" + +void +active_add(const uint8_t *hash) +{ + FILE *fp; + if ((fp = fopen("active", "a")) == NULL) { + btpd_log(BTPD_L_ERROR, "couldn't open file 'active' (%s).\n", + strerror(errno)); + return; + } + fwrite(hash, 20, 1, fp); + fclose(fp); +} + +static void +active_del_pos(FILE *fp, long pos, off_t *size) +{ + uint8_t ehash[20]; + fseek(fp, -20, SEEK_END); + fread(ehash, 20, 1, fp); + fseek(fp, pos, SEEK_SET); + fwrite(ehash, 20, 1, fp); + fflush(fp); + *size -= 20; + ftruncate(fileno(fp), *size); +} + +void +active_del(const uint8_t *hash) +{ + FILE *fp; + long pos; + struct stat sb; + uint8_t buf[20]; + + if ((fp = fopen("active", "r+")) == NULL) { + btpd_log(BTPD_L_ERROR, "couldn't open file 'active' (%s).\n", + strerror(errno)); + return; + } + + if (fstat(fileno(fp), &sb) != 0) { + btpd_log(BTPD_L_ERROR, "couldn't stat file 'active' (%s).\n", + strerror(errno)); + goto close; + } + + pos = 0; + while (fread(buf, 20, 1, fp) == 1) { + if (bcmp(buf, hash, 20) == 0) { + active_del_pos(fp, pos, &sb.st_size); + break; + } + pos += 20; + } +close: + fclose(fp); +} + +void +active_start(void) +{ + FILE *fp; + long pos; + struct stat sb; + uint8_t hash[20]; + + if ((fp = fopen("active", "r+")) == NULL) + return; + + if (fstat(fileno(fp), &sb) != 0) { + btpd_log(BTPD_L_ERROR, "Couldn't stat file 'active' (%s).\n", + strerror(errno)); + goto close; + } + + pos = 0; + while (fread(hash, sizeof(hash), 1, fp) == 1) { + if (torrent_get(hash) == NULL) + if (torrent_start(hash) != 0) { + active_del_pos(fp, pos, &sb.st_size); + fseek(fp, pos, SEEK_SET); + } + pos += 20; + } +close: + fclose(fp); +} + +void +active_clear(void) +{ + unlink("active"); +} diff --git a/btpd/active.h b/btpd/active.h new file mode 100644 index 0000000..47c1519 --- /dev/null +++ b/btpd/active.h @@ -0,0 +1,9 @@ +#ifndef BTPD_ACTIVE_H +#define BTPD_ACTIVE_H + +void active_add(const uint8_t *hash); +void active_del(const uint8_t *hash); +void active_clear(void); +void active_start(void); + +#endif diff --git a/btpd/btpd.c b/btpd/btpd.c index c41d208..8716001 100644 --- a/btpd/btpd.c +++ b/btpd/btpd.c @@ -28,6 +28,7 @@ #include "btpd.h" #include "http.h" +#include "active.h" static uint8_t m_peer_id[20]; static struct event m_sigint; @@ -209,4 +210,9 @@ btpd_init(void) btpd_ev_add(&m_sigterm, NULL); evtimer_set(&m_heartbeat, heartbeat_cb, NULL); btpd_ev_add(&m_heartbeat, (& (struct timeval) { 1, 0 })); + + if (!empty_start) + active_start(); + else + active_clear(); } diff --git a/btpd/cli_if.c b/btpd/cli_if.c index 1473bc3..a6bde4f 100644 --- a/btpd/cli_if.c +++ b/btpd/cli_if.c @@ -12,6 +12,7 @@ #include #include "btpd.h" +#include "active.h" #include "tracker_req.h" struct cli { @@ -121,8 +122,12 @@ cmd_add(struct cli *cli, int argc, const char *args) code = IPC_ERROR; goto out; } - if (torrent_start(hash) != 0) + if (torrent_start(hash) != 0) { code = IPC_ERROR; + goto out; + } + + active_add(hash); out: if (content != NULL) @@ -149,8 +154,10 @@ cmd_del(struct cli *cli, int argc, const char *args) // Stopping a torrent may trigger exit so we need to reply before. int ret = write_code_buffer(cli, IPC_OK); struct torrent *tp = torrent_get(hash); - if (tp != NULL) + if (tp != NULL) { torrent_stop(tp); + active_del(hash); + } return ret; } diff --git a/btpd/main.c b/btpd/main.c index b8165e7..f5c88e2 100644 --- a/btpd/main.c +++ b/btpd/main.c @@ -96,6 +96,9 @@ usage(void) "-d dir\n" "\tThe directory in which to run btpd. Default is '$HOME/.btpd'.\n" "\n" + "--empty-start\n" + "\tStart btpd without any active torrents.\n" + "\n" "--help\n" "\tShow this text.\n" "\n" @@ -144,6 +147,7 @@ static struct option longopts[] = { { "no-daemon", no_argument, &longval, 6 }, { "logfile", required_argument, &longval, 7 }, { "ipcprot", required_argument, &longval, 8 }, + { "empty-start", no_argument, &longval, 9 }, { "help", no_argument, &longval, 128 }, { NULL, 0, NULL, 0 } }; @@ -192,6 +196,9 @@ main(int argc, char **argv) case 8: ipcprot = strtol(optarg, NULL, 8); break; + case 9: + empty_start = 1; + break; default: usage(); } diff --git a/btpd/opts.c b/btpd/opts.c index 97a8045..a6f5817 100644 --- a/btpd/opts.c +++ b/btpd/opts.c @@ -13,3 +13,4 @@ unsigned net_bw_limit_out; int net_port = 6881; off_t cm_alloc_size = 2048 * 1024; int ipcprot = 0600; +int empty_start = 0; diff --git a/btpd/opts.h b/btpd/opts.h index 7e27051..8372f4d 100644 --- a/btpd/opts.h +++ b/btpd/opts.h @@ -10,5 +10,6 @@ extern unsigned net_bw_limit_out; extern int net_port; extern off_t cm_alloc_size; extern int ipcprot; +extern int empty_start; #endif