// File: /workspace/github_c_makefile_star2_O0/Sidd0107[P]EXT2-File-System/ext2_mkdir.c
// Function: main
int main(int argc, char **argv) {

    //Checks valid no of argument
    if(argc != 3) {
        fprintf(stderr, "Usage: ext2_mkdir <image file name> <file path on ext2 image>\n");
        exit(1);
    }
    //Gets arguments
    int fd = open(argv[1], O_RDWR);
    char *path = argv[2];
    char *dirName = extract_filename(argv[2]);
    
    //maps disk in memory and checks for error
    disk = mmap(NULL, 128 * BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(disk == MAP_FAILED) {
        perror("mmap");
        exit(1);
    }
    //gets superblock and groupd desc.
    struct ext2_super_block *sb = (struct ext2_super_block *)(disk + BLOCK_SIZE);
    struct ext2_group_desc *gd = (struct ext2_group_desc *)  (disk + 2*BLOCK_SIZE + ((sb -> s_block_group_nr) *  sizeof(struct ext2_group_desc)));
    // Checks if file already exists and returns if yes.
	char *directory = strrchr(argv[2], '/');
	directory[(argv[2] == directory)? 1:0] = '\0';
    if(file_exists(path, get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), dirName)!=0){
        fprintf(stderr, "mkdir: file exists\n");
        return EEXIST;
    }
    //CHECK FOR INODE TO RESERVE
    int free_inode;
    if((free_inode = find_first_free_bit(get_block(disk, gd -> bg_inode_bitmap, BLOCK_SIZE), 0, 128)) == -1){
        fprintf(stderr, "mkdir: operation failed: No free inodes");
        exit(1);
    }
    unsigned int dirname_length = strlen(dirName);
    unsigned int dir_entry_size = (8 + dirname_length) + (4 - (8 + dirname_length) % 4) % 4;
    //Creates new directory entry
    struct ext2_dir_entry_2  * new_dir = malloc(dir_entry_size);
	if(!new_dir){
		perror("malloc");
		exit(1);
	}
    new_dir -> inode = free_inode + 1;
    new_dir -> name_len = strlen(dirName);
    new_dir -> rec_len = dir_entry_size;
    new_dir -> file_type = EXT2_FT_DIR;
    memcpy(new_dir -> name, dirName, strlen(dirName));
    int new_capacity = gd -> bg_free_blocks_count;
    
    //Getting info to check that destination is a directory and not reserved
    struct basic_fileinfo destination = find_file(argv[2], get_block(disk, gd -> bg_inode_table, BLOCK_SIZE));
    if(destination.inode < 11 && destination.inode != 2){
        fprintf(stderr, "Invalid destination");
        free(new_dir);
        return ENOENT;
    }//Checks if destination is a directory
    if(destination.type != 'd'){
        fprintf(stderr, "mkdir: destination is not a directory");
        free(new_dir);
        return ENOENT;
   }//Checks if directory has space for the new directory
	if(new_capacity < 1){
		fprintf(stderr, "mkdir: not enough capacity");
		return ENOSPC;
	}
    //Reserves location for new directory entry
    if ((new_capacity = reserve_directory_entry(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), destination.inode, new_capacity, new_dir, get_block(disk, gd -> bg_block_bitmap, BLOCK_SIZE))) == -1){
        fprintf(stderr, "mkdir: Not enough capacity for file");
        exit(-1);
    }
    //freeing memory and reducing the free inode count
    free(new_dir);
    gd -> bg_free_inodes_count --;
    set_inode(get_inode(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), free_inode + 1),
              free_inode, 0, NULL,
              0,
              get_block(disk, gd -> bg_block_bitmap, BLOCK_SIZE),
              get_block(disk, gd -> bg_inode_bitmap, BLOCK_SIZE),
		EXT2_S_IFDIR);
    gd -> bg_free_blocks_count = new_capacity;
    printf("Success: Directory entry created.");
    //Adds . directory to the new directory entry
	new_dir = malloc(12);
	if (!new_dir){
		perror("malloc");
		exit(1);
	}
	new_dir -> inode = free_inode + 1;
	new_dir -> name_len = 1; 
	new_dir -> rec_len = 12;
	new_dir -> file_type = EXT2_FT_DIR;
	new_dir -> name[0] = '.';

	struct ext2_inode *inode = get_inode(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), free_inode + 1);
	inode -> i_block[0] = 0;
    // Adds .. to the new directory entry
	new_capacity = reserve_directory_entry(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), free_inode + 1, new_capacity, new_dir, get_block(disk, gd -> bg_block_bitmap, BLOCK_SIZE));
	new_dir -> inode = destination.inode;
	new_dir -> name_len = 2;
	new_dir -> name[0] = '.';
	new_dir -> name[1] = '.';
	reserve_directory_entry(get_block(disk, gd -> bg_inode_table, BLOCK_SIZE), free_inode + 1, new_capacity, new_dir, get_block(disk, gd -> bg_block_bitmap, BLOCK_SIZE));
	gd -> bg_free_blocks_count = new_capacity;
	gd -> bg_used_dirs_count += 3;
	free(new_dir);
	free(dirName);
	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x3, -0x8(%rbp)
