// File: /workspace/github_c_makefile_star2_O3/Carben-dev[P]ext2fs-simple-utilities/ext2_checker.c
// Function: main
int main(int argc, const char * argv[]) {
    if(argc != 2) {
        fprintf(stderr, "Usage: <image file name>\n");
        exit(1);
    }
    int fd = open(argv[1], O_RDWR);
    
    // map disk img into memory
    disk = mmap(NULL, 128 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(disk == MAP_FAILED) {
        perror("mmap");
        exit(1);
    }
    
    // Init utils
    ext2_utils_init();
    
    // varible
    int num_fixed = 0;
    
    // check free inode and block count in sb and gdt
    // always trust bitmap
    // output certain message
    int free_inode_count = count_inode_bitmap();
    int free_block_count = count_block_bitmap();
    
    if (sb->s_free_blocks_count != free_block_count) {
        int s_blocks_off;
        if (sb->s_free_blocks_count > free_block_count) {
            s_blocks_off = sb->s_free_blocks_count - free_block_count;
        } else {
            s_blocks_off = free_block_count - sb->s_free_blocks_count;
        }
        sb->s_free_blocks_count = free_block_count;
        num_fixed++;
        printf("Fixed: superblock's free blocks counter was off by %d compared to the bitmap\n", s_blocks_off);
    }
    
    if (sb->s_free_inodes_count != free_inode_count) {
        int s_inodes_off;
        if (sb->s_free_inodes_count > free_inode_count) {
            s_inodes_off = sb->s_free_inodes_count - free_inode_count;
        } else {
            s_inodes_off = free_inode_count - sb->s_free_inodes_count;
        }
        num_fixed++;
        sb->s_free_inodes_count = free_inode_count;
        printf("Fixed: superblock's free inodes counter was off by %d compared to the bitmap\n", s_inodes_off);
    }
    
    if (gdt->bg_free_blocks_count != free_block_count) {
        int bg_blocks_off;
        if (gdt->bg_free_blocks_count > free_block_count) {
            bg_blocks_off = gdt->bg_free_blocks_count - free_block_count;
        } else {
            bg_blocks_off = free_block_count - gdt->bg_free_blocks_count;
        }
        gdt->bg_free_blocks_count = free_block_count;
        num_fixed++;
        printf("Fixed: block group's free blocks counter was off by %d compared to the bitmap\n", bg_blocks_off);
    }
    
    if (gdt->bg_free_inodes_count != free_inode_count) {
        int bg_inodes_off;
        if (gdt->bg_free_inodes_count > free_inode_count) {
            bg_inodes_off = gdt->bg_free_inodes_count - free_inode_count;
        } else {
            bg_inodes_off = free_inode_count - gdt->bg_free_inodes_count;
        }
        gdt->bg_free_inodes_count = free_inode_count;
        num_fixed++;
        printf("Fixed: block group's free inodes counter was off by %d compared to the bitmap\n", bg_inodes_off);
    }
    
    
    // check if type in dir entry match i_mode in inode
    // trust inode
    // output certain message
    
    
    // check if each inode in bitmap mark as used
    // trust inode
    // output certain message
    
    // check if each inode dtime is 0
    // reset to 0 if not
    // output certain message
    
    // check if each inode datablock mark as used in bitmap
    // trust inode
    // output certain message
    
    unsigned char root_ft_type = EXT2_FT_DIR;
    num_fixed += each_checker_rec(2, 2, &root_ft_type);
    
    // output summary
    if (num_fixed) {
        printf("%d file system inconsistencies repaired!\n", num_fixed);
    } else {
        printf("No file system inconsistencies detected!\n");
    }
    
    
    return 0;
    
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
cmpl $0x2, %edi
jne 0x13d4
movq 0x8(%rsi), %rdi
xorl %r14d, %r14d
movl $0x2, %esi
xorl %eax, %eax
callq 0x10f0
movl $0x20000, %esi          # imm = 0x20000
xorl %edi, %edi
movl $0x3, %edx
movl $0x1, %ecx
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x1080
movq %rax, 0x3dfe(%rip)      # 0x50b0
cmpq $-0x1, %rax
je 0x13d9
callq 0x13e0
callq 0x2068
movl %eax, %ebx
callq 0x2145
movl %eax, %ebp
movl %eax, %r15d
movq 0x3ddf(%rip), %rax      # 0x50b8
movl 0xc(%rax), %ecx
cmpl %ebp, %ecx
je 0x130c
movl %ebp, %edx
subl %ecx, %edx
negl %edx
movl %ebp, %esi
subl %ecx, %esi
cmovbl %edx, %esi
movl %r15d, 0xc(%rax)
leaq 0x1d2b(%rip), %rdi      # 0x3023
xorl %eax, %eax
callq 0x10a0
movl $0x1, %r14d
movq 0x3dac(%rip), %rax      # 0x50b8
movl 0x10(%rax), %ecx
cmpl %ebx, %ecx
je 0x1334
movl %ebx, %edx
subl %ecx, %edx
negl %edx
movl %ebx, %esi
subl %ecx, %esi
cmovbl %edx, %esi
incl %r14d
movl %ebx, 0x10(%rax)
leaq 0x1d44(%rip), %rdi      # 0x3071
xorl %eax, %eax
callq 0x10a0
movq 0x3d85(%rip), %rax      # 0x50c0
movzwl 0xc(%rax), %ecx
subl %ecx, %ebp
je 0x1367
movl %ebp, %esi
negl %esi
cmovsl %ebp, %esi
movw %r15w, 0xc(%rax)
incl %r14d
leaq 0x1d66(%rip), %rdi      # 0x30bf
xorl %eax, %eax
callq 0x10a0
movq 0x3d59(%rip), %rax      # 0x50c0
movzwl 0xe(%rax), %edx
movl %ebx, %ecx
subl %edx, %ecx
je 0x138d
movl %ecx, %esi
negl %esi
cmovsl %ecx, %esi
movw %bx, 0xe(%rax)
incl %r14d
leaq 0x1d88(%rip), %rdi      # 0x310e
xorl %eax, %eax
callq 0x10a0
leaq 0x7(%rsp), %rdx
movb $0x2, (%rdx)
movl $0x2, %edi
movl $0x2, %esi
callq 0x23f4
addl %r14d, %eax
je 0x13bb
leaq 0x1dad(%rip), %rdi      # 0x315d
movl %eax, %esi
xorl %eax, %eax
callq 0x10a0
jmp 0x13c7
leaq 0x1dc5(%rip), %rdi      # 0x3187
callq 0x1060
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
callq 0x1140
callq 0x1165
nop