diff options
-rw-r--r-- | kernel/cpu/syscall.c | 5 | ||||
-rw-r--r-- | kernel/fs/vfs.c | 13 | ||||
-rw-r--r-- | kernel/fs/vfs.h | 1 | ||||
-rw-r--r-- | userland/libc/include/syscall.h | 1 | ||||
-rw-r--r-- | userland/libc/include/unistd.h | 1 | ||||
-rw-r--r-- | userland/libc/unistd/dup.c | 6 |
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(¤t_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)); +} |