torrent-stats/torrentfile.c

162 lines
4.9 KiB
C

/***************************************************************************
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include "configfile.h"
#include "event.h"
#include "list.h"
#include "logging.h"
#include "process.h"
#include "torrentfile.h"
static const char *searchpath;
static const char *ctorrent_bin;
static const char *statserv;
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)
{
char buf[256];
int len = snprintf(buf, sizeof(buf), "%s/%s", searchpath, 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;
}
char *const args[] = { (char *)ctorrent_bin, "-S", (char *)statserv, "-f", buf, NULL };
torrent->child = childproc_alloc(args, searchpath);
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;
}
int torrentfile_init(void)
{
searchpath = config_get_string("global", "search-path", NULL);
if (searchpath == NULL)
log_print(LOG_WARN, "disable torrent autostart");
ctorrent_bin = config_get_string("global", "ctorrent-bin", "/usr/bin/ctorrent");
statserv = config_get_string("global", "statserv", "127.0.0.1:2780");
return 0;
}