From af4b13809409b1bae32fc6a33d6f27dec93ca938 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 25 Jun 2024 19:29:08 +0300 Subject: [PATCH] Kernel/LibC: Implement realpath realpath is implemented as a syscall. This is not really required but it was the easiest way to get it working as there is already path canonicalization at kernel level. --- kernel/include/kernel/Process.h | 2 ++ kernel/kernel/Process.cpp | 16 ++++++++++++++++ userspace/libraries/LibC/include/sys/syscall.h | 1 + userspace/libraries/LibC/stdlib.cpp | 17 +++++++++++++++++ 4 files changed, 36 insertions(+) diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 058c2861..ad702826 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -149,6 +149,8 @@ namespace Kernel BAN::ErrorOr sys_fstatat(int fd, const char* path, struct stat* buf, int flag); BAN::ErrorOr sys_stat(const char* path, struct stat* buf, int flag); + BAN::ErrorOr sys_realpath(const char* path, char* buffer); + BAN::ErrorOr sys_sync(bool should_block); static BAN::ErrorOr clean_poweroff(int command); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 508f3deb..447a327d 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1238,6 +1238,22 @@ namespace Kernel return 0; } + BAN::ErrorOr Process::sys_realpath(const char* path, char* buffer) + { + LockGuard _(m_process_lock); + TRY(validate_string_access(path)); + TRY(validate_pointer_access(buffer, PATH_MAX)); + + auto absolute_path = TRY(absolute_path_of(path)); + + auto file = TRY(VirtualFileSystem::get().file_from_absolute_path(m_credentials, absolute_path, O_SEARCH)); + if (file.canonical_path.size() >= PATH_MAX) + return BAN::Error::from_errno(ENAMETOOLONG); + + strcpy(buffer, file.canonical_path.data()); + return file.canonical_path.size(); + } + BAN::ErrorOr Process::sys_sync(bool should_block) { DevFileSystem::get().initiate_sync(should_block); diff --git a/userspace/libraries/LibC/include/sys/syscall.h b/userspace/libraries/LibC/include/sys/syscall.h index 276c22c0..1d2c85f1 100644 --- a/userspace/libraries/LibC/include/sys/syscall.h +++ b/userspace/libraries/LibC/include/sys/syscall.h @@ -81,6 +81,7 @@ __BEGIN_DECLS O(SYS_GETSOCKNAME, getsockname) \ O(SYS_GETSOCKOPT, getsockopt) \ O(SYS_SETSOCKOPT, setsockopt) \ + O(SYS_REALPATH, realpath) \ enum Syscall { diff --git a/userspace/libraries/LibC/stdlib.cpp b/userspace/libraries/LibC/stdlib.cpp index e67b5a5e..f6598252 100644 --- a/userspace/libraries/LibC/stdlib.cpp +++ b/userspace/libraries/LibC/stdlib.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -368,6 +369,22 @@ char* getenv(const char* name) return nullptr; } +char* realpath(const char* __restrict file_name, char* __restrict resolved_name) +{ + char buffer[PATH_MAX] {}; + long canonical_length = syscall(SYS_REALPATH, file_name, buffer); + if (canonical_length == -1) + return NULL; + if (resolved_name == NULL) + { + resolved_name = static_cast(malloc(canonical_length + 1)); + if (resolved_name == NULL) + return NULL; + } + strcpy(resolved_name, buffer); + return resolved_name; +} + int system(const char* command) { // FIXME