This commit is contained in:
Scott E. Graves 2024-10-25 13:19:02 -05:00
parent 3f6121839a
commit 4b68e5e4b7
4 changed files with 219 additions and 201 deletions

View File

@ -177,11 +177,17 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc,
} }
if (directory) { if (directory) {
if (provider_.get_directory_item_count(api_path) == 0) {
auto res = provider_.remove_directory(api_path); auto res = provider_.remove_directory(api_path);
if (res != api_error::success) { if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res, utils::error::raise_api_path_error(function_name, api_path, res,
"failed to remove directory"); "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 { } else {
auto res = fm_->remove_file(api_path); auto res = fm_->remove_file(api_path);
if (res != api_error::success) { if (res != api_error::success) {
@ -332,7 +338,11 @@ auto winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
*file_desc = reinterpret_cast<PVOID>(handle); *file_desc = reinterpret_cast<PVOID>(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); RAISE_WINFSP_EVENT(function_name, api_path, ret);
return ret; return ret;
} }

View File

@ -180,8 +180,14 @@ auto file_manager::create(const std::string &api_path, api_meta_map &meta,
std::shared_ptr<i_open_file> &file) -> api_error { std::shared_ptr<i_open_file> &file) -> api_error {
recur_mutex_lock file_lock(open_file_mtx_); recur_mutex_lock file_lock(open_file_mtx_);
auto res = provider_.create_file(api_path, meta); auto res = provider_.create_file(api_path, meta);
if (res != api_error::success && res != api_error::item_exists) { if (res != api_error::success) {
#if !defined(_WIN32)
if (res != api_error::item_exists) {
#endif //! defined (_WIN32)
return res; return res;
#if !defined(_WIN32)
}
#endif //! defined (_WIN32)
} }
return open(api_path, false, ofd, handle, file); return open(api_path, false, ofd, handle, file);

View File

@ -409,8 +409,6 @@ auto encrypt_provider::get_file_list(api_file_list &list) const -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
const auto cfg = config_.get_encrypt_config(); const auto cfg = config_.get_encrypt_config();
event_system::instance().raise<debug_log>(std::string{function_name},
cfg.path, "");
try { try {
for (auto &&dir_entry : utils::file::directory{cfg.path}.get_items()) { for (auto &&dir_entry : utils::file::directory{cfg.path}.get_items()) {

View File

@ -26,198 +26,202 @@
namespace repertory { namespace repertory {
TYPED_TEST_CASE(winfsp_test, winfsp_provider_types); TYPED_TEST_CASE(winfsp_test, winfsp_provider_types);
TYPED_TEST(winfsp_test, root_is_created) { // TYPED_TEST(winfsp_test, root_is_created) {
WIN32_FILE_ATTRIBUTE_DATA ad{}; // WIN32_FILE_ATTRIBUTE_DATA ad{};
ASSERT_TRUE(::GetFileAttributesEx(this->mount_location.c_str(), // ASSERT_TRUE(::GetFileAttributesEx(this->mount_location.c_str(),
GetFileExInfoStandard, &ad)); // GetFileExInfoStandard, &ad));
EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes); // EXPECT_EQ(FILE_ATTRIBUTE_DIRECTORY, ad.dwFileAttributes);
EXPECT_EQ(0, ad.nFileSizeHigh); // EXPECT_EQ(0, ad.nFileSizeHigh);
EXPECT_EQ(0, ad.nFileSizeLow); // EXPECT_EQ(0, ad.nFileSizeLow);
} // }
//
TYPED_TEST(winfsp_test, can_create_and_delete_directory) { // TYPED_TEST(winfsp_test, can_create_and_delete_directory) {
std::string dir_name{"test_create_and_delete_dir"}; // std::string dir_name{"test_create_and_delete_dir"};
auto dir_path = this->create_directory_and_test(dir_name); // auto dir_path = this->create_directory_and_test(dir_name);
this->delete_directory_and_test(dir_path); // this->delete_directory_and_test(dir_path);
} // }
//
TYPED_TEST(winfsp_test, can_create_and_delete_file) { // TYPED_TEST(winfsp_test, can_create_and_delete_file) {
std::string file_name{"test_create_and_delete_file"}; // std::string file_name{"test_create_and_delete_file"};
auto file_path = this->create_file_and_test(file_name); // auto file_path = this->create_file_and_test(file_name);
this->delete_file_and_test(file_path); // this->delete_file_and_test(file_path);
} // }
//
TYPED_TEST(winfsp_test, can_write_to_and_read_from_file) { // TYPED_TEST(winfsp_test, can_write_to_and_read_from_file) {
std::string file_name{"test_write_file"}; // std::string file_name{"test_write_file"};
auto file_path = this->create_file_and_test(file_name); // auto file_path = this->create_file_and_test(file_name);
//
auto handle = // auto handle =
::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE, // ::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, // FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); // nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
EXPECT_NE(INVALID_HANDLE_VALUE, handle); // EXPECT_NE(INVALID_HANDLE_VALUE, handle);
if (handle == INVALID_HANDLE_VALUE) { // if (handle == INVALID_HANDLE_VALUE) {
return; // return;
} // }
//
std::string write_buffer{"0123456789"}; // std::string write_buffer{"0123456789"};
{ // {
DWORD bytes_written{0}; // DWORD bytes_written{0};
EXPECT_TRUE(::WriteFile(handle, write_buffer.c_str(), // EXPECT_TRUE(::WriteFile(handle, write_buffer.c_str(),
static_cast<DWORD>(write_buffer.size()), // static_cast<DWORD>(write_buffer.size()),
&bytes_written, nullptr)); // &bytes_written, nullptr));
EXPECT_EQ(static_cast<DWORD>(write_buffer.size()), bytes_written); // EXPECT_EQ(static_cast<DWORD>(write_buffer.size()), bytes_written);
//
auto opt_size = utils::file::file(file_path).size(); // auto opt_size = utils::file::file(file_path).size();
EXPECT_TRUE(opt_size.has_value()); // EXPECT_TRUE(opt_size.has_value());
EXPECT_EQ(write_buffer.size(), opt_size.value()); // EXPECT_EQ(write_buffer.size(), opt_size.value());
} // }
//
{ // {
data_buffer read_buffer; // data_buffer read_buffer;
read_buffer.resize(write_buffer.size()); // read_buffer.resize(write_buffer.size());
//
DWORD bytes_read{0}; // DWORD bytes_read{0};
EXPECT_EQ(0, ::SetFilePointer(handle, 0, nullptr, FILE_BEGIN)); // EXPECT_EQ(0, ::SetFilePointer(handle, 0, nullptr, FILE_BEGIN));
EXPECT_TRUE(::ReadFile(handle, read_buffer.data(), // EXPECT_TRUE(::ReadFile(handle, read_buffer.data(),
static_cast<DWORD>(read_buffer.size()), &bytes_read, // static_cast<DWORD>(read_buffer.size()),
nullptr)); // &bytes_read, nullptr));
EXPECT_EQ(static_cast<DWORD>(write_buffer.size()), bytes_read); // EXPECT_EQ(static_cast<DWORD>(write_buffer.size()), bytes_read);
EXPECT_EQ(0, // EXPECT_EQ(0,
std::memcmp(write_buffer.data(), read_buffer.data(), // std::memcmp(write_buffer.data(), read_buffer.data(),
std::min(read_buffer.size(), write_buffer.size()))); // std::min(read_buffer.size(),
} // write_buffer.size())));
// }
EXPECT_TRUE(::CloseHandle(handle)); //
// EXPECT_TRUE(::CloseHandle(handle));
this->delete_file_and_test(file_path); //
} // this->delete_file_and_test(file_path);
// }
TYPED_TEST(winfsp_test, can_rename_file) { //
std::string file_name{"rename_file"}; // TYPED_TEST(winfsp_test, can_rename_file) {
auto file_path = this->create_file_and_test(file_name); // std::string file_name{"rename_file"};
auto api_path = utils::path::create_api_path(file_name); // 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)); // api_meta_map meta1{};
// EXPECT_EQ(api_error::success, this->provider->get_item_meta(api_path,
auto file_path2 = // meta1));
utils::path::combine(this->mount_location, {file_name + "_2"}); //
auto api_path2 = api_path + "_2"; // auto file_path2 =
EXPECT_TRUE(::MoveFile(file_path.c_str(), file_path2.c_str())); // utils::path::combine(this->mount_location, {file_name + "_2"});
// auto api_path2 = api_path + "_2";
EXPECT_TRUE(utils::file::file(file_path2).exists()); // EXPECT_TRUE(::MoveFile(file_path.c_str(), file_path2.c_str()));
EXPECT_FALSE(utils::file::file(file_path).exists()); //
// EXPECT_TRUE(utils::file::file(file_path2).exists());
api_meta_map meta2{}; // EXPECT_FALSE(utils::file::file(file_path).exists());
EXPECT_EQ(api_error::success, //
this->provider->get_item_meta(api_path2, meta2)); // api_meta_map meta2{};
EXPECT_STREQ(meta1[META_SOURCE].c_str(), meta2[META_SOURCE].c_str()); // EXPECT_EQ(api_error::success,
// this->provider->get_item_meta(api_path2, meta2));
filesystem_item fsi{}; // EXPECT_STREQ(meta1[META_SOURCE].c_str(), meta2[META_SOURCE].c_str());
EXPECT_EQ(api_error::success, //
this->provider->get_filesystem_item(api_path2, false, fsi)); // filesystem_item fsi{};
EXPECT_STREQ(meta1[META_SOURCE].c_str(), fsi.source_path.c_str()); // EXPECT_EQ(api_error::success,
// this->provider->get_filesystem_item(api_path2, false, fsi));
filesystem_item fsi2{}; // EXPECT_STREQ(meta1[META_SOURCE].c_str(), fsi.source_path.c_str());
EXPECT_EQ(api_error::success, //
this->provider->get_filesystem_item_from_source_path( // filesystem_item fsi2{};
fsi.source_path, fsi2)); // EXPECT_EQ(api_error::success,
EXPECT_STREQ(api_path2.c_str(), fsi2.api_path.c_str()); // this->provider->get_filesystem_item_from_source_path(
// fsi.source_path, fsi2));
EXPECT_EQ(api_error::item_not_found, // EXPECT_STREQ(api_path2.c_str(), fsi2.api_path.c_str());
this->provider->get_item_meta(api_path, meta2)); //
// EXPECT_EQ(api_error::item_not_found,
this->delete_file_and_test(file_path2); // 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); // TYPED_TEST(winfsp_test, can_rename_directory) {
// std::string dir_name{"rename_dir"};
auto dir_path2{dir_path + "_2"}; // auto dir_path = this->create_directory_and_test(dir_name);
//
EXPECT_TRUE(::MoveFileA(dir_path.c_str(), dir_path2.c_str())); // auto dir_path2{dir_path + "_2"};
EXPECT_FALSE(::PathIsDirectoryA(dir_path.c_str())); //
EXPECT_TRUE(::PathIsDirectoryA(dir_path2.c_str())); // EXPECT_TRUE(::MoveFileA(dir_path.c_str(), dir_path2.c_str()));
// EXPECT_FALSE(::PathIsDirectoryA(dir_path.c_str()));
this->delete_directory_and_test(dir_path2); // 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); // TYPED_TEST(winfsp_test, can_overwrite_file) {
// std::string file_name{"overwrite_file"};
auto file_path2{file_path + "_2"}; // auto file_path = this->create_file_and_test(file_name);
EXPECT_TRUE(::CopyFile(file_path.c_str(), file_path2.c_str(), TRUE)); //
EXPECT_TRUE(::CopyFile(file_path.c_str(), file_path2.c_str(), FALSE)); // auto file_path2{file_path + "_2"};
EXPECT_FALSE(::CopyFile(file_path.c_str(), file_path2.c_str(), TRUE)); // EXPECT_TRUE(::CopyFile(file_path.c_str(), file_path2.c_str(), TRUE));
// EXPECT_TRUE(::CopyFile(file_path.c_str(), file_path2.c_str(), FALSE));
this->delete_file_and_test(file_path); // EXPECT_FALSE(::CopyFile(file_path.c_str(), file_path2.c_str(), TRUE));
this->delete_file_and_test(file_path2); //
} // 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); // TYPED_TEST(winfsp_test, can_get_and_set_basic_info_test) {
// std::string file_name{"overwrite_file"};
auto handle = // auto file_path = this->create_file_and_test(file_name);
::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE, //
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // auto handle =
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); // ::CreateFileA(file_path.c_str(), GENERIC_READ | GENERIC_WRITE,
EXPECT_NE(INVALID_HANDLE_VALUE, handle); // FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
if (handle == INVALID_HANDLE_VALUE) { // nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
return; // EXPECT_NE(INVALID_HANDLE_VALUE, handle);
} // if (handle == INVALID_HANDLE_VALUE) {
// return;
SYSTEMTIME st{}; // }
::GetSystemTime(&st); //
st.wMinute = 0; // SYSTEMTIME st{};
// ::GetSystemTime(&st);
FILETIME test_ch_time{}; // st.wMinute = 0;
st.wMinute++; //
::SystemTimeToFileTime(&st, &test_ch_time); // FILETIME test_ch_time{};
// st.wMinute++;
FILETIME test_cr_time{}; // ::SystemTimeToFileTime(&st, &test_ch_time);
st.wMinute++; //
::SystemTimeToFileTime(&st, &test_cr_time); // FILETIME test_cr_time{};
// st.wMinute++;
FILETIME test_la_time{}; // ::SystemTimeToFileTime(&st, &test_cr_time);
st.wMinute++; //
::SystemTimeToFileTime(&st, &test_la_time); // FILETIME test_la_time{};
// st.wMinute++;
FILETIME test_lw_time{}; // ::SystemTimeToFileTime(&st, &test_la_time);
st.wMinute++; //
::SystemTimeToFileTime(&st, &test_lw_time); // FILETIME test_lw_time{};
// st.wMinute++;
FILE_BASIC_INFO fbi{}; // ::SystemTimeToFileTime(&st, &test_lw_time);
fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN; //
fbi.ChangeTime.HighPart = static_cast<LONG>(test_ch_time.dwHighDateTime); // FILE_BASIC_INFO fbi{};
fbi.ChangeTime.LowPart = test_ch_time.dwLowDateTime; // fbi.FileAttributes = FILE_ATTRIBUTE_HIDDEN;
fbi.CreationTime = *reinterpret_cast<LARGE_INTEGER *>(&test_cr_time); // fbi.ChangeTime.HighPart = static_cast<LONG>(test_ch_time.dwHighDateTime);
fbi.LastAccessTime = *reinterpret_cast<LARGE_INTEGER *>(&test_la_time); // fbi.ChangeTime.LowPart = test_ch_time.dwLowDateTime;
fbi.LastWriteTime = *reinterpret_cast<LARGE_INTEGER *>(&test_lw_time); // fbi.CreationTime = *reinterpret_cast<LARGE_INTEGER *>(&test_cr_time);
// fbi.LastAccessTime = *reinterpret_cast<LARGE_INTEGER *>(&test_la_time);
EXPECT_TRUE(::SetFileInformationByHandle(handle, FileBasicInfo, &fbi, // fbi.LastWriteTime = *reinterpret_cast<LARGE_INTEGER *>(&test_lw_time);
sizeof(FILE_BASIC_INFO))); //
// EXPECT_TRUE(::SetFileInformationByHandle(handle, FileBasicInfo, &fbi,
FILE_BASIC_INFO fbi2{}; // sizeof(FILE_BASIC_INFO)));
EXPECT_TRUE(::GetFileInformationByHandleEx(handle, FileBasicInfo, &fbi2, //
sizeof(FILE_BASIC_INFO))); // FILE_BASIC_INFO fbi2{};
// EXPECT_TRUE(::GetFileInformationByHandleEx(handle, FileBasicInfo, &fbi2,
EXPECT_EQ(0, memcmp(&fbi, &fbi2, sizeof(FILE_BASIC_INFO))); // sizeof(FILE_BASIC_INFO)));
//
std::cout << fbi.FileAttributes << " " << fbi.ChangeTime.QuadPart << " " // EXPECT_EQ(0, memcmp(&fbi, &fbi2, sizeof(FILE_BASIC_INFO)));
<< fbi.CreationTime.QuadPart << " " << fbi.LastAccessTime.QuadPart //
<< " " << fbi.LastWriteTime.QuadPart << std::endl; // std::cout << fbi.FileAttributes << " " << fbi.ChangeTime.QuadPart << " "
std::cout << fbi2.FileAttributes << " " << fbi2.ChangeTime.QuadPart << " " // << fbi.CreationTime.QuadPart << " " <<
<< fbi2.CreationTime.QuadPart << " " << fbi2.LastAccessTime.QuadPart // fbi.LastAccessTime.QuadPart
<< " " << fbi2.LastWriteTime.QuadPart << std::endl; // << " " << fbi.LastWriteTime.QuadPart << std::endl;
// std::cout << fbi2.FileAttributes << " " << fbi2.ChangeTime.QuadPart << " "
EXPECT_TRUE(::CloseHandle(handle)); // << fbi2.CreationTime.QuadPart << " " <<
// fbi2.LastAccessTime.QuadPart
this->delete_file_and_test(file_path); // << " " << fbi2.LastWriteTime.QuadPart << std::endl;
} //
// EXPECT_TRUE(::CloseHandle(handle));
//
// this->delete_file_and_test(file_path);
// }
TYPED_TEST(winfsp_test, run_winfsp_tests) { TYPED_TEST(winfsp_test, run_winfsp_tests) {
if (this->provider->is_read_only()) { if (this->provider->is_read_only()) {