mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-28 21:54:40 +03:00
Kernel/FileSystem: Simplify the ProcFS inode code
This is done by merging all scattered pieces of derived classes from the ProcFSInode class into that one class, so we don't use inheritance but rather simplistic checks to determine the proper code for each ProcFS inode with its specific characteristics.
This commit is contained in:
parent
e9dcc49f9c
commit
722ae35329
Notes:
sideshowbarker
2024-07-17 01:04:03 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/722ae35329 Pull-request: https://github.com/SerenityOS/serenity/pull/16189 Reviewed-by: https://github.com/ADKaster
@ -132,15 +132,8 @@ set(KERNEL_SOURCES
|
||||
FileSystem/Plan9FS/Inode.cpp
|
||||
FileSystem/Plan9FS/Message.cpp
|
||||
FileSystem/ProcFS/ComponentRegistry.cpp
|
||||
FileSystem/ProcFS/DirectoryInode.cpp
|
||||
FileSystem/ProcFS/FileSystem.cpp
|
||||
FileSystem/ProcFS/GlobalInode.cpp
|
||||
FileSystem/ProcFS/Inode.cpp
|
||||
FileSystem/ProcFS/LinkInode.cpp
|
||||
FileSystem/ProcFS/ProcessAssociatedInode.cpp
|
||||
FileSystem/ProcFS/ProcessDirectoryInode.cpp
|
||||
FileSystem/ProcFS/ProcessPropertyInode.cpp
|
||||
FileSystem/ProcFS/ProcessSubDirectoryInode.cpp
|
||||
FileSystem/SysFS/Component.cpp
|
||||
FileSystem/SysFS/DirectoryInode.cpp
|
||||
FileSystem/SysFS/FileSystem.cpp
|
||||
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/DirectoryInode.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSDirectoryInode>> ProcFSDirectoryInode::try_create(ProcFS const& procfs, ProcFSExposedComponent const& component)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSDirectoryInode(procfs, component));
|
||||
}
|
||||
|
||||
ProcFSDirectoryInode::ProcFSDirectoryInode(ProcFS const& fs, ProcFSExposedComponent const& component)
|
||||
: ProcFSGlobalInode(fs, component)
|
||||
{
|
||||
}
|
||||
|
||||
ProcFSDirectoryInode::~ProcFSDirectoryInode() = default;
|
||||
|
||||
InodeMetadata ProcFSDirectoryInode::metadata() const
|
||||
{
|
||||
MutexLocker locker(m_inode_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;
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSDirectoryInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
|
||||
{
|
||||
MutexLocker locker(procfs().m_lock);
|
||||
return m_associated_component->traverse_as_directory(procfs().fsid(), move(callback));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSDirectoryInode::lookup(StringView name)
|
||||
{
|
||||
MutexLocker locker(procfs().m_lock);
|
||||
auto component = TRY(m_associated_component->lookup(name));
|
||||
return component->to_inode(procfs());
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/GlobalInode.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSDirectoryInode final : public ProcFSGlobalInode {
|
||||
friend class ProcFS;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSDirectoryInode>> try_create(ProcFS const&, ProcFSExposedComponent const&);
|
||||
virtual ~ProcFSDirectoryInode() override;
|
||||
|
||||
protected:
|
||||
ProcFSDirectoryInode(ProcFS const&, ProcFSExposedComponent const&);
|
||||
// ^Inode
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView name) override;
|
||||
};
|
||||
|
||||
}
|
@ -6,8 +6,8 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/DirectoryInode.h>
|
||||
#include <Kernel/FileSystem/ProcFS/FileSystem.h>
|
||||
#include <Kernel/FileSystem/ProcFS/Inode.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
|
||||
namespace Kernel {
|
||||
@ -22,7 +22,7 @@ ProcFS::~ProcFS() = default;
|
||||
|
||||
ErrorOr<void> ProcFS::initialize()
|
||||
{
|
||||
m_root_inode = static_ptr_cast<ProcFSDirectoryInode>(TRY(ProcFSComponentRegistry::the().root_directory().to_inode(*this)));
|
||||
m_root_inode = TRY(ProcFSComponentRegistry::the().root_directory().to_inode(*this));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -14,18 +14,8 @@
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSInode;
|
||||
class ProcFSProcessDirectoryInode;
|
||||
class ProcFSGlobalInode;
|
||||
class ProcFSAssociatedProcessInode;
|
||||
class ProcFSProcessSubDirectoryInode;
|
||||
|
||||
class ProcFS final : public FileSystem {
|
||||
friend class ProcFSInode;
|
||||
friend class ProcFSDirectoryInode;
|
||||
friend class ProcFSProcessDirectoryInode;
|
||||
friend class ProcFSGlobalInode;
|
||||
friend class ProcFSAssociatedProcessInode;
|
||||
friend class ProcFSProcessSubDirectoryInode;
|
||||
|
||||
public:
|
||||
virtual ~ProcFS() override;
|
||||
@ -39,7 +29,7 @@ public:
|
||||
private:
|
||||
ProcFS();
|
||||
|
||||
LockRefPtr<ProcFSDirectoryInode> m_root_inode;
|
||||
LockRefPtr<ProcFSInode> m_root_inode;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/GlobalInode.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSGlobalInode>> ProcFSGlobalInode::try_create(ProcFS const& fs, ProcFSExposedComponent const& component)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSGlobalInode(fs, component));
|
||||
}
|
||||
|
||||
ProcFSGlobalInode::ProcFSGlobalInode(ProcFS const& fs, ProcFSExposedComponent const& component)
|
||||
: ProcFSInode(fs, component.component_index())
|
||||
, m_associated_component(component)
|
||||
{
|
||||
}
|
||||
|
||||
void ProcFSGlobalInode::did_seek(OpenFileDescription& 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());
|
||||
}
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSGlobalInode::attach(OpenFileDescription& description)
|
||||
{
|
||||
return m_associated_component->refresh_data(description);
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSGlobalInode::read_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* fd) const
|
||||
{
|
||||
return m_associated_component->read_bytes(offset, count, buffer, fd);
|
||||
}
|
||||
|
||||
StringView ProcFSGlobalInode::name() const
|
||||
{
|
||||
return m_associated_component->name();
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSGlobalInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSGlobalInode::lookup(StringView)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSGlobalInode::truncate(u64 size)
|
||||
{
|
||||
return m_associated_component->truncate(size);
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSGlobalInode::update_timestamps(Optional<Time>, Optional<Time>, Optional<Time>)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
InodeMetadata ProcFSGlobalInode::metadata() const
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
InodeMetadata metadata;
|
||||
metadata.inode = { fsid(), m_associated_component->component_index() };
|
||||
metadata.mode = S_IFREG | 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;
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSGlobalInode::write_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer const& buffer, OpenFileDescription* fd)
|
||||
{
|
||||
return m_associated_component->write_bytes(offset, count, buffer, fd);
|
||||
}
|
||||
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/FileSystem.h>
|
||||
#include <Kernel/FileSystem/ProcFS/Inode.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSGlobalInode : public ProcFSInode {
|
||||
friend class ProcFS;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSGlobalInode>> try_create(ProcFS const&, ProcFSExposedComponent const&);
|
||||
virtual ~ProcFSGlobalInode() override {};
|
||||
StringView name() const;
|
||||
|
||||
protected:
|
||||
ProcFSGlobalInode(ProcFS const&, ProcFSExposedComponent const&);
|
||||
|
||||
// ^Inode
|
||||
virtual ErrorOr<void> attach(OpenFileDescription& description) override final;
|
||||
virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final;
|
||||
virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& buffer, OpenFileDescription*) override final;
|
||||
virtual void did_seek(OpenFileDescription&, off_t) override final;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView) override;
|
||||
virtual ErrorOr<void> truncate(u64) override final;
|
||||
virtual ErrorOr<void> update_timestamps(Optional<Time> atime, Optional<Time> ctime, Optional<Time> mtime) override;
|
||||
|
||||
NonnullLockRefPtr<ProcFSExposedComponent> m_associated_component;
|
||||
};
|
||||
|
||||
}
|
@ -1,20 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
* Copyright (c) 2021-2022, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/Inode.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& fs, InodeIndex index)
|
||||
: Inode(const_cast<ProcFS&>(fs), index)
|
||||
{
|
||||
}
|
||||
|
||||
ProcFSInode::~ProcFSInode() = default;
|
||||
|
||||
ErrorOr<void> ProcFSInode::flush_metadata()
|
||||
@ -52,4 +49,496 @@ ErrorOr<void> ProcFSInode::replace_child(StringView, Inode&)
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSInode::write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSInode::truncate(u64)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSInode::update_timestamps(Optional<Time>, Optional<Time>, Optional<Time>)
|
||||
{
|
||||
// Note: Silently ignore the update request.
|
||||
return {};
|
||||
}
|
||||
|
||||
static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessSubDirectory parent_subdirectory_type, Optional<SegmentedProcFSIndex::MainProcessProperty> main_property)
|
||||
{
|
||||
if (parent_subdirectory_type == SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions)
|
||||
return S_IFLNK | 0400;
|
||||
if (parent_subdirectory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks)
|
||||
return S_IFREG | 0400;
|
||||
if (parent_subdirectory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children)
|
||||
return S_IFLNK | 0400;
|
||||
VERIFY(parent_subdirectory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
||||
if (main_property == SegmentedProcFSIndex::MainProcessProperty::BinaryLink)
|
||||
return S_IFLNK | 0777;
|
||||
if (main_property == SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink)
|
||||
return S_IFLNK | 0777;
|
||||
return S_IFREG | 0400;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSInode::try_create_as_file_description_link_inode(ProcFS const& procfs_instance, unsigned fd_number, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSInode(procfs_instance, fd_number, pid));
|
||||
}
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, unsigned file_description_index, ProcessID pid)
|
||||
: Inode(const_cast<ProcFS&>(procfs_instance), SegmentedProcFSIndex::build_segmented_index_for_file_description(pid, file_description_index))
|
||||
, m_type(Type::FileDescriptionLink)
|
||||
, m_parent_subdirectory_type(SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions)
|
||||
, m_associated_pid(pid)
|
||||
{
|
||||
m_possible_data.property_index = file_description_index;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSInode::try_create_as_thread_stack_inode(ProcFS const& procfs_instance, ThreadID stack_thread_index, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSInode(procfs_instance, stack_thread_index, pid));
|
||||
}
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, ThreadID thread_stack_index, ProcessID pid)
|
||||
: Inode(const_cast<ProcFS&>(procfs_instance), SegmentedProcFSIndex::build_segmented_index_for_thread_stack(pid, thread_stack_index))
|
||||
, m_type(Type::ThreadStack)
|
||||
, m_parent_subdirectory_type(SegmentedProcFSIndex::ProcessSubDirectory::Stacks)
|
||||
, m_associated_pid(pid)
|
||||
{
|
||||
m_possible_data.property_index = thread_stack_index.value();
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSInode::try_create_as_pid_property_inode(ProcFS const& procfs_instance, SegmentedProcFSIndex::MainProcessProperty process_property, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSInode(procfs_instance, process_property, pid));
|
||||
}
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid)
|
||||
: Inode(const_cast<ProcFS&>(procfs_instance), SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(pid, main_property_type))
|
||||
, m_type(Type::ProcessProperty)
|
||||
, m_parent_subdirectory_type(SegmentedProcFSIndex::ProcessSubDirectory::Reserved)
|
||||
, m_associated_pid(pid)
|
||||
{
|
||||
m_possible_data.property_type = main_property_type;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSInode::try_create_as_child_process_link_inode(ProcFS const& procfs_instance, ProcessID child_pid, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSInode(procfs_instance, child_pid, pid));
|
||||
}
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, ProcessID child_pid, ProcessID pid)
|
||||
: Inode(const_cast<ProcFS&>(procfs_instance), SegmentedProcFSIndex::build_segmented_index_for_children(pid, child_pid))
|
||||
, m_type(Type::ChildProcessLink)
|
||||
, m_parent_subdirectory_type(SegmentedProcFSIndex::ProcessSubDirectory::Children)
|
||||
, m_associated_pid(pid)
|
||||
{
|
||||
m_possible_data.property_index = child_pid.value();
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSInode::try_create_as_process_directory_inode(ProcFS const& procfs_instance, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSInode(procfs_instance, pid));
|
||||
}
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, ProcessID pid)
|
||||
: Inode(const_cast<ProcFS&>(procfs_instance), SegmentedProcFSIndex::build_segmented_index_for_pid_directory(pid))
|
||||
, m_type(Type::ProcessDirectory)
|
||||
, m_associated_pid(pid)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSInode::try_create_as_process_subdirectory_inode(ProcFS const& procfs_instance, SegmentedProcFSIndex::ProcessSubDirectory subdirectory_type, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSInode(procfs_instance, subdirectory_type, pid));
|
||||
}
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, SegmentedProcFSIndex::ProcessSubDirectory subdirectory_type, ProcessID pid)
|
||||
: Inode(const_cast<ProcFS&>(procfs_instance), SegmentedProcFSIndex::build_segmented_index_for_sub_directory(pid, subdirectory_type))
|
||||
, m_type(Type::ProcessSubdirectory)
|
||||
, m_subdirectory_type(subdirectory_type)
|
||||
, m_associated_pid(pid)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSInode::try_create_as_global_link_inode(ProcFS const& procfs_instance, ProcFSExposedLink const& link_component)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSInode(procfs_instance, link_component));
|
||||
}
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, ProcFSExposedLink const& link_component)
|
||||
: Inode(const_cast<ProcFS&>(procfs_instance), link_component.component_index())
|
||||
, m_type(Type::GlobalLink)
|
||||
, m_associated_component(link_component)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSInode::try_create_as_directory_inode(ProcFS const& procfs_instance, ProcFSExposedDirectory const& directory_component)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSInode(procfs_instance, directory_component));
|
||||
}
|
||||
|
||||
ProcFSInode::ProcFSInode(ProcFS const& procfs_instance, ProcFSExposedDirectory const& directory_component)
|
||||
: Inode(const_cast<ProcFS&>(procfs_instance), directory_component.component_index())
|
||||
, m_type(Type::GlobalDirectory)
|
||||
, m_associated_component(directory_component)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
|
||||
{
|
||||
MutexLocker locker(procfs().m_lock);
|
||||
if (m_type == Type::ProcessSubdirectory) {
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
VERIFY(m_subdirectory_type.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return EINVAL;
|
||||
switch (m_subdirectory_type.value()) {
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions:
|
||||
return process->traverse_file_descriptions_directory(procfs().fsid(), move(callback));
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
||||
return process->traverse_stacks_directory(procfs().fsid(), move(callback));
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::Children:
|
||||
return process->traverse_children_directory(procfs().fsid(), move(callback));
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
if (m_type == Type::GlobalDirectory) {
|
||||
VERIFY(m_associated_component);
|
||||
return m_associated_component->traverse_as_directory(procfs().fsid(), move(callback));
|
||||
}
|
||||
VERIFY(m_type == Type::ProcessDirectory);
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return EINVAL;
|
||||
return process->procfs_traits()->traverse_as_directory(procfs().fsid(), move(callback));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSInode::lookup(StringView name)
|
||||
{
|
||||
MutexLocker locker(procfs().m_lock);
|
||||
if (m_type == Type::ProcessSubdirectory) {
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
VERIFY(m_subdirectory_type.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return ESRCH;
|
||||
switch (m_subdirectory_type.value()) {
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions:
|
||||
return process->lookup_file_descriptions_directory(procfs(), name);
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
||||
return process->lookup_stacks_directory(procfs(), name);
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::Children:
|
||||
return process->lookup_children_directory(procfs(), name);
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
if (m_type == Type::GlobalDirectory) {
|
||||
VERIFY(m_associated_component);
|
||||
auto component = TRY(m_associated_component->lookup(name));
|
||||
return TRY(component->to_inode(procfs()));
|
||||
}
|
||||
|
||||
VERIFY(m_type == Type::ProcessDirectory);
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return ESRCH;
|
||||
if (name == "fd"sv)
|
||||
return TRY(ProcFSInode::try_create_as_process_subdirectory_inode(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions, m_associated_pid.value()));
|
||||
if (name == "stacks"sv)
|
||||
return TRY(ProcFSInode::try_create_as_process_subdirectory_inode(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks, m_associated_pid.value()));
|
||||
if (name == "children"sv)
|
||||
return TRY(ProcFSInode::try_create_as_process_subdirectory_inode(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Children, m_associated_pid.value()));
|
||||
if (name == "unveil"sv)
|
||||
return TRY(ProcFSInode::try_create_as_pid_property_inode(procfs(), SegmentedProcFSIndex::MainProcessProperty::Unveil, m_associated_pid.value()));
|
||||
if (name == "pledge"sv)
|
||||
return TRY(ProcFSInode::try_create_as_pid_property_inode(procfs(), SegmentedProcFSIndex::MainProcessProperty::Pledge, m_associated_pid.value()));
|
||||
if (name == "fds"sv)
|
||||
return TRY(ProcFSInode::try_create_as_pid_property_inode(procfs(), SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions, m_associated_pid.value()));
|
||||
if (name == "exe"sv)
|
||||
return TRY(ProcFSInode::try_create_as_pid_property_inode(procfs(), SegmentedProcFSIndex::MainProcessProperty::BinaryLink, m_associated_pid.value()));
|
||||
if (name == "cwd"sv)
|
||||
return TRY(ProcFSInode::try_create_as_pid_property_inode(procfs(), SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink, m_associated_pid.value()));
|
||||
if (name == "perf_events"sv)
|
||||
return TRY(ProcFSInode::try_create_as_pid_property_inode(procfs(), SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents, m_associated_pid.value()));
|
||||
if (name == "vm"sv)
|
||||
return TRY(ProcFSInode::try_create_as_pid_property_inode(procfs(), SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats, m_associated_pid.value()));
|
||||
if (name == "cmdline"sv)
|
||||
return TRY(ProcFSInode::try_create_as_pid_property_inode(procfs(), SegmentedProcFSIndex::MainProcessProperty::CommandLine, m_associated_pid.value()));
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSInode::attach(OpenFileDescription& description)
|
||||
{
|
||||
if (m_type == Type::GlobalDirectory || m_type == Type::ProcessDirectory || m_type == Type::ProcessSubdirectory)
|
||||
return {};
|
||||
if (m_type == Type::GlobalLink)
|
||||
return m_associated_component->refresh_data(description);
|
||||
VERIFY(m_type == Type::ProcessProperty || m_type == Type::FileDescriptionLink || m_type == Type::ThreadStack || m_type == Type::ChildProcessLink);
|
||||
return refresh_process_property_data(description);
|
||||
}
|
||||
|
||||
void ProcFSInode::did_seek(OpenFileDescription& description, off_t offset)
|
||||
{
|
||||
if (m_type == Type::GlobalLink) {
|
||||
if (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());
|
||||
}
|
||||
}
|
||||
VERIFY(m_type == Type::ProcessProperty || m_type == Type::FileDescriptionLink || m_type == Type::ThreadStack || m_type == Type::ChildProcessLink);
|
||||
if (offset != 0)
|
||||
return;
|
||||
(void)refresh_process_property_data(description);
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSInode::read_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* description) const
|
||||
{
|
||||
dbgln_if(PROCFS_DEBUG, "ProcFSInode: read_bytes_locked offset: {} count: {}", offset, count);
|
||||
if (m_type == Type::GlobalLink) {
|
||||
VERIFY(m_associated_component);
|
||||
return m_associated_component->read_bytes(offset, count, buffer, description);
|
||||
}
|
||||
|
||||
VERIFY(m_type == Type::ProcessProperty || m_type == Type::FileDescriptionLink || m_type == Type::ThreadStack || m_type == Type::ChildProcessLink);
|
||||
VERIFY(offset >= 0);
|
||||
VERIFY(buffer.user_or_kernel_ptr());
|
||||
|
||||
if (!description) {
|
||||
auto builder = TRY(KBufferBuilder::try_create());
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return Error::from_errno(ESRCH);
|
||||
TRY(try_fetch_process_property_data(*process, builder));
|
||||
auto data_buffer = builder.build();
|
||||
if (!data_buffer)
|
||||
return Error::from_errno(EFAULT);
|
||||
ssize_t nread = min(static_cast<off_t>(data_buffer->size() - offset), static_cast<off_t>(count));
|
||||
TRY(buffer.write(data_buffer->data() + offset, nread));
|
||||
return nread;
|
||||
}
|
||||
if (!description->data()) {
|
||||
dbgln("ProcFS Process Information: Do not have cached data!");
|
||||
return Error::from_errno(EIO);
|
||||
}
|
||||
|
||||
MutexLocker locker(m_refresh_lock);
|
||||
|
||||
auto& typed_cached_data = static_cast<ProcFSInodeData&>(*description->data());
|
||||
auto& data_buffer = typed_cached_data.buffer;
|
||||
|
||||
if (!data_buffer || (size_t)offset >= data_buffer->size())
|
||||
return 0;
|
||||
|
||||
ssize_t nread = min(static_cast<off_t>(data_buffer->size() - offset), static_cast<off_t>(count));
|
||||
TRY(buffer.write(data_buffer->data() + offset, nread));
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
static ErrorOr<void> build_from_cached_data(KBufferBuilder& builder, ProcFSInodeData& cached_data)
|
||||
{
|
||||
cached_data.buffer = builder.build();
|
||||
if (!cached_data.buffer)
|
||||
return ENOMEM;
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSInode::try_fetch_process_property_data(NonnullLockRefPtr<Process> process, KBufferBuilder& builder) const
|
||||
{
|
||||
VERIFY(m_type == Type::ProcessProperty || m_type == Type::FileDescriptionLink || m_type == Type::ThreadStack || m_type == Type::ChildProcessLink);
|
||||
VERIFY(m_parent_subdirectory_type.has_value());
|
||||
auto parent_subdirectory_type = m_parent_subdirectory_type.value();
|
||||
if (parent_subdirectory_type == SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) {
|
||||
TRY(process->procfs_get_file_description_link(m_possible_data.property_index, builder));
|
||||
return {};
|
||||
}
|
||||
if (parent_subdirectory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks) {
|
||||
TRY(process->procfs_get_thread_stack(m_possible_data.property_index, builder));
|
||||
return {};
|
||||
}
|
||||
if (parent_subdirectory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children) {
|
||||
TRY(process->procfs_get_child_proccess_link(m_possible_data.property_index, builder));
|
||||
return {};
|
||||
}
|
||||
|
||||
VERIFY(m_type == Type::ProcessProperty);
|
||||
VERIFY(parent_subdirectory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
||||
switch (m_possible_data.property_type) {
|
||||
case SegmentedProcFSIndex::MainProcessProperty::Unveil:
|
||||
return process->procfs_get_unveil_stats(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::Pledge:
|
||||
return process->procfs_get_pledge_stats(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions:
|
||||
return process->procfs_get_fds_stats(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::BinaryLink:
|
||||
return process->procfs_get_binary_link(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink:
|
||||
return process->procfs_get_current_work_directory_link(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents:
|
||||
return process->procfs_get_perf_events(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats:
|
||||
return process->procfs_get_virtual_memory_stats(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::CommandLine:
|
||||
return process->procfs_get_command_line(builder);
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSInode::refresh_process_property_data(OpenFileDescription& description)
|
||||
{
|
||||
// For process-specific inodes, hold the process's ptrace lock across refresh
|
||||
// and refuse to load data if the process is not dumpable.
|
||||
// Without this, files opened before a process went non-dumpable could still be used for dumping.
|
||||
VERIFY(m_type == Type::ProcessProperty || m_type == Type::FileDescriptionLink || m_type == Type::ThreadStack || m_type == Type::ChildProcessLink);
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return Error::from_errno(ESRCH);
|
||||
process->ptrace_lock().lock();
|
||||
if (!process->is_dumpable()) {
|
||||
process->ptrace_lock().unlock();
|
||||
return EPERM;
|
||||
}
|
||||
ScopeGuard guard = [&] {
|
||||
process->ptrace_lock().unlock();
|
||||
};
|
||||
MutexLocker locker(m_refresh_lock);
|
||||
auto& cached_data = description.data();
|
||||
if (!cached_data) {
|
||||
cached_data = adopt_own_if_nonnull(new (nothrow) ProcFSInodeData);
|
||||
if (!cached_data)
|
||||
return ENOMEM;
|
||||
}
|
||||
auto builder = TRY(KBufferBuilder::try_create());
|
||||
TRY(try_fetch_process_property_data(*process, builder));
|
||||
return build_from_cached_data(builder, static_cast<ProcFSInodeData&>(*cached_data));
|
||||
}
|
||||
|
||||
InodeMetadata ProcFSInode::metadata() const
|
||||
{
|
||||
InodeMetadata metadata;
|
||||
switch (m_type) {
|
||||
case Type::GlobalLink: {
|
||||
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();
|
||||
break;
|
||||
}
|
||||
case Type::GlobalDirectory: {
|
||||
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();
|
||||
break;
|
||||
}
|
||||
case Type::FileDescriptionLink: {
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return {};
|
||||
auto traits = process->procfs_traits();
|
||||
metadata.inode = { fsid(), SegmentedProcFSIndex::build_segmented_index_for_file_description(m_associated_pid.value(), m_possible_data.property_index) };
|
||||
metadata.mode = determine_procfs_process_inode_mode(m_parent_subdirectory_type.value(), {});
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
break;
|
||||
}
|
||||
case Type::ThreadStack: {
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return {};
|
||||
auto traits = process->procfs_traits();
|
||||
metadata.inode = { fsid(), SegmentedProcFSIndex::build_segmented_index_for_thread_stack(m_associated_pid.value(), m_possible_data.property_index) };
|
||||
metadata.mode = determine_procfs_process_inode_mode(m_parent_subdirectory_type.value(), {});
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
break;
|
||||
}
|
||||
case Type::ProcessProperty: {
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return {};
|
||||
auto traits = process->procfs_traits();
|
||||
metadata.inode = { fsid(), SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(m_associated_pid.value(), m_possible_data.property_type) };
|
||||
metadata.mode = determine_procfs_process_inode_mode(m_parent_subdirectory_type.value(), m_possible_data.property_type);
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
break;
|
||||
}
|
||||
case Type::ChildProcessLink: {
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return {};
|
||||
auto traits = process->procfs_traits();
|
||||
metadata.inode = { fsid(), SegmentedProcFSIndex::build_segmented_index_for_children(m_associated_pid.value(), m_possible_data.property_index) };
|
||||
metadata.mode = determine_procfs_process_inode_mode(m_parent_subdirectory_type.value(), {});
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
break;
|
||||
}
|
||||
case Type::ProcessDirectory: {
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return {};
|
||||
auto traits = process->procfs_traits();
|
||||
metadata.inode = { fsid(), traits->component_index() };
|
||||
metadata.mode = S_IFDIR | traits->required_mode();
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
break;
|
||||
}
|
||||
case Type::ProcessSubdirectory: {
|
||||
VERIFY(m_associated_pid.has_value());
|
||||
VERIFY(m_subdirectory_type.has_value());
|
||||
auto process = Process::from_pid_in_same_jail(m_associated_pid.value());
|
||||
if (!process)
|
||||
return {};
|
||||
auto traits = process->procfs_traits();
|
||||
metadata.inode = { fsid(), SegmentedProcFSIndex::build_segmented_index_for_sub_directory(m_associated_pid.value(), m_subdirectory_type.value()) };
|
||||
metadata.mode = S_IFDIR | traits->required_mode();
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,28 +14,90 @@
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSInode : public Inode {
|
||||
class ProcFSExposedDirectory;
|
||||
class ProcFSExposedLink;
|
||||
class ProcFSInode final : public Inode {
|
||||
friend class ProcFS;
|
||||
|
||||
public:
|
||||
enum class Type {
|
||||
GlobalLink,
|
||||
GlobalDirectory,
|
||||
FileDescriptionLink,
|
||||
ThreadStack,
|
||||
ProcessProperty,
|
||||
ChildProcessLink,
|
||||
ProcessDirectory,
|
||||
ProcessSubdirectory,
|
||||
};
|
||||
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSInode>> try_create_as_file_description_link_inode(ProcFS const&, unsigned, ProcessID);
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSInode>> try_create_as_thread_stack_inode(ProcFS const&, ThreadID, ProcessID);
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSInode>> try_create_as_pid_property_inode(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID);
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSInode>> try_create_as_child_process_link_inode(ProcFS const&, ProcessID, ProcessID);
|
||||
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSInode>> try_create_as_process_directory_inode(ProcFS const&, ProcessID);
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSInode>> try_create_as_process_subdirectory_inode(ProcFS const&, SegmentedProcFSIndex::ProcessSubDirectory, ProcessID);
|
||||
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSInode>> try_create_as_directory_inode(ProcFS const&, ProcFSExposedDirectory const&);
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSInode>> try_create_as_global_link_inode(ProcFS const&, ProcFSExposedLink const&);
|
||||
|
||||
virtual ~ProcFSInode() override;
|
||||
|
||||
protected:
|
||||
ProcFSInode(ProcFS const&, InodeIndex);
|
||||
private:
|
||||
// ProcFS PID property inode (/proc/PID/PROPERTY)
|
||||
ProcFSInode(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID);
|
||||
// ProcFS Thread stack inode (/proc/PID/stacks/TID)
|
||||
ProcFSInode(ProcFS const&, ThreadID, ProcessID);
|
||||
// ProcFS File description link inode (/proc/PID/fd/FD)
|
||||
ProcFSInode(ProcFS const&, unsigned, ProcessID);
|
||||
// ProcFS Child process link inode (/proc/PID/children/CHILD_PID)
|
||||
ProcFSInode(ProcFS const&, ProcessID, ProcessID);
|
||||
// ProcFS Process directory inode (/proc/PID/)
|
||||
ProcFSInode(ProcFS const&, ProcessID);
|
||||
// ProcFS Process sub directory inode (/proc/PID/SUBDIRECTORY)
|
||||
ProcFSInode(ProcFS const&, SegmentedProcFSIndex::ProcessSubDirectory, ProcessID);
|
||||
|
||||
ProcFSInode(ProcFS const&, ProcFSExposedLink const&);
|
||||
ProcFSInode(ProcFS const&, ProcFSExposedDirectory const&);
|
||||
|
||||
ProcFS& procfs() { return static_cast<ProcFS&>(Inode::fs()); }
|
||||
ProcFS const& procfs() const { return static_cast<ProcFS const&>(Inode::fs()); }
|
||||
|
||||
// ^Inode
|
||||
virtual ErrorOr<void> attach(OpenFileDescription& description) override = 0;
|
||||
virtual void did_seek(OpenFileDescription&, off_t) override = 0;
|
||||
virtual ErrorOr<void> attach(OpenFileDescription& description) override;
|
||||
virtual void did_seek(OpenFileDescription&, off_t) override;
|
||||
virtual ErrorOr<void> flush_metadata() override final;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override final;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override;
|
||||
virtual ErrorOr<void> add_child(Inode&, StringView name, mode_t) override final;
|
||||
virtual ErrorOr<void> remove_child(StringView name) override final;
|
||||
virtual ErrorOr<void> replace_child(StringView name, Inode& child) override final;
|
||||
virtual ErrorOr<void> chmod(mode_t) override final;
|
||||
virtual ErrorOr<void> chown(UserID, GroupID) override final;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override;
|
||||
virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& buffer, OpenFileDescription*) override;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView name) override final;
|
||||
virtual ErrorOr<void> truncate(u64) override final;
|
||||
virtual ErrorOr<void> update_timestamps(Optional<Time> atime, Optional<Time> ctime, Optional<Time> mtime) override;
|
||||
|
||||
ErrorOr<void> refresh_process_property_data(OpenFileDescription& description);
|
||||
ErrorOr<void> try_fetch_process_property_data(NonnullLockRefPtr<Process>, KBufferBuilder& builder) const;
|
||||
|
||||
Type m_type;
|
||||
|
||||
union {
|
||||
SegmentedProcFSIndex::MainProcessProperty property_type;
|
||||
unsigned property_index;
|
||||
} m_possible_data;
|
||||
Optional<SegmentedProcFSIndex::ProcessSubDirectory> const m_parent_subdirectory_type {};
|
||||
Optional<SegmentedProcFSIndex::ProcessSubDirectory> const m_subdirectory_type {};
|
||||
|
||||
Optional<ProcessID> const m_associated_pid {};
|
||||
|
||||
LockRefPtr<ProcFSExposedComponent> m_associated_component;
|
||||
mutable Mutex m_refresh_lock;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/LinkInode.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSLinkInode>> ProcFSLinkInode::try_create(ProcFS const& procfs, ProcFSExposedComponent const& component)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSLinkInode(procfs, component));
|
||||
}
|
||||
|
||||
ProcFSLinkInode::ProcFSLinkInode(ProcFS const& fs, ProcFSExposedComponent const& component)
|
||||
: ProcFSGlobalInode(fs, component)
|
||||
{
|
||||
}
|
||||
|
||||
InodeMetadata ProcFSLinkInode::metadata() const
|
||||
{
|
||||
MutexLocker locker(m_inode_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;
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/GlobalInode.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSLinkInode : public ProcFSGlobalInode {
|
||||
friend class ProcFS;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSLinkInode>> try_create(ProcFS const&, ProcFSExposedComponent const&);
|
||||
|
||||
protected:
|
||||
ProcFSLinkInode(ProcFS const&, ProcFSExposedComponent const&);
|
||||
virtual InodeMetadata metadata() const override;
|
||||
};
|
||||
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessAssociatedInode.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ProcFSProcessAssociatedInode::ProcFSProcessAssociatedInode(ProcFS const& fs, ProcessID associated_pid, InodeIndex determined_index)
|
||||
: ProcFSInode(fs, determined_index)
|
||||
, m_pid(associated_pid)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSProcessAssociatedInode::write_bytes_locked(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*)
|
||||
{
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/Inode.h>
|
||||
#include <Kernel/Forward.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSProcessAssociatedInode : public ProcFSInode {
|
||||
friend class ProcFS;
|
||||
|
||||
protected:
|
||||
ProcFSProcessAssociatedInode(ProcFS const&, ProcessID, InodeIndex);
|
||||
ProcessID associated_pid() const { return m_pid; }
|
||||
|
||||
// ^Inode
|
||||
virtual ErrorOr<size_t> write_bytes_locked(off_t, size_t, UserOrKernelBuffer const& buffer, OpenFileDescription*) override final;
|
||||
|
||||
private:
|
||||
const ProcessID m_pid;
|
||||
};
|
||||
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessDirectoryInode.h>
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessPropertyInode.h>
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessSubDirectoryInode.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSProcessDirectoryInode>> ProcFSProcessDirectoryInode::try_create(ProcFS const& procfs, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessDirectoryInode(procfs, pid));
|
||||
}
|
||||
|
||||
ProcFSProcessDirectoryInode::ProcFSProcessDirectoryInode(ProcFS const& procfs, ProcessID pid)
|
||||
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_pid_directory(pid))
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSProcessDirectoryInode::attach(OpenFileDescription&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
InodeMetadata ProcFSProcessDirectoryInode::metadata() const
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return {};
|
||||
|
||||
auto traits = process->procfs_traits();
|
||||
InodeMetadata metadata;
|
||||
metadata.inode = { fsid(), traits->component_index() };
|
||||
metadata.mode = S_IFDIR | traits->required_mode();
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
return metadata;
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSProcessDirectoryInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSProcessDirectoryInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
|
||||
{
|
||||
MutexLocker locker(procfs().m_lock);
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return EINVAL;
|
||||
return process->procfs_traits()->traverse_as_directory(procfs().fsid(), move(callback));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSProcessDirectoryInode::lookup(StringView name)
|
||||
{
|
||||
MutexLocker locker(procfs().m_lock);
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return ESRCH;
|
||||
if (name == "fd"sv)
|
||||
return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions, associated_pid()));
|
||||
if (name == "stacks"sv)
|
||||
return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks, associated_pid()));
|
||||
if (name == "children"sv)
|
||||
return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Children, associated_pid()));
|
||||
if (name == "unveil"sv)
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Unveil, associated_pid()));
|
||||
if (name == "pledge"sv)
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Pledge, associated_pid()));
|
||||
if (name == "fds"sv)
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions, associated_pid()));
|
||||
if (name == "exe"sv)
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::BinaryLink, associated_pid()));
|
||||
if (name == "cwd"sv)
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink, associated_pid()));
|
||||
if (name == "perf_events"sv)
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents, associated_pid()));
|
||||
if (name == "vm"sv)
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats, associated_pid()));
|
||||
if (name == "cmdline"sv)
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::CommandLine, associated_pid()));
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessAssociatedInode.h>
|
||||
#include <Kernel/Forward.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSProcessDirectoryInode final : public ProcFSProcessAssociatedInode {
|
||||
friend class ProcFS;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSProcessDirectoryInode>> try_create(ProcFS const&, ProcessID);
|
||||
|
||||
private:
|
||||
ProcFSProcessDirectoryInode(ProcFS const&, ProcessID);
|
||||
// ^Inode
|
||||
virtual ErrorOr<void> attach(OpenFileDescription& description) override;
|
||||
virtual void did_seek(OpenFileDescription&, off_t) override { }
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView name) override;
|
||||
};
|
||||
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/API/POSIX/errno.h>
|
||||
#include <Kernel/Debug.h>
|
||||
#include <Kernel/FileSystem/OpenFileDescription.h>
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessPropertyInode.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::try_create_for_file_description_link(ProcFS const& procfs, unsigned file_description_index, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, file_description_index, pid));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::try_create_for_thread_stack(ProcFS const& procfs, ThreadID stack_thread_index, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, stack_thread_index, pid));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::try_create_for_pid_property(ProcFS const& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, main_property_type, pid));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::try_create_for_child_process_link(ProcFS const& procfs, ProcessID child_pid, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, child_pid, pid));
|
||||
}
|
||||
|
||||
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid)
|
||||
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(pid, main_property_type))
|
||||
, m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Reserved)
|
||||
{
|
||||
m_possible_data.property_type = main_property_type;
|
||||
}
|
||||
|
||||
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, unsigned file_description_index, ProcessID pid)
|
||||
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_file_description(pid, file_description_index))
|
||||
, m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions)
|
||||
{
|
||||
m_possible_data.property_index = file_description_index;
|
||||
}
|
||||
|
||||
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, ThreadID thread_stack_index, ProcessID pid)
|
||||
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_thread_stack(pid, thread_stack_index))
|
||||
, m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Stacks)
|
||||
{
|
||||
m_possible_data.property_index = thread_stack_index.value();
|
||||
}
|
||||
|
||||
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, ProcessID child_pid, ProcessID pid)
|
||||
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_children(pid, child_pid))
|
||||
, m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Children)
|
||||
{
|
||||
m_possible_data.property_index = child_pid.value();
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSProcessPropertyInode::attach(OpenFileDescription& description)
|
||||
{
|
||||
return refresh_data(description);
|
||||
}
|
||||
|
||||
void ProcFSProcessPropertyInode::did_seek(OpenFileDescription& description, off_t offset)
|
||||
{
|
||||
if (offset != 0)
|
||||
return;
|
||||
(void)refresh_data(description);
|
||||
}
|
||||
|
||||
static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessSubDirectory parent_sub_directory_type, SegmentedProcFSIndex::MainProcessProperty main_property)
|
||||
{
|
||||
if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions)
|
||||
return S_IFLNK | 0400;
|
||||
if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks)
|
||||
return S_IFREG | 0400;
|
||||
if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children)
|
||||
return S_IFLNK | 0400;
|
||||
VERIFY(parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
||||
if (main_property == SegmentedProcFSIndex::MainProcessProperty::BinaryLink)
|
||||
return S_IFLNK | 0777;
|
||||
if (main_property == SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink)
|
||||
return S_IFLNK | 0777;
|
||||
return S_IFREG | 0400;
|
||||
}
|
||||
|
||||
InodeMetadata ProcFSProcessPropertyInode::metadata() const
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return {};
|
||||
|
||||
auto traits = process->procfs_traits();
|
||||
InodeMetadata metadata;
|
||||
metadata.inode = { fsid(), traits->component_index() };
|
||||
metadata.mode = determine_procfs_process_inode_mode(m_parent_sub_directory_type, m_possible_data.property_type);
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
return metadata;
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSProcessPropertyInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSProcessPropertyInode::read_bytes_locked(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* description) const
|
||||
{
|
||||
dbgln_if(PROCFS_DEBUG, "ProcFS ProcessInformation: read_bytes_locked offset: {} count: {}", offset, count);
|
||||
|
||||
VERIFY(offset >= 0);
|
||||
VERIFY(buffer.user_or_kernel_ptr());
|
||||
|
||||
if (!description) {
|
||||
auto builder = TRY(KBufferBuilder::try_create());
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return Error::from_errno(ESRCH);
|
||||
TRY(try_to_acquire_data(*process, builder));
|
||||
auto data_buffer = builder.build();
|
||||
if (!data_buffer)
|
||||
return Error::from_errno(EFAULT);
|
||||
ssize_t nread = min(static_cast<off_t>(data_buffer->size() - offset), static_cast<off_t>(count));
|
||||
TRY(buffer.write(data_buffer->data() + offset, nread));
|
||||
return nread;
|
||||
}
|
||||
if (!description->data()) {
|
||||
dbgln("ProcFS Process Information: Do not have cached data!");
|
||||
return Error::from_errno(EIO);
|
||||
}
|
||||
|
||||
MutexLocker locker(m_refresh_lock);
|
||||
|
||||
auto& typed_cached_data = static_cast<ProcFSInodeData&>(*description->data());
|
||||
auto& data_buffer = typed_cached_data.buffer;
|
||||
|
||||
if (!data_buffer || (size_t)offset >= data_buffer->size())
|
||||
return 0;
|
||||
|
||||
ssize_t nread = min(static_cast<off_t>(data_buffer->size() - offset), static_cast<off_t>(count));
|
||||
TRY(buffer.write(data_buffer->data() + offset, nread));
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSProcessPropertyInode::lookup(StringView)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
static ErrorOr<void> build_from_cached_data(KBufferBuilder& builder, ProcFSInodeData& cached_data)
|
||||
{
|
||||
cached_data.buffer = builder.build();
|
||||
if (!cached_data.buffer)
|
||||
return ENOMEM;
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSProcessPropertyInode::try_to_acquire_data(Process& process, KBufferBuilder& builder) const
|
||||
{
|
||||
// FIXME: Verify process is already ref-counted
|
||||
if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) {
|
||||
TRY(process.procfs_get_file_description_link(m_possible_data.property_index, builder));
|
||||
return {};
|
||||
}
|
||||
if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks) {
|
||||
TRY(process.procfs_get_thread_stack(m_possible_data.property_index, builder));
|
||||
return {};
|
||||
}
|
||||
if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children) {
|
||||
TRY(process.procfs_get_child_proccess_link(m_possible_data.property_index, builder));
|
||||
return {};
|
||||
}
|
||||
|
||||
VERIFY(m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
||||
switch (m_possible_data.property_type) {
|
||||
case SegmentedProcFSIndex::MainProcessProperty::Unveil:
|
||||
return process.procfs_get_unveil_stats(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::Pledge:
|
||||
return process.procfs_get_pledge_stats(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions:
|
||||
return process.procfs_get_fds_stats(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::BinaryLink:
|
||||
return process.procfs_get_binary_link(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::CurrentWorkDirectoryLink:
|
||||
return process.procfs_get_current_work_directory_link(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::PerformanceEvents:
|
||||
return process.procfs_get_perf_events(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::VirtualMemoryStats:
|
||||
return process.procfs_get_virtual_memory_stats(builder);
|
||||
case SegmentedProcFSIndex::MainProcessProperty::CommandLine:
|
||||
return process.procfs_get_command_line(builder);
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSProcessPropertyInode::refresh_data(OpenFileDescription& description)
|
||||
{
|
||||
// For process-specific inodes, hold the process's ptrace lock across refresh
|
||||
// and refuse to load data if the process is not dumpable.
|
||||
// Without this, files opened before a process went non-dumpable could still be used for dumping.
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return Error::from_errno(ESRCH);
|
||||
process->ptrace_lock().lock();
|
||||
if (!process->is_dumpable()) {
|
||||
process->ptrace_lock().unlock();
|
||||
return EPERM;
|
||||
}
|
||||
ScopeGuard guard = [&] {
|
||||
process->ptrace_lock().unlock();
|
||||
};
|
||||
MutexLocker locker(m_refresh_lock);
|
||||
auto& cached_data = description.data();
|
||||
if (!cached_data) {
|
||||
cached_data = adopt_own_if_nonnull(new (nothrow) ProcFSInodeData);
|
||||
if (!cached_data)
|
||||
return ENOMEM;
|
||||
}
|
||||
auto builder = TRY(KBufferBuilder::try_create());
|
||||
TRY(try_to_acquire_data(*process, builder));
|
||||
return build_from_cached_data(builder, static_cast<ProcFSInodeData&>(*cached_data));
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessAssociatedInode.h>
|
||||
#include <Kernel/Forward.h>
|
||||
#include <Kernel/KBufferBuilder.h>
|
||||
#include <Kernel/Locking/Mutex.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
#include <Kernel/UnixTypes.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSProcessPropertyInode final : public ProcFSProcessAssociatedInode {
|
||||
friend class ProcFS;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> try_create_for_file_description_link(ProcFS const&, unsigned, ProcessID);
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> try_create_for_thread_stack(ProcFS const&, ThreadID, ProcessID);
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> try_create_for_pid_property(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID);
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> try_create_for_child_process_link(ProcFS const&, ProcessID, ProcessID);
|
||||
|
||||
private:
|
||||
ProcFSProcessPropertyInode(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID);
|
||||
ProcFSProcessPropertyInode(ProcFS const&, ThreadID, ProcessID);
|
||||
ProcFSProcessPropertyInode(ProcFS const&, unsigned, ProcessID);
|
||||
ProcFSProcessPropertyInode(ProcFS const&, ProcessID, ProcessID);
|
||||
|
||||
// ^Inode
|
||||
virtual ErrorOr<void> attach(OpenFileDescription& description) override;
|
||||
virtual void did_seek(OpenFileDescription&, off_t) override;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView name) override final;
|
||||
|
||||
ErrorOr<void> refresh_data(OpenFileDescription& description);
|
||||
ErrorOr<void> try_to_acquire_data(Process& process, KBufferBuilder& builder) const;
|
||||
|
||||
const SegmentedProcFSIndex::ProcessSubDirectory m_parent_sub_directory_type;
|
||||
union {
|
||||
SegmentedProcFSIndex::MainProcessProperty property_type;
|
||||
unsigned property_index;
|
||||
} m_possible_data;
|
||||
mutable Mutex m_refresh_lock;
|
||||
};
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Spencer Dixon <spencercdixon@gmail.com>
|
||||
* Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessSubDirectoryInode.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSProcessSubDirectoryInode>> ProcFSProcessSubDirectoryInode::try_create(ProcFS const& procfs, SegmentedProcFSIndex::ProcessSubDirectory sub_directory_type, ProcessID pid)
|
||||
{
|
||||
return adopt_nonnull_lock_ref_or_enomem(new (nothrow) ProcFSProcessSubDirectoryInode(procfs, sub_directory_type, pid));
|
||||
}
|
||||
|
||||
ProcFSProcessSubDirectoryInode::ProcFSProcessSubDirectoryInode(ProcFS const& procfs, SegmentedProcFSIndex::ProcessSubDirectory sub_directory_type, ProcessID pid)
|
||||
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(pid, sub_directory_type))
|
||||
, m_sub_directory_type(sub_directory_type)
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSProcessSubDirectoryInode::read_bytes_locked(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSProcessSubDirectoryInode::attach(OpenFileDescription&)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
void ProcFSProcessSubDirectoryInode::did_seek(OpenFileDescription&, off_t)
|
||||
{
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
InodeMetadata ProcFSProcessSubDirectoryInode::metadata() const
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return {};
|
||||
|
||||
auto traits = process->procfs_traits();
|
||||
InodeMetadata metadata;
|
||||
metadata.inode = { fsid(), traits->component_index() };
|
||||
metadata.mode = S_IFDIR | traits->required_mode();
|
||||
metadata.uid = traits->owner_user();
|
||||
metadata.gid = traits->owner_group();
|
||||
metadata.size = 0;
|
||||
metadata.mtime = traits->modified_time();
|
||||
return metadata;
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSProcessSubDirectoryInode::traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
|
||||
{
|
||||
MutexLocker locker(procfs().m_lock);
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return EINVAL;
|
||||
switch (m_sub_directory_type) {
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions:
|
||||
return process->traverse_file_descriptions_directory(procfs().fsid(), move(callback));
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
||||
return process->traverse_stacks_directory(procfs().fsid(), move(callback));
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::Children:
|
||||
return process->traverse_children_directory(procfs().fsid(), move(callback));
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSProcessSubDirectoryInode::lookup(StringView name)
|
||||
{
|
||||
MutexLocker locker(procfs().m_lock);
|
||||
auto process = Process::from_pid_in_same_jail(associated_pid());
|
||||
if (!process)
|
||||
return ESRCH;
|
||||
switch (m_sub_directory_type) {
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions:
|
||||
return process->lookup_file_descriptions_directory(procfs(), name);
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
||||
return process->lookup_stacks_directory(procfs(), name);
|
||||
case SegmentedProcFSIndex::ProcessSubDirectory::Children:
|
||||
return process->lookup_children_directory(procfs(), name);
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessAssociatedInode.h>
|
||||
#include <Kernel/Forward.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class ProcFSProcessSubDirectoryInode final : public ProcFSProcessAssociatedInode {
|
||||
friend class ProcFS;
|
||||
|
||||
public:
|
||||
static ErrorOr<NonnullLockRefPtr<ProcFSProcessSubDirectoryInode>> try_create(ProcFS const&, SegmentedProcFSIndex::ProcessSubDirectory, ProcessID);
|
||||
|
||||
private:
|
||||
ProcFSProcessSubDirectoryInode(ProcFS const&, SegmentedProcFSIndex::ProcessSubDirectory, ProcessID);
|
||||
// ^Inode
|
||||
virtual ErrorOr<void> attach(OpenFileDescription& description) override;
|
||||
virtual void did_seek(OpenFileDescription&, off_t) override;
|
||||
virtual InodeMetadata metadata() const override;
|
||||
virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual ErrorOr<size_t> read_bytes_locked(off_t, size_t, UserOrKernelBuffer& buffer, OpenFileDescription*) const override final;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView name) override;
|
||||
|
||||
const SegmentedProcFSIndex::ProcessSubDirectory m_sub_directory_type;
|
||||
};
|
||||
|
||||
}
|
@ -40,7 +40,6 @@ class MasterPTY;
|
||||
class Mount;
|
||||
class PerformanceEventBuffer;
|
||||
class ProcFS;
|
||||
class ProcFSDirectoryInode;
|
||||
class ProcFSExposedComponent;
|
||||
class ProcFSExposedDirectory;
|
||||
class ProcFSInode;
|
||||
|
@ -815,7 +815,7 @@ public:
|
||||
}
|
||||
|
||||
virtual InodeIndex component_index() const override;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> to_inode(ProcFS const& procfs_instance) const override;
|
||||
virtual ErrorOr<NonnullLockRefPtr<ProcFSInode>> to_inode(ProcFS const& procfs_instance) const override;
|
||||
virtual ErrorOr<void> traverse_as_directory(FileSystemID, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual mode_t required_mode() const override { return 0555; }
|
||||
|
||||
|
@ -4,8 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/DirectoryInode.h>
|
||||
#include <Kernel/FileSystem/ProcFS/LinkInode.h>
|
||||
#include <Kernel/FileSystem/ProcFS/Inode.h>
|
||||
#include <Kernel/KBufferBuilder.h>
|
||||
#include <Kernel/PerformanceEventBuffer.h>
|
||||
#include <Kernel/Process.h>
|
||||
@ -125,14 +124,14 @@ ErrorOr<size_t> ProcFSExposedLink::read_bytes(off_t offset, size_t count, UserOr
|
||||
return nread;
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSExposedLink::to_inode(ProcFS const& procfs_instance) const
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSExposedLink::to_inode(ProcFS const& procfs_instance) const
|
||||
{
|
||||
return TRY(ProcFSLinkInode::try_create(procfs_instance, *this));
|
||||
return TRY(ProcFSInode::try_create_as_global_link_inode(procfs_instance, *this));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> ProcFSExposedDirectory::to_inode(ProcFS const& procfs_instance) const
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> ProcFSExposedDirectory::to_inode(ProcFS const& procfs_instance) const
|
||||
{
|
||||
return TRY(ProcFSDirectoryInode::try_create(procfs_instance, *this));
|
||||
return TRY(ProcFSInode::try_create_as_directory_inode(procfs_instance, *this));
|
||||
}
|
||||
|
||||
void ProcFSExposedDirectory::add_component(ProcFSExposedComponent const&)
|
||||
|
@ -86,7 +86,7 @@ public:
|
||||
return {};
|
||||
}
|
||||
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> to_inode(ProcFS const& procfs_instance) const = 0;
|
||||
virtual ErrorOr<NonnullLockRefPtr<ProcFSInode>> to_inode(ProcFS const& procfs_instance) const = 0;
|
||||
|
||||
virtual InodeIndex component_index() const { return m_component_index; }
|
||||
|
||||
@ -119,7 +119,7 @@ public:
|
||||
}
|
||||
virtual mode_t required_mode() const override { return 0555; }
|
||||
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> to_inode(ProcFS const& procfs_instance) const override final;
|
||||
virtual ErrorOr<NonnullLockRefPtr<ProcFSInode>> to_inode(ProcFS const& procfs_instance) const override final;
|
||||
|
||||
protected:
|
||||
explicit ProcFSExposedDirectory(StringView name);
|
||||
@ -130,7 +130,7 @@ protected:
|
||||
|
||||
class ProcFSExposedLink : public ProcFSExposedComponent {
|
||||
public:
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> to_inode(ProcFS const& procfs_instance) const override final;
|
||||
virtual ErrorOr<NonnullLockRefPtr<ProcFSInode>> to_inode(ProcFS const& procfs_instance) const override final;
|
||||
|
||||
virtual ErrorOr<size_t> read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription* description) const override;
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessDirectoryInode.h>
|
||||
#include <Kernel/FileSystem/ProcFS/Inode.h>
|
||||
#include <Kernel/Process.h>
|
||||
#include <Kernel/ProcessExposed.h>
|
||||
|
||||
@ -39,13 +39,13 @@ InodeIndex Process::ProcessProcFSTraits::component_index() const
|
||||
return SegmentedProcFSIndex::build_segmented_index_for_pid_directory(process->pid());
|
||||
}
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<Inode>> Process::ProcessProcFSTraits::to_inode(ProcFS const& procfs_instance) const
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> Process::ProcessProcFSTraits::to_inode(ProcFS const& procfs_instance) const
|
||||
{
|
||||
auto process = m_process.strong_ref();
|
||||
if (!process)
|
||||
return ESRCH;
|
||||
|
||||
return TRY(ProcFSProcessDirectoryInode::try_create(procfs_instance, process->pid()));
|
||||
return TRY(ProcFSInode::try_create_as_process_directory_inode(procfs_instance, process->pid()));
|
||||
}
|
||||
|
||||
ErrorOr<void> Process::ProcessProcFSTraits::traverse_as_directory(FileSystemID fsid, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <AK/JsonObjectSerializer.h>
|
||||
#include <AK/JsonValue.h>
|
||||
#include <Kernel/FileSystem/Custody.h>
|
||||
#include <Kernel/FileSystem/ProcFS/ProcessPropertyInode.h>
|
||||
#include <Kernel/FileSystem/ProcFS/Inode.h>
|
||||
#include <Kernel/InterruptDisabler.h>
|
||||
#include <Kernel/KBufferBuilder.h>
|
||||
#include <Kernel/Memory/AnonymousVMObject.h>
|
||||
@ -65,12 +65,12 @@ ErrorOr<NonnullLockRefPtr<Inode>> Process::lookup_stacks_directory(ProcFS const&
|
||||
return ENOENT;
|
||||
auto needle = maybe_needle.release_value();
|
||||
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSProcessPropertyInode>> thread_stack_inode { ENOENT };
|
||||
ErrorOr<NonnullLockRefPtr<ProcFSInode>> thread_stack_inode { ENOENT };
|
||||
for_each_thread([&](Thread const& thread) {
|
||||
int tid = thread.tid().value();
|
||||
VERIFY(!(tid < 0));
|
||||
if (needle == (unsigned)tid) {
|
||||
thread_stack_inode = ProcFSProcessPropertyInode::try_create_for_thread_stack(procfs, thread.tid(), pid());
|
||||
thread_stack_inode = ProcFSInode::try_create_as_thread_stack_inode(procfs, thread.tid(), pid());
|
||||
return IterationDecision::Break;
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
@ -105,7 +105,7 @@ ErrorOr<NonnullLockRefPtr<Inode>> Process::lookup_children_directory(ProcFS cons
|
||||
if (!child_process || child_process->ppid() != pid())
|
||||
return ENOENT;
|
||||
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_child_process_link(procfs, *maybe_pid, pid()));
|
||||
return TRY(ProcFSInode::try_create_as_child_process_link_inode(procfs, *maybe_pid, pid()));
|
||||
}
|
||||
|
||||
ErrorOr<size_t> Process::procfs_get_child_proccess_link(ProcessID child_pid, KBufferBuilder& builder) const
|
||||
@ -153,7 +153,7 @@ ErrorOr<NonnullLockRefPtr<Inode>> Process::lookup_file_descriptions_directory(Pr
|
||||
if (!m_fds.with_shared([&](auto& fds) { return fds.get_if_valid(*maybe_index); }))
|
||||
return ENOENT;
|
||||
|
||||
return TRY(ProcFSProcessPropertyInode::try_create_for_file_description_link(procfs, *maybe_index, pid()));
|
||||
return TRY(ProcFSInode::try_create_as_file_description_link_inode(procfs, *maybe_index, pid()));
|
||||
}
|
||||
|
||||
ErrorOr<void> Process::procfs_get_pledge_stats(KBufferBuilder& builder) const
|
||||
|
Loading…
Reference in New Issue
Block a user