#pragma once #include #include #include #include #include struct Credentials; namespace VFS { enum class InodeType { RegularFile, Directory, CharacterDevice, BlockDevice, Symlink, FIFO, }; class Inode; class FileSystem { public: virtual SharedPtr root_inode() const = 0; virtual Result> create_file_inode() = 0; virtual Result> create_dir_inode(SharedPtr parent) = 0; virtual Result> create_device_inode(u32 major, u32 minor) = 0; virtual Result> create_symlink_inode(StringView link) = 0; virtual Result set_mount_dir(SharedPtr parent) = 0; virtual bool is_readonly() const { return false; } virtual u64 handles() const { return m_handles; } virtual void add_handle() { m_handles++; } virtual void remove_handle() { m_handles--; } virtual dev_t host_device_id() const = 0; virtual ~FileSystem() = default; protected: u64 m_handles { 0 }; }; struct DirectoryEntry { public: SharedPtr inode; StaticString<128> name; }; class Inode { public: virtual Result ioctl(int, void*) { return err(ENOTTY); } // Directory-specific methods virtual Result> find(const char* name) const = 0; virtual Option get(usize index) const = 0; virtual Result> create_file(const char* name) = 0; virtual Result> create_subdirectory(const char* name) = 0; virtual Result add_entry(SharedPtr inode, const char* name) = 0; virtual Result remove_entry(const char* name) = 0; virtual Result replace_entry(SharedPtr inode, const char* name) = 0; virtual usize entries() const = 0; // File-specific methods virtual Result read(u8* buf, usize offset, usize length) const = 0; virtual Result write(const u8* buf, usize offset, usize length) = 0; virtual Result truncate(usize size) = 0; virtual bool blocking() const = 0; // Symlink-specific methods virtual Result readlink() { return StringView {}; } virtual dev_t device_id() const { return luna_dev_makedev(0, 0); } // Metadata accessors virtual usize size() const = 0; virtual mode_t mode() const = 0; virtual nlink_t nlinks() const { return 1; } virtual u32 uid() const { return 0; } virtual u32 gid() const { return 0; } virtual bool is_mountpoint() const { return false; } virtual void did_link() = 0; virtual void did_unlink() = 0; // Metadata changers virtual Result chmod(mode_t mode) = 0; virtual Result chown(u32 uid, u32 gid) = 0; // Generic VFS-related methods virtual FileSystem* fs() const = 0; virtual ~Inode() = default; virtual InodeType type() const = 0; virtual usize inode_number() const = 0; virtual void add_handle() { auto* f = fs(); if (f) f->add_handle(); } virtual void remove_handle() { auto* f = fs(); if (f) f->remove_handle(); } }; class FileInode : Inode { public: Result> find(const char*) const override { return err(ENOTDIR); } Option get(usize) const override { return {}; } Result> create_file(const char*) override { return err(ENOTDIR); } Result> create_subdirectory(const char*) override { return err(ENOTDIR); } Result add_entry(SharedPtr, const char*) override { return err(ENOTDIR); } Result replace_entry(SharedPtr, const char*) override { return err(ENOTDIR); } Result remove_entry(const char*) override { return err(ENOTDIR); } usize entries() const override { return 0; } bool blocking() const override { return false; } InodeType type() const override { return InodeType::RegularFile; } virtual ~FileInode() = default; }; class DeviceInode : Inode { public: Result> find(const char*) const override { return err(ENOTDIR); } Option get(usize) const override { return {}; } Result> create_file(const char*) override { return err(ENOTDIR); } Result> create_subdirectory(const char*) override { return err(ENOTDIR); } Result add_entry(SharedPtr, const char*) override { return err(ENOTDIR); } Result replace_entry(SharedPtr, const char*) override { return err(ENOTDIR); } Result remove_entry(const char*) override { return err(ENOTDIR); } usize entries() const override { return 0; } InodeType type() const override { return InodeType::CharacterDevice; } virtual ~DeviceInode() = default; }; Result> resolve_path(const char* path, Credentials auth, SharedPtr working_directory = {}, bool follow_last_symlink = true); Result> create_directory(const char* path, Credentials auth, SharedPtr working_directory = {}); Result> create_file(const char* path, Credentials auth, SharedPtr working_directory = {}); Result validate_filename(StringView name); bool can_execute(SharedPtr inode, Credentials auth); bool can_read(SharedPtr inode, Credentials auth); bool can_write(SharedPtr inode, Credentials auth); bool is_setuid(SharedPtr inode); bool is_setgid(SharedPtr inode); bool is_sticky(SharedPtr inode); bool is_seekable(SharedPtr inode); Inode& root_inode(); Result mount_root(SharedPtr fs); Result pivot_root(const char* new_root, const char* put_old, SharedPtr working_directory); Result mount(const char* path, SharedPtr fs, Credentials auth, SharedPtr working_directory = {}); Result umount(const char* path, Credentials auth, SharedPtr working_directory = {}); }