From 52c2780283202668a09597d6d6539affd7c27f40 Mon Sep 17 00:00:00 2001 From: "Scott E. Graves" Date: Fri, 4 Apr 2025 10:02:37 -0500 Subject: [PATCH] [bug] Windows-to-Linux remote mount ignores CREATE_NEW #44 --- CHANGELOG.md | 1 + repertory/librepertory/include/common.hpp | 5 +- .../drives/fuse/remotefuse/remote_server.cpp | 83 ++++++++++--------- .../winfsp/remotewinfsp/remote_client.cpp | 28 +++---- 4 files changed, 62 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6afd2e44..b13926a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * ~~\#33 Complete initial v2.0 documentation~~ * \#42 [bug] Remote mount directory listing on Windows connected to Linux is failing * \#43 [bug] Directories are not importing properly for Sia +* \#44 [bug] Windows-to-Linux remote mount ignores `CREATE_NEW` ### Changes from v2.0.5-rc diff --git a/repertory/librepertory/include/common.hpp b/repertory/librepertory/include/common.hpp index 9774b3f4..9d7ff1f0 100644 --- a/repertory/librepertory/include/common.hpp +++ b/repertory/librepertory/include/common.hpp @@ -222,7 +222,6 @@ using WCHAR = wchar_t; #define MAX_PATH 260 -#define STATUS_SUCCESS std::uint32_t{0U} #define STATUS_ACCESS_DENIED std::uint32_t{0xC0000022L} #define STATUS_DEVICE_BUSY std::uint32_t{0x80000011L} #define STATUS_DEVICE_INSUFFICIENT_RESOURCES std::uint32_t{0xC0000468L} @@ -235,11 +234,13 @@ using WCHAR = wchar_t; #define STATUS_INVALID_HANDLE std::uint32_t{0xC0000006L} #define STATUS_INVALID_IMAGE_FORMAT std::uint32_t{0xC000007BL} #define STATUS_INVALID_PARAMETER std::uint32_t{0xC000000DL} -#define STATUS_NO_MEMORY std::uint32_t{0xC0000017L} #define STATUS_NOT_IMPLEMENTED std::uint32_t{0xC0000002L} +#define STATUS_NO_MEMORY std::uint32_t{0xC0000017L} +#define STATUS_OBJECT_NAME_COLLISION std::uint32_t{0xC0000035L} #define STATUS_OBJECT_NAME_EXISTS std::uint32_t{0x40000000L} #define STATUS_OBJECT_NAME_NOT_FOUND std::uint32_t{0xC0000034L} #define STATUS_OBJECT_PATH_INVALID std::uint32_t{0xC0000039L} +#define STATUS_SUCCESS std::uint32_t{0U} #define STATUS_UNEXPECTED_IO_ERROR std::uint32_t{0xC00000E9L} #define CONVERT_STATUS_NOT_IMPLEMENTED(e) \ diff --git a/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp b/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp index 0fc6e3cf..440991d3 100644 --- a/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp +++ b/repertory/librepertory/src/drives/fuse/remotefuse/remote_server.cpp @@ -1120,49 +1120,56 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options, -> packet::error_type { REPERTORY_USES_FUNCTION_NAME(); - const auto relative_path = utils::string::to_utf8(file_name); - const auto file_path = construct_path(relative_path); - exists = utils::file::file(file_path).exists(); + auto relative_path = utils::string::to_utf8(file_name); + auto file_path = construct_path(relative_path); + exists = utils::file::file{file_path}.exists() || + utils::file::directory{file_path}.exists(); - if ((create_options & FILE_DIRECTORY_FILE) != 0U) { - attributes |= FILE_ATTRIBUTE_DIRECTORY; + auto ret{static_cast(STATUS_SUCCESS)}; + if (exists) { + ret = static_cast(STATUS_OBJECT_NAME_COLLISION); } else { - attributes &= static_cast(~FILE_ATTRIBUTE_DIRECTORY); - attributes |= FILE_ATTRIBUTE_ARCHIVE; - } - - remote::file_mode mode{0U}; - std::uint32_t flags{0U}; - utils::windows_create_to_unix(create_options, granted_access, flags, mode); - - int res = 0; - if ((create_options & FILE_DIRECTORY_FILE) != 0U) { - res = mkdir(file_path.c_str(), mode); - if (res >= 0) { - res = open(file_path.c_str(), static_cast(flags)); + if ((create_options & FILE_DIRECTORY_FILE) != 0U) { + attributes |= FILE_ATTRIBUTE_DIRECTORY; + } else { + attributes &= static_cast(~FILE_ATTRIBUTE_DIRECTORY); + attributes |= FILE_ATTRIBUTE_ARCHIVE; } - } else { - res = open(file_path.c_str(), static_cast(flags), mode); + + remote::file_mode mode{0U}; + std::uint32_t flags{0U}; + utils::windows_create_to_unix(create_options, granted_access, flags, mode); + + int res = 0; + if ((create_options & FILE_DIRECTORY_FILE) != 0U) { + res = mkdir(file_path.c_str(), mode); + if (res >= 0) { + res = open(file_path.c_str(), static_cast(flags)); + } + } else { + res = open(file_path.c_str(), static_cast(flags), mode); + } + + if (res >= 0) { + *file_desc = reinterpret_cast(res); + drive_.set_item_meta(construct_api_path(file_path), META_ATTRIBUTES, + std::to_string(attributes)); + set_open_info(res, open_info{ + "", + nullptr, + {}, + file_path, + }); + + const auto api_path = utils::path::create_api_path(relative_path); + normalized_name = utils::string::replace_copy(api_path, '/', '\\'); + populate_file_info(api_path, 0, attributes, *file_info); + } + + ret = static_cast( + utils::unix_error_to_windows((res < 0) ? errno : 0)); } - if (res >= 0) { - *file_desc = reinterpret_cast(res); - drive_.set_item_meta(construct_api_path(file_path), META_ATTRIBUTES, - std::to_string(attributes)); - set_open_info(res, open_info{ - "", - nullptr, - {}, - file_path, - }); - - const auto api_path = utils::path::create_api_path(relative_path); - normalized_name = utils::string::replace_copy(api_path, '/', '\\'); - populate_file_info(api_path, 0, attributes, *file_info); - } - - auto ret = static_cast( - utils::unix_error_to_windows((res < 0) ? errno : 0)); RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret); return ret; } diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp index 71ec10f4..1f14696c 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp @@ -188,23 +188,21 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options, DECODE_OR_IGNORE(&response, normalized_name); DECODE_OR_IGNORE(&response, exists); - if (ret == STATUS_SUCCESS) { - *file_desc = reinterpret_cast(handle); - set_open_info(to_handle(*file_desc), - open_info{ - "", - nullptr, - {}, - utils::string::to_utf8(file_name), - }); -#if defined(_WIN32) - if (exists) { - ::SetLastError(ERROR_ALREADY_EXISTS); - } -#endif - } + *file_desc = reinterpret_cast(handle); + set_open_info(to_handle(*file_desc), open_info{ + "", + nullptr, + {}, + utils::string::to_utf8(file_name), + }); } +#if defined(_WIN32) + if (ret == STATUS_OBJECT_NAME_COLLISION && exists != 0U) { + ::SetLastError(ERROR_ALREADY_EXISTS); + } +#endif // defined(_WIN32) + return ret; }