#pragma once #include <luna/SharedPtr.h> #include <luna/StaticString.h> #include <luna/StringView.h> #include <sys/types.h> struct Credentials; namespace VFS { enum class InodeType { RegularFile, Directory, Device, Symlink }; class Inode; class FileSystem { public: virtual SharedPtr<Inode> root_inode() const = 0; virtual Result<SharedPtr<Inode>> create_file_inode() = 0; virtual Result<SharedPtr<Inode>> create_dir_inode(SharedPtr<Inode> parent) = 0; virtual Result<SharedPtr<Inode>> create_device_inode(u32 major, u32 minor) = 0; virtual Result<SharedPtr<Inode>> create_symlink_inode(StringView link) = 0; virtual Result<void> set_mount_dir(SharedPtr<Inode> parent) = 0; virtual u64 handles() const { return m_handles; } virtual void add_handle() { m_handles++; } virtual void remove_handle() { m_handles--; } virtual ~FileSystem() = default; protected: u64 m_handles { 0 }; }; struct DirectoryEntry { public: SharedPtr<Inode> inode; StaticString<128> name; }; class Inode { public: virtual Result<u64> ioctl(int, void*) { return err(ENOTTY); } // Directory-specific methods virtual Result<SharedPtr<Inode>> find(const char* name) const = 0; virtual Option<DirectoryEntry> get(usize index) const = 0; virtual Result<SharedPtr<Inode>> create_file(const char* name) = 0; virtual Result<SharedPtr<Inode>> create_subdirectory(const char* name) = 0; virtual Result<void> add_entry(SharedPtr<Inode> inode, const char* name) = 0; virtual Result<void> remove_entry(const char* name) = 0; virtual Result<void> replace_entry(SharedPtr<Inode> inode, const char* name) = 0; virtual usize entries() const = 0; // File-specific methods virtual Result<usize> read(u8* buf, usize offset, usize length) const = 0; virtual Result<usize> write(const u8* buf, usize offset, usize length) = 0; virtual Result<void> truncate(usize size) = 0; virtual bool blocking() const = 0; // Symlink-specific methods virtual Result<StringView> readlink() { return StringView {}; } // Metadata accessors virtual usize size() const = 0; virtual mode_t mode() const = 0; 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<void> chmod(mode_t mode) = 0; virtual Result<void> 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<SharedPtr<Inode>> find(const char*) const override { return err(ENOTDIR); } Option<DirectoryEntry> get(usize) const override { return {}; } Result<SharedPtr<Inode>> create_file(const char*) override { return err(ENOTDIR); } Result<SharedPtr<Inode>> create_subdirectory(const char*) override { return err(ENOTDIR); } Result<void> add_entry(SharedPtr<Inode>, const char*) override { return err(ENOTDIR); } Result<void> replace_entry(SharedPtr<Inode>, const char*) override { return err(ENOTDIR); } Result<void> 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<SharedPtr<Inode>> find(const char*) const override { return err(ENOTDIR); } Option<DirectoryEntry> get(usize) const override { return {}; } Result<SharedPtr<Inode>> create_file(const char*) override { return err(ENOTDIR); } Result<SharedPtr<Inode>> create_subdirectory(const char*) override { return err(ENOTDIR); } Result<void> add_entry(SharedPtr<Inode>, const char*) override { return err(ENOTDIR); } Result<void> replace_entry(SharedPtr<Inode>, const char*) override { return err(ENOTDIR); } Result<void> remove_entry(const char*) override { return err(ENOTDIR); } usize entries() const override { return 0; } InodeType type() const override { return InodeType::Device; } virtual ~DeviceInode() = default; }; Result<SharedPtr<Inode>> resolve_path(const char* path, Credentials auth, SharedPtr<VFS::Inode> working_directory = {}, bool follow_last_symlink = true); Result<SharedPtr<Inode>> create_directory(const char* path, Credentials auth, SharedPtr<VFS::Inode> working_directory = {}); Result<SharedPtr<Inode>> create_file(const char* path, Credentials auth, SharedPtr<VFS::Inode> working_directory = {}); Result<void> validate_filename(StringView name); bool can_execute(SharedPtr<Inode> inode, Credentials auth); bool can_read(SharedPtr<Inode> inode, Credentials auth); bool can_write(SharedPtr<Inode> inode, Credentials auth); bool is_setuid(SharedPtr<Inode> inode); bool is_setgid(SharedPtr<Inode> inode); Inode& root_inode(); Result<void> mount_root(SharedPtr<VFS::FileSystem> fs); Result<void> mount(const char* path, SharedPtr<VFS::FileSystem> fs, Credentials auth, SharedPtr<Inode> working_directory = {}); Result<void> umount(const char* path, Credentials auth, SharedPtr<Inode> working_directory = {}); }