diff options
author | dzwdz | 2023-06-10 17:47:16 +0200 |
---|---|---|
committer | dzwdz | 2023-06-10 17:47:16 +0200 |
commit | 17fe7bc9c8311f7e192385e47550607e61874528 (patch) | |
tree | 2e64187a886fa88c652e5df5e6b8e36e34609f7e | |
parent | ede58f88397ad32f4d573d17811279735e2e386a (diff) |
kernel: implement DUP_SEARCH (like unix's F_DUPFD)
-rw-r--r-- | src/kernel/proc.c | 9 | ||||
-rw-r--r-- | src/kernel/proc.h | 5 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 3 | ||||
-rw-r--r-- | src/shared/include/camellia/flags.h | 1 | ||||
-rw-r--r-- | src/user/lib/fcntl.c | 17 |
5 files changed, 24 insertions, 11 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 108a006..ecbd839 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -484,6 +484,9 @@ Proc *proc_next(Proc *p, Proc *root) { } hid_t proc_find_free_handle(Proc *proc, hid_t start_at) { + if (start_at < 0) { + start_at = 0; + } for (hid_t hid = start_at; hid < HANDLE_MAX; hid++) { if (proc->_handles[hid] == NULL) return hid; @@ -526,11 +529,11 @@ hid_t proc_handle_init(Proc *p, enum handle_type type, Handle **hs) { return hid; } -hid_t proc_handle_dup(Proc *p, hid_t from, hid_t to) { +hid_t proc_handle_dup(Proc *p, hid_t from, hid_t to, int flags) { Handle *fromh, **toh; - if (to < 0) { - to = proc_find_free_handle(p, 0); + if (to < 0 || (flags & DUP_SEARCH)) { + to = proc_find_free_handle(p, to); if (to < 0) return -EMFILE; } else if (to >= HANDLE_MAX) { return -EBADF; diff --git a/src/kernel/proc.h b/src/kernel/proc.h index bf5db69..f473124 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -129,10 +129,9 @@ Proc *proc_next(Proc *p, Proc *root); hid_t proc_find_free_handle(Proc *proc, hid_t start_at); Handle *proc_handle_get(Proc *, hid_t); hid_t proc_handle_init(Proc *, enum handle_type, Handle **); -hid_t proc_handle_dup(Proc *p, hid_t from, hid_t to); +hid_t proc_handle_dup(Proc *p, hid_t from, hid_t to, int flags); static inline void proc_handle_close(Proc *p, hid_t hid) { - // TODO test - proc_handle_dup(p, -1, hid); + proc_handle_dup(p, -1, hid, 0); } /* Gets a handle and removes the process' reference to it, without decreasing the refcount. diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 03d9ef1..1e75f9d 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -177,8 +177,7 @@ fail: } hid_t _sys_dup(hid_t from, hid_t to, int flags) { - if (flags != 0) SYSCALL_RETURN(-ENOSYS); - SYSCALL_RETURN(proc_handle_dup(proc_cur, from, to)); + SYSCALL_RETURN(proc_handle_dup(proc_cur, from, to, flags)); } static long simple_vfsop( diff --git a/src/shared/include/camellia/flags.h b/src/shared/include/camellia/flags.h index 5ff9f10..f4c54fe 100644 --- a/src/shared/include/camellia/flags.h +++ b/src/shared/include/camellia/flags.h @@ -12,6 +12,7 @@ #define FSR_DELEGATE 1 +#define DUP_SEARCH 1 #define OPEN_READ 1 #define OPEN_WRITE 2 diff --git a/src/user/lib/fcntl.c b/src/user/lib/fcntl.c index 89412a5..b2d8685 100644 --- a/src/user/lib/fcntl.c +++ b/src/user/lib/fcntl.c @@ -1,6 +1,9 @@ #include <bits/panic.h> +#include <camellia.h> +#include <camellia/syscalls.h> #include <errno.h> #include <fcntl.h> +#include <stdarg.h> #include <stdio.h> @@ -11,7 +14,15 @@ int open(const char *path, int flags, ...) { } int fcntl(int fd, int cmd, ...) { - (void)fd; (void)cmd; - _klogf("failing fcntl(%d)", cmd); - return errno = ENOSYS, -1; + va_list argp; + va_start(argp, cmd); + if (cmd == F_DUPFD) { + int to = va_arg(argp, int); + va_end(argp); + return _sys_dup(fd, to, DUP_SEARCH); + } else { + va_end(argp); + _klogf("failing fcntl(%d)", cmd); + return errno = ENOSYS, -1; + } } |