// File: /workspace/github_c_makefile_star2_O0/JavieW[P]CSCC69_Ext2_File-System/readimage.c
// Function: main
int main(int argc, char **argv) {

    if(argc != 2) {
        fprintf(stderr, "Usage: readimg <image file name>\n");
        exit(1);
    }
    int fd = open(argv[1], O_RDWR);

    disk = mmap(NULL, 128 * 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(disk == MAP_FAILED) {
	perror("mmap");
	exit(1);
    }

    struct ext2_super_block *sb = getSuperblock();
    printf("Inodes: %d\n", sb->s_inodes_count);
    printf("Blocks: %d\n", sb->s_blocks_count);

    struct ext2_group_desc *gd = getGroupDesc();
    printf("Block group:\n");
    printf("\tblock bitmap: %d\n", gd->bg_block_bitmap);
    printf("\tinode bitmap: %d\n", gd->bg_inode_bitmap);
    printf("\tinode table: %d\n", gd->bg_inode_table);
    printf("\tfree blocks: %d\n", gd->bg_free_blocks_count);
    printf("\tfree inodes: %d\n", gd->bg_free_inodes_count);
    printf("\tused_dirs: %d\n", gd->bg_used_dirs_count);

    // task1, print bitmap
    int i,j;
    char unsigned *block_bitmap = getBitmap(BLOCK_BITMAP);
    char unsigned *inode_bitmap = getBitmap(INODE_BITMAP);
    printf("Block bitmap:");
    for (i=0; i<sb->s_blocks_count/8; i++) {
        printf(" ");
        for (j=0; j<8; j++) {
            printf("%d", ((block_bitmap[i]>>j)&1));
        }
    }
    printf("\nInode bitmap:");
    for (i=0; i<sb->s_inodes_count/8; i++) {
        printf(" ");
        for (j=0; j<8; j++) {
            printf("%d", ((inode_bitmap[i]>>j)&1));
        }
    }
    printf("\n\n");

    // task2, print inode
    struct ext2_inode *inodeTable = getInodeTable();
    char mode='\0';
    printf("Inodes:\n");
    for(i = 0; i < sb->s_inodes_count; i++) 
    {
        // print root inode and used unreserved inodes
        if ((getBit(inode_bitmap, i)==1 && i>=EXT2_GOOD_OLD_FIRST_INO) || (i==EXT2_ROOT_INO-1))
        {
            // skip the inodes that don't reserve blocks
            if (inodeTable[i].i_block[0] == 0)
                continue;

            // print out the following info about the inode 
            if (inodeTable[i].i_mode & EXT2_S_IFDIR)
                mode = 'd';
            else if (inodeTable[i].i_mode & EXT2_S_IFREG)
                mode = 'f';
            else if (inodeTable[i].i_mode & EXT2_S_IFLNK)
                mode = 'l';
            printf("[%d] type: %c size: %d links: %d blocks: %d\n", i+1, mode, inodeTable[i].i_size, inodeTable[i].i_links_count, inodeTable[i].i_blocks);
            printf("[%d] Blocks: %d\n", i+1, inodeTable[i].i_block[0]);
        }
    }
    printf("\n");

    // task3, print directory enties
    char type='\0';
    struct ext2_dir_entry_2 *dir_entry;
    int total_rec_len;
    printf("Directory Blocks:\n");
    for(i = 0; i < sb->s_inodes_count; i++) 
    {
        // print root inode and used unreserved inodes
        if ((getBit(inode_bitmap, i)==1 && i>=EXT2_GOOD_OLD_FIRST_INO) || (i==EXT2_ROOT_INO-1))
        {
            // skip the inodes that not belong to a directory
            if (!(inodeTable[i].i_mode & EXT2_S_IFDIR))
                continue;
            
            for (int j=0; j<12; j++) {
                if (inodeTable[i].i_block[j] == 0) continue;
                printf("\tDIR BLOCK NUM: %d (for inode %d)\n", inodeTable[i].i_block[j], i+1);
                dir_entry = (struct ext2_dir_entry_2 *)getBlock(inodeTable[i].i_block[j]);
                
                // while not hit the end of the block
                total_rec_len = 0;
                while (total_rec_len < EXT2_BLOCK_SIZE) { 
                    if (dir_entry->file_type == EXT2_FT_UNKNOWN)
                        type = 'u';
                    else if (dir_entry->file_type == EXT2_FT_REG_FILE)
                        type = 'f';
                    else if (dir_entry->file_type == EXT2_FT_DIR)
                        type = 'd';
                    else if (dir_entry->file_type == EXT2_FT_SYMLINK)
                        type = 'l';
                    if (dir_entry->name_len != 0)
                        printf("Inode: %d rec_len: %d name_len: %d type= %c name=%s\n", dir_entry->inode, dir_entry->rec_len, dir_entry->name_len, type, dir_entry->name);
                    total_rec_len = total_rec_len + dir_entry->rec_len;
                    dir_entry = (void *) dir_entry + dir_entry->rec_len;
                }
            }   
        }
    }



    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x2, -0x8(%rbp)
je 0x123e
movq 0x3dd5(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x1dd7(%rip), %rsi      # 0x3004
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x10f0
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movl $0x2, %esi
movb $0x0, %al
callq 0x10c0
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x20000, %esi          # imm = 0x20000
movl $0x3, %edx
movl $0x1, %ecx
movq %r9, %rdi
callq 0x1050
movq %rax, 0x3e1c(%rip)      # 0x5098
movq $-0x1, %rax
cmpq %rax, 0x3e0e(%rip)      # 0x5098
jne 0x12a2
leaq 0x1d93(%rip), %rdi      # 0x3026
callq 0x10d0
movl $0x1, %edi
callq 0x10f0
callq 0x17d0
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %esi
leaq 0x1d73(%rip), %rdi      # 0x302b
movb $0x0, %al
callq 0x1060
movq -0x20(%rbp), %rax
movl 0x4(%rax), %esi
leaq 0x1e44(%rip), %rdi      # 0x3111
movb $0x0, %al
callq 0x1060
callq 0x17f0
movq %rax, -0x28(%rbp)
leaq 0x1d53(%rip), %rdi      # 0x3037
movb $0x0, %al
callq 0x1060
movq -0x28(%rbp), %rax
movl (%rax), %esi
leaq 0x1d4d(%rip), %rdi      # 0x3045
movb $0x0, %al
callq 0x1060
movq -0x28(%rbp), %rax
movl 0x4(%rax), %esi
leaq 0x1d4b(%rip), %rdi      # 0x3058
movb $0x0, %al
callq 0x1060
movq -0x28(%rbp), %rax
movl 0x8(%rax), %esi
leaq 0x1d49(%rip), %rdi      # 0x306b
movb $0x0, %al
callq 0x1060
movq -0x28(%rbp), %rax
movzwl 0xc(%rax), %esi
leaq 0x1d45(%rip), %rdi      # 0x307d
movb $0x0, %al
callq 0x1060
movq -0x28(%rbp), %rax
movzwl 0xe(%rax), %esi
leaq 0x1d41(%rip), %rdi      # 0x308f
movb $0x0, %al
callq 0x1060
movq -0x28(%rbp), %rax
movzwl 0x10(%rax), %esi
leaq 0x1d3d(%rip), %rdi      # 0x30a1
movb $0x0, %al
callq 0x1060
xorl %edi, %edi
callq 0x1810
movq %rax, -0x38(%rbp)
movl $0x1, %edi
callq 0x1810
movq %rax, -0x40(%rbp)
leaq 0x1d26(%rip), %rdi      # 0x30b1
movb $0x0, %al
callq 0x1060
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movq -0x20(%rbp), %rcx
movl 0x4(%rcx), %ecx
shrl $0x3, %ecx
cmpl %ecx, %eax
jae 0x13ff
leaq 0x1d0e(%rip), %rdi      # 0x30bf
movb $0x0, %al
callq 0x1060
movl $0x0, -0x30(%rbp)
cmpl $0x8, -0x30(%rbp)
jge 0x13f2
movq -0x38(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movzbl (%rax,%rcx), %esi
movl -0x30(%rbp), %ecx
sarl %cl, %esi
andl $0x1, %esi
leaq 0x1ce1(%rip), %rdi      # 0x30c1
movb $0x0, %al
callq 0x1060
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x13bf
jmp 0x13f4
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x1399
leaq 0x1cbe(%rip), %rdi      # 0x30c4
movb $0x0, %al
callq 0x1060
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movq -0x20(%rbp), %rcx
movl (%rcx), %ecx
shrl $0x3, %ecx
cmpl %ecx, %eax
jae 0x1479
leaq 0x1c94(%rip), %rdi      # 0x30bf
movb $0x0, %al
callq 0x1060
movl $0x0, -0x30(%rbp)
cmpl $0x8, -0x30(%rbp)
jge 0x146c
movq -0x40(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movzbl (%rax,%rcx), %esi
movl -0x30(%rbp), %ecx
sarl %cl, %esi
andl $0x1, %esi
leaq 0x1c67(%rip), %rdi      # 0x30c1
movb $0x0, %al
callq 0x1060
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x1439
jmp 0x146e
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x1414
leaq 0x1c53(%rip), %rdi      # 0x30d3
movb $0x0, %al
callq 0x1060
callq 0x1a70
movq %rax, -0x48(%rbp)
movb $0x0, -0x49(%rbp)
leaq 0x1c3b(%rip), %rdi      # 0x30d6
movb $0x0, %al
callq 0x1060
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl (%rcx), %eax
jae 0x15e2
movq -0x40(%rbp), %rdi
movl -0x2c(%rbp), %esi
callq 0x1890
cmpl $0x1, %eax
jne 0x14cf
cmpl $0xb, -0x2c(%rbp)
jge 0x14d9
cmpl $0x1, -0x2c(%rbp)
jne 0x15d2
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
cmpl $0x0, 0x28(%rax)
jne 0x14f3
jmp 0x15d4
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movzwl (%rax), %eax
andl $0x4000, %eax           # imm = 0x4000
cmpl $0x0, %eax
je 0x1515
movb $0x64, -0x49(%rbp)
jmp 0x155b
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movzwl (%rax), %eax
andl $0x8000, %eax           # imm = 0x8000
cmpl $0x0, %eax
je 0x1537
movb $0x66, -0x49(%rbp)
jmp 0x1559
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movzwl (%rax), %eax
andl $0xa000, %eax           # imm = 0xA000
cmpl $0x0, %eax
je 0x1557
movb $0x6c, -0x49(%rbp)
jmp 0x1559
jmp 0x155b
movl -0x2c(%rbp), %esi
addl $0x1, %esi
movsbl -0x49(%rbp), %edx
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movl 0x4(%rax), %ecx
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rdi
shlq $0x7, %rdi
addq %rdi, %rax
movzwl 0x1a(%rax), %r8d
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rdi
shlq $0x7, %rdi
addq %rdi, %rax
movl 0x1c(%rax), %r9d
leaq 0x1b3a(%rip), %rdi      # 0x30df
movb $0x0, %al
callq 0x1060
movl -0x2c(%rbp), %esi
addl $0x1, %esi
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movl 0x28(%rax), %edx
leaq 0x1b41(%rip), %rdi      # 0x310c
movb $0x0, %al
callq 0x1060
jmp 0x15d4
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x14a9
leaq 0x1aeb(%rip), %rdi      # 0x30d4
movb $0x0, %al
callq 0x1060
movb $0x0, -0x4a(%rbp)
leaq 0x1b22(%rip), %rdi      # 0x311d
movb $0x0, %al
callq 0x1060
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movq -0x20(%rbp), %rcx
cmpl (%rcx), %eax
jae 0x17c4
movq -0x40(%rbp), %rdi
movl -0x2c(%rbp), %esi
callq 0x1890
cmpl $0x1, %eax
jne 0x162f
cmpl $0xb, -0x2c(%rbp)
jge 0x1639
cmpl $0x1, -0x2c(%rbp)
jne 0x17b4
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movzwl (%rax), %eax
andl $0x4000, %eax           # imm = 0x4000
cmpl $0x0, %eax
jne 0x165a
jmp 0x17b6
movl $0x0, -0x60(%rbp)
cmpl $0xc, -0x60(%rbp)
jge 0x17b2
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movslq -0x60(%rbp), %rcx
cmpl $0x0, 0x28(%rax,%rcx,4)
jne 0x168a
jmp 0x17a4
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movslq -0x60(%rbp), %rcx
movl 0x28(%rax,%rcx,4), %esi
movl -0x2c(%rbp), %edx
addl $0x1, %edx
leaq 0x1a82(%rip), %rdi      # 0x3130
movb $0x0, %al
callq 0x1060
movq -0x48(%rbp), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movslq -0x60(%rbp), %rcx
movl 0x28(%rax,%rcx,4), %edi
callq 0x1d60
movq %rax, -0x58(%rbp)
movl $0x0, -0x5c(%rbp)
cmpl $0x400, -0x5c(%rbp)     # imm = 0x400
jge 0x17a2
movq -0x58(%rbp), %rax
movzbl 0x7(%rax), %eax
cmpl $0x0, %eax
jne 0x16fc
movb $0x75, -0x4a(%rbp)
jmp 0x1739
movq -0x58(%rbp), %rax
movzbl 0x7(%rax), %eax
cmpl $0x1, %eax
jne 0x170f
movb $0x66, -0x4a(%rbp)
jmp 0x1737
movq -0x58(%rbp), %rax
movzbl 0x7(%rax), %eax
cmpl $0x2, %eax
jne 0x1722
movb $0x64, -0x4a(%rbp)
jmp 0x1735
movq -0x58(%rbp), %rax
movzbl 0x7(%rax), %eax
cmpl $0x7, %eax
jne 0x1733
movb $0x6c, -0x4a(%rbp)
jmp 0x1735
jmp 0x1737
jmp 0x1739
movq -0x58(%rbp), %rax
movzbl 0x6(%rax), %eax
cmpl $0x0, %eax
je 0x1777
movq -0x58(%rbp), %rax
movl (%rax), %esi
movq -0x58(%rbp), %rax
movzwl 0x4(%rax), %edx
movq -0x58(%rbp), %rax
movzbl 0x6(%rax), %ecx
movsbl -0x4a(%rbp), %r8d
movq -0x58(%rbp), %r9
addq $0x8, %r9
leaq 0x19e3(%rip), %rdi      # 0x3153
movb $0x0, %al
callq 0x1060
movl -0x5c(%rbp), %eax
movq -0x58(%rbp), %rcx
movzwl 0x4(%rcx), %ecx
addl %ecx, %eax
movl %eax, -0x5c(%rbp)
movq -0x58(%rbp), %rax
movq -0x58(%rbp), %rcx
movzwl 0x4(%rcx), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
jmp 0x16dc
jmp 0x17a4
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x1661
jmp 0x17b4
jmp 0x17b6
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x1609
xorl %eax, %eax
addq $0x60, %rsp
popq %rbp
retq
nopl (%rax)