// File: /workspace/github_c_makefile_star2_O1/Carben-dev[P]ext2fs-simple-utilities/ext2_utils.c
// Function: add_to_dir_entry
void add_to_dir_entry(struct ext2_inode *parent_inode,
                      unsigned int inode_num,
                      char *name,
                      unsigned char type)
{
    int parent_inode_last_block_index = (parent_inode->i_blocks / 2) - 1;
    unsigned char *parent_inode_data = disk + EXT2_BLOCK_SIZE * parent_inode->i_block[parent_inode_last_block_index];
    
    // Find out the last entry
    int curr_entry_off = 0;
    struct ext2_dir_entry *entry;
    while (1) {
        entry = (struct ext2_dir_entry *)(parent_inode_data + curr_entry_off);
        if (entry->rec_len + curr_entry_off == EXT2_BLOCK_SIZE) {
            
            //handle case: no space for last entry
            if (entry->rec_len - sizeof(struct ext2_dir_entry) - entry->name_len < sizeof(struct ext2_dir_entry) + strlen(name)) {
                // allocate new block on datablock
                int new_block_number = dalloc();
                if (new_block_number < 0) {
                    exit(ENOSPC);
                }
                
                // add this block back to parent inode
                parent_inode->i_block[parent_inode_last_block_index + 1] = new_block_number;
                parent_inode->i_blocks += 2;
                
                // add entry in this block
                entry = (struct ext2_dir_entry *)(disk + EXT2_BLOCK_SIZE * new_block_number);
                // Build entry in parent for new dir
                entry->file_type    = type;
                entry->inode        = inode_num;
                entry->name_len     = strlen(name);
                entry->rec_len      = EXT2_BLOCK_SIZE;
                memcpy(entry->name, name, entry->name_len);
                // align name, padding null char to the end of entry->name
                int padding_len = 4 - (entry->name_len % 4);
                memset(entry->name + entry->name_len, '\0', padding_len);
                
                // Update link count for self
                struct ext2_inode *self_inode = inode_table + (inode_num - 1);
                self_inode->i_links_count++;
                return;
            }
            
            
            break;
        }
        curr_entry_off += entry->rec_len;
    }
    
    // Update the last entry's rec_len
    int last_entry_len = sizeof(struct ext2_dir_entry) + entry->name_len;
    if (last_entry_len % 4) {   // align
        last_entry_len += 4 - (last_entry_len % 4);
    }
    entry->rec_len = last_entry_len;
    
    // Move to next
    curr_entry_off += entry->rec_len;
    entry = (struct ext2_dir_entry *)(parent_inode_data + curr_entry_off);
    
    // Build entry in parent for new dir
    entry->file_type    = type;
    entry->inode        = inode_num;
    entry->name_len     = strlen(name);
    entry->rec_len      = EXT2_BLOCK_SIZE - curr_entry_off;
    memcpy(entry->name, name, entry->name_len);
    // align name, padding null char to the end of entry->name
    int padding_len = 4 - (entry->name_len % 4);
    memset(entry->name + entry->name_len, '\0', padding_len);
    
    // Update link count for self
    struct ext2_inode *self_inode = inode_table + (inode_num - 1);
    self_inode->i_links_count++;
    
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %ecx, 0x4(%rsp)
movq %rsi, 0x10(%rsp)
movq %rdi, %r15
movl 0x1c(%rdi), %r13d
shrl %r13d
movl %r13d, %eax
decl %eax
leaq 0x37ad(%rip), %rcx      # 0x50b0
cltq
movl 0x28(%rdi,%rax,4), %ebp
shll $0xa, %ebp
addq (%rcx), %rbp
xorl %eax, %eax
movl %eax, %r12d
movzwl 0x4(%rbp,%r12), %ebx
addl %ebx, %eax
cmpl $0x400, %eax            # imm = 0x400
jne 0x1911
movzbl 0x6(%rbp,%r12), %r14d
subq %r14, %rbx
addq $-0x8, %rbx
movq %rdx, %rdi
movq %rdx, 0x8(%rsp)
callq 0x1070
addq $0x8, %rax
cmpq %rax, %rbx
jae 0x19d1
movq 0x8(%rsp), %rbp
callq 0x1815
testl %eax, %eax
js 0x1a7f
movl %eax, 0x28(%r15,%r13,4)
addl $0x2, 0x1c(%r15)
leaq 0x3743(%rip), %rcx      # 0x50b0
movq (%rcx), %rcx
shll $0xa, %eax
leaq (%rcx,%rax), %rbx
leaq (%rcx,%rax), %r15
addq $0x8, %r15
movl 0x4(%rsp), %eax
movb %al, -0x1(%r15)
movq 0x10(%rsp), %r14
movl %r14d, -0x8(%r15)
movq %rbp, %rdi
callq 0x1070
movq %rax, %r12
movb %r12b, -0x2(%r15)
movw $0x400, -0x4(%r15)      # imm = 0x400
movzbl %r12b, %r13d
movq %r15, %rdi
movq %rbp, %rsi
movq %r13, %rdx
callq 0x10c0
andl $0x3, %r12d
movl $0x4, %edx
subq %r12, %rdx
leaq (%rbx,%r13), %rdi
addq $0x8, %rdi
jmp 0x1a52
leal 0x8(%r14), %eax
movl %r14d, %ebx
andl $-0x4, %ebx
addl $0xc, %ebx
testb $0x3, %r14b
cmovel %eax, %ebx
movw %bx, 0x4(%rbp,%r12)
addq %r12, %rbx
leaq (%rbx,%rbp), %r15
addq $0x8, %r15
addq %rbx, %rbp
movl 0x4(%rsp), %eax
movb %al, -0x1(%r15)
movq 0x10(%rsp), %r14
movl %r14d, -0x8(%r15)
movq 0x8(%rsp), %rdi
callq 0x1070
movq %rax, %r12
movb %r12b, -0x2(%r15)
movl $0x400, %eax            # imm = 0x400
subl %ebx, %eax
movw %ax, -0x4(%r15)
movzbl %r12b, %r13d
movq %r15, %rdi
movq 0x8(%rsp), %rsi
movq %r13, %rdx
callq 0x10c0
andl $0x3, %r12d
movl $0x4, %edx
subq %r12, %rdx
leaq 0x8(,%rbp), %rdi
addq %r13, %rdi
xorl %esi, %esi
callq 0x10b0
leaq 0x3658(%rip), %rax      # 0x50b8
movq (%rax), %rax
decl %r14d
shlq $0x7, %r14
incw 0x1a(%rax,%r14)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x1c, %edi
callq 0x1110