diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2022-01-11 16:51:34 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-01-12 14:54:12 +0100 |
commit | 182016d7c0059e9cfd74124c3d732060d31f3cec (patch) | |
tree | da1c24baf53142d00e3aee901ca858f6c6580150 /Kernel/Syscalls | |
parent | 5f71925aa42ca3c5665d66ec5ada87494ad0a885 (diff) | |
download | serenity-182016d7c0059e9cfd74124c3d732060d31f3cec.zip |
Kernel+LibC+LibCore+UE: Implement `fchmodat(2)`
This function is an extended version of `chmod(2)` that lets one control
whether to dereference symlinks, and specify a file descriptor to a
directory that will be used as the base for relative paths.
Diffstat (limited to 'Kernel/Syscalls')
-rw-r--r-- | Kernel/Syscalls/chmod.cpp | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/Kernel/Syscalls/chmod.cpp b/Kernel/Syscalls/chmod.cpp index 34af280f07..9b79682afd 100644 --- a/Kernel/Syscalls/chmod.cpp +++ b/Kernel/Syscalls/chmod.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2022, Daniel Bertalan <dani@danielbertalan.dev> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -10,12 +11,24 @@ namespace Kernel { -ErrorOr<FlatPtr> Process::sys$chmod(Userspace<const char*> user_path, size_t path_length, mode_t mode) +ErrorOr<FlatPtr> Process::sys$chmod(Userspace<Syscall::SC_chmod_params const*> user_params) { VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this); TRY(require_promise(Pledge::fattr)); - auto path = TRY(get_syscall_path_argument(user_path, path_length)); - TRY(VirtualFileSystem::the().chmod(path->view(), mode, current_directory())); + auto params = TRY(copy_typed_from_user(user_params)); + auto path = TRY(get_syscall_path_argument(params.path)); + + RefPtr<Custody> base; + if (params.dirfd == AT_FDCWD) { + base = current_directory(); + } else { + auto base_description = TRY(fds().open_file_description(params.dirfd)); + if (!base_description->custody()) + return EINVAL; + base = base_description->custody(); + } + + TRY(VirtualFileSystem::the().chmod(path->view(), params.mode, *base, params.follow_symlinks ? 0 : O_NOFOLLOW_NOERROR)); return 0; } |