From 5c61252061e53a9b3772dc3bdfdd4f434d8ceff4 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 15 Oct 2022 10:56:06 +0200 Subject: [PATCH] Kernel: Add a new fcntl() system call --- kernel/include/sys/Syscall.h | 4 ++- kernel/src/sys/Syscall.cpp | 3 +- kernel/src/sys/stdio.cpp | 62 +++++++++++++++++++++++++++++------- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/kernel/include/sys/Syscall.h b/kernel/include/sys/Syscall.h index a5928008..a0a8e10a 100644 --- a/kernel/include/sys/Syscall.h +++ b/kernel/include/sys/Syscall.h @@ -16,6 +16,7 @@ #define SYS_close 11 #define SYS_seek 12 #define SYS_exec 13 +#define SYS_fcntl 14 namespace Syscall { @@ -37,4 +38,5 @@ void sys_open(Context* context, const char* filename, int flags); void sys_read(Context* context, int fd, size_t size, char* buffer); void sys_close(Context* context, int fd); void sys_seek(Context* context, int fd, long offset, int whence); -void sys_exec(Context* context, const char* pathname); \ No newline at end of file +void sys_exec(Context* context, const char* pathname); +void sys_fcntl(Context* context, int fd, int command, uintptr_t arg); \ No newline at end of file diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp index df373bee..d4ac73b7 100644 --- a/kernel/src/sys/Syscall.cpp +++ b/kernel/src/sys/Syscall.cpp @@ -25,12 +25,13 @@ void Syscall::entry(Context* context) case SYS_close: sys_close(context, (int)context->rdi); break; case SYS_seek: sys_seek(context, (int)context->rdi, (long)context->rsi, (int)context->rdx); break; case SYS_exec: sys_exec(context, (const char*)context->rdi); break; + case SYS_fcntl: sys_fcntl(context, (int)context->rdi, (int)context->rsi, context->rdx); break; default: context->rax = -ENOSYS; break; } VMM::exit_syscall_context(); } -char* Syscall::strdup_from_user(const char* user_string) +char* Syscall::strdup_from_user(const char* user_string) // FIXME: This function is a little hacky. { uint64_t phys = VMM::get_physical((uint64_t)user_string); if (phys == (uint64_t)-1) { return nullptr; } diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp index 522aa3b4..459c6d6c 100644 --- a/kernel/src/sys/stdio.cpp +++ b/kernel/src/sys/stdio.cpp @@ -18,6 +18,42 @@ #define SEEK_CUR 1 #define SEEK_END 2 +#define FNCTL_DUPFD 0 + +void sys_fcntl(Context* context, int fd, int command, uintptr_t arg) +{ + if (fd >= TASK_MAX_FDS || fd < 0) + { + context->rax = -EBADF; + return; + } + Task* current_task = Scheduler::current_task(); + if (!current_task->files[fd].is_open()) + { + context->rax = -EBADF; + return; + } + Descriptor& file = current_task->files[fd]; + if (command == FNCTL_DUPFD) + { + int dupfd = current_task->alloc_fd(); + if (dupfd < 0) + { + context->rax = -EMFILE; + return; + } + current_task->files[dupfd] = file; + context->rax = dupfd; + kdbgln("fcntl(F_DUPFD): duplicated fd %d, result is %d", fd, dupfd); + return; + } + else + { + context->rax = -EINVAL; + return; + } +} + void sys_seek(Context* context, int fd, long offset, int whence) { if (whence < SEEK_SET || whence > SEEK_END) @@ -36,12 +72,13 @@ void sys_seek(Context* context, int fd, long offset, int whence) context->rax = -EBADF; return; } + Descriptor& file = current_task->files[fd]; long new_offset; if (whence == SEEK_SET) new_offset = offset; else if (whence == SEEK_CUR) - new_offset = offset + current_task->files[fd].offset(); + new_offset = offset + file.offset(); else if (whence == SEEK_END) - new_offset = current_task->files[fd].length() + offset; + new_offset = file.length() + offset; else __builtin_unreachable(); if (new_offset < 0) @@ -49,7 +86,12 @@ void sys_seek(Context* context, int fd, long offset, int whence) context->rax = -EINVAL; // FIXME: Is this the right error? return; } - int result = current_task->files[fd].seek(new_offset); + if (new_offset == file.offset()) + { + context->rax = new_offset; + return; + } + int result = file.seek(new_offset); if (result < 0) { context->rax = result; @@ -77,12 +119,13 @@ void sys_write(Context* context, int fd, size_t size, const char* addr) context->rax = -EBADF; return; } - if (!current_task->files[fd].can_write()) + Descriptor& file = current_task->files[fd]; + if (!file.can_write()) { context->rax = -EBADF; return; } - ssize_t result = current_task->files[fd].write(size, (const char*)VMM::get_physical((uint64_t)addr)); + ssize_t result = file.write(size, (const char*)VMM::get_physical((uint64_t)addr)); context->rax = (size_t)result; return; } @@ -90,13 +133,8 @@ void sys_write(Context* context, int fd, size_t size, const char* addr) void sys_open(Context* context, const char* filename, int flags) { Task* current_task = Scheduler::current_task(); - int fd; - for (fd = 0; fd < TASK_MAX_FDS; fd++) - { - if (!current_task->files[fd].is_open()) break; - } - - if (fd == TASK_MAX_FDS) + int fd = current_task->alloc_fd(); + if (fd < 0) { context->rax = -EMFILE; return;