diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index b0b4ccfa59..84ea356185 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -1806,6 +1807,35 @@ int Process::sys$mkdir(const char* pathname, mode_t mode) return VFS::the().mkdir(StringView(pathname, pathname_length), mode & ~umask(), current_directory()); } +int Process::sys$realpath(const char* pathname, char* buffer, size_t size) +{ + if (!validate_read_str(pathname)) + return -EFAULT; + + size_t pathname_length = strlen(pathname); + if (pathname_length == 0) + return -EINVAL; + if (pathname_length >= size) + return -ENAMETOOLONG; + if (!validate_write(buffer, size)) + return -EFAULT; + + auto custody_or_error = VFS::the().resolve_path(pathname, current_directory()); + if (custody_or_error.is_error()) + return custody_or_error.error(); + auto& custody = custody_or_error.value(); + + // FIXME: Once resolve_path is fixed to deal with .. and . , remove the use of FileSystemPath::canonical_path. + FileSystemPath canonical_path(custody->absolute_path()); + if (!canonical_path.is_valid()) { + printf("FileSystemPath failed to canonicalize '%s'\n", custody->absolute_path()); + return 1; + } + + strncpy(buffer, canonical_path.string().characters(), size); + return 0; +}; + clock_t Process::sys$times(tms* times) { if (!validate_write_typed(times)) diff --git a/Kernel/Process.h b/Kernel/Process.h index 919df12f56..e34e1bc22c 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -222,6 +222,7 @@ public: int sys$halt(); int sys$reboot(); int sys$set_process_icon(int icon_id); + int sys$realpath(const char* pathname, char*, size_t); static void initialize(); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index eff996fbfb..ac40386569 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -311,6 +311,8 @@ static u32 handle(RegisterDump& regs, u32 function, u32 arg1, u32 arg2, u32 arg3 return current->process().sys$mprotect((void*)arg1, (size_t)arg2, (int)arg3); case Syscall::SC_get_process_name: return current->process().sys$get_process_name((char*)arg1, (int)arg2); + case Syscall::SC_realpath: + return current->process().sys$realpath((const char*)arg1, (char*)arg2, (size_t)arg3); default: kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3); return -ENOSYS; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 92ebf16675..d0690a676f 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -125,6 +125,7 @@ struct timeval; __ENUMERATE_SYSCALL(share_buffer_globally) \ __ENUMERATE_SYSCALL(set_process_icon) \ __ENUMERATE_SYSCALL(mprotect) \ + __ENUMERATE_SYSCALL(realpath) \ __ENUMERATE_SYSCALL(get_process_name) namespace Syscall {