je 0x23a1
movq 0x2c72(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0xcf2(%rip), %rsi       # 0x3082
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x10f0
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movl $0x2, %esi
movb $0x0, %al
callq 0x10d0
movl %eax, -0x14(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x2080
movq %rax, -0x28(%rbp)
movl -0x14(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x20000, %esi          # imm = 0x20000
movl $0x3, %edx
movl $0x1, %ecx
movq %r9, %rdi
callq 0x1070
movq %rax, 0x2c9c(%rip)      # 0x5098
movq $-0x1, %rax
cmpq %rax, 0x2c8e(%rip)      # 0x5098
jne 0x2422
leaq 0xcae(%rip), %rdi       # 0x30c1
callq 0x10e0
movl $0x1, %edi
callq 0x10f0
movq 0x2c6f(%rip), %rax      # 0x5098
addq $0x400, %rax            # imm = 0x400
movq %rax, -0x30(%rbp)
movq 0x2c5e(%rip), %rax      # 0x5098
addq $0x800, %rax            # imm = 0x800
movq -0x30(%rbp), %rcx
movzwl 0x5e(%rcx), %ecx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
movl $0x2f, %esi
callq 0x1090
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0x10(%rcx), %rsi
movq -0x40(%rbp), %rdi
xorl %ecx, %ecx
movl $0x1, %edx
cmpq %rdi, %rsi
cmovel %edx, %ecx
movslq %ecx, %rcx
movb $0x0, (%rax,%rcx)
movq -0x20(%rbp), %rax
movq %rax, -0x78(%rbp)
movq 0x2bfc(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x8(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq -0x78(%rbp), %rdi
movq %rax, %rsi
movq -0x28(%rbp), %rdx
callq 0x1370
cmpl $0x0, %eax
je 0x24e6
movq 0x2b2f(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0xbf3(%rip), %rsi       # 0x30c6
movb $0x0, %al
callq 0x10a0
movl $0x11, -0x4(%rbp)
jmp 0x2a16
movq 0x2bab(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x4(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq %rax, %rdi
xorl %esi, %esi
movl $0x80, %edx
callq 0x1b50
movl %eax, -0x44(%rbp)
cmpl $-0x1, %eax
jne 0x2537
movq 0x2adc(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0xbb4(%rip), %rsi       # 0x30da
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x10f0
movq -0x28(%rbp), %rdi
callq 0x1060
movl %eax, -0x48(%rbp)
movl -0x48(%rbp), %eax
addl $0x8, %eax
movl -0x48(%rbp), %edx
addl $0x8, %edx
andl $0x3, %edx
movl $0x4, %ecx
subl %edx, %ecx
andl $0x3, %ecx
addl %ecx, %eax
movl %eax, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movl %eax, %edi
callq 0x10c0
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
jne 0x258c
leaq 0xaa7(%rip), %rdi       # 0x3024
callq 0x10e0
movl $0x1, %edi
callq 0x10f0
movl -0x44(%rbp), %ecx
addl $0x1, %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
movq -0x28(%rbp), %rdi
callq 0x1060
movb %al, %cl
movq -0x58(%rbp), %rax
movb %cl, 0x6(%rax)
movl -0x4c(%rbp), %eax
movw %ax, %cx
movq -0x58(%rbp), %rax
movw %cx, 0x4(%rax)
movq -0x58(%rbp), %rax
movb $0x2, 0x7(%rax)
movq -0x58(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x90(%rbp)
movq -0x28(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x28(%rbp), %rdi
callq 0x1060
movq -0x90(%rbp), %rdi
movq -0x88(%rbp), %rsi
movq %rax, %rdx
callq 0x10b0
movq -0x38(%rbp), %rax
movzwl 0xc(%rax), %eax
movl %eax, -0x5c(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x80(%rbp)
movq 0x2a81(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x8(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq -0x80(%rbp), %rdi
movq %rax, %rsi
callq 0x13c0
movq %rax, -0x64(%rbp)
cmpl $0xb, -0x60(%rbp)
jae 0x2671
cmpl $0x2, -0x60(%rbp)
je 0x2671
movq 0x29ad(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0xaad(%rip), %rsi       # 0x3102
movb $0x0, %al
callq 0x10a0
movq -0x58(%rbp), %rdi
callq 0x1030
movl $0x2, -0x4(%rbp)
jmp 0x2a16
movsbl -0x64(%rbp), %eax
cmpl $0x64, %eax
je 0x26a7
movq 0x2977(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0xa8b(%rip), %rsi       # 0x3116
movb $0x0, %al
callq 0x10a0
movq -0x58(%rbp), %rdi
callq 0x1030
movl $0x2, -0x4(%rbp)
jmp 0x2a16
cmpl $0x1, -0x5c(%rbp)
jge 0x26d1
movq 0x2944(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0xa7e(%rip), %rsi       # 0x313c
movb $0x0, %al
callq 0x10a0
movl $0x1c, -0x4(%rbp)
jmp 0x2a16
movq 0x29c0(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x8(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq %rax, -0xa8(%rbp)
movl -0x60(%rbp), %eax
movl %eax, -0xa0(%rbp)
movl -0x5c(%rbp), %eax
movl %eax, -0x9c(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0x98(%rbp)
movq 0x2984(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl (%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq -0xa8(%rbp), %rdi
movl -0xa0(%rbp), %esi
movl -0x9c(%rbp), %edx
movq -0x98(%rbp), %rcx
movq %rax, %r8
callq 0x1e60
movl %eax, -0x5c(%rbp)
cmpl $-0x1, %eax
jne 0x2770
movq 0x28a3(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x9f8(%rip), %rsi       # 0x3157
movb $0x0, %al
callq 0x10a0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x10f0
movq -0x58(%rbp), %rdi
callq 0x1030
movq -0x38(%rbp), %rax
movw 0xe(%rax), %cx
addw $-0x1, %cx
movw %cx, 0xe(%rax)
movq 0x2908(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x8(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq %rax, %rdi
movl -0x44(%rbp), %esi
addl $0x1, %esi
callq 0x17a0
movq %rax, -0xc0(%rbp)
movl -0x44(%rbp), %eax
movl %eax, -0xb4(%rbp)
movq 0x28d2(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl (%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq %rax, -0xb0(%rbp)
movq 0x28b4(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x4(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq -0xc0(%rbp), %rdi
movl -0xb4(%rbp), %esi
movq -0xb0(%rbp), %r9
xorl %r8d, %r8d
xorl %ecx, %ecx
movl %r8d, %edx
movq %rax, (%rsp)
movl $0x4000, 0x8(%rsp)      # imm = 0x4000
callq 0x1c50
movl -0x5c(%rbp), %eax
movw %ax, %cx
movq -0x38(%rbp), %rax
movw %cx, 0xc(%rax)
leaq 0x944(%rip), %rdi       # 0x317b
movb $0x0, %al
callq 0x1080
movl $0xc, %edi
callq 0x10c0
movq %rax, -0x58(%rbp)
cmpq $0x0, -0x58(%rbp)
jne 0x2869
leaq 0x7ca(%rip), %rdi       # 0x3024
callq 0x10e0
movl $0x1, %edi
callq 0x10f0
movl -0x44(%rbp), %ecx
addl $0x1, %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
movq -0x58(%rbp), %rax
movb $0x1, 0x6(%rax)
movq -0x58(%rbp), %rax
movw $0xc, 0x4(%rax)
movq -0x58(%rbp), %rax
movb $0x2, 0x7(%rax)
movq -0x58(%rbp), %rax
movb $0x2e, 0x8(%rax)
movq 0x27fa(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x8(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq %rax, %rdi
movl -0x44(%rbp), %esi
addl $0x1, %esi
callq 0x17a0
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movl $0x0, 0x28(%rax)
movq 0x27c5(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x8(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq %rax, -0xf0(%rbp)
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe8(%rbp)
movl -0x5c(%rbp), %eax
movl %eax, -0xe4(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0xe0(%rbp)
movq 0x2786(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl (%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq -0xf0(%rbp), %rdi
movl -0xe8(%rbp), %esi
movl -0xe4(%rbp), %edx
movq -0xe0(%rbp), %rcx
movq %rax, %r8
callq 0x1e60
movl %eax, -0x5c(%rbp)
movl -0x60(%rbp), %ecx
movq -0x58(%rbp), %rax
movl %ecx, (%rax)
movq -0x58(%rbp), %rax
movb $0x2, 0x6(%rax)
movq -0x58(%rbp), %rax
movb $0x2e, 0x8(%rax)
movq -0x58(%rbp), %rax
movb $0x2e, 0x9(%rax)
movq 0x2729(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl 0x8(%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq %rax, -0xd8(%rbp)
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd0(%rbp)
movl -0x5c(%rbp), %eax
movl %eax, -0xcc(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0xc8(%rbp)
movq 0x26ea(%rip), %rdi      # 0x5098
movq -0x38(%rbp), %rax
movl (%rax), %esi
movl $0x400, %edx            # imm = 0x400
callq 0x17c0
movq -0xd8(%rbp), %rdi
movl -0xd0(%rbp), %esi
movl -0xcc(%rbp), %edx
movq -0xc8(%rbp), %rcx
movq %rax, %r8
callq 0x1e60
movl -0x5c(%rbp), %eax
movw %ax, %cx
movq -0x38(%rbp), %rax
movw %cx, 0xc(%rax)
movq -0x38(%rbp), %rax
movzwl 0x10(%rax), %ecx
addl $0x3, %ecx
movw %cx, 0x10(%rax)
movq -0x58(%rbp), %rdi
callq 0x1030
movq -0x28(%rbp), %rdi
callq 0x1030
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq