/* * Copyright (c) 2018-2021, Andreas Kling * Copyright (c) 2021, Spencer Dixon * Copyright (c) 2021, Liav A. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include #include #include #include #include #include #include namespace Kernel { static AK::Singleton s_the; ProcFSComponentsRegistrar& ProcFSComponentsRegistrar::the() { return *s_the; } UNMAP_AFTER_INIT void ProcFSComponentsRegistrar::initialize() { VERIFY(!s_the.is_initialized()); s_the.ensure_instance(); } UNMAP_AFTER_INIT ProcFSComponentsRegistrar::ProcFSComponentsRegistrar() : m_root_folder(ProcFSRootFolder::must_create()) { } const ProcFSBusDirectory& ProcFSComponentsRegistrar::buses_folder() const { return *m_root_folder->m_buses_folder; } void ProcFSComponentsRegistrar::register_new_bus_folder(ProcFSExposedFolder& new_bus_folder) { VERIFY(!m_root_folder->m_buses_folder.is_null()); m_root_folder->m_buses_folder->m_components.append(new_bus_folder); } void ProcFSComponentsRegistrar::register_new_process(Process& new_process) { Locker locker(m_lock); m_root_folder->m_process_folders.append(ProcFSProcessFolder::create(new_process)); } void ProcFSComponentsRegistrar::unregister_process(Process& deleted_process) { auto process_folder = m_root_folder->process_folder_for(deleted_process).release_nonnull(); process_folder->prepare_for_deletion(); process_folder->m_list_node.remove(); dbgln_if(PROCFS_DEBUG, "ProcFSExposedFolder ref_count now: {}", process_folder->ref_count()); // Note: Let's ensure we are the last holder of the ProcFSProcessFolder object before it can be deleted for good VERIFY(process_folder->ref_count() == 1); } RefPtr ProcFS::create() { return adopt_ref_if_nonnull(new (nothrow) ProcFS); } ProcFS::~ProcFS() { } bool ProcFS::initialize() { return true; } NonnullRefPtr ProcFS::root_inode() const { return *m_root_inode; } NonnullRefPtr ProcFSInode::create(const ProcFS& fs, const ProcFSExposedComponent& component) { return adopt_ref(*new (nothrow) ProcFSInode(fs, component)); } ProcFSInode::ProcFSInode(const ProcFS& fs, const ProcFSExposedComponent& component) : Inode(const_cast(fs), component.component_index()) , m_associated_component(component) { } KResult ProcFSInode::attach(FileDescription& description) { return m_associated_component->refresh_data(description); } void ProcFSInode::did_seek(FileDescription& description, off_t new_offset) { if (new_offset != 0) return; auto result = m_associated_component->refresh_data(description); if (result.is_error()) { // Subsequent calls to read will return EIO! dbgln("ProcFS: Could not refresh contents: {}", result.error()); } } ProcFSInode::~ProcFSInode() { } ProcFS::ProcFS() : m_root_inode(ProcFSComponentsRegistrar::the().m_root_folder->to_inode(*this)) { } KResultOr ProcFSInode::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* fd) const { return m_associated_component->read_bytes(offset, count, buffer, fd); } StringView ProcFSInode::name() const { return m_associated_component->name(); } KResult ProcFSInode::traverse_as_directory(Function) const { VERIFY_NOT_REACHED(); } RefPtr ProcFSInode::lookup(StringView) { VERIFY_NOT_REACHED(); } InodeMetadata ProcFSInode::metadata() const { Locker locker(m_lock); InodeMetadata metadata; metadata.inode = { fsid(), m_associated_component->component_index() }; metadata.mode = m_associated_component->required_mode(); metadata.uid = m_associated_component->owner_user(); metadata.gid = m_associated_component->owner_group(); metadata.size = m_associated_component->size(); metadata.mtime = m_associated_component->modified_time(); return metadata; } void ProcFSInode::flush_metadata() { } KResultOr ProcFSInode::write_bytes(off_t offset, size_t count, const UserOrKernelBuffer& buffer, FileDescription* fd) { return m_associated_component->write_bytes(offset, count, buffer, fd); } KResultOr> ProcFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) { return EROFS; } KResult ProcFSInode::add_child(Inode&, const StringView&, mode_t) { return EROFS; } KResult ProcFSInode::remove_child(const StringView&) { return EROFS; } KResultOr ProcFSInode::directory_entry_count() const { VERIFY_NOT_REACHED(); } KResult ProcFSInode::chmod(mode_t) { return EPERM; } KResult ProcFSInode::chown(uid_t, gid_t) { return EPERM; } KResult ProcFSInode::truncate(u64) { return EPERM; } NonnullRefPtr ProcFSDirectoryInode::create(const ProcFS& procfs, const ProcFSExposedComponent& component) { return adopt_ref(*new (nothrow) ProcFSDirectoryInode(procfs, component)); } ProcFSDirectoryInode::ProcFSDirectoryInode(const ProcFS& fs, const ProcFSExposedComponent& component) : ProcFSInode(fs, component) , m_parent_fs(const_cast(fs)) { } ProcFSDirectoryInode::~ProcFSDirectoryInode() { } InodeMetadata ProcFSDirectoryInode::metadata() const { Locker locker(m_lock); InodeMetadata metadata; metadata.inode = { fsid(), m_associated_component->component_index() }; metadata.mode = S_IFDIR | m_associated_component->required_mode(); metadata.uid = m_associated_component->owner_user(); metadata.gid = m_associated_component->owner_group(); metadata.size = 0; metadata.mtime = m_associated_component->modified_time(); return metadata; } KResult ProcFSDirectoryInode::traverse_as_directory(Function callback) const { Locker locker(m_parent_fs.m_lock); return m_associated_component->traverse_as_directory(m_parent_fs.fsid(), move(callback)); } RefPtr ProcFSDirectoryInode::lookup(StringView name) { Locker locker(m_parent_fs.m_lock); auto component = m_associated_component->lookup(name); if (!component) return {}; return component->to_inode(m_parent_fs); } KResultOr ProcFSDirectoryInode::directory_entry_count() const { Locker locker(m_lock); return m_associated_component->entries_count(); } NonnullRefPtr ProcFSLinkInode::create(const ProcFS& procfs, const ProcFSExposedComponent& component) { return adopt_ref(*new (nothrow) ProcFSLinkInode(procfs, component)); } ProcFSLinkInode::ProcFSLinkInode(const ProcFS& fs, const ProcFSExposedComponent& component) : ProcFSInode(fs, component) { } InodeMetadata ProcFSLinkInode::metadata() const { Locker locker(m_lock); InodeMetadata metadata; metadata.inode = { fsid(), m_associated_component->component_index() }; metadata.mode = S_IFLNK | m_associated_component->required_mode(); metadata.uid = m_associated_component->owner_user(); metadata.gid = m_associated_component->owner_group(); metadata.size = 0; metadata.mtime = m_associated_component->modified_time(); return metadata; } }