support renaming files to absolute paths
This commit is contained in:
parent
91f8c32937
commit
8f3723cdef
|
@ -1,3 +1,4 @@
|
|||
* allow moving files to absolute paths, out of the download directory
|
||||
* make move_storage more generic to allow both overwriting files as well as taking existing ones
|
||||
* fix choking issue at high upload rates
|
||||
* optimized rate limiter
|
||||
|
|
|
@ -1914,6 +1914,12 @@ If you want to rename the base name of the torrent (for a multifile torrent), yo
|
|||
can copy the ``file_storage`` (see `files() orig_files()`_), change the name, and
|
||||
then use `remap_files()`_.
|
||||
|
||||
The ``new_filename`` can both be a relative path, in which case the file name
|
||||
is relative to the ``save_path`` of the torrent. If the ``new_filename`` is
|
||||
an absolute path (i.e. ``is_complete(new_filename) == true``), then the file
|
||||
is detached from the ``save_path`` of the torrent. In this case the file is
|
||||
not moved when move_storage_ is invoked.
|
||||
|
||||
|
||||
begin_files() end_files() rbegin_files() rend_files()
|
||||
-----------------------------------------------------
|
||||
|
@ -2660,6 +2666,11 @@ of the other modes.
|
|||
``dont_replace`` always takes the existing file in the target directory, if there is
|
||||
one. The source files will still be removed in that case.
|
||||
|
||||
Files that have been renamed to have absolute pahts are not moved by this function.
|
||||
Keep in mind that files that don't belong to the torrent but are stored in the torrent's
|
||||
directory may be moved as well. This goes for files that have been renamed to
|
||||
absolute paths that still end up inside the save path.
|
||||
|
||||
rename_file()
|
||||
-------------
|
||||
|
||||
|
|
|
@ -149,6 +149,10 @@ namespace libtorrent
|
|||
// the full path to this file, concatenate the path
|
||||
// from that array with the 'name' field in
|
||||
// this struct
|
||||
// if path_index == -2, it means the filename
|
||||
// in this field contains the full, absolute path
|
||||
// to the file
|
||||
// -1 means no path (i.e. single file torrent)
|
||||
int path_index;
|
||||
};
|
||||
|
||||
|
@ -251,7 +255,7 @@ namespace libtorrent
|
|||
time_t mtime(int index) const;
|
||||
size_type file_base(int index) const;
|
||||
void set_file_base(int index, size_type off);
|
||||
std::string file_path(int index) const;
|
||||
std::string file_path(int index, std::string const& save_path = "") const;
|
||||
std::string file_name(int index) const;
|
||||
size_type file_size(int index) const;
|
||||
bool pad_file_at(int index) const;
|
||||
|
@ -263,7 +267,7 @@ namespace libtorrent
|
|||
int file_index(internal_file_entry const& fe) const;
|
||||
size_type file_base(internal_file_entry const& fe) const;
|
||||
void set_file_base(internal_file_entry const& fe, size_type off);
|
||||
std::string file_path(internal_file_entry const& fe) const;
|
||||
std::string file_path(internal_file_entry const& fe, std::string const& save_path = "") const;
|
||||
std::string file_name(internal_file_entry const& fe) const;
|
||||
size_type file_size(internal_file_entry const& fe) const;
|
||||
bool pad_file_at(internal_file_entry const& fe) const;
|
||||
|
|
|
@ -71,7 +71,13 @@ namespace libtorrent
|
|||
|
||||
void file_storage::update_path_index(internal_file_entry& e)
|
||||
{
|
||||
std::string parent = parent_path(e.filename());
|
||||
std::string fname = e.filename();
|
||||
if (is_complete(fname))
|
||||
{
|
||||
e.path_index = -2;
|
||||
return;
|
||||
}
|
||||
std::string parent = parent_path(fname);
|
||||
if (parent.empty())
|
||||
{
|
||||
e.path_index = -1;
|
||||
|
@ -431,13 +437,18 @@ namespace libtorrent
|
|||
return m_file_base[index];
|
||||
}
|
||||
|
||||
std::string file_storage::file_path(int index) const
|
||||
std::string file_storage::file_path(int index, std::string const& save_path) const
|
||||
{
|
||||
TORRENT_ASSERT(index >= 0 && index < int(m_files.size()));
|
||||
internal_file_entry const& fe = m_files[index];
|
||||
TORRENT_ASSERT(fe.path_index >= -1 && fe.path_index < int(m_paths.size()));
|
||||
if (fe.path_index == -1) return fe.filename();
|
||||
return combine_path(m_paths[fe.path_index], fe.filename());
|
||||
TORRENT_ASSERT(fe.path_index >= -2 && fe.path_index < int(m_paths.size()));
|
||||
// -2 means this is an absolute path filename
|
||||
if (fe.path_index == -2) return fe.filename();
|
||||
|
||||
// -1 means no path
|
||||
if (fe.path_index == -1) return combine_path(save_path, fe.filename());
|
||||
|
||||
return combine_path(save_path, combine_path(m_paths[fe.path_index], fe.filename()));
|
||||
}
|
||||
|
||||
std::string file_storage::file_name(int index) const
|
||||
|
@ -507,11 +518,16 @@ namespace libtorrent
|
|||
return m_file_base[index];
|
||||
}
|
||||
|
||||
std::string file_storage::file_path(internal_file_entry const& fe) const
|
||||
std::string file_storage::file_path(internal_file_entry const& fe, std::string const& save_path) const
|
||||
{
|
||||
TORRENT_ASSERT(fe.path_index >= -1 && fe.path_index < int(m_paths.size()));
|
||||
if (fe.path_index == -1) return fe.filename();
|
||||
return combine_path(m_paths[fe.path_index], fe.filename());
|
||||
TORRENT_ASSERT(fe.path_index >= -2 && fe.path_index < int(m_paths.size()));
|
||||
// -2 means this is an absolute path filename
|
||||
if (fe.path_index == -2) return fe.filename();
|
||||
|
||||
// -1 means no path
|
||||
if (fe.path_index == -1) return combine_path(save_path, fe.filename());
|
||||
|
||||
return combine_path(save_path, combine_path(m_paths[fe.path_index], fe.filename()));
|
||||
}
|
||||
|
||||
std::string file_storage::file_name(internal_file_entry const& fe) const
|
||||
|
|
|
@ -110,7 +110,7 @@ namespace libtorrent
|
|||
{
|
||||
file_status s;
|
||||
error_code ec;
|
||||
stat_file(combine_path(save_path, storage.file_path(*i)), &s, ec);
|
||||
stat_file(storage.file_path(*i, save_path), &s, ec);
|
||||
|
||||
if (!ec)
|
||||
{
|
||||
|
@ -160,7 +160,7 @@ namespace libtorrent
|
|||
|
||||
file_status s;
|
||||
error_code ec;
|
||||
stat_file(combine_path(p, fs.file_path(*i)), &s, ec);
|
||||
stat_file(fs.file_path(*i, p), &s, ec);
|
||||
|
||||
if (!ec)
|
||||
{
|
||||
|
@ -417,7 +417,7 @@ namespace libtorrent
|
|||
// ignore pad files
|
||||
if (file_iter->pad_file) continue;
|
||||
|
||||
std::string file_path = combine_path(m_save_path, files().file_path(*file_iter));
|
||||
std::string file_path = files().file_path(*file_iter, m_save_path);
|
||||
|
||||
file_status s;
|
||||
stat_file(file_path, &s, ec);
|
||||
|
@ -482,7 +482,7 @@ namespace libtorrent
|
|||
{
|
||||
error_code ec;
|
||||
file_status s;
|
||||
stat_file(combine_path(m_save_path, files().file_path(*i)), &s, ec);
|
||||
stat_file(files().file_path(*i, m_save_path), &s, ec);
|
||||
if (ec) continue;
|
||||
if (s.mode & file_status::regular_file && i->size > 0)
|
||||
return true;
|
||||
|
@ -493,11 +493,13 @@ namespace libtorrent
|
|||
bool default_storage::rename_file(int index, std::string const& new_filename)
|
||||
{
|
||||
if (index < 0 || index >= files().num_files()) return true;
|
||||
std::string old_name = combine_path(m_save_path, files().file_path(files().at(index)));
|
||||
std::string old_name = files().file_path(index, m_save_path);
|
||||
m_pool.release(this, index);
|
||||
|
||||
error_code ec;
|
||||
std::string new_path = combine_path(m_save_path, new_filename);
|
||||
std::string new_path;
|
||||
if (is_complete(new_filename)) new_path = new_filename;
|
||||
else new_path = combine_path(m_save_path, new_filename);
|
||||
std::string new_dir = parent_path(new_path);
|
||||
|
||||
// create any missing directories that the new filename
|
||||
|
@ -556,14 +558,18 @@ namespace libtorrent
|
|||
, end(files().end()); i != end; ++i)
|
||||
{
|
||||
std::string fp = files().file_path(*i);
|
||||
std::string p = combine_path(m_save_path, fp);
|
||||
std::string bp = parent_path(fp);
|
||||
std::pair<iter_t, bool> ret;
|
||||
ret.second = true;
|
||||
while (ret.second && !bp.empty())
|
||||
bool complete = is_complete(fp);
|
||||
std::string p = complete ? fp : combine_path(m_save_path, fp);
|
||||
if (!complete)
|
||||
{
|
||||
ret = directories.insert(combine_path(m_save_path, bp));
|
||||
bp = parent_path(bp);
|
||||
std::string bp = parent_path(fp);
|
||||
std::pair<iter_t, bool> ret;
|
||||
ret.second = true;
|
||||
while (ret.second && !bp.empty())
|
||||
{
|
||||
ret = directories.insert(combine_path(m_save_path, bp));
|
||||
bp = parent_path(bp);
|
||||
}
|
||||
}
|
||||
delete_one_file(p);
|
||||
}
|
||||
|
@ -768,7 +774,10 @@ namespace libtorrent
|
|||
for (file_storage::iterator i = f.begin()
|
||||
, end(f.end()); i != end; ++i)
|
||||
{
|
||||
std::string new_path = combine_path(save_path, f.file_path(*i));
|
||||
// files moved out to absolute paths are ignored
|
||||
if (is_complete(f.file_path(*i))) continue;
|
||||
|
||||
std::string new_path = f.file_path(*i, save_path);
|
||||
stat_file(new_path, &s, ec);
|
||||
if (ec != boost::system::errc::no_such_file_or_directory)
|
||||
return piece_manager::file_exist;
|
||||
|
@ -783,6 +792,9 @@ namespace libtorrent
|
|||
for (file_storage::iterator i = f.begin()
|
||||
, end(f.end()); i != end; ++i)
|
||||
{
|
||||
// files moved out to absolute paths are not moved
|
||||
if (is_complete(f.file_path(*i))) continue;
|
||||
|
||||
std::string split = split_path(f.file_path(*i));
|
||||
to_move.insert(to_move.begin(), split);
|
||||
}
|
||||
|
@ -1199,7 +1211,7 @@ ret:
|
|||
// this means the directory the file is in doesn't exist.
|
||||
// so create it
|
||||
ec.clear();
|
||||
std::string path = combine_path(m_save_path, files().file_path(*file_iter));
|
||||
std::string path = files().file_path(*file_iter, m_save_path);
|
||||
create_directories(parent_path(path), ec);
|
||||
// if the directory creation failed, don't try to open the file again
|
||||
// but actually just fail
|
||||
|
@ -1208,7 +1220,7 @@ ret:
|
|||
|
||||
if (!file_handle || ec)
|
||||
{
|
||||
std::string path = combine_path(m_save_path, files().file_path(*file_iter));
|
||||
std::string path = files().file_path(*file_iter, m_save_path);
|
||||
TORRENT_ASSERT(ec);
|
||||
set_error(path, ec);
|
||||
return -1;
|
||||
|
@ -1253,7 +1265,7 @@ ret:
|
|||
|
||||
if (ec)
|
||||
{
|
||||
set_error(combine_path(m_save_path, files().file_path(*file_iter)), ec);
|
||||
set_error(files().file_path(*file_iter, m_save_path), ec);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,9 +77,51 @@ void setup_test_storage(file_storage& st)
|
|||
int test_main()
|
||||
{
|
||||
{
|
||||
file_storage a;
|
||||
setup_test_storage(a);
|
||||
file_storage st;
|
||||
setup_test_storage(st);
|
||||
|
||||
st.rename_file(0, "test/c/d");
|
||||
TEST_EQUAL(st.file_path(0, "./"), "./test/c/d");
|
||||
|
||||
st.rename_file(0, "/tmp/a");
|
||||
TEST_EQUAL(st.file_path(0, "./"), "/tmp/a");
|
||||
}
|
||||
|
||||
{
|
||||
file_storage st;
|
||||
st.add_file("a", 10000);
|
||||
|
||||
st.rename_file(0, "test/c/d");
|
||||
TEST_EQUAL(st.file_path(0, "./"), "./test/c/d");
|
||||
|
||||
st.rename_file(0, "/tmp/a");
|
||||
TEST_EQUAL(st.file_path(0, "./"), "/tmp/a");
|
||||
}
|
||||
|
||||
{
|
||||
file_storage fs;
|
||||
fs.set_piece_length(512);
|
||||
fs.add_file("temp_storage/test1.tmp", 17);
|
||||
fs.add_file("temp_storage/test2.tmp", 612);
|
||||
fs.add_file("temp_storage/test3.tmp", 0);
|
||||
fs.add_file("temp_storage/test4.tmp", 0);
|
||||
fs.add_file("temp_storage/test5.tmp", 3253);
|
||||
// size: 3882
|
||||
fs.add_file("temp_storage/test6.tmp", 841);
|
||||
// size: 4723
|
||||
|
||||
peer_request rq = fs.map_file(0, 0, 10);
|
||||
TEST_EQUAL(rq.piece, 0);
|
||||
TEST_EQUAL(rq.start, 0);
|
||||
TEST_EQUAL(rq.length, 10);
|
||||
rq = fs.map_file(5, 0, 10);
|
||||
TEST_EQUAL(rq.piece, 7);
|
||||
TEST_EQUAL(rq.start, 298);
|
||||
TEST_EQUAL(rq.length, 10);
|
||||
rq = fs.map_file(5, 0, 1000);
|
||||
TEST_EQUAL(rq.piece, 7);
|
||||
TEST_EQUAL(rq.start, 298);
|
||||
TEST_EQUAL(rq.length, 841);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -901,6 +901,8 @@ void test_fastresume(std::string const& test_path)
|
|||
boost::intrusive_ptr<torrent_info> t = ::create_torrent(&file);
|
||||
file.close();
|
||||
TEST_CHECK(exists(combine_path(test_path, "tmp1/temporary")));
|
||||
if (!exists(combine_path(test_path, "tmp1/temporary")))
|
||||
return;
|
||||
|
||||
entry resume;
|
||||
{
|
||||
|
@ -914,23 +916,37 @@ void test_fastresume(std::string const& test_path)
|
|||
p.save_path = combine_path(test_path, "tmp1");
|
||||
p.storage_mode = storage_mode_compact;
|
||||
torrent_handle h = ses.add_torrent(p, ec);
|
||||
TEST_CHECK(exists(combine_path(p.save_path, "temporary")));
|
||||
if (!exists(combine_path(p.save_path, "temporary")))
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 10; ++i)
|
||||
torrent_status s;
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
print_alerts(ses, "ses");
|
||||
test_sleep(1000);
|
||||
torrent_status s = h.status();
|
||||
s = h.status();
|
||||
if (s.progress == 1.0f)
|
||||
{
|
||||
std::cout << "progress: 1.0f" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the whole point of the test is to have a resume
|
||||
// data which expects the file to exist in full. If
|
||||
// we failed to do that, we might as well abort
|
||||
TEST_EQUAL(s.progress, 1.0f);
|
||||
if (s.progress != 1.0f)
|
||||
return;
|
||||
|
||||
// TODO: 3 don't use this deprecated function
|
||||
resume = h.write_resume_data();
|
||||
ses.remove_torrent(h, session::delete_files);
|
||||
}
|
||||
TEST_CHECK(!exists(combine_path(test_path, "tmp1/temporary")));
|
||||
if (exists(combine_path(test_path, "tmp1/temporary")))
|
||||
return;
|
||||
#if defined TORRENT_DEBUG && TORRENT_USE_IOSTREAM
|
||||
resume.print(std::cout);
|
||||
#endif
|
||||
|
@ -962,6 +978,7 @@ void test_fastresume(std::string const& test_path)
|
|||
assert(a.get());
|
||||
std::cerr << a->message() << std::endl;
|
||||
}
|
||||
// we expect the fast resume to be rejected because the files were removed
|
||||
TEST_CHECK(dynamic_cast<fastresume_rejected_alert*>(a.get()) != 0);
|
||||
}
|
||||
remove_all(combine_path(test_path, "tmp1"), ec);
|
||||
|
@ -1094,31 +1111,6 @@ int test_main()
|
|||
std::for_each(test_paths.begin(), test_paths.end(), boost::bind(&run_test, _1, true));
|
||||
std::for_each(test_paths.begin(), test_paths.end(), boost::bind(&run_test, _1, false));
|
||||
|
||||
file_storage fs;
|
||||
fs.set_piece_length(512);
|
||||
fs.add_file("temp_storage/test1.tmp", 17);
|
||||
fs.add_file("temp_storage/test2.tmp", 612);
|
||||
fs.add_file("temp_storage/test3.tmp", 0);
|
||||
fs.add_file("temp_storage/test4.tmp", 0);
|
||||
fs.add_file("temp_storage/test5.tmp", 3253);
|
||||
// size: 3882
|
||||
fs.add_file("temp_storage/test6.tmp", 841);
|
||||
// size: 4723
|
||||
|
||||
peer_request rq = fs.map_file(0, 0, 10);
|
||||
TEST_EQUAL(rq.piece, 0);
|
||||
TEST_EQUAL(rq.start, 0);
|
||||
TEST_EQUAL(rq.length, 10);
|
||||
rq = fs.map_file(5, 0, 10);
|
||||
TEST_EQUAL(rq.piece, 7);
|
||||
TEST_EQUAL(rq.start, 298);
|
||||
TEST_EQUAL(rq.length, 10);
|
||||
rq = fs.map_file(5, 0, 1000);
|
||||
TEST_EQUAL(rq.piece, 7);
|
||||
TEST_EQUAL(rq.start, 298);
|
||||
TEST_EQUAL(rq.length, 841);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue