diff --git a/doc/rtorrent.1.xml b/doc/rtorrent.1.xml
index f8bf8439..3ec568d9 100644
--- a/doc/rtorrent.1.xml
+++ b/doc/rtorrent.1.xml
@@ -130,21 +130,32 @@ Change view.
- ^s
+ ^S
Start download.
- ^d
+ ^D
- Stop an active download, or remove a stopped download.
+
+Stop an active download, or remove a stopped download.
+
- ^r
+ ^K
+
+
+Close a torrent and its files.
+
+
+
+
+
+ ^R
Initiate hash check of torrent.
@@ -553,11 +564,13 @@ Delete id from the scheduler.
stop_untied =
+ close_untied =
remove_untied =
-Stop or remove the torrents that are tied to filenames that have been
-deleted, the association is then cleared.
+Stop, close or remove the torrents that are tied to filenames that
+have been deleted, the association with the file is then cleared so
+the event will not trigger more than once.
diff --git a/rak/error_number.h b/rak/error_number.h
index 64fbfbb5..2eef3193 100644
--- a/rak/error_number.h
+++ b/rak/error_number.h
@@ -49,6 +49,10 @@ public:
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_notdir = ENOTDIR;
+
static const int e_intr = EINTR;
error_number() : m_errno(0) {}
@@ -64,6 +68,8 @@ public:
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; }
diff --git a/src/core/download_store.cc b/src/core/download_store.cc
index 95c9532f..904d85ea 100644
--- a/src/core/download_store.cc
+++ b/src/core/download_store.cc
@@ -41,6 +41,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -68,7 +69,10 @@ DownloadStore::enable(bool lock) {
m_lockfile.set_path(std::string());
if (!m_lockfile.try_lock())
- throw torrent::input_error("Could not lock session directory: \"" + m_path + "\", held by \"" + m_lockfile.locked_by_as_string() + "\".");
+ if (rak::error_number::current().is_bad_path())
+ throw torrent::input_error("Could not lock session directory: \"" + m_path + "\", " + rak::error_number::current().c_str());
+ else
+ throw torrent::input_error("Could not lock session directory: \"" + m_path + "\", held by \"" + m_lockfile.locked_by_as_string() + "\".");
}
void
diff --git a/src/core/view_manager.cc b/src/core/view_manager.cc
index 36f43f87..1a223dfd 100644
--- a/src/core/view_manager.cc
+++ b/src/core/view_manager.cc
@@ -146,7 +146,7 @@ ViewManager::ViewManager(DownloadList* dl) :
m_filter["started"] = new ViewFilterVariableValue("state", 1);
m_filter["stopped"] = new ViewFilterVariableValue("state", 0);
- m_filter["complete"] = new ViewFilterVariableValue("complete", 0, false);
+ m_filter["complete"] = new ViewFilterVariableValue("complete", 0, true);
m_filter["incomplete"] = new ViewFilterVariableValue("complete", 0);
m_filter["hashing"] = new ViewFilterVariableValue("hashing", 0, true);
}
diff --git a/src/option_handler_rules.cc b/src/option_handler_rules.cc
index 8256f79f..c71ef13a 100644
--- a/src/option_handler_rules.cc
+++ b/src/option_handler_rules.cc
@@ -116,6 +116,25 @@ apply_stop_untied(Control* m) {
}
}
+void
+apply_close_untied(Control* m) {
+ core::Manager::DListItr itr = m->core()->download_list()->begin();
+
+ while ((itr = std::find_if(itr, m->core()->download_list()->end(),
+ rak::on(rak::bind2nd(std::mem_fun(&core::Download::variable_string), "tied_to_file"),
+ std::not1(std::mem_fun_ref(&std::string::empty)))))
+ != m->core()->download_list()->end()) {
+ rak::file_stat fs;
+
+ if (!fs.update(rak::path_expand((*itr)->variable_string("tied_to_file")))) {
+ (*itr)->variable()->set("tied_to_file", std::string());
+ m->core()->download_list()->close(*itr);
+ }
+
+ ++itr;
+ }
+}
+
void
apply_remove_untied(Control* m) {
core::Manager::DListItr itr = m->core()->download_list()->begin();
@@ -386,6 +405,7 @@ initialize_option_handler(Control* c) {
variables->insert("load", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_load, c)));
variables->insert("load_start", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_load_start, c)));
variables->insert("stop_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_stop_untied, c)));
+ variables->insert("close_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_close_untied, c)));
variables->insert("remove_untied", new utils::VariableVoidSlot(rak::bind_ptr_fn(&apply_remove_untied, c)));
variables->insert("enable_trackers", new utils::VariableStringSlot(rak::value_fn(std::string()), rak::bind_ptr_fn(&apply_enable_trackers, c)));