diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c937a2c..a816202 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,15 +15,20 @@ jobs: max-parallel: 48 fail-fast: false matrix: - os: [windows-latest, windows-2019] + os: [windows-2025, windows-2022] steps: - uses: actions/checkout@v2 - - name: Build on ${{ matrix.os }} with vs-2019 + - name: Set up with Developer Command Prompt for Microsoft Visual C++ + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: amd64 + - name: Build on ${{ matrix.os }} with MSVC run: | - .\scripts\win_build.bat + cmake -G "NMake Makefiles" -DCIO_TESTS=On . + cmake --build . - name: Run unit tests. run: | - ctest --rerun-failed --output-on-failure -C Debug --test-dir . + ctest . --rerun-failed --output-on-failure --test-dir . build-unix: name: Build sources on amd64 for ${{ matrix.os }} - ${{ matrix.compiler }} runs-on: ${{ matrix.os }} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bb52273..3590143 100644 --- a/src/CMakeLists.txt +++ b/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/src/cio_os.c b/src/cio_os.c index 0adbc61..c4e6c89 100644 --- a/src/cio_os.c +++ b/src/cio_os.c @@ -49,6 +49,45 @@ int cio_os_isdir(const char *dir) return -1; } +#ifdef _WIN32 +inline int cio_os_win32_make_recursive_path(const char* path) { + char dir[MAX_PATH]; + char* p = NULL; + + if (_fullpath(dir, path, MAX_PATH) == NULL) { + return 1; + } + + for (p = dir; *p; p++) { + /* Skip the drive letter (e.g., "C:") */ + if (p > dir && *p == ':' && *(p - 1) != '\0') { + continue; + } + + if (*p == '\\' || *p == '/') { + char original_char = *p; + *p = '\0'; + + if (!CreateDirectoryA(dir, NULL)) { + if (GetLastError() != ERROR_ALREADY_EXISTS) { + *p = original_char; + return 1; + } + } + *p = original_char; + } + } + + if (!CreateDirectoryA(dir, NULL)) { + if (GetLastError() != ERROR_ALREADY_EXISTS) { + return 1; + } + } + + return 0; +} +#endif + /* Create directory */ int cio_os_mkpath(const char *dir, mode_t mode) { @@ -85,7 +124,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/src/win32/dirent.c b/src/win32/dirent.c index 6ea57f9..020943d 100644 --- a/src/win32/dirent.c +++ b/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; }