diff --git a/kernel/include/kernel/FS/ProcFS/Inode.h b/kernel/include/kernel/FS/ProcFS/Inode.h index adaa49c1..011fff5e 100644 --- a/kernel/include/kernel/FS/ProcFS/Inode.h +++ b/kernel/include/kernel/FS/ProcFS/Inode.h @@ -82,4 +82,30 @@ namespace Kernel size_t (*m_callback)(off_t, BAN::ByteSpan); }; + class ProcSymlinkInode final : public TmpInode + { + public: + static BAN::ErrorOr> create_new(BAN::ErrorOr (*)(void*), void* data, TmpFileSystem&, mode_t, uid_t, gid_t); + ~ProcSymlinkInode() = default; + + protected: + virtual BAN::ErrorOr link_target_impl() override; + + // You may not write here and this is always non blocking + virtual BAN::ErrorOr write_impl(off_t, BAN::ConstByteSpan) override { return BAN::Error::from_errno(EINVAL); } + virtual BAN::ErrorOr truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); } + + virtual bool can_read_impl() const override { return false; } + virtual bool can_write_impl() const override { return false; } + virtual bool has_error_impl() const override { return false; } + virtual bool has_hungup_impl() const override { return false; } + + private: + ProcSymlinkInode(BAN::ErrorOr (*callback)(void*), void* data, TmpFileSystem&, const TmpInodeInfo&); + + private: + BAN::ErrorOr (*m_callback)(void*); + void* m_data; + }; + } diff --git a/kernel/kernel/FS/ProcFS/FileSystem.cpp b/kernel/kernel/FS/ProcFS/FileSystem.cpp index 08ce62d3..c9452320 100644 --- a/kernel/kernel/FS/ProcFS/FileSystem.cpp +++ b/kernel/kernel/FS/ProcFS/FileSystem.cpp @@ -38,6 +38,14 @@ namespace Kernel auto cmdline_inode = MUST(TmpFileInode::create_new(*s_instance, 0444, 0, 0)); MUST(cmdline_inode->write(0, { reinterpret_cast(g_boot_info.command_line.data()), g_boot_info.command_line.size() })); MUST(static_cast(s_instance->root_inode().ptr())->link_inode(*cmdline_inode, "cmdline"_sv)); + + auto self_inode = MUST(ProcSymlinkInode::create_new( + [](void*) -> BAN::ErrorOr { + return BAN::String::formatted("{}", Process::current().pid()); + }, + nullptr, *s_instance, 0444, 0, 0) + ); + MUST(static_cast(s_instance->root_inode().ptr())->link_inode(*self_inode, "self"_sv)); } ProcFileSystem& ProcFileSystem::get() diff --git a/kernel/kernel/FS/ProcFS/Inode.cpp b/kernel/kernel/FS/ProcFS/Inode.cpp index 66d3fe28..14cfe253 100644 --- a/kernel/kernel/FS/ProcFS/Inode.cpp +++ b/kernel/kernel/FS/ProcFS/Inode.cpp @@ -83,4 +83,27 @@ namespace Kernel return m_callback(offset, buffer); } + BAN::ErrorOr> ProcSymlinkInode::create_new(BAN::ErrorOr (*callback)(void*), void* data, TmpFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) + { + auto inode_info = create_inode_info(Mode::IFLNK | mode, uid, gid); + + auto* inode_ptr = new ProcSymlinkInode(callback, data, fs, inode_info); + if (inode_ptr == nullptr) + return BAN::Error::from_errno(ENOMEM); + return BAN::RefPtr::adopt(inode_ptr); + } + + ProcSymlinkInode::ProcSymlinkInode(BAN::ErrorOr (*callback)(void*), void* data, TmpFileSystem& fs, const TmpInodeInfo& inode_info) + : TmpInode(fs, MUST(fs.allocate_inode(inode_info)), inode_info) + , m_callback(callback) + , m_data(data) + { + m_inode_info.mode |= Inode::Mode::IFLNK; + } + + BAN::ErrorOr ProcSymlinkInode::link_target_impl() + { + return m_callback(m_data); + } + }