From 69f3cc6b883437048f62a9d08098e3375fdb83cd Mon Sep 17 00:00:00 2001 From: Enrico Fraccaroli Date: Tue, 14 Dec 2021 01:51:48 +0100 Subject: [PATCH] Add more EXT2 data structures. --- mentos/src/fs/ext2.c | 187 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 171 insertions(+), 16 deletions(-) diff --git a/mentos/src/fs/ext2.c b/mentos/src/fs/ext2.c index b30c479..eb32100 100644 --- a/mentos/src/fs/ext2.c +++ b/mentos/src/fs/ext2.c @@ -22,6 +22,10 @@ #include "stdio.h" #include "fcntl.h" +#define EXT2_SUPERBLOCK_MAGIC 0xEF53 +#define EXT2_INDIRECT_BLOCKS 12 +#define EXT2_NAME_LEN 255 + /// @brief The superblock contains all the information about the configuration /// of the filesystem. /// @details The primary copy of the superblock is stored at an offset of 1024 @@ -29,61 +33,211 @@ /// filesystem. Since it is so important, backup copies of the superblock are /// stored in block groups throughout the filesystem. typedef struct ext2_superblock_t { + /// @brief Total number of inodes in file system. uint32_t inodes_count; + /// @brief Total number of blocks in file system uint32_t blocks_count; + /// @brief Number of blocks reserved for superuser. uint32_t r_blocks_count; + /// @brief Total number of unallocated blocks. uint32_t free_blocks_count; + /// @brief Total number of unallocated inodes. uint32_t free_inodes_count; + /// @brief Block number of the block containing the superblock. uint32_t first_data_block; + /// @brief The number to shift 1024 to the left by to obtain the block size + /// (log2 (block size) - 10). uint32_t log_block_size; + /// @brief The number to shift 1,024 to the left by to obtain the fragment + /// size (log2 (fragment size) - 10). uint32_t log_frag_size; + /// @brief Number of blocks in each block group. uint32_t blocks_per_group; + /// @brief Number of fragments in each block group. uint32_t frags_per_group; + /// @brief Number of inodes in each block group. uint32_t inodes_per_group; + /// @brief Last mount time (in POSIX time). uint32_t mtime; + /// @brief Last written time (in POSIX time). uint32_t wtime; + /// @brief Number of times the volume has been mounted since its last + /// consistency check (fsck). uint16_t mnt_count; + /// @brief Number of mounts allowed before a consistency check (fsck) must + /// be done. uint16_t max_mnt_count; + /// @brief Ext2 signature (0xef53), used to help confirm the presence of + /// Ext2 on a volume. uint16_t magic; + /// @brief File system state. uint16_t state; + /// @brief What to do when an error is detected. uint16_t errors; + /// @brief Minor portion of version (combine with Major portion below to + /// construct full version field). uint16_t minor_rev_level; + /// @brief POSIX time of last consistency check (fsck). uint32_t lastcheck; + /// @brief Interval (in POSIX time) between forced consistency checks + /// (fsck). uint32_t checkinterval; + /// @brief Operating system ID from which the filesystem on this volume was + /// created. uint32_t creator_os; + /// @brief Major portion of version (combine with Minor portion above to + /// construct full version field). uint32_t rev_level; + /// @brief User ID that can use reserved blocks. uint16_t def_resuid; + /// @brief Group ID that can use reserved blocks. uint16_t def_resgid; - // EXT2_DYNAMIC_REV + + // == Extended Superblock Fields ========================================== + /// @brief First non-reserved inode in file system. (In versions < 1.0, this + /// is fixed as 11) uint32_t first_ino; + /// @brief Size of each inode structure in bytes. (In versions < 1.0, this + /// is fixed as 128) uint16_t inode_size; + /// @brief Block group that this superblock is part of (if backup copy). uint16_t block_group_nr; + /// @brief Optional features present (features that are not required to read + /// or write, but usually result in a performance increase). uint32_t feature_compat; + /// @brief Required features present (features that are required to be + /// supported to read or write) uint32_t feature_incompat; + /// @brief Features that if not supported, the volume must be mounted + /// read-only). uint32_t feature_ro_compat; + /// @brief File system ID (what is output by blkid). uint8_t uuid[16]; + /// @brief Volume name (C-style string: characters terminated by a 0 byte). uint8_t volume_name[16]; + /// @brief Path volume was last mounted to (C-style string: characters + /// terminated by a 0 byte). uint8_t last_mounted[64]; + /// @brief Compression algorithms used. uint32_t algo_bitmap; - // Performance Hints + + // == Performance Hints =================================================== + /// @brief Number of blocks to preallocate for files. uint8_t prealloc_blocks; + /// @brief Number of blocks to preallocate for directories. uint8_t prealloc_dir_blocks; - uint16_t _padding; - // Journaling Support + /// @brief (Unused) + uint16_t padding0; + + // == Journaling Support ================================================== + /// @brief Journal ID uint8_t journal_uuid[16]; + /// @brief Inode number of journal file. uint32_t journal_inum; + /// @brief Device number of journal file. uint32_t jounral_dev; + /// @brief Start of list of inodes to delete. uint32_t last_orphan; - // Directory Indexing Support + + // == Directory Indexing Support ========================================== + /// @brief HTree hash seed. uint32_t hash_seed[4]; + /// @brief Ddefault hash version to use. uint8_t def_hash_version; - uint16_t _padding_a; - uint8_t _padding_b; - // Other Options + /// @brief Padding. + uint16_t padding1; + /// @brief Padding. + uint8_t padding2; + + // == Other Options ======================================================= + /// @brief The default mount options for the file system. uint32_t default_mount_options; - uint32_t first_meta_bg; - uint8_t _unused[760]; -} __attribute__((packed)) ext2_superblock_t; + /// @brief The ID of the first meta block group. + uint32_t first_meta_block_group_id; + /// @brief Reserved. + uint8_t reserved[760]; +} ext2_superblock_t; + +/// @brief +typedef struct ext2_group_descriptor_t { + /// @brief The block number of the block bitmap for this Block Group + uint32_t block_bitmap; + /// @brief The block number of the inode allocation bitmap for this Block Group. + uint32_t inode_bitmap; + /// @brief The block number of the starting block for the inode table for this Block Group. + uint32_t inode_table; + /// @brief Number of free blocks. + uint16_t free_blocks_count; + /// @brief Number of free inodes. + uint16_t free_inodes_count; + /// @brief Number of used directories. + uint16_t used_dirs_count; + /// @brief Padding. + uint16_t pad; + /// @brief Reserved. + uint32_t reserved[3]; +} ext2_group_descriptor_t; + +/// @brief The ext2 inode. +typedef struct ext2_inode_t { + /// @brief File mode + uint16_t mode; + /// @brief The user identifiers of the owners. + uint16_t uid; + /// @brief The size of the file in bytes. + uint32_t size; + /// @brief The time that the inode was accessed. + uint32_t atime; + /// @brief The time that the inode was created. + uint32_t ctime; + /// @brief The time that the inode was modified the last time. + uint32_t mtime; + /// @brief The time that the inode was deleted. + uint32_t dtime; + /// @brief The group identifiers of the owners. + uint16_t gid; + /// @brief Number of hard links. + uint16_t links_count; + /// @brief Blocks count. + uint32_t blocks_count; + /// @brief File flags. + uint32_t flags; + /// @brief OS dependant value. + uint32_t osd1; + union { + struct datablocks { + uint32_t dir_blocks[EXT2_INDIRECT_BLOCKS]; + uint32_t indir_block; + uint32_t double_indir_block; + uint32_t triple_indir_block; + } blocks; + char symlink[60]; + } data; + /// @brief Value used to indicate the file version (used by NFS). + uint32_t generation; + /// @brief Value indicating the block number containing the extended attributes. + uint32_t file_acl; + /// @brief For regular files this 32bit value contains the high 32 bits of the 64bit file size. + uint32_t dir_acl; + /// @brief Value indicating the location of the file fragment. + uint32_t fragment_addr; + /// @brief OS dependant structure. + uint32_t osd2[3]; +} ext2_inode_t; + +/// @brief The header of an ext2 directory entry. +typedef struct ext2_dirent_t { + /// @brief Inode number. + uint32_t inode; + /// @brief Directory entry length + uint16_t direntlen; + /// @brief Name length + uint8_t namelen; + /// @brief File type. + uint8_t filetype; + /// @brief File name. + char name[EXT2_NAME_LEN]; +} ext2_dirent_t; static const char *uuid_to_string(uint8_t uuid[16]) { @@ -119,7 +273,7 @@ static void ext2_dump_superblock(ext2_superblock_t *sb) pr_debug("wtime : %s\n", time_to_string(sb->wtime)); pr_debug("mnt_count : %d\n", sb->mnt_count); pr_debug("max_mnt_count : %d\n", sb->max_mnt_count); - pr_debug("magic : %d\n", sb->magic); + pr_debug("magic : 0x%0x\n", sb->magic); pr_debug("state : %d\n", sb->state); pr_debug("errors : %d\n", sb->errors); pr_debug("minor_rev_level : %d\n", sb->minor_rev_level); @@ -141,17 +295,14 @@ static void ext2_dump_superblock(ext2_superblock_t *sb) pr_debug("algo_bitmap : %d\n", sb->algo_bitmap); pr_debug("prealloc_blocks : %d\n", sb->prealloc_blocks); pr_debug("prealloc_dir_blocks : %d\n", sb->prealloc_dir_blocks); - pr_debug("_padding : %d\n", sb->_padding); pr_debug("journal_uuid : %s\n", uuid_to_string(sb->journal_uuid)); pr_debug("journal_inum : %d\n", sb->journal_inum); pr_debug("jounral_dev : %d\n", sb->jounral_dev); pr_debug("last_orphan : %d\n", sb->last_orphan); pr_debug("hash_seed : %u %u %u %u\n", sb->hash_seed[0], sb->hash_seed[1], sb->hash_seed[2], sb->hash_seed[3]); pr_debug("def_hash_version : %d\n", sb->def_hash_version); - pr_debug("_padding_a : %d\n", sb->_padding_a); - pr_debug("_padding_b : %d\n", sb->_padding_b); pr_debug("default_mount_options : %d\n", sb->default_mount_options); - pr_debug("first_meta_bg : %d\n", sb->first_meta_bg); + pr_debug("first_meta_bg : %d\n", sb->first_meta_block_group_id); } static vfs_file_t *ext2_mount_callback(const char *path, const char *device) @@ -165,6 +316,10 @@ static vfs_file_t *ext2_mount_callback(const char *path, const char *device) pr_err("Failed to read the superblock table at 1024.\n"); return NULL; } + if (sb.magic != EXT2_SUPERBLOCK_MAGIC) { + pr_err("Wrong magic number, it is not an EXT2 filesystem.\n"); + return NULL; + } ext2_dump_superblock(&sb); } return NULL;