#pragma once #include "fs/tmpfs/FileSystem.h" #include #include #include #include #include namespace TmpFS { class FileInode : public VFS::FileInode { public: FileInode() = default; void set_fs(FileSystem& fs, Badge) { m_fs = &fs; } void set_inode_number(usize inum, Badge) { m_inode_number = inum; } VFS::FileSystem* fs() const override { return m_fs; } usize inode_number() const override { return m_inode_number; } Result read(u8*, usize, usize) const override; Result write(const u8*, usize, usize) override; Result truncate(usize size) override; usize size() const override; mode_t mode() const override { return m_mode; } u32 uid() const override { return m_uid; } u32 gid() const override { return m_gid; } nlink_t nlinks() const override { return (nlink_t)m_nlinks; } Result chmod(mode_t mode) override { m_mode = mode; return {}; } Result chown(u32 uid, u32 gid) override { m_uid = uid; m_gid = gid; return {}; } void did_link() override { m_nlinks++; } void did_unlink() override { m_nlinks--; } virtual ~FileInode() = default; private: VFS::FileSystem* m_fs; Buffer m_data_buffer; usize m_inode_number; mode_t m_mode; u32 m_uid { 0 }; u32 m_gid { 0 }; u32 m_nlinks { 0 }; }; class SymlinkInode : public VFS::FileInode { public: SymlinkInode() = default; VFS::InodeType type() const override { return VFS::InodeType::Symlink; } void set_fs(FileSystem& fs, Badge) { m_fs = &fs; } void set_inode_number(usize inum, Badge) { m_inode_number = inum; } Result set_link(StringView link, Badge) { m_link = TRY(String::from_string_view(link)); return {}; } VFS::FileSystem* fs() const override { return m_fs; } usize inode_number() const override { return m_inode_number; } Result read(u8*, usize, usize) const override { return err(ENOTSUP); } Result write(const u8*, usize, usize) override { return err(ENOTSUP); } Result truncate(usize) override { return err(ENOTSUP); } usize size() const override { return m_link.length(); } mode_t mode() const override { return 0777; } u32 uid() const override { return m_uid; } u32 gid() const override { return m_gid; } nlink_t nlinks() const override { return (nlink_t)m_nlinks; } Result chmod(mode_t) override { return {}; } Result chown(u32 uid, u32 gid) override { m_uid = uid; m_gid = gid; return {}; } void did_link() override { m_nlinks++; } void did_unlink() override { m_nlinks--; } Result readlink() override { return m_link.view(); } virtual ~SymlinkInode() = default; private: VFS::FileSystem* m_fs; String m_link; usize m_inode_number; u32 m_uid { 0 }; u32 m_gid { 0 }; u32 m_nlinks { 0 }; }; class DeviceInode : public VFS::DeviceInode { public: DeviceInode() = default; VFS::InodeType type() const override { return m_device->is_block_device() ? VFS::InodeType::BlockDevice : VFS::InodeType::CharacterDevice; } void set_fs(FileSystem& fs, Badge) { m_fs = &fs; } void set_inode_number(usize inum, Badge) { m_inode_number = inum; } void set_device(SharedPtr device, Badge) { m_device = device; } void set_device_id(dev_t id, Badge) { m_device_id = id; } VFS::FileSystem* fs() const override { return m_fs; } dev_t device_id() const override { return m_device_id; } usize inode_number() const override { return m_inode_number; } Result read(u8* buf, usize offset, usize length) const override { return m_device->read(buf, offset, length); } Result write(const u8* buf, usize offset, usize length) override { return m_device->write(buf, offset, length); } Result truncate(usize) override { // POSIX says truncate is for regular files, but doesn't tell us what error to return for non-regular files. return err(EINVAL); } Result ioctl(int request, void* arg) override { return m_device->ioctl(request, arg); } Result isatty() const override { return m_device->isatty(); } bool blocking() const override { return m_device->blocking(); } usize size() const override { return m_device->size(); } mode_t mode() const override { return m_mode; } u32 uid() const override { return m_uid; } u32 gid() const override { return m_gid; } nlink_t nlinks() const override { return (nlink_t)m_nlinks; } Result chmod(mode_t mode) override { m_mode = mode; return {}; } Result chown(u32 uid, u32 gid) override { m_uid = uid; m_gid = gid; return {}; } void did_link() override { m_nlinks++; } void did_unlink() override { m_nlinks--; } virtual ~DeviceInode() = default; private: VFS::FileSystem* m_fs; SharedPtr m_device; usize m_inode_number; mode_t m_mode; u32 m_uid { 0 }; u32 m_gid { 0 }; u32 m_nlinks { 0 }; dev_t m_device_id { 0 }; }; class DirInode : public VFS::Inode { public: DirInode() = default; void set_fs(FileSystem& fs, Badge) { m_fs = &fs; } void set_inode_number(usize inum, Badge) { m_inode_number = inum; } void set_self(SharedPtr self, Badge) { m_self = self; } Result> find(const char* name) const override; Option get(usize index) const override; Result read(u8*, usize, usize) const override { return err(EISDIR); } Result write(const u8*, usize, usize) override { return err(EISDIR); } Result truncate(usize) override { return err(EISDIR); } bool blocking() const override { return false; } usize size() const override { return 0; } mode_t mode() const override { return m_mode; } u32 uid() const override { return m_uid; } u32 gid() const override { return m_gid; } Result chmod(mode_t mode) override { m_mode = mode; return {}; } Result chown(u32 uid, u32 gid) override { m_uid = uid; m_gid = gid; return {}; } VFS::FileSystem* fs() const override { return m_fs; } usize inode_number() const override { return m_inode_number; } VFS::InodeType type() const override { return VFS::InodeType::Directory; } void did_link() override { } void did_unlink() override { m_self = {}; m_entries.clear(); } usize entries() const override { return m_entries.size(); } Result remove_entry(const char* name) override; Result> create_file(const char* name) override; Result> create_subdirectory(const char* name) override; Result add_entry(SharedPtr inode, const char* name); Result replace_entry(SharedPtr inode, const char* name); virtual ~DirInode() = default; private: VFS::FileSystem* m_fs; usize m_inode_number; mode_t m_mode; u32 m_uid { 0 }; u32 m_gid { 0 }; SharedPtr m_self; Vector m_entries; }; }