diff --git a/repertory/librepertory/include/file_manager/file_manager.hpp b/repertory/librepertory/include/file_manager/file_manager.hpp index 498eaf17..56ac87b4 100644 --- a/repertory/librepertory/include/file_manager/file_manager.hpp +++ b/repertory/librepertory/include/file_manager/file_manager.hpp @@ -176,6 +176,8 @@ public: const open_file_data &ofd, std::uint64_t &handle, std::shared_ptr &file) -> api_error; + [[nodiscard]] auto remove_directory(const std::string &api_path) -> api_error; + [[nodiscard]] auto remove_file(const std::string &api_path) -> api_error; [[nodiscard]] auto rename_directory(const std::string &from_api_path, diff --git a/repertory/librepertory/src/drives/fuse/fuse_drive.cpp b/repertory/librepertory/src/drives/fuse/fuse_drive.cpp index d8d4560f..4ace5b1d 100644 --- a/repertory/librepertory/src/drives/fuse/fuse_drive.cpp +++ b/repertory/librepertory/src/drives/fuse/fuse_drive.cpp @@ -931,12 +931,12 @@ auto fuse_drive::rmdir_impl(std::string api_path) -> api_error { return res; } - res = provider_.remove_directory(api_path); + res = fm_->remove_directory(api_path); if (res != api_error::success) { return res; } - auto iter = directory_cache_->remove_directory(api_path); + directory_cache_->remove_directory(api_path); return api_error::success; } diff --git a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp index 8bfc1798..bd722c0b 100644 --- a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp +++ b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp @@ -216,15 +216,11 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc, FspFileSystemDeleteDirectoryBuffer(&directory_buffer); } - if (not directory) { - return handle_error(fm_->remove_file(api_path)); + if (directory) { + return handle_error(fm_->remove_directory(api_path)); } - if (provider_.get_directory_item_count(api_path) == 0) { - return handle_error(provider_.remove_directory(api_path)); - } - - return handle_error(api_error::directory_not_empty); + return handle_error(fm_->remove_file(api_path)); } if (((flags & FspCleanupSetArchiveBit) != 0U) && not directory) { diff --git a/repertory/librepertory/src/file_manager/file_manager.cpp b/repertory/librepertory/src/file_manager/file_manager.cpp index cc615183..55376260 100644 --- a/repertory/librepertory/src/file_manager/file_manager.cpp +++ b/repertory/librepertory/src/file_manager/file_manager.cpp @@ -101,6 +101,10 @@ void file_manager::close(std::uint64_t handle) { closeable_file->close(); + if (closeable_file->is_directory()) { + return; + } + auto file = utils::file::file{closeable_file->get_source_path()}; if (file.remove()) { return; @@ -689,9 +693,41 @@ void file_manager::queue_upload(const std::string &api_path, } } +auto file_manager::remove_directory(const std::string &api_path) -> api_error { + REPERTORY_USES_FUNCTION_NAME(); + + unique_recur_mutex_lock open_lock(open_file_mtx_); + if (provider_.get_directory_item_count(api_path) != 0) { + return api_error::directory_not_empty; + } + + auto res = provider_.remove_directory(api_path); + if (res != api_error::success) { + return res; + } + + auto file_iter = open_file_lookup_.find(api_path); + if (file_iter == open_file_lookup_.end()) { + return api_error::success; + } + + auto closed_file = file_iter->second; + open_file_lookup_.erase(api_path); + + closed_file->set_unlinked(true); + for (const auto &[handle, ofd] : closed_file->get_open_data()) { + unlinked_file_lookup_[handle] = closed_file; + } + open_lock.unlock(); + + return api_error::success; +} + auto file_manager::remove_file(const std::string &api_path) -> api_error { REPERTORY_USES_FUNCTION_NAME(); + unique_recur_mutex_lock open_lock(open_file_mtx_); + filesystem_item fsi{}; auto res = provider_.get_filesystem_item(api_path, false, fsi); if (res != api_error::success) { @@ -704,8 +740,6 @@ auto file_manager::remove_file(const std::string &api_path) -> api_error { return res; } - unique_recur_mutex_lock open_lock(open_file_mtx_); - unique_mutex_lock upload_lock(upload_mtx_); remove_upload(api_path, true); remove_resume(api_path, fsi.source_path, true); diff --git a/repertory/repertory_test/src/fuse_drive_directory_test.cpp b/repertory/repertory_test/src/fuse_drive_directory_test.cpp index 22088085..9c8bcb1d 100644 --- a/repertory/repertory_test/src/fuse_drive_directory_test.cpp +++ b/repertory/repertory_test/src/fuse_drive_directory_test.cpp @@ -115,6 +115,11 @@ TYPED_TEST(fuse_test, directory_can_opendir_after_closedir) { } TYPED_TEST(fuse_test, directory_rmdir_on_non_empty_directory_should_fail) { + if (this->current_provider == provider_type::encrypt) { + GTEST_SKIP(); + return; + } + std::string dir_name{"non_empty"}; auto dir = this->create_directory_and_test(dir_name);