From 770286a19d7f52be1cceed347356107289a34792 Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 24 Mar 2023 21:33:20 +0100 Subject: [PATCH] kernel+libc: Implement fcntl() for F_DUPFD and F_DUPFD_CLOEXEC --- kernel/src/sys/file.cpp | 32 ++++++++++++++++++++++++++++++++ libc/include/bits/fcntl.h | 9 +++++++++ libc/include/fcntl.h | 4 ++++ libc/include/unistd.h | 3 +++ libc/src/fcntl.cpp | 13 +++++++++++++ libc/src/unistd.cpp | 6 ++++++ libluna/include/luna/Syscall.h | 2 +- 7 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 libc/include/bits/fcntl.h diff --git a/kernel/src/sys/file.cpp b/kernel/src/sys/file.cpp index 0e3f7f7b..c227da3c 100644 --- a/kernel/src/sys/file.cpp +++ b/kernel/src/sys/file.cpp @@ -3,6 +3,8 @@ #include "memory/MemoryManager.h" #include "sys/Syscall.h" #include "thread/Scheduler.h" +#include +#include #include #include #include @@ -84,3 +86,33 @@ Result sys_lseek(Registers*, SyscallArgs args) return (u64)new_offset; } + +Result sys_fcntl(Registers*, SyscallArgs args) +{ + int fd = (int)args[0]; + int cmd = (int)args[1]; + + Thread* current = Scheduler::current(); + + auto& descriptor = *TRY(current->resolve_fd(fd)); + + bool is_cloexec = true; + + switch (cmd) + { + case F_DUPFD: is_cloexec = false; [[fallthrough]]; + case F_DUPFD_CLOEXEC: { + int arg = (int)args[2]; + int new_fd = TRY(current->allocate_fd(arg)); + + current->fd_table[new_fd] = descriptor; + + if (is_cloexec) current->fd_table[new_fd]->flags |= O_CLOEXEC; + else + current->fd_table[new_fd]->flags &= ~O_CLOEXEC; + + return (u64)new_fd; + } + default: return err(EINVAL); + } +} diff --git a/libc/include/bits/fcntl.h b/libc/include/bits/fcntl.h new file mode 100644 index 00000000..c2178168 --- /dev/null +++ b/libc/include/bits/fcntl.h @@ -0,0 +1,9 @@ +/* bits/fcntl.h: File control flags. */ + +#ifndef _BITS_FCNTL_H +#define _BITS_FCNTL_H + +#define F_DUPFD 0 +#define F_DUPFD_CLOEXEC 1 + +#endif diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h index e9f9bd4d..dd9bc746 100644 --- a/libc/include/fcntl.h +++ b/libc/include/fcntl.h @@ -3,6 +3,7 @@ #ifndef _FCNTL_H #define _FCNTL_H +#include #include #include @@ -17,6 +18,9 @@ extern "C" /* Create a file and return a file descriptor to it. */ int creat(const char* path, mode_t mode); + /* Perform a file control operation. */ + int fcntl(int fd, int cmd, ...); + #ifdef __cplusplus } #endif diff --git a/libc/include/unistd.h b/libc/include/unistd.h index e9fe0bc3..b0403e6e 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -55,6 +55,9 @@ extern "C" /* Modify a file descriptor's offset. */ off_t lseek(int fd, off_t offset, int whence); + /* Duplicate a file descriptor. */ + int dup(int fd); + #ifdef __cplusplus } #endif diff --git a/libc/src/fcntl.cpp b/libc/src/fcntl.cpp index e639546f..87de09c4 100644 --- a/libc/src/fcntl.cpp +++ b/libc/src/fcntl.cpp @@ -23,4 +23,17 @@ extern "C" { return open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); } + + int fcntl(int fd, int cmd, ...) + { + va_list ap; + va_start(ap, cmd); + + uintptr_t arg = (uintptr_t)va_arg(ap, uintptr_t); + + long rc = syscall(SYS_fcntl, fd, cmd, arg); + + va_end(ap); + __errno_return(rc, int); + } } diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp index f01d5cfa..58a219cd 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -83,4 +84,9 @@ extern "C" long rc = syscall(SYS_lseek, fd, offset, whence); __errno_return(rc, off_t); } + + int dup(int fd) + { + return fcntl(fd, F_DUPFD, 0); + } } diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index 4179622e..ca5bb217 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -2,7 +2,7 @@ #define enumerate_syscalls(_e) \ _e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(open) _e(close) _e(read) _e(getpid) _e(write) \ - _e(lseek) _e(mkdir) _e(exec) _e(mknod) _e(fork) _e(waitpid) _e(getppid) + _e(lseek) _e(mkdir) _e(exec) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) enum Syscalls {