Serenity Operating System
at master 89 lines 2.8 kB view raw
1/* 2 * Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/RefPtr.h> 8#include <AK/Singleton.h> 9#include <AK/StringBuilder.h> 10#include <AK/StringView.h> 11#include <AK/Vector.h> 12#include <Kernel/FileSystem/Custody.h> 13#include <Kernel/FileSystem/Inode.h> 14 15namespace Kernel { 16 17static Singleton<SpinlockProtected<Custody::AllCustodiesList, LockRank::None>> s_all_instances; 18 19SpinlockProtected<Custody::AllCustodiesList, LockRank::None>& Custody::all_instances() 20{ 21 return s_all_instances; 22} 23 24ErrorOr<NonnullRefPtr<Custody>> Custody::try_create(Custody* parent, StringView name, Inode& inode, int mount_flags) 25{ 26 return all_instances().with([&](auto& all_custodies) -> ErrorOr<NonnullRefPtr<Custody>> { 27 for (Custody& custody : all_custodies) { 28 if (custody.parent() == parent 29 && custody.name() == name 30 && &custody.inode() == &inode 31 && custody.mount_flags() == mount_flags) { 32 return NonnullRefPtr { custody }; 33 } 34 } 35 36 auto name_kstring = TRY(KString::try_create(name)); 37 auto custody = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) Custody(parent, move(name_kstring), inode, mount_flags))); 38 all_custodies.prepend(*custody); 39 return custody; 40 }); 41} 42 43Custody::Custody(Custody* parent, NonnullOwnPtr<KString> name, Inode& inode, int mount_flags) 44 : m_parent(parent) 45 , m_name(move(name)) 46 , m_inode(inode) 47 , m_mount_flags(mount_flags) 48{ 49} 50 51Custody::~Custody() = default; 52 53ErrorOr<NonnullOwnPtr<KString>> Custody::try_serialize_absolute_path() const 54{ 55 if (!parent()) 56 return KString::try_create("/"sv); 57 58 Vector<Custody const*, 32> custody_chain; 59 size_t path_length = 0; 60 for (auto const* custody = this; custody; custody = custody->parent()) { 61 TRY(custody_chain.try_append(custody)); 62 path_length += custody->m_name->length() + 1; 63 } 64 VERIFY(path_length > 0); 65 66 char* buffer; 67 auto string = TRY(KString::try_create_uninitialized(path_length - 1, buffer)); 68 size_t string_index = 0; 69 for (size_t custody_index = custody_chain.size() - 1; custody_index > 0; --custody_index) { 70 buffer[string_index] = '/'; 71 ++string_index; 72 auto const& custody_name = *custody_chain[custody_index - 1]->m_name; 73 __builtin_memcpy(buffer + string_index, custody_name.characters(), custody_name.length()); 74 string_index += custody_name.length(); 75 } 76 VERIFY(string->length() == string_index); 77 buffer[string_index] = 0; 78 return string; 79} 80 81bool Custody::is_readonly() const 82{ 83 if (m_mount_flags & MS_RDONLY) 84 return true; 85 86 return m_inode->fs().is_readonly(); 87} 88 89}