Merge pull request #4917 from MarcZX100/codex/carry-directory-read-4912

fix(libkernel): fail reads on Windows directory descriptors
This commit is contained in:
Dean 2026-10-14 14:25:43 +13:00 committed by GitHub
commit 2e7ab67e8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 2 deletions

View File

@ -59,6 +59,10 @@ static int NativeRead(int fd, void* buf, std::size_t n) {
const auto positioned = File::LockPositionedTransfer(fd);
const int result = ::_read(fd, buf, static_cast<unsigned int>(n));
if (result < 0 && _doserrno == ERROR_NO_DATA) errno = EAGAIN;
if (result == 0 && File::DirectoryDescriptorPath(fd)) {
errno = EISDIR;
return -1;
}
return result;
}
static int NativeWrite(int fd, const void* buf, std::size_t n) {

View File

@ -213,7 +213,7 @@ std::int64_t NativePositioned_nid_no_patch(int descriptor, void* buf, std::size_
const auto positioned = File::LockPositionedTransfer(descriptor);
LARGE_INTEGER position{};
if (::GetFileType(handle) != FILE_TYPE_DISK || !::SetFilePointerEx(handle, LARGE_INTEGER{}, &position, FILE_CURRENT)) {
errno = ESPIPE;
errno = !File::DirectoryDescriptorPath(descriptor) ? ESPIPE : write ? EBADF : EISDIR;
return -1;
}
OVERLAPPED overlapped{};
@ -1078,6 +1078,7 @@ static std::int64_t TransferIovecs(int d, const KernelIovec* iov, int iovcnt, co
const auto result = offset != nullptr ? NativePositioned_nid_no_patch(d, &none, 0, *offset, write) : NativeTransfer(d, &none, 0, write);
return result < 0 ? SceErrorFromErrno(errno) : 0;
}
if (!write && offset == nullptr && File::DirectoryDescriptorPath(d)) return SceErrorFromErrno(GUEST_EISDIR);
const bool whole = write || offset != nullptr || NativeIsDisk(d);
std::int64_t done = 0;
for (int i = 0; i < iovcnt; ++i) {

View File

@ -52,6 +52,11 @@ 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);
std::int64_t APS5_VABI sceKernelRead(int, void*, std::size_t);
std::int64_t APS5_VABI sceKernelReadv(int, const void*, int);
std::int64_t APS5_VABI sceKernelPread(int, void*, std::size_t, std::int64_t);
std::int64_t APS5_VABI sceKernelPreadv(int, const void*, int, std::int64_t);
std::int64_t APS5_VABI sceKernelPwrite(int, const void*, std::size_t, std::int64_t);
int APS5_VABI sceKernelStat(const char*, FileStat*);
int APS5_VABI sceKernelCheckReachability(const char*);
int APS5_VABI sceKernelFstat(int, FileStat*);
@ -730,7 +735,18 @@ int main() {
Require(syncedLocked >= 0 && sceKernelFsync(syncedLocked) == 0 && close_nid_postfix(syncedLocked) == 0);
Require(sceKernelChmod_nid_postfix(presentName.c_str(), 0600) == 0);
const int directoryDescriptor = open_nid_postfix(rootName.c_str(), 0, 0);
Require(directoryDescriptor >= 0 && close_nid_postfix(directoryDescriptor) == 0);
Require(directoryDescriptor >= 0);
char directoryBytes[8]{};
struct { void* base; std::size_t length; } directoryVector[2] = {{directoryBytes, 3}, {directoryBytes + 3, 5}};
Require(read_nid_postfix(directoryDescriptor, directoryBytes, sizeof(directoryBytes)) == -1 && *__error_nid_postfix() == 21);
Require(sceKernelRead(directoryDescriptor, directoryBytes, sizeof(directoryBytes)) == static_cast<int>(0x80020015u));
Require(sceKernelReadv(directoryDescriptor, directoryVector, 2) == static_cast<int>(0x80020015u));
Require(sceKernelPread(directoryDescriptor, directoryBytes, sizeof(directoryBytes), 0) == static_cast<int>(0x80020015u));
Require(sceKernelPreadv(directoryDescriptor, directoryVector, 2, 0) == static_cast<int>(0x80020015u));
Require(sceKernelPwrite(directoryDescriptor, "x", 1, 0) == static_cast<int>(0x80020009u));
std::vector<char> listing(4096);
Require(sceKernelGetdents(directoryDescriptor, listing.data(), static_cast<int>(listing.size())) > 0);
Require(close_nid_postfix(directoryDescriptor) == 0);
const int flaggedDirectory = sceKernelOpen(rootName.c_str(), 0x20000, 0);
Require(flaggedDirectory >= 0 && sceKernelClose(flaggedDirectory) == 0);
std::vector<char> entries(4096);