]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: readv/writev syscalls (81/82) + ulibc sys/uio.h wrappers
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 03:14:55 +0000 (00:14 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:20:50 +0000 (23:20 -0300)
src/kernel/syscall.c
user/ulibc/include/sys/uio.h [new file with mode: 0644]
user/ulibc/src/uio.c [new file with mode: 0644]

index 5254431555dfbda9c55dfa7fc7dd491c0a2edc88..b133e823a2fc99639ac5bc420ee5fc79e4002884 100644 (file)
@@ -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 (file)
index 0000000..89958a6
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef ULIBC_SYS_UIO_H
+#define ULIBC_SYS_UIO_H
+
+#include <stddef.h>
+
+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 (file)
index 0000000..d765e46
--- /dev/null
@@ -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));
+}