// File: /workspace/github_c_makefile_star2_O0/Carben-dev[P]ext2fs-simple-utilities/ext2_ln.c
// Function: main
int main(int argc, const char * argv[]) {
    // if -s flag set, this will be set to 1
    int create_symlink = 0;
    
    if(argc < 4) {
        fprintf(stderr, "Usage: <image file name> <-s flag> <src> <dst>\n");
        exit(1);
    }
    
    if (argc == 5 && strncmp("-s", argv[2], strlen("-s")) == 0) {
        create_symlink = 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();
    
    // find out max path len
    unsigned long src_path_len;
    unsigned long lnk_path_len;
    if (create_symlink) {
        src_path_len = strlen(argv[3]) + 1;
        lnk_path_len = strlen(argv[4]) + 1;
    } else {
        src_path_len = strlen(argv[2]) + 1;
        lnk_path_len = strlen(argv[3]) + 1;
    }
    
    //
    char src_path[src_path_len];
    char lnk_path[lnk_path_len];
    char src_parent_path[src_path_len];
    char src_file_name[EXT2_NAME_LEN];
    char lnk_parent_path[lnk_path_len];
    char lnk_file_name[EXT2_NAME_LEN];
    
    if (create_symlink) {
        strcpy(src_path, argv[3]);
        strcpy(lnk_path, argv[4]);
    } else {
        strcpy(src_path, argv[2]);
        strcpy(lnk_path, argv[3]);
    }
    
    clear_end_slash(src_path);
    clear_end_slash(lnk_path);
    
    cut_path(src_path, src_parent_path, src_file_name);
    cut_path(lnk_path, lnk_parent_path, lnk_file_name);
    
    int src_file_inode_num = get_inode_number_by_path(src_path);
    struct ext2_inode *src_file_inode = inode_table + (src_file_inode_num - 1);
    int lnk_parent_inode_num = get_inode_number_by_path(lnk_parent_path);
    struct ext2_inode *lnk_parent_inode = inode_table + (lnk_parent_inode_num - 1);
    
    // check if src path exist
    if (src_file_inode_num < 0) {
        return ENOENT;
    }
    
    // check if lnk parent exist
    if (lnk_parent_inode_num < 0) {
        return ENOENT;
    }
    
    
    // check if lnk already exist
    if (get_inode_number_by_name(lnk_parent_inode_num, lnk_parent_path) > 0) {
        return EEXIST;
    }
    
    if (create_symlink) { // create soft link
        // allocate space in inode_table for soft link
        int soft_link_inode_num = new_inode(EXT2_S_IFLNK, strlen(src_path)+1);
        struct ext2_inode *soft_link_inode = inode_table + (soft_link_inode_num - 1);
        
        // copy src_path to datablock
        copy_to_inode_datablock(soft_link_inode, (unsigned char *)src_path, strlen(src_path)+1);
        
        // add soft link inode to lnk_parent
        add_to_dir_entry(lnk_parent_inode, soft_link_inode_num, lnk_file_name, EXT2_FT_SYMLINK);
        return 0;
        
    } else { // create hard link
        // check if src is a dir
        if (src_file_inode->i_mode & EXT2_S_IFDIR) {
            return EISDIR;
        }
        
        unsigned char type;
        
        // check file type
        if ((src_file_inode->i_mode & EXT2_S_IFLNK) == EXT2_S_IFLNK) {
            type = EXT2_FT_SYMLINK;
        } else if (src_file_inode->i_mode & EXT2_S_IFREG) {
            type = EXT2_FT_REG_FILE;
        } else {
            exit(-1);
        }
        
        add_to_dir_entry(lnk_parent_inode, src_file_inode_num, lnk_file_name, type);
        return 0;
    }
    
    
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2c0, %rsp            # imm = 0x2C0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
cmpl $0x4, -0x8(%rbp)
jge 0x1278
movq 0x4d9b(%rip), %rax      # 0x5ff8
movq (%rax), %rdi
leaq 0x2d9d(%rip), %rsi      # 0x4004
movb $0x0, %al
callq 0x10c0
movl $0x1, %edi
callq 0x1120
cmpl $0x5, -0x8(%rbp)
jne 0x12a3
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
leaq 0x2da7(%rip), %rdi      # 0x4034
movl $0x2, %edx
callq 0x1050
cmpl $0x0, %eax
jne 0x12a3
movl $0x1, -0x14(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movl $0x2, %esi
movb $0x0, %al
callq 0x1100
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x20000, %esi          # imm = 0x20000
movl $0x3, %edx
movl $0x1, %ecx
movq %r9, %rdi
callq 0x1080
movq %rax, 0x4dcf(%rip)      # 0x60b0
movq $-0x1, %rax
cmpq %rax, 0x4dc1(%rip)      # 0x60b0
jne 0x1307
leaq 0x2d3f(%rip), %rdi      # 0x4037
callq 0x1110
movl $0x1, %edi
callq 0x1120
callq 0x16e0
cmpl $0x0, -0x14(%rbp)
je 0x133e
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x1070
addq $0x1, %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x1070
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x1368
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x1070
addq $0x1, %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x1070
addq $0x1, %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movq %rsp, %rcx
movq %rcx, -0x30(%rbp)
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x2b8(%rbp)
movq %rcx, %rsp
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x2b0(%rbp)
movq %rcx, %rsp
movq %rax, -0x40(%rbp)
movq -0x20(%rbp), %rax
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x2a8(%rbp)
movq %rcx, %rsp
movq %rax, -0x48(%rbp)
movq -0x28(%rbp), %rax
movq %rax, %rdx
addq $0xf, %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x2a0(%rbp)
movq %rcx, %rsp
movq %rax, -0x158(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x142e
movq -0x2b8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x1060
movq -0x2b0(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rsi
callq 0x1060
jmp 0x1456
movq -0x2b8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
callq 0x1060
movq -0x2b0(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rsi
callq 0x1060
movq -0x2b8(%rbp), %rdi
callq 0x2df0
movq -0x2b0(%rbp), %rdi
callq 0x2df0
movq -0x2a8(%rbp), %rsi
movq -0x2b8(%rbp), %rdi
leaq -0x150(%rbp), %rdx
callq 0x2e50
movq -0x2b0(%rbp), %rdi
movq -0x2a0(%rbp), %rsi
leaq -0x260(%rbp), %rdx
callq 0x2e50
movq -0x2b8(%rbp), %rdi
callq 0x1b80
movq -0x2a0(%rbp), %rdi
movl %eax, -0x264(%rbp)
movq 0x4bf6(%rip), %rax      # 0x60b8
movl -0x264(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x270(%rbp)
callq 0x1b80
movl %eax, -0x274(%rbp)
movq 0x4bca(%rip), %rax      # 0x60b8
movl -0x274(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x280(%rbp)
cmpl $0x0, -0x264(%rbp)
jge 0x1527
movl $0x2, -0x4(%rbp)
movl $0x1, -0x284(%rbp)
jmp 0x16c7
cmpl $0x0, -0x274(%rbp)
jge 0x1546
movl $0x2, -0x4(%rbp)
movl $0x1, -0x284(%rbp)
jmp 0x16c7
movq -0x2a0(%rbp), %rsi
movl -0x274(%rbp), %edi
callq 0x17a0
cmpl $0x0, %eax
jle 0x1573
movl $0x11, -0x4(%rbp)
movl $0x1, -0x284(%rbp)
jmp 0x16c7
cmpl $0x0, -0x14(%rbp)
je 0x1627
movq -0x2b8(%rbp), %rdi
callq 0x1070
addq $0x1, %rax
movl %eax, %esi
movl $0xa000, %edi           # imm = 0xA000
callq 0x3040
movq -0x2b8(%rbp), %rdi
movl %eax, -0x288(%rbp)
movq 0x4b0b(%rip), %rax      # 0x60b8
movl -0x288(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x290(%rbp)
movq -0x290(%rbp), %rax
movq %rax, -0x2c0(%rbp)
callq 0x1070
movq -0x2c0(%rbp), %rdi
movq -0x2b8(%rbp), %rsi
addq $0x1, %rax
movl %eax, %edx
callq 0x2f10
movq -0x280(%rbp), %rdi
movl -0x288(%rbp), %esi
leaq -0x260(%rbp), %rdx
movl $0x7, %ecx
callq 0x2070
movl $0x0, -0x4(%rbp)
movl $0x1, -0x284(%rbp)
jmp 0x16c7
movq -0x270(%rbp), %rax
movzwl (%rax), %eax
andl $0x4000, %eax           # imm = 0x4000
cmpl $0x0, %eax
je 0x164e
movl $0x15, -0x4(%rbp)
movl $0x1, -0x284(%rbp)
jmp 0x16c7
movq -0x270(%rbp), %rax
movzwl (%rax), %eax
andl $0xa000, %eax           # imm = 0xA000
cmpl $0xa000, %eax           # imm = 0xA000
jne 0x166d
movb $0x7, -0x291(%rbp)
jmp 0x1696
movq -0x270(%rbp), %rax
movzwl (%rax), %eax
andl $0x8000, %eax           # imm = 0x8000
cmpl $0x0, %eax
je 0x168a
movb $0x1, -0x291(%rbp)
jmp 0x1694
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x1120
jmp 0x1696
movq -0x280(%rbp), %rdi
movl -0x264(%rbp), %esi
leaq -0x260(%rbp), %rdx
movzbl -0x291(%rbp), %ecx
callq 0x2070
movl $0x0, -0x4(%rbp)
movl $0x1, -0x284(%rbp)
movq -0x30(%rbp), %rax
movq %rax, %rsp
movl -0x4(%rbp), %eax
movq %rbp, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)