mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-22 00:56:18 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 83c32cea55 | |||
| ffaae64d83 |
@@ -64,8 +64,6 @@ jobs:
|
||||
repository: ${{ env.PR_HEAD_REPO }}
|
||||
ref: ${{ env.PR_HEAD_SHA }}
|
||||
persist-credentials: false
|
||||
# Only read by the comment action, never built or run.
|
||||
allow-unsafe-pr-checkout: true
|
||||
- name: Redownload analysis results
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
|
||||
@@ -16,7 +16,6 @@ jobs:
|
||||
sudo apt-get install -y \
|
||||
bear \
|
||||
clang-tidy \
|
||||
libcppunit-dev \
|
||||
libcurl4-openssl-dev \
|
||||
zlib1g-dev
|
||||
- name: Fetch libtorrent
|
||||
@@ -50,19 +49,16 @@ jobs:
|
||||
autoconf -i
|
||||
autoheader
|
||||
automake --add-missing
|
||||
mkdir build
|
||||
cd build
|
||||
"${GITHUB_WORKSPACE}/configure"
|
||||
./configure
|
||||
- name: Prepare compile_commands.json
|
||||
run: |
|
||||
cd build
|
||||
bear -- make check TESTS=
|
||||
bear -- make
|
||||
- name: Create results directory
|
||||
run: |
|
||||
mkdir clang-tidy-result
|
||||
- name: Analyze
|
||||
run: |
|
||||
git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml "-extra-arg=-include/${PWD}/build/config.h"
|
||||
git diff -U0 "$(git merge-base HEAD "upstream/${{ github.event.pull_request.base.ref }}")" | clang-tidy-diff -p1 -path build -export-fixes clang-tidy-result/fixes.yml "-extra-arg=-include/${PWD}/config.h"
|
||||
- name: Save PR metadata
|
||||
run: |
|
||||
echo "${{ github.event.number }}" > clang-tidy-result/pr-id.txt
|
||||
|
||||
+5
-5
@@ -52,11 +52,11 @@
|
||||
# watch directory.
|
||||
#
|
||||
#directory.watch.ready = ./watch, load.start
|
||||
#schedule = watch_directory,5,5,load.start=./watch/*.torrent
|
||||
#schedule2 = watch_directory,5,5,load.start=./watch/*.torrent
|
||||
|
||||
# Close torrents when disk-space is low.
|
||||
#
|
||||
#schedule = low_diskspace,5,60,close_low_diskspace=100M
|
||||
#schedule2 = low_diskspace,5,60,close_low_diskspace=100M
|
||||
|
||||
# The IP address reported to the tracker.
|
||||
#
|
||||
@@ -100,8 +100,8 @@
|
||||
|
||||
# Alternative calls to bind and IP that should handle dynamic IP's.
|
||||
#
|
||||
#schedule = ip_tick,0,1800,ip=rakshasa
|
||||
#schedule = bind_tick,0,1800,bind=rakshasa
|
||||
#schedule2 = ip_tick,0,1800,ip=rakshasa
|
||||
#schedule2 = bind_tick,0,1800,bind=rakshasa
|
||||
|
||||
# Encryption options, set to none (default) or any combination of the following:
|
||||
# allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
|
||||
@@ -145,4 +145,4 @@
|
||||
#
|
||||
#network.scgi.open_port = "127.0.0.1:5000"
|
||||
#network.scgi.open_local = (cat,(session.path),/rpc.sock)
|
||||
#schedule = socket_chmod, 0, 0, "execute.nothrow=chmod,770,(cat,(session.path),/rpc.sock)"
|
||||
#schedule2 = socket_chmod, 0, 0, "execute.nothrow=chmod,770,(cat,(session.path),/rpc.sock)"
|
||||
|
||||
+9
-15
@@ -30,6 +30,7 @@ network.listen.port.random.set = no
|
||||
# (conservative settings for 'private' trackers, change for 'public')
|
||||
dht.mode.set = disable
|
||||
protocol.pex.set = no
|
||||
trackers.use_udp.set = no
|
||||
|
||||
# Peer settings
|
||||
throttle.max_uploads.set = 100
|
||||
@@ -41,22 +42,14 @@ throttle.min_peers.seed.set = 30
|
||||
throttle.max_peers.seed.set = 80
|
||||
trackers.numwant.set = 80
|
||||
|
||||
# Select encryption for handshake and connection:
|
||||
#
|
||||
# protocol.encryption.set = {deny,allow,prefer,require}
|
||||
# protocol.encryption.set = handshake_{deny,allow,prefer,require}, stream_{deny,allow,prefer,require}
|
||||
#
|
||||
#protocol.encryption.set = deny
|
||||
#protocol.encryption.set = require
|
||||
#protocol.encryption.set = handshake_prefer, stream_deny
|
||||
#protocol.encryption.set = handshake_require, stream_prefer
|
||||
protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
|
||||
|
||||
# Limits for file handle resources, this is optimized for
|
||||
# an `ulimit` of 1024 (a common default). You MUST leave
|
||||
# a ceiling of handles reserved for rTorrent's internal needs!
|
||||
|
||||
# Deprecated, see: https://github.com/rakshasa/rtorrent/wiki/Socket-Manager-and-Resource-Allocation
|
||||
|
||||
network.http.max_open.set = 50
|
||||
network.max_open_files.set = 600
|
||||
network.max_open_sockets.set = 300
|
||||
|
||||
# Memory resource usage (increase if you have a large number of items loaded,
|
||||
# and/or the available resources to spend)
|
||||
@@ -72,10 +65,11 @@ execute.nothrow = sh, -c, (cat, "echo >",\
|
||||
(session.path), "rtorrent.pid", " ", (system.pid))
|
||||
|
||||
# Other operational settings (check & adapt)
|
||||
encoding.add = utf8
|
||||
system.umask.set = 0027
|
||||
system.cwd.set = (directory.default)
|
||||
network.http.dns_cache_timeout.set = 25
|
||||
schedule = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
|
||||
schedule2 = monitor_diskspace, 15, 60, ((close_low_diskspace, 1000M))
|
||||
##pieces.hash.on_completion.set = no
|
||||
##view.sort_current = seeding, greater=d.ratio=
|
||||
##keys.layout.set = qwerty
|
||||
@@ -94,8 +88,8 @@ method.insert = d.data_path, simple,\
|
||||
method.insert = d.session_file, simple, "cat=(session.path), (d.hash), .torrent"
|
||||
|
||||
# Watch directories (add more as you like, but use unique schedule names)
|
||||
schedule = watch_start, 10, 10, ((load.start_verbose, (cat, (cfg.watch), "start/*.torrent")))
|
||||
schedule = watch_load, 11, 10, ((load.verbose, (cat, (cfg.watch), "load/*.torrent")))
|
||||
schedule2 = watch_start, 10, 10, ((load.start_verbose, (cat, (cfg.watch), "start/*.torrent")))
|
||||
schedule2 = watch_load, 11, 10, ((load.verbose, (cat, (cfg.watch), "load/*.torrent")))
|
||||
|
||||
# Run the rTorrent process as a daemon in the background
|
||||
# (and control via XMLRPC sockets)
|
||||
|
||||
@@ -60,6 +60,7 @@ rc.network.listen.port.random = false
|
||||
-- (conservative settings for 'private' trackers, change for 'public')
|
||||
rc.dht.mode = 'disable'
|
||||
rc.protocol.pex = false
|
||||
rc.trackers.use_udp = false
|
||||
|
||||
-- Peer settings
|
||||
rc.throttle.max_uploads = 100
|
||||
@@ -71,11 +72,14 @@ rc.throttle.min_peers.seed = 30
|
||||
rc.throttle.max_peers.seed = 80
|
||||
rc.trackers.numwant = 80
|
||||
|
||||
rc.protocol.encryption.set('allow_incoming', 'try_outgoing', 'enable_retry')
|
||||
|
||||
-- Limits for file handle resources, this is optimized for
|
||||
-- an `ulimit` of 1024 (a common default). You MUST leave
|
||||
-- a ceiling of handles reserved for rTorrent's internal needs!
|
||||
|
||||
-- Deprecated, see: https://github.com/rakshasa/rtorrent/wiki/Socket-Manager-and-Resource-Allocation
|
||||
rc.network.http.max_open = 50
|
||||
rc.network.max_open_files = 600
|
||||
rc.network.max_open_sockets = 300
|
||||
|
||||
-- Memory resource usage (increase if you have a large number of items loaded,
|
||||
-- and/or the available resources to spend)
|
||||
@@ -93,10 +97,11 @@ rc.execute.nothrow(
|
||||
}))
|
||||
|
||||
-- Other operational settings (check & adapt)
|
||||
rc.encoding.add('utf8')
|
||||
rc.system.umask = 0027
|
||||
rc.system.cwd = rc.directory.default()
|
||||
rc.network.http.dns_cache_timeout = 25
|
||||
rc.schedule('monitor_diskspace', '15', '60', 'close_low_diskspace=1000M')
|
||||
rc.schedule2('monitor_diskspace', '15', '60', 'close_low_diskspace=1000M')
|
||||
--rc.pieces.hash.on_completion = false
|
||||
--rc.view.sort_current('seeding', 'greater=d.ratio=')
|
||||
--rc.keys.layout = 'qwerty'
|
||||
@@ -116,8 +121,8 @@ rc.method.insert('d.data_path', 'simple',
|
||||
rc.method.insert('d.session_file', 'simple', 'cat=(session.path), (d.hash), .torrent')
|
||||
|
||||
-- Watch directories (add more as you like, but use unique schedule names)
|
||||
rc.schedule('watch_start', '10', '10', 'load.start_verbose=(cat, (cfg.watch), "start/*.torrent")')
|
||||
rc.schedule('watch_load', '11', '10', 'load.verbose=(cat, (cfg.watch), "load/*.torrent")')
|
||||
rc.schedule2('watch_start', '10', '10', 'load.start_verbose=(cat, (cfg.watch), "start/*.torrent")')
|
||||
rc.schedule2('watch_load', '11', '10', 'load.verbose=(cat, (cfg.watch), "load/*.torrent")')
|
||||
|
||||
-- Run the rTorrent process as a daemon in the background
|
||||
-- (and control via XMLRPC sockets)
|
||||
|
||||
@@ -668,8 +668,8 @@ initialize_command_download() {
|
||||
CMD2_DL("d.base_path.base64", [](auto* download, auto) { return retrieve_d_base_path(download).object_base64(); });
|
||||
CMD2_DL("d.base_path.base64_as_binary", [](auto* download, auto) { return retrieve_d_base_path(download).object_base64_as_binary(); });
|
||||
CMD2_DL("d.base_path.as_binary", [](auto* download, auto) { return retrieve_d_base_path(download).object_as_binary(); });
|
||||
CMD2_DL("d.base_path.or_base64", [](auto* download, auto) { return retrieve_d_base_path(download).object_utf8_text_or_base64(); });
|
||||
CMD2_DL("d.base_path.or_as_binary", [](auto* download, auto) { return retrieve_d_base_path(download).object_utf8_text_or_as_binary(); });
|
||||
CMD2_DL("d.base_path.or_base64", [](auto* download, auto) { return retrieve_d_base_path(download).object_utf8_or_base64(); });
|
||||
CMD2_DL("d.base_path.or_as_binary", [](auto* download, auto) { return retrieve_d_base_path(download).object_utf8_or_as_binary(); });
|
||||
CMD2_DL("d.base_path.realpath.or_empty", [](auto* download, auto) { return resolve_path(retrieve_d_base_path(download).str()); });
|
||||
CMD2_DL("d.base_path.realpath.or_throw", [](auto* download, auto) { return resolve_path_or_throw(retrieve_d_base_path(download).str()); });
|
||||
CMD2_DL("d.base_filename", [](auto* download, auto) { return retrieve_d_base_filename(download).str(); });
|
||||
@@ -677,16 +677,16 @@ initialize_command_download() {
|
||||
CMD2_DL("d.base_filename.base64", [](auto* download, auto) { return retrieve_d_base_filename(download).object_base64(); });
|
||||
CMD2_DL("d.base_filename.base64_as_binary", [](auto* download, auto) { return retrieve_d_base_filename(download).object_base64_as_binary(); });
|
||||
CMD2_DL("d.base_filename.as_binary", [](auto* download, auto) { return retrieve_d_base_filename(download).object_as_binary(); });
|
||||
CMD2_DL("d.base_filename.or_base64", [](auto* download, auto) { return retrieve_d_base_filename(download).object_utf8_text_or_base64(); });
|
||||
CMD2_DL("d.base_filename.or_as_binary", [](auto* download, auto) { return retrieve_d_base_filename(download).object_utf8_text_or_as_binary(); });
|
||||
CMD2_DL("d.base_filename.or_base64", [](auto* download, auto) { return retrieve_d_base_filename(download).object_utf8_or_base64(); });
|
||||
CMD2_DL("d.base_filename.or_as_binary", [](auto* download, auto) { return retrieve_d_base_filename(download).object_utf8_or_as_binary(); });
|
||||
|
||||
CMD2_DL("d.name", [](auto* download, auto) { return download->info()->name().str(); });
|
||||
CMD2_DL("d.name.hex", [](auto* download, auto) { return download->info()->name().object_hex(); });
|
||||
CMD2_DL("d.name.base64", [](auto* download, auto) { return download->info()->name().object_base64(); });
|
||||
CMD2_DL("d.name.base64_as_binary", [](auto* download, auto) { return download->info()->name().object_base64_as_binary(); });
|
||||
CMD2_DL("d.name.as_binary", [](auto* download, auto) { return download->info()->name().object_as_binary(); });
|
||||
CMD2_DL("d.name.or_base64", [](auto* download, auto) { return download->info()->name().object_utf8_text_or_base64(); });
|
||||
CMD2_DL("d.name.or_as_binary", [](auto* download, auto) { return download->info()->name().object_utf8_text_or_as_binary(); });
|
||||
CMD2_DL("d.name.or_base64", [](auto* download, auto) { return download->info()->name().object_utf8_or_base64(); });
|
||||
CMD2_DL("d.name.or_as_binary", [](auto* download, auto) { return download->info()->name().object_utf8_or_as_binary(); });
|
||||
CMD2_DL("d.creation_date", [](auto* download, auto) { return download->info()->creation_date(); });
|
||||
CMD2_DL("d.load_date", [](auto* download, auto) { return download->info()->load_date(); });
|
||||
|
||||
|
||||
+9
-9
@@ -40,13 +40,13 @@ apply_f_path_components(torrent::File* file, int output_type) {
|
||||
|
||||
for (const auto& itr : *file->path()) {
|
||||
switch (output_type) {
|
||||
case 0: result.push_back(itr.str()); break;
|
||||
case 1: result.push_back(itr.object_hex()); break;
|
||||
case 2: result.push_back(itr.object_base64()); break;
|
||||
case 3: result.push_back(itr.object_base64_as_binary()); break;
|
||||
case 4: result.push_back(itr.object_as_binary()); break;
|
||||
case 5: result.push_back(itr.object_utf8_text_or_base64()); break;
|
||||
case 6: result.push_back(itr.object_utf8_text_or_as_binary()); break;
|
||||
case 0: result.push_back(itr.str()); break;
|
||||
case 1: result.push_back(itr.object_hex()); break;
|
||||
case 2: result.push_back(itr.object_base64()); break;
|
||||
case 3: result.push_back(itr.object_base64_as_binary()); break;
|
||||
case 4: result.push_back(itr.object_as_binary()); break;
|
||||
case 5: result.push_back(itr.object_utf8_or_base64()); break;
|
||||
case 6: result.push_back(itr.object_utf8_or_as_binary()); break;
|
||||
default: throw torrent::input_error("apply_f_path_components(): invalid output type");
|
||||
};
|
||||
}
|
||||
@@ -114,8 +114,8 @@ initialize_command_file() {
|
||||
CMD2_FILE("f.frozen_path.hex", [](auto* file, auto) { return file->frozen_path().object_hex(); });
|
||||
CMD2_FILE("f.frozen_path.base64", [](auto* file, auto) { return file->frozen_path().object_base64(); });
|
||||
CMD2_FILE("f.frozen_path.as_binary", [](auto* file, auto) { return file->frozen_path().object_as_binary(); });
|
||||
CMD2_FILE("f.frozen_path.or_base64", [](auto* file, auto) { return file->frozen_path().object_utf8_text_or_base64(); });
|
||||
CMD2_FILE("f.frozen_path.or_as_binary", [](auto* file, auto) { return file->frozen_path().object_utf8_text_or_as_binary(); });
|
||||
CMD2_FILE("f.frozen_path.or_base64", [](auto* file, auto) { return file->frozen_path().object_utf8_or_base64(); });
|
||||
CMD2_FILE("f.frozen_path.or_as_binary", [](auto* file, auto) { return file->frozen_path().object_utf8_or_as_binary(); });
|
||||
CMD2_FILE("f.frozen_path.realpath.or_empty", [](auto* file, auto) { return resolve_path(file->frozen_path().str()); });
|
||||
CMD2_FILE("f.frozen_path.realpath.or_throw", [](auto* file, auto) { return resolve_path_or_throw(file->frozen_path().str()); });
|
||||
|
||||
|
||||
@@ -123,8 +123,6 @@ initialize_command_local() {
|
||||
CMD_ANY_STRING_V("session.path.set", [](auto, auto& str) { return session_thread::manager()->set_path(str); });
|
||||
CMD_ANY ("session.use_lock", [](auto, auto) { return session_thread::manager()->use_lock(); });
|
||||
CMD_ANY_VALUE_V ("session.use_lock.set", [](auto, auto& value) { return session_thread::manager()->set_use_lock(value); });
|
||||
CMD_ANY ("session.umask", [](auto, auto) { return session_thread::manager()->umask(); });
|
||||
CMD_ANY_VALUE_V ("session.umask.set", [](auto, auto& value) { return session_thread::manager()->set_umask(value); });
|
||||
CMD_VAR_BOOL ("session.on_completion", true);
|
||||
|
||||
CMD_ANY_V ("session.save", [dList](auto, auto) { return dList->session_save(); });
|
||||
@@ -173,7 +171,6 @@ initialize_command_local() {
|
||||
rpc::rpc.mark_safe("directory.default.realpath.or_empty");
|
||||
rpc::rpc.mark_safe("directory.default.realpath.or_throw");
|
||||
rpc::rpc.mark_safe("session.use_lock");
|
||||
rpc::rpc.mark_safe("session.umask");
|
||||
rpc::rpc.mark_safe("session.on_completion");
|
||||
|
||||
rpc::rpc.mark_safe("pieces.sync.always_safe");
|
||||
|
||||
+9
-9
@@ -138,6 +138,15 @@ Control::handle_shutdown() {
|
||||
if (scgi_thread::thread()->is_active())
|
||||
scgi_thread::thread()->stop_thread_wait();
|
||||
|
||||
if (!m_shutdown_session_saved) {
|
||||
// Flush the latest state before stopped announces can consume the timeout. A shutdown hook may
|
||||
// already have queued these resume builds.
|
||||
m_core->download_list()->session_save();
|
||||
session_thread::manager()->flush_shutdown_saves();
|
||||
|
||||
m_shutdown_session_saved = true;
|
||||
}
|
||||
|
||||
if (!m_shutdown_quick) {
|
||||
torrent::runtime::network_manager()->listen_close();
|
||||
torrent::runtime::shutdown();
|
||||
@@ -153,15 +162,6 @@ Control::handle_shutdown() {
|
||||
m_core->shutdown(true);
|
||||
}
|
||||
|
||||
if (!m_shutdown_session_saved) {
|
||||
// Transfers are stopped, so this is the final state; write it before the
|
||||
// stopped announces can hold the shutdown. A shutdown hook may already
|
||||
// have queued these resume builds.
|
||||
m_core->download_list()->session_save();
|
||||
session_thread::manager()->flush_shutdown_saves();
|
||||
m_shutdown_session_saved = true;
|
||||
}
|
||||
|
||||
if (!m_task_shutdown_clear_requests.is_scheduled())
|
||||
torrent::this_thread::scheduler()->wait_for_ceil_seconds(&m_task_shutdown_clear_requests, 10s);
|
||||
|
||||
|
||||
+2
-2
@@ -50,7 +50,6 @@ public:
|
||||
bool is_shutdown_completed();
|
||||
bool is_shutdown_received() { return m_shutdown_received; }
|
||||
bool is_shutdown_started() { return m_shutdown_quick; }
|
||||
bool is_shutdown_session_saved() { return m_shutdown_session_saved; }
|
||||
|
||||
void initialize();
|
||||
void cleanup();
|
||||
@@ -113,9 +112,10 @@ private:
|
||||
|
||||
int m_clear_requests_count{};
|
||||
|
||||
bool m_shutdown_session_saved{};
|
||||
|
||||
align_cacheline
|
||||
|
||||
bool m_shutdown_session_saved{};
|
||||
std::atomic<bool> m_shutdown_received{};
|
||||
std::atomic<bool> m_shutdown_quick{};
|
||||
};
|
||||
|
||||
@@ -278,21 +278,12 @@ DownloadFactory::receive_success() {
|
||||
|
||||
// Check first if we already have these values set in the session
|
||||
// torrent, so that it is safe to change the values.
|
||||
try {
|
||||
if (rpc::call_command_value("system.file.split_size") >= 0)
|
||||
torrent::file_split_all(download->download()->file_list(),
|
||||
rpc::call_command_value("system.file.split_size"),
|
||||
rpc::call_command_string("system.file.split_suffix"));
|
||||
} catch (const torrent::input_error& e) {
|
||||
std::string msg = "Could not split files: " + std::string(e.what());
|
||||
|
||||
lt_log_print(torrent::LOG_ERRORS, "%s: %s", msg.c_str(), m_uri.c_str());
|
||||
|
||||
torrent::download_remove(*download->download());
|
||||
delete download;
|
||||
|
||||
return receive_failed(msg);
|
||||
}
|
||||
//
|
||||
// Need to also catch the exceptions.
|
||||
if (rpc::call_command_value("system.file.split_size") >= 0)
|
||||
torrent::file_split_all(download->download()->file_list(),
|
||||
rpc::call_command_value("system.file.split_size"),
|
||||
rpc::call_command_string("system.file.split_suffix"));
|
||||
|
||||
if (rtorrent->has_key_string("directory")) {
|
||||
rpc::call_command("d.directory_base.set", rtorrent->get_key("directory"), rpc::make_target(download));
|
||||
|
||||
@@ -586,23 +586,6 @@ DownloadList::hash_done(Download* download) {
|
||||
if (download->is_done() && download->download()->info()->is_meta_download())
|
||||
return process_meta_download(download);
|
||||
|
||||
constexpr auto completed_unfinished_message =
|
||||
"Download registered as completed, but hash check returned unfinished chunks.";
|
||||
constexpr auto final_bad_chunks_message = "Hash check on download completion found bad chunks.";
|
||||
constexpr auto invalid_hashing_message =
|
||||
"Hash check completed but the \"hashing\" variable is in an invalid state.";
|
||||
|
||||
// A pass that found every chunk retires the diagnoses an earlier pass set
|
||||
// below. Any other message is left alone.
|
||||
if (download->is_done() &&
|
||||
(hashing == Download::variable_hashing_initial ||
|
||||
hashing == Download::variable_hashing_rehash ||
|
||||
hashing == Download::variable_hashing_last) &&
|
||||
(download->message() == completed_unfinished_message ||
|
||||
download->message() == final_bad_chunks_message ||
|
||||
download->message() == invalid_hashing_message))
|
||||
download->set_message("");
|
||||
|
||||
switch (hashing) {
|
||||
case Download::variable_hashing_initial:
|
||||
case Download::variable_hashing_rehash:
|
||||
@@ -612,7 +595,7 @@ DownloadList::hash_done(Download* download) {
|
||||
// f.ex deleted, then we clear the state and complete.
|
||||
if (rpc::call_command_value("d.complete", rpc::make_target(download)) && !download->is_done()) {
|
||||
set_state_stopped(download);
|
||||
download->set_message(completed_unfinished_message);
|
||||
download->set_message("Download registered as completed, but hash check returned unfinished chunks.");
|
||||
}
|
||||
|
||||
// Save resume data so we update time-stamps and priorities if
|
||||
@@ -636,7 +619,7 @@ DownloadList::hash_done(Download* download) {
|
||||
if (download->is_done()) {
|
||||
confirm_finished(download);
|
||||
} else {
|
||||
download->set_message(final_bad_chunks_message);
|
||||
download->set_message("Hash check on download completion found bad chunks.");
|
||||
LT_LOG_DOWNLOAD_EVENTS("hash check on download completion found bad chunks", 0);
|
||||
|
||||
DL_TRIGGER_EVENT(download, "event.download.hash_final_failed");
|
||||
@@ -648,7 +631,7 @@ DownloadList::hash_done(Download* download) {
|
||||
case Download::variable_hashing_stopped:
|
||||
default:
|
||||
// Either an error or someone wrote to the hashing variable...
|
||||
download->set_message(invalid_hashing_message);
|
||||
download->set_message("Hash check completed but the \"hashing\" variable is in an invalid state.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -436,9 +436,8 @@ Manager::receive_hashing_changed() {
|
||||
if (tryQuick) {
|
||||
// Make sure we don't repeat the quick hashing.
|
||||
rpc::call_command_set_value("d.hashing.set", Download::variable_hashing_rehash, rpc::make_target(*itr));
|
||||
}
|
||||
|
||||
if (!tryQuick || !foundHashing) {
|
||||
} else {
|
||||
(*itr)->set_hash_failed(true);
|
||||
(*itr)->set_message("Hashing failed: " + std::string(e.what()));
|
||||
|
||||
|
||||
+1
-5
@@ -489,11 +489,7 @@ main(int argc, char** argv) {
|
||||
|
||||
torrent::system::Thread::self()->event_loop();
|
||||
|
||||
// A quick shutdown with no tracker request pending leaves the loop before
|
||||
// handle_shutdown() could save.
|
||||
if (!control->is_shutdown_session_saved())
|
||||
control->core()->download_list()->session_save();
|
||||
|
||||
control->core()->download_list()->session_save();
|
||||
control->cleanup();
|
||||
|
||||
} catch (torrent::internal_error& e) {
|
||||
|
||||
+1
-31
@@ -10,8 +10,6 @@
|
||||
#include <torrent/net/fd.h>
|
||||
#include <torrent/net/socket_address.h>
|
||||
#include <torrent/system/poll.h>
|
||||
#include <torrent/system/scheduler.h>
|
||||
#include <torrent/utils/log.h>
|
||||
#include <torrent/runtime/socket_manager.h>
|
||||
|
||||
#include "control.h"
|
||||
@@ -27,8 +25,6 @@ SCgi::SCgi() {
|
||||
std::generate(m_tasks.begin(), m_tasks.end(), []() { return std::make_unique<SCgiTask>(); });
|
||||
|
||||
m_current = m_tasks.begin();
|
||||
|
||||
m_resume_accept.slot() = [this] { resume_accept(); };
|
||||
}
|
||||
|
||||
SCgi::~SCgi() {
|
||||
@@ -125,9 +121,6 @@ SCgi::stop() {
|
||||
if (!is_open())
|
||||
return;
|
||||
|
||||
if (m_resume_accept.is_scheduled())
|
||||
torrent::this_thread::scheduler()->erase(&m_resume_accept);
|
||||
|
||||
for (auto& itr : m_tasks) {
|
||||
if (itr->is_open())
|
||||
itr->close();
|
||||
@@ -165,16 +158,9 @@ SCgi::event_read() {
|
||||
return;
|
||||
|
||||
// Force a new event_read() call just to be sure we don't enter an infinite loop.
|
||||
if (errno == ECONNABORTED || errno == EPROTO || errno == EPERM)
|
||||
if (errno == ECONNABORTED)
|
||||
return;
|
||||
|
||||
// Out of file descriptors or memory: the connection stays queued and the socket stays readable,
|
||||
// so stop reading it for a while instead of spinning.
|
||||
if (errno == EMFILE || errno == ENFILE || errno == ENOBUFS || errno == ENOMEM) {
|
||||
pause_accept(errno);
|
||||
return;
|
||||
}
|
||||
|
||||
throw torrent::resource_error("Listener port accept() failed: " + std::string(std::strerror(errno)));
|
||||
}
|
||||
|
||||
@@ -203,22 +189,6 @@ SCgi::event_read() {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SCgi::pause_accept(int error) {
|
||||
lt_log_print(torrent::LOG_ERRORS, "scgi: accept() failed: %s : not accepting connections for a second", std::strerror(error));
|
||||
|
||||
torrent::this_thread::poll()->remove_read(this);
|
||||
torrent::this_thread::scheduler()->update_wait_for(&m_resume_accept, std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
void
|
||||
SCgi::resume_accept() {
|
||||
if (!is_open())
|
||||
return;
|
||||
|
||||
torrent::this_thread::poll()->insert_read(this);
|
||||
}
|
||||
|
||||
void
|
||||
SCgi::event_write() {
|
||||
throw torrent::internal_error("Listener does not support write().");
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <torrent/system/event.h>
|
||||
#include <torrent/system/scheduler.h>
|
||||
|
||||
#include "rpc/scgi_task.h"
|
||||
|
||||
@@ -40,16 +39,12 @@ private:
|
||||
using task_list = std::array<std::unique_ptr<SCgiTask>, max_tasks>;
|
||||
|
||||
void open(sockaddr* sa, unsigned int length);
|
||||
void pause_accept(int error);
|
||||
void resume_accept();
|
||||
|
||||
std::string m_path;
|
||||
int m_logFd{-1};
|
||||
|
||||
task_list m_tasks;
|
||||
task_list::iterator m_current;
|
||||
|
||||
torrent::system::SchedulerEntry m_resume_accept;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <torrent/exceptions.h>
|
||||
#include <torrent/object.h>
|
||||
@@ -124,7 +123,7 @@ is_correct_format(const std::string& f) {
|
||||
}
|
||||
|
||||
void
|
||||
save_stream(const std::string& path, bool use_fsyncdisk, mode_t file_mode, const std::stringstream& stream) {
|
||||
save_stream(const std::string& path, bool use_fsyncdisk, const std::stringstream& stream) {
|
||||
// Remove any leftover temporary file first so that O_EXCL only ever fails on
|
||||
// an entry that appeared after the unlink, and O_NOFOLLOW keeps a symlink
|
||||
// planted in the session directory from redirecting the write.
|
||||
@@ -137,12 +136,6 @@ save_stream(const std::string& path, bool use_fsyncdisk, mode_t file_mode, const
|
||||
if (fd < 0)
|
||||
throw torrent::storage_error("failed to open file for writing : " + path);
|
||||
|
||||
// open() applies the process umask, so set the configured mode explicitly.
|
||||
if (file_mode != 0 && ::fchmod(fd, file_mode) == -1) {
|
||||
::close(fd);
|
||||
throw torrent::storage_error("failed to set file permissions : " + path);
|
||||
}
|
||||
|
||||
const auto data = stream.view();
|
||||
std::size_t remaining = data.size();
|
||||
const char* cursor = data.data();
|
||||
@@ -203,7 +196,7 @@ sync_directory_of(const std::string& path) {
|
||||
} // namespace anonymous
|
||||
|
||||
void
|
||||
DownloadStorer::save_and_move_streams(const std::string& path, bool use_fsyncdisk, mode_t file_mode,
|
||||
DownloadStorer::save_and_move_streams(const std::string& path, bool use_fsyncdisk,
|
||||
const std::stringstream* torrent_stream,
|
||||
const std::stringstream* rtorrent_stream,
|
||||
const std::stringstream* libtorrent_stream) {
|
||||
@@ -212,10 +205,10 @@ DownloadStorer::save_and_move_streams(const std::string& path, bool use_fsyncdis
|
||||
auto rtorrent_path = path + ".rtorrent";
|
||||
|
||||
if (torrent_stream)
|
||||
save_stream(torrent_path + ".new", use_fsyncdisk, file_mode, *torrent_stream);
|
||||
save_stream(torrent_path + ".new", use_fsyncdisk, *torrent_stream);
|
||||
|
||||
save_stream(libtorrent_path + ".new", use_fsyncdisk, file_mode, *libtorrent_stream);
|
||||
save_stream(rtorrent_path + ".new", use_fsyncdisk, file_mode, *rtorrent_stream);
|
||||
save_stream(libtorrent_path + ".new", use_fsyncdisk, *libtorrent_stream);
|
||||
save_stream(rtorrent_path + ".new", use_fsyncdisk, *rtorrent_stream);
|
||||
|
||||
if (torrent_stream) {
|
||||
if (::rename((torrent_path + ".new").c_str(), torrent_path.c_str()) == -1)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <sys/types.h>
|
||||
#include <string>
|
||||
#include <torrent/common.h>
|
||||
|
||||
@@ -34,7 +33,7 @@ public:
|
||||
auto rtorrent_stream() { return std::move(m_rtorrent_stream); }
|
||||
auto libtorrent_stream() { return std::move(m_libtorrent_stream); }
|
||||
|
||||
static void save_and_move_streams(const std::string& path, bool use_fsyncdisk, mode_t file_mode,
|
||||
static void save_and_move_streams(const std::string& path, bool use_fsyncdisk,
|
||||
const std::stringstream* torrent_stream,
|
||||
const std::stringstream* rtorrent_stream,
|
||||
const std::stringstream* libtorrent_stream);
|
||||
|
||||
@@ -65,30 +65,6 @@ SessionManager::set_use_lock(bool use_lock) {
|
||||
m_use_lock = use_lock;
|
||||
}
|
||||
|
||||
mode_t
|
||||
SessionManager::file_mode() const {
|
||||
if (m_umask == 0)
|
||||
return 0;
|
||||
|
||||
return 0666 & ~m_umask;
|
||||
}
|
||||
|
||||
void
|
||||
SessionManager::set_umask(int64_t umask) {
|
||||
assert(torrent::this_thread::thread() == torrent::main_thread::thread());
|
||||
|
||||
if (m_freeze_info)
|
||||
throw torrent::input_error("Session umask option cannot be changed after startup.");
|
||||
|
||||
if (umask < 0 || umask > 0777)
|
||||
throw torrent::input_error("Session umask must be in the range 0 to 0777.");
|
||||
|
||||
if (umask != 0 && (umask & 0600) != 0)
|
||||
throw torrent::input_error("Session umask must not mask owner read/write permissions (0600).");
|
||||
|
||||
m_umask = umask;
|
||||
}
|
||||
|
||||
void
|
||||
SessionManager::save_resume_download(core::Download* download) {
|
||||
assert(torrent::this_thread::thread() == torrent::main_thread::thread());
|
||||
@@ -403,7 +379,7 @@ SessionManager::process_next_save_request_unsafe() {
|
||||
};
|
||||
|
||||
try {
|
||||
DownloadStorer::save_and_move_streams(itr->second.path, m_use_fsyncdisk, file_mode(),
|
||||
DownloadStorer::save_and_move_streams(itr->second.path, m_use_fsyncdisk,
|
||||
itr->second.torrent_stream.get(),
|
||||
itr->second.rtorrent_stream.get(),
|
||||
itr->second.libtorrent_stream.get());
|
||||
@@ -437,33 +413,34 @@ SessionManager::process_finished_saves() {
|
||||
callback_save_request();
|
||||
}
|
||||
|
||||
// Storage errors share a five-minute log limit and count what they suppress.
|
||||
// Callers hold m_mutex.
|
||||
void
|
||||
SessionManager::report_storage_error_unsafe(const std::string& what) {
|
||||
// Returns true when a storage error was suppressed.
|
||||
bool
|
||||
SessionManager::report_storage_error_unsafe(const std::string& msg) {
|
||||
if (m_last_storage_error_message + std::chrono::minutes(5) > torrent::this_thread::cached_time()) {
|
||||
m_ignored_storage_error_count++;
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
lt_log_print(torrent::LOG_ERRORS, "Storage errors saving session data for download: ignored:%u : %s", m_ignored_storage_error_count, what.c_str());
|
||||
lt_log_print(torrent::LOG_ERRORS, "Storage errors saving session data for download: ignored:%u : %s", m_ignored_storage_error_count, msg.c_str());
|
||||
|
||||
m_last_storage_error_message = torrent::this_thread::cached_time();
|
||||
m_last_storage_error_message = torrent::this_thread::cached_time();
|
||||
m_ignored_storage_error_count = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// The one policy for a finished save, on the session thread and in shutdown
|
||||
// flushes: storage errors go to report_storage_error_unsafe(), internal and
|
||||
// unknown errors propagate. Callers hold m_mutex.
|
||||
void
|
||||
// The one policy for a finished save, on the session thread and in shutdown flushes: storage errors
|
||||
// go to report_storage_error_unsafe(), internal and unknown errors propagate.
|
||||
//
|
||||
// Returns true when a storage error was suppressed.
|
||||
bool
|
||||
SessionManager::consume_finished_save_unsafe(ProcessingSave& request) {
|
||||
try {
|
||||
request.first.get();
|
||||
|
||||
} catch (torrent::storage_error& e) {
|
||||
LT_LOG("error saving download : storage error :download:%p path:%s : %s", request.second.download, request.second.path.c_str(), e.what());
|
||||
report_storage_error_unsafe(e.what());
|
||||
return;
|
||||
return report_storage_error_unsafe(e.what());
|
||||
|
||||
} catch (torrent::internal_error& e) {
|
||||
LT_LOG("error saving download : internal error : download:%p path:%s : %s", request.second.download, request.second.path.c_str(), e.what());
|
||||
@@ -475,13 +452,17 @@ SessionManager::consume_finished_save_unsafe(ProcessingSave& request) {
|
||||
}
|
||||
|
||||
LT_LOG("finished saving download : download:%p path:%s", request.second.download, request.second.path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SessionManager::flush_shutdown_saves() {
|
||||
assert(torrent::this_thread::thread() == torrent::main_thread::thread());
|
||||
|
||||
flush_all_pending_builds();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
flush_all_and_wait_unsafe(lock);
|
||||
}
|
||||
|
||||
@@ -503,15 +484,17 @@ SessionManager::flush_all_and_wait_unsafe(std::unique_lock<std::mutex>& lock) {
|
||||
while (!m_processing_saves.empty())
|
||||
m_finished_condition.wait(lock);
|
||||
|
||||
unsigned int suppressed = 0;
|
||||
|
||||
for (auto& request : m_finished_saves)
|
||||
consume_finished_save_unsafe(request);
|
||||
suppressed += consume_finished_save_unsafe(request) ? 1 : 0;
|
||||
|
||||
m_finished_saves.clear();
|
||||
|
||||
// Report and reset what was suppressed since the last error line. The count
|
||||
// includes saves the session thread consumed while this flush waited.
|
||||
if (m_ignored_storage_error_count != 0) {
|
||||
lt_log_print(torrent::LOG_ERRORS, "Storage errors flushing session data: ignored:%u", m_ignored_storage_error_count);
|
||||
lt_log_print(torrent::LOG_ERRORS, "Storage errors flushing session data: ignored:%u previous:%u",
|
||||
suppressed, m_ignored_storage_error_count - suppressed);
|
||||
|
||||
m_ignored_storage_error_count = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
#include <deque>
|
||||
#include <future>
|
||||
#include <list>
|
||||
#include <cstdint>
|
||||
#include <sys/types.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
@@ -61,10 +59,6 @@ public:
|
||||
bool use_lock() const;
|
||||
void set_use_lock(bool use_lock);
|
||||
|
||||
int umask() const;
|
||||
void set_umask(int64_t umask);
|
||||
mode_t file_mode() const;
|
||||
|
||||
void save_full_download(core::Download* download);
|
||||
void save_resume_download(core::Download* download);
|
||||
void remove_download(core::Download* download);
|
||||
@@ -82,6 +76,7 @@ protected:
|
||||
void flush_shutdown_saves();
|
||||
|
||||
private:
|
||||
|
||||
void callback_pending_builds();
|
||||
void callback_save_request();
|
||||
void callback_finished_saves();
|
||||
@@ -99,8 +94,8 @@ private:
|
||||
|
||||
using ProcessingSave = std::pair<std::future<void>, SaveRequest>;
|
||||
|
||||
void consume_finished_save_unsafe(ProcessingSave& request);
|
||||
void report_storage_error_unsafe(const std::string& what);
|
||||
bool consume_finished_save_unsafe(ProcessingSave& request);
|
||||
bool report_storage_error_unsafe(const std::string& msg);
|
||||
|
||||
torrent::system::Thread* m_thread;
|
||||
torrent::system::callback_id m_callback_id;
|
||||
@@ -109,7 +104,6 @@ private:
|
||||
std::string m_path;
|
||||
bool m_use_fsyncdisk{true};
|
||||
bool m_use_lock{true};
|
||||
int m_umask{};
|
||||
|
||||
align_cacheline
|
||||
|
||||
@@ -144,7 +138,6 @@ inline bool SessionManager::is_used() const { return !m_path.e
|
||||
inline std::string SessionManager::path() const { return m_path; }
|
||||
inline bool SessionManager::use_fsyncdisk() const { return m_use_fsyncdisk; }
|
||||
inline bool SessionManager::use_lock() const { return m_use_lock; }
|
||||
inline int SessionManager::umask() const { return m_umask; }
|
||||
inline void SessionManager::flush_all_pending_builds() { process_pending_builds(true); }
|
||||
|
||||
} // namespace session
|
||||
|
||||
@@ -59,8 +59,6 @@ rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \
|
||||
rpc/test_rpc_manager.h
|
||||
|
||||
rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \
|
||||
src/test_command_download.cc \
|
||||
src/test_command_download.h \
|
||||
src/test_command_dynamic.cc \
|
||||
src/test_command_dynamic.h \
|
||||
src/test_command_groups.cc \
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "test/src/test_command_download.h"
|
||||
|
||||
#include <torrent/download.h>
|
||||
#include <torrent/object.h>
|
||||
#include <torrent/torrent.h>
|
||||
#include <torrent/utils/string_manip.h>
|
||||
|
||||
#include "control.h"
|
||||
#include "core/download.h"
|
||||
#include "globals.h"
|
||||
#include "rpc/parse_commands.h"
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestCommandDownload);
|
||||
|
||||
void initialize_command_download();
|
||||
|
||||
namespace {
|
||||
|
||||
// Valid UTF-8 with a carriage return and a C0 control character.
|
||||
const std::string control_name = "cr\r ctl\x01 \xc3\xa9.bin";
|
||||
|
||||
core::Download*
|
||||
insert_download(core::DownloadList* list, const std::string& name) {
|
||||
torrent::Object info = torrent::Object::create_map();
|
||||
info.insert_key("name", name);
|
||||
info.insert_key("length", int64_t{16});
|
||||
info.insert_key("piece length", int64_t{262144});
|
||||
info.insert_key("pieces", std::string(20, char(0)));
|
||||
|
||||
auto* object = new torrent::Object(torrent::Object::create_map());
|
||||
object->insert_key("info", info);
|
||||
|
||||
auto* download = new core::Download(torrent::download_add(object, 0));
|
||||
list->insert(download);
|
||||
|
||||
return download;
|
||||
}
|
||||
|
||||
torrent::Object
|
||||
call_d(const char* key, core::Download* download) {
|
||||
return rpc::commands.call_command_d(key, download, torrent::Object());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
TestCommandDownload::setUp() {
|
||||
// torrent::download_add() opens a socket through the mocked fd functions.
|
||||
mock_redirect_defaults();
|
||||
|
||||
torrent::initialize_main_thread();
|
||||
torrent::initialize();
|
||||
|
||||
if (control == nullptr)
|
||||
control = new Control;
|
||||
|
||||
if (!rpc::commands.has("d.name"))
|
||||
initialize_command_download();
|
||||
}
|
||||
|
||||
void
|
||||
TestCommandDownload::tearDown() {
|
||||
m_list.clear();
|
||||
|
||||
torrent::cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
TestCommandDownload::test_name_or_base64() {
|
||||
auto* plain = insert_download(&m_list, "plain.bin");
|
||||
auto* download = insert_download(&m_list, control_name);
|
||||
|
||||
auto plain_result = call_d("d.name.or_base64", plain);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("plain.bin"), plain_result.as_string());
|
||||
CPPUNIT_ASSERT_EQUAL(uint32_t{0}, plain_result.flags());
|
||||
|
||||
auto result = call_d("d.name.or_base64", download);
|
||||
CPPUNIT_ASSERT_EQUAL(torrent::utils::transform_to_base64(control_name), result.as_string());
|
||||
CPPUNIT_ASSERT_EQUAL(torrent::Object::flag_base64 | torrent::Object::flag_as_binary, result.flags());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(control_name, call_d("d.name", download).as_string());
|
||||
CPPUNIT_ASSERT_EQUAL(uint32_t{0}, call_d("d.name", download).flags());
|
||||
}
|
||||
|
||||
void
|
||||
TestCommandDownload::test_name_or_as_binary() {
|
||||
auto* plain = insert_download(&m_list, "plain.bin");
|
||||
auto* download = insert_download(&m_list, control_name);
|
||||
|
||||
auto plain_result = call_d("d.name.or_as_binary", plain);
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("plain.bin"), plain_result.as_string());
|
||||
CPPUNIT_ASSERT_EQUAL(uint32_t{0}, plain_result.flags());
|
||||
|
||||
auto result = call_d("d.name.or_as_binary", download);
|
||||
CPPUNIT_ASSERT_EQUAL(control_name, result.as_string());
|
||||
CPPUNIT_ASSERT_EQUAL(torrent::Object::flag_as_binary, result.flags());
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include "core/download_list.h"
|
||||
#include "test/helpers/test_fixture.h"
|
||||
|
||||
class TestCommandDownload : public test_fixture {
|
||||
CPPUNIT_TEST_SUITE(TestCommandDownload);
|
||||
|
||||
CPPUNIT_TEST(test_name_or_base64);
|
||||
CPPUNIT_TEST(test_name_or_as_binary);
|
||||
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
void setUp();
|
||||
void tearDown();
|
||||
|
||||
void test_name_or_base64();
|
||||
void test_name_or_as_binary();
|
||||
|
||||
private:
|
||||
core::DownloadList m_list;
|
||||
};
|
||||
@@ -73,7 +73,7 @@ TestSessionCommit::commit_and_verify(bool use_fsyncdisk) {
|
||||
std::stringstream rtorrent_stream("rtorrent-data");
|
||||
std::stringstream libtorrent_stream("libtorrent-data");
|
||||
|
||||
session::DownloadStorer::save_and_move_streams(path, use_fsyncdisk, 0600, &torrent_stream, &rtorrent_stream, &libtorrent_stream);
|
||||
session::DownloadStorer::save_and_move_streams(path, use_fsyncdisk, &torrent_stream, &rtorrent_stream, &libtorrent_stream);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("torrent-data"), read_file(path));
|
||||
CPPUNIT_ASSERT_EQUAL(std::string("rtorrent-data"), read_file(path + ".rtorrent"));
|
||||
|
||||
@@ -39,12 +39,12 @@ read_file(const std::string& path) {
|
||||
}
|
||||
|
||||
void
|
||||
save_session_files(const std::string& path, mode_t file_mode = 0600) {
|
||||
save_session_files(const std::string& path) {
|
||||
std::stringstream torrent_stream("torrent-data");
|
||||
std::stringstream rtorrent_stream("rtorrent-data");
|
||||
std::stringstream libtorrent_stream("libtorrent-data");
|
||||
|
||||
session::DownloadStorer::save_and_move_streams(path, false, file_mode, &torrent_stream, &rtorrent_stream, &libtorrent_stream);
|
||||
session::DownloadStorer::save_and_move_streams(path, false, &torrent_stream, &rtorrent_stream, &libtorrent_stream);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
@@ -130,21 +130,6 @@ TestSessionStorer::test_saved_files_are_owner_only() {
|
||||
CPPUNIT_ASSERT_EQUAL(0600u, permissions_of(path + ".libtorrent_resume"));
|
||||
}
|
||||
|
||||
void
|
||||
TestSessionStorer::test_saved_files_use_configured_mode() {
|
||||
for (mode_t mode : {0660, 0640}) {
|
||||
auto path = m_session_dir + "/" + entry_name;
|
||||
auto prev_umask = ::umask(0);
|
||||
|
||||
save_session_files(path, mode);
|
||||
::umask(prev_umask);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)mode, permissions_of(path));
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)mode, permissions_of(path + ".rtorrent"));
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)mode, permissions_of(path + ".libtorrent_resume"));
|
||||
}
|
||||
}
|
||||
|
||||
// Entries listed for loading must report their real type so that a symlink in
|
||||
// the session directory is skipped instead of loaded.
|
||||
void
|
||||
|
||||
@@ -7,7 +7,6 @@ class TestSessionStorer : public test_fixture {
|
||||
|
||||
CPPUNIT_TEST(test_temp_file_symlink_is_not_followed);
|
||||
CPPUNIT_TEST(test_saved_files_are_owner_only);
|
||||
CPPUNIT_TEST(test_saved_files_use_configured_mode);
|
||||
CPPUNIT_TEST(test_symlinked_entry_is_not_a_file);
|
||||
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
@@ -18,7 +17,6 @@ public:
|
||||
|
||||
void test_temp_file_symlink_is_not_followed();
|
||||
void test_saved_files_are_owner_only();
|
||||
void test_saved_files_use_configured_mode();
|
||||
void test_symlinked_entry_is_not_a_file();
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user