// File: /workspace/github_c_makefile_star2_O0/sheheryarbutt[P]Ext2-File-System/ext2_restore.c
// Function: main
int main(int argc, char **argv) {
	if(argc != 3) { 
        fprintf(stderr, "Usage: ext2_restore <image file name> <Absolute path>\n");
         exit(1);
    }
    int fd = open(argv[1], O_RDWR);
 
	char *path = malloc(sizeof(char)*((unsigned int)strlen(argv[2]) + 1));
	strcpy(path, argv[2]);
	path[(unsigned int)strlen(argv[2])] = '\0';

    disk = mmap(NULL, 128 * EXT2_BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if(disk == MAP_FAILED) {
		perror("mmap");
		exit(1);
 	}

 	sb = (struct ext2_super_block *)(disk + EXT2_BLOCK_SIZE);
    gd = (struct ext2_group_desc *)(disk + (2*EXT2_BLOCK_SIZE));
		 
 	inode_table = (struct ext2_inode *)(disk + (5*EXT2_BLOCK_SIZE));



	//This part gives us directory_path and file_name
	char *absPath=malloc((unsigned int)strlen(path)); strcpy(absPath,path);
	if((unsigned int)strlen(absPath)==1 && strcmp(absPath,"/")==0){
		fprintf(stderr, "ERROR: %s\n", strerror(EISDIR)); 
		exit(EISDIR);
	}
	remove_trailing_slash(absPath); // remove the trailing slashes
	char * file_name=basename(absPath); unsigned int file_name_length= (unsigned int)strlen(file_name);
	unsigned int absPath_length=(unsigned int) strlen(absPath);
	absPath[absPath_length - (file_name_length + 1)]='\0';
	char directory_path[absPath_length - file_name_length]; strcpy(directory_path,absPath);
	
	if((unsigned int)strlen(directory_path) == 0){ // if only "/file" is given 
		strcpy(directory_path,"/");
	}

	int * file_in_dir_block=malloc(sizeof(int *)); *file_in_dir_block=-1;
	int * file_offset=malloc(sizeof(int *));  *file_offset=-1; 
	int * entry_offset=malloc(sizeof(int *));  *entry_offset=-1;
	int * file_inode=malloc(sizeof(int *)); *file_inode=0;
	int in_gap=file_in_gap(directory_path,file_name,file_in_dir_block, file_offset, file_inode,entry_offset);

	if(in_gap){//maybe we found the file
		if(*file_inode>EXT2_GOOD_OLD_FIRST_INO || *file_inode<=32){ 

				unsigned int * ib = (unsigned int *)(disk+EXT2_BLOCK_SIZE*4);
				// -0 represents what we want the n=10 bit too (its really 11 tho!)
				if ( ib[0]&(1<< ((*file_inode) - 1 ))){// check if its a 1 or 0
					fprintf(stderr, "ERROR: %s\n", strerror(EPERM)); 
					exit(EPERM); 
				}
				//block/data bitmap
				struct ext2_inode inode = inode_table[*file_inode-1];//access the specific inode!
				int cur_index=0;
				int inode_i_block= inode.i_block[cur_index];// accessing the first i_block[0]= some block #
				unsigned int * bb=(unsigned int *)(disk + EXT2_BLOCK_SIZE*3);//accessing the data bitmap

				while(inode_i_block){// going through all the data blocks gotten  from i_block[] of the inode!
					int index_of_bb=(inode_i_block-1)/32;// gonna be 0,1,2 or 3  
					// If data block is replaced -> return error
					if(bb[index_of_bb]& (1<< (inode_i_block -1) % 32)){
						fprintf(stderr, "ERROR: %s\n", strerror(EPERM)); 
						exit(EPERM); 
					}
					cur_index++;
					inode_i_block= inode.i_block[cur_index];
				}// After this while we know all data blocks havent been reused!

				ib[0] ^= (-1 ^ ib[0]) & (1U << (*file_inode-1)); // change inode bitmap val. to 1
	
				cur_index=0; inode_i_block= inode.i_block[cur_index];
				while(inode_i_block){// going through all the data blocks 
					int index_of_bb=(inode_i_block-1)/32;// gonna be 0,1,2 or 3  
					bb[index_of_bb] ^= 1U << (inode_i_block -1) % 32;
					cur_index++;
					inode_i_block= inode.i_block[cur_index];
				}
				//decreasing number of free inodes and blocks
				sb->s_free_inodes_count-=1;  sb->s_free_blocks_count-=inode.i_blocks/2;
				gd->bg_free_inodes_count-=1; gd->bg_free_blocks_count-=inode.i_blocks/2;
				//changing links count and d_time
				 inode_table[*file_inode-1].i_links_count=1;  inode_table[*file_inode-1].i_dtime=0;
				//Updating rec_len of the enteries!
				struct ext2_dir_entry *direntry = (struct ext2_dir_entry *)(disk + (*file_in_dir_block)*EXT2_BLOCK_SIZE + (*entry_offset));
				struct ext2_dir_entry *gapEntry = (struct ext2_dir_entry *)(disk + (*file_in_dir_block)*EXT2_BLOCK_SIZE + (*file_offset));
				int entry_rec_len= direntry->rec_len;
				direntry->rec_len=(*file_offset)-(*entry_offset);
				gapEntry->rec_len=entry_rec_len - (direntry->rec_len);

		}
		else{
			fprintf(stderr, "ERROR: %s\n", strerror(EPERM)); 
			exit(EPERM); 
		}
	}
	else{// no such file found in gaps!
		fprintf(stderr, "ERROR: %s\n", strerror(EPERM)); 
		exit(EPERM); 
	}
	free(file_in_dir_block); free(file_offset);
	free(entry_offset); free(file_inode);

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x3, -0x8(%rbp)
je 0x1261
movq 0x3db2(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x1db4(%rip), %rsi      # 0x3004
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1100
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
movl $0x2, %esi
movb $0x0, %al
callq 0x10e0
movl %eax, -0x14(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x1060
addl $0x1, %eax
movl %eax, %eax
movl %eax, %edi
shlq $0x0, %rdi
callq 0x10d0
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
callq 0x1050
movq -0x20(%rbp), %rax
movq %rax, -0x130(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
callq 0x1060
movq %rax, %rcx
movq -0x130(%rbp), %rax
movl %ecx, %ecx
movb $0x0, (%rax,%rcx)
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, 0x3daf(%rip)      # 0x50a8
movq $-0x1, %rax
cmpq %rax, 0x3da1(%rip)      # 0x50a8
jne 0x131f
leaq 0x1d2b(%rip), %rdi      # 0x303b
callq 0x10f0
movl $0x1, %edi
callq 0x1100
movq 0x3d82(%rip), %rax      # 0x50a8
addq $0x400, %rax            # imm = 0x400
movq %rax, 0x3d7d(%rip)      # 0x50b0
movq 0x3d6e(%rip), %rax      # 0x50a8
addq $0x800, %rax            # imm = 0x800
movq %rax, 0x3d71(%rip)      # 0x50b8
movq 0x3d5a(%rip), %rax      # 0x50a8
addq $0x1400, %rax           # imm = 0x1400
movq %rax, 0x3d65(%rip)      # 0x50c0
movq -0x20(%rbp), %rdi
callq 0x1060
movl %eax, %eax
movl %eax, %edi
callq 0x10d0
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x1050
movq -0x28(%rbp), %rdi
callq 0x1060
cmpl $0x1, %eax
jne 0x13de
movq -0x28(%rbp), %rdi
leaq 0x1ca9(%rip), %rsi      # 0x3040
callq 0x1080
cmpl $0x0, %eax
jne 0x13de
movq 0x3c50(%rip), %rax      # 0x4ff8
movq (%rax), %rax
movq %rax, -0x138(%rbp)
movl $0x15, %edi
callq 0x1110
movq -0x138(%rbp), %rdi
movq %rax, %rdx
leaq 0x1c75(%rip), %rsi      # 0x3042
movb $0x0, %al
callq 0x1090
movl $0x15, %edi
callq 0x1100
movq -0x28(%rbp), %rdi
callq 0x2080
movq -0x28(%rbp), %rdi
callq 0x10b0
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
callq 0x1060
movl %eax, -0x34(%rbp)
movq -0x28(%rbp), %rdi
callq 0x1060
movl %eax, -0x38(%rbp)
movq -0x28(%rbp), %rax
movl -0x38(%rbp), %edx
movl -0x34(%rbp), %ecx
notl %ecx
addl %edx, %ecx
movb $0x0, (%rax,%rcx)
movl -0x38(%rbp), %eax
movl -0x34(%rbp), %ecx
subl %ecx, %eax
movq %rsp, %rcx
movq %rcx, -0x40(%rbp)
movq %rax, %rcx
addq $0xf, %rcx
andq $-0x10, %rcx
movq %rsp, %rdi
subq %rcx, %rdi
movq %rdi, -0x140(%rbp)
movq %rdi, %rsp
movq %rax, -0x48(%rbp)
movq -0x28(%rbp), %rsi
callq 0x1050
movq -0x140(%rbp), %rdi
callq 0x1060
cmpl $0x0, %eax
jne 0x1479
movq -0x140(%rbp), %rdi
leaq 0x1bcc(%rip), %rsi      # 0x3040
callq 0x1050
movl $0x8, %edi
callq 0x10d0
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movl $0x8, %edi
callq 0x10d0
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movl $0x8, %edi
callq 0x10d0
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movl $0xffffffff, (%rax)     # imm = 0xFFFFFFFF
movl $0x8, %edi
callq 0x10d0
movq -0x140(%rbp), %rdi
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
movl $0x0, (%rax)
movq -0x30(%rbp), %rsi
movq -0x50(%rbp), %rdx
movq -0x58(%rbp), %rcx
movq -0x68(%rbp), %r8
movq -0x60(%rbp), %r9
callq 0x1950
movl %eax, -0x6c(%rbp)
cmpl $0x0, -0x6c(%rbp)
je 0x18de
movq -0x68(%rbp), %rax
cmpl $0xb, (%rax)
jg 0x151c
movq -0x68(%rbp), %rax
cmpl $0x20, (%rax)
jg 0x189f
movq 0x3b85(%rip), %rax      # 0x50a8
addq $0x1000, %rax           # imm = 0x1000
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movl (%rax), %eax
movq -0x68(%rbp), %rcx
movl (%rcx), %ecx
subl $0x1, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x1589
movq 0x3aa5(%rip), %rax      # 0x4ff8
movq (%rax), %rax
movq %rax, -0x148(%rbp)
movl $0x1, %edi
callq 0x1110
movq -0x148(%rbp), %rdi
movq %rax, %rdx
leaq 0x1aca(%rip), %rsi      # 0x3042
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1100
movq 0x3b30(%rip), %rsi      # 0x50c0
movq -0x68(%rbp), %rax
movl (%rax), %eax
subl $0x1, %eax
cltq
shlq $0x7, %rax
addq %rax, %rsi
leaq -0xf8(%rbp), %rdi
movl $0x80, %edx
callq 0x10a0
movl $0x0, -0xfc(%rbp)
movslq -0xfc(%rbp), %rax
movl -0xd0(%rbp,%rax,4), %eax
movl %eax, -0x100(%rbp)
movq 0x3ad0(%rip), %rax      # 0x50a8
addq $0xc00, %rax            # imm = 0xC00
movq %rax, -0x108(%rbp)
cmpl $0x0, -0x100(%rbp)
je 0x16ae
movl -0x100(%rbp), %eax
subl $0x1, %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl %eax, -0x10c(%rbp)
movq -0x108(%rbp), %rax
movslq -0x10c(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x14c(%rbp)
movl -0x100(%rbp), %eax
subl $0x1, %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl -0x14c(%rbp), %eax
movl %edx, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x1686
movq 0x39a8(%rip), %rax      # 0x4ff8
movq (%rax), %rax
movq %rax, -0x158(%rbp)
movl $0x1, %edi
callq 0x1110
movq -0x158(%rbp), %rdi
movq %rax, %rdx
leaq 0x19cd(%rip), %rsi      # 0x3042
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1100
movl -0xfc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xfc(%rbp)
movslq -0xfc(%rbp), %rax
movl -0xd0(%rbp,%rax,4), %eax
movl %eax, -0x100(%rbp)
jmp 0x15e5
movq -0x78(%rbp), %rax
movl (%rax), %eax
xorl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl %eax, -0x15c(%rbp)
movq -0x68(%rbp), %rax
movl (%rax), %ecx
subl $0x1, %ecx
movl $0x1, %eax
shll %cl, %eax
movl -0x15c(%rbp), %ecx
andl %eax, %ecx
movq -0x78(%rbp), %rax
xorl (%rax), %ecx
movl %ecx, (%rax)
movl $0x0, -0xfc(%rbp)
movslq -0xfc(%rbp), %rax
movl -0xd0(%rbp,%rax,4), %eax
movl %eax, -0x100(%rbp)
cmpl $0x0, -0x100(%rbp)
je 0x1770
movl -0x100(%rbp), %eax
subl $0x1, %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl %eax, -0x110(%rbp)
movl -0x100(%rbp), %eax
subl $0x1, %eax
movl $0x20, %ecx
cltd
idivl %ecx
movl %edx, %ecx
movl $0x1, %edx
shll %cl, %edx
movq -0x108(%rbp), %rax
movslq -0x110(%rbp), %rcx
xorl (%rax,%rcx,4), %edx
movl %edx, (%rax,%rcx,4)
movl -0xfc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xfc(%rbp)
movslq -0xfc(%rbp), %rax
movl -0xd0(%rbp,%rax,4), %eax
movl %eax, -0x100(%rbp)
jmp 0x16fd
movq 0x3939(%rip), %rax      # 0x50b0
movl 0x10(%rax), %ecx
subl $0x1, %ecx
movl %ecx, 0x10(%rax)
movl -0xdc(%rbp), %edx
shrl %edx
movq 0x3921(%rip), %rax      # 0x50b0
movl 0xc(%rax), %ecx
subl %edx, %ecx
movl %ecx, 0xc(%rax)
movq 0x391a(%rip), %rax      # 0x50b8
movzwl 0xe(%rax), %ecx
subl $0x1, %ecx
movw %cx, 0xe(%rax)
movl -0xdc(%rbp), %edx
shrl %edx
movq 0x3900(%rip), %rax      # 0x50b8
movzwl 0xc(%rax), %ecx
subl %edx, %ecx
movw %cx, 0xc(%rax)
movq 0x38f7(%rip), %rax      # 0x50c0
movq -0x68(%rbp), %rcx
movl (%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movw $0x1, 0x1a(%rax)
movq 0x38d7(%rip), %rax      # 0x50c0
movq -0x68(%rbp), %rcx
movl (%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movl $0x0, 0x14(%rax)
movq 0x389e(%rip), %rax      # 0x50a8
movq -0x50(%rbp), %rcx
movl (%rcx), %ecx
shll $0xa, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq -0x60(%rbp), %rcx
movslq (%rcx), %rcx
addq %rcx, %rax
movq %rax, -0x118(%rbp)
movq 0x3877(%rip), %rax      # 0x50a8
movq -0x50(%rbp), %rcx
movl (%rcx), %ecx
shll $0xa, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq -0x58(%rbp), %rcx
movslq (%rcx), %rcx
addq %rcx, %rax
movq %rax, -0x120(%rbp)
movq -0x118(%rbp), %rax
movzwl 0x4(%rax), %eax
movl %eax, -0x124(%rbp)
movq -0x58(%rbp), %rax
movl (%rax), %eax
movq -0x60(%rbp), %rcx
subl (%rcx), %eax
movw %ax, %cx
movq -0x118(%rbp), %rax
movw %cx, 0x4(%rax)
movl -0x124(%rbp), %eax
movq -0x118(%rbp), %rcx
movzwl 0x4(%rcx), %ecx
subl %ecx, %eax
movw %ax, %cx
movq -0x120(%rbp), %rax
movw %cx, 0x4(%rax)
jmp 0x18dc
movq 0x3752(%rip), %rax      # 0x4ff8
movq (%rax), %rax
movq %rax, -0x168(%rbp)
movl $0x1, %edi
callq 0x1110
movq -0x168(%rbp), %rdi
movq %rax, %rdx
leaq 0x1777(%rip), %rsi      # 0x3042
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1100
jmp 0x191b
movq 0x3713(%rip), %rax      # 0x4ff8
movq (%rax), %rax
movq %rax, -0x170(%rbp)
movl $0x1, %edi
callq 0x1110
movq -0x170(%rbp), %rdi
movq %rax, %rdx
leaq 0x1738(%rip), %rsi      # 0x3042
movb $0x0, %al
callq 0x1090
movl $0x1, %edi
callq 0x1100
movq -0x50(%rbp), %rdi
callq 0x1030
movq -0x58(%rbp), %rdi
callq 0x1030
movq -0x60(%rbp), %rdi
callq 0x1030
movq -0x68(%rbp), %rdi
callq 0x1030
movq -0x40(%rbp), %rax
movq %rax, %rsp
movl -0x4(%rbp), %eax
movq %rbp, %rsp
popq %rbp
retq
nop