diff --git a/src/file.cpp b/src/file.cpp index 93f1e93f2..e49b453c8 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -468,7 +468,7 @@ namespace libtorrent if (::rename(f1.c_str(), f2.c_str()) < 0) #endif { - ec.assign(errno, system_category()); + ec.assign(errno, generic_category()); return; } } diff --git a/src/storage.cpp b/src/storage.cpp index 1ee74249d..ae509695b 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -1209,9 +1209,13 @@ namespace libtorrent e.clear(); rename(old_path, new_path, e); // if the source file doesn't exist. That's not a problem + // we just ignore that file if (e == boost::system::errc::no_such_file_or_directory) e.clear(); + // on OSX, the error when trying to rename a file across different + // volumes is EXDEV, which will make it fall back to copying. + if (e) { if (flags == dont_replace && e == boost::system::errc::file_exists) @@ -1220,6 +1224,15 @@ namespace libtorrent continue; } + if (e == boost::system::errc::invalid_argument + || e == boost::system::errc::permission_denied) + { + ec.ec = e; + ec.file = i->second; + ec.operation = storage_error::rename; + break; + } + if (e != boost::system::errc::no_such_file_or_directory) { e.clear(); diff --git a/test/test_storage.cpp b/test/test_storage.cpp index 0a898e3d5..3c975b0e4 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -122,11 +122,11 @@ boost::shared_ptr setup_torrent(file_storage& fs , std::string const& test_path , aux::session_settings& set) { - fs.add_file("temp_storage/test1.tmp", 8); - fs.add_file("temp_storage/folder1/test2.tmp", 8); - fs.add_file("temp_storage/folder2/test3.tmp", 0); - fs.add_file("temp_storage/_folder3/test4.tmp", 0); - fs.add_file("temp_storage/_folder3/subfolder/test5.tmp", 8); + fs.add_file(combine_path("temp_storage", "test1.tmp"), 8); + fs.add_file(combine_path("temp_storage", combine_path("folder1", "test2.tmp")), 8); + fs.add_file(combine_path("temp_storage", combine_path("folder2", "test3.tmp")), 0); + fs.add_file(combine_path("temp_storage", combine_path("_folder3", "test4.tmp")), 0); + fs.add_file(combine_path("temp_storage", combine_path("_folder3", combine_path("subfolder", "test5.tmp"))), 8); libtorrent::create_torrent t(fs, 4, -1, 0); char buf_[4] = {0, 0, 0, 0}; @@ -1251,3 +1251,29 @@ TORRENT_TEST(readwritev_zero_size_files) TEST_CHECK(check_pattern(buf, 0)); } +TORRENT_TEST(move_storage_into_self) +{ + aux::session_settings set; + file_storage fs; + std::vector buf; + file_pool fp; + io_service ios; + disk_buffer_pool dp(16 * 1024, ios, boost::bind(&nop)); + boost::shared_ptr s = setup_torrent(fs, fp, buf + , current_working_directory() + , set); + + file::iovec_t b = {&buf[0], 4}; + storage_error se; + s->writev(&b, 1, 2, 0, 0, se); + + s->move_storage(combine_path("temp_storage", "folder1"), 0, se); + + printf("move error: %s\n", se.ec.message().c_str()); +#ifdef _WIN32 + TEST_EQUAL(se.ec, boost::system::errc::permission_denied); +#else + TEST_EQUAL(se.ec, boost::system::errc::invalid_argument); +#endif +} +