From eef01078bb79d26cf4d571ec2d7e3fcb904373de Mon Sep 17 00:00:00 2001 From: Matheus Date: Fri, 30 Sep 2022 17:04:18 -0300 Subject: [PATCH] syscalls: fstatat --- src/arch/x86_64/syscall.asm | 4 +- src/sys/syscalls/fstatat.c | 79 +++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/sys/syscalls/fstatat.c diff --git a/src/arch/x86_64/syscall.asm b/src/arch/x86_64/syscall.asm index b00ffdba..bbcfb8d3 100644 --- a/src/arch/x86_64/syscall.asm +++ b/src/arch/x86_64/syscall.asm @@ -24,7 +24,8 @@ extern syscall_getpid extern syscall_getdirent extern syscall_ioctl extern syscall_chdir -func_count equ 23 +extern syscall_fstatat +func_count equ 24 func_table: @@ -51,6 +52,7 @@ func_table: dq syscall_getdirent dq syscall_ioctl dq syscall_chdir + dq syscall_fstatat section .text global asm_syscall_entry diff --git a/src/sys/syscalls/fstatat.c b/src/sys/syscalls/fstatat.c new file mode 100644 index 00000000..55a4ee25 --- /dev/null +++ b/src/sys/syscalls/fstatat.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include +#include + +#define AT_FDCWD -100 + +syscallret syscall_fstatat(int ifd, char* path, stat* st, int flags){ + syscallret retv; + retv.ret = -1; + + if(flags){ + retv.errno = EINVAL; + return retv; + } + + if(st > USER_SPACE_END || path > USER_SPACE_END){ + retv.errno = EFAULT; + return retv; + } + + size_t len = strlen(path); + + char buff[len+1]; + + strcpy(buff, path); + + proc_t* proc = arch_getcls()->thread->proc; + + dirnode_t* targnode; + fd_t* fd; + + if(ifd != AT_FDCWD){ + + + int err = fd_access(&proc->fdtable, &fd, ifd); + + if(err){ + retv.errno = err; + return retv; + } + + if(buff[0] != '/' && GETTYPE(fd->mode) != TYPE_DIR){ + retv.errno = ENOTDIR; + goto _fail; + } + + targnode = fd->node; + + } + else + targnode = proc->cwd; + + + vnode_t* node; + + retv.errno = vfs_open(&node, buff[0] == '/' ? proc->root : targnode, buff); + + if(retv.errno) + goto _fail; + + + memcpy(st, &node->st, sizeof(stat)); // XXX user memcpy + + vfs_close(node); + + _fail: + + if(ifd != AT_FDCWD) + fd_release(fd); + + retv.ret = 0; + + return retv; + +}