diff options
Diffstat (limited to 'pk')
-rw-r--r-- | pk/file.c | 14 | ||||
-rw-r--r-- | pk/file.h | 1 | ||||
-rw-r--r-- | pk/syscall.c | 16 | ||||
-rw-r--r-- | pk/syscall.h | 1 |
4 files changed, 32 insertions, 0 deletions
@@ -53,6 +53,20 @@ int file_dup(file_t* f) return -1; } +int file_dup3(file_t* f, int newfd) +{ + if (newfd < 0 || newfd >= MAX_FDS) + return -1; + + if (atomic_cas(&fds[newfd], 0, f) == 0) + { + file_incref(f); + return newfd; + } + + return -1; +} + void file_init() { // create stdin, stdout, stderr and FDs 0-2 @@ -23,6 +23,7 @@ file_t* file_open(const char* fn, int flags, int mode); void file_decref(file_t*); void file_incref(file_t*); int file_dup(file_t*); +int file_dup3(file_t*, int newfd); file_t* file_openat(int dirfd, const char* fn, int flags, int mode); ssize_t file_pwrite(file_t* f, const void* buf, size_t n, off_t off); diff --git a/pk/syscall.c b/pk/syscall.c index 07fa41d..4978f3a 100644 --- a/pk/syscall.c +++ b/pk/syscall.c @@ -181,6 +181,21 @@ int sys_dup(int fd) return r; } +int sys_dup3(int fd, int newfd, int flags) +{ + kassert(flags == 0); + int r = -EBADF; + file_t* f = file_get(fd); + + if (f) + { + r = file_dup3(f, newfd); + file_decref(f); + } + + return r; +} + ssize_t sys_lseek(int fd, size_t ptr, int dir) { ssize_t r = -EBADF; @@ -462,6 +477,7 @@ long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, unsigned l [SYS_ftruncate] = sys_ftruncate, [SYS_getdents] = sys_getdents, [SYS_dup] = sys_dup, + [SYS_dup3] = sys_dup3, [SYS_readlinkat] = sys_stub_nosys, [SYS_rt_sigprocmask] = sys_stub_success, [SYS_ioctl] = sys_stub_nosys, diff --git a/pk/syscall.h b/pk/syscall.h index 478ea61..60355ae 100644 --- a/pk/syscall.h +++ b/pk/syscall.h @@ -43,6 +43,7 @@ #define SYS_ftruncate 46 #define SYS_getdents 61 #define SYS_dup 23 +#define SYS_dup3 24 #define SYS_readlinkat 78 #define SYS_rt_sigprocmask 135 #define SYS_ioctl 29 |