// File: /workspace/github_c_makefile_star2_O2/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 0x1389
movq 0x8(%rsi), %rdi
pushq $0x2
popq %rsi
xorl %eax, %eax
callq 0x10f0
pushq $0x3
popq %rdx
pushq $0x1
popq %rbx
movl $0x20000, %esi          # imm = 0x20000
xorl %edi, %edi
movl %ebx, %ecx
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x1080
movq %rax, 0x3e45(%rip)      # 0x50b0
cmpq $-0x1, %rax
je 0x13a7
callq 0x13bc
callq 0x1f70
movl %eax, %ebp
callq 0x1fb3
movl %eax, %r14d
movl %eax, %r15d
movq 0x3e25(%rip), %rax      # 0x50b8
movl 0xc(%rax), %ecx
cmpl %r14d, %ecx
jne 0x129f
xorl %ebx, %ebx
jmp 0x12c7
movl %r14d, %edx
subl %ecx, %edx
negl %edx
movl %r14d, %esi
subl %ecx, %esi
cmovbl %edx, %esi
movl %r15d, 0xc(%rax)
leaq 0x1d6a(%rip), %rdi      # 0x3023
xorl %eax, %eax
callq 0x10a0
movq 0x3df1(%rip), %rax      # 0x50b8
movl 0x10(%rax), %ecx
cmpl %ebp, %ecx
je 0x12ee
movl %ebp, %edx
subl %ecx, %edx
negl %edx
movl %ebp, %esi
subl %ecx, %esi
cmovbl %edx, %esi
incl %ebx
movl %ebp, 0x10(%rax)
leaq 0x1d8a(%rip), %rdi      # 0x3071
xorl %eax, %eax
callq 0x10a0
movq 0x3dcb(%rip), %rax      # 0x50c0
movzwl 0xc(%rax), %ecx
subl %ecx, %r14d
je 0x1323
movl %r14d, %esi
negl %esi
cmovsl %r14d, %esi
movw %r15w, 0xc(%rax)
incl %ebx
leaq 0x1daa(%rip), %rdi      # 0x30bf
xorl %eax, %eax
callq 0x10a0
movq 0x3d9d(%rip), %rax      # 0x50c0
movzwl 0xe(%rax), %edx
movl %ebp, %ecx
subl %edx, %ecx
je 0x1348
movl %ecx, %esi
negl %esi
cmovsl %ecx, %esi
movw %bp, 0xe(%rax)
incl %ebx
leaq 0x1dcd(%rip), %rdi      # 0x310e
xorl %eax, %eax
callq 0x10a0
leaq 0x7(%rsp), %rdx
movb $0x2, (%rdx)
pushq $0x2
popq %rdi
movl %edi, %esi
callq 0x21b0
addl %ebx, %eax
je 0x1370
leaq 0x1df8(%rip), %rdi      # 0x315d
movl %eax, %esi
xorl %eax, %eax
callq 0x10a0
jmp 0x137c
leaq 0x1e10(%rip), %rdi      # 0x3187
callq 0x1060
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq 0x3c68(%rip), %rax      # 0x4ff8
movq (%rax), %rcx
leaq 0x1c6a(%rip), %rdi      # 0x3004
pushq $0x19
popq %rsi
pushq $0x1
popq %rdx
callq 0x1120
jmp 0x13b3
leaq 0x1c70(%rip), %rdi      # 0x301e
callq 0x1100
pushq $0x1
popq %rdi
callq 0x1110
nop