diff --git a/kernel/src/fs/ext2/FileSystem.cpp b/kernel/src/fs/ext2/FileSystem.cpp new file mode 100644 index 00000000..d77af270 --- /dev/null +++ b/kernel/src/fs/ext2/FileSystem.cpp @@ -0,0 +1,27 @@ +#include "fs/ext2/FileSystem.h" + +namespace Ext2 +{ + FileSystem::FileSystem() + { + } + + Result> FileSystem::find_inode_by_number(ino_t inode) + { + auto maybe_inode = m_inode_cache.try_get(inode); + if (maybe_inode.has_value()) return maybe_inode.value(); + + return err(ENOENT); + } + + Result> FileSystem::create(SharedPtr host_device) + { + SharedPtr fs = TRY(adopt_shared_if_nonnull(new (std::nothrow) FileSystem())); + const usize nread = TRY(host_device->read((u8*)&fs->m_superblock, 1024, 1024)); + if (nread != 1024) return err(EINVAL); // Source had an invalid superblock. + if (fs->m_superblock.signature != EXT2_MAGIC) return err(EINVAL); // Source had an invalid superblock. + + // TODO: Implement basic Ext2 reading, enough to be able to mount a volume. + return err(ENOTSUP); + } +} diff --git a/kernel/src/fs/ext2/FileSystem.h b/kernel/src/fs/ext2/FileSystem.h new file mode 100644 index 00000000..157edf2e --- /dev/null +++ b/kernel/src/fs/ext2/FileSystem.h @@ -0,0 +1,100 @@ +#pragma once +#include "fs/VFS.h" +#include "fs/devices/DeviceRegistry.h" +#include + +#define EXT2_MAGIC 0xef53 + +namespace Ext2 +{ + struct [[gnu::packed]] Superblock + { + u32 nr_inodes; + u32 nr_blocks; + u32 nr_reserved; + u32 nr_free_inodes; + u32 nr_free_blocks; + u32 superblock_block; + u32 log_block_size; + u32 log_fragment_size; + u32 blocks_per_block_group; + u32 fragments_per_block_group; + u32 inodes_per_block_group; + u32 last_mount_time; + u32 last_write_time; + u16 mounts_since_last_fsck; + u16 mounts_allowed_before_fsck; + u16 signature; + u16 fs_state; + u16 error_action; + u16 minor_version; + u32 last_fsck_time; + u32 fsck_time_interval; + u32 os_id; + u32 major_version; + u16 reserved_block_uid; + u16 reserved_block_gid; + u8 padding[1024 - 84]; + }; + + static_assert(sizeof(Superblock) == 1024); + + class FileSystem : public VFS::FileSystem + { + public: + SharedPtr root_inode() const override + { + return m_root_inode; + } + + Result> create_file_inode() override + { + return err(EROFS); + } + + Result> create_dir_inode(SharedPtr) override + { + return err(EROFS); + } + + Result> create_device_inode(u32, u32) override + { + return err(EROFS); + } + + Result> create_symlink_inode(StringView) override + { + return err(EROFS); + } + + Result set_mount_dir(SharedPtr) override + { + return {}; + } + + static Result> create(SharedPtr host_device); + + dev_t host_device_id() const override + { + return m_host_device_id; + } + + Result> find_inode_by_number(ino_t inode); + + virtual ~FileSystem() = default; + + private: + FileSystem(); + + SharedPtr m_root_inode; + + SharedPtr m_host_device; + dev_t m_host_device_id; + + Superblock m_superblock; + + // FIXME: This inode cache will keep all inodes in it alive despite having no other references to it, but we're + // not worrying about that as for now the filesystem implementation is read-only. + HashMap> m_inode_cache; + }; +}