diff --git a/ChangeLog b/ChangeLog index 1f78f335c..c0343d2b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,7 @@ 0.16.8 release + * make rename_file create missing directories for new filename * added missing python function: parse_magnet_uri * fix alerts.all_categories in python binding * fix torrent-abort issue which would cancel name lookups of other torrents diff --git a/src/storage.cpp b/src/storage.cpp index 48e7a6687..7078f22f4 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -503,8 +503,23 @@ namespace libtorrent m_pool.release(this, index); error_code ec; - rename(old_name, combine_path(m_save_path, new_filename), ec); + std::string 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 + // lands in + create_directories(new_dir, ec); + if (ec) + { + set_error(new_dir, ec); + return true; + } + + rename(old_name, new_path, ec); + // if old_name doesn't exist, that's not an error + // here. Once we start writing to the file, it will + // be written to the new filename if (ec && ec != boost::system::errc::no_such_file_or_directory) { set_error(old_name, ec); diff --git a/test/test_storage.cpp b/test/test_storage.cpp index 908482c9f..857841c60 100644 --- a/test/test_storage.cpp +++ b/test/test_storage.cpp @@ -547,13 +547,23 @@ void run_storage_tests(boost::intrusive_ptr info // test rename_file remove(combine_path(test_path, "part0"), ec); if (ec) std::cerr << "remove: " << ec.message() << std::endl; + remove_all(combine_path(test_path, "test_dir"), ec); + if (ec) std::cerr << "remove: " << ec.message() << std::endl; TEST_CHECK(exists(combine_path(test_path, "temp_storage/test1.tmp"))); TEST_CHECK(!exists(combine_path(test_path, "part0"))); - boost::function none; + TEST_CHECK(!exists(combine_path(test_path, "test_dir/subdir/part0"))); + + // test that we can create missing directories when we rename a file + done = false; + pm->async_rename_file(0, "test_dir/subdir/part0", boost::bind(&signal_bool, &done, "rename_file")); + run_until(ios, done); + TEST_CHECK(!exists(combine_path(test_path, "temp_storage/test1.tmp"))); + TEST_CHECK(!exists(combine_path(test_path, "temp_storage2"))); + TEST_CHECK(exists(combine_path(test_path, "test_dir/subdir/part0"))); + done = false; pm->async_rename_file(0, "part0", boost::bind(&signal_bool, &done, "rename_file")); run_until(ios, done); - TEST_CHECK(!exists(combine_path(test_path, "temp_storage/test1.tmp"))); TEST_CHECK(!exists(combine_path(test_path, "temp_storage2"))); TEST_CHECK(exists(combine_path(test_path, "part0")));