ctorrent stat collector
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

168 lines
5.1KB

  1. /***************************************************************************
  2. * Copyright (C) 05/2009 by Olaf Rempel *
  3. * razzor@kopf-tisch.de *
  4. * *
  5. * This program is free software; you can redistribute it and/or modify *
  6. * it under the terms of the GNU General Public License as published by *
  7. * the Free Software Foundation; version 2 of the License *
  8. * *
  9. * This program is distributed in the hope that it will be useful, *
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  12. * GNU General Public License for more details. *
  13. * *
  14. * You should have received a copy of the GNU General Public License *
  15. * along with this program; if not, write to the *
  16. * Free Software Foundation, Inc., *
  17. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  18. ***************************************************************************/
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <unistd.h>
  22. #include <string.h>
  23. #include <sys/stat.h>
  24. #include "configfile.h"
  25. #include "event.h"
  26. #include "list.h"
  27. #include "logging.h"
  28. #include "process.h"
  29. #include "torrentfile.h"
  30. static const char *searchpath;
  31. static const char *ctorrent_bin;
  32. static const char *statserv;
  33. LIST_HEAD(torrent_list);
  34. struct torrent_file * find_create_torrent(const char *fullpath)
  35. {
  36. /* strip directory from filename */
  37. const char *filename = strrchr(fullpath, '/');
  38. if (filename == NULL || *(filename +1) == '\0')
  39. filename = fullpath;
  40. else
  41. filename++;
  42. /* search for this torrent */
  43. struct torrent_file *torrent;
  44. list_for_each_entry(torrent, &torrent_list, list) {
  45. if (strcmp(torrent->name, filename) == 0)
  46. return torrent;
  47. }
  48. /* create a new one */
  49. torrent = malloc(sizeof(struct torrent_file) + strlen(filename));
  50. if (torrent == NULL) {
  51. log_print(LOG_WARN, "find_create_torrent(): out of memory");
  52. return NULL;
  53. }
  54. /* init fields */
  55. INIT_LIST_HEAD(&torrent->client_list);
  56. torrent->name = strdup(filename);
  57. torrent->destroy = 0;
  58. torrent->child = NULL;
  59. /* keep torrent list sorted by name */
  60. struct torrent_file *search;
  61. list_for_each_entry(search, &torrent_list, list)
  62. if (strcmp(search->name, torrent->name) > 0)
  63. break;
  64. list_add_tail(&torrent->list, &search->list);
  65. return torrent;
  66. }
  67. int destroy_torrent(struct torrent_file *torrent)
  68. {
  69. /* check if we're still seeding, and deferr the destroy after sigchld */
  70. if (torrent->child != NULL) {
  71. torrent->destroy = 1;
  72. if (kill(SIGTERM, torrent->child->pid) < 0)
  73. log_print(LOG_WARN, "failed to kill ctorrent [pid:%d]", torrent->child->pid);
  74. return 0;
  75. }
  76. /* remove us from list */
  77. list_del(&torrent->list);
  78. free(torrent->name);
  79. free(torrent);
  80. return 0;
  81. }
  82. static void child_exit(struct child_process *child, int exit_code, void *privdata)
  83. {
  84. struct torrent_file *torrent = (struct torrent_file *)privdata;
  85. log_print(LOG_INFO, "ctorrent [pid:%d] was killed (exit:%d)", child->pid, exit_code);
  86. torrent->child = NULL;
  87. close(child->fd[STDIN_FILENO]);
  88. close(child->fd[STDOUT_FILENO]);
  89. close(child->fd[STDERR_FILENO]);
  90. /* destroy was deferred until our child died, so do it now */
  91. if (torrent->destroy)
  92. destroy_torrent(torrent);
  93. }
  94. static int null_read(int fd, void *privdata)
  95. {
  96. char buf[256];
  97. int len = read(fd, buf, sizeof(buf));
  98. return !(len > 0);
  99. }
  100. int seed_torrent(struct torrent_file *torrent)
  101. {
  102. char buf[256];
  103. int len = snprintf(buf, sizeof(buf), "%s/%s", searchpath, torrent->name);
  104. if (len < 0 || len >= sizeof(buf)) {
  105. log_print(LOG_WARN, "filename > max");
  106. return -1;
  107. }
  108. struct stat statbuf;
  109. if (stat(buf, &statbuf) < 0) {
  110. log_print(LOG_WARN, "torrent file not found: %s", buf);
  111. return -1;
  112. }
  113. char *const args[] = { (char *)ctorrent_bin, "-S", (char *)statserv, "-f", buf, NULL };
  114. torrent->child = childproc_alloc(args, searchpath);
  115. if (torrent->child == NULL)
  116. return -1;
  117. if (childproc_fork(torrent->child, child_exit, torrent) < 0) {
  118. log_print(LOG_ERROR, "spawn_child(%s)", args[0]);
  119. childproc_free(torrent->child);
  120. torrent->child = NULL;
  121. return -1;
  122. }
  123. log_print(LOG_INFO, "spawned ctorrent for %s [pid:%d]", torrent->name, torrent->child->pid);
  124. /* just read all output from ctorrent to /dev/null */
  125. event_add_readfd(NULL, torrent->child->fd[STDOUT_FILENO], null_read, NULL);
  126. event_add_readfd(NULL, torrent->child->fd[STDERR_FILENO], null_read, NULL);
  127. return 0;
  128. }
  129. int torrentfile_init(void)
  130. {
  131. searchpath = config_get_string("global", "search-path", NULL);
  132. if (searchpath == NULL)
  133. log_print(LOG_WARN, "disable torrent autostart");
  134. ctorrent_bin = config_get_string("global", "ctorrent-bin", "/usr/bin/ctorrent");
  135. statserv = config_get_string("global", "statserv", "127.0.0.1:2780");
  136. return 0;
  137. }