/* ext2.h - Read-only ext2 filesystem driver for Pactor64 */ #ifndef _EXT2_H #define _EXT2_H #include "pactor64.h" /* ext2 magic number */ #define EXT2_SUPER_MAGIC 0xEF53 /* ext2 superblock (at byte offset 1024 from start of partition) */ typedef struct { uint32_t s_inodes_count; uint32_t s_blocks_count; uint32_t s_r_blocks_count; uint32_t s_free_blocks_count; uint32_t s_free_inodes_count; uint32_t s_first_data_block; uint32_t s_log_block_size; uint32_t s_log_frag_size; uint32_t s_blocks_per_group; uint32_t s_frags_per_group; uint32_t s_inodes_per_group; uint32_t s_mtime; uint32_t s_wtime; uint16_t s_mnt_count; uint16_t s_max_mnt_count; uint16_t s_magic; uint16_t s_state; uint16_t s_errors; uint16_t s_minor_rev_level; uint32_t s_lastcheck; uint32_t s_checkinterval; uint32_t s_creator_os; uint32_t s_rev_level; uint16_t s_def_resuid; uint16_t s_def_resgid; /* Extended fields (rev >= 1) */ uint32_t s_first_ino; uint16_t s_inode_size; uint16_t s_block_group_nr; uint32_t s_feature_compat; uint32_t s_feature_incompat; uint32_t s_feature_ro_compat; uint8_t s_uuid[16]; char s_volume_name[16]; char s_last_mounted[64]; uint32_t s_algo_usage_bitmap; } __attribute__((packed)) ext2_superblock_t; /* Block group descriptor */ typedef struct { uint32_t bg_block_bitmap; uint32_t bg_inode_bitmap; uint32_t bg_inode_table; uint16_t bg_free_blocks_count; uint16_t bg_free_inodes_count; uint16_t bg_used_dirs_count; uint16_t bg_pad; uint8_t bg_reserved[12]; } __attribute__((packed)) ext2_bgd_t; /* Inode */ typedef struct { uint16_t i_mode; uint16_t i_uid; uint32_t i_size; uint32_t i_atime; uint32_t i_ctime; uint32_t i_mtime; uint32_t i_dtime; uint16_t i_gid; uint16_t i_links_count; uint32_t i_blocks; uint32_t i_flags; uint32_t i_osd1; uint32_t i_block[15]; /* 0-11 direct, 12 indirect, 13 double, 14 triple */ uint32_t i_generation; uint32_t i_file_acl; uint32_t i_dir_acl; uint32_t i_faddr; uint8_t i_osd2[12]; } __attribute__((packed)) ext2_inode_t; /* Directory entry */ typedef struct { uint32_t inode; uint16_t rec_len; uint8_t name_len; uint8_t file_type; char name[]; } __attribute__((packed)) ext2_dirent_t; /* Directory entry file types */ #define EXT2_FT_UNKNOWN 0 #define EXT2_FT_REG_FILE 1 #define EXT2_FT_DIR 2 #define EXT2_FT_CHRDEV 3 #define EXT2_FT_BLKDEV 4 #define EXT2_FT_FIFO 5 #define EXT2_FT_SOCK 6 #define EXT2_FT_SYMLINK 7 /* Inode mode bits */ #define EXT2_S_IFREG 0x8000 #define EXT2_S_IFDIR 0x4000 #define EXT2_S_IFLNK 0xA000 /* Root inode */ #define EXT2_ROOT_INO 2 /* Maximum path component length */ #define EXT2_NAME_LEN 255 /* Block device read function type */ typedef int (*block_read_fn)(uint64_t lba, uint32_t count, void *buf); /* ext2 filesystem context */ typedef struct { block_read_fn read_block; ext2_superblock_t sb; ext2_bgd_t *bgdt; /* Block group descriptor table */ uint32_t block_size; uint32_t inodes_per_group; uint32_t inode_size; uint32_t groups_count; } ext2_fs_t; /* File handle */ typedef struct { ext2_fs_t *fs; ext2_inode_t inode; uint32_t inode_num; uint32_t size; uint32_t position; } ext2_file_t; /* Directory entry callback */ typedef void (*ext2_dirent_cb)(const char *name, uint8_t name_len, uint32_t inode, uint8_t file_type, void *ctx); /* Initialize ext2 filesystem from block device */ int ext2_init(ext2_fs_t *fs, block_read_fn read_fn); /* Open a file by path (returns 0 on success) */ int ext2_open(ext2_fs_t *fs, const char *path, ext2_file_t *file); /* Read from an open file */ int ext2_read(ext2_file_t *file, void *buf, uint32_t size); /* Close an open file */ void ext2_close(ext2_file_t *file); /* Read directory entries (callback-based) */ int ext2_readdir(ext2_fs_t *fs, uint32_t dir_inode, ext2_dirent_cb cb, void *ctx); /* Read a raw inode by number */ int ext2_read_inode(ext2_fs_t *fs, uint32_t inode_num, ext2_inode_t *inode); /* Mount ext2 from ATA disk at given partition LBA offset */ int ext2_mount(ext2_fs_t *fs, uint32_t part_lba); #endif /* _EXT2_H */