summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordzwdz2023-06-10 17:47:16 +0200
committerdzwdz2023-06-10 17:47:16 +0200
commit17fe7bc9c8311f7e192385e47550607e61874528 (patch)
tree2e64187a886fa88c652e5df5e6b8e36e34609f7e
parentede58f88397ad32f4d573d17811279735e2e386a (diff)
kernel: implement DUP_SEARCH (like unix's F_DUPFD)
-rw-r--r--src/kernel/proc.c9
-rw-r--r--src/kernel/proc.h5
-rw-r--r--src/kernel/syscalls.c3
-rw-r--r--src/shared/include/camellia/flags.h1
-rw-r--r--src/user/lib/fcntl.c17
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;
+ }
}