From 665e6f17822fd010d16005cb7f64bf02245462cb Mon Sep 17 00:00:00 2001 From: David Date: Tue, 13 Oct 2026 02:40:04 +0400 Subject: [PATCH] fix(libkernel): fill every buffer of readv from a pipe on Windows --- core/libs/prx/libkernel/File/src/Stdio.cpp | 8 +++++++- core/libs/tests/GuestFileVector.cpp | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libkernel/File/src/Stdio.cpp b/core/libs/prx/libkernel/File/src/Stdio.cpp index 71550eb1c..2855e6194 100644 --- a/core/libs/prx/libkernel/File/src/Stdio.cpp +++ b/core/libs/prx/libkernel/File/src/Stdio.cpp @@ -218,6 +218,12 @@ static bool NativeIsDisk(int descriptor) { const auto handle = reinterpret_cast(::_get_osfhandle(descriptor)); return handle != INVALID_HANDLE_VALUE && ::GetFileType(handle) == FILE_TYPE_DISK; } +static bool NativePipeHasData(int descriptor) { + const auto handle = reinterpret_cast(::_get_osfhandle(descriptor)); + DWORD available = 0; + return handle != INVALID_HANDLE_VALUE && ::GetFileType(handle) == FILE_TYPE_PIPE + && ::PeekNamedPipe(handle, nullptr, 0, nullptr, &available, nullptr) && available != 0; +} static std::int64_t NativePread(int descriptor, void* buf, std::size_t nbytes, std::int64_t offset) { return NativePositioned_nid_no_patch(descriptor, buf, nbytes, offset, false); } @@ -1003,7 +1009,7 @@ static std::int64_t TransferIovecs(int d, const KernelIovec* iov, int iovcnt, co if (result < 0) return done != 0 ? done : SceErrorFromErrno(errno); done += result; position += static_cast(result); - if (static_cast(result) < chunk || !whole) return done; + if (static_cast(result) < chunk || (!whole && !NativePipeHasData(d))) return done; } } return done; diff --git a/core/libs/tests/GuestFileVector.cpp b/core/libs/tests/GuestFileVector.cpp index 370be6be8..eda9297d8 100644 --- a/core/libs/tests/GuestFileVector.cpp +++ b/core/libs/tests/GuestFileVector.cpp @@ -206,6 +206,15 @@ int main() { Require(sceKernelWritev(ends[1], message, 1) == 3); Require(sceKernelReadv(ends[0], reads, 2) == 3); Require(std::memcmp(first, "xyz", 3) == 0); + char stuvw[] = "stuvw"; + GuestIovec longer[1] = {{stuvw, 5}}; + Require(sceKernelWritev(ends[1], longer, 1) == 5); + Require(sceKernelReadv(ends[0], reads, 2) == 5); + Require(std::memcmp(first, "stu", 3) == 0 && std::memcmp(second, "vw", 2) == 0); + Require(sceKernelWritev(ends[1], longer, 1) == 5 && sceKernelWritev(ends[1], longer, 1) == 5); + Require(readv_nid_postfix(ends[0], reads, 2) == 7); + Require(std::memcmp(first, "stu", 3) == 0 && std::memcmp(second, "vwst", 4) == 0); + Require(sceKernelReadv(ends[0], reads, 2) == 3 && std::memcmp(first, "uvw", 3) == 0); Require(sceKernelPreadv(ends[0], reads, 2, 0) == ErrorEspipe); Require(sceKernelPwritev(ends[1], message, 1, 0) == ErrorEspipe); #ifndef _WIN32