From fa9f58446f85d478689c6048eac0c65ef87635be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Wed, 30 Apr 2025 11:09:40 +0200 Subject: [PATCH] Implement sceKernelPwritev (#2865) --- src/core/devices/base_device.h | 4 ++++ src/core/libraries/kernel/file_system.cpp | 27 ++++++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/core/devices/base_device.h b/src/core/devices/base_device.h index 36614b8f4..0cbbd3a00 100644 --- a/src/core/devices/base_device.h +++ b/src/core/devices/base_device.h @@ -40,6 +40,10 @@ public: return ORBIS_KERNEL_ERROR_EBADF; } + virtual size_t pwritev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) { + return ORBIS_KERNEL_ERROR_EBADF; + } + virtual s64 lseek(s64 offset, int whence) { return ORBIS_KERNEL_ERROR_EBADF; } diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index bc34dff98..bcfa15a62 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -877,7 +877,7 @@ s32 PS4_SYSV_ABI sceKernelGetdirentries(s32 fd, char* buf, s32 nbytes, s64* base return result; } -s64 PS4_SYSV_ABI posix_pwrite(s32 fd, void* buf, size_t nbytes, s64 offset) { +s64 PS4_SYSV_ABI posix_pwritev(s32 fd, const SceKernelIovec* iov, s32 iovcnt, s64 offset) { if (offset < 0) { *__Error() = POSIX_EINVAL; return -1; @@ -893,7 +893,7 @@ s64 PS4_SYSV_ABI posix_pwrite(s32 fd, void* buf, size_t nbytes, s64 offset) { std::scoped_lock lk{file->m_mutex}; if (file->type == Core::FileSys::FileType::Device) { - s64 result = file->device->pwrite(buf, nbytes, offset); + s64 result = file->device->pwritev(iov, iovcnt, offset); if (result < 0) { ErrSceToPosix(result); return -1; @@ -908,7 +908,16 @@ s64 PS4_SYSV_ABI posix_pwrite(s32 fd, void* buf, size_t nbytes, s64 offset) { *__Error() = POSIX_EIO; return -1; } - return file->f.WriteRaw(buf, nbytes); + size_t total_written = 0; + for (int i = 0; i < iovcnt; i++) { + total_written += file->f.WriteRaw(iov[i].iov_base, iov[i].iov_len); + } + return total_written; +} + +s64 PS4_SYSV_ABI posix_pwrite(s32 fd, void* buf, size_t nbytes, s64 offset) { + SceKernelIovec iovec{buf, nbytes}; + return posix_pwritev(fd, &iovec, 1, offset); } s64 PS4_SYSV_ABI sceKernelPwrite(s32 fd, void* buf, size_t nbytes, s64 offset) { @@ -920,6 +929,15 @@ s64 PS4_SYSV_ABI sceKernelPwrite(s32 fd, void* buf, size_t nbytes, s64 offset) { return result; } +s64 PS4_SYSV_ABI sceKernelPwritev(s32 fd, const SceKernelIovec* iov, s32 iovcnt, s64 offset) { + s64 result = posix_pwritev(fd, iov, iovcnt, offset); + if (result < 0) { + LOG_ERROR(Kernel_Fs, "error = {}", *__Error()); + return ErrnoToSceKernelError(*__Error()); + } + return result; +} + s32 PS4_SYSV_ABI posix_unlink(const char* path) { if (path == nullptr) { *__Error() = POSIX_EINVAL; @@ -1017,7 +1035,10 @@ void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("sfKygSjIbI8", "libkernel", 1, "libkernel", 1, 1, getdirentries); LIB_FUNCTION("taRWhTJFTgE", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdirentries); LIB_FUNCTION("C2kJ-byS5rM", "libkernel", 1, "libkernel", 1, 1, posix_pwrite); + LIB_FUNCTION("FCcmRZhWtOk", "libScePosix", 1, "libkernel", 1, 1, posix_pwritev); + LIB_FUNCTION("FCcmRZhWtOk", "libkernel", 1, "libkernel", 1, 1, posix_pwritev); LIB_FUNCTION("nKWi-N2HBV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPwrite); + LIB_FUNCTION("mBd4AfLP+u8", "libkernel", 1, "libkernel", 1, 1, sceKernelPwritev); LIB_FUNCTION("AUXVxWeJU-A", "libkernel", 1, "libkernel", 1, 1, sceKernelUnlink); }