// File: /workspace/github_c_makefile_star2_O2/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, 0x8(%rsp)
movq %rdi, %r15
movl 0x1c(%rdi), %r13d
shrl %r13d
movl %r13d, %eax
decl %eax
leaq 0x386f(%rip), %rcx      # 0x50b0
cltq
movl 0x28(%rdi,%rax,4), %r12d
shll $0xa, %r12d
addq (%rcx), %r12
xorl %eax, %eax
movl %eax, %ebp
movzwl 0x4(%r12,%rbp), %ebx
addl %ebx, %eax
cmpl $0x400, %eax            # imm = 0x400
jne 0x1851
movzbl 0x6(%r12,%rbp), %r14d
subq %r14, %rbx
addq $-0x8, %rbx
movq %rdx, %rdi
movq %rdx, 0x10(%rsp)
callq 0x1070
addq $0x8, %rax
cmpq %rax, %rbx
jae 0x18de
movq 0x10(%rsp), %rbp
callq 0x1754
testl %eax, %eax
js 0x1984
movl %eax, %r12d
movl %eax, 0x28(%r15,%r13,4)
addl $0x2, 0x1c(%r15)
leaq 0x3805(%rip), %rax      # 0x50b0
movq (%rax), %rbx
shll $0xa, %r12d
leaq (%rbx,%r12), %r13
movl 0x4(%rsp), %eax
movb %al, 0x7(%rbx,%r12)
movq 0x8(%rsp), %r14
movl %r14d, (%rbx,%r12)
movq %rbp, %rdi
callq 0x1070
movq %rax, %r15
movb %r15b, 0x6(%rbx,%r12)
movw $0x400, %ax             # imm = 0x400
jmp 0x192d
leal 0x8(%r14), %eax
movl %r14d, %ebx
andl $-0x4, %ebx
addl $0xc, %ebx
testb $0x3, %r14b
cmovel %eax, %ebx
movw %bx, 0x4(%r12,%rbp)
addq %rbp, %rbx
leaq (%r12,%rbx), %r13
movl 0x4(%rsp), %eax
movb %al, 0x7(%r12,%rbx)
movq 0x8(%rsp), %r14
movl %r14d, (%r12,%rbx)
movq 0x10(%rsp), %rbp
movq %rbp, %rdi
callq 0x1070
movq %rax, %r15
movb %r15b, 0x6(%r12,%rbx)
movl $0x400, %eax            # imm = 0x400
subl %ebx, %eax
movw %ax, 0x4(%r13)
leaq 0x8(%r13), %rdi
movzbl %r15b, %r12d
movq %rbp, %rsi
movq %r12, %rdx
callq 0x10c0
andl $0x3, %r15d
pushq $0x4
popq %rdx
subq %r15, %rdx
leaq (%r12,%r13), %rdi
addq $0x8, %rdi
xorl %esi, %esi
callq 0x10b0
leaq 0x3753(%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
pushq $0x1c
popq %rdi
callq 0x1110