2023-06-20 21:39:22 +02:00
|
|
|
#pragma once
|
|
|
|
#include "fs/VFS.h"
|
|
|
|
#include "fs/devices/DeviceRegistry.h"
|
|
|
|
#include <luna/HashMap.h>
|
|
|
|
|
|
|
|
#define EXT2_MAGIC 0xef53
|
|
|
|
|
2023-06-22 19:41:35 +02:00
|
|
|
#define EXT2_REQUIRED_COMPAT_D_TYPE 0x0002
|
|
|
|
|
2023-06-20 21:39:22 +02:00
|
|
|
namespace Ext2
|
|
|
|
{
|
|
|
|
struct [[gnu::packed]] Superblock
|
|
|
|
{
|
|
|
|
u32 nr_inodes;
|
|
|
|
u32 nr_blocks;
|
2023-06-21 21:32:28 +02:00
|
|
|
u32 nr_reserved_blocks;
|
2023-06-20 21:39:22 +02:00
|
|
|
u32 nr_free_blocks;
|
2023-06-21 21:32:28 +02:00
|
|
|
u32 nr_free_inodes;
|
|
|
|
u32 first_data_block;
|
2023-06-20 21:39:22 +02:00
|
|
|
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;
|
2023-06-21 21:32:28 +02:00
|
|
|
|
2023-06-20 21:39:22 +02:00
|
|
|
u16 mounts_since_last_fsck;
|
|
|
|
u16 mounts_allowed_before_fsck;
|
|
|
|
u16 signature;
|
|
|
|
u16 fs_state;
|
|
|
|
u16 error_action;
|
|
|
|
u16 minor_version;
|
2023-06-21 21:32:28 +02:00
|
|
|
|
2023-06-20 21:39:22 +02:00
|
|
|
u32 last_fsck_time;
|
|
|
|
u32 fsck_time_interval;
|
|
|
|
u32 os_id;
|
|
|
|
u32 major_version;
|
2023-06-21 21:32:28 +02:00
|
|
|
|
2023-06-20 21:39:22 +02:00
|
|
|
u16 reserved_block_uid;
|
|
|
|
u16 reserved_block_gid;
|
2023-07-02 19:50:27 +02:00
|
|
|
struct [[gnu::packed]]
|
2023-06-22 19:41:35 +02:00
|
|
|
{
|
|
|
|
u32 first_non_reserved_inode;
|
|
|
|
u16 inode_size;
|
|
|
|
u16 this_block_group;
|
|
|
|
u32 optional_features;
|
|
|
|
u32 required_features;
|
|
|
|
u32 ro_features;
|
|
|
|
u8 fsid[16];
|
|
|
|
u8 name[16];
|
|
|
|
u8 last_mountpoint[64];
|
|
|
|
u32 compression_algs;
|
|
|
|
u8 nr_preallocated_blocks_for_files;
|
|
|
|
u8 nr_preallocated_blocks_for_dirs;
|
|
|
|
u16 unused;
|
|
|
|
u8 journal_id[16];
|
|
|
|
u32 journal_inode;
|
|
|
|
u32 journal_device;
|
|
|
|
u32 orphan_inode_head;
|
|
|
|
} ext_superblock;
|
|
|
|
u8 padding[1024 - 236];
|
2023-06-20 21:39:22 +02:00
|
|
|
};
|
|
|
|
|
2023-06-21 21:32:28 +02:00
|
|
|
struct [[gnu::packed]] BlockGroupDescriptor
|
|
|
|
{
|
|
|
|
u32 block_usage_addr;
|
|
|
|
u32 inode_usage_addr;
|
|
|
|
u32 inode_table_start;
|
|
|
|
u16 nr_free_blocks;
|
|
|
|
u16 nr_free_inodes;
|
|
|
|
u16 nr_directories;
|
|
|
|
u8 padding[32 - 18];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct [[gnu::packed]] RawInode
|
|
|
|
{
|
|
|
|
u16 mode;
|
|
|
|
u16 uid;
|
|
|
|
u32 size_low;
|
|
|
|
u32 atime;
|
|
|
|
u32 create_time;
|
|
|
|
u32 mtime;
|
|
|
|
u32 delete_time;
|
|
|
|
u16 gid;
|
|
|
|
u16 nlinks;
|
|
|
|
u32 sectors_used;
|
|
|
|
u32 flags;
|
|
|
|
u32 os_specific_1;
|
|
|
|
u32 direct_pointers[12];
|
|
|
|
u32 singly_indirect_ptr;
|
|
|
|
u32 doubly_indirect_ptr;
|
|
|
|
u32 triply_indirect_ptr;
|
|
|
|
u32 gen_number;
|
|
|
|
u32 extended_attrs;
|
|
|
|
u32 size_high;
|
|
|
|
u32 frag_addr;
|
|
|
|
u32 os_specific_2[3];
|
|
|
|
};
|
|
|
|
|
2023-06-22 19:41:35 +02:00
|
|
|
struct [[gnu::packed]] RawDirectoryEntry
|
|
|
|
{
|
|
|
|
u32 inum;
|
|
|
|
u16 size;
|
|
|
|
union {
|
|
|
|
u16 name_length;
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
u8 name_length_low;
|
|
|
|
u8 type;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
char name[4]; // Names should be padded to a multiple of 4 bytes.
|
|
|
|
};
|
|
|
|
|
2023-06-20 21:39:22 +02:00
|
|
|
static_assert(sizeof(Superblock) == 1024);
|
2023-06-21 21:32:28 +02:00
|
|
|
static_assert(sizeof(BlockGroupDescriptor) == 32);
|
|
|
|
static_assert(sizeof(RawInode) == 128);
|
2023-06-20 21:39:22 +02:00
|
|
|
|
2023-06-22 16:34:22 +02:00
|
|
|
class Inode;
|
|
|
|
|
2023-06-20 21:39:22 +02:00
|
|
|
class FileSystem : public VFS::FileSystem
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SharedPtr<VFS::Inode> root_inode() const override
|
|
|
|
{
|
|
|
|
return m_root_inode;
|
|
|
|
}
|
|
|
|
|
2023-08-01 17:20:28 +02:00
|
|
|
Result<SharedPtr<VFS::Inode>> create_file_inode(mode_t) override
|
2023-06-20 21:39:22 +02:00
|
|
|
{
|
|
|
|
return err(EROFS);
|
|
|
|
}
|
|
|
|
|
2023-08-01 17:20:28 +02:00
|
|
|
Result<SharedPtr<VFS::Inode>> create_dir_inode(SharedPtr<VFS::Inode>, mode_t) override
|
2023-06-20 21:39:22 +02:00
|
|
|
{
|
|
|
|
return err(EROFS);
|
|
|
|
}
|
|
|
|
|
2023-08-01 17:20:28 +02:00
|
|
|
Result<SharedPtr<VFS::Inode>> create_device_inode(u32, u32, mode_t) override
|
2023-06-20 21:39:22 +02:00
|
|
|
{
|
|
|
|
return err(EROFS);
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<SharedPtr<VFS::Inode>> create_symlink_inode(StringView) override
|
|
|
|
{
|
|
|
|
return err(EROFS);
|
|
|
|
}
|
|
|
|
|
2023-06-22 19:41:35 +02:00
|
|
|
Result<void> set_mount_dir(SharedPtr<VFS::Inode>) override;
|
2023-06-20 21:39:22 +02:00
|
|
|
|
2023-06-22 19:57:12 +02:00
|
|
|
Result<void> reset_mount_dir() override;
|
|
|
|
|
2023-06-21 21:32:28 +02:00
|
|
|
bool is_readonly() const override
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-06-20 21:39:22 +02:00
|
|
|
static Result<SharedPtr<VFS::FileSystem>> create(SharedPtr<Device> host_device);
|
|
|
|
|
|
|
|
dev_t host_device_id() const override
|
|
|
|
{
|
|
|
|
return m_host_device_id;
|
|
|
|
}
|
|
|
|
|
2023-06-22 19:41:35 +02:00
|
|
|
Result<SharedPtr<VFS::Inode>> find_inode_by_number(ino_t inode, bool initialize_dir_now = false);
|
2023-06-21 21:32:28 +02:00
|
|
|
Result<const BlockGroupDescriptor*> find_block_group_descriptor(u32 index);
|
2023-06-20 21:39:22 +02:00
|
|
|
|
|
|
|
virtual ~FileSystem() = default;
|
|
|
|
|
|
|
|
private:
|
|
|
|
FileSystem();
|
|
|
|
|
|
|
|
SharedPtr<VFS::Inode> m_root_inode;
|
|
|
|
|
|
|
|
SharedPtr<Device> m_host_device;
|
|
|
|
dev_t m_host_device_id;
|
|
|
|
|
|
|
|
Superblock m_superblock;
|
|
|
|
|
2023-06-21 21:32:28 +02:00
|
|
|
u64 m_block_size;
|
|
|
|
u64 m_block_groups;
|
|
|
|
|
2023-06-22 19:41:35 +02:00
|
|
|
u32 m_inode_size { 128 };
|
|
|
|
|
|
|
|
bool m_dirs_have_type_field { false };
|
|
|
|
bool m_uses_extended_size { false };
|
|
|
|
|
2023-06-20 21:39:22 +02:00
|
|
|
// 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<ino_t, SharedPtr<VFS::Inode>> m_inode_cache;
|
2023-06-21 21:32:28 +02:00
|
|
|
|
|
|
|
HashMap<u32, BlockGroupDescriptor> m_block_group_descriptor_cache;
|
2023-06-22 16:34:22 +02:00
|
|
|
|
|
|
|
friend class Inode;
|
2023-06-20 21:39:22 +02:00
|
|
|
};
|
|
|
|
}
|