#pragma once #include "fs/VFS.h" #include "fs/devices/DeviceRegistry.h" #include #include #include #include #include namespace TmpFS { class FileSystem : public VFS::FileSystem { public: SharedPtr root_inode() const override { return m_root_inode; } Result> create_file_inode() override; Result> create_dir_inode(SharedPtr parent) override; Result> create_device_inode(u32 major, u32 minor) override; Result set_mount_dir(SharedPtr parent) override; static Result> create(); virtual ~FileSystem() = default; private: FileSystem() = default; void set_root(SharedPtr root); SharedPtr m_root_inode; Atomic m_next_inode_number { 2 }; }; 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; } 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 DeviceInode : public VFS::DeviceInode { public: DeviceInode() = default; 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; } VFS::FileSystem* fs() const override { return m_fs; } 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); } 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; } 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 }; }; 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; }; }