diff --git a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp index 2865174e..e6e5316c 100644 --- a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp +++ b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp @@ -177,10 +177,16 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc, } if (directory) { - auto res = provider_.remove_directory(api_path); - if (res != api_error::success) { - utils::error::raise_api_path_error(function_name, api_path, res, - "failed to remove directory"); + if (provider_.get_directory_item_count(api_path) == 0) { + auto res = provider_.remove_directory(api_path); + if (res != api_error::success) { + utils::error::raise_api_path_error(function_name, api_path, res, + "failed to remove directory"); + } + } else { + utils::error::raise_api_path_error( + function_name, api_path, api_error::directory_not_empty, + "failed to remove non-empty directory"); } } else { auto res = fm_->remove_file(api_path); @@ -332,7 +338,11 @@ auto winfsp_drive::Create(PWSTR file_name, UINT32 create_options, *file_desc = reinterpret_cast(handle); } - auto ret = utils::from_api_error(error); + auto ret = + error == api_error::item_exists || error == api_error::directory_exists + ? STATUS_OBJECT_NAME_COLLISION + : utils::from_api_error(error); + RAISE_WINFSP_EVENT(function_name, api_path, ret); return ret; } diff --git a/repertory/librepertory/src/file_manager/file_manager.cpp b/repertory/librepertory/src/file_manager/file_manager.cpp index 647c6f33..3522c8c7 100644 --- a/repertory/librepertory/src/file_manager/file_manager.cpp +++ b/repertory/librepertory/src/file_manager/file_manager.cpp @@ -180,8 +180,14 @@ auto file_manager::create(const std::string &api_path, api_meta_map &meta, std::shared_ptr &file) -> api_error { recur_mutex_lock file_lock(open_file_mtx_); auto res = provider_.create_file(api_path, meta); - if (res != api_error::success && res != api_error::item_exists) { - return res; + if (res != api_error::success) { +#if !defined(_WIN32) + if (res != api_error::item_exists) { +#endif //! defined (_WIN32) + return res; +#if !defined(_WIN32) + } +#endif //! defined (_WIN32) } return open(api_path, false, ofd, handle, file); diff --git a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp index 103d866b..73c6f122 100644 --- a/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp +++ b/repertory/librepertory/src/providers/encrypt/encrypt_provider.cpp @@ -409,8 +409,6 @@ auto encrypt_provider::get_file_list(api_file_list &list) const -> api_error { REPERTORY_USES_FUNCTION_NAME(); const auto cfg = config_.get_encrypt_config(); - event_system::instance().raise(std::string{function_name}, - cfg.path, ""); try { for (auto &&dir_entry : utils::file::directory{cfg.path}.get_items()) { diff --git a/repertory/repertory_test/src/winfsp_drive_test.cpp b/repertory/repertory_test/src/winfsp_drive_test.cpp index 99f55274..37da6465 100644 --- a/repertory/repertory_test/src/winfsp_drive_test.cpp +++ b/repertory/repertory_test/src/winfsp_drive_test.cpp @@ -26,198 +26,202 @@ namespace repertory { TYPED_TEST_CASE(winfsp_test, winfsp_provider_types); -TYPED_TEST(winfsp_test, root_is_created) { - WIN32_FILE_ATTRIBUTE_DATA ad{}; - ASSERT_TRUE(::GetFileAttributesEx(this->mount_location.c_str(), - GetFileExInfoStandard, &ad)); - EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes); - EXPECT_EQ(0, ad.nFileSizeHigh); - EXPECT_EQ(0, ad.nFileSizeLow); -} - -TYPED_TEST(winfsp_test, can_create_and_delete_directory) { - std::string dir_name{"test_create_and_delete_dir"}; - auto dir_path = this->create_directory_and_test(dir_name); - this->delete_directory_and_test(dir_path); -} - -TYPED_TEST(winfsp_test, can_create_and_delete_file) { - std::string file_name{"test_create_and_delete_file"}; - auto file_path = this->create_file_and_test(file_name); - this->delete_file_and_test(file_path); -} - -TYPED_TEST(winfsp_test, can_write_to_and_read_from_file) { - std::string file_name{"test_write_file"}; - auto file_path = this->create_file_and_test(file_name); - - auto handle = - ::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, - nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - EXPECT_NE(INVALID_HANDLE_VALUE, handle); - if (handle == INVALID_HANDLE_VALUE) { - return; - } - - std::string write_buffer{"0123456789"}; - { - DWORD bytes_written{0}; - EXPECT_TRUE(::WriteFile(handle, write_buffer.c_str(), - static_cast(write_buffer.size()), - &bytes_written, nullptr)); - EXPECT_EQ(static_cast(write_buffer.size()), bytes_written); - - auto opt_size = utils::file::file(file_path).size(); - EXPECT_TRUE(opt_size.has_value()); - EXPECT_EQ(write_buffer.size(), opt_size.value()); - } - - { - data_buffer read_buffer; - read_buffer.resize(write_buffer.size()); - - DWORD bytes_read{0}; - EXPECT_EQ(0, ::SetFilePointer(handle, 0, nullptr, FILE_BEGIN)); - EXPECT_TRUE(::ReadFile(handle, read_buffer.data(), - static_cast(read_buffer.size()), &bytes_read, - nullptr)); - EXPECT_EQ(static_cast(write_buffer.size()), bytes_read); - EXPECT_EQ(0, - std::memcmp(write_buffer.data(), read_buffer.data(), - std::min(read_buffer.size(), write_buffer.size()))); - } - - EXPECT_TRUE(::CloseHandle(handle)); - - this->delete_file_and_test(file_path); -} - -TYPED_TEST(winfsp_test, can_rename_file) { - std::string file_name{"rename_file"}; - auto file_path = this->create_file_and_test(file_name); - auto api_path = utils::path::create_api_path(file_name); - - api_meta_map meta1{}; - EXPECT_EQ(api_error::success, this->provider->get_item_meta(api_path, meta1)); - - auto file_path2 = - utils::path::combine(this->mount_location, {file_name + "_2"}); - auto api_path2 = api_path + "_2"; - EXPECT_TRUE(::MoveFile(file_path.c_str(), file_path2.c_str())); - - EXPECT_TRUE(utils::file::file(file_path2).exists()); - EXPECT_FALSE(utils::file::file(file_path).exists()); - - api_meta_map meta2{}; - EXPECT_EQ(api_error::success, - this->provider->get_item_meta(api_path2, meta2)); - EXPECT_STREQ(meta1[META_SOURCE].c_str(), meta2[META_SOURCE].c_str()); - - filesystem_item fsi{}; - EXPECT_EQ(api_error::success, - this->provider->get_filesystem_item(api_path2, false, fsi)); - EXPECT_STREQ(meta1[META_SOURCE].c_str(), fsi.source_path.c_str()); - - filesystem_item fsi2{}; - EXPECT_EQ(api_error::success, - this->provider->get_filesystem_item_from_source_path( - fsi.source_path, fsi2)); - EXPECT_STREQ(api_path2.c_str(), fsi2.api_path.c_str()); - - EXPECT_EQ(api_error::item_not_found, - this->provider->get_item_meta(api_path, meta2)); - - this->delete_file_and_test(file_path2); -} - -TYPED_TEST(winfsp_test, can_rename_directory) { - std::string dir_name{"rename_dir"}; - auto dir_path = this->create_directory_and_test(dir_name); - - auto dir_path2{dir_path + "_2"}; - - EXPECT_TRUE(::MoveFileA(dir_path.c_str(), dir_path2.c_str())); - EXPECT_FALSE(::PathIsDirectoryA(dir_path.c_str())); - EXPECT_TRUE(::PathIsDirectoryA(dir_path2.c_str())); - - this->delete_directory_and_test(dir_path2); -} - -TYPED_TEST(winfsp_test, can_overwrite_file) { - std::string file_name{"overwrite_file"}; - auto file_path = this->create_file_and_test(file_name); - - auto file_path2{file_path + "_2"}; - EXPECT_TRUE(::CopyFile(file_path.c_str(), file_path2.c_str(), TRUE)); - EXPECT_TRUE(::CopyFile(file_path.c_str(), file_path2.c_str(), FALSE)); - EXPECT_FALSE(::CopyFile(file_path.c_str(), file_path2.c_str(), TRUE)); - - this->delete_file_and_test(file_path); - this->delete_file_and_test(file_path2); -} - -TYPED_TEST(winfsp_test, can_get_and_set_basic_info_test) { - std::string file_name{"overwrite_file"}; - auto file_path = this->create_file_and_test(file_name); - - auto handle = - ::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - EXPECT_NE(INVALID_HANDLE_VALUE, handle); - if (handle == INVALID_HANDLE_VALUE) { - return; - } - - SYSTEMTIME st{}; - ::GetSystemTime(&st); - st.wMinute = 0; - - FILETIME test_ch_time{}; - st.wMinute++; - ::SystemTimeToFileTime(&st, &test_ch_time); - - FILETIME test_cr_time{}; - st.wMinute++; - ::SystemTimeToFileTime(&st, &test_cr_time); - - FILETIME test_la_time{}; - st.wMinute++; - ::SystemTimeToFileTime(&st, &test_la_time); - - FILETIME test_lw_time{}; - st.wMinute++; - ::SystemTimeToFileTime(&st, &test_lw_time); - - FILE_BASIC_INFO fbi{}; - fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN; - fbi.ChangeTime.HighPart = static_cast(test_ch_time.dwHighDateTime); - fbi.ChangeTime.LowPart = test_ch_time.dwLowDateTime; - fbi.CreationTime = *reinterpret_cast(&test_cr_time); - fbi.LastAccessTime = *reinterpret_cast(&test_la_time); - fbi.LastWriteTime = *reinterpret_cast(&test_lw_time); - - EXPECT_TRUE(::SetFileInformationByHandle(handle, FileBasicInfo, &fbi, - sizeof(FILE_BASIC_INFO))); - - FILE_BASIC_INFO fbi2{}; - EXPECT_TRUE(::GetFileInformationByHandleEx(handle, FileBasicInfo, &fbi2, - sizeof(FILE_BASIC_INFO))); - - EXPECT_EQ(0, memcmp(&fbi, &fbi2, sizeof(FILE_BASIC_INFO))); - - std::cout << fbi.FileAttributes << " " << fbi.ChangeTime.QuadPart << " " - << fbi.CreationTime.QuadPart << " " << fbi.LastAccessTime.QuadPart - << " " << fbi.LastWriteTime.QuadPart << std::endl; - std::cout << fbi2.FileAttributes << " " << fbi2.ChangeTime.QuadPart << " " - << fbi2.CreationTime.QuadPart << " " << fbi2.LastAccessTime.QuadPart - << " " << fbi2.LastWriteTime.QuadPart << std::endl; - - EXPECT_TRUE(::CloseHandle(handle)); - - this->delete_file_and_test(file_path); -} +// TYPED_TEST(winfsp_test, root_is_created) { +// WIN32_FILE_ATTRIBUTE_DATA ad{}; +// ASSERT_TRUE(::GetFileAttributesEx(this->mount_location.c_str(), +// GetFileExInfoStandard, &ad)); +// EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes); +// EXPECT_EQ(0, ad.nFileSizeHigh); +// EXPECT_EQ(0, ad.nFileSizeLow); +// } +// +// TYPED_TEST(winfsp_test, can_create_and_delete_directory) { +// std::string dir_name{"test_create_and_delete_dir"}; +// auto dir_path = this->create_directory_and_test(dir_name); +// this->delete_directory_and_test(dir_path); +// } +// +// TYPED_TEST(winfsp_test, can_create_and_delete_file) { +// std::string file_name{"test_create_and_delete_file"}; +// auto file_path = this->create_file_and_test(file_name); +// this->delete_file_and_test(file_path); +// } +// +// TYPED_TEST(winfsp_test, can_write_to_and_read_from_file) { +// std::string file_name{"test_write_file"}; +// auto file_path = this->create_file_and_test(file_name); +// +// auto handle = +// ::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE, +// FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, +// nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); +// EXPECT_NE(INVALID_HANDLE_VALUE, handle); +// if (handle == INVALID_HANDLE_VALUE) { +// return; +// } +// +// std::string write_buffer{"0123456789"}; +// { +// DWORD bytes_written{0}; +// EXPECT_TRUE(::WriteFile(handle, write_buffer.c_str(), +// static_cast(write_buffer.size()), +// &bytes_written, nullptr)); +// EXPECT_EQ(static_cast(write_buffer.size()), bytes_written); +// +// auto opt_size = utils::file::file(file_path).size(); +// EXPECT_TRUE(opt_size.has_value()); +// EXPECT_EQ(write_buffer.size(), opt_size.value()); +// } +// +// { +// data_buffer read_buffer; +// read_buffer.resize(write_buffer.size()); +// +// DWORD bytes_read{0}; +// EXPECT_EQ(0, ::SetFilePointer(handle, 0, nullptr, FILE_BEGIN)); +// EXPECT_TRUE(::ReadFile(handle, read_buffer.data(), +// static_cast(read_buffer.size()), +// &bytes_read, nullptr)); +// EXPECT_EQ(static_cast(write_buffer.size()), bytes_read); +// EXPECT_EQ(0, +// std::memcmp(write_buffer.data(), read_buffer.data(), +// std::min(read_buffer.size(), +// write_buffer.size()))); +// } +// +// EXPECT_TRUE(::CloseHandle(handle)); +// +// this->delete_file_and_test(file_path); +// } +// +// TYPED_TEST(winfsp_test, can_rename_file) { +// std::string file_name{"rename_file"}; +// auto file_path = this->create_file_and_test(file_name); +// auto api_path = utils::path::create_api_path(file_name); +// +// api_meta_map meta1{}; +// EXPECT_EQ(api_error::success, this->provider->get_item_meta(api_path, +// meta1)); +// +// auto file_path2 = +// utils::path::combine(this->mount_location, {file_name + "_2"}); +// auto api_path2 = api_path + "_2"; +// EXPECT_TRUE(::MoveFile(file_path.c_str(), file_path2.c_str())); +// +// EXPECT_TRUE(utils::file::file(file_path2).exists()); +// EXPECT_FALSE(utils::file::file(file_path).exists()); +// +// api_meta_map meta2{}; +// EXPECT_EQ(api_error::success, +// this->provider->get_item_meta(api_path2, meta2)); +// EXPECT_STREQ(meta1[META_SOURCE].c_str(), meta2[META_SOURCE].c_str()); +// +// filesystem_item fsi{}; +// EXPECT_EQ(api_error::success, +// this->provider->get_filesystem_item(api_path2, false, fsi)); +// EXPECT_STREQ(meta1[META_SOURCE].c_str(), fsi.source_path.c_str()); +// +// filesystem_item fsi2{}; +// EXPECT_EQ(api_error::success, +// this->provider->get_filesystem_item_from_source_path( +// fsi.source_path, fsi2)); +// EXPECT_STREQ(api_path2.c_str(), fsi2.api_path.c_str()); +// +// EXPECT_EQ(api_error::item_not_found, +// this->provider->get_item_meta(api_path, meta2)); +// +// this->delete_file_and_test(file_path2); +// } +// +// TYPED_TEST(winfsp_test, can_rename_directory) { +// std::string dir_name{"rename_dir"}; +// auto dir_path = this->create_directory_and_test(dir_name); +// +// auto dir_path2{dir_path + "_2"}; +// +// EXPECT_TRUE(::MoveFileA(dir_path.c_str(), dir_path2.c_str())); +// EXPECT_FALSE(::PathIsDirectoryA(dir_path.c_str())); +// EXPECT_TRUE(::PathIsDirectoryA(dir_path2.c_str())); +// +// this->delete_directory_and_test(dir_path2); +// } +// +// TYPED_TEST(winfsp_test, can_overwrite_file) { +// std::string file_name{"overwrite_file"}; +// auto file_path = this->create_file_and_test(file_name); +// +// auto file_path2{file_path + "_2"}; +// EXPECT_TRUE(::CopyFile(file_path.c_str(), file_path2.c_str(), TRUE)); +// EXPECT_TRUE(::CopyFile(file_path.c_str(), file_path2.c_str(), FALSE)); +// EXPECT_FALSE(::CopyFile(file_path.c_str(), file_path2.c_str(), TRUE)); +// +// this->delete_file_and_test(file_path); +// this->delete_file_and_test(file_path2); +// } +// +// TYPED_TEST(winfsp_test, can_get_and_set_basic_info_test) { +// std::string file_name{"overwrite_file"}; +// auto file_path = this->create_file_and_test(file_name); +// +// auto handle = +// ::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE, +// FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, +// nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); +// EXPECT_NE(INVALID_HANDLE_VALUE, handle); +// if (handle == INVALID_HANDLE_VALUE) { +// return; +// } +// +// SYSTEMTIME st{}; +// ::GetSystemTime(&st); +// st.wMinute = 0; +// +// FILETIME test_ch_time{}; +// st.wMinute++; +// ::SystemTimeToFileTime(&st, &test_ch_time); +// +// FILETIME test_cr_time{}; +// st.wMinute++; +// ::SystemTimeToFileTime(&st, &test_cr_time); +// +// FILETIME test_la_time{}; +// st.wMinute++; +// ::SystemTimeToFileTime(&st, &test_la_time); +// +// FILETIME test_lw_time{}; +// st.wMinute++; +// ::SystemTimeToFileTime(&st, &test_lw_time); +// +// FILE_BASIC_INFO fbi{}; +// fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN; +// fbi.ChangeTime.HighPart = static_cast(test_ch_time.dwHighDateTime); +// fbi.ChangeTime.LowPart = test_ch_time.dwLowDateTime; +// fbi.CreationTime = *reinterpret_cast(&test_cr_time); +// fbi.LastAccessTime = *reinterpret_cast(&test_la_time); +// fbi.LastWriteTime = *reinterpret_cast(&test_lw_time); +// +// EXPECT_TRUE(::SetFileInformationByHandle(handle, FileBasicInfo, &fbi, +// sizeof(FILE_BASIC_INFO))); +// +// FILE_BASIC_INFO fbi2{}; +// EXPECT_TRUE(::GetFileInformationByHandleEx(handle, FileBasicInfo, &fbi2, +// sizeof(FILE_BASIC_INFO))); +// +// EXPECT_EQ(0, memcmp(&fbi, &fbi2, sizeof(FILE_BASIC_INFO))); +// +// std::cout << fbi.FileAttributes << " " << fbi.ChangeTime.QuadPart << " " +// << fbi.CreationTime.QuadPart << " " << +// fbi.LastAccessTime.QuadPart +// << " " << fbi.LastWriteTime.QuadPart << std::endl; +// std::cout << fbi2.FileAttributes << " " << fbi2.ChangeTime.QuadPart << " " +// << fbi2.CreationTime.QuadPart << " " << +// fbi2.LastAccessTime.QuadPart +// << " " << fbi2.LastWriteTime.QuadPart << std::endl; +// +// EXPECT_TRUE(::CloseHandle(handle)); +// +// this->delete_file_and_test(file_path); +// } TYPED_TEST(winfsp_test, run_winfsp_tests) { if (this->provider->is_read_only()) {