diff options
author | dzwdz | 2022-07-10 23:17:27 +0200 |
---|---|---|
committer | dzwdz | 2022-07-10 23:17:27 +0200 |
commit | d3be139a93c578d1e055bfd5f6f79eda312091f9 (patch) | |
tree | 0d2bf35333017e41c88fea49969d12fdad0a08c2 /src/kernel/syscalls.c | |
parent | 45c5bf044a063a289fad6a53b8d27ce675d9c272 (diff) |
syscalls: implement dup
Diffstat (limited to 'src/kernel/syscalls.c')
-rw-r--r-- | src/kernel/syscalls.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index 421b5ce..1d18ad1 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -176,6 +176,30 @@ fail: SYSCALL_RETURN(-1); } +handle_t _syscall_dup(handle_t from, handle_t to, int flags) { + struct handle *fromh, **toh; + if (flags) SYSCALL_RETURN(-1); + + if (to < 0) { + to = process_find_free_handle(process_current, 0); + if (to < 0) SYSCALL_RETURN(-1); + } else if (to >= HANDLE_MAX) { + SYSCALL_RETURN(-1); + } + + if (to == from) + SYSCALL_RETURN(to); + toh = &process_current->handles[to]; + fromh = (from >= 0 && from < HANDLE_MAX) ? + process_current->handles[from] : NULL; + + if (*toh) handle_close(*toh); + *toh = fromh; + if (fromh) fromh->refcount++; + + SYSCALL_RETURN(to); +} + int _syscall_read(handle_t handle_num, void __user *buf, size_t len, int offset) { struct handle *h = process_handle_get(process_current, handle_num); if (!h) SYSCALL_RETURN(-1); @@ -360,6 +384,9 @@ int _syscall(int num, int a, int b, int c, int d) { case _SYSCALL_MOUNT: _syscall_mount(a, (userptr_t)b, c); break; + case _SYSCALL_DUP: + _syscall_dup(a, b, c); + break; case _SYSCALL_READ: _syscall_read(a, (userptr_t)b, c, d); break; |