fix(libkernel): fill every buffer of readv from a pipe on Windows

This commit is contained in:
David 2026-10-13 02:40:04 +04:00 committed by milescoviello
parent 1c5e62878a
commit 665e6f1782
2 changed files with 16 additions and 1 deletions

View File

@ -218,6 +218,12 @@ static bool NativeIsDisk(int descriptor) {
const auto handle = reinterpret_cast<HANDLE>(::_get_osfhandle(descriptor));
return handle != INVALID_HANDLE_VALUE && ::GetFileType(handle) == FILE_TYPE_DISK;
}
static bool NativePipeHasData(int descriptor) {
const auto handle = reinterpret_cast<HANDLE>(::_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<std::size_t>(result);
if (static_cast<std::size_t>(result) < chunk || !whole) return done;
if (static_cast<std::size_t>(result) < chunk || (!whole && !NativePipeHasData(d))) return done;
}
}
return done;

View File

@ -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