From 4834353501fa92f8ba5dbfa80f557981d3bf8ef5 Mon Sep 17 00:00:00 2001 From: Matheus Date: Fri, 21 Oct 2022 13:25:29 -0300 Subject: [PATCH] syscalls: link at --- src/arch/x86_64/syscall.asm | 4 +- src/fs/tmpfs.c | 6 ++- src/sys/syscalls/linkat.c | 95 +++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 src/sys/syscalls/linkat.c diff --git a/src/arch/x86_64/syscall.asm b/src/arch/x86_64/syscall.asm index 8e5993b7..8f8e9b63 100644 --- a/src/arch/x86_64/syscall.asm +++ b/src/arch/x86_64/syscall.asm @@ -42,7 +42,8 @@ extern syscall_connect extern syscall_accept extern syscall_nanosleep extern syscall_fchmod -func_count equ 41 +extern syscall_linkat +func_count equ 42 func_table: @@ -87,6 +88,7 @@ func_table: dq syscall_accept dq syscall_nanosleep dq syscall_fchmod + dq syscall_linkat section .text global asm_syscall_entry diff --git a/src/fs/tmpfs.c b/src/fs/tmpfs.c index af6836b0..0632f6fa 100644 --- a/src/fs/tmpfs.c +++ b/src/fs/tmpfs.c @@ -220,13 +220,15 @@ static int tmpfs_readlink(vnode_t *node, char** buff, size_t* linksize){ } -static int tmpfs_link(dirnode_t* parent, char* name, vnode_t* link){ - +static int tmpfs_link(dirnode_t* parent, vnode_t* link, char* name){ + if(!hashtable_insert(&parent->children, name, link)) return ENOMEM; ++link->st.st_nlink; + return 0; + } static fscalls_t funcs = { diff --git a/src/sys/syscalls/linkat.c b/src/sys/syscalls/linkat.c new file mode 100644 index 00000000..91c75735 --- /dev/null +++ b/src/sys/syscalls/linkat.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include +#include + + +static int gettarget(fd_t** targ, dirnode_t** targnode, int ifd, proc_t* proc){ + + if(ifd != AT_FDCWD){ + + int err = fd_access(&proc->fdtable, targ, ifd); + + if(err) + return err; + + + if(GETTYPE((*targ)->mode) != TYPE_DIR) + return ENOTDIR; + + + *targnode = (*targ)->node; + } + else + *targnode = proc->cwd; + +} + + +// flags is ignored for now + +syscallret syscall_linkat(int srcdirfd, const char* srcpath, int tgtdirfd, const char* tgtpath, int flags){ + + syscallret retv; + retv.ret = -1; + + + if(srcpath > USER_SPACE_END || tgtpath > USER_SPACE_END){ + retv.errno = EFAULT; + return retv; + } + + size_t srclen = strlen(srcpath); + size_t tgtlen = strlen(tgtpath); + + char srcbuff[srclen+1]; + char tgtbuff[tgtlen+1]; + + strcpy(srcbuff, srcpath); + strcpy(tgtbuff, tgtpath); + + proc_t* proc = arch_getcls()->thread->proc; + + + dirnode_t* source; + fd_t* srcfd = NULL; + dirnode_t* target; + fd_t* tgtfd = NULL; + + retv.errno = gettarget(&srcfd, &source, srcdirfd, proc); + + if(retv.errno) + goto _fail; + + retv.errno = gettarget(&tgtfd, &target, tgtdirfd, proc); + + if(retv.errno) + goto _fail; + + vnode_t* node; + + retv.errno = vfs_open(&node, srcbuff[0] == '/' ? proc->root : source, srcbuff); + + if(retv.errno) + goto _fail; + + retv.errno = vfs_link(tgtbuff[0] == '/' ? proc->root : target, node, tgtbuff); + + vfs_close(node); + + _fail: + + if(srcdirfd != AT_FDCWD && srcfd) + fd_release(srcfd); + + if(tgtdirfd != AT_FDCWD && tgtfd) + fd_release(tgtfd); + + retv.ret = retv.errno ? -1 : 0; + + return retv; + +}