// File: /workspace/github_c_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x218, %rsp            # imm = 0x218
cmpl $0x3, %edi
jle 0x149a
movq %rsi, %r14
movb $0x1, %bl
cmpl $0x5, %edi
jne 0x1271
movq 0x10(%r14), %rcx
movzbl (%rcx), %eax
subl $0x2d, %eax
jne 0x126a
movzbl 0x1(%rcx), %ecx
pushq $0x73
popq %rax
subl %ecx, %eax
jmp 0x126c
negl %eax
testl %eax, %eax
setne %bl
movq 0x8(%r14), %rdi
pushq $0x2
popq %rsi
xorl %eax, %eax
callq 0x10f0
pushq $0x3
popq %rdx
pushq $0x1
popq %rcx
movl $0x20000, %esi          # imm = 0x20000
xorl %edi, %edi
movl %eax, %r8d
xorl %r9d, %r9d
callq 0x1080
movq %rax, 0x3e12(%rip)      # 0x50b0
cmpq $-0x1, %rax
je 0x14b8
callq 0x14d0
testb %bl, %bl
movb %bl, -0x29(%rbp)
movq %r14, -0x38(%rbp)
je 0x12cd
movq 0x10(%r14), %rdi
callq 0x1070
movq %rax, %r12
movq 0x18(%r14), %rdi
movq %rdi, %r13
jmp 0x12e0
movq 0x18(%r14), %r13
movq %r13, %rdi
callq 0x1070
movq %rax, %r12
movq 0x20(%r14), %rdi
callq 0x1070
movq %rsp, %r15
addq $0x10, %r12
andq $-0x10, %r12
subq %r12, %r15
movq %r15, %rsp
movq %rsp, %rbx
addq $0x10, %rax
andq $-0x10, %rax
subq %rax, %rbx
movq %rbx, %rsp
movq %rsp, %r14
subq %r12, %r14
movq %r14, %rsp
movq %rsp, %r12
subq %rax, %r12
movq %r12, %rsp
cmpb $0x0, -0x29(%rbp)
je 0x1331
movq -0x38(%rbp), %rax
movq 0x10(%rax), %rsi
movq %r15, %rdi
callq 0x1060
jmp 0x1344
movq %r15, %rdi
movq %r13, %rsi
callq 0x1060
movq -0x38(%rbp), %rax
movq 0x20(%rax), %r13
movq %rbx, %rdi
movq %r13, %rsi
callq 0x1060
movq %r15, %rdi
callq 0x210b
movq %rbx, %rdi
callq 0x210b
leaq -0x240(%rbp), %rdx
movq %r15, %rdi
movq %r14, %rsi
callq 0x2122
leaq -0x140(%rbp), %rdx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2122
movq %r15, %rdi
callq 0x1757
movl %eax, %r14d
movslq %eax, %r13
shlq $0x7, %r13
addq 0x3d1c(%rip), %r13      # 0x50b8
movq %r12, %rdi
callq 0x1757
testl %r14d, %r14d
js 0x13cf
movl %eax, %ebx
testl %eax, %eax
pushq $0x2
popq %rax
js 0x13d2
movq 0x3cff(%rip), %rax      # 0x50b8
movq %rax, -0x38(%rbp)
movl %ebx, %edi
movq %r12, %rsi
callq 0x153f
testl %eax, %eax
jle 0x13e1
pushq $0x11
jmp 0x13d1
pushq $0x2
popq %rax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movslq %ebx, %rax
shlq $0x7, %rax
movq -0x38(%rbp), %rcx
leaq (%rcx,%rax), %rbx
addq $-0x80, %rbx
cmpb $0x0, -0x29(%rbp)
je 0x1433
movzwl -0x80(%r13), %eax
btl $0xe, %eax
jb 0x1493
movl %eax, %edx
notl %edx
movb $0x7, %cl
testw $0xa000, %dx            # imm = 0xA000
je 0x1421
movb $0x1, %cl
testw %ax, %ax
jns 0x14cc
movzbl %cl, %ecx
leaq -0x140(%rbp), %rdx
movq %rbx, %rdi
movl %r14d, %esi
jmp 0x1487
movq %r15, %rdi
callq 0x1070
leal 0x1(%rax), %esi
movl $0xa000, %edi           # imm = 0xA000
callq 0x2266
movq 0x3c69(%rip), %rcx      # 0x50b8
movslq %eax, %r14
movq %r14, %rax
shlq $0x7, %rax
leaq (%rcx,%rax), %r12
addq $-0x80, %r12
movq %r15, %rdi
callq 0x1070
leal 0x1(%rax), %edx
movq %r12, %rdi
movq %r15, %rsi
callq 0x2196
leaq -0x140(%rbp), %rdx
pushq $0x7
popq %rcx
movq %rbx, %rdi
movl %r14d, %esi
callq 0x1998
xorl %eax, %eax
jmp 0x13d2
pushq $0x15
jmp 0x13d1
movq 0x3b57(%rip), %rax      # 0x4ff8
movq (%rax), %rcx
leaq 0x1b59(%rip), %rdi      # 0x3004
pushq $0x2f
popq %rsi
pushq $0x1
popq %rdx
callq 0x1120
jmp 0x14c4
leaq 0x1b75(%rip), %rdi      # 0x3034
callq 0x1100
pushq $0x1
popq %rdi
callq 0x1110
pushq $-0x1
jmp 0x14c6