[bug] Windows-to-Linux remote mount ignores CREATE_NEW #44
This commit is contained in:
		| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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)                                      \ | ||||
|   | ||||
| @@ -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<packet::error_type>(STATUS_SUCCESS)}; | ||||
|   if (exists) { | ||||
|     ret = static_cast<packet::error_type>(STATUS_OBJECT_NAME_COLLISION); | ||||
|   } else { | ||||
|     attributes &= static_cast<UINT32>(~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<int>(flags)); | ||||
|     if ((create_options & FILE_DIRECTORY_FILE) != 0U) { | ||||
|       attributes |= FILE_ATTRIBUTE_DIRECTORY; | ||||
|     } else { | ||||
|       attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_DIRECTORY); | ||||
|       attributes |= FILE_ATTRIBUTE_ARCHIVE; | ||||
|     } | ||||
|   } else { | ||||
|     res = open(file_path.c_str(), static_cast<int>(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<int>(flags)); | ||||
|       } | ||||
|     } else { | ||||
|       res = open(file_path.c_str(), static_cast<int>(flags), mode); | ||||
|     } | ||||
|  | ||||
|     if (res >= 0) { | ||||
|       *file_desc = reinterpret_cast<PVOID>(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<packet::error_type>( | ||||
|         utils::unix_error_to_windows((res < 0) ? errno : 0)); | ||||
|   } | ||||
|  | ||||
|   if (res >= 0) { | ||||
|     *file_desc = reinterpret_cast<PVOID>(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<packet::error_type>( | ||||
|       utils::unix_error_to_windows((res < 0) ? errno : 0)); | ||||
|   RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret); | ||||
|   return ret; | ||||
| } | ||||
|   | ||||
| @@ -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<PVOID>(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<PVOID>(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; | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user