#pragma once #include #include #include #include #include #include #include "InodeIdentifier.h" #include "InodeMetadata.h" #include "Limits.h" #include "FileSystem.h" #include #define O_RDONLY 0 #define O_WRONLY 1 #define O_RDWR 2 #define O_CREAT 0100 #define O_EXCL 0200 #define O_NOCTTY 0400 #define O_TRUNC 01000 #define O_APPEND 02000 #define O_NONBLOCK 04000 #define O_DIRECTORY 00200000 #define O_NOFOLLOW 00400000 #define O_CLOEXEC 02000000 #define O_NOFOLLOW_NOERROR 0x4000000 class Device; class FileDescriptor; inline constexpr dword encoded_device(unsigned major, unsigned minor) { return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); } class VFS; class VFS { AK_MAKE_ETERNAL public: class Mount { public: Mount(InodeIdentifier host, RetainPtr&&); InodeIdentifier host() const { return m_host; } InodeIdentifier guest() const { return m_guest; } const FS& guest_fs() const { return *m_guest_fs; } private: InodeIdentifier m_host; InodeIdentifier m_guest; RetainPtr m_guest_fs; }; [[gnu::pure]] static VFS& the(); VFS(); ~VFS(); bool mount_root(RetainPtr&&); bool mount(RetainPtr&&, const String& path); RetainPtr open(RetainPtr&&, int& error, int options); RetainPtr open(const String& path, int& error, int options, mode_t mode, Inode& base); RetainPtr create(const String& path, int& error, int options, mode_t mode, Inode& base); KResult mkdir(const String& path, mode_t mode, Inode& base); bool link(const String& old_path, const String& new_path, Inode& base, int& error); bool unlink(const String& path, Inode& base, int& error); bool rmdir(const String& path, Inode& base, int& error); KResult chmod(const String& path, mode_t, Inode& base); bool stat(const String& path, int& error, int options, Inode& base, struct stat&); KResult utime(const String& path, Inode& base, time_t atime, time_t mtime); void register_device(Device&); void unregister_device(Device&); size_t mount_count() const { return m_mounts.size(); } void for_each_mount(Function) const; String absolute_path(Inode&); String absolute_path(InodeIdentifier); InodeIdentifier root_inode_id() const; Inode* root_inode() { return m_root_inode.ptr(); } const Inode* root_inode() const { return m_root_inode.ptr(); } void sync(); Device* get_device(unsigned major, unsigned minor); private: friend class FileDescriptor; RetainPtr get_inode(InodeIdentifier); bool is_vfs_root(InodeIdentifier) const; void traverse_directory_inode(Inode&, Function); InodeIdentifier old_resolve_path(const String& path, InodeIdentifier base, int& error, int options = 0, InodeIdentifier* parent_id = nullptr); KResultOr resolve_path(const String& path, InodeIdentifier base, int options = 0, InodeIdentifier* parent_id = nullptr); RetainPtr resolve_path_to_inode(const String& path, Inode& base, int& error, RetainPtr* parent_id = nullptr); KResultOr> resolve_path_to_inode(const String& path, Inode& base, RetainPtr* parent_id = nullptr); KResultOr resolve_symbolic_link(InodeIdentifier base, Inode& symlink_inode); Mount* find_mount_for_host(InodeIdentifier); Mount* find_mount_for_guest(InodeIdentifier); RetainPtr m_root_inode; Vector> m_mounts; HashMap m_devices; };