diff --git a/core/libs/prx/libkernel/File/src/Open.cpp b/core/libs/prx/libkernel/File/src/Open.cpp index eebabd5e4..dc0dcad58 100644 --- a/core/libs/prx/libkernel/File/src/Open.cpp +++ b/core/libs/prx/libkernel/File/src/Open.cpp @@ -169,12 +169,14 @@ static int OpenNative(const std::filesystem::path& native, int flags, std::uint1 #endif int fd = NativeOpen(native, MapFlags(flags), mode); #ifdef _WIN32 - if (fd < 0 && errno != ENOENT) { + if (fd < 0 && (errno != ENOENT || !native.has_filename())) { + auto directory = native; + while (!directory.has_filename() && directory.has_relative_path()) directory = directory.parent_path(); std::error_code error; - if (std::filesystem::is_directory(native, error)) { + if (std::filesystem::is_directory(directory, error)) { if ((flags & (SCE_KERNEL_O_CREAT | SCE_KERNEL_O_EXCL)) == (SCE_KERNEL_O_CREAT | SCE_KERNEL_O_EXCL)) errno = EEXIST; else if ((flags & SCE_KERNEL_O_ACCMODE) != SCE_KERNEL_O_RDONLY || (flags & (SCE_KERNEL_O_CREAT | SCE_KERNEL_O_TRUNC))) errno = EISDIR; - else fd = File::OpenDirectoryDescriptor(native); + else fd = File::OpenDirectoryDescriptor(directory); } } #endif diff --git a/core/libs/tests/GuestFilesystem.cpp b/core/libs/tests/GuestFilesystem.cpp index f759e12d3..9c5ba0108 100644 --- a/core/libs/tests/GuestFilesystem.cpp +++ b/core/libs/tests/GuestFilesystem.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #ifdef _WIN32 #include #include @@ -48,6 +50,7 @@ int APS5_VABI rmdir_nid_postfix(const char*); int APS5_VABI mkdir_nid_postfix(const char*, unsigned short); int APS5_VABI sceKernelOpen(const char*, int, unsigned short); int APS5_VABI sceKernelClose(int); +int APS5_VABI sceKernelGetdents(int, char*, int); int APS5_VABI sceKernelStat(const char*, FileStat*); int APS5_VABI sceKernelCheckReachability(const char*); int APS5_VABI sceKernelFstat(int, FileStat*); @@ -567,6 +570,15 @@ int main() { Require(directoryDescriptor >= 0 && close_nid_postfix(directoryDescriptor) == 0); const int flaggedDirectory = sceKernelOpen(rootName.c_str(), 0x20000, 0); Require(flaggedDirectory >= 0 && sceKernelClose(flaggedDirectory) == 0); + std::vector entries(4096); + for (const auto& directoryName : {std::string("/"), std::string("."), rootName + "/", rootName + "/.."}) { + const int listed = sceKernelOpen(directoryName.c_str(), 0x20000, 0); + Require(listed >= 0); + int read = sceKernelGetdents(listed, entries.data(), static_cast(entries.size())); + Require(read > 0); + while (read > 0) read = sceKernelGetdents(listed, entries.data(), static_cast(entries.size())); + Require(read == 0 && sceKernelClose(listed) == 0); + } Require(open_nid_postfix(presentName.c_str(), 0x20000, 0) == -1 && *__error_nid_postfix() == 20); Require(sceKernelOpen(presentName.c_str(), 0x20000, 0) == static_cast(0x80020014u)); Require(sceKernelOpen(presentName.c_str(), 0x20402, 0) == static_cast(0x80020014u));