summaryrefslogtreecommitdiff
path: root/Kernel/Syscalls/utimensat.cpp
diff options
context:
space:
mode:
authorAriel Don <ariel@arieldon.com>2022-05-02 15:26:10 -0500
committerAndreas Kling <kling@serenityos.org>2022-05-21 18:15:00 +0200
commit9a6bd859243df604c1b1f1762bb701165917f367 (patch)
tree45e15f48dcc9c2b996e02ac925da99b278226d0c /Kernel/Syscalls/utimensat.cpp
parent7550017f97d7892f8b7d26074046a87144f491dd (diff)
downloadserenity-9a6bd859243df604c1b1f1762bb701165917f367.zip
Kernel+LibC+VFS: Implement utimensat(3)
Create POSIX utimensat() library call and corresponding system call to update file access and modification times.
Diffstat (limited to 'Kernel/Syscalls/utimensat.cpp')
-rw-r--r--Kernel/Syscalls/utimensat.cpp61
1 files changed, 61 insertions, 0 deletions
diff --git a/Kernel/Syscalls/utimensat.cpp b/Kernel/Syscalls/utimensat.cpp
new file mode 100644
index 0000000000..4a6ca189a3
--- /dev/null
+++ b/Kernel/Syscalls/utimensat.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022, Ariel Don <ariel@arieldon.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <AK/Assertions.h>
+#include <AK/StringView.h>
+#include <Kernel/FileSystem/VirtualFileSystem.h>
+#include <Kernel/KLexicalPath.h>
+#include <Kernel/Process.h>
+
+namespace Kernel {
+
+ErrorOr<FlatPtr> Process::sys$utimensat(Userspace<Syscall::SC_utimensat_params const*> user_params)
+{
+ VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
+ TRY(require_promise(Pledge::fattr));
+
+ auto params = TRY(copy_typed_from_user(user_params));
+ auto now = kgettimeofday().to_truncated_seconds();
+
+ timespec times[2];
+ if (params.times) {
+ TRY(copy_from_user(times, params.times, sizeof(times)));
+ if (times[0].tv_nsec == UTIME_NOW)
+ times[0].tv_sec = now;
+ if (times[1].tv_nsec == UTIME_NOW)
+ times[1].tv_sec = now;
+ } else {
+ // According to POSIX, both access and modification times are set to
+ // the current time given a nullptr.
+ times[0].tv_sec = now;
+ times[0].tv_nsec = UTIME_NOW;
+ times[1].tv_sec = now;
+ times[1].tv_nsec = UTIME_NOW;
+ }
+
+ int dirfd = params.dirfd;
+ auto path = TRY(get_syscall_path_argument(params.path));
+
+ RefPtr<Custody> base;
+ if (dirfd == AT_FDCWD) {
+ base = current_directory();
+ } else {
+ auto base_description = TRY(open_file_description(dirfd));
+ if (!KLexicalPath::is_absolute(path->view()) && !base_description->is_directory())
+ return ENOTDIR;
+ if (!base_description->custody())
+ return EINVAL;
+ base = base_description->custody();
+ }
+
+ auto& atime = times[0];
+ auto& mtime = times[1];
+ int follow_symlink = params.flag & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW_NOERROR : 0;
+ TRY(VirtualFileSystem::the().utimensat(path->view(), *base, atime, mtime, follow_symlink));
+ return 0;
+}
+
+}