diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 88e73104..6430b206 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -58,6 +58,7 @@ namespace Kernel BAN::ErrorOr setenvp(char** envp); BAN::ErrorOr open(BAN::StringView, int); + BAN::ErrorOr openat(int, BAN::StringView, int); BAN::ErrorOr close(int fd); BAN::ErrorOr read(int fd, void* buffer, size_t count); BAN::ErrorOr write(int fd, const void* buffer, size_t count); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 3a77a6d7..9bab8124 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -469,6 +469,22 @@ namespace Kernel return fd; } + BAN::ErrorOr Process::openat(int fd, BAN::StringView path, int flags) + { + BAN::String absolute_path; + + { + LockGuard _(m_lock); + TRY(validate_fd(fd)); + TRY(absolute_path.append(open_file_description(fd).path)); + } + + TRY(absolute_path.push_back('/')); + TRY(absolute_path.append(path)); + + return open(absolute_path, flags); + } + BAN::ErrorOr Process::close(int fd) { LockGuard _(m_lock); diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index 648af54d..7d3f6c3a 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -48,6 +48,14 @@ namespace Kernel return -res.error().get_error_code(); return res.value(); } + + int sys_openat(int fd, const char* path, int oflags) + { + auto res = Process::current().openat(fd, path, oflags); + if (res.is_error()) + return -res.error().get_error_code(); + return res.value(); + } long sys_alloc(size_t bytes) { @@ -187,6 +195,9 @@ namespace Kernel case SYS_OPEN: ret = sys_open((const char*)arg1, (int)arg2); break; + case SYS_OPENAT: + ret = sys_openat((int)arg1, (const char*)arg2, (int)arg3); + break; case SYS_ALLOC: ret = sys_alloc((size_t)arg1); break; diff --git a/libc/fcntl.cpp b/libc/fcntl.cpp index 6be03408..d4e05ded 100644 --- a/libc/fcntl.cpp +++ b/libc/fcntl.cpp @@ -7,3 +7,8 @@ int open(const char* path, int oflag, ...) { return syscall(SYS_OPEN, path, oflag); } + +int openat(int fd, const char* path, int oflag, ...) +{ + return syscall(SYS_OPENAT, fd, path, oflag); +} diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 5fc7c9a9..78af2442 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -11,20 +11,21 @@ __BEGIN_DECLS #define SYS_TERMID 4 #define SYS_CLOSE 5 #define SYS_OPEN 6 -#define SYS_ALLOC 7 -#define SYS_FREE 8 -#define SYS_SEEK 9 -#define SYS_TELL 10 -#define SYS_GET_TERMIOS 11 -#define SYS_SET_TERMIOS 12 -#define SYS_FORK 13 -#define SYS_SLEEP 14 -#define SYS_EXEC 15 -#define SYS_REALLOC 16 -#define SYS_WAIT 17 -#define SYS_FSTAT 18 -#define SYS_SETENVP 19 -#define SYS_READ_DIR_ENTRIES 20 +#define SYS_OPENAT 7 +#define SYS_ALLOC 8 +#define SYS_REALLOC 9 +#define SYS_FREE 10 +#define SYS_SEEK 11 +#define SYS_TELL 12 +#define SYS_GET_TERMIOS 13 +#define SYS_SET_TERMIOS 14 +#define SYS_FORK 15 +#define SYS_EXEC 16 +#define SYS_SLEEP 17 +#define SYS_WAIT 18 +#define SYS_FSTAT 19 +#define SYS_SETENVP 20 +#define SYS_READ_DIR_ENTRIES 21 __END_DECLS