#pragma once #include #include #include #include #include #include "InodeIdentifier.h" class FileHandle; class FileSystem; class VirtualFileSystem { public: struct Node { InodeIdentifier inode; bool inUse() const { return inode.isValid(); } void retain(); void release(); FileSystem* fileSystem() { return inode.fileSystem(); } const FileSystem* fileSystem() const { return inode.fileSystem(); } private: friend class VirtualFileSystem; VirtualFileSystem* vfs { nullptr }; unsigned retainCount { 0 }; }; VirtualFileSystem(); ~VirtualFileSystem(); bool isDirectory(const String& path); void listDirectory(const String& path); void listDirectoryRecursively(const String& path); unsigned maxNodeCount() const { return m_maxNodeCount; } unsigned allocatedNodeCount() const { return m_maxNodeCount - m_nodeFreeList.size(); } Node* root() { return m_rootNode.ptr(); } const Node* root() const { return m_rootNode.ptr(); } bool mountRoot(RetainPtr&&); bool mount(RetainPtr&&, const String& path); OwnPtr open(const String& path); OwnPtr create(const String& path); bool isRoot(InodeIdentifier) const; bool touch(const String&path); private: template void enumerateDirectoryInode(InodeIdentifier, F func); InodeIdentifier resolvePath(const String& path); InodeIdentifier resolveSymbolicLink(const String& basePath, InodeIdentifier symlinkInode); RetainPtr allocateNode(); void freeNode(Node*); RetainPtr makeNode(InodeIdentifier); RetainPtr getOrCreateNode(InodeIdentifier); class Mount { public: Mount(InodeIdentifier host, RetainPtr&&); InodeIdentifier host() const { return m_host; } InodeIdentifier guest() const { return m_guest; } private: InodeIdentifier m_host; InodeIdentifier m_guest; RetainPtr m_fileSystem; }; Mount* findMountForHost(InodeIdentifier); Mount* findMountForGuest(InodeIdentifier); HashMap m_inode2vnode; Vector> m_mounts; unsigned m_maxNodeCount { 0 }; Node* m_nodes { nullptr }; Vector m_nodeFreeList; RetainPtr m_rootNode; };