// File: /workspace/github_c_makefile_star2_O0/JavieW[P]CSCC69_Ext2_File-System/utilities.c
// Function: rm
void rm(struct ext2_inode *parentInode, char *childFileName) {
    struct ext2_dir_entry_2 *pre_dir_entry = NULL;
    struct ext2_dir_entry_2 *cur_dir_entry = NULL;
    struct ext2_dir_entry_2 *child_dir_entry = NULL;
    struct ext2_inode *childInode = NULL;
    int total_rec_len;
    
    // delete childFile from parentDir and get childInode
    pre_dir_entry = getPreDirent(parentInode, childFileName);
    cur_dir_entry = (void *)pre_dir_entry + pre_dir_entry->rec_len;
    childInode = getInode(cur_dir_entry->inode);

    // base case1, if childInode is Symbolic link
    if (cur_dir_entry->file_type == EXT2_FT_SYMLINK)
    {
        if (childInode->i_size > 60) {
            changeBitmap(getBitmap(BLOCK_BITMAP), childInode->i_block[0]-1, 'd');
            getGroupDesc()->bg_free_blocks_count++;
        }
        changeBitmap(getBitmap(INODE_BITMAP), cur_dir_entry->inode-1, 'd');
        getGroupDesc()->bg_free_inodes_count++;
    }
    // base case2, if childInode is a file
    else if (cur_dir_entry->file_type == EXT2_FT_REG_FILE)
    {
        // if link count == 0 remove inode
        if (childInode->i_links_count == 1) {
            deleteInode(cur_dir_entry->inode);
        } else {
            childInode->i_links_count--;
        }
    }
    // recursive case, if childInode is a dir
    else if (cur_dir_entry->file_type == EXT2_FT_DIR)
    {
        // reduce link count for self and parent (. and ..)
        childInode->i_links_count--;
        parentInode->i_links_count--;

        // for each file name (other than . and ..) in child dir, call recursion
        for (int i=0; i<12; i++) {
            if (childInode->i_block[i] == 0)
                continue;
            child_dir_entry = (struct ext2_dir_entry_2 *)getBlock(childInode->i_block[i]);
            total_rec_len = 0;
            // for each dir entry in the block
            while (total_rec_len < EXT2_BLOCK_SIZE) {
                if (child_dir_entry->name_len != 0 &&
                    strcmp(child_dir_entry->name, ".")!=0 &&
                    strcmp(child_dir_entry->name, "..")!=0) {
                    rm(childInode, child_dir_entry->name);
                }
                total_rec_len = total_rec_len + child_dir_entry->rec_len;
                child_dir_entry = (void *) child_dir_entry + child_dir_entry->rec_len;
            }
        }
        
        // if child link count == 0 remove inode
        if (childInode->i_links_count == 1) {
            deleteInode(cur_dir_entry->inode);
            getGroupDesc()->bg_used_dirs_count--;
        }
    }
    pre_dir_entry->rec_len += cur_dir_entry->rec_len;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x1e60
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movq -0x18(%rbp), %rcx
movzwl 0x4(%rcx), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %edi
callq 0x1aa0
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movzbl 0x7(%rax), %eax
cmpl $0x7, %eax
jne 0x2592
movq -0x30(%rbp), %rax
cmpl $0x3c, 0x4(%rax)
jbe 0x255c
xorl %edi, %edi
callq 0x1810
movq %rax, %rdi
movq -0x30(%rbp), %rax
movl 0x28(%rax), %esi
subl $0x1, %esi
movl $0x64, %edx
callq 0x1970
callq 0x17f0
movw 0xc(%rax), %cx
addw $0x1, %cx
movw %cx, 0xc(%rax)
movl $0x1, %edi
callq 0x1810
movq %rax, %rdi
movq -0x20(%rbp), %rax
movl (%rax), %esi
subl $0x1, %esi
movl $0x64, %edx
callq 0x1970
callq 0x17f0
movw 0xe(%rax), %cx
addw $0x1, %cx
movw %cx, 0xe(%rax)
jmp 0x2703
movq -0x20(%rbp), %rax
movzbl 0x7(%rax), %eax
cmpl $0x1, %eax
jne 0x25ce
movq -0x30(%rbp), %rax
movzwl 0x1a(%rax), %eax
cmpl $0x1, %eax
jne 0x25b9
movq -0x20(%rbp), %rax
movl (%rax), %edi
callq 0x1be0
jmp 0x25c9
movq -0x30(%rbp), %rax
movw 0x1a(%rax), %cx
addw $-0x1, %cx
movw %cx, 0x1a(%rax)
jmp 0x2701
movq -0x20(%rbp), %rax
movzbl 0x7(%rax), %eax
cmpl $0x2, %eax
jne 0x26ff
movq -0x30(%rbp), %rax
movw 0x1a(%rax), %cx
addw $-0x1, %cx
movw %cx, 0x1a(%rax)
movq -0x8(%rbp), %rax
movw 0x1a(%rax), %cx
addw $-0x1, %cx
movw %cx, 0x1a(%rax)
movl $0x0, -0x38(%rbp)
cmpl $0xc, -0x38(%rbp)
jge 0x26d4
movq -0x30(%rbp), %rax
movslq -0x38(%rbp), %rcx
cmpl $0x0, 0x28(%rax,%rcx,4)
jne 0x2624
jmp 0x26c6
movq -0x30(%rbp), %rax
movslq -0x38(%rbp), %rcx
movl 0x28(%rax,%rcx,4), %edi
callq 0x1d60
movq %rax, -0x28(%rbp)
movl $0x0, -0x34(%rbp)
cmpl $0x400, -0x34(%rbp)     # imm = 0x400
jge 0x26c4
movq -0x28(%rbp), %rax
movzbl 0x6(%rax), %eax
cmpl $0x0, %eax
je 0x2699
movq -0x28(%rbp), %rdi
addq $0x8, %rdi
leaq 0xb65(%rip), %rsi       # 0x31ca
callq 0x1090
cmpl $0x0, %eax
je 0x2699
movq -0x28(%rbp), %rdi
addq $0x8, %rdi
leaq 0xb4b(%rip), %rsi       # 0x31c9
callq 0x1090
cmpl $0x0, %eax
je 0x2699
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
addq $0x8, %rsi
callq 0x24b0
movl -0x34(%rbp), %eax
movq -0x28(%rbp), %rcx
movzwl 0x4(%rcx), %ecx
addl %ecx, %eax
movl %eax, -0x34(%rbp)
movq -0x28(%rbp), %rax
movq -0x28(%rbp), %rcx
movzwl 0x4(%rcx), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x28(%rbp)
jmp 0x2640
jmp 0x26c6
movl -0x38(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x38(%rbp)
jmp 0x2606
movq -0x30(%rbp), %rax
movzwl 0x1a(%rax), %eax
cmpl $0x1, %eax
jne 0x26fd
movq -0x20(%rbp), %rax
movl (%rax), %edi
callq 0x1be0
callq 0x17f0
movw 0x10(%rax), %cx
addw $-0x1, %cx
movw %cx, 0x10(%rax)
jmp 0x26ff
jmp 0x2701
jmp 0x2703
movq -0x20(%rbp), %rax
movzwl 0x4(%rax), %edx
movq -0x18(%rbp), %rax
movzwl 0x4(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x4(%rax)
addq $0x40, %rsp
popq %rbp
retq