From f12d2de271a58b84c4c3aa13bf742f972a395e46 Mon Sep 17 00:00:00 2001 From: Get-fix <100056769+Get-fix@users.noreply.github.com> Date: Sun, 11 Oct 2026 17:46:31 +0300 Subject: [PATCH] fix(libkernel): export _readv, _writev, _fcntl, _fstat, __sys_socketex OpenOrbis programs and modules import these PS4 libkernel names (the graphics, library and networking samples). The underscore names forward to readv, writev, fcntl and fstat, as _ioctl already does; _fcntl passes its argument on as a full 64-bit value, so the record lock commands keep their whole pointer. __sys_socketex creates a socket like socket(); its name argument is ignored, as sceNetSocket does. --- core/libs/prx/libkernel/File/src/Stdio.cpp | 12 ++++++++++++ core/libs/prx/libkernel/Socket/src/Udp.cpp | 18 ++++++++++++++++++ core/libs/tests/GuestFileTimestamps.cpp | 6 ++++-- core/libs/tests/GuestFileVector.cpp | 7 +++++++ core/libs/tests/GuestKernelFcntl.cpp | 8 ++++++++ 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/core/libs/prx/libkernel/File/src/Stdio.cpp b/core/libs/prx/libkernel/File/src/Stdio.cpp index 58f00fafaa..3e4b1da3b2 100644 --- a/core/libs/prx/libkernel/File/src/Stdio.cpp +++ b/core/libs/prx/libkernel/File/src/Stdio.cpp @@ -729,6 +729,10 @@ int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int d, FileStat* sb) { return 0; } +int64_t APS5_VABI _fstat_nid_postfix(int d, FileStat* sb) { + return fstat_nid_disambig1_nid_postfix(d, sb); +} + int APS5_VABI ftruncate_nid_postfix(int d, int64_t length) { if (length < 0 || GuestSockets::IsOpen(d)) { return PosixFailure(GUEST_EINVAL); @@ -1342,4 +1346,12 @@ int64_t APS5_VABI writev_nid_postfix(int d, const KernelIovec* iov, int iovcnt) return result < 0 ? PosixFailure(static_cast(result) & 0xffff) : result; } +int64_t APS5_VABI _readv_nid_postfix(int d, const KernelIovec* iov, int iovcnt) { + return readv_nid_postfix(d, iov, iovcnt); +} + +int64_t APS5_VABI _writev_nid_postfix(int d, const KernelIovec* iov, int iovcnt) { + return writev_nid_postfix(d, iov, iovcnt); +} + } diff --git a/core/libs/prx/libkernel/Socket/src/Udp.cpp b/core/libs/prx/libkernel/Socket/src/Udp.cpp index 435d75c4d7..28771eb8c2 100644 --- a/core/libs/prx/libkernel/Socket/src/Udp.cpp +++ b/core/libs/prx/libkernel/Socket/src/Udp.cpp @@ -789,6 +789,20 @@ int APS5_VABI fcntl_nid_postfix(int descriptor, int command, ...) { socket->nonblocking = enabled != 0; return 0; } +int APS5_VABI _fcntl_nid_postfix(int descriptor, int command, ...) { +#ifdef _WIN32 + __builtin_sysv_va_list arguments; + __builtin_sysv_va_start(arguments, command); + const auto argument = __builtin_va_arg(arguments, std::uint64_t); + __builtin_sysv_va_end(arguments); +#else + std::va_list arguments; + va_start(arguments, command); + const auto argument = va_arg(arguments, std::uint64_t); + va_end(arguments); +#endif + return fcntl_nid_postfix(descriptor, command, argument); +} int APS5_VABI setsockopt_nid_postfix(int descriptor, int level, int option, const void* value, std::uint32_t length) { int netError = 0; @@ -838,6 +852,10 @@ int APS5_VABI socket_nid_postfix(int family, int type, int protocol) { return Fail(12); } } +int APS5_VABI __sys_socketex_nid_postfix(const char* name, int family, int type, int protocol) { + static_cast(name); + return socket_nid_postfix(family, type, protocol); +} int APS5_VABI socketpair_nid_postfix(int family, int type, int protocol, int* descriptors) { const bool nonblocking = (type & GuestNonBlocking) != 0; const int plainType = type & ~(GuestCloseOnExec | GuestNonBlocking); diff --git a/core/libs/tests/GuestFileTimestamps.cpp b/core/libs/tests/GuestFileTimestamps.cpp index 13c71a958d..b1e91115f8 100644 --- a/core/libs/tests/GuestFileTimestamps.cpp +++ b/core/libs/tests/GuestFileTimestamps.cpp @@ -19,6 +19,7 @@ int APS5_VABI stat_nid_postfix(const char*, FileStat*); int APS5_VABI lstat_nid_postfix(const char*, FileStat*); int APS5_VABI sceKernelFstat(int, FileStat*); std::int64_t APS5_VABI fstat_nid_disambig1_nid_postfix(int, FileStat*); +std::int64_t APS5_VABI _fstat_nid_postfix(int, FileStat*); int APS5_VABI open_nid_postfix(const char*, int, int); int APS5_VABI close_nid_postfix(int); int APS5_VABI pipe_nid_postfix(int*); @@ -37,11 +38,12 @@ static bool Same(const KernelTimespec& actual, const KernelTimeval& expected) { } static void CheckTimes(const std::string& path, int fd, const KernelTimeval* expected) { - FileStat byPath{}, byFd{}, byKernel{}; + FileStat byPath{}, byFd{}, byKernel{}, byAlias{}; Require(stat_nid_postfix(path.c_str(), &byPath) == 0, "stat"); Require(fstat_nid_disambig1_nid_postfix(fd, &byFd) == 0, "fstat"); Require(sceKernelFstat(fd, &byKernel) == 0, "sceKernelFstat"); - for (const auto* status : {&byPath, &byFd, &byKernel}) { + Require(_fstat_nid_postfix(fd, &byAlias) == 0, "_fstat"); + for (const auto* status : {&byPath, &byFd, &byKernel, &byAlias}) { Require(Same(status->st_atim, expected[0]), "access time preserves microseconds"); Require(Same(status->st_mtim, expected[1]), "modification time preserves microseconds"); } diff --git a/core/libs/tests/GuestFileVector.cpp b/core/libs/tests/GuestFileVector.cpp index 76f392261f..21d6249e87 100644 --- a/core/libs/tests/GuestFileVector.cpp +++ b/core/libs/tests/GuestFileVector.cpp @@ -36,6 +36,8 @@ int APS5_VABI sceKernelLseek(int, std::int64_t, int); std::int64_t APS5_VABI sceKernelReadv(int, const GuestIovec*, int); std::int64_t APS5_VABI readv_nid_postfix(int, const GuestIovec*, int); std::int64_t APS5_VABI writev_nid_postfix(int, const GuestIovec*, int); +std::int64_t APS5_VABI _readv_nid_postfix(int, const GuestIovec*, int); +std::int64_t APS5_VABI _writev_nid_postfix(int, const GuestIovec*, int); int* APS5_VABI __error_nid_postfix(); std::int64_t APS5_VABI sceKernelWritev(int, const GuestIovec*, int); std::int64_t APS5_VABI sceKernelPreadv(int, const GuestIovec*, int, std::int64_t); @@ -94,6 +96,8 @@ int main() { Require(sceKernelLseek(file, 0, 1) == 7); Require(readv_nid_postfix(file, reads, 2) == 3); Require(readv_nid_postfix(file, reads, 2) == 0); + Require(sceKernelLseek(file, 3, 0) == 3 && _readv_nid_postfix(file, reads, 2) == 7); + Require(std::memcmp(first, "345", 3) == 0 && std::memcmp(second, "6789", 4) == 0); Require(readv_nid_postfix(file, reads, -1) == -1 && *__error_nid_postfix() == 22); Require(writev_nid_postfix(file, nullptr, 1) == -1 && *__error_nid_postfix() == 14); @@ -118,6 +122,9 @@ int main() { Require(sceKernelLseek(file, 0, 1) == 13 && Contents(path) == "01ABCDE7CDEAB"); Require(sceKernelLseek(file, 8, 0) == 8 && writev_nid_postfix(file, writes, 2) == 5); Require(Contents(path) == "01ABCDE7ABCDE"); + Require(sceKernelLseek(file, 8, 0) == 8 && _writev_nid_postfix(file, swapped, 2) == 5); + Require(sceKernelLseek(file, 0, 1) == 13 && Contents(path) == "01ABCDE7CDEAB"); + Require(sceKernelLseek(file, 8, 0) == 8 && writev_nid_postfix(file, writes, 2) == 5); GuestIovec gapped[3] = {{first, 2}, {nullptr, 0}, {second, 3}}; Require(sceKernelPreadv(file, gapped, 3, 0) == 5); diff --git a/core/libs/tests/GuestKernelFcntl.cpp b/core/libs/tests/GuestKernelFcntl.cpp index 679a739b64..d53e717eaf 100644 --- a/core/libs/tests/GuestKernelFcntl.cpp +++ b/core/libs/tests/GuestKernelFcntl.cpp @@ -11,9 +11,11 @@ #include extern "C" { int APS5_VABI socket_nid_postfix(int, int, int); +int APS5_VABI __sys_socketex_nid_postfix(const char*, int, int, int); int APS5_VABI close_nid_postfix(int); int APS5_VABI pipe_nid_postfix(int*); int APS5_VABI fcntl_nid_postfix(int, int, ...); +int APS5_VABI _fcntl_nid_postfix(int, int, ...); int APS5_VABI ioctl_nid_postfix(int, std::uint64_t, void*); std::int64_t APS5_VABI read_nid_postfix(int, void*, std::uint64_t); std::int64_t APS5_VABI write_nid_postfix(int, const char*, std::int64_t); @@ -110,6 +112,8 @@ static void SocketsKeepTheirPath() { Require(sceKernelFcntl(socket, GetFlags) == SceEbadf); Require(sceKernelFcntl(-1, GetFlags) == SceEbadf); Require(sceKernelFcntl(12345, GetFlags) == SceEbadf); + const int named = __sys_socketex_nid_postfix("probe", 2, 1, 0); + Require(named >= 0 && sceKernelFcntl(named, GetFlags) == ReadWrite && close_nid_postfix(named) == 0); } static void FileFlagsRoundTrip() { @@ -166,6 +170,10 @@ static void FileFlagsRoundTrip() { Require(fcntl_nid_postfix(file, SetLock, &lock) == 0); GuestLock probe{0, 0, 0, 1, 0, 0}; Require(fcntl_nid_postfix(file, GetLock, &probe) == 0 && probe.type == 2); + static GuestLock imageProbe{0, 0, 0, 1, 0, 0}; + Require(_fcntl_nid_postfix(file, GetLock, &imageProbe) == 0 && imageProbe.type == 2); + Require(_fcntl_nid_postfix(file, SetDescriptorFlags, 1) == 0 && _fcntl_nid_postfix(file, GetDescriptorFlags) == 1); + Require(_fcntl_nid_postfix(file, SetDescriptorFlags, 0) == 0); lock.type = 2; Require(fcntl_nid_postfix(file, SetLock, &lock) == 0); lock.type = 7;