Edit

thodg/ext4fs/include/ext4fs.h

Branch :

  • include/ext4fs.h
  • /* kc3
     * Copyright 2025 kmx.io <contact@kmx.io>
     *
     * Permission is hereby granted to use this software granted the above
     * copyright notice and this permission paragraph are included in all
     * copies and substantial portions of this software.
     *
     * THIS SOFTWARE IS PROVIDED "AS-IS" WITHOUT ANY GUARANTEE OF
     * PURPOSE AND PERFORMANCE. IN NO EVENT WHATSOEVER SHALL THE
     * AUTHOR BE CONSIDERED LIABLE FOR THE USE AND PERFORMANCE OF
     * THIS SOFTWARE.
     */
    #ifndef EXT4FS_H
    #define EXT4FS_H
    
    #include <stddef.h>
    #include <stdint.h>
    #include <time.h>
    
    typedef struct {
      uint32_t value;
      const char *name;
    } s_enum;
    
    #define EXT4FS_REV_DYNAMIC 1
    #define EXT4FS_REV_MINOR 0
    #define EXT4FS_LABEL_MAX 16
    #define EXT4FS_LAST_MOUNTED_MAX 64
    #define EXT4FS_MAGIC 0xEF53
    #define EXT4FS_SUPER_BLOCK_OFFSET 1024
    #define EXT4FS_SUPER_BLOCK_SIZE 1024
    #define EXT4FS_VALID_FS 1
    
    #define EXT4FS_ERRORS_CONTINUE  1  // Log and keep going
    #define EXT4FS_ERRORS_RO        2  // Remount read-only
    #define EXT4FS_ERRORS_PANIC     3  // Kernel panic
    
    extern const char *ext4fs_errors_str[];
    
    #define EXT4FS_FEATURE_COMPAT_DIR_PREALLOC   0x0001
    #define EXT4FS_FEATURE_COMPAT_IMAGIC_INODES  0x0002
    #define EXT4FS_FEATURE_COMPAT_HAS_JOURNAL    0x0004
    #define EXT4FS_FEATURE_COMPAT_EXT_ATTR       0x0008
    #define EXT4FS_FEATURE_COMPAT_RESIZE_INODE   0x0010
    #define EXT4FS_FEATURE_COMPAT_DIR_INDEX      0x0020
    
    extern const s_enum ext4fs_feature_compat_enum[];
    
    #define EXT4FS_FEATURE_INCOMPAT_COMPRESSION  0x00001 // Not used in ext4
    #define EXT4FS_FEATURE_INCOMPAT_FILETYPE     0x00002 // Directory entry has type
    #define EXT4FS_FEATURE_INCOMPAT_RECOVER      0x00004 // Needs journal replay
    #define EXT4FS_FEATURE_INCOMPAT_JOURNAL_DEV  0x00008 // External journal device
    #define EXT4FS_FEATURE_INCOMPAT_META_BG      0x00010 // Meta block groups
    #define EXT4FS_FEATURE_INCOMPAT_EXTENTS      0x00040 // Extents instead of block map
    #define EXT4FS_FEATURE_INCOMPAT_64BIT        0x00080 // 64-bit block numbers
    #define EXT4FS_FEATURE_INCOMPAT_MMP          0x00100 // Multiple mount protection
    #define EXT4FS_FEATURE_INCOMPAT_FLEX_BG      0x00200 // Flexible block groups
    #define EXT4FS_FEATURE_INCOMPAT_EA_INODE     0x00400 // In-inode xattrs
    #define EXT4FS_FEATURE_INCOMPAT_DIRDATA      0x01000 // Inline dir data
    #define EXT4FS_FEATURE_INCOMPAT_CSUM_SEED    0x02000 // Metadata checksum seed
    #define EXT4FS_FEATURE_INCOMPAT_LARGEDIR     0x04000 // Large dir support
    #define EXT4FS_FEATURE_INCOMPAT_INLINE_DATA  0x08000 // Inline file data
    #define EXT4FS_FEATURE_INCOMPAT_ENCRYPT      0x10000 // File encryption
    
    extern const s_enum ext4fs_feature_incompat_enum[];
    
    #define EXT4FS_FEATURE_RO_COMPAT_SPARSE_SUPER   0x0001
    #define EXT4FS_FEATURE_RO_COMPAT_LARGE_FILE     0x0002
    #define EXT4FS_FEATURE_RO_COMPAT_BTREE_DIR      0x0004  // Not used in ext4
    #define EXT4FS_FEATURE_RO_COMPAT_HUGE_FILE      0x0008
    #define EXT4FS_FEATURE_RO_COMPAT_GDT_CSUM       0x0010
    #define EXT4FS_FEATURE_RO_COMPAT_DIR_NLINK      0x0020
    #define EXT4FS_FEATURE_RO_COMPAT_EXTRA_ISIZE    0x0040
    #define EXT4FS_FEATURE_RO_COMPAT_HAS_SNAPSHOT   0x0080  // Unused
    #define EXT4FS_FEATURE_RO_COMPAT_QUOTA          0x0100
    #define EXT4FS_FEATURE_RO_COMPAT_BIGALLOC       0x0200
    #define EXT4FS_FEATURE_RO_COMPAT_METADATA_CSUM  0x0400
    #define EXT4FS_FEATURE_RO_COMPAT_REPLICA        0x0800  // Unused
    #define EXT4FS_FEATURE_RO_COMPAT_READONLY       0x1000
    #define EXT4FS_FEATURE_RO_COMPAT_PROJECT        0x2000
    
    extern const s_enum ext4fs_feature_ro_compat_enum[];
    
    #define EXT4FS_MOUNT_READONLY              0x0001
    #define EXT4FS_MOUNT_NO_ATIME              0x0002
    #define EXT4FS_MOUNT_DIRSYNC               0x0004
    #define EXT4FS_MOUNT_DATA_JOURNAL          0x0008
    #define EXT4FS_MOUNT_DATA_ORDERED          0x0010
    #define EXT4FS_MOUNT_DATA_WRITEBACK        0x0020
    #define EXT4FS_MOUNT_ERRORS_CONTINUE       0x0040
    #define EXT4FS_MOUNT_ERRORS_REMOUNT_RO     0x0080
    #define EXT4FS_MOUNT_ERRORS_PANIC          0x0100
    #define EXT4FS_MOUNT_DISCARD               0x0200
    #define EXT4FS_MOUNT_NO_BUFFER_HEADS       0x0400
    #define EXT4FS_MOUNT_SKIP_JOURNAL          0x0800
    #define EXT4FS_MOUNT_NOAUTO_DELAYED_ALLOC  0x1000
    
    extern const s_enum ext4fs_mount_enum[];
    
    #define EXT4FS_OS_LINUX     0
    #define EXT4FS_OS_HURD      1
    #define EXT4FS_OS_MASIX     2
    #define EXT4FS_OS_FREEBSD   3
    #define EXT4FS_OS_LITES     4
    #define EXT4FS_OS_OPENBSD   5
    
    extern const char *ext4fs_os_str[];
    
    #define EXT4FS_STATE_VALID  0x0001  // Clean unmount
    #define EXT4FS_STATE_ERROR  0x0002  // Errors detected (fsck needed)
    
    extern const s_enum ext4fs_state_enum[];
    
    struct ext4fs_super_block {
      uint32_t sb_inodes_count;
      uint32_t sb_blocks_count_lo;
      uint32_t sb_reserved_blocks_count_lo;
      uint32_t sb_free_blocks_count_lo;
    
      uint32_t sb_free_inodes_count;
      uint32_t sb_first_data_block;
      uint32_t sb_log_block_size;       // log2(block size) - 10
      uint32_t sb_log_cluster_size;     // log2(cluster size) - 10
    
      uint32_t sb_blocks_per_group;
      uint32_t sb_clusters_per_group;
      uint32_t sb_inodes_per_group;
      uint32_t sb_mount_time;
    
      uint32_t sb_write_time;
      uint16_t sb_mount_count;
      int16_t  sb_max_mount_count_before_fsck;
      uint16_t sb_magic;
      uint16_t sb_state;                // EXT4FS_STATE_*
      uint16_t sb_errors;               // EXT4FS_ERRORS_*
      uint16_t sb_revision_level_minor;
    
      uint32_t sb_check_time;
      uint32_t sb_check_interval;
      uint32_t sb_creator_os;           // EXT4FS_OS_*
      uint32_t sb_revision_level;
    
      uint16_t sb_default_reserved_uid;
      uint16_t sb_default_reserved_gid;
    
      uint32_t sb_first_non_reserved_inode;
      uint16_t sb_inode_size;
      uint16_t sb_block_group_id;
      uint32_t sb_feature_compat;
    
      uint32_t sb_feature_incompat;
      uint32_t sb_feature_ro_compat;
      uint8_t  sb_uuid[16];
      char     sb_volume_name[EXT4FS_LABEL_MAX];
      char     sb_last_mounted[EXT4FS_LAST_MOUNTED_MAX];
      uint32_t sb_algorithm_usage_bitmap;
      uint8_t  sb_preallocate_blocks;
      uint8_t  sb_preallocate_dir_blocks;
      uint16_t sb_reserved_gdt_blocks;  // Per group desc for online growth
    
      uint8_t  sb_journal_uuid[16];     // UUID of journal superblock
    
      uint32_t sb_journal_inode_number;
      uint32_t sb_journal_device_number;
      uint32_t sb_last_orphan;
      uint32_t sb_hash_seed[4];
      uint8_t  sb_default_hash_version;
      uint8_t  sb_journal_backup_type;
      uint16_t sb_group_descriptor_size;
    
      uint32_t sb_default_mount_opts;
      uint32_t sb_first_meta_block_group;
      uint32_t sb_newfs_time;
      uint32_t sb_jnl_blocks[17];       // Backup of journal inode
    
      uint32_t sb_blocks_count_hi;
      uint32_t sb_reserved_blocks_count_hi;
      uint32_t sb_free_blocks_count_hi;
      uint16_t sb_min_extra_isize;
      uint16_t sb_want_extra_isize;
    
      uint32_t sb_flags;
      uint16_t sb_raid_stride;
      uint16_t sb_mmp_interval;
      uint64_t sb_mmp_block;
      
      uint32_t sb_raid_stripe_width;
      uint8_t  sb_log_groups_per_flex;
      uint8_t  sb_checksum_type;
      uint16_t sb_reserved_pad;
      uint64_t sb_kbytes_written;
    
      uint32_t sb_snapshot_inum;
      uint32_t sb_snapshot_id;  
      uint64_t sb_snapshot_r_blocks_count;
    
      uint32_t sb_snapshot_list;
      uint32_t sb_error_count;
      uint32_t sb_first_error_time;
      uint32_t sb_first_error_ino;
    
      uint64_t sb_first_error_block;
      uint8_t  sb_first_error_func[32];
      uint32_t sb_first_error_line;
      uint32_t sb_last_error_time;
      uint32_t sb_last_error_ino;
      uint32_t sb_last_error_line;
      uint64_t sb_last_error_block;
      uint8_t  sb_last_error_func[32];
    
      uint8_t  sb_mount_opts[64];
      uint32_t sb_usr_quota_inum;
      uint32_t sb_grp_quota_inum;
      uint32_t sb_overhead_blocks;
      uint32_t sb_backup_bgs[2];
      uint8_t  sb_encrypt_algos[4];
      uint8_t  sb_encrypt_pw_salt[16];
      uint32_t sb_lpf_ino;
      uint32_t sb_prj_quota_inum;
      uint32_t sb_checksum_seed;
    
      uint8_t  sb_wtime_hi;
      uint8_t  sb_mtime_hi;
      uint8_t  sb_mkfs_time_hi;
      uint8_t  sb_lastcheck_hi;
      uint8_t  sb_first_error_time_hi;
      uint8_t  sb_last_error_time_hi;
      uint8_t  sb_pad[2];
      uint32_t sb_reserved[96];
    
      uint32_t sb_checksum;             // Superblock checksum
    } __attribute__((packed));
    
    struct ext4fs_group_desc {
        uint32_t gd_block_bitmap_lo;   // Block ID of block bitmap
        uint32_t gd_inode_bitmap_lo;   // Block ID of inode bitmap
        uint32_t gd_inode_table_lo;    // Starting block of inode table
        uint16_t gd_free_blocks_count; // Free blocks in this group
        uint16_t gd_free_inodes_count; // Free inodes in this group
        uint16_t gd_used_dirs_count;   // Number of directories in this group
        uint16_t gd_flags;
        uint32_t gd_exclude_bitmap_lo; // Optional (sparse allocation)
        uint16_t gd_block_bitmap_csum;
        uint16_t gd_inode_bitmap_csum;
        uint16_t gd_itable_unused;
        uint16_t gd_checksum;
        uint32_t gd_block_bitmap_hi;
        uint32_t gd_inode_bitmap_hi;
        uint32_t gd_inode_table_hi;
        uint16_t gd_free_blocks_count_hi;
        uint16_t gd_free_inodes_count_hi;
        uint16_t gd_used_dirs_count_hi;
        uint16_t gd_itable_unused_hi;
        uint32_t gd_exclude_bitmap_hi;
        uint16_t gd_block_bitmap_csum_hi;
        uint16_t gd_inode_bitmap_csum_hi;
        uint32_t gd_reserved;
    } __attribute__((packed));
    
    int ext4fs_block_bitmap (const struct ext4fs_super_block *sb,
                             const struct ext4fs_group_desc *gd,
                             uint64_t *dest);
    
    int ext4fs_block_size (const struct ext4fs_super_block *sb,
                           uint32_t *dest);
    
    int ext4fs_blocks_count (const struct ext4fs_super_block *sb,
                             uint64_t *dest);
    
    int ext4fs_free_blocks_count (const struct ext4fs_super_block *sb,
                                  uint64_t *dest);
    
    struct ext4fs_group_desc *
    ext4fs_group_desc_read (struct ext4fs_group_desc *gd,
                            int fd,
                            const struct ext4fs_super_block *sb);
    
    int ext4fs_inode_bitmap (const struct ext4fs_super_block *sb,
                             const struct ext4fs_group_desc *gd,
                             uint64_t *dest);
    
    int ext4fs_inode_table (const struct ext4fs_super_block *sb,
                            const struct ext4fs_group_desc *gd,
                            uint64_t *dest);
    
    int ext4fs_inspect (int fd);
    
    void ext4fs_inspect_creator_os (uint16_t creator_os);
    
    int ext4fs_inspect_enum (uint32_t x, const s_enum *enum_desc);
    
    void ext4fs_inspect_errors (uint16_t errors);
    
    int ext4fs_inspect_group_desc (const struct ext4fs_super_block *sb,
                                   const struct ext4fs_group_desc *gd);
    
    int ext4fs_inspect_super_block (const struct ext4fs_super_block *sb);
    
    int ext4fs_reserved_blocks_count (const struct ext4fs_super_block *sb,
                                      uint64_t *dest);
    
    int ext4fs_size (int fd, uint64_t *dest);
    
    struct ext4fs_super_block *
    ext4fs_super_block_read (struct ext4fs_super_block *sb,
                             int fd);
    
    int ext4fs_time_to_str (time_t time, char *str, size_t size);
    
    #endif /* EXT4FS_H */