Compare commits

...

13 Commits

Author SHA1 Message Date
rakshasa 7ead88448b Removed rak/error_number.h from Makefile.am. 2026-03-04 11:39:25 +01:00
rakshasa 650f0299b5 Tagged release 0.16.7. 2026-03-04 10:47:30 +01:00
rakshasa 5dfb2ae938 Allow dht bootstrap nodes to be added when dht is off. 2026-03-02 09:45:09 +01:00
Jorge Israel Peña f05a2ae520 Re-send smkx on SIGWINCH to fix arrow keys after terminal reattach 2026-02-19 16:06:42 +01:00
Miroslav Marchev ecefdba734 dht_add_peer_node is empty, use dht_add_bootstrap_node instead
After a refactor dht_add_peer_node became empty function. Replace with dht_add_bootstrap_node to make adding bootstrap nodes work.
2026-02-14 14:32:48 +01:00
Jari Sundell 87666199b3 Added SocketManager to handle reuse of uninterested fd's by the kernel. 2026-01-29 04:00:31 +09:00
Jari Sundell 9489793dcb Created torrent/runtime include directory. 2026-01-27 08:21:05 +09:00
Jari Sundell 2fa7568165 Remove obsolete SocketFd class. 2026-01-26 19:13:03 +09:00
fffe f4b718f685 add separate commands for unbuffered logs 2026-01-16 16:10:02 +01:00
Jari Sundell b233e24465 Deprecated rak::path_expand. 2026-01-08 23:27:53 +09:00
Jari Sundell 289ab046bf Expand '~/' to $HOME in session path. 2026-01-06 20:44:40 +09:00
Jari Sundell a8b6a47054 Removed deprecated rak errno and file headers. 2026-01-04 03:22:02 +09:00
Zoltan Celedes 110591d5c1 Fix key/value pairs in Lua
Previously, the keys and values were swapped in d.custom.items()
2026-01-03 12:20:08 +01:00
42 changed files with 327 additions and 1026 deletions
-3
View File
@@ -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
View File
@@ -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.7],[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.7])
AC_LANG_PUSH(C++)
TORRENT_WITH_XMLRPC_C
-85
View File
@@ -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
-75
View File
@@ -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
View File
@@ -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
-2
View File
@@ -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 \
+7 -8
View File
@@ -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
View File
@@ -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,
-36
View File
@@ -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
View File
@@ -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);
+3 -4
View File
@@ -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
View File
@@ -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));
+3 -6
View File
@@ -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");
+2 -5
View File
@@ -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
View File
@@ -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"
+1 -1
View File
@@ -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
View File
@@ -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);
}
+3 -4
View File
@@ -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
View File
@@ -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.
+1
View File
@@ -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();
+1 -3
View File
@@ -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();
+22
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
-1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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;
+91 -58
View File
@@ -1,6 +1,7 @@
#include "config.h"
#include <cassert>
#include <unistd.h>
#include <sys/un.h>
#include <torrent/connection_manager.h>
#include <torrent/torrent.h>
@@ -8,11 +9,11 @@
#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"
@@ -20,30 +21,29 @@
namespace rpc {
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 +51,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 +98,67 @@ 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 (SCgiTask* itr = m_task, *last = m_task + max_tasks; itr != last; ++itr)
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() {
while (true) {
int fd = torrent::fd_accept(get_fd().get_fd());
if (fd == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
break;
throw torrent::resource_error("Listener port accept() failed: " + std::string(std::strerror(errno)));
}
SCgiTask* task = std::find_if(m_task, m_task + max_tasks, std::mem_fn(&SCgiTask::is_available));
auto* task = std::find_if(m_task, m_task + max_tasks, std::mem_fn(&SCgiTask::is_available));
if (task == m_task + max_tasks) {
torrent::fd_close(fd);
// 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);
continue;
}
task->open(this, fd);
auto open_func = [this, task]() {
int fd = torrent::fd_accept(file_descriptor());
if (fd == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
return;
throw torrent::resource_error("Listener port accept() failed: " + std::string(std::strerror(errno)));
}
task->open(this, fd);
};
auto cleanup_func = [task]() {
task->cancel_open();
};
bool result = torrent::runtime::socket_manager()->open_event_or_cleanup(task, open_func, cleanup_func);
if (!result)
break;
}
}
+4 -10
View File
@@ -5,11 +5,6 @@
#include <torrent/event.h>
#include "rpc/scgi_task.h"
#include "utils/socket_fd.h"
namespace utils {
class SocketFd;
}
namespace rpc {
@@ -21,11 +16,12 @@ public:
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,10 +32,8 @@ 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);
void open(sockaddr* sa, unsigned int length);
std::string m_path;
int m_logFd{-1};
+56 -45
View File
@@ -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,64 @@
#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::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);
});
};
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 +91,14 @@ SCgiTask::event_read() {
// receive all the data we need the first time.
char* current;
int header_size = strtol(m_buffer, &current, 0);
int header_size = strtol(m_buffer.get(), &current, 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 +153,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 +164,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 +186,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 +202,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 +260,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 +276,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 +289,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 +299,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 +329,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
View File
@@ -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};
+8 -5
View File
@@ -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());
+4 -1
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+10 -43
View File
@@ -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);
}
}
+2 -37
View File
@@ -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.
-159
View File
@@ -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);
}
}
-55
View File
@@ -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