]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
syscall: support write() to files (tmpfs test)
authorTulio A M Mendes <[email protected]>
Sat, 7 Feb 2026 22:32:02 +0000 (19:32 -0300)
committerTulio A M Mendes <[email protected]>
Sat, 7 Feb 2026 22:32:02 +0000 (19:32 -0300)
src/kernel/syscall.c
user/init.c

index ae219dc9529cb7f314db1309162966f1bf987576..93f02df73a7a313558673395825e1702b92f5b28 100644 (file)
@@ -199,6 +199,41 @@ static int syscall_read_impl(int fd, void* user_buf, uint32_t len) {
     return (int)total;
 }
 
+static int syscall_write_impl(int fd, const void* user_buf, uint32_t len) {
+    if (len > 1024 * 1024) return -EINVAL;
+    if (user_range_ok(user_buf, (size_t)len) == 0) return -EFAULT;
+
+    if (fd == 1 || fd == 2) {
+        return tty_write((const char*)user_buf, len);
+    }
+
+    if (fd == 0) return -EBADF;
+
+    struct file* f = fd_get(fd);
+    if (!f || !f->node) return -EBADF;
+    if (f->node->flags != FS_FILE) return -ESPIPE;
+    if (!f->node->write) return -ESPIPE;
+
+    uint8_t kbuf[256];
+    uint32_t total = 0;
+    while (total < len) {
+        uint32_t chunk = len - total;
+        if (chunk > sizeof(kbuf)) chunk = (uint32_t)sizeof(kbuf);
+
+        if (copy_from_user(kbuf, (const uint8_t*)user_buf + total, chunk) < 0) {
+            return -EFAULT;
+        }
+
+        uint32_t wr = vfs_write(f->node, f->offset, chunk, kbuf);
+        if (wr == 0) break;
+        f->offset += wr;
+        total += wr;
+        if (wr < chunk) break;
+    }
+
+    return (int)total;
+}
+
 static void syscall_handler(struct registers* regs) {
     uint32_t syscall_no = regs->eax;
 
@@ -207,12 +242,7 @@ static void syscall_handler(struct registers* regs) {
         const char* buf = (const char*)regs->ecx;
         uint32_t len = regs->edx;
 
-        if (fd != 1 && fd != 2) {
-            regs->eax = (uint32_t)-1;
-            return;
-        }
-
-        regs->eax = (uint32_t)tty_write(buf, len);
+        regs->eax = (uint32_t)syscall_write_impl((int)fd, buf, len);
         return;
     }
 
index 8d1ecd08b49a47952c5da0ab8ba6742029b5893e..2b9ffa9798fde2e8bda7dbe60d9ab31555266f50 100644 (file)
@@ -221,6 +221,126 @@ void _start(void) {
 
     sys_write(1, "[init] lseek/stat/fstat OK\n", 27);
 
+    fd = sys_open("/tmp/hello.txt", 0);
+    if (fd < 0) {
+        sys_write(1, "[init] tmpfs open failed\n", 24);
+        sys_exit(1);
+    }
+
+    if (sys_stat("/tmp/hello.txt", &st) < 0) {
+        sys_write(1, "[init] tmpfs stat failed\n", 24);
+        sys_exit(1);
+    }
+    if ((st.st_mode & S_IFMT) != S_IFREG) {
+        sys_write(1, "[init] tmpfs stat not reg\n", 26);
+        sys_exit(1);
+    }
+    if (st.st_size == 0) {
+        sys_write(1, "[init] tmpfs stat size 0\n", 25);
+        sys_exit(1);
+    }
+
+    struct stat fst;
+    if (sys_fstat(fd, &fst) < 0) {
+        sys_write(1, "[init] tmpfs fstat failed\n", 25);
+        sys_exit(1);
+    }
+    if (fst.st_size != st.st_size) {
+        sys_write(1, "[init] tmpfs stat size mismatch\n", 31);
+        sys_exit(1);
+    }
+
+    int end = sys_lseek(fd, 0, SEEK_END);
+    if (end < 0 || (uint32_t)end != st.st_size) {
+        sys_write(1, "[init] tmpfs lseek end bad\n", 27);
+        sys_exit(1);
+    }
+
+    uint8_t eofb;
+    if (sys_read(fd, &eofb, 1) != 0) {
+        sys_write(1, "[init] tmpfs eof read bad\n", 27);
+        sys_exit(1);
+    }
+
+    if (sys_lseek(fd, 0, 999) >= 0) {
+        sys_write(1, "[init] tmpfs lseek whence bad\n", 30);
+        sys_exit(1);
+    }
+
+    if (sys_lseek(fd, 0, SEEK_SET) < 0) {
+        sys_write(1, "[init] tmpfs lseek set failed\n", 30);
+        sys_exit(1);
+    }
+
+    uint8_t tbuf[6];
+    if (sys_read(fd, tbuf, 5) != 5) {
+        sys_write(1, "[init] tmpfs read failed\n", 24);
+        sys_exit(1);
+    }
+    tbuf[5] = 0;
+    if (tbuf[0] != 'h' || tbuf[1] != 'e' || tbuf[2] != 'l' || tbuf[3] != 'l' || tbuf[4] != 'o') {
+        sys_write(1, "[init] tmpfs bad data\n", 22);
+        sys_exit(1);
+    }
+
+    if (sys_close(fd) < 0) {
+        sys_write(1, "[init] tmpfs close failed\n", 25);
+        sys_exit(1);
+    }
+
+    if (sys_open("/tmp/does_not_exist", 0) >= 0) {
+        sys_write(1, "[init] tmpfs open nonexist bad\n", 32);
+        sys_exit(1);
+    }
+
+    fd = sys_open("/tmp/hello.txt", 0);
+    if (fd < 0) {
+        sys_write(1, "[init] tmpfs open3 failed\n", 25);
+        sys_exit(1);
+    }
+
+    if (sys_fstat(fd, &fst) < 0) {
+        sys_write(1, "[init] tmpfs fstat2 failed\n", 26);
+        sys_exit(1);
+    }
+
+    if (sys_lseek(fd, 0, SEEK_END) < 0) {
+        sys_write(1, "[init] tmpfs lseek end2 failed\n", 31);
+        sys_exit(1);
+    }
+
+    static const char suf[] = "XYZ";
+    if (sys_write(fd, suf, 3) != 3) {
+        sys_write(1, "[init] tmpfs write failed\n", 25);
+        sys_exit(1);
+    }
+
+    if (sys_fstat(fd, &fst) < 0) {
+        sys_write(1, "[init] tmpfs fstat3 failed\n", 26);
+        sys_exit(1);
+    }
+    if (fst.st_size != st.st_size + 3) {
+        sys_write(1, "[init] tmpfs size not grown\n", 27);
+        sys_exit(1);
+    }
+
+    if (sys_lseek(fd, -3, SEEK_END) < 0) {
+        sys_write(1, "[init] tmpfs lseek back failed\n", 31);
+        sys_exit(1);
+    }
+    uint8_t s2[3];
+    if (sys_read(fd, s2, 3) != 3 || s2[0] != 'X' || s2[1] != 'Y' || s2[2] != 'Z') {
+        sys_write(1, "[init] tmpfs suffix mismatch\n", 27);
+        sys_exit(1);
+    }
+
+    if (sys_close(fd) < 0) {
+        sys_write(1, "[init] tmpfs close3 failed\n", 26);
+        sys_exit(1);
+    }
+
+    sys_write(1, "[init] tmpfs/mount OK\n", 22);
+
     enum { NCHILD = 100 };
     int children[NCHILD];
     for (int i = 0; i < NCHILD; i++) {