diff --git a/Source/utils/file_util.cpp b/Source/utils/file_util.cpp index 9a5ac9141..be82e5499 100644 --- a/Source/utils/file_util.cpp +++ b/Source/utils/file_util.cpp @@ -87,75 +87,100 @@ std::string_view Dirname(std::string_view path) return std::string_view { path.data(), sep }; } -bool FileExists(const char *path) -{ #ifdef _WIN32 +namespace { +DWORD WindowsGetFileAttributes(const char *path) +{ #ifdef DEVILUTIONX_WINDOWS_NO_WCHAR - const bool exists = ::GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES; + const DWORD attr = ::GetFileAttributesA(path); #else const auto pathUtf16 = ToWideChar(path); if (pathUtf16 == nullptr) { LogError("UTF-8 -> UTF-16 conversion error code {}", ::GetLastError()); return false; } - const bool exists = ::PathFileExistsW(&pathUtf16[0]); + const DWORD attr = ::GetFileAttributesW(&pathUtf16[0]); #endif - if (!exists) { + if (attr == INVALID_FILE_ATTRIBUTES) { if (::GetLastError() == ERROR_FILE_NOT_FOUND || ::GetLastError() == ERROR_PATH_NOT_FOUND) { ::SetLastError(ERROR_SUCCESS); } else { #ifdef DEVILUTIONX_WINDOWS_NO_WCHAR - LogError("GetFileAttributesA({}): error code {}", path, ::GetLastError()); + LogError("GetFileAttributesA: error code {}", ::GetLastError()); #else - LogError("PathFileExistsW({}): error code {}", path, ::GetLastError()); + LogError("GetFileAttributesW: error code {}", ::GetLastError()); #endif } - return false; } - return true; -#elif defined(DVL_HAS_POSIX_2001) && !defined(__ANDROID__) - return ::access(path, F_OK) == 0; -#elif defined(DVL_HAS_FILESYSTEM) - std::error_code ec; - return std::filesystem::exists(reinterpret_cast(path), ec); + return attr; +} + +#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR +bool WindowsFindFile(const char *path) #else - SDL_IOStream *file = SDL_IOFromFile(path, "rb"); - if (file == nullptr) return false; - SDL_CloseIO(file); - return true; +bool WindowsFindFile(const wchar_t *path) +#endif +{ +#ifdef DEVILUTIONX_WINDOWS_NO_WCHAR + WIN32_FIND_DATAA findFileData; + HANDLE hFind = FindFirstFileA(path, &findFileData); +#else + WIN32_FIND_DATAW findFileData; + HANDLE hFind = FindFirstFileW(path, &findFileData); #endif + if (hFind == INVALID_HANDLE_VALUE) { + return false; + } + FindClose(hFind); + return true; } -#ifdef _WIN32 -namespace { -DWORD WindowsGetFileAttributes(const char *path) +bool WindowsFileExists(const char *path) { #ifdef DEVILUTIONX_WINDOWS_NO_WCHAR - const DWORD attr = ::GetFileAttributesA(path); + const bool exists = ::GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES; #else const auto pathUtf16 = ToWideChar(path); if (pathUtf16 == nullptr) { LogError("UTF-8 -> UTF-16 conversion error code {}", ::GetLastError()); return false; } - const DWORD attr = ::GetFileAttributesW(&pathUtf16[0]); + const bool exists = ::PathFileExistsW(&pathUtf16[0]); #endif - if (attr == INVALID_FILE_ATTRIBUTES) { - if (::GetLastError() == ERROR_FILE_NOT_FOUND || ::GetLastError() == ERROR_PATH_NOT_FOUND) { - ::SetLastError(ERROR_SUCCESS); - } else { + if (exists) { + return true; + } + if (::GetLastError() == ERROR_FILE_NOT_FOUND || ::GetLastError() == ERROR_PATH_NOT_FOUND) { + ::SetLastError(ERROR_SUCCESS); + return false; + } #ifdef DEVILUTIONX_WINDOWS_NO_WCHAR - LogError("GetFileAttributesA: error code {}", ::GetLastError()); + LogError("GetFileAttributesA({}): error code {}", path, ::GetLastError()); + return WindowsFindFile(path); #else - LogError("GetFileAttributesW: error code {}", ::GetLastError()); + LogError("PathFileExistsW({}): error code {}", path, ::GetLastError()); + return WindowsFindFile(pathUtf16.get()); #endif - } - } - return attr; } } // namespace +#endif +bool FileExists(const char *path) +{ +#ifdef _WIN32 + return WindowsFileExists(path); +#elif defined(DVL_HAS_POSIX_2001) && !defined(__ANDROID__) && !defined(_WIN32) + return ::access(path, F_OK) == 0; +#elif defined(DVL_HAS_FILESYSTEM) && !defined(_WIN32) + std::error_code ec; + return std::filesystem::exists(reinterpret_cast(path), ec); +#else + SDL_IOStream *file = SDL_IOFromFile(path, "rb"); + if (file == nullptr) return false; + SDL_CloseIO(file); + return true; #endif +} bool DirectoryExists(const char *path) {