#pragma once #include #include #include #include class Process; class ProcFSInode; class ProcFS final : public FS { friend class ProcFSInode; public: [[gnu::pure]] static ProcFS& the(); virtual ~ProcFS() override; static Retained create(); virtual bool initialize() override; virtual const char* class_name() const override; virtual InodeIdentifier root_inode() const override; virtual RetainPtr get_inode(InodeIdentifier) const override; virtual RetainPtr create_inode(InodeIdentifier parent_id, const String& name, mode_t, off_t size, dev_t, int& error) override; virtual RetainPtr create_directory(InodeIdentifier parent_id, const String& name, mode_t, int& error) override; void add_sys_file(String&&, Function&& read_callback, Function&& write_callback); void add_sys_bool(String&&, Lockable&, Function&& notify_callback = nullptr); void add_sys_string(String&&, Lockable&, Function&& notify_callback = nullptr); private: ProcFS(); struct ProcFSDirectoryEntry { ProcFSDirectoryEntry() {} ProcFSDirectoryEntry(const char* a_name, unsigned a_proc_file_type, Function&& a_read_callback = nullptr, Function&& a_write_callback = nullptr, RetainPtr&& a_inode = nullptr) : name(a_name) , proc_file_type(a_proc_file_type) , read_callback(move(a_read_callback)) , write_callback(move(a_write_callback)) , inode(move(a_inode)) { } const char* name { nullptr }; unsigned proc_file_type { 0 }; Function read_callback; Function write_callback; RetainPtr inode; InodeIdentifier identifier(unsigned fsid) const; }; ProcFSDirectoryEntry* get_directory_entry(InodeIdentifier) const; Vector m_entries; Vector m_sys_entries; mutable Lock m_inodes_lock; mutable HashMap m_inodes; RetainPtr m_root_inode; Lockable m_kmalloc_stack_helper; }; struct ProcFSInodeCustomData { virtual ~ProcFSInodeCustomData(); }; class ProcFSInode final : public Inode { friend class ProcFS; public: virtual ~ProcFSInode() override; void set_custom_data(OwnPtr&& custom_data) { m_custom_data = move(custom_data); } ProcFSInodeCustomData* custom_data() { return m_custom_data.ptr(); } const ProcFSInodeCustomData* custom_data() const { return m_custom_data.ptr(); } private: // ^Inode virtual ssize_t read_bytes(off_t, ssize_t, byte* buffer, FileDescription*) const override; virtual InodeMetadata metadata() const override; virtual bool traverse_as_directory(Function) const override; virtual InodeIdentifier lookup(StringView name) override; virtual void flush_metadata() override; virtual ssize_t write_bytes(off_t, ssize_t, const byte* buffer, FileDescription*) override; virtual KResult add_child(InodeIdentifier child_id, const String& name, mode_t) override; virtual KResult remove_child(const String& name) override; virtual size_t directory_entry_count() const override; virtual KResult chmod(mode_t) override; virtual KResult chown(uid_t, gid_t) override; ProcFS& fs() { return static_cast(Inode::fs()); } const ProcFS& fs() const { return static_cast(Inode::fs()); } ProcFSInode(ProcFS&, unsigned index); OwnPtr m_custom_data; };