From 8284b4dd0658828c63b04c889869c3ba5ff91828 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Tue, 19 Aug 2025 20:21:00 +0900 Subject: [PATCH] lib: chunkio: update to 98988d25 Signed-off-by: Hiroshi Hatake --- lib/chunkio/src/CMakeLists.txt | 3 +- lib/chunkio/src/cio_os.c | 69 +++++++++++++++++++++++++++++++++- lib/chunkio/src/win32/dirent.c | 22 ++++++++++- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/lib/chunkio/src/CMakeLists.txt b/lib/chunkio/src/CMakeLists.txt index bb52273d494..3590143fd05 100644 --- a/lib/chunkio/src/CMakeLists.txt +++ b/lib/chunkio/src/CMakeLists.txt @@ -23,8 +23,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") ) set(libs ${libs} - Shell32.lib - Shlwapi.lib) + Shell32.lib) else() set(src ${src} diff --git a/lib/chunkio/src/cio_os.c b/lib/chunkio/src/cio_os.c index 0adbc617ce8..637b74e4bee 100644 --- a/lib/chunkio/src/cio_os.c +++ b/lib/chunkio/src/cio_os.c @@ -49,6 +49,73 @@ int cio_os_isdir(const char *dir) return -1; } +#ifdef _WIN32 +static int cio_os_win32_make_recursive_path(const char* path) { + char dir[MAX_PATH]; + char* p; + size_t len; + size_t root_len = 0; + size_t i = 0, seps = 0; + char saved; + + if (_fullpath(dir, path, MAX_PATH) == NULL) { + return 1; + } + + /* Normalize to backslashes */ + for (p = dir; *p; p++) { + if (*p == '/') { + *p = '\\'; + } + } + + len = strlen(dir); + + /* Determine root length: "C:\" (3) or UNC root "\\server\share\" */ + if (len >= 2 && + ((dir[0] >= 'A' && dir[0] <= 'Z') || (dir[0] >= 'a' && dir[0] <= 'z')) && + dir[1] == ':') { + root_len = (len >= 3 && dir[2] == '\\') ? 3 : 2; + } + else if (len >= 5 && dir[0] == '\\' && dir[1] == '\\') { + /* Skip server and share components: \\server\share\ */ + i = 2; + while (i < len && seps < 2) { + if (dir[i] == '\\') { + seps++; + } + i++; + } + root_len = i; /* points just past "\\server\share\" */ + } + + /* Create each intermediate component after the root */ + for (p = dir + root_len; *p; p++) { + if (*p == '\\') { + saved = *p; + *p = '\0'; + if (!CreateDirectoryA(dir, NULL)) { + DWORD err = GetLastError(); + if (err != ERROR_ALREADY_EXISTS) { + *p = saved; + return 1; + } + } + *p = saved; + } + } + + /* Create the final directory */ + if (!CreateDirectoryA(dir, NULL)) { + DWORD err = GetLastError(); + if (err != ERROR_ALREADY_EXISTS) { + return 1; + } + } + return 0; +} +#endif + /* Create directory */ int cio_os_mkpath(const char *dir, mode_t mode) { @@ -85,7 +152,7 @@ int cio_os_mkpath(const char *dir, mode_t mode) return 1; } - if (SHCreateDirectoryExA(NULL, path, NULL) != ERROR_SUCCESS) { + if (cio_os_win32_make_recursive_path(path) != ERROR_SUCCESS) { return 1; } return 0; diff --git a/lib/chunkio/src/win32/dirent.c b/lib/chunkio/src/win32/dirent.c index 6ea57f9626a..020943d0eac 100644 --- a/lib/chunkio/src/win32/dirent.c +++ b/lib/chunkio/src/win32/dirent.c @@ -23,7 +23,6 @@ */ #include -#include #include "dirent.h" @@ -75,11 +74,30 @@ static char *create_pattern(const char *path) return buf; } +/** + * @brief Checks if a given path string refers to an existing directory. + * @param pszPath The null-terminated string that contains the path. + * @return Returns TRUE if the path is a directory, otherwise FALSE. + */ +BOOL path_is_directory(LPCSTR pszPath) { + DWORD dwAttrib = GetFileAttributesA(pszPath); + + if (dwAttrib == INVALID_FILE_ATTRIBUTES) { + return FALSE; + } + + if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) { + return TRUE; + } + + return FALSE; +} + struct CIO_WIN32_DIR *cio_win32_opendir(const char *path) { struct CIO_WIN32_DIR *d; - if (!PathIsDirectoryA(path)) { + if (!path_is_directory(path)) { return NULL; }