From 1e86acd4c08ee2b64c839c4f8dd78912ac08f7c7 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 15 Oct 2022 11:16:34 +0200 Subject: [PATCH] libc: Implement fcntl(F_DUPFD) and dup() --- apps/src/init.c | 18 ++++++++++++++++++ kernel/src/sys/stdio.cpp | 5 +++-- libs/libc/include/fcntl.h | 6 ++++++ libs/libc/include/luna/syscall.h | 1 + libs/libc/include/unistd.h | 3 +++ libs/libc/src/fcntl.cpp | 15 +++++++++++++++ libs/libc/src/unistd.cpp | 7 +++++++ 7 files changed, 53 insertions(+), 2 deletions(-) diff --git a/apps/src/init.c b/apps/src/init.c index f6c1f1c7..fe54d161 100644 --- a/apps/src/init.c +++ b/apps/src/init.c @@ -141,5 +141,23 @@ int main() printf("Press any key to restart.\n\n"); + int ferr = fileno(stderr); + int newerr = dup(ferr); + if (newerr < 0) + { + perror("dup"); + return 1; + } + FILE* new_stderr = fdopen(newerr, "rw"); + if (!new_stderr) + { + perror("fdopen"); + return 1; + } + + fprintf(new_stderr, "Bye!\n"); + + fclose(new_stderr); + return 0; } diff --git a/kernel/src/sys/stdio.cpp b/kernel/src/sys/stdio.cpp index 459c6d6c..ac31b1b4 100644 --- a/kernel/src/sys/stdio.cpp +++ b/kernel/src/sys/stdio.cpp @@ -20,7 +20,7 @@ #define FNCTL_DUPFD 0 -void sys_fcntl(Context* context, int fd, int command, uintptr_t arg) +void sys_fcntl(Context* context, int fd, int command, [[maybe_unused]] uintptr_t arg) { if (fd >= TASK_MAX_FDS || fd < 0) { @@ -34,7 +34,8 @@ void sys_fcntl(Context* context, int fd, int command, uintptr_t arg) return; } Descriptor& file = current_task->files[fd]; - if (command == FNCTL_DUPFD) + if (command == FNCTL_DUPFD) // FIXME: If arg is greater than 0, return the lowest numbered available file descriptor + // greater than or equal to arg. { int dupfd = current_task->alloc_fd(); if (dupfd < 0) diff --git a/libs/libc/include/fcntl.h b/libs/libc/include/fcntl.h index e60f6b55..1f4b2715 100644 --- a/libs/libc/include/fcntl.h +++ b/libs/libc/include/fcntl.h @@ -8,6 +8,9 @@ /* Open for reading and writing. */ #define O_RDWR 3 +/* Duplicate a file descriptor. */ +#define F_DUPFD 0 + #ifdef __cplusplus extern "C" { @@ -16,6 +19,9 @@ extern "C" /* Opens the file specified by pathname. Returns a file descriptor on success, or -1 on error. */ int open(const char* pathname, int flags); + /* Performs an operation on the file descriptor fd determined by cmd. */ + int fcntl(int fd, int cmd, ...); + #ifdef __cplusplus } #endif diff --git a/libs/libc/include/luna/syscall.h b/libs/libc/include/luna/syscall.h index cc0c24ce..7378a77e 100644 --- a/libs/libc/include/luna/syscall.h +++ b/libs/libc/include/luna/syscall.h @@ -15,6 +15,7 @@ #define SYS_close 11 #define SYS_seek 12 #define SYS_exec 13 +#define SYS_fcntl 14 #ifndef __want_syscalls #ifdef __cplusplus diff --git a/libs/libc/include/unistd.h b/libs/libc/include/unistd.h index cde368b0..2e324007 100644 --- a/libs/libc/include/unistd.h +++ b/libs/libc/include/unistd.h @@ -45,6 +45,9 @@ extern "C" /* Moves the read/write file offset for fd to offset, depending on whence. */ off_t lseek(int fd, off_t offset, int whence); + /* Returns a copy of the file descriptor fd. */ + int dup(int fd); + #ifdef __cplusplus } #endif diff --git a/libs/libc/src/fcntl.cpp b/libs/libc/src/fcntl.cpp index 58839006..69ae13c1 100644 --- a/libs/libc/src/fcntl.cpp +++ b/libs/libc/src/fcntl.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -8,4 +9,18 @@ extern "C" { return (int)syscall(SYS_open, pathname, flags); } + + int fcntl(int fd, int cmd, ...) + { + va_list ap; + va_start(ap, cmd); + long result; + switch (cmd) + { + case F_DUPFD: result = syscall(SYS_fcntl, fd, cmd, va_arg(ap, int)); break; + default: result = syscall(SYS_fcntl, fd, cmd, 0); break; + } + va_end(ap); + return (int)result; + } } \ No newline at end of file diff --git a/libs/libc/src/unistd.cpp b/libs/libc/src/unistd.cpp index 8c05f72a..cb5fbb31 100644 --- a/libs/libc/src/unistd.cpp +++ b/libs/libc/src/unistd.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -45,6 +46,7 @@ extern "C" result = __luna_syscall2(number, arg0, arg1); break; } + case SYS_fcntl: case SYS_seek: case SYS_write: case SYS_read: @@ -101,4 +103,9 @@ extern "C" syscall(SYS_exit, status); __builtin_unreachable(); } + + int dup(int fd) + { + return fcntl(fd, F_DUPFD, 0); + } } \ No newline at end of file