From ecc29bb52e6fcd8be14be38106c3061aacd21744 Mon Sep 17 00:00:00 2001 From: Liav A Date: Fri, 22 Apr 2022 20:35:15 +0300 Subject: [PATCH] Kernel/SysFS: Add Symbolic link functionality to the filesystem This will be used later on to help connecting a node at /sys/dev/block/ that represents a Storage device to a directory in /sys/devices/storage/ with details on that device in that directory. --- Kernel/FileSystem/SysFS.cpp | 25 +++++++++++++ Kernel/FileSystem/SysFS.h | 13 +++++++ Kernel/FileSystem/SysFS/Component.cpp | 52 +++++++++++++++++++++++++++ Kernel/FileSystem/SysFS/Component.h | 14 ++++++++ 4 files changed, 104 insertions(+) diff --git a/Kernel/FileSystem/SysFS.cpp b/Kernel/FileSystem/SysFS.cpp index 576b6bbddb..16940f76be 100644 --- a/Kernel/FileSystem/SysFS.cpp +++ b/Kernel/FileSystem/SysFS.cpp @@ -131,6 +131,31 @@ ErrorOr SysFSInode::truncate(u64 size) return m_associated_component->truncate(size); } +ErrorOr> SysFSLinkInode::try_create(SysFS const& sysfs, SysFSComponent const& component) +{ + return adopt_nonnull_ref_or_enomem(new (nothrow) SysFSLinkInode(sysfs, component)); +} + +SysFSLinkInode::SysFSLinkInode(SysFS const& fs, SysFSComponent const& component) + : SysFSInode(fs, component) +{ +} + +SysFSLinkInode::~SysFSLinkInode() = default; + +InodeMetadata SysFSLinkInode::metadata() const +{ + // NOTE: No locking required as m_associated_component or its component index will never change during our lifetime. + InodeMetadata metadata; + metadata.inode = { fsid(), m_associated_component->component_index() }; + metadata.mode = S_IFLNK | S_IRUSR | S_IRGRP | S_IROTH | S_IXOTH; + metadata.uid = 0; + metadata.gid = 0; + metadata.size = 0; + metadata.mtime = TimeManagement::boot_time(); + return metadata; +} + ErrorOr> SysFSDirectoryInode::try_create(SysFS const& sysfs, SysFSComponent const& component) { return adopt_nonnull_ref_or_enomem(new (nothrow) SysFSDirectoryInode(sysfs, component)); diff --git a/Kernel/FileSystem/SysFS.h b/Kernel/FileSystem/SysFS.h index 2813c90ad1..b1aa80b15f 100644 --- a/Kernel/FileSystem/SysFS.h +++ b/Kernel/FileSystem/SysFS.h @@ -62,6 +62,19 @@ protected: NonnullRefPtr m_associated_component; }; +class SysFSLinkInode : public SysFSInode { + friend class SysFS; + +public: + static ErrorOr> try_create(SysFS const&, SysFSComponent const&); + virtual ~SysFSLinkInode() override; + +protected: + SysFSLinkInode(SysFS const&, SysFSComponent const&); + // ^Inode + virtual InodeMetadata metadata() const override; +}; + class SysFSDirectoryInode : public SysFSInode { friend class SysFS; diff --git a/Kernel/FileSystem/SysFS/Component.cpp b/Kernel/FileSystem/SysFS/Component.cpp index 38d5de68ab..3216f199d2 100644 --- a/Kernel/FileSystem/SysFS/Component.cpp +++ b/Kernel/FileSystem/SysFS/Component.cpp @@ -57,6 +57,53 @@ mode_t SysFSComponent::permissions() const return S_IRUSR | S_IRGRP | S_IROTH; } +ErrorOr SysFSSymbolicLink::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription*) const +{ + auto blob = TRY(try_to_generate_buffer()); + + if ((size_t)offset >= blob->size()) + return 0; + + ssize_t nread = min(static_cast(blob->size() - offset), static_cast(count)); + TRY(buffer.write(blob->data() + offset, nread)); + return nread; +} + +ErrorOr> SysFSSymbolicLink::try_to_generate_buffer() const +{ + auto return_path_to_mount_point = TRY(try_generate_return_path_to_mount_point()); + if (!m_pointed_component) + return Error::from_errno(EIO); + auto pointed_component_base_name = MUST(KString::try_create(m_pointed_component->name())); + auto pointed_component_relative_path = MUST(m_pointed_component->relative_path(move(pointed_component_base_name), 0)); + auto full_return_and_target_path = TRY(KString::formatted("{}{}", return_path_to_mount_point->view(), pointed_component_relative_path->view())); + return KBuffer::try_create_with_bytes("SysFSSymbolicLink"sv, full_return_and_target_path->view().bytes()); +} + +static ErrorOr> generate_return_path_to_mount_point(NonnullOwnPtr current_path, size_t remaining_hop) +{ + if (remaining_hop == 0) + return current_path; + auto new_path = TRY(KString::formatted("../{}"sv, current_path->view())); + remaining_hop--; + return generate_return_path_to_mount_point(move(new_path), remaining_hop); +} + +ErrorOr> SysFSSymbolicLink::try_generate_return_path_to_mount_point() const +{ + auto hops_from_mountpoint = TRY(relative_path_hops_count_from_mountpoint()); + if (hops_from_mountpoint == 0) + return KString::try_create("./"sv); + auto start_return_path = TRY(KString::try_create("./"sv)); + return generate_return_path_to_mount_point(move(start_return_path), hops_from_mountpoint); +} + +SysFSSymbolicLink::SysFSSymbolicLink(SysFSDirectory const& parent_directory, SysFSComponent const& pointed_component) + : SysFSComponent(parent_directory) + , m_pointed_component(pointed_component) +{ +} + ErrorOr SysFSDirectory::traverse_as_directory(FileSystemID fsid, Function(FileSystem::DirectoryEntryView const&)> callback) const { MutexLocker locker(SysFSComponentRegistry::the().get_lock()); @@ -91,6 +138,11 @@ ErrorOr> SysFSDirectory::to_inode(SysFS const& sysfs_i return TRY(SysFSDirectoryInode::try_create(sysfs_instance, *this)); } +ErrorOr> SysFSSymbolicLink::to_inode(SysFS const& sysfs_instance) const +{ + return TRY(SysFSLinkInode::try_create(sysfs_instance, *this)); +} + ErrorOr> SysFSComponent::to_inode(SysFS const& sysfs_instance) const { return SysFSInode::try_create(sysfs_instance, *this); diff --git a/Kernel/FileSystem/SysFS/Component.h b/Kernel/FileSystem/SysFS/Component.h index 62162a29c9..5c6d7da9b3 100644 --- a/Kernel/FileSystem/SysFS/Component.h +++ b/Kernel/FileSystem/SysFS/Component.h @@ -56,6 +56,20 @@ private: InodeIndex m_component_index {}; }; +class SysFSSymbolicLink : public SysFSComponent { +public: + virtual ErrorOr read_bytes(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const override final; + virtual ErrorOr> to_inode(SysFS const& sysfs_instance) const override final; + +protected: + ErrorOr> try_generate_return_path_to_mount_point() const; + ErrorOr> try_to_generate_buffer() const; + + explicit SysFSSymbolicLink(SysFSDirectory const& parent_directory, SysFSComponent const& pointed_component); + + RefPtr m_pointed_component; +}; + class SysFSDirectory : public SysFSComponent { public: virtual ErrorOr traverse_as_directory(FileSystemID, Function(FileSystem::DirectoryEntryView const&)>) const override;