162 lines
4.9 KiB
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;
|
|
}
|