summaryrefslogtreecommitdiff
path: root/Kernel/Syscalls
diff options
context:
space:
mode:
authorDaniel Bertalan <dani@danielbertalan.dev>2022-01-11 16:51:34 +0100
committerAndreas Kling <kling@serenityos.org>2022-01-12 14:54:12 +0100
commit182016d7c0059e9cfd74124c3d732060d31f3cec (patch)
treeda1c24baf53142d00e3aee901ca858f6c6580150 /Kernel/Syscalls
parent5f71925aa42ca3c5665d66ec5ada87494ad0a885 (diff)
downloadserenity-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.cpp19
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;
}