From: Tulio A M Mendes Date: Thu, 12 Feb 2026 03:14:55 +0000 (-0300) Subject: feat: readv/writev syscalls (81/82) + ulibc sys/uio.h wrappers X-Git-Url: https://projects.tadryanom.me/docs/POSIX_ROADMAP.md?a=commitdiff_plain;h=15c0fb983e20a513c8b7c18c1f6e716a139a2e72;p=AdrOS.git feat: readv/writev syscalls (81/82) + ulibc sys/uio.h wrappers --- diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 5254431..b133e82 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -2230,7 +2230,8 @@ void syscall_handler(struct registers* regs) { if (syscall_no == SYSCALL_PREAD || syscall_no == SYSCALL_PWRITE || syscall_no == SYSCALL_ACCESS || syscall_no == SYSCALL_TRUNCATE || - syscall_no == SYSCALL_FTRUNCATE) { + syscall_no == SYSCALL_FTRUNCATE || syscall_no == SYSCALL_READV || + syscall_no == SYSCALL_WRITEV) { posix_ext_syscall_dispatch(regs, syscall_no); return; } @@ -2374,6 +2375,48 @@ static void posix_ext_syscall_dispatch(struct registers* regs, uint32_t syscall_ return; } + if (syscall_no == SYSCALL_READV) { + int fd = (int)regs->ebx; + struct { void* iov_base; uint32_t iov_len; } iov; + const void* user_iov = (const void*)regs->ecx; + int iovcnt = (int)regs->edx; + if (iovcnt <= 0 || iovcnt > 16) { regs->eax = (uint32_t)-EINVAL; return; } + uint32_t total = 0; + for (int i = 0; i < iovcnt; i++) { + if (copy_from_user(&iov, (const char*)user_iov + i * 8, 8) < 0) { + regs->eax = (uint32_t)-EFAULT; return; + } + if (iov.iov_len == 0) continue; + int r = syscall_read_impl(fd, iov.iov_base, iov.iov_len); + if (r < 0) { if (total == 0) { regs->eax = (uint32_t)r; return; } break; } + total += (uint32_t)r; + if ((uint32_t)r < iov.iov_len) break; + } + regs->eax = total; + return; + } + + if (syscall_no == SYSCALL_WRITEV) { + int fd = (int)regs->ebx; + struct { const void* iov_base; uint32_t iov_len; } iov; + const void* user_iov = (const void*)regs->ecx; + int iovcnt = (int)regs->edx; + if (iovcnt <= 0 || iovcnt > 16) { regs->eax = (uint32_t)-EINVAL; return; } + uint32_t total = 0; + for (int i = 0; i < iovcnt; i++) { + if (copy_from_user(&iov, (const char*)user_iov + i * 8, 8) < 0) { + regs->eax = (uint32_t)-EFAULT; return; + } + if (iov.iov_len == 0) continue; + int r = syscall_write_impl(fd, iov.iov_base, iov.iov_len); + if (r < 0) { if (total == 0) { regs->eax = (uint32_t)r; return; } break; } + total += (uint32_t)r; + if ((uint32_t)r < iov.iov_len) break; + } + regs->eax = total; + return; + } + regs->eax = (uint32_t)-ENOSYS; } diff --git a/user/ulibc/include/sys/uio.h b/user/ulibc/include/sys/uio.h new file mode 100644 index 0000000..89958a6 --- /dev/null +++ b/user/ulibc/include/sys/uio.h @@ -0,0 +1,14 @@ +#ifndef ULIBC_SYS_UIO_H +#define ULIBC_SYS_UIO_H + +#include + +struct iovec { + void* iov_base; + size_t iov_len; +}; + +int readv(int fd, const struct iovec* iov, int iovcnt); +int writev(int fd, const struct iovec* iov, int iovcnt); + +#endif diff --git a/user/ulibc/src/uio.c b/user/ulibc/src/uio.c new file mode 100644 index 0000000..d765e46 --- /dev/null +++ b/user/ulibc/src/uio.c @@ -0,0 +1,11 @@ +#include "sys/uio.h" +#include "syscall.h" +#include "errno.h" + +int readv(int fd, const struct iovec* iov, int iovcnt) { + return __syscall_ret(_syscall3(SYS_READV, fd, (int)iov, iovcnt)); +} + +int writev(int fd, const struct iovec* iov, int iovcnt) { + return __syscall_ret(_syscall3(SYS_WRITEV, fd, (int)iov, iovcnt)); +}