void fat_fs::fat_fs::update_node(vfs_node* node) { unsigned char shortname[8]; fat_directory_entry* old_fsinfo = (fat_directory_entry*)node->fs_info; memcpy( (void*)shortname, (void*)old_fsinfo->shortname, 8 ); kfree(old_fsinfo); node->fs_info = (void*)read_dir_entry( (vfs_directory*)node->parent, shortname ); if(node->type == vfs_node_types::file) { vfs_file* fn = (vfs_file*)node; fn->size = ((fat_directory_entry*)node->fs_info)->fsize; } }
/* * Reads the directory of a pak file * into a linked list and returns * a pointer to the first element. * * *fd -> a file descriptor holding * holding the pak to be read */ static directory * read_directory(FILE *fd, int listOnly, int* num_entries) { int i; int direntry_len = dk_pak_mode ? HDR_DIR_LEN_DK : HDR_DIR_LEN_Q2; int num_dir_entries = header.dir_length / direntry_len; directory* dir = calloc(num_dir_entries, sizeof(directory)); if(dir == NULL) { perror("Couldn't allocate memory"); return NULL; } /* Navigate to the directory */ fseek(fd, header.dir_offset, SEEK_SET); for (i = 0; i < num_dir_entries; ++i) { directory* cur = &dir[i]; if (!read_dir_entry(cur, fd)) { perror("Could not read directory entry"); *num_entries = 0; free(dir); return NULL; } if(listOnly) { printf("%s (%d bytes", cur->file_name, cur->file_length); if(dk_pak_mode && cur->is_compressed) printf(", %d compressed", cur->compressed_length); printf(")\n"); } } *num_entries = num_dir_entries; return dir; }
int search_file(uint8_t* rd, char* path){ int i,j,k; struct rd_path* path_list; struct rd_path* path_tmp; struct rd_path* path_root; struct rd_path* path_leave; char tmp[14]; int inodeNO; //parse the path by token '/' #ifdef UL_DEBUG if(!(path_list=(struct rd_path*)malloc(sizeof(struct rd_path)))){ fprintf(stderr, "No space for path list struct\n"); exit(-1); } #endif #ifndef UL_DEBUG if(!(path_list=(struct rd_path*)vmalloc(sizeof(struct rd_path)))){ printk("<1> No space for path list struct\n"); return (-1); } #endif path_list->next=NULL; if(path[0]!='/'){//the first character of path should be root path return -1; } strcpy(path_list->filename,"/");//the root filename is "/" path_root=path_list; path_leave=path_list; i=1; j=0; while(path[i]){//if not '\0' if(path[i]=='/'){ if(j==0){ #ifdef UL_DEBUG printf("Error, Wrong path\n"); #endif #ifndef UL_DEBUG printk("<1> Error, Wrong path\n"); #endif return -1; } else if(j>=14){ #ifdef UL_DEBUG printf("Error, dir name %s too long\n",tmp); #endif #ifndef UL_DEBUG printk("<1> Error, dir name %s too long\n",tmp); #endif return -1; } else{ tmp[j]='\0'; j=0; #ifdef UL_DEBUG if(!(path_list=(struct rd_path*)malloc(sizeof(struct rd_path)))){ fprintf(stderr, "No space for path list struct\n"); exit(-1); } #endif #ifndef UL_DEBUG if(!(path_list=(struct rd_path*)vmalloc(sizeof(struct rd_path)))){ printk("<1> No space for path list struct\n"); return (-1); } #endif //add the path_list to the end of the link list path_list->next=NULL; path_leave->next=path_list; path_leave=path_list; strcpy(path_leave->filename,tmp); } j=0; } else{ tmp[j]=path[i]; j++; } i++; } if(j==0&&i>1){ #ifdef UL_DEBUG printf("Error, Wrong path\n"); #endif #ifndef UL_DEBUG printk("<1> Error, Wrong path\n"); #endif return -1; } else if(j==0&&i==1){ //means the path is "/", return the 0th inode return 0; } else if(j>=14){ #ifdef UL_DEBUG printf("Error, dir name %s too long\n",tmp); #endif #ifndef UL_DEBUG printk("<1> Error, dir name %s too long\n",tmp); #endif return -1; } else{ tmp[j]='\0'; #ifdef UL_DEBUG if(!(path_list=(struct rd_path*)malloc(sizeof(struct rd_path)))){ fprintf(stderr, "No space for path list struct\n"); exit(-1); } #endif #ifndef UL_DEBUG if(!(path_list=(struct rd_path*)vmalloc(sizeof(struct rd_path)))){ printk("<1>No space for path list struct\n"); return (-1); } #endif //add the path_list to the end of the link list path_list->next=NULL; path_leave->next=path_list; path_leave=path_list; strcpy(path_leave->filename,tmp); } #ifdef UL_DEBUG //printf("Path list printing...\n"); //for(path_list=path_root;path_list!=NULL;path_list=path_list->next){ // printf("%s\n",path_list->filename); //} #endif // the path list is started with path_root and ended with path_leave // int current_inodeid=0;//start from the root inode struct rd_inode* current_inode; uint32_t current_direct_blockid; uint32_t current_single_indirect_blockid; uint32_t current_double_indirect_blockid; int size_region_type; struct dir_entry* current_dir_entry; int find_next_level_entry=0; int return_inodeNO; int single_indirect_pointer_block_number; int direct_pointer_block_number; #ifdef UL_DEBUG if(!(current_inode=(struct rd_inode*)malloc(sizeof(struct rd_inode)))){ fprintf(stderr,"No mem space!\n"); exit(-1); } if(!(current_dir_entry=(struct dir_entry*)malloc(sizeof(struct dir_entry)))){ fprintf(stderr,"No mem space!\n"); exit(-1); } #endif #ifndef UL_DEBUG if(!(current_inode=(struct rd_inode*)vmalloc(sizeof(struct rd_inode)))){ printk("<1> No mem space!\n"); return (-1); } if(!(current_dir_entry=(struct dir_entry*)vmalloc(sizeof(struct dir_entry)))){ printk("<1> No mem space!\n"); return (-1); } #endif for(path_list=path_root->next;path_list!=NULL;path_list=path_list->next){ find_next_level_entry=0; read_inode(rd, current_inodeid, current_inode); if(current_inode->type==1 && path_list->next!=NULL){ #ifdef UL_DEBUG printf("The dir is actually a regular file, wrong path\n"); #endif #ifndef UL_DEBUG printk("<1> The dir is actually a regular file, wrong path\n"); #endif return -1; } /* the size of file have three regions (unit:block) * [1,8] size_region_type=0 * [9,72] size_region_type=1 * [73, 1067008] size_region_type=2 */ //determing the file size belongs to which region if(current_inode->size<=8*RD_BLOCK_SIZE){ size_region_type=0; } else if(current_inode->size>8*RD_BLOCK_SIZE && current_inode->size<=72*RD_BLOCK_SIZE){ size_region_type=1; } else if(current_inode->size>72*RD_BLOCK_SIZE && current_inode->size<=4168*RD_BLOCK_SIZE){ size_region_type=2; } //first traverse the 8 direct block pointers for(i=0;i<((size_region_type==0)?(current_inode->size/RD_BLOCK_SIZE+1):8);i++){ current_direct_blockid=current_inode->BlockPointer[i]; if(current_direct_blockid<261){ /*the first 261 blocks is taken by superblock, inodes and bitmap * Therefore, the blockid that is smaller than 261 is invalid */ continue; } #ifdef UL_DEBUG // printf("the direct block id is %d\n",current_direct_blockid); // fflush(stdout); #endif for(j=0;j<16;j++){//every block of dir file has 16 entries read_dir_entry(&rd[current_direct_blockid*RD_BLOCK_SIZE+j*16],current_dir_entry); #ifdef UL_DEBUG // printf("i=%d, j=%d, %s, %d \n", i,j,current_dir_entry->filename,current_dir_entry->InodeNo ); #endif if(strcmp(current_dir_entry->filename,path_list->filename)==0){ find_next_level_entry=1; current_inodeid=current_dir_entry->InodeNo; break; } } if(find_next_level_entry) break; } if(find_next_level_entry) continue; else if(size_region_type<1){ //tried all the possible entries, not found #ifdef UL_DEBUG printf("File not found in the first 8 blocks\n"); #endif return -1; } //if not found, then try the 9th single-indirect pointer current_single_indirect_blockid=current_inode->BlockPointer[8]; #ifdef UL_DEBUG // printf("the 9th block (single indirect block) id is %d\n",current_single_indirect_blockid); // fflush(stdout); #endif for(i=0;i<((size_region_type==1)?((current_inode->size-8*RD_BLOCK_SIZE)/RD_BLOCK_SIZE+1):64);i++){ current_direct_blockid=(uint32_t)(rd[current_single_indirect_blockid*RD_BLOCK_SIZE+4*i]) | ((uint32_t)(rd[current_single_indirect_blockid*RD_BLOCK_SIZE+4*i+1])<<BYTELEN) | ((uint32_t)(rd[current_single_indirect_blockid*RD_BLOCK_SIZE+4*i+2])<<(2*BYTELEN)) | ((uint32_t)(rd[current_single_indirect_blockid*RD_BLOCK_SIZE+4*i+3])<<(3*BYTELEN)); #ifdef UL_DEBUG // printf("the direct block id is %d\n",current_direct_blockid); // fflush(stdout); #endif for(j=0;j<16;j++){ read_dir_entry(&rd[(current_direct_blockid)*RD_BLOCK_SIZE+j*16],current_dir_entry); #ifdef UL_DEBUG // printf("i=%d, j=%d, %s, %d ,%s \n", i,j,current_dir_entry->filename,current_dir_entry->InodeNo,path_list->filename ); #endif if(strcmp(current_dir_entry->filename,path_list->filename)==0){ find_next_level_entry=1; current_inodeid=current_dir_entry->InodeNo; break; } } if(find_next_level_entry) break; } if(find_next_level_entry) continue; else if(size_region_type<2){ //tried all the possible entries, not found #ifdef UL_DEBUG printf("File not found in the 9th blocks\n"); #endif return -1; } //if not found, then try the 10th double-indirect pointer /* The 10th pointer points to a block with 64 single-indirect block pointers * Each of these single-indirect block pointers points to a block with 64 direct block pointers */ current_double_indirect_blockid=current_inode->BlockPointer[9]; single_indirect_pointer_block_number=(current_inode->size-72*RD_BLOCK_SIZE)/(64*RD_BLOCK_SIZE)+1; for(i=0;i<single_indirect_pointer_block_number;i++){ current_single_indirect_blockid=(uint32_t)(rd[current_double_indirect_blockid*RD_BLOCK_SIZE+4*i]) | ((uint32_t)(rd[current_double_indirect_blockid*RD_BLOCK_SIZE+4*i+1])<<BYTELEN) | ((uint32_t)(rd[current_double_indirect_blockid*RD_BLOCK_SIZE+4*i+2])<<(2*BYTELEN)) | ((uint32_t)(rd[current_double_indirect_blockid*RD_BLOCK_SIZE+4*i+3])<<(3*BYTELEN)); direct_pointer_block_number=((i==single_indirect_pointer_block_number-1)?(((current_inode->size-72*RD_BLOCK_SIZE)%(64*RD_BLOCK_SIZE))/RD_BLOCK_SIZE+1):64); for(j=0;j<direct_pointer_block_number;j++){ current_direct_blockid=(uint32_t)(rd[current_single_indirect_blockid*RD_BLOCK_SIZE+4*j]) | ((uint32_t)(rd[current_single_indirect_blockid*RD_BLOCK_SIZE+4*j+1])<<BYTELEN) | ((uint32_t)(rd[current_single_indirect_blockid*RD_BLOCK_SIZE+4*j+2])<<(2*BYTELEN)) | ((uint32_t)(rd[current_single_indirect_blockid*RD_BLOCK_SIZE+4*j+3])<<(3*BYTELEN)); for(k=0;k<16;k++){ read_dir_entry(&rd[current_direct_blockid*RD_BLOCK_SIZE+k*16],current_dir_entry); if(strcmp(current_dir_entry->filename,path_list->filename)==0){ find_next_level_entry=1; current_inodeid=current_dir_entry->InodeNo; break; } } if(find_next_level_entry) break; } if(find_next_level_entry) break; } if(find_next_level_entry) continue; else{ #ifdef UL_DEBUG printf("File not found in the 10th blocks\n"); #endif return -1; } } #ifndef UL_DEBUG path_list=path_root; while(path_list){ path_tmp=path_list; path_list=path_list->next; vfree(path_tmp); } vfree(current_inode); vfree(current_dir_entry); #endif return current_inodeid; }