mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-05 17:52:29 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 39f186e523 | |||
| 70e6964823 | |||
| 7ead88448b | |||
| 650f0299b5 | |||
| 5dfb2ae938 | |||
| f05a2ae520 | |||
| ecefdba734 | |||
| 87666199b3 | |||
| 9489793dcb | |||
| 2fa7568165 | |||
| f4b718f685 | |||
| b233e24465 | |||
| 289ab046bf | |||
| a8b6a47054 | |||
| 110591d5c1 |
@@ -9,9 +9,6 @@ nobase_dist_pkgdata_DATA = \
|
||||
EXTRA_DIST= \
|
||||
rak/address_info.h \
|
||||
rak/algorithm.h \
|
||||
rak/error_number.h \
|
||||
rak/file_stat.h \
|
||||
rak/path.h \
|
||||
rak/partial_queue.h \
|
||||
rak/regex.h \
|
||||
rak/string_manip.h \
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
m4_pattern_allow([PKG_CHECK_EXISTS])
|
||||
|
||||
AC_INIT([rtorrent],[0.16.6],[sundell.software@gmail.com])
|
||||
AC_INIT([rtorrent],[0.16.8],[sundell.software@gmail.com])
|
||||
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIRS([scripts])
|
||||
@@ -11,7 +11,7 @@ LT_INIT
|
||||
|
||||
AC_PROG_CXX
|
||||
|
||||
AC_DEFINE([API_VERSION], [18], [api version])
|
||||
AC_DEFINE([API_VERSION], [19], [api version])
|
||||
|
||||
# Filter out unwanted flags added by autoconf on some systems, e.g. MacOS.
|
||||
TORRENT_REMOVE_UNWANTED(CXX, $CXX, -std=c++11 -std=gnu++11)
|
||||
@@ -48,7 +48,7 @@ if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES([CPPUNIT], [cppunit],, [no_cppunit="yes"])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.6])
|
||||
PKG_CHECK_MODULES([DEPENDENCIES], [libtorrent >= 0.16.8])
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
TORRENT_WITH_XMLRPC_C
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
#ifndef RAK_ERROR_NUMBER_H
|
||||
#define RAK_ERROR_NUMBER_H
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
|
||||
namespace rak {
|
||||
|
||||
class error_number {
|
||||
public:
|
||||
static const int e_access = EACCES;
|
||||
static const int e_again = EAGAIN;
|
||||
static const int e_connreset = ECONNRESET;
|
||||
static const int e_connaborted = ECONNABORTED;
|
||||
static const int e_deadlk = EDEADLK;
|
||||
|
||||
static const int e_noent = ENOENT;
|
||||
static const int e_nodev = ENODEV;
|
||||
static const int e_nomem = ENOMEM;
|
||||
static const int e_notdir = ENOTDIR;
|
||||
static const int e_isdir = EISDIR;
|
||||
|
||||
static const int e_intr = EINTR;
|
||||
|
||||
error_number() : m_errno(0) {}
|
||||
error_number(int e) : m_errno(e) {}
|
||||
|
||||
bool is_valid() const { return m_errno != 0; }
|
||||
|
||||
int value() const { return m_errno; }
|
||||
const char* c_str() const { return std::strerror(m_errno); }
|
||||
|
||||
bool is_blocked_momentary() const { return m_errno == e_again || m_errno == e_intr; }
|
||||
bool is_blocked_prolonged() const { return m_errno == e_deadlk; }
|
||||
|
||||
bool is_closed() const { return m_errno == e_connreset || m_errno == e_connaborted; }
|
||||
|
||||
bool is_bad_path() const { return m_errno == e_noent || m_errno == e_notdir || m_errno == e_access; }
|
||||
|
||||
static error_number current() { return errno; }
|
||||
static void clear_global() { errno = 0; }
|
||||
static void set_global(error_number err) { errno = err.m_errno; }
|
||||
|
||||
bool operator == (const error_number& e) const { return m_errno == e.m_errno; }
|
||||
|
||||
private:
|
||||
int m_errno;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,75 +0,0 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RAK_FILE_STAT_H
|
||||
#define RAK_FILE_STAT_H
|
||||
|
||||
#include <string>
|
||||
#include <cinttypes>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace rak {
|
||||
|
||||
class file_stat {
|
||||
public:
|
||||
// Consider storing rak::error_number.
|
||||
|
||||
bool update(int fd) { return fstat(fd, &m_stat) == 0; }
|
||||
bool update(const char* filename) { return stat(filename, &m_stat) == 0; }
|
||||
bool update(const std::string& filename) { return update(filename.c_str()); }
|
||||
|
||||
bool update_link(const char* filename) { return lstat(filename, &m_stat) == 0; }
|
||||
bool update_link(const std::string& filename) { return update_link(filename.c_str()); }
|
||||
|
||||
bool is_regular() const { return S_ISREG(m_stat.st_mode); }
|
||||
bool is_directory() const { return S_ISDIR(m_stat.st_mode); }
|
||||
bool is_character() const { return S_ISCHR(m_stat.st_mode); }
|
||||
bool is_block() const { return S_ISBLK(m_stat.st_mode); }
|
||||
bool is_fifo() const { return S_ISFIFO(m_stat.st_mode); }
|
||||
bool is_link() const { return S_ISLNK(m_stat.st_mode); }
|
||||
bool is_socket() const { return S_ISSOCK(m_stat.st_mode); }
|
||||
|
||||
off_t size() const { return m_stat.st_size; }
|
||||
|
||||
time_t access_time() const { return m_stat.st_atime; }
|
||||
time_t change_time() const { return m_stat.st_ctime; }
|
||||
time_t modified_time() const { return m_stat.st_mtime; }
|
||||
|
||||
private:
|
||||
struct stat m_stat;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2007, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
// Various functions for manipulating file paths. Also consider making
|
||||
// a directory iterator.
|
||||
|
||||
#ifndef RAK_PATH_H
|
||||
#define RAK_PATH_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
namespace rak {
|
||||
|
||||
inline std::string
|
||||
path_expand(const std::string& path) {
|
||||
if (path.empty() || path[0] != '~')
|
||||
return path;
|
||||
|
||||
char* home = std::getenv("HOME");
|
||||
|
||||
if (home == NULL)
|
||||
return path;
|
||||
|
||||
return home + path.substr(1);
|
||||
}
|
||||
|
||||
// Don't inline this...
|
||||
//
|
||||
// Same strlcpy as found in *bsd.
|
||||
inline size_t
|
||||
strlcpy(char *dest, const char *src, size_t size) {
|
||||
size_t n = size;
|
||||
const char* first = src;
|
||||
|
||||
if (n != 0) {
|
||||
while (--n != 0)
|
||||
if ((*dest++ = *src++) == '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
if (size != 0)
|
||||
*dest = '\0';
|
||||
|
||||
while (*src++)
|
||||
;
|
||||
}
|
||||
|
||||
return src - first - 1;
|
||||
}
|
||||
|
||||
inline char*
|
||||
path_expand(const char* src, char* first, char* last) {
|
||||
if (*src == '~') {
|
||||
char* home = std::getenv("HOME");
|
||||
|
||||
if (home == NULL)
|
||||
return first;
|
||||
|
||||
first += strlcpy(first, home, std::distance(first, last));
|
||||
|
||||
if (first > last)
|
||||
return last;
|
||||
|
||||
src++;
|
||||
}
|
||||
|
||||
return std::min(first + strlcpy(first, src, std::distance(first, last)), last);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -172,8 +172,6 @@ libsub_root_a_SOURCES = \
|
||||
utils/list_focus.h \
|
||||
utils/lockfile.cc \
|
||||
utils/lockfile.h \
|
||||
utils/socket_fd.cc \
|
||||
utils/socket_fd.h \
|
||||
\
|
||||
command_download.cc \
|
||||
command_dynamic.cc \
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include <functional>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/path.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <rak/regex.h>
|
||||
#include <torrent/rate.h>
|
||||
@@ -21,6 +19,7 @@
|
||||
#include <torrent/net/types.h>
|
||||
#include <torrent/peer/connection_list.h>
|
||||
#include <torrent/peer/peer_list.h>
|
||||
#include <torrent/utils/file_stat.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
@@ -77,23 +76,23 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
|
||||
|
||||
if (type == "base_path") {
|
||||
target = rpc::call_command_string("d.base_path", rpc::make_target(download));
|
||||
link = rak::path_expand(prefix + rpc::call_command_string("d.base_path", rpc::make_target(download)) + postfix);
|
||||
link = expand_path(prefix + rpc::call_command_string("d.base_path", rpc::make_target(download)) + postfix);
|
||||
|
||||
} else if (type == "base_filename") {
|
||||
target = rpc::call_command_string("d.base_path", rpc::make_target(download));
|
||||
link = rak::path_expand(prefix + rpc::call_command_string("d.base_filename", rpc::make_target(download)) + postfix);
|
||||
link = expand_path(prefix + rpc::call_command_string("d.base_filename", rpc::make_target(download)) + postfix);
|
||||
|
||||
// } else if (type == "directory_path") {
|
||||
// target = rpc::call_command_string("d.directory", rpc::make_target(download));
|
||||
// link = rak::path_expand(prefix + rpc::call_command_string("d.base_path", rpc::make_target(download)) + postfix);
|
||||
|
||||
} else if (type == "tied") {
|
||||
link = rak::path_expand(rpc::call_command_string("d.tied_to_file", rpc::make_target(download)));
|
||||
link = expand_path(rpc::call_command_string("d.tied_to_file", rpc::make_target(download)));
|
||||
|
||||
if (link.empty())
|
||||
return torrent::Object();
|
||||
|
||||
link = rak::path_expand(prefix + link + postfix);
|
||||
link = expand_path(prefix + link + postfix);
|
||||
target = rpc::call_command_string("d.base_path", rpc::make_target(download));
|
||||
|
||||
} else {
|
||||
@@ -109,7 +108,7 @@ apply_d_change_link(core::Download* download, const torrent::Object::list_type&
|
||||
|
||||
case 1:
|
||||
{
|
||||
rak::file_stat fileStat;
|
||||
torrent::utils::FileStat fileStat;
|
||||
errno = 0;
|
||||
|
||||
if (!fileStat.update_link(link) || !fileStat.is_link() || unlink(link.c_str()) == -1)
|
||||
@@ -131,7 +130,7 @@ apply_d_delete_tied(core::Download* download) {
|
||||
if (tie.empty())
|
||||
return torrent::Object();
|
||||
|
||||
if (::unlink(rak::path_expand(tie).c_str()) == -1)
|
||||
if (::unlink(expand_path(tie).c_str()) == -1)
|
||||
control->core()->push_log_std("Could not unlink tied file: " + std::string(std::strerror(errno)));
|
||||
|
||||
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(download));
|
||||
|
||||
+10
-12
@@ -2,14 +2,12 @@
|
||||
|
||||
#include <functional>
|
||||
#include <cstdio>
|
||||
#include <rak/error_number.h>
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/path.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/hash_string.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/directory_events.h>
|
||||
#include <torrent/utils/file_stat.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "control.h"
|
||||
@@ -67,10 +65,10 @@ apply_start_tied() {
|
||||
if (rpc::call_command_value("d.state", rpc::make_target(download)) == 1)
|
||||
continue;
|
||||
|
||||
rak::file_stat fs;
|
||||
torrent::utils::FileStat fs;
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(download));
|
||||
|
||||
if (!tied_to_file.empty() && fs.update(rak::path_expand(tied_to_file)))
|
||||
if (!tied_to_file.empty() && fs.update(expand_path(tied_to_file)))
|
||||
rpc::parse_command_single(rpc::make_target(download), "d.try_start=");
|
||||
}
|
||||
|
||||
@@ -83,10 +81,10 @@ apply_stop_untied() {
|
||||
if (rpc::call_command_value("d.state", rpc::make_target(download)) == 0)
|
||||
continue;
|
||||
|
||||
rak::file_stat fs;
|
||||
torrent::utils::FileStat fs;
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(download));
|
||||
|
||||
if (!tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file)))
|
||||
if (!tied_to_file.empty() && !fs.update(expand_path(tied_to_file)))
|
||||
rpc::parse_command_single(rpc::make_target(download), "d.try_stop=");
|
||||
}
|
||||
|
||||
@@ -96,10 +94,10 @@ apply_stop_untied() {
|
||||
torrent::Object
|
||||
apply_close_untied() {
|
||||
for (const auto& download : *control->core()->download_list()) {
|
||||
rak::file_stat fs;
|
||||
torrent::utils::FileStat fs;
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(download));
|
||||
|
||||
if (rpc::call_command_value("d.ignore_commands", rpc::make_target(download)) == 0 && !tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file)))
|
||||
if (rpc::call_command_value("d.ignore_commands", rpc::make_target(download)) == 0 && !tied_to_file.empty() && !fs.update(expand_path(tied_to_file)))
|
||||
rpc::parse_command_single(rpc::make_target(download), "d.try_close=");
|
||||
}
|
||||
|
||||
@@ -109,10 +107,10 @@ apply_close_untied() {
|
||||
torrent::Object
|
||||
apply_remove_untied() {
|
||||
for (auto itr = control->core()->download_list()->begin(); itr != control->core()->download_list()->end(); ) {
|
||||
rak::file_stat fs;
|
||||
torrent::utils::FileStat fs;
|
||||
const std::string& tied_to_file = rpc::call_command_string("d.tied_to_file", rpc::make_target(*itr));
|
||||
|
||||
if (!tied_to_file.empty() && !fs.update(rak::path_expand(tied_to_file))) {
|
||||
if (!tied_to_file.empty() && !fs.update(expand_path(tied_to_file))) {
|
||||
// Need to clear tied_to_file so it doesn't try to delete it.
|
||||
rpc::call_command("d.tied_to_file.set", std::string(), rpc::make_target(*itr));
|
||||
|
||||
@@ -301,7 +299,7 @@ directory_watch_added(const torrent::Object::list_type& args) {
|
||||
auto& command = args.back().as_string();
|
||||
|
||||
if (!control->directory_events()->open())
|
||||
throw torrent::input_error("Could not open inotify:" + std::string(rak::error_number::current().c_str()));
|
||||
throw torrent::input_error("Could not open inotify:" + std::string(std::strerror(errno)));
|
||||
|
||||
control->directory_events()->notify_on(path.c_str(),
|
||||
torrent::directory_events::flag_on_added | torrent::directory_events::flag_on_updated,
|
||||
|
||||
@@ -1,41 +1,5 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <rak/error_number.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/data/file.h>
|
||||
#include <torrent/data/file_list.h>
|
||||
#include <torrent/data/file_list_iterator.h>
|
||||
|
||||
+10
-46
@@ -1,54 +1,18 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/peer/peer_list.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "command_helpers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <torrent/peer/peer_list.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/option_strings.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "command_helpers.h"
|
||||
|
||||
bool ipv4_range_parse(const char* address, uint32_t* address_start, uint32_t* address_end);
|
||||
|
||||
@@ -89,7 +53,7 @@ apply_ip_tables_get(const torrent::Object::list_type& args) {
|
||||
if (table_itr == ip_tables.end())
|
||||
throw torrent::input_error("Could not find ip table.");
|
||||
|
||||
if (!ipv4_range_parse(address.c_str(), &address_start, &address_end))
|
||||
if (!ipv4_range_parse(address.c_str(), &address_start, &address_end))
|
||||
throw torrent::input_error("Invalid address format.");
|
||||
|
||||
if(!table_itr->table.defined(address_start, address_end))
|
||||
@@ -298,7 +262,7 @@ apply_ipv4_filter_get(const std::string& args) {
|
||||
uint32_t address_start;
|
||||
uint32_t address_end;
|
||||
|
||||
if (!ipv4_range_parse(args.c_str(), &address_start, &address_end))
|
||||
if (!ipv4_range_parse(args.c_str(), &address_start, &address_end))
|
||||
throw torrent::input_error("Invalid address format.");
|
||||
|
||||
if(!torrent::PeerList::ipv4_filter()->defined(address_start, address_end))
|
||||
@@ -326,8 +290,8 @@ apply_ipv4_filter_load(const torrent::Object::list_type& args) {
|
||||
std::string value_name = args.back().as_string();
|
||||
int value = torrent::option_find_string(torrent::OPTION_IP_FILTER, value_name.c_str());
|
||||
|
||||
std::fstream file(rak::path_expand(filename).c_str(), std::ios::in);
|
||||
|
||||
std::fstream file(expand_path(filename).c_str(), std::ios::in);
|
||||
|
||||
if (!file.is_open())
|
||||
throw torrent::input_error("Could not open ip filter file: " + filename);
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <functional>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <rak/path.h>
|
||||
#include <rak/error_number.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <torrent/torrent.h>
|
||||
@@ -171,8 +170,8 @@ cmd_file_append(const torrent::Object::list_type& args) {
|
||||
|
||||
FILE* output = fopen(args.front().as_string().c_str(), "a");
|
||||
|
||||
if (output == NULL)
|
||||
throw torrent::input_error("Could not append to file '" + args.front().as_string() + "': " + rak::error_number::current().c_str());
|
||||
if (output == nullptr)
|
||||
throw torrent::input_error("Could not append to file '" + args.front().as_string() + "': " + std::strerror(errno));
|
||||
|
||||
file_print_list(++args.begin(), args.end(), output, file_print_delim_space);
|
||||
|
||||
|
||||
+14
-11
@@ -14,12 +14,12 @@
|
||||
#include "core/download.h"
|
||||
#include "core/download_list.h"
|
||||
#include "core/manager.h"
|
||||
#include "rak/path.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
static const int log_flag_use_gz = 0x1;
|
||||
static const int log_flag_append_pid = 0x2;
|
||||
static const int log_flag_append_file = 0x4;
|
||||
static const int log_flag_flush = 0x8;
|
||||
|
||||
void
|
||||
log_add_group_output_str(const char* group_name, const char* output_id) {
|
||||
@@ -34,8 +34,8 @@ apply_log_open(int output_flags, const torrent::Object::list_type& args) {
|
||||
|
||||
torrent::Object::list_const_iterator itr = args.begin();
|
||||
|
||||
std::string output_id = (itr++)->as_string();
|
||||
std::string file_name = rak::path_expand((itr++)->as_string());
|
||||
auto output_id = (itr++)->as_string();
|
||||
auto file_name = expand_path((itr++)->as_string());
|
||||
|
||||
if ((output_flags & log_flag_append_pid)) {
|
||||
char buffer[32];
|
||||
@@ -45,11 +45,12 @@ apply_log_open(int output_flags, const torrent::Object::list_type& args) {
|
||||
}
|
||||
|
||||
bool append = (output_flags & log_flag_append_file);
|
||||
bool flush = (output_flags & log_flag_flush);
|
||||
|
||||
if ((output_flags & log_flag_use_gz))
|
||||
torrent::log_open_gz_file_output(output_id.c_str(), file_name.c_str(), append);
|
||||
else
|
||||
torrent::log_open_file_output(output_id.c_str(), file_name.c_str(), append);
|
||||
torrent::log_open_file_output(output_id.c_str(), file_name.c_str(), append, flush);
|
||||
|
||||
while (itr != args.end())
|
||||
log_add_group_output_str((itr++)->as_string().c_str(), output_id.c_str());
|
||||
@@ -85,7 +86,7 @@ apply_log(const torrent::Object::string_type& arg, int logType) {
|
||||
}
|
||||
|
||||
if (!arg.empty()) {
|
||||
int logFd = open(rak::path_expand(arg).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644);
|
||||
int logFd = open(expand_path(arg).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644);
|
||||
|
||||
if (logFd < 0)
|
||||
throw torrent::input_error("Could not open execute log file.");
|
||||
@@ -127,12 +128,14 @@ log_vmmap_dump(const std::string& str) {
|
||||
|
||||
void
|
||||
initialize_command_logging() {
|
||||
CMD2_ANY_LIST ("log.open_file", std::bind(&apply_log_open, 0, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_gz_file", std::bind(&apply_log_open, log_flag_use_gz, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_file_pid", std::bind(&apply_log_open, log_flag_append_pid, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_gz_file_pid", std::bind(&apply_log_open, log_flag_append_pid | log_flag_use_gz, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_gz_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_file", std::bind(&apply_log_open, 0, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_file.flush", std::bind(&apply_log_open, log_flag_flush, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_gz_file", std::bind(&apply_log_open, log_flag_use_gz, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_file_pid", std::bind(&apply_log_open, log_flag_append_pid, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.open_gz_file_pid", std::bind(&apply_log_open, log_flag_append_pid | log_flag_use_gz, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_file.flush", std::bind(&apply_log_open, log_flag_append_file | log_flag_flush, std::placeholders::_2));
|
||||
CMD2_ANY_LIST ("log.append_gz_file", std::bind(&apply_log_open, log_flag_append_file, std::placeholders::_2));
|
||||
|
||||
CMD2_ANY_STRING_V("log.close", std::bind(&torrent::log_close_output_str, std::placeholders::_2));
|
||||
|
||||
|
||||
@@ -4,14 +4,12 @@
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
#include <rak/address_info.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/data/file_manager.h>
|
||||
#include <torrent/download/resource_manager.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/net/network_config.h>
|
||||
#include <torrent/net/network_manager.h>
|
||||
#include <torrent/net/socket_address.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/utils/log.h>
|
||||
@@ -125,7 +123,7 @@ apply_scgi(const std::string& arg, int type) {
|
||||
|
||||
case 2:
|
||||
default:
|
||||
path = rak::path_expand(arg);
|
||||
path = expand_path(arg);
|
||||
|
||||
unlink(path.c_str());
|
||||
scgi->open_named(path);
|
||||
@@ -168,7 +166,6 @@ initialize_command_network() {
|
||||
auto file_manager = torrent::file_manager();
|
||||
auto http_stack = torrent::net_thread::http_stack();
|
||||
auto nw_config = torrent::config::network_config();
|
||||
auto nw_manager = torrent::runtime::network_manager();
|
||||
|
||||
CMD2_ANY_STRING ("encoding.add", std::bind(&apply_encoding_list, std::placeholders::_2));
|
||||
|
||||
@@ -177,12 +174,12 @@ initialize_command_network() {
|
||||
CMD2_VAR_BOOL ("network.port_random", true);
|
||||
CMD2_VAR_STRING ("network.port_range", "6881-6999");
|
||||
|
||||
CMD2_ANY ("network.listen.port", [nw_manager](auto, auto) { return nw_manager->listen_port(); });
|
||||
CMD2_ANY ("network.listen.port", [](auto, auto) { return torrent::runtime::listen_port(); });
|
||||
CMD2_ANY ("network.listen.backlog", [nw_config](auto, auto) { return nw_config->listen_backlog(); });
|
||||
CMD2_ANY_VALUE_V ("network.listen.backlog.set", [nw_config](auto, auto& value) { return nw_config->set_listen_backlog(value); });
|
||||
|
||||
CMD2_VAR_BOOL ("protocol.pex", true);
|
||||
CMD2_ANY_LIST ("protocol.encryption.set", [](auto, auto& args) { return apply_encryption(args); });
|
||||
CMD2_ANY_LIST ("protocol.encryption.set", [](auto, auto& args) { return apply_encryption(args); });
|
||||
|
||||
CMD2_VAR_STRING ("protocol.connection.leech", "leech");
|
||||
CMD2_VAR_STRING ("protocol.connection.seed", "seed");
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include <cstdio>
|
||||
#include <netdb.h>
|
||||
#include <torrent/net/network_config.h>
|
||||
#include <torrent/net/network_manager.h>
|
||||
#include <torrent/net/resolver.h>
|
||||
#include <torrent/runtime/network_manager.h>
|
||||
#include <torrent/tracker/dht_controller.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/utils/log.h>
|
||||
@@ -28,9 +28,6 @@ tracker_set_enabled(torrent::tracker::Tracker* tracker, bool state) {
|
||||
|
||||
torrent::Object
|
||||
apply_dht_add_node(const std::string& arg) {
|
||||
if (!torrent::runtime::network_manager()->is_dht_valid())
|
||||
throw torrent::input_error("DHT not enabled.");
|
||||
|
||||
int port;
|
||||
char dummy;
|
||||
char host[1024];
|
||||
@@ -59,7 +56,7 @@ apply_dht_add_node(const std::string& arg) {
|
||||
}
|
||||
|
||||
lt_log_print(torrent::LOG_DHT_CONTROLLER, "dht.add_node : %s", host_str.c_str());
|
||||
torrent::runtime::network_manager()->dht_add_peer_node(sa.get(), port);
|
||||
torrent::runtime::network_manager()->dht_add_bootstrap_node(host_str.c_str(), port);
|
||||
});
|
||||
|
||||
return torrent::Object();
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/net/network_manager.h>
|
||||
#include <torrent/runtime/network_manager.h>
|
||||
#include <torrent/utils/directory_events.h>
|
||||
|
||||
#include "core/dht_manager.h"
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include <sstream>
|
||||
#include <torrent/object.h>
|
||||
#include <torrent/object_stream.h>
|
||||
#include <torrent/net/network_manager.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/runtime/network_manager.h>
|
||||
#include <torrent/tracker/dht_controller.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
|
||||
+11
-10
@@ -1,25 +1,25 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "core/download.h"
|
||||
|
||||
#include <list>
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/rate.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/tracker/tracker.h>
|
||||
#include <torrent/data/file.h>
|
||||
#include <torrent/data/file_list.h>
|
||||
#include <torrent/utils/file_stat.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
#include "control.h"
|
||||
#include "download.h"
|
||||
#include "manager.h"
|
||||
#include "core/manager.h"
|
||||
|
||||
namespace core {
|
||||
|
||||
Download::Download(download_type d) :
|
||||
m_download(d) {
|
||||
Download::Download(download_type d)
|
||||
: m_download(d) {
|
||||
|
||||
m_download.info()->signal_tracker_success().push_back(std::bind(&Download::receive_tracker_msg, this, ""));
|
||||
m_download.info()->signal_tracker_failed().push_back(std::bind(&Download::receive_tracker_msg, this, std::placeholders::_1));
|
||||
@@ -118,13 +118,14 @@ void
|
||||
Download::set_root_directory(const std::string& path) {
|
||||
// If the download is open, hashed and has completed chunks make
|
||||
// sure to verify that the download files are still present.
|
||||
//
|
||||
//
|
||||
// This should ensure that no one tries to set the destination
|
||||
// directory 'after' moving files. In cases where the user wants to
|
||||
// override this behavior the download must first be closed or
|
||||
// 'd.directory_base.set' may be used.
|
||||
rak::file_stat file_stat;
|
||||
torrent::FileList* file_list = m_download.file_list();
|
||||
|
||||
torrent::utils::FileStat file_stat;
|
||||
torrent::FileList* file_list = m_download.file_list();
|
||||
|
||||
if (is_hash_checked() && file_list->completed_chunks() != 0 &&
|
||||
|
||||
@@ -140,7 +141,7 @@ Download::set_root_directory(const std::string& path) {
|
||||
}
|
||||
|
||||
control->core()->download_list()->close_directly(this);
|
||||
file_list->set_root_dir(rak::path_expand(path));
|
||||
file_list->set_root_dir(expand_path(path));
|
||||
|
||||
bencode()->get_key("rtorrent").insert_key("directory", path);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/resume.h>
|
||||
#include <torrent/object.h>
|
||||
@@ -123,7 +122,7 @@ DownloadFactory::receive_load() {
|
||||
receive_loaded();
|
||||
|
||||
} else {
|
||||
std::fstream stream(rak::path_expand(m_uri).c_str(), std::ios::in | std::ios::binary);
|
||||
std::fstream stream(expand_path(m_uri).c_str(), std::ios::in | std::ios::binary);
|
||||
|
||||
if (!stream.is_open())
|
||||
return receive_failed("Could not open file");
|
||||
@@ -158,8 +157,8 @@ DownloadFactory::receive_commit() {
|
||||
|
||||
void
|
||||
DownloadFactory::receive_success() {
|
||||
auto rtorrent_object = download_factory_load_stream((rak::path_expand(m_uri) + ".rtorrent").c_str());
|
||||
auto libtorrent_resume_object = download_factory_load_stream((rak::path_expand(m_uri) + ".libtorrent_resume").c_str());
|
||||
auto rtorrent_object = download_factory_load_stream((expand_path(m_uri) + ".rtorrent").c_str());
|
||||
auto libtorrent_resume_object = download_factory_load_stream((expand_path(m_uri) + ".libtorrent_resume").c_str());
|
||||
|
||||
uint32_t tracker_key;
|
||||
|
||||
|
||||
+4
-4
@@ -1,5 +1,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "core/manager.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
@@ -8,7 +10,6 @@
|
||||
#include <sys/select.h>
|
||||
#include <rak/address_info.h>
|
||||
#include <rak/regex.h>
|
||||
#include <rak/path.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/utils/resume.h>
|
||||
#include <torrent/object.h>
|
||||
@@ -19,8 +20,8 @@
|
||||
#include <torrent/throttle.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/net/network_config.h>
|
||||
#include <torrent/net/network_manager.h>
|
||||
#include <torrent/net/socket_address.h>
|
||||
#include <torrent/runtime/network_manager.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "rpc/parse_commands.h"
|
||||
@@ -33,7 +34,6 @@
|
||||
#include "core/download.h"
|
||||
#include "core/download_factory.h"
|
||||
#include "core/http_queue.h"
|
||||
#include "core/manager.h"
|
||||
#include "core/view.h"
|
||||
|
||||
namespace core {
|
||||
@@ -257,7 +257,7 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
|
||||
!is_network_uri(uri) &&
|
||||
!is_magnet_uri(uri) &&
|
||||
!is_data_uri(uri) &&
|
||||
!file_status_cache()->insert(uri, 0))
|
||||
!file_status_cache()->insert(uri))
|
||||
return;
|
||||
|
||||
// Adding download.
|
||||
|
||||
@@ -55,6 +55,7 @@ Manager::receive_update() {
|
||||
m_force_redraw = false;
|
||||
|
||||
display::Canvas::resize_term(display::Canvas::term_size());
|
||||
keypad(stdscr, TRUE);
|
||||
Canvas::redraw_std();
|
||||
|
||||
adjust_layout();
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#include <torrent/download/resource_manager.h>
|
||||
#include <torrent/net/http_stack.h>
|
||||
#include <torrent/net/network_config.h>
|
||||
#include <torrent/net/network_manager.h>
|
||||
#include <torrent/net/socket_address.h>
|
||||
#include <torrent/peer/client_info.h>
|
||||
|
||||
@@ -375,8 +374,7 @@ print_status_info(char* first, char* last) {
|
||||
first = print_status_throttle_rate(first, last, false, throttle_down_names, global_downrate);
|
||||
|
||||
first = print_buffer(first, last, " KB]");
|
||||
|
||||
first = print_buffer(first, last, " [Port: %i]", (unsigned int)torrent::runtime::network_manager()->listen_port());
|
||||
first = print_buffer(first, last, " [Port: %i]", (unsigned int)torrent::runtime::listen_port());
|
||||
|
||||
auto local_address = torrent::config::network_config()->local_address_best_match();
|
||||
|
||||
|
||||
@@ -2,6 +2,28 @@
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
rpc::ip_table_list ip_tables;
|
||||
|
||||
Control* control{};
|
||||
|
||||
std::string
|
||||
expand_path(const std::string& path) {
|
||||
if (path.empty())
|
||||
return std::string();
|
||||
|
||||
if (path[0] == '~') {
|
||||
if (path.size() < 2 || path[1] != '/')
|
||||
throw torrent::input_error("Could not expand ~ in session path, only ~/<path> is supported.");
|
||||
|
||||
const char* home = std::getenv("HOME");
|
||||
|
||||
if (home == nullptr || *home == '\0')
|
||||
throw torrent::input_error("Could not expand ~ in session path, HOME environment variable not set.");
|
||||
|
||||
return home + path.substr(1);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
+2
-1
@@ -8,8 +8,9 @@
|
||||
class Control;
|
||||
|
||||
extern rpc::ip_table_list ip_tables;
|
||||
extern Control* control;
|
||||
|
||||
extern Control* control;
|
||||
std::string expand_path(const std::string& path);
|
||||
|
||||
namespace rpc {
|
||||
class SCgi;
|
||||
|
||||
+1
-36
@@ -1,42 +1,7 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
#include <rak/algorithm.h>
|
||||
#include <rak/path.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -73,7 +38,7 @@ PathInput::receive_do_complete() {
|
||||
size_type dirEnd = find_last_delim();
|
||||
|
||||
utils::Directory dir(dirEnd != 0 ? str().substr(0, dirEnd) : "./");
|
||||
|
||||
|
||||
if (!dir.update(utils::Directory::update_sort | utils::Directory::update_hide_dot) || dir.empty()) {
|
||||
mark_dirty();
|
||||
|
||||
|
||||
+1
-2
@@ -13,7 +13,6 @@
|
||||
#include <torrent/net/fd.h>
|
||||
#include <torrent/utils/chrono.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <rak/error_number.h>
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
#include <execinfo.h>
|
||||
@@ -564,7 +563,7 @@ handle_sigbus(int signum, siginfo_t* sa, [[maybe_unused]] void* ptr) {
|
||||
#else
|
||||
output << "Stack dump not enabled." << std::endl;
|
||||
#endif
|
||||
output << std::endl << "Error: " << rak::error_number(sa->si_errno).c_str() << std::endl;
|
||||
output << std::endl << "Error: " << std::strerror(sa->si_errno) << std::endl;
|
||||
|
||||
const char* signal_reason;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <rak/path.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <torrent/utils/thread.h>
|
||||
|
||||
+9
-4
@@ -1,5 +1,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
@@ -10,8 +11,6 @@
|
||||
#include <lua.hpp>
|
||||
#endif
|
||||
|
||||
#include <rak/error_number.h>
|
||||
#include <rak/path.h>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/object.h>
|
||||
|
||||
@@ -266,8 +265,10 @@ object_to_lua(lua_State* l_state, torrent::Object const& object) {
|
||||
lua_createtable(l_state, 0, static_cast<int>(object_map.size()));
|
||||
int table_idx = lua_gettop(l_state);
|
||||
for (const auto& itr : object_map) {
|
||||
object_to_lua(l_state, itr.second);
|
||||
// lua_rawset requires the value to be on top of the stack, with the
|
||||
// key below it.
|
||||
lua_pushlstring(l_state, itr.first.c_str(), itr.first.size());
|
||||
object_to_lua(l_state, itr.second);
|
||||
lua_rawset(l_state, table_idx);
|
||||
}
|
||||
break;
|
||||
@@ -417,12 +418,16 @@ execute_lua(LuaEngine* engine, rpc::target_type target_type, torrent::Object con
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
torrent::Object
|
||||
execute_lua(LuaEngine* engine, torrent::Object const& rawArgs, int flags) {
|
||||
execute_lua([[maybe_unused]] LuaEngine* engine, [[maybe_unused]] torrent::Object const& rawArgs, [[maybe_unused]] int flags) {
|
||||
throw torrent::input_error("Lua support not enabled");
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
LuaEngine::LuaEngine() {}
|
||||
LuaEngine::~LuaEngine() {}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
+24
-55
@@ -1,45 +1,11 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <locale>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "parse.h"
|
||||
|
||||
namespace rpc {
|
||||
@@ -90,7 +56,7 @@ parse_string(const char* first, const char* last, std::string* dest, bool (*deli
|
||||
|
||||
dest->push_back(*first++);
|
||||
}
|
||||
|
||||
|
||||
return first;
|
||||
}
|
||||
}
|
||||
@@ -100,7 +66,7 @@ parse_whole_string(const char* first, const char* last, std::string* dest) {
|
||||
first = parse_skip_wspace(first, last);
|
||||
first = parse_string(first, last, dest);
|
||||
first = parse_skip_wspace(first, last);
|
||||
|
||||
|
||||
if (first != last)
|
||||
throw torrent::input_error("Junk at end of input.");
|
||||
}
|
||||
@@ -175,7 +141,7 @@ parse_object(const char* first, const char* last, torrent::Object* dest, bool (*
|
||||
*dest = torrent::Object::create_list();
|
||||
first = parse_list(first + 1, last, dest, &parse_is_delim_block);
|
||||
first = parse_skip_wspace(first, last);
|
||||
|
||||
|
||||
if (first == last || *first != '}')
|
||||
throw torrent::input_error("Could not find closing '}'.");
|
||||
|
||||
@@ -238,7 +204,7 @@ parse_list(const char* first, const char* last, torrent::Object* dest, bool (*de
|
||||
first = parse_skip_wspace(first, last);
|
||||
|
||||
dest->as_list().push_back(tmp);
|
||||
|
||||
|
||||
if (first == last || !parse_is_seperator(*first))
|
||||
break;
|
||||
|
||||
@@ -284,12 +250,12 @@ convert_to_string(const torrent::Object& rawSrc) {
|
||||
|
||||
if (src.as_raw_bencode().is_raw_string())
|
||||
return src.as_raw_bencode().as_raw_string().as_string();
|
||||
|
||||
|
||||
if (src.as_raw_bencode().is_value())
|
||||
return src.as_raw_bencode().as_value_string();
|
||||
|
||||
default: throw torrent::input_error("Not a string.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
@@ -341,9 +307,9 @@ convert_list_to_command(torrent::Object::list_const_iterator first,
|
||||
if (first == last)
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
std::string dest = (first++)->as_string();
|
||||
std::string::size_type quoteItr = dest.find('=');
|
||||
|
||||
auto dest = (first++)->as_string();
|
||||
auto quoteItr = dest.find('=');
|
||||
|
||||
if (quoteItr == std::string::npos)
|
||||
throw torrent::input_error("Could not find '=' in command.");
|
||||
|
||||
@@ -419,7 +385,7 @@ convert_to_value_nothrow(const torrent::Object& src, int64_t* value, int base, i
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -430,20 +396,23 @@ print_object(char* first, char* last, const torrent::Object* src, int flags) {
|
||||
{
|
||||
const std::string& str = src->as_string();
|
||||
|
||||
if (first == last)
|
||||
return first;
|
||||
|
||||
if ((flags & print_expand_tilde) && *str.c_str() == '~') {
|
||||
return rak::path_expand(str.c_str(), first, last);
|
||||
auto expanded = expand_path(str);
|
||||
|
||||
} else {
|
||||
if (first == last)
|
||||
return first;
|
||||
|
||||
size_t n = std::min<size_t>(str.size(), std::distance(first, last) - 1);
|
||||
|
||||
std::memcpy(first, str.c_str(), n);
|
||||
size_t n = std::min<size_t>(expanded.size(), std::distance(first, last) - 1);
|
||||
std::memcpy(first, expanded.c_str(), n);
|
||||
*(first += n) = '\0';
|
||||
|
||||
return first;
|
||||
} else {
|
||||
size_t n = std::min<size_t>(str.size(), std::distance(first, last) - 1);
|
||||
std::memcpy(first, str.c_str(), n);
|
||||
*(first += n) = '\0';
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
@@ -480,7 +449,7 @@ print_object_std(std::string* dest, const torrent::Object* src, int flags) {
|
||||
const std::string& str = src->as_string();
|
||||
|
||||
if ((flags & print_expand_tilde) && *str.c_str() == '~')
|
||||
*dest += rak::path_expand(str);
|
||||
*dest += expand_path(str);
|
||||
else
|
||||
*dest += str;
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "rpc/parse.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "rpc/rpc_manager.h"
|
||||
@@ -140,7 +140,7 @@ parse_command_multiple(target_type target, const char* first, const char* last)
|
||||
|
||||
bool
|
||||
parse_command_file(const std::string& path) {
|
||||
std::fstream file(rak::path_expand(path).c_str(), std::ios::in);
|
||||
std::fstream file(expand_path(path).c_str(), std::ios::in);
|
||||
|
||||
if (!file.is_open())
|
||||
return false;
|
||||
|
||||
+110
-56
@@ -1,6 +1,8 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <unistd.h>
|
||||
#include <sys/un.h>
|
||||
#include <torrent/connection_manager.h>
|
||||
#include <torrent/torrent.h>
|
||||
@@ -8,42 +10,47 @@
|
||||
#include <torrent/net/fd.h>
|
||||
#include <torrent/net/poll.h>
|
||||
#include <torrent/net/socket_address.h>
|
||||
#include <torrent/runtime/socket_manager.h>
|
||||
|
||||
#include "control.h"
|
||||
#include "globals.h"
|
||||
#include "rpc/scgi_task.h"
|
||||
#include "utils/socket_fd.h"
|
||||
|
||||
// TODO: Figure out why moving this to the top causes a build error.
|
||||
#include "rpc/scgi.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
SCgi::SCgi() {
|
||||
std::generate(m_tasks.begin(), m_tasks.end(), []() { return std::make_unique<SCgiTask>(); });
|
||||
|
||||
m_current = m_tasks.begin();
|
||||
}
|
||||
|
||||
SCgi::~SCgi() {
|
||||
if (!get_fd().is_valid())
|
||||
return;
|
||||
|
||||
for (SCgiTask* itr = m_task, *last = m_task + max_tasks; itr != last; ++itr)
|
||||
if (itr->is_open())
|
||||
itr->close();
|
||||
|
||||
deactivate();
|
||||
torrent::connection_manager()->dec_socket_count();
|
||||
|
||||
get_fd().close();
|
||||
get_fd().clear();
|
||||
|
||||
if (!m_path.empty())
|
||||
::unlink(m_path.c_str());
|
||||
assert(!is_open() && "SCgi::~SCgi() called while open");
|
||||
}
|
||||
|
||||
void
|
||||
SCgi::open_port(void* sa, unsigned int length, bool dontRoute) {
|
||||
if (!get_fd().open_stream() ||
|
||||
(dontRoute && !get_fd().set_dont_route(true)))
|
||||
throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno)));
|
||||
SCgi::open_port(sockaddr* sa, unsigned int length, bool dont_route) {
|
||||
torrent::runtime::socket_manager()->open_event_or_throw(this, [&]() {
|
||||
int fd = torrent::fd_open_family(torrent::fd_flag_stream | torrent::fd_flag_nonblock | torrent::fd_flag_reuse_address,
|
||||
sa->sa_family);
|
||||
|
||||
open(sa, length);
|
||||
if (fd == -1)
|
||||
throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno)));
|
||||
|
||||
if (dont_route && !torrent::fd_set_dont_route(fd, true)) {
|
||||
torrent::fd_close(fd);
|
||||
throw torrent::resource_error("Could not set socket option IP_DONTROUTE: " + std::string(std::strerror(errno)));
|
||||
}
|
||||
|
||||
set_file_descriptor(fd);
|
||||
|
||||
open(reinterpret_cast<sockaddr*>(sa), length);
|
||||
});
|
||||
|
||||
torrent::connection_manager()->inc_socket_count();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -51,45 +58,44 @@ SCgi::open_named(const std::string& filename) {
|
||||
if (filename.empty() || filename.size() > 4096)
|
||||
throw torrent::resource_error("Invalid filename length.");
|
||||
|
||||
auto buffer = std::make_unique<char[]>(sizeof(sockaddr_un) + filename.size());
|
||||
auto buffer = std::make_unique<char[]>(sizeof(sockaddr_un) + filename.size() + 1);
|
||||
|
||||
sockaddr_un* sa = reinterpret_cast<sockaddr_un*>(buffer.get());
|
||||
|
||||
#ifdef __sun__
|
||||
sa->sun_family = AF_UNIX;
|
||||
#else
|
||||
sa->sun_family = AF_LOCAL;
|
||||
#endif
|
||||
|
||||
std::memcpy(sa->sun_path, filename.c_str(), filename.size() + 1);
|
||||
|
||||
if (!get_fd().open_local())
|
||||
throw torrent::resource_error("Could not open socket for listening.");
|
||||
torrent::runtime::socket_manager()->open_event_or_throw(this, [&]() {
|
||||
int fd = torrent::fd_open_local(torrent::fd_flag_stream | torrent::fd_flag_nonblock | torrent::fd_flag_reuse_address);
|
||||
|
||||
if (fd == -1)
|
||||
throw torrent::resource_error("Could not open socket for listening: " + std::string(std::strerror(errno)));
|
||||
|
||||
set_file_descriptor(fd);
|
||||
|
||||
open(reinterpret_cast<sockaddr*>(sa), offsetof(struct sockaddr_un, sun_path) + filename.size() + 1);
|
||||
});
|
||||
|
||||
torrent::connection_manager()->inc_socket_count();
|
||||
|
||||
open(sa, offsetof(struct sockaddr_un, sun_path) + filename.size() + 1);
|
||||
m_path = filename;
|
||||
}
|
||||
|
||||
void
|
||||
SCgi::open(void* sa, unsigned int length) {
|
||||
SCgi::open(sockaddr* sa, unsigned int length) {
|
||||
try {
|
||||
if (!get_fd().set_nonblock() ||
|
||||
!get_fd().set_reuse_address(true) ||
|
||||
!get_fd().bind_sa(reinterpret_cast<sockaddr*>(sa), length) ||
|
||||
!get_fd().listen(max_tasks))
|
||||
if (::bind(file_descriptor(), sa, length) == -1)
|
||||
throw torrent::resource_error("Could not bind socket for listening: " + std::string(std::strerror(errno)));
|
||||
|
||||
if (!torrent::fd_listen(file_descriptor(), max_tasks))
|
||||
throw torrent::resource_error("Could not prepare socket for listening: " + std::string(std::strerror(errno)));
|
||||
|
||||
torrent::connection_manager()->inc_socket_count();
|
||||
|
||||
} catch (torrent::resource_error& e) {
|
||||
get_fd().close();
|
||||
get_fd().clear();
|
||||
|
||||
throw e;
|
||||
torrent::fd_close(file_descriptor());
|
||||
set_file_descriptor(-1);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Verify this is run in correct thread, also only ever call poll methods from thread_self.
|
||||
|
||||
void
|
||||
SCgi::activate() {
|
||||
assert(torrent::this_thread::thread() == scgi_thread::thread());
|
||||
@@ -99,33 +105,81 @@ SCgi::activate() {
|
||||
torrent::this_thread::poll()->insert_error(this);
|
||||
}
|
||||
|
||||
// TODO: This should close the fd to avoid reuse.
|
||||
void
|
||||
SCgi::deactivate() {
|
||||
SCgi::stop() {
|
||||
assert(torrent::this_thread::thread() == scgi_thread::thread());
|
||||
|
||||
torrent::this_thread::poll()->remove_and_close(this);
|
||||
if (!is_open())
|
||||
return;
|
||||
|
||||
for (auto& itr : m_tasks) {
|
||||
if (itr->is_open())
|
||||
itr->close();
|
||||
}
|
||||
|
||||
torrent::runtime::socket_manager()->close_event_or_throw(this, [this]() {
|
||||
torrent::this_thread::poll()->remove_and_close(this);
|
||||
|
||||
torrent::fd_close(file_descriptor());
|
||||
set_file_descriptor(-1);
|
||||
});
|
||||
|
||||
torrent::connection_manager()->dec_socket_count();
|
||||
|
||||
if (!m_path.empty())
|
||||
::unlink(m_path.c_str());
|
||||
}
|
||||
|
||||
void
|
||||
SCgi::event_read() {
|
||||
if (m_current < m_tasks.begin() || m_current >= m_tasks.end())
|
||||
throw torrent::internal_error("SCgi::event_read() m_current is out of bounds");
|
||||
|
||||
while (true) {
|
||||
int fd = torrent::fd_accept(get_fd().get_fd());
|
||||
// TODO: Optimize this by keeping track of count.
|
||||
auto prev = m_current;
|
||||
|
||||
if (fd == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
break;
|
||||
m_current = std::find_if(m_current + 1, m_tasks.end(), [](const auto& task) { return !task->is_open(); });
|
||||
|
||||
throw torrent::resource_error("Listener port accept() failed: " + std::string(std::strerror(errno)));
|
||||
}
|
||||
if (m_current == m_tasks.end())
|
||||
m_current = std::find_if(m_tasks.begin(), prev, [](const auto& task) { return !task->is_open(); });
|
||||
|
||||
SCgiTask* task = std::find_if(m_task, m_task + max_tasks, std::mem_fn(&SCgiTask::is_available));
|
||||
if (m_current == prev) {
|
||||
// TODO: Currently just close, although we should remove ourselves from read.
|
||||
int fd = torrent::fd_accept(file_descriptor());
|
||||
|
||||
if (fd != -1)
|
||||
torrent::fd_close(fd);
|
||||
|
||||
if (task == m_task + max_tasks) {
|
||||
torrent::fd_close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
task->open(this, fd);
|
||||
auto open_func = [this, task = m_current->get()]() {
|
||||
int fd = torrent::fd_accept(file_descriptor());
|
||||
|
||||
if (fd == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
|
||||
return;
|
||||
|
||||
// Force a new event_read() call just to be sure we don't enter an infinite loop.
|
||||
if (errno == ECONNABORTED)
|
||||
return;
|
||||
|
||||
throw torrent::resource_error("Listener port accept() failed: " + std::string(std::strerror(errno)));
|
||||
}
|
||||
|
||||
task->open(this, fd);
|
||||
};
|
||||
|
||||
auto cleanup_func = [task = m_current->get()]() {
|
||||
task->cancel_open();
|
||||
};
|
||||
|
||||
bool result = torrent::runtime::socket_manager()->open_event_or_cleanup(m_current->get(), open_func, cleanup_func);
|
||||
|
||||
if (!result)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-11
@@ -1,15 +1,12 @@
|
||||
#ifndef RTORRENT_RPC_SCGI_H
|
||||
#define RTORRENT_RPC_SCGI_H
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <torrent/event.h>
|
||||
|
||||
#include "rpc/scgi_task.h"
|
||||
#include "utils/socket_fd.h"
|
||||
|
||||
namespace utils {
|
||||
class SocketFd;
|
||||
}
|
||||
|
||||
namespace rpc {
|
||||
|
||||
@@ -17,15 +14,17 @@ class SCgi : public torrent::Event {
|
||||
public:
|
||||
static const int max_tasks = 100;
|
||||
|
||||
SCgi();
|
||||
~SCgi() override;
|
||||
|
||||
const char* type_name() const override { return "scgi"; }
|
||||
|
||||
void open_port(void* sa, unsigned int length, bool dontRoute);
|
||||
void open_port(sockaddr* sa, unsigned int length, bool dont_route);
|
||||
void open_named(const std::string& filename);
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
|
||||
void stop();
|
||||
|
||||
const std::string& path() const { return m_path; }
|
||||
|
||||
@@ -36,14 +35,16 @@ public:
|
||||
void event_write() override;
|
||||
void event_error() override;
|
||||
|
||||
utils::SocketFd& get_fd() { return *reinterpret_cast<utils::SocketFd*>(&m_fileDesc); }
|
||||
|
||||
private:
|
||||
void open(void* sa, unsigned int length);
|
||||
using task_list = std::array<std::unique_ptr<SCgiTask>, max_tasks>;
|
||||
|
||||
void open(sockaddr* sa, unsigned int length);
|
||||
|
||||
std::string m_path;
|
||||
int m_logFd{-1};
|
||||
SCgiTask m_task[max_tasks];
|
||||
|
||||
task_list m_tasks;
|
||||
task_list::iterator m_current;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+54
-45
@@ -2,14 +2,16 @@
|
||||
|
||||
#include "rpc/scgi_task.h"
|
||||
|
||||
#include <rak/error_number.h>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/net/fd.h>
|
||||
#include <torrent/net/poll.h>
|
||||
#include <torrent/runtime/socket_manager.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/utils/thread.h>
|
||||
|
||||
@@ -17,49 +19,62 @@
|
||||
#include "globals.h"
|
||||
#include "scgi.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
#include "utils/socket_fd.h"
|
||||
|
||||
namespace rpc {
|
||||
|
||||
void
|
||||
SCgiTask::open(SCgi* parent, int fd) {
|
||||
set_file_descriptor(fd);
|
||||
|
||||
m_buffer.reset(new char[default_buffer_size + 1]);
|
||||
|
||||
m_parent = parent;
|
||||
m_fileDesc = fd;
|
||||
m_buffer = new char[default_buffer_size + 1];
|
||||
m_buffer_size = default_buffer_size;
|
||||
m_position = m_buffer;
|
||||
m_body = NULL;
|
||||
m_position = m_buffer.get();
|
||||
m_body = nullptr;
|
||||
|
||||
torrent::this_thread::poll()->open(this);
|
||||
torrent::this_thread::poll()->insert_read(this);
|
||||
torrent::this_thread::poll()->insert_error(this);
|
||||
}
|
||||
|
||||
void
|
||||
SCgiTask::cancel_open() {
|
||||
if (!is_open())
|
||||
return;
|
||||
|
||||
torrent::this_thread::poll()->remove_and_close(this);
|
||||
|
||||
torrent::fd_close(file_descriptor());
|
||||
set_file_descriptor(-1);
|
||||
};
|
||||
|
||||
void
|
||||
SCgiTask::close() {
|
||||
if (!get_fd().is_valid())
|
||||
if (!is_open())
|
||||
return;
|
||||
|
||||
torrent::main_thread::thread()->cancel_callback_and_wait(this);
|
||||
torrent::utils::Thread::self()->cancel_callback(this);
|
||||
|
||||
torrent::this_thread::poll()->remove_and_close(this);
|
||||
torrent::runtime::socket_manager()->close_event_or_throw(this, [this]() {
|
||||
torrent::this_thread::poll()->remove_and_close(this);
|
||||
|
||||
get_fd().close();
|
||||
get_fd().clear();
|
||||
torrent::fd_close(file_descriptor());
|
||||
set_file_descriptor(-1);
|
||||
});
|
||||
|
||||
auto lock = std::lock_guard<std::mutex>(m_result_mutex);
|
||||
|
||||
delete[] m_buffer;
|
||||
m_buffer = NULL;
|
||||
m_buffer = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SCgiTask::event_read() {
|
||||
int bytes = ::recv(m_fileDesc, m_position, m_buffer_size - (m_position - m_buffer), 0);
|
||||
int bytes = ::recv(m_fileDesc, m_position, m_buffer_size - (m_position - m_buffer.get()), 0);
|
||||
|
||||
if (bytes <= 0) {
|
||||
if (bytes == 0 || !rak::error_number::current().is_blocked_momentary())
|
||||
if (bytes == 0 || !(errno == EAGAIN || errno == EINTR))
|
||||
close();
|
||||
|
||||
return;
|
||||
@@ -74,14 +89,14 @@ SCgiTask::event_read() {
|
||||
// receive all the data we need the first time.
|
||||
char* current;
|
||||
|
||||
int header_size = strtol(m_buffer, ¤t, 0);
|
||||
int header_size = strtol(m_buffer.get(), ¤t, 0);
|
||||
|
||||
if (current == m_position)
|
||||
return;
|
||||
|
||||
// If the request doesn't start with an integer or if it didn't
|
||||
// end in ':', then close the connection.
|
||||
if (current == m_buffer || *current != ':' || header_size < 17 || header_size > max_header_size)
|
||||
if (current == m_buffer.get() || *current != ':' || header_size < 17 || header_size > max_header_size)
|
||||
goto event_read_failed;
|
||||
|
||||
if (std::distance(++current, m_position) < header_size + 1)
|
||||
@@ -136,7 +151,7 @@ SCgiTask::event_read() {
|
||||
goto event_read_failed;
|
||||
|
||||
m_body = current + 1;
|
||||
header_size = std::distance(m_buffer, m_body);
|
||||
header_size = std::distance(m_buffer.get(), m_body);
|
||||
|
||||
if (!detect_content_type(content_type))
|
||||
goto event_read_failed;
|
||||
@@ -147,19 +162,19 @@ SCgiTask::event_read() {
|
||||
} else if ((unsigned int)content_length <= default_buffer_size) {
|
||||
m_buffer_size = content_length;
|
||||
|
||||
std::memmove(m_buffer, m_body, std::distance(m_body, m_position));
|
||||
m_position = m_buffer + std::distance(m_body, m_position);
|
||||
m_body = m_buffer;
|
||||
std::memmove(m_buffer.get(), m_body, std::distance(m_body, m_position));
|
||||
m_position = m_buffer.get() + std::distance(m_body, m_position);
|
||||
m_body = m_buffer.get();
|
||||
|
||||
} else {
|
||||
realloc_buffer((m_buffer_size = content_length) + 1, m_body, std::distance(m_body, m_position));
|
||||
|
||||
m_position = m_buffer + std::distance(m_body, m_position);
|
||||
m_body = m_buffer;
|
||||
m_position = m_buffer.get() + std::distance(m_body, m_position);
|
||||
m_body = m_buffer.get();
|
||||
}
|
||||
}
|
||||
|
||||
if ((unsigned int)std::distance(m_buffer, m_position) != m_buffer_size)
|
||||
if ((unsigned int)std::distance(m_buffer.get(), m_position) != m_buffer_size)
|
||||
return;
|
||||
|
||||
torrent::this_thread::poll()->remove_read(this);
|
||||
@@ -169,13 +184,13 @@ SCgiTask::event_read() {
|
||||
|
||||
// Clean up logging, this is just plain ugly...
|
||||
// write(m_logFd, "\n---\n", sizeof("\n---\n"));
|
||||
result = write(m_parent->log_fd(), m_buffer, m_buffer_size);
|
||||
result = write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n"));
|
||||
result = ::write(m_parent->log_fd(), m_buffer.get(), m_buffer_size);
|
||||
result = ::write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n"));
|
||||
}
|
||||
|
||||
lt_log_print_dump(torrent::LOG_RPC_DUMP, m_body, m_buffer_size - std::distance(m_buffer, m_body), "scgi", "RPC read.", 0);
|
||||
lt_log_print_dump(torrent::LOG_RPC_DUMP, m_body, m_buffer_size - std::distance(m_buffer.get(), m_body), "scgi", "RPC read.", 0);
|
||||
|
||||
receive_call(m_body, m_buffer_size - std::distance(m_buffer, m_body));
|
||||
receive_call(m_body, m_buffer_size - std::distance(m_buffer.get(), m_body));
|
||||
return;
|
||||
|
||||
event_read_failed:
|
||||
@@ -185,16 +200,10 @@ event_read_failed:
|
||||
|
||||
void
|
||||
SCgiTask::event_write() {
|
||||
// Apple and Solaris do not support MSG_NOSIGNAL,
|
||||
// so disable this fix until we find a better solution
|
||||
#if defined(__APPLE__) || defined(__sun__)
|
||||
int bytes = ::send(m_fileDesc, m_position, m_buffer_size, 0);
|
||||
#else
|
||||
int bytes = ::send(m_fileDesc, m_position, m_buffer_size, MSG_NOSIGNAL);
|
||||
#endif
|
||||
|
||||
if (bytes == -1) {
|
||||
if (!rak::error_number::current().is_blocked_momentary())
|
||||
if (!(errno == EAGAIN || errno == EINTR))
|
||||
close();
|
||||
|
||||
return;
|
||||
@@ -249,11 +258,11 @@ SCgiTask::detect_content_type(const std::string& content_type) {
|
||||
// If bufferSize is zero then memcpy won't do anything.
|
||||
void
|
||||
SCgiTask::realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize) {
|
||||
char* tmp = new char[size];
|
||||
auto tmp = new char[size];
|
||||
|
||||
std::memcpy(tmp, buffer, bufferSize);
|
||||
::free(m_buffer);
|
||||
m_buffer = tmp;
|
||||
|
||||
m_buffer.reset(tmp);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -265,7 +274,7 @@ SCgiTask::receive_call(const char* buffer, uint32_t length) {
|
||||
auto result_callback = [this, scgi_thread](const char* b, uint32_t l) {
|
||||
receive_write(b, l);
|
||||
|
||||
scgi_thread->callback_interrupt_pollling(this, [this]() {
|
||||
scgi_thread->callback_interrupt_polling(this, [this]() {
|
||||
// Only need to lock once here as a memory barrier.
|
||||
m_result_mutex.lock();
|
||||
m_result_mutex.unlock();
|
||||
@@ -278,7 +287,7 @@ SCgiTask::receive_call(const char* buffer, uint32_t length) {
|
||||
|
||||
switch (content_type()) {
|
||||
case rpc::SCgiTask::ContentType::JSON:
|
||||
torrent::main_thread::thread()->callback_interrupt_pollling(this, [buffer, length, result_callback]() {
|
||||
torrent::main_thread::thread()->callback_interrupt_polling(this, [buffer, length, result_callback]() {
|
||||
rpc.process(RpcManager::RPCType::JSON, buffer, length,
|
||||
[result_callback](const char* b, uint32_t l) {
|
||||
result_callback(b, l);
|
||||
@@ -288,7 +297,7 @@ SCgiTask::receive_call(const char* buffer, uint32_t length) {
|
||||
break;
|
||||
|
||||
case rpc::SCgiTask::ContentType::XML:
|
||||
torrent::main_thread::thread()->callback_interrupt_pollling(this, [buffer, length, result_callback]() {
|
||||
torrent::main_thread::thread()->callback_interrupt_polling(this, [buffer, length, result_callback]() {
|
||||
rpc.process(RpcManager::RPCType::XML, buffer, length,
|
||||
[result_callback](const char* b, uint32_t l) {
|
||||
result_callback(b, l);
|
||||
@@ -318,20 +327,20 @@ SCgiTask::receive_write(const char* buffer, uint32_t length) {
|
||||
: "Status: 200 OK\r\nContent-Type: text/xml\r\nContent-Length: %i\r\n\r\n";
|
||||
|
||||
// Who ever bothers to check the return value?
|
||||
int headerSize = snprintf(m_buffer, m_buffer_size, header, length);
|
||||
int headerSize = snprintf(m_buffer.get(), m_buffer_size, header, length);
|
||||
|
||||
m_position = m_buffer;
|
||||
m_position = m_buffer.get();
|
||||
m_buffer_size = length + headerSize;
|
||||
|
||||
std::memcpy(m_buffer + headerSize, buffer, length);
|
||||
std::memcpy(m_buffer.get() + headerSize, buffer, length);
|
||||
|
||||
if (m_parent->log_fd() >= 0) {
|
||||
[[maybe_unused]] int result;
|
||||
result = write(m_parent->log_fd(), m_buffer, m_buffer_size);
|
||||
result = write(m_parent->log_fd(), m_buffer.get(), m_buffer_size);
|
||||
result = write(m_parent->log_fd(), "\n---\n", sizeof("\n---\n"));
|
||||
}
|
||||
|
||||
lt_log_print_dump(torrent::LOG_RPC_DUMP, m_buffer, m_buffer_size, "scgi", "RPC write.", 0);
|
||||
lt_log_print_dump(torrent::LOG_RPC_DUMP, m_buffer.get(), m_buffer_size, "scgi", "RPC write.", 0);
|
||||
}
|
||||
|
||||
} // namespace rpc
|
||||
|
||||
+6
-10
@@ -5,10 +5,6 @@
|
||||
#include <mutex>
|
||||
#include <torrent/event.h>
|
||||
|
||||
namespace utils {
|
||||
class SocketFd;
|
||||
}
|
||||
|
||||
namespace rpc {
|
||||
|
||||
class SCgi;
|
||||
@@ -29,6 +25,8 @@ public:
|
||||
bool is_available() const { return m_fileDesc == -1; }
|
||||
|
||||
void open(SCgi* parent, int fd);
|
||||
void cancel_open();
|
||||
|
||||
void close();
|
||||
|
||||
ContentType content_type() const { return m_content_type; }
|
||||
@@ -37,8 +35,6 @@ public:
|
||||
void event_write() override;
|
||||
void event_error() override;
|
||||
|
||||
utils::SocketFd& get_fd() { return *reinterpret_cast<utils::SocketFd*>(&m_fileDesc); }
|
||||
|
||||
private:
|
||||
bool detect_content_type(const std::string& content_type);
|
||||
void realloc_buffer(uint32_t size, const char* buffer, uint32_t bufferSize);
|
||||
@@ -46,13 +42,13 @@ private:
|
||||
void receive_call(const char* buffer, uint32_t length);
|
||||
void receive_write(const char* buffer, uint32_t length);
|
||||
|
||||
SCgi* m_parent;
|
||||
SCgi* m_parent{};
|
||||
|
||||
std::mutex m_result_mutex;
|
||||
|
||||
char* m_buffer{nullptr};
|
||||
char* m_position{nullptr};
|
||||
char* m_body{nullptr};
|
||||
std::unique_ptr<char[]> m_buffer;
|
||||
char* m_position{};
|
||||
char* m_body{};
|
||||
|
||||
unsigned int m_buffer_size{0};
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "rpc/scgi.h"
|
||||
|
||||
namespace scgi {
|
||||
@@ -41,7 +41,7 @@ ThreadScgi::thread_scgi() {
|
||||
void
|
||||
ThreadScgi::cleanup_thread() {
|
||||
if (m_scgi != nullptr)
|
||||
m_scgi.load()->deactivate();
|
||||
m_scgi.load()->stop();
|
||||
}
|
||||
|
||||
rpc::SCgi*
|
||||
@@ -49,6 +49,8 @@ ThreadScgi::scgi() {
|
||||
return m_scgi;
|
||||
}
|
||||
|
||||
// TODO: Disable changing SCGI once set?
|
||||
|
||||
bool
|
||||
ThreadScgi::set_scgi(rpc::SCgi* scgi) {
|
||||
rpc::SCgi* expected = nullptr;
|
||||
@@ -59,7 +61,7 @@ ThreadScgi::set_scgi(rpc::SCgi* scgi) {
|
||||
change_rpc_log();
|
||||
|
||||
callback(nullptr, [this]() {
|
||||
if (m_scgi == NULL)
|
||||
if (m_scgi == nullptr)
|
||||
throw torrent::internal_error("Tried to start SCGI but object was not present.");
|
||||
|
||||
m_scgi.load()->activate();
|
||||
@@ -78,19 +80,20 @@ ThreadScgi::set_rpc_log(const std::string& filename) {
|
||||
|
||||
void
|
||||
ThreadScgi::change_rpc_log() {
|
||||
if (scgi() == NULL)
|
||||
if (scgi() == nullptr)
|
||||
return;
|
||||
|
||||
if (scgi()->log_fd() != -1) {
|
||||
::close(scgi()->log_fd());
|
||||
scgi()->set_log_fd(-1);
|
||||
|
||||
lt_log_print(torrent::LOG_NOTICE, "Closed RPC log.", 0);
|
||||
}
|
||||
|
||||
if (m_rpc_log_filename.empty())
|
||||
return;
|
||||
|
||||
scgi()->set_log_fd(open(rak::path_expand(m_rpc_log_filename).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644));
|
||||
scgi()->set_log_fd(open(expand_path(m_rpc_log_filename).c_str(), O_WRONLY | O_APPEND | O_CREAT, 0644));
|
||||
|
||||
if (scgi()->log_fd() == -1) {
|
||||
lt_log_print(torrent::LOG_NOTICE, "Could not open RPC log file '%s'.", m_rpc_log_filename.c_str());
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "session/session_manager.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/utils/log.h>
|
||||
|
||||
@@ -23,12 +24,14 @@ SessionManager::SessionManager(torrent::utils::Thread* thread)
|
||||
SessionManager::~SessionManager() = default;
|
||||
|
||||
void
|
||||
SessionManager::set_path(const std::string& path) {
|
||||
SessionManager::set_path(std::string path) {
|
||||
assert(torrent::this_thread::thread() == torrent::main_thread::thread());
|
||||
|
||||
if (m_freeze_info)
|
||||
throw torrent::input_error("Session path cannot be changed after startup.");
|
||||
|
||||
path = expand_path(path);
|
||||
|
||||
if (path.empty() || path.back() == '/')
|
||||
m_path = path;
|
||||
else
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
bool is_used() const;
|
||||
|
||||
std::string path() const;
|
||||
void set_path(const std::string& path);
|
||||
void set_path(std::string path);
|
||||
|
||||
bool use_fsyncdisk() const;
|
||||
void set_use_fsyncdisk(bool use_fsyncdisk);
|
||||
|
||||
+4
-37
@@ -1,44 +1,11 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <signal.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "rak/error_number.h"
|
||||
#include "signal_handler.h"
|
||||
|
||||
#ifdef __sun__
|
||||
@@ -80,7 +47,7 @@ SignalHandler::set_handler(unsigned int signum, slot_void slot) {
|
||||
sa.sa_handler = &SignalHandler::caught;
|
||||
|
||||
if (sigaction(signum, &sa, NULL) == -1)
|
||||
throw std::logic_error("Could not set sigaction: " + std::string(rak::error_number::current().c_str()));
|
||||
throw std::logic_error("Could not set sigaction: " + std::string(std::strerror(errno)));
|
||||
else
|
||||
m_handlers[signum] = slot;
|
||||
}
|
||||
@@ -97,7 +64,7 @@ SignalHandler::set_sigaction_handler(unsigned int signum, handler_slot slot) {
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
if (sigaction(signum, &sa, NULL) == -1)
|
||||
throw std::logic_error("Could not set sigaction: " + std::string(rak::error_number::current().c_str()));
|
||||
throw std::logic_error("Could not set sigaction: " + std::string(std::strerror(errno)));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+6
-40
@@ -1,48 +1,14 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include "utils/directory.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <dirent.h>
|
||||
#include <functional>
|
||||
#include <sys/stat.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "directory.h"
|
||||
#include "globals.h"
|
||||
|
||||
namespace utils {
|
||||
|
||||
@@ -52,7 +18,7 @@ Directory::is_valid() const {
|
||||
if (m_path.empty())
|
||||
return false;
|
||||
|
||||
DIR* d = opendir(rak::path_expand(m_path).c_str());
|
||||
DIR* d = opendir(expand_path(m_path).c_str());
|
||||
closedir(d);
|
||||
|
||||
return d;
|
||||
@@ -63,7 +29,7 @@ Directory::update(int flags) {
|
||||
if (m_path.empty())
|
||||
throw torrent::input_error("Directory::update() tried to open an empty path.");
|
||||
|
||||
DIR* d = opendir(rak::path_expand(m_path).c_str());
|
||||
DIR* d = opendir(expand_path(m_path).c_str());
|
||||
|
||||
if (d == NULL)
|
||||
return false;
|
||||
|
||||
@@ -1,55 +1,22 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <rak/file_stat.h>
|
||||
#include <rak/path.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include "utils/file_status_cache.h"
|
||||
|
||||
#include "file_status_cache.h"
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/utils/file_stat.h>
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
namespace utils {
|
||||
|
||||
bool
|
||||
FileStatusCache::insert(const std::string& path, int flags) {
|
||||
rak::file_stat fs;
|
||||
FileStatusCache::insert(const std::string& path) {
|
||||
torrent::utils::FileStat fs;
|
||||
|
||||
// Should we expand somewhere else? Problem is it adds a lot of junk
|
||||
// to the start of the paths added to the cache, causing more work
|
||||
// during search, etc.
|
||||
if (!fs.update(rak::path_expand(path)))
|
||||
if (!fs.update(expand_path(path)))
|
||||
return false;
|
||||
|
||||
std::pair<iterator, bool> result = base_type::insert(value_type(path, file_status()));
|
||||
@@ -71,10 +38,10 @@ FileStatusCache::prune() {
|
||||
iterator itr = begin();
|
||||
|
||||
while (itr != end()) {
|
||||
rak::file_stat fs;
|
||||
torrent::utils::FileStat fs;
|
||||
iterator tmp = itr++;
|
||||
|
||||
if (!fs.update(rak::path_expand(tmp->first)) || tmp->second.m_mtime != (uint32_t)fs.modified_time())
|
||||
if (!fs.update(expand_path(tmp->first)) || tmp->second.m_mtime != (uint32_t)fs.modified_time())
|
||||
base_type::erase(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,9 @@
|
||||
// rTorrent - BitTorrent client
|
||||
// Copyright (C) 2005-2011, Jari Sundell
|
||||
//
|
||||
// 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; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <sundell.software@gmail.com>
|
||||
|
||||
|
||||
#ifndef RTORRENT_UTILS_FILE_STATUS_CACHE_H
|
||||
#define RTORRENT_UTILS_FILE_STATUS_CACHE_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace utils {
|
||||
|
||||
@@ -65,11 +32,9 @@ public:
|
||||
|
||||
using base_type::erase;
|
||||
|
||||
// static int flag_
|
||||
|
||||
// Insert and return true if the entry does not exist or the new
|
||||
// file's mtime is more recent.
|
||||
bool insert(const std::string& path, int flags);
|
||||
bool insert(const std::string& path);
|
||||
|
||||
// Add a function for pruning a sorted list of paths.
|
||||
|
||||
|
||||
@@ -1,159 +0,0 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/net/socket_address.h>
|
||||
|
||||
#include "socket_fd.h"
|
||||
|
||||
namespace utils {
|
||||
|
||||
inline void
|
||||
SocketFd::check_valid() const {
|
||||
if (!is_valid())
|
||||
throw torrent::internal_error("SocketFd function called on an invalid fd.");
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::set_nonblock() {
|
||||
check_valid();
|
||||
|
||||
return fcntl(m_fd, F_SETFL, O_NONBLOCK) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::set_priority(priority_type p) {
|
||||
check_valid();
|
||||
int opt = p;
|
||||
|
||||
if (m_ipv6_socket)
|
||||
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) == 0;
|
||||
else
|
||||
return setsockopt(m_fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::set_reuse_address(bool state) {
|
||||
check_valid();
|
||||
int opt = state;
|
||||
|
||||
return setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::set_dont_route(bool state) {
|
||||
check_valid();
|
||||
int opt = state;
|
||||
|
||||
return setsockopt(m_fd, SOL_SOCKET, SO_DONTROUTE, &opt, sizeof(opt)) == 0;
|
||||
}
|
||||
|
||||
// bool
|
||||
// SocketFd::set_bind_to_device(const char* device) {
|
||||
// check_valid();
|
||||
// struct ifreq ifr;
|
||||
// strlcpy(ifr.ifr_name, device, IFNAMSIZ);
|
||||
|
||||
// return setsockopt(m_fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == 0;
|
||||
// }
|
||||
|
||||
bool
|
||||
SocketFd::set_send_buffer_size(uint32_t s) {
|
||||
check_valid();
|
||||
int opt = s;
|
||||
|
||||
return setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::set_receive_buffer_size(uint32_t s) {
|
||||
check_valid();
|
||||
int opt = s;
|
||||
|
||||
return setsockopt(m_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) == 0;
|
||||
}
|
||||
|
||||
int
|
||||
SocketFd::get_error() const {
|
||||
check_valid();
|
||||
|
||||
int err;
|
||||
socklen_t length = sizeof(err);
|
||||
|
||||
if (getsockopt(m_fd, SOL_SOCKET, SO_ERROR, &err, &length) == -1)
|
||||
throw torrent::internal_error("SocketFd::get_error() could not get error");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::open_stream() {
|
||||
m_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (m_fd == -1) {
|
||||
m_ipv6_socket = false;
|
||||
return (m_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1;
|
||||
}
|
||||
|
||||
m_ipv6_socket = true;
|
||||
|
||||
int zero = 0;
|
||||
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::open_datagram() {
|
||||
m_fd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
if (m_fd == -1) {
|
||||
m_ipv6_socket = false;
|
||||
return (m_fd = socket(AF_INET, SOCK_DGRAM, 0)) != -1;
|
||||
}
|
||||
m_ipv6_socket = true;
|
||||
|
||||
int zero = 0;
|
||||
return setsockopt(m_fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero)) != -1;
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::open_local() {
|
||||
return (m_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) != -1;
|
||||
}
|
||||
|
||||
void
|
||||
SocketFd::close() {
|
||||
if (::close(m_fd) && errno == EBADF)
|
||||
throw torrent::internal_error("SocketFd::close() called on an invalid file descriptor");
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::bind_sa(const sockaddr* sa, unsigned int length) {
|
||||
check_valid();
|
||||
|
||||
if (m_ipv6_socket && sa->sa_family == AF_INET) {
|
||||
if (length < sizeof(sockaddr_in))
|
||||
throw torrent::input_error("SocketFd::bind_sa: invalid sockaddr length for AF_INET");
|
||||
|
||||
auto mapped_sa = torrent::sin6_to_v4mapped_in(reinterpret_cast<const sockaddr_in*>(sa));
|
||||
return !::bind(m_fd, reinterpret_cast<const sockaddr*>(mapped_sa.get()), sizeof(sockaddr_in6));
|
||||
}
|
||||
|
||||
return !::bind(m_fd, sa, length);
|
||||
}
|
||||
|
||||
bool
|
||||
SocketFd::listen(int size) {
|
||||
check_valid();
|
||||
|
||||
return !::listen(m_fd, size);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
#ifndef RTORRENT_UTILS_SOCKET_FD_H
|
||||
#define RTORRENT_UTILS_SOCKET_FD_H
|
||||
|
||||
#include <cinttypes>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
namespace utils {
|
||||
|
||||
class SocketFd {
|
||||
public:
|
||||
typedef uint8_t priority_type;
|
||||
|
||||
SocketFd() : m_fd(-1) {}
|
||||
explicit SocketFd(int fd) : m_fd(fd) {}
|
||||
|
||||
bool is_valid() const { return m_fd >= 0; }
|
||||
|
||||
int get_fd() const { return m_fd; }
|
||||
void set_fd(int fd) { m_fd = fd; }
|
||||
|
||||
bool set_nonblock();
|
||||
bool set_reuse_address(bool state);
|
||||
bool set_dont_route(bool state);
|
||||
|
||||
bool set_bind_to_device(const char* device);
|
||||
|
||||
bool set_priority(priority_type p);
|
||||
|
||||
bool set_send_buffer_size(uint32_t s);
|
||||
bool set_receive_buffer_size(uint32_t s);
|
||||
|
||||
int get_error() const;
|
||||
|
||||
bool open_stream();
|
||||
bool open_datagram();
|
||||
bool open_local();
|
||||
void close();
|
||||
|
||||
void clear() { m_fd = -1; }
|
||||
|
||||
bool bind_sa(const sockaddr* sa, unsigned int length);
|
||||
|
||||
bool listen(int size);
|
||||
|
||||
private:
|
||||
inline void check_valid() const;
|
||||
|
||||
int m_fd;
|
||||
bool m_ipv6_socket;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user