"""
Extension 2 (ext2)
Used in Linux systems
"""
from construct import *

Char = SLInt8
UChar = ULInt8
Short = SLInt16
UShort = ULInt16
Long = SLInt32
ULong = ULInt32


def BlockPointer(name):
    return Struct(name,
                  ULong("block_number"),
                  OnDemandPointer(lambda ctx: ctx["block_number"]),
                  )


superblock = Struct("superblock",
                    ULong('inodes_count'),
                    ULong('blocks_count'),
                    ULong('reserved_blocks_count'),
                    ULong('free_blocks_count'),
                    ULong('free_inodes_count'),
                    ULong('first_data_block'),
                    Enum(ULong('log_block_size'),
                         OneKB=0,
                         TwoKB=1,
                         FourKB=2,
                         ),
                    Long('log_frag_size'),
                    ULong('blocks_per_group'),
                    ULong('frags_per_group'),
                    ULong('inodes_per_group'),
                    ULong('mtime'),
                    ULong('wtime'),
                    UShort('mnt_count'),
                    Short('max_mnt_count'),
                    Const(UShort('magic'), 0xEF53),
                    UShort('state'),
                    UShort('errors'),
                    Padding(2),
                    ULong('lastcheck'),
                    ULong('checkinterval'),
                    ULong('creator_os'),
                    ULong('rev_level'),
                    Padding(235 * 4),
                    )

group_descriptor = Struct("group_descriptor",
                          ULong('block_bitmap'),
                          ULong('inode_bitmap'),
                          ULong('inode_table'),
                          UShort('free_blocks_count'),
                          UShort('free_inodes_count'),
                          UShort('used_dirs_count'),
                          Padding(14),
                          )

inode = Struct("inode",
               FlagsEnum(UShort('mode'),
                         IXOTH=0x0001,
                         IWOTH=0x0002,
                         IROTH=0x0004,
                         IRWXO=0x0007,
                         IXGRP=0x0008,
                         IWGRP=0x0010,
                         IRGRP=0x0020,
                         IRWXG=0x0038,
                         IXUSR=0x0040,
                         IWUSR=0x0080,
                         IRUSR=0x0100,
                         IRWXU=0x01C0,
                         ISVTX=0x0200,
                         ISGID=0x0400,
                         ISUID=0x0800,
                         IFIFO=0x1000,
                         IFCHR=0x2000,
                         IFDIR=0x4000,
                         IFBLK=0x6000,
                         IFREG=0x8000,
                         IFLNK=0xC000,
                         IFSOCK=0xA000,
                         IFMT=0xF000,
                         ),
               UShort('uid'),
               ULong('size'),
               ULong('atime'),
               ULong('ctime'),
               ULong('mtime'),
               ULong('dtime'),
               UShort('gid'),
               UShort('links_count'),
               ULong('blocks'),
               FlagsEnum(ULong('flags'),
                         SecureDelete=0x0001,
                         AllowUndelete=0x0002,
                         Compressed=0x0004,
                         Synchronous=0x0008,
                         ),
               Padding(4),
               Array(12, ULong('blocks')),
               ULong("indirect1_block"),
               ULong("indirect2_block"),
               ULong("indirect3_block"),
               ULong('version'),
               ULong('file_acl'),
               ULong('dir_acl'),
               ULong('faddr'),
               UChar('frag'),
               Byte('fsize'),
               Padding(10),
               )

# special inodes
EXT2_BAD_INO = 1
EXT2_ROOT_INO = 2
EXT2_ACL_IDX_INO = 3
EXT2_ACL_DATA_INO = 4
EXT2_BOOT_LOADER_INO = 5
EXT2_UNDEL_DIR_INO = 6
EXT2_FIRST_INO = 11

directory_record = Struct("directory_entry",
                          ULong("inode"),
                          UShort("rec_length"),
                          UShort("name_length"),
                          Field("name", lambda ctx: ctx["name_length"]),
                          Padding(lambda ctx: ctx["rec_length"] - ctx["name_length"])
                          )

if __name__ == "__main__":
    print(superblock.sizeof())
