示例#1
0
文件: fat_fs.cpp 项目: stmobo/Omamori
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;
	}
}
示例#2
0
/*
 * 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;
}
示例#3
0
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;

}