/*************************************************************************** * Copyright (C) 05/2009 by Olaf Rempel * * razzor@kopf-tisch.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include "configfile.h" #include "event.h" #include "list.h" #include "logging.h" #include "process.h" #include "torrentfile.h" LIST_HEAD(torrent_list); struct torrent_file * find_create_torrent(const char *fullpath) { /* strip directory from filename */ const char *filename = strrchr(fullpath, '/'); if (filename == NULL || *(filename +1) == '\0') filename = fullpath; else filename++; /* search for this torrent */ struct torrent_file *torrent; list_for_each_entry(torrent, &torrent_list, list) { if (strcmp(torrent->name, filename) == 0) return torrent; } /* create a new one */ torrent = malloc(sizeof(struct torrent_file) + strlen(filename)); if (torrent == NULL) { log_print(LOG_WARN, "find_create_torrent(): out of memory"); return NULL; } /* init fields */ INIT_LIST_HEAD(&torrent->client_list); torrent->name = strdup(filename); torrent->destroy = 0; torrent->child = NULL; /* keep torrent list sorted by name */ struct torrent_file *search; list_for_each_entry(search, &torrent_list, list) if (strcmp(search->name, torrent->name) > 0) break; list_add_tail(&torrent->list, &search->list); return torrent; } int destroy_torrent(struct torrent_file *torrent) { /* remove us from list */ list_del(&torrent->list); /* check if we're seeding, destroy after sigchld */ if (torrent->child != NULL) { torrent->destroy = 1; kill(SIGTERM, torrent->child->pid); return 0; } free(torrent->name); free(torrent); return 0; } static void child_exit(struct child_process *child, int exit_code, void *privdata) { struct torrent_file *torrent = (struct torrent_file *)privdata; log_print(LOG_INFO, "ctorrent [pid:%d] was killed (exit:%d)", child->pid, exit_code); torrent->child = NULL; close(child->fd[STDIN_FILENO]); close(child->fd[STDOUT_FILENO]); close(child->fd[STDERR_FILENO]); if (torrent->destroy) destroy_torrent(torrent); } static int null_read(int fd, void *privdata) { char buf[256]; int len = read(fd, buf, sizeof(buf)); return !(len > 0); } int seed_torrent(struct torrent_file *torrent) { const char *path = config_get_string("global", "search-path", NULL); if (path == NULL) { log_print(LOG_WARN, "requesting torrentfile, but no search path given"); return -1; } char buf[256]; int len = snprintf(buf, sizeof(buf), "%s/%s", path, torrent->name); if (len < 0 || len >= sizeof(buf)) { log_print(LOG_WARN, "filename > max"); return -1; } struct stat statbuf; if (stat(buf, &statbuf) < 0) { log_print(LOG_WARN, "torrent file not found: %s", buf); return -1; } const char *ctorrent_bin = config_get_string("global", "ctorrent-bin", "/usr/bin/ctorrent"); const char *statserv = config_get_string("global", "statserv", "127.0.0.1:2780"); char *const args[] = { (char *)ctorrent_bin, "-S", (char *)statserv, "-f", buf, NULL }; torrent->child = childproc_alloc(args, path); if (childproc_fork(torrent->child, child_exit, torrent) < 0) { log_print(LOG_ERROR, "spawn_child(%s)", args[0]); childproc_free(torrent->child); torrent->child = NULL; return -1; } log_print(LOG_INFO, "spawned ctorrent for %s [pid:%d]", torrent->name, torrent->child->pid); /* just read all output from ctorrent to /dev/null */ event_add_readfd(NULL, torrent->child->fd[STDOUT_FILENO], null_read, NULL); event_add_readfd(NULL, torrent->child->fd[STDERR_FILENO], null_read, NULL); return 0; }