summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/cpu/syscall.c5
-rw-r--r--kernel/fs/vfs.c13
-rw-r--r--kernel/fs/vfs.h1
-rw-r--r--userland/libc/include/syscall.h1
-rw-r--r--userland/libc/include/unistd.h1
-rw-r--r--userland/libc/unistd/dup.c6
6 files changed, 27 insertions, 0 deletions
diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c
index aad0284..d4db1dd 100644
--- a/kernel/cpu/syscall.c
+++ b/kernel/cpu/syscall.c
@@ -439,6 +439,10 @@ int syscall_read(int fd, void *buf, size_t count) {
return rc;
}
+int syscall_dup(int fd) {
+ return vfs_dup(fd);
+}
+
int syscall_dup2(SYS_DUP2_PARAMS *args) {
return vfs_dup2(args->org_fd, args->new_fd);
}
@@ -700,6 +704,7 @@ int (*syscall_functions[])() = {
(void(*))syscall_queue_wait,
(void(*))syscall_sendfile,
(void(*))syscall_shm_unlink,
+ (void(*))syscall_dup,
};
void int_syscall(reg_t *r);
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index 9684a18..1f28f13 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -395,6 +395,19 @@ vfs_vm_object_t *vfs_get_vm_object(int fd, u64 length, u64 offset) {
return r;
}
+int vfs_dup(int fd) {
+ vfs_fd_t *ptr = get_vfs_fd(fd, NULL);
+ if (!ptr) {
+ return -EBADF;
+ }
+ int index;
+ if (!relist_add(&current_task->file_descriptors, ptr, &index)) {
+ return -EMFILE;
+ }
+ ptr->reference_count++;
+ return index;
+}
+
int vfs_dup2(int org_fd, int new_fd) {
if (org_fd == new_fd) {
return -EINVAL;
diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h
index 396802b..e22897e 100644
--- a/kernel/fs/vfs.h
+++ b/kernel/fs/vfs.h
@@ -77,6 +77,7 @@ int raw_vfs_pwrite(vfs_fd_t *vfs_fd, void *buf, u64 count, u64 offset);
int raw_vfs_pread(vfs_fd_t *vfs_fd, void *buf, u64 count, u64 offset);
int vfs_pread(int fd, void *buf, u64 count, u64 offset);
vfs_vm_object_t *vfs_get_vm_object(int fd, u64 length, u64 offset);
+int vfs_dup(int fd);
int vfs_dup2(int org_fd, int new_fd);
vfs_inode_t *vfs_internal_open(const char *file);
int vfs_mkdir(const char *path, int mode);
diff --git a/userland/libc/include/syscall.h b/userland/libc/include/syscall.h
index a0303f4..95ab817 100644
--- a/userland/libc/include/syscall.h
+++ b/userland/libc/include/syscall.h
@@ -53,6 +53,7 @@
#define SYS_QUEUE_WAIT 45
#define SYS_SENDFILE 46
#define SYS_SHM_UNLINK 47
+#define SYS_DUP 48
int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx,
uint32_t esi, uint32_t edi);
diff --git a/userland/libc/include/unistd.h b/userland/libc/include/unistd.h
index b44ca3e..3f17df4 100644
--- a/userland/libc/include/unistd.h
+++ b/userland/libc/include/unistd.h
@@ -15,6 +15,7 @@ int close(int fildes);
int ftruncate(int fildes, size_t length);
int execv(char *path, char **argv);
int pipe(int fd[2]);
+int dup(int fildes);
int dup2(int org_fd, int new_fd);
int getopt(int argc, char *const argv[], const char *optstring);
pid_t getpid(void);
diff --git a/userland/libc/unistd/dup.c b/userland/libc/unistd/dup.c
new file mode 100644
index 0000000..176659b
--- /dev/null
+++ b/userland/libc/unistd/dup.c
@@ -0,0 +1,6 @@
+#include <syscall.h>
+#include <unistd.h>
+
+int dup(int fildes) {
+ RC_ERRNO(syscall(SYS_DUP, (u32)fildes, 0, 0, 0, 0));
+}