mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-05 17:52:29 +00:00
* Added a default low_diskspace check for 500MB.
* Properly catch the exceptions being thrown by the 'in_*' events. * Expand ~ in ExecFile. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@950 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
||||
AC_INIT(rtorrent, 0.7.6, jaris@ifi.uio.no)
|
||||
AC_INIT(rtorrent, 0.7.7, jaris@ifi.uio.no)
|
||||
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
+15
@@ -58,6 +58,21 @@ path_expand(const std::string& path) {
|
||||
return home + path.substr(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));
|
||||
src++;
|
||||
}
|
||||
|
||||
return first + strlcpy(first, src, std::distance(first, last));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -62,18 +62,18 @@ torrent::Object
|
||||
apply_on_state_change(core::DownloadList::slot_map* slotMap, const torrent::Object& rawArgs) {
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
|
||||
if (args.size() < 2)
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
if (args.size() == 0 || args.size() > 2)
|
||||
throw torrent::input_error("Wrong number of arguments.");
|
||||
|
||||
if (args.front().as_string().empty())
|
||||
throw torrent::input_error("Empty key.");
|
||||
|
||||
std::string key = "1_state_" + args.front().as_string();
|
||||
|
||||
if (args.back().as_string().empty())
|
||||
if (args.size() == 1)
|
||||
slotMap->erase(key);
|
||||
else
|
||||
(*slotMap)[key] = sigc::bind(sigc::ptr_fun(&rpc::parse_command_d_multiple_std), rpc::convert_list_to_command(++args.begin(), args.end()));
|
||||
(*slotMap)[key] = sigc::bind(sigc::ptr_fun(&rpc::parse_command_d_multiple_std), args.back().as_string());
|
||||
|
||||
return torrent::Object();
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ initialize_command_local() {
|
||||
core::DownloadList* dList = control->core()->download_list();
|
||||
core::DownloadStore* dStore = control->core()->download_store();
|
||||
|
||||
ADD_VARIABLE_C_STRING("client_version", PACKAGE_VERSION);
|
||||
ADD_VARIABLE_C_STRING("client_version", PACKAGE_VERSION);
|
||||
ADD_VARIABLE_C_STRING("library_version", torrent::version());
|
||||
|
||||
ADD_VARIABLE_VALUE("max_file_size", -1);
|
||||
@@ -83,5 +83,5 @@ initialize_command_local() {
|
||||
ADD_COMMAND_VALUE_TRI_OCT("umask", rak::make_mem_fun(control, &Control::set_umask), rak::make_mem_fun(control, &Control::umask));
|
||||
ADD_COMMAND_STRING_TRI("working_directory", rak::make_mem_fun(control, &Control::set_working_directory), rak::make_mem_fun(control, &Control::working_directory));
|
||||
|
||||
ADD_COMMAND_LIST("execute", rak::mem_fn(&rpc::execFile, &rpc::ExecFile::execute_object));
|
||||
ADD_COMMAND_LIST("execute", rak::bind2_mem_fn(&rpc::execFile, &rpc::ExecFile::execute_object, rpc::ExecFile::flag_throw | rpc::ExecFile::flag_expand_tilde));
|
||||
}
|
||||
|
||||
@@ -73,7 +73,11 @@ struct download_list_call {
|
||||
download_list_call(Download* d) : m_download(d) {}
|
||||
|
||||
void operator () (const DownloadList::slot_map::value_type& s) {
|
||||
s.second(m_download);
|
||||
try {
|
||||
s.second(m_download);
|
||||
} catch (torrent::input_error& e) {
|
||||
control->core()->push_log((std::string("Download event action failed: ") + e.what()).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Download* m_download;
|
||||
@@ -561,6 +565,9 @@ DownloadList::confirm_finished(Download* download) {
|
||||
// up/downloaded baseline.
|
||||
download->download()->tracker_list().send_completed();
|
||||
|
||||
// Close before calling on_finished to ensure the user can do stuff
|
||||
// like change move the downloaded files and change the directory.
|
||||
close_throw(download);
|
||||
std::for_each(slot_map_finished().begin(), slot_map_finished().end(), download_list_call(download));
|
||||
|
||||
if (!download->is_active() && rpc::call_command_d_value("get_d_state", download) == 1)
|
||||
|
||||
@@ -220,6 +220,7 @@ main(int argc, char** argv) {
|
||||
|
||||
//"schedule = scheduler,10,10,download_scheduler=\n"
|
||||
"schedule = session_save,1800,1800,session_save=\n"
|
||||
"schedule = low_diskspace,5,60,close_low_diskspace=500M\n"
|
||||
|
||||
// Changing these will bork the (non-existant) scheduler.
|
||||
"view_add = scheduler\n"
|
||||
|
||||
+23
-11
@@ -37,6 +37,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <rak/path.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
@@ -73,12 +74,12 @@ ExecFile::execute(const char* file, char* const* argv) {
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
ExecFile::execute_object(const torrent::Object& rawArgs) {
|
||||
char* argsBuffer[128];
|
||||
ExecFile::execute_object(const torrent::Object& rawArgs, int flags) {
|
||||
char* argsBuffer[max_args];
|
||||
char** argsCurrent = argsBuffer;
|
||||
|
||||
// Size of strings are less than 24.
|
||||
char valueBuffer[3072];
|
||||
// Size of value strings are less than 24.
|
||||
char valueBuffer[buffer_size];
|
||||
char* valueCurrent = valueBuffer;
|
||||
|
||||
const torrent::Object::list_type& args = rawArgs.as_list();
|
||||
@@ -87,18 +88,27 @@ ExecFile::execute_object(const torrent::Object& rawArgs) {
|
||||
throw torrent::input_error("Too few arguments.");
|
||||
|
||||
for (torrent::Object::list_type::const_iterator itr = args.begin(), last = args.end(); itr != last; itr++, argsCurrent++) {
|
||||
if (argsCurrent == argsBuffer + 128 - 1)
|
||||
if (argsCurrent == argsBuffer + max_args - 1)
|
||||
throw torrent::input_error("Too many arguments.");
|
||||
|
||||
switch (itr->type()) {
|
||||
case torrent::Object::TYPE_STRING:
|
||||
*argsCurrent = const_cast<char*>(itr->as_string().c_str());
|
||||
break;
|
||||
{
|
||||
const std::string& str = itr->as_string();
|
||||
|
||||
if ((flags & flag_expand_tilde) && *str.c_str() == '~') {
|
||||
*argsCurrent = valueCurrent;
|
||||
valueCurrent = rak::path_expand(str.c_str(), valueCurrent, valueBuffer + buffer_size) + 1;
|
||||
} else {
|
||||
*argsCurrent = const_cast<char*>(str.c_str());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case torrent::Object::TYPE_VALUE:
|
||||
*argsCurrent = valueCurrent;
|
||||
|
||||
valueCurrent += std::max(snprintf(valueCurrent, valueBuffer + 3072 - valueCurrent, "%lli", itr->as_value()), 0);
|
||||
valueCurrent += snprintf(valueCurrent, valueBuffer + buffer_size - valueCurrent, "%lli", itr->as_value()) + 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -108,12 +118,14 @@ ExecFile::execute_object(const torrent::Object& rawArgs) {
|
||||
|
||||
*argsCurrent = NULL;
|
||||
|
||||
// Check if we overflowed the valueBuffer.
|
||||
|
||||
int status = execute(argsBuffer[0], argsBuffer);
|
||||
|
||||
if (status != 0)
|
||||
throw torrent::input_error("ExecFile::execute_object(...) status != 0.");
|
||||
if ((flags & flag_throw) && status != 0)
|
||||
throw torrent::input_error("Bad return code.");
|
||||
|
||||
return torrent::Object();
|
||||
return torrent::Object((int64_t)status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+7
-2
@@ -43,10 +43,15 @@ namespace rpc {
|
||||
|
||||
class ExecFile {
|
||||
public:
|
||||
|
||||
static const unsigned int max_args = 128;
|
||||
static const unsigned int buffer_size = 4096;
|
||||
|
||||
static const int flag_throw = 0x1;
|
||||
static const int flag_expand_tilde = 0x2;
|
||||
|
||||
int execute(const char* file, char* const* argv);
|
||||
|
||||
torrent::Object execute_object(const torrent::Object& rawArgs);
|
||||
torrent::Object execute_object(const torrent::Object& rawArgs, int flags);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ SocketFd::set_dont_route(bool state) {
|
||||
// SocketFd::set_bind_to_device(const char* device) {
|
||||
// check_valid();
|
||||
// struct ifreq ifr;
|
||||
// strncpy(ifr.ifr_name, device, IFNAMSIZ);
|
||||
// strlcpy(ifr.ifr_name, device, IFNAMSIZ);
|
||||
|
||||
// return setsockopt(m_fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == 0;
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user