Serenity Operating System
at master 61 lines 2.0 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/RefPtr.h> 8#include <Kernel/FileSystem/Custody.h> 9#include <Kernel/FileSystem/VirtualFileSystem.h> 10#include <Kernel/Process.h> 11 12namespace Kernel { 13 14ErrorOr<FlatPtr> Process::sys$chdir(Userspace<char const*> user_path, size_t path_length) 15{ 16 VERIFY_NO_PROCESS_BIG_LOCK(this); 17 TRY(require_promise(Pledge::rpath)); 18 auto path = TRY(get_syscall_path_argument(user_path, path_length)); 19 auto current_directory = m_current_directory.with([](auto& current_directory) -> NonnullRefPtr<Custody> { 20 return *current_directory; 21 }); 22 RefPtr<Custody> new_directory = TRY(VirtualFileSystem::the().open_directory(credentials(), path->view(), *current_directory)); 23 m_current_directory.with([&](auto& current_directory) { 24 // NOTE: We use swap() here to avoid manipulating the ref counts while holding the lock. 25 swap(current_directory, new_directory); 26 }); 27 return 0; 28} 29 30ErrorOr<FlatPtr> Process::sys$fchdir(int fd) 31{ 32 VERIFY_NO_PROCESS_BIG_LOCK(this); 33 TRY(require_promise(Pledge::stdio)); 34 auto description = TRY(open_file_description(fd)); 35 if (!description->is_directory()) 36 return ENOTDIR; 37 if (!description->metadata().may_execute(credentials())) 38 return EACCES; 39 m_current_directory.with([&](auto& current_directory) { 40 current_directory = description->custody(); 41 }); 42 return 0; 43} 44 45ErrorOr<FlatPtr> Process::sys$getcwd(Userspace<char*> buffer, size_t size) 46{ 47 VERIFY_NO_PROCESS_BIG_LOCK(this); 48 TRY(require_promise(Pledge::rpath)); 49 50 if (size > NumericLimits<ssize_t>::max()) 51 return EINVAL; 52 53 auto path = TRY(current_directory()->try_serialize_absolute_path()); 54 size_t ideal_size = path->length() + 1; 55 auto size_to_copy = min(ideal_size, size); 56 TRY(copy_to_user(buffer, path->characters(), size_to_copy)); 57 // Note: we return the whole size here, not the copied size. 58 return ideal_size; 59} 60 61}