diff options
author | sin-ack <sin-ack@users.noreply.github.com> | 2022-10-01 11:15:02 +0000 |
---|---|---|
committer | Andrew Kaster <andrewdkaster@gmail.com> | 2022-12-11 19:55:37 -0700 |
commit | 9850a69cd199d48bc30a34e2fe38d5590b536aac (patch) | |
tree | 506a12437ac1651c9e25b2e08cdbc63ac80bf119 | |
parent | 5c1d5ed51da2cf3b9463413f704ea0e740950736 (diff) | |
download | serenity-9850a69cd199d48bc30a34e2fe38d5590b536aac.zip |
Kernel+LibC+LibCore: Implement `symlinkat(2)`
Co-Authored-By: Daniel Bertalan <dani@danielbertalan.dev>
-rw-r--r-- | Kernel/API/Syscall.h | 1 | ||||
-rw-r--r-- | Kernel/Syscalls/link.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibC/unistd.cpp | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibC/unistd.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibCore/System.cpp | 1 |
5 files changed, 11 insertions, 2 deletions
diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index f306e549b1..cd58e676bb 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -413,6 +413,7 @@ struct SC_mknod_params { struct SC_symlink_params { StringArgument target; StringArgument linkpath; + int dirfd; }; struct SC_rename_params { diff --git a/Kernel/Syscalls/link.cpp b/Kernel/Syscalls/link.cpp index 5cc048caa8..a94f02ac2f 100644 --- a/Kernel/Syscalls/link.cpp +++ b/Kernel/Syscalls/link.cpp @@ -29,7 +29,7 @@ ErrorOr<FlatPtr> Process::sys$symlink(Userspace<Syscall::SC_symlink_params const auto target = TRY(get_syscall_path_argument(params.target)); auto linkpath = TRY(get_syscall_path_argument(params.linkpath)); - TRY(VirtualFileSystem::the().symlink(credentials(), target->view(), linkpath->view(), current_directory())); + TRY(VirtualFileSystem::the().symlink(credentials(), target->view(), linkpath->view(), TRY(custody_for_dirfd(params.dirfd)))); return 0; } diff --git a/Userland/Libraries/LibC/unistd.cpp b/Userland/Libraries/LibC/unistd.cpp index e3fbca0e9f..8e732f197a 100644 --- a/Userland/Libraries/LibC/unistd.cpp +++ b/Userland/Libraries/LibC/unistd.cpp @@ -673,11 +673,17 @@ int unlinkat(int dirfd, char const* pathname, int flags) // https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlink.html int symlink(char const* target, char const* linkpath) { + return symlinkat(target, AT_FDCWD, linkpath); +} + +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html +int symlinkat(char const* target, int newdirfd, char const* linkpath) +{ if (!target || !linkpath) { errno = EFAULT; return -1; } - Syscall::SC_symlink_params params { { target, strlen(target) }, { linkpath, strlen(linkpath) } }; + Syscall::SC_symlink_params params { { target, strlen(target) }, { linkpath, strlen(linkpath) }, newdirfd }; int rc = syscall(SC_symlink, ¶ms); __RETURN_WITH_ERRNO(rc, rc, -1); } diff --git a/Userland/Libraries/LibC/unistd.h b/Userland/Libraries/LibC/unistd.h index ee4bf2f1ae..ef8c28ad47 100644 --- a/Userland/Libraries/LibC/unistd.h +++ b/Userland/Libraries/LibC/unistd.h @@ -95,6 +95,7 @@ int link(char const* oldpath, char const* newpath); int unlink(char const* pathname); int unlinkat(int dirfd, char const* pathname, int flags); int symlink(char const* target, char const* linkpath); +int symlinkat(char const* target, int newdirfd, char const* linkpath); int rmdir(char const* pathname); int dup(int old_fd); int dup2(int old_fd, int new_fd); diff --git a/Userland/Libraries/LibCore/System.cpp b/Userland/Libraries/LibCore/System.cpp index 2970c23dfe..f58b4952b7 100644 --- a/Userland/Libraries/LibCore/System.cpp +++ b/Userland/Libraries/LibCore/System.cpp @@ -839,6 +839,7 @@ ErrorOr<void> symlink(StringView target, StringView link_path) Syscall::SC_symlink_params params { .target = { target.characters_without_null_termination(), target.length() }, .linkpath = { link_path.characters_without_null_termination(), link_path.length() }, + .dirfd = AT_FDCWD, }; int rc = syscall(SC_symlink, ¶ms); HANDLE_SYSCALL_RETURN_VALUE("symlink", rc, {}); |