Serenity Operating System
at master 76 lines 2.5 kB view raw
1/* 2 * Copyright (c) 2022, Ariel Don <ariel@arieldon.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Assertions.h> 8#include <AK/StringView.h> 9#include <Kernel/FileSystem/VirtualFileSystem.h> 10#include <Kernel/KLexicalPath.h> 11#include <Kernel/Process.h> 12 13namespace Kernel { 14 15ErrorOr<FlatPtr> Process::sys$utimensat(Userspace<Syscall::SC_utimensat_params const*> user_params) 16{ 17 VERIFY_NO_PROCESS_BIG_LOCK(this); 18 TRY(require_promise(Pledge::fattr)); 19 20 auto params = TRY(copy_typed_from_user(user_params)); 21 auto now = kgettimeofday().to_timespec(); 22 23 int dirfd = params.dirfd; 24 int follow_symlink = params.flag & AT_SYMLINK_NOFOLLOW ? O_NOFOLLOW_NOERROR : 0; 25 26 timespec times[2]; 27 if (params.times) { 28 TRY(copy_from_user(times, params.times, sizeof(times))); 29 if (times[0].tv_nsec == UTIME_NOW) 30 times[0] = now; 31 if (times[1].tv_nsec == UTIME_NOW) 32 times[1] = now; 33 } else { 34 // According to POSIX, both access and modification times are set to 35 // the current time given a nullptr. 36 times[0] = now; 37 times[1] = now; 38 } 39 40 OwnPtr<KString> path; 41 RefPtr<OpenFileDescription> description; 42 RefPtr<Custody> base; 43 44 auto path_or_error = get_syscall_path_argument(params.path); 45 if (path_or_error.is_error()) { 46 // If the path is empty ("") but not a nullptr, attempt to get a path 47 // from the file descriptor. This allows futimens() to be implemented 48 // in terms of utimensat(). 49 if (params.path.characters && params.path.length == 0) { 50 description = TRY(open_file_description(dirfd)); 51 path = TRY(description->original_absolute_path()); 52 base = description->custody(); 53 } else { 54 return path_or_error.release_error(); 55 } 56 } else { 57 path = path_or_error.release_value(); 58 if (dirfd == AT_FDCWD) { 59 base = current_directory(); 60 } else { 61 description = TRY(open_file_description(dirfd)); 62 if (!KLexicalPath::is_absolute(path->view()) && !description->is_directory()) 63 return ENOTDIR; 64 if (!description->custody()) 65 return EINVAL; 66 base = description->custody(); 67 } 68 } 69 70 auto& atime = times[0]; 71 auto& mtime = times[1]; 72 TRY(VirtualFileSystem::the().utimensat(credentials(), path->view(), *base, atime, mtime, follow_symlink)); 73 return 0; 74} 75 76}