This commit is contained in:
georgemoralis 2025-07-10 16:09:34 +05:30 committed by GitHub
commit eb00d0f2a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 71 additions and 6 deletions

View file

@ -11,11 +11,11 @@
#include "common/path_util.h" #include "common/path_util.h"
#ifdef _WIN32 #ifdef _WIN32
#include "common/ntapi.h" #include <fcntl.h>
#include <io.h> #include <io.h>
#include <share.h> #include <share.h>
#include <windows.h> #include <windows.h>
#include "common/ntapi.h"
#else #else
#include <unistd.h> #include <unistd.h>
#endif #endif
@ -172,8 +172,11 @@ IOFile& IOFile::operator=(IOFile&& other) noexcept {
int IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) { int IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) {
Close(); Close();
#ifdef _WIN32
file_path = RemoveTrailingSeparator(path);
#else
file_path = path; file_path = path;
#endif
file_access_mode = mode; file_access_mode = mode;
file_type = type; file_type = type;
@ -193,9 +196,22 @@ int IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileS
#endif #endif
if (!IsOpen()) { if (!IsOpen()) {
#ifdef _WIN32
file = OpenDirAsFilePtr(
path.c_str(), AccessModeToWStr(mode, type),
fs::is_directory(
path)); // this can't be used with fread, fwrite etc . Let's hope it will not needed
result = errno;
if (!IsOpen()) {
const auto ec = std::error_code{result, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, error_message={}",
PathToUTF8String(file_path), ec.message());
}
#else
const auto ec = std::error_code{result, std::generic_category()}; const auto ec = std::error_code{result, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, error_message={}", LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, error_message={}",
PathToUTF8String(file_path), ec.message()); PathToUTF8String(file_path), ec.message());
#endif
} }
return result; return result;
@ -415,5 +431,44 @@ u64 GetDirectorySize(const std::filesystem::path& path) {
} }
return total; return total;
} }
#ifdef _WIN32
FILE* OpenDirAsFilePtr(const wchar_t* path, const wchar_t* mode, bool isDirectory = false) {
DWORD access = 0;
DWORD creation = OPEN_EXISTING;
DWORD flags = FILE_ATTRIBUTE_NORMAL;
DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
// Handle access based on mode
if (wcschr(mode, L'r'))
access |= GENERIC_READ;
if (wcschr(mode, L'w') || wcschr(mode, L'a'))
access |= GENERIC_WRITE;
// Add backup semantics if this is a directory
if (isDirectory) {
flags |= FILE_FLAG_BACKUP_SEMANTICS;
}
HANDLE hFile = CreateFileW(path, access, share, nullptr, creation, flags, nullptr);
if (hFile == INVALID_HANDLE_VALUE) {
return nullptr;
}
int fd = _open_osfhandle((intptr_t)hFile, _O_BINARY);
if (fd == -1) {
CloseHandle(hFile);
return nullptr;
}
FILE* file = _fdopen(fd, (wcschr(mode, L'w') || wcschr(mode, L'a')) ? "wb" : "rb");
if (!file) {
_close(fd);
return nullptr;
}
return file;
}
#endif
} // namespace Common::FS } // namespace Common::FS

View file

@ -213,7 +213,15 @@ public:
IOFile out(path, FileAccessMode::Write); IOFile out(path, FileAccessMode::Write);
return out.Write(data); return out.Write(data);
} }
#ifdef _WIN32
std::filesystem::path RemoveTrailingSeparator(const std::filesystem::path& input) {
std::wstring str = input.native();
while (!str.empty() && (str.back() == L'\\' || str.back() == L'/')) {
str.pop_back();
}
return std::filesystem::path(str);
}
#endif
private: private:
std::filesystem::path file_path; std::filesystem::path file_path;
FileAccessMode file_access_mode{}; FileAccessMode file_access_mode{};
@ -224,5 +232,7 @@ private:
}; };
u64 GetDirectorySize(const std::filesystem::path& path); u64 GetDirectorySize(const std::filesystem::path& path);
#ifdef _WIN32
FILE* OpenDirAsFilePtr(const wchar_t* path, const wchar_t* mode, bool isDirectory);
#endif
} // namespace Common::FS } // namespace Common::FS

View file

@ -168,7 +168,7 @@ s32 PS4_SYSV_ABI open(const char* raw_path, s32 flags, u16 mode) {
return -1; return -1;
} }
if (e == EACCES) { if (e == EACCES || e == ENOENT) {
// Hack to bypass some platform limitations, ignore the error and continue as normal. // Hack to bypass some platform limitations, ignore the error and continue as normal.
LOG_WARNING(Kernel_Fs, "Opening directories is not fully supported on this platform"); LOG_WARNING(Kernel_Fs, "Opening directories is not fully supported on this platform");
e = 0; e = 0;