From: Tulio A M Mendes Date: Sat, 7 Feb 2026 22:32:02 +0000 (-0300) Subject: syscall: support write() to files (tmpfs test) X-Git-Url: https://projects.tadryanom.me/?a=commitdiff_plain;h=cf38e66ef445adf88320ac80291f38be57f9e73c;p=AdrOS.git syscall: support write() to files (tmpfs test) --- diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index ae219dc..93f02df 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -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; } diff --git a/user/init.c b/user/init.c index 8d1ecd0..2b9ffa9 100644 --- a/user/init.c +++ b/user/init.c @@ -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++) {