From 12cf37d0a77e334769de0d3b9b1cb5e10cc4aa05 Mon Sep 17 00:00:00 2001 From: apio Date: Tue, 11 Oct 2022 21:06:12 +0200 Subject: [PATCH] Kernel/syscalls: Modify sys_write to accept a file descriptor and write to it Previously, sys_write only wrote to the tty. Now, it uses the VFS interface, as it should. --- kernel/include/sys/Syscall.h | 2 +- kernel/src/sys/Syscall.cpp | 2 +- kernel/src/sys/stdio.cpp | 60 ++++++++++++++++++++++++++++++++---- libs/libc/include/unistd.h | 1 + libs/libc/src/unistd.cpp | 7 ++++- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/kernel/include/sys/Syscall.h b/kernel/include/sys/Syscall.h index 9facde47..13d69c0f 100644 --- a/kernel/include/sys/Syscall.h +++ b/kernel/include/sys/Syscall.h @@ -24,7 +24,7 @@ namespace Syscall void sys_exit(Context* context, int status); void sys_yield(Context* context); void sys_sleep(Context* context, uint64_t ms); -void sys_write(Context* context, const char* addr, size_t size); +void sys_write(Context* context, int fd, size_t size, const char* addr); void sys_paint(Context* context, uint64_t x, uint64_t y, uint64_t w, uint64_t h, uint64_t col); void sys_rand(Context* context); void sys_getversion(Context* context, char* buffer, size_t max); diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp index 78c68ae5..b470acaf 100644 --- a/kernel/src/sys/Syscall.cpp +++ b/kernel/src/sys/Syscall.cpp @@ -18,7 +18,7 @@ void Syscall::entry(Context* context) sys_sleep(context, context->rdi); break; case SYS_write: // sys_write - sys_write(context, (const char*)context->rdi, context->rsi); + sys_write(context, (int)context->rdi, context->rsi, (const char*)context->rdx); break; case SYS_paint: sys_paint(context, context->rdi, context->rsi, context->rdx, context->r10, context->r8); break; case SYS_rand: sys_rand(context); break; diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp index a4136a6d..6968747a 100644 --- a/kernel/src/sys/stdio.cpp +++ b/kernel/src/sys/stdio.cpp @@ -8,12 +8,44 @@ #include "thread/Scheduler.h" #include "thread/Task.h" +#define OPEN_READ 1 +#define OPEN_WRITE 2 + #define STDIO_FAIL(function, error) kwarnln("%s failed with %s", #function, #error) -void sys_write(Context* context, const char* addr, size_t size) +void sys_write(Context* context, int fd, size_t size, const char* addr) { - context->rax = size; - TextRenderer::write(addr, size); + if (!addr) + { + STDIO_FAIL(write, EINVAL); + context->rax = -EINVAL; // FIXME: This should probably return EFAULT. + return; + } + if (fd >= TASK_MAX_FDS || fd < 0) + { + kwarnln("file descriptor %d is outside the valid range", fd); + STDIO_FAIL(write, EBADF); + context->rax = -EBADF; + return; + } + Task* current_task = Scheduler::current_task(); + if (!current_task->files[fd].is_open()) + { + kwarnln("file descriptor %d is not open", fd); + STDIO_FAIL(write, EBADF); + context->rax = -EBADF; + return; + } + if (!current_task->files[fd].can_write()) + { + kwarnln("file descriptor %d is not open for writing", fd); + STDIO_FAIL(write, EBADF); + context->rax = -EBADF; + return; + } + ssize_t result = current_task->files[fd].write(size, addr); + context->rax = (size_t)result; + return; } void sys_open(Context* context, const char* filename, int flags) @@ -24,12 +56,14 @@ void sys_open(Context* context, const char* filename, int flags) { if (!current_task->files[fd].is_open()) break; } + if (fd == TASK_MAX_FDS) { STDIO_FAIL(open, EMFILE); context->rax = -EMFILE; return; } + VFS::Node* node = VFS::resolve_path(filename); if (!node) { @@ -37,9 +71,23 @@ void sys_open(Context* context, const char* filename, int flags) context->rax = -ENOENT; return; } - kdbgln("open(): opening %s, allocated file descriptor %d", filename, fd); - current_task->files[fd].open(node, - (bool)flags); // FIXME: Implement more flags. (right now, 1 is can_read, 0 is not) + + bool can_read = (flags & OPEN_READ) > 0; + bool can_write = (flags & OPEN_WRITE) > 0; + if (!can_read && !can_write) + { + STDIO_FAIL(open, EINVAL); + context->rax = -EINVAL; + return; + } + + kdbgln("open(): opening %s %s, allocated file descriptor %d", filename, + (can_read && can_write) ? "rw" + : can_read ? "r-" + : "-w", + fd); + + current_task->files[fd].open(node, can_read, can_write); context->rax = fd; return; } diff --git a/libs/libc/include/unistd.h b/libs/libc/include/unistd.h index 5ab7f8f6..8226a74a 100644 --- a/libs/libc/include/unistd.h +++ b/libs/libc/include/unistd.h @@ -16,6 +16,7 @@ extern "C" unsigned int sleep(unsigned int); ssize_t read(int, void*, size_t); + ssize_t write(int, const void*, size_t); int close(int); #ifdef __cplusplus diff --git a/libs/libc/src/unistd.cpp b/libs/libc/src/unistd.cpp index 41ff2be7..ebe2a8a4 100644 --- a/libs/libc/src/unistd.cpp +++ b/libs/libc/src/unistd.cpp @@ -37,7 +37,6 @@ extern "C" case SYS_exit: case SYS_close: case SYS_sleep: result = __luna_syscall1(number, va_arg(ap, arg)); break; - case SYS_write: case SYS_munmap: case SYS_open: case SYS_getversion: { @@ -46,6 +45,7 @@ extern "C" result = __luna_syscall2(number, arg0, arg1); break; } + case SYS_write: case SYS_read: case SYS_mmap: { arg arg0 = va_arg(ap, arg); @@ -80,6 +80,11 @@ extern "C" return syscall(SYS_read, fd, count, buf); // yes, our read() syscall is in the wrong order. } + ssize_t write(int fd, const void* buf, size_t count) + { + return syscall(SYS_write, fd, count, buf); // yes, our read() syscall is in the wrong order. + } + int close(int fd) { return (int)syscall(SYS_close, fd);