⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inode.c

📁 一款linux的文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
			page_cache_release(push_page);		}	}	if(inode->u.squashfs_i.u.s1.fragment_start_block == SQUASHFS_INVALID_BLK || index < (inode->i_size >> sBlk->block_log))		up(&msBlk->read_page_mutex);	else		release_cached_fragment(msBlk, fragment);	return 0;skip_read:	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);	kunmap(page);	flush_dcache_page(page);	SetPageUptodate(page);	UnlockPage(page);	return 0;}static int squashfs_readpage4K(struct file *file, struct page *page){	struct inode *inode = page->mapping->host;	squashfs_sb_info *msBlk = &inode->i_sb->u.squashfs_sb;	squashfs_super_block *sBlk = &msBlk->sBlk;	unsigned char block_list[SIZE];	unsigned int bsize, block, bytes = 0; 	void *pageaddr = kmap(page);		TRACE("Entered squashfs_readpage4K, page index %x, start block %x\n", (unsigned int) page->index,		inode->u.squashfs_i.start_block);	if(page->index >= ((inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)) {		goto skip_read;	}	if(inode->u.squashfs_i.u.s1.fragment_start_block == SQUASHFS_INVALID_BLK || page->index < (inode->i_size >> sBlk->block_log)) {		block = (msBlk->read_blocklist)(inode, page->index, 1, block_list, NULL, &bsize);		if(!(bytes = read_data(inode->i_sb, pageaddr, block, bsize, NULL)))			ERROR("Unable to read page, block %x, size %x\n", block, bsize);	} else {		struct squashfs_fragment_cache *fragment;		if((fragment = get_cached_fragment(inode->i_sb, inode->u.squashfs_i.u.s1.fragment_start_block, inode->u.squashfs_i.u.s1.fragment_size)) == NULL)			ERROR("Unable to read page, block %x, size %x\n", inode->u.squashfs_i.u.s1.fragment_start_block, (int) inode->u.squashfs_i.u.s1.fragment_size);		else {			bytes = inode->i_size & (sBlk->block_size - 1);			memcpy(pageaddr, fragment->data + inode->u.squashfs_i.u.s1.fragment_offset, bytes);			release_cached_fragment(msBlk, fragment);		}	}skip_read:	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);	kunmap(page);	flush_dcache_page(page);	SetPageUptodate(page);	UnlockPage(page);	return 0;}#ifdef SQUASHFS_1_0_COMPATIBILITYstatic int squashfs_readpage_lessthan4K(struct file *file, struct page *page){	struct inode *inode = page->mapping->host;	squashfs_sb_info *msBlk = &inode->i_sb->u.squashfs_sb;	squashfs_super_block *sBlk = &msBlk->sBlk;	unsigned char block_list[SIZE];	unsigned short *block_listp, block, bytes = 0;	int index = page->index << (PAGE_CACHE_SHIFT - sBlk->block_log);	int file_blocks = ((inode->i_size - 1) >> sBlk->block_log) + 1;	int readahead_blks = 1 << (PAGE_CACHE_SHIFT - sBlk->block_log); 	void *pageaddr = kmap(page);		int i_end = index + (1 << (PAGE_CACHE_SHIFT - sBlk->block_log));	int byte;	TRACE("Entered squashfs_readpage_lessthan4K, page index %x, start block %x\n", (unsigned int) page->index,		inode->u.squashfs_i.start_block);	block = read_blocklist_1(inode, index, readahead_blks, block_list, &block_listp, NULL);	if(i_end > file_blocks)		i_end = file_blocks;	while(index < i_end) {		int c_byte = !SQUASHFS_COMPRESSED(*block_listp) ? SQUASHFS_COMPRESSED_SIZE(*block_listp) | SQUASHFS_COMPRESSED_BIT_BLOCK : *block_listp;		if(!(byte = read_data(inode->i_sb, pageaddr, block, c_byte, NULL))) {			ERROR("Unable to read page, block %x, size %x\n", block, *block_listp);			goto skip_read;		}		block += SQUASHFS_COMPRESSED_SIZE(*block_listp);		pageaddr += byte;		bytes += byte;		index ++;		block_listp ++;	}skip_read:	memset(pageaddr, 0, PAGE_CACHE_SIZE - bytes);	kunmap(page);	flush_dcache_page(page);	SetPageUptodate(page);	UnlockPage(page);	return 0;}#endifstatic int get_dir_index_using_offset(struct super_block *s, unsigned int *next_block,	unsigned int *next_offset, unsigned int index_start, unsigned int index_offset,	int i_count, long long f_pos){	squashfs_sb_info *msBlk = &s->u.squashfs_sb;	squashfs_super_block *sBlk = &msBlk->sBlk;	int i, length = 0;	squashfs_dir_index index;	TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", i_count, (unsigned int) f_pos);	if(f_pos == 0)		return 0;	for(i = 0; i < i_count; i++) {		if(msBlk->swap) {			squashfs_dir_index sindex;			squashfs_get_cached_block(s, (char *) &sindex, index_start, index_offset,				sizeof(sindex), &index_start, &index_offset);			SQUASHFS_SWAP_DIR_INDEX(&index, &sindex);		} else			squashfs_get_cached_block(s, (char *) &index, index_start, index_offset,				sizeof(index), &index_start, &index_offset);		if(index.index > f_pos)			break;		squashfs_get_cached_block(s, NULL, index_start, index_offset,				index.size + 1, &index_start, &index_offset);		length = index.index;		*next_block = index.start_block + sBlk->directory_table_start;	}	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;	return length;}static int get_dir_index_using_name(struct super_block *s, unsigned int *next_block,	unsigned int *next_offset, unsigned int index_start, unsigned int index_offset,	int i_count, const char *name, int size){	squashfs_sb_info *msBlk = &s->u.squashfs_sb;	squashfs_super_block *sBlk = &msBlk->sBlk;	int i, length = 0;	char buffer[sizeof(squashfs_dir_index) + SQUASHFS_NAME_LEN + 1];	squashfs_dir_index *index = (squashfs_dir_index *) buffer;	char str[SQUASHFS_NAME_LEN + 1];	TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count);	strncpy(str, name, size);	str[size] = '\0';	for(i = 0; i < i_count; i++) {		if(msBlk->swap) {			squashfs_dir_index sindex;			squashfs_get_cached_block(s, (char *) &sindex, index_start, index_offset,				sizeof(sindex), &index_start, &index_offset);			SQUASHFS_SWAP_DIR_INDEX(index, &sindex);		} else			squashfs_get_cached_block(s, (char *) index, index_start, index_offset,				sizeof(squashfs_dir_index), &index_start, &index_offset);		squashfs_get_cached_block(s, index->name, index_start, index_offset,				index->size + 1, &index_start, &index_offset);		index->name[index->size + 1] = '\0';		if(strcmp(index->name, str) > 0)			break;		length = index->index;		*next_block = index->start_block + sBlk->directory_table_start;	}	*next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE;	return length;}static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir){	struct inode *i = file->f_dentry->d_inode;	squashfs_sb_info *msBlk = &i->i_sb->u.squashfs_sb;	squashfs_super_block *sBlk = &msBlk->sBlk;	int next_block = i->u.squashfs_i.start_block + sBlk->directory_table_start, next_offset =		i->u.squashfs_i.offset, length = 0, dirs_read = 0, dir_count;	squashfs_dir_header dirh;	char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];	squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;	TRACE("Entered squashfs_readdir [%x:%x]\n", next_block, next_offset);	length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, i->u.squashfs_i.u.s2.directory_index_start,		i->u.squashfs_i.u.s2.directory_index_offset, i->u.squashfs_i.u.s2.directory_index_count, file->f_pos);	while(length < i->i_size) {		/* read directory header */		if(msBlk->swap) {			squashfs_dir_header sdirh;			if(!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block,						next_offset, sizeof(sdirh), &next_block, &next_offset))				goto failed_read;			length += sizeof(sdirh);			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);		} else {			if(!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block,						next_offset, sizeof(dirh), &next_block, &next_offset))				goto failed_read;			length += sizeof(dirh);		}		dir_count = dirh.count + 1;		while(dir_count--) {			if(msBlk->swap) {				squashfs_dir_entry sdire;				if(!squashfs_get_cached_block(i->i_sb, (char *) &sdire, next_block,							next_offset, sizeof(sdire), &next_block, &next_offset))					goto failed_read;				length += sizeof(sdire);				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);			} else {				if(!squashfs_get_cached_block(i->i_sb, (char *) dire, next_block,							next_offset, sizeof(*dire), &next_block, &next_offset))					goto failed_read;				length += sizeof(*dire);			}			if(!squashfs_get_cached_block(i->i_sb, dire->name, next_block,						next_offset, dire->size + 1, &next_block, &next_offset))				goto failed_read;			length += dire->size + 1;			if(file->f_pos >= length)				continue;			dire->name[dire->size + 1] = '\0';			TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", (unsigned int) dirent,			dire->name, dire->size + 1, (int) file->f_pos,			dirh.start_block, dire->offset, squashfs_filetype_table[dire->type]);			if(filldir(dirent, dire->name, dire->size + 1, file->f_pos, SQUASHFS_MK_VFS_INODE(dirh.start_block,							dire->offset), squashfs_filetype_table[dire->type]) < 0) {				TRACE("Filldir returned less than 0\n");				return dirs_read;			}			file->f_pos = length;			dirs_read ++;		}	}	return dirs_read;failed_read:	ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset);	return 0;}static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry){	const char *name =dentry->d_name.name;	int len = dentry->d_name.len;	struct inode *inode = NULL;	squashfs_sb_info *msBlk = &i->i_sb->u.squashfs_sb;	squashfs_super_block *sBlk = &msBlk->sBlk;	int next_block = i->u.squashfs_i.start_block + sBlk->directory_table_start, next_offset =		i->u.squashfs_i.offset, length = 0, dir_count;	squashfs_dir_header dirh;	char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN];	squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;	int squashfs_2_1 = sBlk->s_major == 2 && sBlk->s_minor == 1;	TRACE("Entered squashfs_lookup [%x:%x]\n", next_block, next_offset);	length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, i->u.squashfs_i.u.s2.directory_index_start,		i->u.squashfs_i.u.s2.directory_index_offset, i->u.squashfs_i.u.s2.directory_index_count, name, len);	while(length < i->i_size) {		/* read directory header */		if(msBlk->swap) {			squashfs_dir_header sdirh;			if(!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block, next_offset,						sizeof(sdirh), &next_block, &next_offset))				goto failed_read;			length += sizeof(sdirh);			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);		} else {			if(!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block, next_offset,						sizeof(dirh), &next_block, &next_offset))				goto failed_read;			length += sizeof(dirh);		}		dir_count = dirh.count + 1;		while(dir_count--) {			if(msBlk->swap) {				squashfs_dir_entry sdire;				if(!squashfs_get_cached_block(i->i_sb, (char *) &sdire,							next_block,next_offset, sizeof(sdire), &next_block, &next_offset))					goto failed_read;				length += sizeof(sdire);				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);			} else {				if(!squashfs_get_cached_block(i->i_sb, (char *) dire,							next_block,next_offset, sizeof(*dire), &next_block, &next_offset))					goto failed_read;				length += sizeof(*dire);			}			if(!squashfs_get_cached_block(i->i_sb, dire->name,						next_block, next_offset, dire->size + 1, &next_block, &next_offset))				goto failed_read;			length += dire->size + 1;			if(squashfs_2_1 && name[0] < dire->name[0])				goto exit_loop;			if((len == dire->size + 1) && !strncmp(name, dire->name, len)) {				squashfs_inode ino = SQUASHFS_MKINODE(dirh.start_block, dire->offset);				TRACE("calling squashfs_iget for directory entry %s, inode %x:%x\n",						name, dirh.start_block, dire->offset);				inode = (msBlk->iget)(i->i_sb, ino);				goto exit_loop;			}		}	}exit_loop:	d_add(dentry, inode);	return ERR_PTR(0);failed_read:	ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset);	goto exit_loop;}static void squashfs_put_super(struct super_block *s){	int i;	squashfs_sb_info *sbi = (squashfs_sb_info *) &s->u.squashfs_sb;	if(sbi->block_cache) {		for(i = 0; i < SQUASHFS_CACHED_BLKS; i++)			if(sbi->block_cache[i].block != SQUASHFS_INVALID_BLK)				kfree(sbi->block_cache[i].data);		kfree(sbi->block_cache);	}	if(sbi->read_data) kfree(sbi->read_data);	if(sbi->read_page) kfree(sbi->read_page);	if(sbi->uid) kfree(sbi->uid);	if(sbi->fragment) {		for(i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) 			if(sbi->fragment[i].data != NULL)				kfree(sbi->fragment[i].data);		kfree(sbi->fragment);	}	if(sbi->fragment_index) kfree(sbi->fragment_index);	sbi->block_cache = NULL;	sbi->uid = NULL;	sbi->read_data = NULL;	sbi->read_page = NULL;	sbi->fragment = NULL;	sbi->fragment_index = NULL;}static int __init init_squashfs_fs(void){	printk(KERN_INFO "Squashfs 2.1-r2 (released 2004/12/15) (C) 2002-2004 Phillip Lougher\n");	if(!(stream.workspace = (char *) vmalloc(zlib_inflate_workspacesize()))) {		ERROR("Failed to allocate zlib workspace\n");		return -ENOMEM;	}	return register_filesystem(&squashfs_fs_type);}static void __exit exit_squashfs_fs(void){	vfree(stream.workspace);	unregister_filesystem(&squashfs_fs_type);}EXPORT_NO_SYMBOLS;module_init(init_squashfs_fs);module_exit(exit_squashfs_fs);MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");MODULE_AUTHOR("Phillip Lougher <plougher@users.sourceforge.net>");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -