diff --git a/src/arch/x86_64/syscall.asm b/src/arch/x86_64/syscall.asm index 083b104b..a82595db 100644 --- a/src/arch/x86_64/syscall.asm +++ b/src/arch/x86_64/syscall.asm @@ -31,7 +31,8 @@ extern syscall_munmap extern syscall_umask extern syscall_poll extern syscall_fchmodat -func_count equ 30 +extern syscall_openat +func_count equ 31 func_table: @@ -65,6 +66,7 @@ func_table: dq syscall_umask dq syscall_poll dq syscall_fchmodat + dq syscall_openat section .text global asm_syscall_entry diff --git a/src/sys/syscalls/open.c b/src/sys/syscalls/open.c index ffa58ae3..5fc4e184 100644 --- a/src/sys/syscalls/open.c +++ b/src/sys/syscalls/open.c @@ -8,8 +8,7 @@ #include #include - -syscallret syscall_open(const char* pathname, int flags, mode_t mode){ +syscallret syscall_openat(int dirfd, const char* pathname, int flags, mode_t mode){ syscallret retv; retv.ret = -1; @@ -39,6 +38,26 @@ syscallret syscall_open(const char* pathname, int flags, mode_t mode){ return retv; } + fd_t* targfd; + dirnode_t* target; + + if(dirfd != AT_FDCWD){ + + err = fd_access(&proc->fdtable, &targfd, dirfd); + + if(err){ + retv.errno = err; + free(name); + fd_release(fd); + fd_free(&proc->fdtable, fd); + return retv; + } + + target = targfd->node; + + } + else target = proc->cwd; + fd->flags = flags + 1; // 1 is added to make O_RDONLY etc easier to lookup fd->offset = 0; @@ -47,8 +66,8 @@ syscallret syscall_open(const char* pathname, int flags, mode_t mode){ retry: size_t ret = vfs_open(&file, - *name == '/' ? proc->root : proc->cwd, - *name == '/' ? name + 1 : name + *name == '/' ? proc->root : target, + name ); if(ret == ENOENT && (flags & O_CREAT)){ @@ -93,9 +112,18 @@ syscallret syscall_open(const char* pathname, int flags, mode_t mode){ if(file) vfs_close(file); + if(dirfd != AT_FDCWD) + fd_release(targfd); + fd_release(fd); fd_free(&proc->fdtable, fd); free(name); return retv; } + +// kept so no ABI breaks happen + +syscallret syscall_open(const char* pathname, int flags, mode_t mode){ + return syscall_openat(AT_FDCWD, pathname, flags, mode); +}