📄 inode.c
字号:
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 + -