aboutsummaryrefslogtreecommitdiff
path: root/pk
diff options
context:
space:
mode:
authorLuís Marques <luismarques@lowrisc.org>2019-10-22 18:08:57 +0100
committerAndrew Waterman <andrew@sifive.com>2019-10-22 10:08:57 -0700
commit43969b149eb3be5fe18daa7c69a02467e6f16d15 (patch)
tree7dab24aa1df371e12a0a1dd924c36311441d51c7 /pk
parent15329a8aac5d0f1f1fea01c68230421147c8b50b (diff)
downloadpk-43969b149eb3be5fe18daa7c69a02467e6f16d15.zip
pk-43969b149eb3be5fe18daa7c69a02467e6f16d15.tar.gz
pk-43969b149eb3be5fe18daa7c69a02467e6f16d15.tar.bz2
Implement dup3 syscall (#162)
Diffstat (limited to 'pk')
-rw-r--r--pk/file.c14
-rw-r--r--pk/file.h1
-rw-r--r--pk/syscall.c16
-rw-r--r--pk/syscall.h1
4 files changed, 32 insertions, 0 deletions
diff --git a/pk/file.c b/pk/file.c
index 53087c3..502ff6a 100644
--- a/pk/file.c
+++ b/pk/file.c
@@ -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
diff --git a/pk/file.h b/pk/file.h
index 3bf7f12..f761e28 100644
--- a/pk/file.h
+++ b/pk/file.h
@@ -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