mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[ext2fs] update ext2fs to latest
* Also drop nt_io_manager() as a function call and just use a direct ref to the manager.
This commit is contained in:
		
							parent
							
								
									fce645543f
								
							
						
					
					
						commit
						3056d54cc1
					
				
					 31 changed files with 1365 additions and 369 deletions
				
			
		|  | @ -53,6 +53,7 @@ | ||||||
|     <ClCompile Include="..\src\ext2fs\crc32c.c" /> |     <ClCompile Include="..\src\ext2fs\crc32c.c" /> | ||||||
|     <ClCompile Include="..\src\ext2fs\csum.c" /> |     <ClCompile Include="..\src\ext2fs\csum.c" /> | ||||||
|     <ClCompile Include="..\src\ext2fs\dirblock.c" /> |     <ClCompile Include="..\src\ext2fs\dirblock.c" /> | ||||||
|  |     <ClCompile Include="..\src\ext2fs\dirhash.c" /> | ||||||
|     <ClCompile Include="..\src\ext2fs\dir_iterate.c" /> |     <ClCompile Include="..\src\ext2fs\dir_iterate.c" /> | ||||||
|     <ClCompile Include="..\src\ext2fs\extent.c" /> |     <ClCompile Include="..\src\ext2fs\extent.c" /> | ||||||
|     <ClCompile Include="..\src\ext2fs\ext_attr.c" /> |     <ClCompile Include="..\src\ext2fs\ext_attr.c" /> | ||||||
|  |  | ||||||
|  | @ -162,6 +162,9 @@ | ||||||
|     <ClCompile Include="..\src\ext2fs\namei.c"> |     <ClCompile Include="..\src\ext2fs\namei.c"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\src\ext2fs\dirhash.c"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="..\src\ext2fs\ext2_fs.h"> |     <ClInclude Include="..\src\ext2fs\ext2_fs.h"> | ||||||
|  |  | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| noinst_LIBRARIES = libext2fs.a | noinst_LIBRARIES = libext2fs.a | ||||||
| 
 | 
 | ||||||
| libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c       \ | libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c bitmaps.c   \ | ||||||
| 	bitmaps.c bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c         \ | 	bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c crc32c.c          \ | ||||||
| 	crc32c.c csum.c dirblock.c dir_iterate.c extent.c ext_attr.c extent.c fallocate.c fileio.c       \ | 	csum.c dirblock.c dirhash.c dir_iterate.c extent.c ext_attr.c extent.c fallocate.c fileio.c      \ | ||||||
| 	freefs.c gen_bitmap.c gen_bitmap64.c get_num_dirs.c hashmap.c i_block.c ind_block.c initialize.c \ | 	freefs.c gen_bitmap.c gen_bitmap64.c get_num_dirs.c hashmap.c i_block.c ind_block.c initialize.c \ | ||||||
| 	inline.c inline_data.c inode.c io_manager.c link.c lookup.c mkdir.c mkjournal.c namei.c mmp.c    \ | 	inline.c inline_data.c inode.c io_manager.c link.c lookup.c mkdir.c mkjournal.c namei.c mmp.c    \ | ||||||
| 	newdir.c nt_io.c openfs.c punch.c rbtree.c read_bb.c rw_bitmaps.c sha512.c symlink.c valid_blk.c | 	newdir.c nt_io.c openfs.c punch.c rbtree.c read_bb.c rw_bitmaps.c sha512.c symlink.c valid_blk.c | ||||||
|  |  | ||||||
|  | @ -104,7 +104,7 @@ am_libext2fs_a_OBJECTS = libext2fs_a-alloc.$(OBJEXT) \ | ||||||
| 	libext2fs_a-block.$(OBJEXT) libext2fs_a-bmap.$(OBJEXT) \
 | 	libext2fs_a-block.$(OBJEXT) libext2fs_a-bmap.$(OBJEXT) \
 | ||||||
| 	libext2fs_a-closefs.$(OBJEXT) libext2fs_a-crc16.$(OBJEXT) \
 | 	libext2fs_a-closefs.$(OBJEXT) libext2fs_a-crc16.$(OBJEXT) \
 | ||||||
| 	libext2fs_a-crc32c.$(OBJEXT) libext2fs_a-csum.$(OBJEXT) \
 | 	libext2fs_a-crc32c.$(OBJEXT) libext2fs_a-csum.$(OBJEXT) \
 | ||||||
| 	libext2fs_a-dirblock.$(OBJEXT) \
 | 	libext2fs_a-dirblock.$(OBJEXT) libext2fs_a-dirhash.$(OBJEXT) \
 | ||||||
| 	libext2fs_a-dir_iterate.$(OBJEXT) libext2fs_a-extent.$(OBJEXT) \
 | 	libext2fs_a-dir_iterate.$(OBJEXT) libext2fs_a-extent.$(OBJEXT) \
 | ||||||
| 	libext2fs_a-ext_attr.$(OBJEXT) libext2fs_a-extent.$(OBJEXT) \
 | 	libext2fs_a-ext_attr.$(OBJEXT) libext2fs_a-extent.$(OBJEXT) \
 | ||||||
| 	libext2fs_a-fallocate.$(OBJEXT) libext2fs_a-fileio.$(OBJEXT) \
 | 	libext2fs_a-fallocate.$(OBJEXT) libext2fs_a-fileio.$(OBJEXT) \
 | ||||||
|  | @ -271,9 +271,9 @@ top_build_prefix = @top_build_prefix@ | ||||||
| top_builddir = @top_builddir@ | top_builddir = @top_builddir@ | ||||||
| top_srcdir = @top_srcdir@ | top_srcdir = @top_srcdir@ | ||||||
| noinst_LIBRARIES = libext2fs.a | noinst_LIBRARIES = libext2fs.a | ||||||
| libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c       \
 | libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c bitmaps.c   \
 | ||||||
| 	bitmaps.c bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c         \
 | 	bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c crc32c.c          \
 | ||||||
| 	crc32c.c csum.c dirblock.c dir_iterate.c extent.c ext_attr.c extent.c fallocate.c fileio.c       \
 | 	csum.c dirblock.c dirhash.c dir_iterate.c extent.c ext_attr.c extent.c fallocate.c fileio.c      \
 | ||||||
| 	freefs.c gen_bitmap.c gen_bitmap64.c get_num_dirs.c hashmap.c i_block.c ind_block.c initialize.c \
 | 	freefs.c gen_bitmap.c gen_bitmap64.c get_num_dirs.c hashmap.c i_block.c ind_block.c initialize.c \
 | ||||||
| 	inline.c inline_data.c inode.c io_manager.c link.c lookup.c mkdir.c mkjournal.c namei.c mmp.c    \
 | 	inline.c inline_data.c inode.c io_manager.c link.c lookup.c mkdir.c mkjournal.c namei.c mmp.c    \
 | ||||||
| 	newdir.c nt_io.c openfs.c punch.c rbtree.c read_bb.c rw_bitmaps.c sha512.c symlink.c valid_blk.c | 	newdir.c nt_io.c openfs.c punch.c rbtree.c read_bb.c rw_bitmaps.c sha512.c symlink.c valid_blk.c | ||||||
|  | @ -442,6 +442,12 @@ libext2fs_a-dirblock.o: dirblock.c | ||||||
| libext2fs_a-dirblock.obj: dirblock.c | libext2fs_a-dirblock.obj: dirblock.c | ||||||
| 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dirblock.obj `if test -f 'dirblock.c'; then $(CYGPATH_W) 'dirblock.c'; else $(CYGPATH_W) '$(srcdir)/dirblock.c'; fi` | 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dirblock.obj `if test -f 'dirblock.c'; then $(CYGPATH_W) 'dirblock.c'; else $(CYGPATH_W) '$(srcdir)/dirblock.c'; fi` | ||||||
| 
 | 
 | ||||||
|  | libext2fs_a-dirhash.o: dirhash.c | ||||||
|  | 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dirhash.o `test -f 'dirhash.c' || echo '$(srcdir)/'`dirhash.c | ||||||
|  | 
 | ||||||
|  | libext2fs_a-dirhash.obj: dirhash.c | ||||||
|  | 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dirhash.obj `if test -f 'dirhash.c'; then $(CYGPATH_W) 'dirhash.c'; else $(CYGPATH_W) '$(srcdir)/dirhash.c'; fi` | ||||||
|  | 
 | ||||||
| libext2fs_a-dir_iterate.o: dir_iterate.c | libext2fs_a-dir_iterate.o: dir_iterate.c | ||||||
| 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dir_iterate.o `test -f 'dir_iterate.c' || echo '$(srcdir)/'`dir_iterate.c | 	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libext2fs_a_CFLAGS) $(CFLAGS) -c -o libext2fs_a-dir_iterate.o `test -f 'dir_iterate.c' || echo '$(srcdir)/'`dir_iterate.c | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -85,6 +85,22 @@ blk64_t ext2fs_inode_i_blocks(ext2_filsys fs, | ||||||
| 		 (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0)); | 		 (__u64)inode->osd2.linux2.l_i_blocks_hi << 32 : 0)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Return the inode i_blocks in stat (512 byte) units | ||||||
|  |  */ | ||||||
|  | blk64_t ext2fs_get_stat_i_blocks(ext2_filsys fs, | ||||||
|  | 				 struct ext2_inode *inode) | ||||||
|  | { | ||||||
|  | 	blk64_t	ret = inode->i_blocks; | ||||||
|  | 
 | ||||||
|  | 	if (ext2fs_has_feature_huge_file(fs->super)) { | ||||||
|  | 		ret += ((long long) inode->osd2.linux2.l_i_blocks_hi) << 32; | ||||||
|  | 		if (inode->i_flags & EXT4_HUGE_FILE_FL) | ||||||
|  | 			ret *= (fs->blocksize / 512); | ||||||
|  | 	} | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Return the fs block count |  * Return the fs block count | ||||||
|  */ |  */ | ||||||
|  | @ -185,9 +201,42 @@ struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, | ||||||
| 					  struct opaque_ext2_group_desc *gdp, | 					  struct opaque_ext2_group_desc *gdp, | ||||||
| 					  dgrp_t group) | 					  dgrp_t group) | ||||||
| { | { | ||||||
| 	int desc_size = EXT2_DESC_SIZE(fs->super) & ~7; | 	struct ext2_group_desc *ret_gdp; | ||||||
|  | 	errcode_t	retval; | ||||||
|  | 	static char	*buf = 0; | ||||||
|  | 	static int	bufsize = 0; | ||||||
|  | 	blk64_t		blk; | ||||||
|  | 	int		desc_size = EXT2_DESC_SIZE(fs->super) & ~7; | ||||||
|  | 	int		desc_per_blk = EXT2_DESC_PER_BLOCK(fs->super); | ||||||
| 
 | 
 | ||||||
| 	return (struct ext2_group_desc *)((char *)gdp + group * desc_size); | 	if (group > fs->group_desc_count) | ||||||
|  | 		return NULL; | ||||||
|  | 	if (gdp) | ||||||
|  | 		return (struct ext2_group_desc *)((char *)gdp + | ||||||
|  | 						  group * desc_size); | ||||||
|  | 	/*
 | ||||||
|  | 	 * If fs->group_desc wasn't read in when the file system was | ||||||
|  | 	 * opened, then read it on demand here. | ||||||
|  | 	 */ | ||||||
|  | 	if (bufsize < fs->blocksize) | ||||||
|  | 		ext2fs_free_mem(&buf); | ||||||
|  | 	if (!buf) { | ||||||
|  | 		retval = ext2fs_get_mem(fs->blocksize, &buf); | ||||||
|  | 		if (retval) | ||||||
|  | 			return NULL; | ||||||
|  | 		bufsize = fs->blocksize; | ||||||
|  | 	} | ||||||
|  | 	blk = ext2fs_descriptor_block_loc2(fs, fs->super->s_first_data_block, | ||||||
|  | 					   group / desc_per_blk); | ||||||
|  | 	retval = io_channel_read_blk(fs->io, blk, 1, buf); | ||||||
|  | 	if (retval) | ||||||
|  | 		return NULL; | ||||||
|  | 	ret_gdp = (struct ext2_group_desc *) | ||||||
|  | 		(buf + ((group % desc_per_blk) * desc_size)); | ||||||
|  | #ifdef WORDS_BIGENDIAN | ||||||
|  | 	ext2fs_swap_group_desc2(fs, ret_gdp); | ||||||
|  | #endif | ||||||
|  | 	return ret_gdp; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Do the same but as an ext4 group desc for internal use here */ | /* Do the same but as an ext4 group desc for internal use here */ | ||||||
|  |  | ||||||
|  | @ -293,6 +293,11 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags) | ||||||
| 
 | 
 | ||||||
| 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | ||||||
| 
 | 
 | ||||||
|  | 	if ((fs->flags & EXT2_FLAG_SUPER_ONLY) == 0 && | ||||||
|  | 	    !ext2fs_has_feature_journal_dev(fs->super) && | ||||||
|  | 	    fs->group_desc == NULL) | ||||||
|  | 		return EXT2_ET_NO_GDESC; | ||||||
|  | 
 | ||||||
| 	fs_state = fs->super->s_state; | 	fs_state = fs->super->s_state; | ||||||
| 	feature_incompat = fs->super->s_feature_incompat; | 	feature_incompat = fs->super->s_feature_incompat; | ||||||
| 
 | 
 | ||||||
|  | @ -326,20 +331,24 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags) | ||||||
| #ifdef WORDS_BIGENDIAN | #ifdef WORDS_BIGENDIAN | ||||||
| 	retval = EXT2_ET_NO_MEMORY; | 	retval = EXT2_ET_NO_MEMORY; | ||||||
| 	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); | 	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); | ||||||
| 	if (retval) |  | ||||||
| 		goto errout; |  | ||||||
| 	retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, |  | ||||||
| 				  &group_shadow); |  | ||||||
| 	if (retval) | 	if (retval) | ||||||
| 		goto errout; | 		goto errout; | ||||||
| 	memcpy(super_shadow, fs->super, sizeof(struct ext2_super_block)); | 	memcpy(super_shadow, fs->super, sizeof(struct ext2_super_block)); | ||||||
| 	memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize * |  | ||||||
| 	       fs->desc_blocks); |  | ||||||
| 
 |  | ||||||
| 	ext2fs_swap_super(super_shadow); | 	ext2fs_swap_super(super_shadow); | ||||||
| 	for (j = 0; j < fs->group_desc_count; j++) { | 
 | ||||||
| 		gdp = ext2fs_group_desc(fs, group_shadow, j); | 	if (((fs->flags & EXT2_FLAG_SUPER_ONLY) == 0) && | ||||||
| 		ext2fs_swap_group_desc2(fs, gdp); | 	    !ext2fs_has_feature_journal_dev(fs->super)) { | ||||||
|  | 		retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, | ||||||
|  | 					  &group_shadow); | ||||||
|  | 		if (retval) | ||||||
|  | 			goto errout; | ||||||
|  | 		memcpy(group_shadow, fs->group_desc, (size_t) fs->blocksize * | ||||||
|  | 		       fs->desc_blocks); | ||||||
|  | 
 | ||||||
|  | 		for (j = 0; j < fs->group_desc_count; j++) { | ||||||
|  | 			gdp = ext2fs_group_desc(fs, group_shadow, j); | ||||||
|  | 			ext2fs_swap_group_desc2(fs, gdp); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| #else | #else | ||||||
| 	super_shadow = fs->super; | 	super_shadow = fs->super; | ||||||
|  |  | ||||||
|  | @ -266,14 +266,15 @@ static errcode_t __get_dirent_tail(ext2_filsys fs, | ||||||
| 	d = dirent; | 	d = dirent; | ||||||
| 	top = EXT2_DIRENT_TAIL(dirent, fs->blocksize); | 	top = EXT2_DIRENT_TAIL(dirent, fs->blocksize); | ||||||
| 
 | 
 | ||||||
| 	rec_len = translate(d->rec_len); | 	while ((void *) d < top) { | ||||||
| 	while (rec_len && !(rec_len & 0x3)) { |  | ||||||
| 		d = (struct ext2_dir_entry *)(((char *)d) + rec_len); |  | ||||||
| 		if ((void *)d >= top) |  | ||||||
| 			break; |  | ||||||
| 		rec_len = translate(d->rec_len); | 		rec_len = translate(d->rec_len); | ||||||
|  | 		if ((rec_len < 8) || (rec_len & 0x03)) | ||||||
|  | 			return EXT2_ET_DIR_CORRUPTED; | ||||||
|  | 		d = (struct ext2_dir_entry *)(((char *)d) + rec_len); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if ((char *)d > ((char *)dirent + fs->blocksize)) | ||||||
|  | 			return EXT2_ET_DIR_CORRUPTED; | ||||||
| 	if (d != top) | 	if (d != top) | ||||||
| 		return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; | 		return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; | ||||||
| 
 | 
 | ||||||
|  | @ -290,7 +291,8 @@ static errcode_t __get_dirent_tail(ext2_filsys fs, | ||||||
| 
 | 
 | ||||||
| int ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent) | int ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent) | ||||||
| { | { | ||||||
| 	return __get_dirent_tail(fs, dirent, NULL, 0) == 0; | 	return __get_dirent_tail(fs, dirent, NULL, 0) != | ||||||
|  | 		EXT2_ET_DIR_NO_SPACE_FOR_CSUM; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum, | static errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum, | ||||||
|  | @ -358,20 +360,31 @@ static errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum, | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, | errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, | ||||||
| 				struct ext2_dir_entry *dirent, | 			 struct ext2_dir_entry *dirent, | ||||||
| 				__u32 *crc, int count_offset, int count, | 			 __u32 *crc, struct ext2_dx_tail **ret_t) | ||||||
| 				struct ext2_dx_tail *t) |  | ||||||
| { | { | ||||||
| 	errcode_t retval; | 	errcode_t retval; | ||||||
| 	char *buf = (char *)dirent; | 	char *buf = (char *)dirent; | ||||||
| 	int size; | 	int size; | ||||||
| 	__u32 old_csum, gen; | 	__u32 gen, dummy_csum = 0; | ||||||
| 	struct ext2_inode inode; | 	struct ext2_inode inode; | ||||||
|  | 	struct ext2_dx_tail *t; | ||||||
|  | 	struct ext2_dx_countlimit *c; | ||||||
|  | 	int count_offset, limit, count; | ||||||
|  | 
 | ||||||
|  | 	retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	limit = ext2fs_le16_to_cpu(c->limit); | ||||||
|  | 	count = ext2fs_le16_to_cpu(c->count); | ||||||
|  | 	if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > | ||||||
|  | 	    fs->blocksize - sizeof(struct ext2_dx_tail)) | ||||||
|  | 		return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; | ||||||
|  | 	/* htree structs are accessed in LE order */ | ||||||
|  | 	t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); | ||||||
| 
 | 
 | ||||||
| 	size = count_offset + (count * sizeof(struct ext2_dx_entry)); | 	size = count_offset + (count * sizeof(struct ext2_dx_entry)); | ||||||
| 	old_csum = t->dt_checksum; |  | ||||||
| 	t->dt_checksum = 0; |  | ||||||
| 
 | 
 | ||||||
| 	retval = ext2fs_read_inode(fs, inum, &inode); | 	retval = ext2fs_read_inode(fs, inum, &inode); | ||||||
| 	if (retval) | 	if (retval) | ||||||
|  | @ -383,10 +396,11 @@ static errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, | ||||||
| 				sizeof(inum)); | 				sizeof(inum)); | ||||||
| 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); | 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); | ||||||
| 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); | 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); | ||||||
| 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)t, | 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)t, 4); | ||||||
| 				sizeof(struct ext2_dx_tail)); | 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)&dummy_csum, 4); | ||||||
| 	t->dt_checksum = old_csum; |  | ||||||
| 
 | 
 | ||||||
|  | 	if (ret_t) | ||||||
|  | 		*ret_t = t; | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -395,22 +409,9 @@ static int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum, | ||||||
| { | { | ||||||
| 	__u32 calculated; | 	__u32 calculated; | ||||||
| 	errcode_t retval; | 	errcode_t retval; | ||||||
| 	struct ext2_dx_countlimit *c; |  | ||||||
| 	struct ext2_dx_tail *t; | 	struct ext2_dx_tail *t; | ||||||
| 	int count_offset, limit, count; |  | ||||||
| 
 | 
 | ||||||
| 	retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); | 	retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, &t); | ||||||
| 	if (retval) |  | ||||||
| 		return 1; |  | ||||||
| 	limit = ext2fs_le16_to_cpu(c->limit); |  | ||||||
| 	count = ext2fs_le16_to_cpu(c->count); |  | ||||||
| 	if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > |  | ||||||
| 	    fs->blocksize - sizeof(struct ext2_dx_tail)) |  | ||||||
| 		return 0; |  | ||||||
| 	/* htree structs are accessed in LE order */ |  | ||||||
| 	t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); |  | ||||||
| 	retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, count_offset, |  | ||||||
| 				count, t); |  | ||||||
| 	if (retval) | 	if (retval) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
|  | @ -422,22 +423,9 @@ static errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum, | ||||||
| { | { | ||||||
| 	__u32 crc; | 	__u32 crc; | ||||||
| 	errcode_t retval = 0; | 	errcode_t retval = 0; | ||||||
| 	struct ext2_dx_countlimit *c; |  | ||||||
| 	struct ext2_dx_tail *t; | 	struct ext2_dx_tail *t; | ||||||
| 	int count_offset, limit, count; |  | ||||||
| 
 | 
 | ||||||
| 	retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); | 	retval = ext2fs_dx_csum(fs, inum, dirent, &crc, &t); | ||||||
| 	if (retval) |  | ||||||
| 		return retval; |  | ||||||
| 	limit = ext2fs_le16_to_cpu(c->limit); |  | ||||||
| 	count = ext2fs_le16_to_cpu(c->count); |  | ||||||
| 	if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > |  | ||||||
| 	    fs->blocksize - sizeof(struct ext2_dx_tail)) |  | ||||||
| 		return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; |  | ||||||
| 	t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); |  | ||||||
| 
 |  | ||||||
| 	/* htree structs are accessed in LE order */ |  | ||||||
| 	retval = ext2fs_dx_csum(fs, inum, dirent, &crc, count_offset, count, t); |  | ||||||
| 	if (retval) | 	if (retval) | ||||||
| 		return retval; | 		return retval; | ||||||
| 	t->dt_checksum = ext2fs_cpu_to_le32(crc); | 	t->dt_checksum = ext2fs_cpu_to_le32(crc); | ||||||
|  |  | ||||||
							
								
								
									
										307
									
								
								src/ext2fs/dirhash.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								src/ext2fs/dirhash.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,307 @@ | ||||||
|  | /*
 | ||||||
|  |  * dirhash.c -- Calculate the hash of a directory entry | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2001  Daniel Phillips | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2002 Theodore Ts'o. | ||||||
|  |  * | ||||||
|  |  * %Begin-Header% | ||||||
|  |  * This file may be redistributed under the terms of the GNU Library | ||||||
|  |  * General Public License, version 2. | ||||||
|  |  * %End-Header% | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "config.h" | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <limits.h> | ||||||
|  | 
 | ||||||
|  | #include "ext2_fs.h" | ||||||
|  | #include "ext2fs.h" | ||||||
|  | #include "ext2fsP.h" | ||||||
|  | 
 | ||||||
|  | #ifndef PATH_MAX | ||||||
|  | #define PATH_MAX 4096 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Keyed 32-bit hash function using TEA in a Davis-Meyer function | ||||||
|  |  *   H0 = Key | ||||||
|  |  *   Hi = E Mi(Hi-1) + Hi-1 | ||||||
|  |  * | ||||||
|  |  * (see Applied Cryptography, 2nd edition, p448). | ||||||
|  |  * | ||||||
|  |  * Jeremy Fitzhardinge <jeremy@zip.com.au> 1998 | ||||||
|  |  * | ||||||
|  |  * This code is made available under the terms of the GPL | ||||||
|  |  */ | ||||||
|  | #define DELTA 0x9E3779B9 | ||||||
|  | 
 | ||||||
|  | static void TEA_transform(__u32 buf[4], __u32 const in[]) | ||||||
|  | { | ||||||
|  | 	__u32	sum = 0; | ||||||
|  | 	__u32	b0 = buf[0], b1 = buf[1]; | ||||||
|  | 	__u32	a = in[0], b = in[1], c = in[2], d = in[3]; | ||||||
|  | 	int	n = 16; | ||||||
|  | 
 | ||||||
|  | 	do { | ||||||
|  | 		sum += DELTA; | ||||||
|  | 		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); | ||||||
|  | 		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); | ||||||
|  | 	} while(--n); | ||||||
|  | 
 | ||||||
|  | 	buf[0] += b0; | ||||||
|  | 	buf[1] += b1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* F, G and H are basic MD4 functions: selection, majority, parity */ | ||||||
|  | #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) | ||||||
|  | #define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z))) | ||||||
|  | #define H(x, y, z) ((x) ^ (y) ^ (z)) | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * The generic round function.  The application is so specific that | ||||||
|  |  * we don't bother protecting all the arguments with parens, as is generally | ||||||
|  |  * good macro practice, in favor of extra legibility. | ||||||
|  |  * Rotation is separate from addition to prevent recomputation | ||||||
|  |  */ | ||||||
|  | #define ROUND(f, a, b, c, d, x, s)	\ | ||||||
|  | 	(a += f(b, c, d) + x, a = (a << s) | (a >> (32-s))) | ||||||
|  | #define K1 0 | ||||||
|  | #define K2 013240474631UL | ||||||
|  | #define K3 015666365641UL | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Basic cut-down MD4 transform.  Returns only 32 bits of result. | ||||||
|  |  */ | ||||||
|  | static void halfMD4Transform (__u32 buf[4], __u32 const in[]) | ||||||
|  | { | ||||||
|  | 	__u32	a = buf[0], b = buf[1], c = buf[2], d = buf[3]; | ||||||
|  | 
 | ||||||
|  | 	/* Round 1 */ | ||||||
|  | 	ROUND(F, a, b, c, d, in[0] + K1,  3); | ||||||
|  | 	ROUND(F, d, a, b, c, in[1] + K1,  7); | ||||||
|  | 	ROUND(F, c, d, a, b, in[2] + K1, 11); | ||||||
|  | 	ROUND(F, b, c, d, a, in[3] + K1, 19); | ||||||
|  | 	ROUND(F, a, b, c, d, in[4] + K1,  3); | ||||||
|  | 	ROUND(F, d, a, b, c, in[5] + K1,  7); | ||||||
|  | 	ROUND(F, c, d, a, b, in[6] + K1, 11); | ||||||
|  | 	ROUND(F, b, c, d, a, in[7] + K1, 19); | ||||||
|  | 
 | ||||||
|  | 	/* Round 2 */ | ||||||
|  | 	ROUND(G, a, b, c, d, in[1] + K2,  3); | ||||||
|  | 	ROUND(G, d, a, b, c, in[3] + K2,  5); | ||||||
|  | 	ROUND(G, c, d, a, b, in[5] + K2,  9); | ||||||
|  | 	ROUND(G, b, c, d, a, in[7] + K2, 13); | ||||||
|  | 	ROUND(G, a, b, c, d, in[0] + K2,  3); | ||||||
|  | 	ROUND(G, d, a, b, c, in[2] + K2,  5); | ||||||
|  | 	ROUND(G, c, d, a, b, in[4] + K2,  9); | ||||||
|  | 	ROUND(G, b, c, d, a, in[6] + K2, 13); | ||||||
|  | 
 | ||||||
|  | 	/* Round 3 */ | ||||||
|  | 	ROUND(H, a, b, c, d, in[3] + K3,  3); | ||||||
|  | 	ROUND(H, d, a, b, c, in[7] + K3,  9); | ||||||
|  | 	ROUND(H, c, d, a, b, in[2] + K3, 11); | ||||||
|  | 	ROUND(H, b, c, d, a, in[6] + K3, 15); | ||||||
|  | 	ROUND(H, a, b, c, d, in[1] + K3,  3); | ||||||
|  | 	ROUND(H, d, a, b, c, in[5] + K3,  9); | ||||||
|  | 	ROUND(H, c, d, a, b, in[0] + K3, 11); | ||||||
|  | 	ROUND(H, b, c, d, a, in[4] + K3, 15); | ||||||
|  | 
 | ||||||
|  | 	buf[0] += a; | ||||||
|  | 	buf[1] += b; | ||||||
|  | 	buf[2] += c; | ||||||
|  | 	buf[3] += d; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #undef ROUND | ||||||
|  | #undef F | ||||||
|  | #undef G | ||||||
|  | #undef H | ||||||
|  | #undef K1 | ||||||
|  | #undef K2 | ||||||
|  | #undef K3 | ||||||
|  | 
 | ||||||
|  | /* The old legacy hash */ | ||||||
|  | static ext2_dirhash_t dx_hack_hash (const char *name, int len, | ||||||
|  | 				    int unsigned_flag) | ||||||
|  | { | ||||||
|  | 	__u32 hash, hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; | ||||||
|  | 	const unsigned char *ucp = (const unsigned char *) name; | ||||||
|  | 	const signed char *scp = (const signed char *) name; | ||||||
|  | 	int c; | ||||||
|  | 
 | ||||||
|  | 	while (len--) { | ||||||
|  | 		if (unsigned_flag) | ||||||
|  | 			c = (int) *ucp++; | ||||||
|  | 		else | ||||||
|  | 			c = (int) *scp++; | ||||||
|  | 		hash = hash1 + (hash0 ^ (c * 7152373)); | ||||||
|  | 
 | ||||||
|  | 		if (hash & 0x80000000) hash -= 0x7fffffff; | ||||||
|  | 		hash1 = hash0; | ||||||
|  | 		hash0 = hash; | ||||||
|  | 	} | ||||||
|  | 	return (hash0 << 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void str2hashbuf(const char *msg, int len, __u32 *buf, int num, | ||||||
|  | 			int unsigned_flag) | ||||||
|  | { | ||||||
|  | 	__u32	pad, val; | ||||||
|  | 	int	i, c; | ||||||
|  | 	const unsigned char *ucp = (const unsigned char *) msg; | ||||||
|  | 	const signed char *scp = (const signed char *) msg; | ||||||
|  | 
 | ||||||
|  | 	pad = (__u32)len | ((__u32)len << 8); | ||||||
|  | 	pad |= pad << 16; | ||||||
|  | 
 | ||||||
|  | 	val = pad; | ||||||
|  | 	if (len > num*4) | ||||||
|  | 		len = num * 4; | ||||||
|  | 	for (i=0; i < len; i++) { | ||||||
|  | 		if (unsigned_flag) | ||||||
|  | 			c = (int) ucp[i]; | ||||||
|  | 		else | ||||||
|  | 			c = (int) scp[i]; | ||||||
|  | 
 | ||||||
|  | 		val = c + (val << 8); | ||||||
|  | 		if ((i % 4) == 3) { | ||||||
|  | 			*buf++ = val; | ||||||
|  | 			val = pad; | ||||||
|  | 			num--; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (--num >= 0) | ||||||
|  | 		*buf++ = val; | ||||||
|  | 	while (--num >= 0) | ||||||
|  | 		*buf++ = pad; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Returns the hash of a filename.  If len is 0 and name is NULL, then | ||||||
|  |  * this function can be used to test whether or not a hash version is | ||||||
|  |  * supported. | ||||||
|  |  * | ||||||
|  |  * The seed is an 4 longword (32 bits) "secret" which can be used to | ||||||
|  |  * uniquify a hash.  If the seed is all zero's, then some default seed | ||||||
|  |  * may be used. | ||||||
|  |  * | ||||||
|  |  * A particular hash version specifies whether or not the seed is | ||||||
|  |  * represented, and whether or not the returned hash is 32 bits or 64 | ||||||
|  |  * bits.  32 bit hashes will return 0 for the minor hash. | ||||||
|  |  * | ||||||
|  |  * This function doesn't do any normalization or casefolding of the | ||||||
|  |  * input string.  To take charset encoding into account, use | ||||||
|  |  * ext2fs_dirhash2. | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  | errcode_t ext2fs_dirhash(int version, const char *name, int len, | ||||||
|  | 			 const __u32 *seed, | ||||||
|  | 			 ext2_dirhash_t *ret_hash, | ||||||
|  | 			 ext2_dirhash_t *ret_minor_hash) | ||||||
|  | { | ||||||
|  | 	__u32	hash; | ||||||
|  | 	__u32	minor_hash = 0; | ||||||
|  | 	const char	*p; | ||||||
|  | 	int		i; | ||||||
|  | 	__u32 		in[8], buf[4]; | ||||||
|  | 	int		unsigned_flag = 0; | ||||||
|  | 
 | ||||||
|  | 	/* Initialize the default seed for the hash checksum functions */ | ||||||
|  | 	buf[0] = 0x67452301; | ||||||
|  | 	buf[1] = 0xefcdab89; | ||||||
|  | 	buf[2] = 0x98badcfe; | ||||||
|  | 	buf[3] = 0x10325476; | ||||||
|  | 
 | ||||||
|  | 	/* Check to see if the seed is all zero's */ | ||||||
|  | 	if (seed) { | ||||||
|  | 		for (i=0; i < 4; i++) { | ||||||
|  | 			if (seed[i]) | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 		if (i < 4) | ||||||
|  | 			memcpy(buf, seed, sizeof(buf)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (version) { | ||||||
|  | 	case EXT2_HASH_LEGACY_UNSIGNED: | ||||||
|  | 		unsigned_flag++; | ||||||
|  | 		/* fallthrough */ | ||||||
|  | 	case EXT2_HASH_LEGACY: | ||||||
|  | 		hash = dx_hack_hash(name, len, unsigned_flag); | ||||||
|  | 		break; | ||||||
|  | 	case EXT2_HASH_HALF_MD4_UNSIGNED: | ||||||
|  | 		unsigned_flag++; | ||||||
|  | 		/* fallthrough */ | ||||||
|  | 	case EXT2_HASH_HALF_MD4: | ||||||
|  | 		p = name; | ||||||
|  | 		while (len > 0) { | ||||||
|  | 			str2hashbuf(p, len, in, 8, unsigned_flag); | ||||||
|  | 			halfMD4Transform(buf, in); | ||||||
|  | 			len -= 32; | ||||||
|  | 			p += 32; | ||||||
|  | 		} | ||||||
|  | 		minor_hash = buf[2]; | ||||||
|  | 		hash = buf[1]; | ||||||
|  | 		break; | ||||||
|  | 	case EXT2_HASH_TEA_UNSIGNED: | ||||||
|  | 		unsigned_flag++; | ||||||
|  | 		/* fallthrough */ | ||||||
|  | 	case EXT2_HASH_TEA: | ||||||
|  | 		p = name; | ||||||
|  | 		while (len > 0) { | ||||||
|  | 			str2hashbuf(p, len, in, 4, unsigned_flag); | ||||||
|  | 			TEA_transform(buf, in); | ||||||
|  | 			len -= 16; | ||||||
|  | 			p += 16; | ||||||
|  | 		} | ||||||
|  | 		hash = buf[0]; | ||||||
|  | 		minor_hash = buf[1]; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		*ret_hash = 0; | ||||||
|  | 		return EXT2_ET_DIRHASH_UNSUPP; | ||||||
|  | 	} | ||||||
|  | 	*ret_hash = hash & ~1; | ||||||
|  | 	if (ret_minor_hash) | ||||||
|  | 		*ret_minor_hash = minor_hash; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Returns the hash of a filename considering normalization and | ||||||
|  |  * casefolding.  This is a wrapper around ext2fs_dirhash with string | ||||||
|  |  * encoding support based on the nls_table and the flags. Check | ||||||
|  |  * ext2fs_dirhash for documentation on the input and output parameters. | ||||||
|  |  */ | ||||||
|  | errcode_t ext2fs_dirhash2(int version, const char *name, int len, | ||||||
|  | 			  const struct ext2fs_nls_table *charset, | ||||||
|  | 			  int hash_flags, const __u32 *seed, | ||||||
|  | 			  ext2_dirhash_t *ret_hash, | ||||||
|  | 			  ext2_dirhash_t *ret_minor_hash) | ||||||
|  | { | ||||||
|  | 	errcode_t r; | ||||||
|  | 	int dlen; | ||||||
|  | 
 | ||||||
|  | 	if (len && charset && (hash_flags & EXT4_CASEFOLD_FL)) { | ||||||
|  | 		char buff[PATH_MAX]; | ||||||
|  | 
 | ||||||
|  | 		dlen = charset->ops->casefold(charset, | ||||||
|  | 			      (const unsigned char *) name, len, | ||||||
|  | 			      (unsigned char *) buff, sizeof(buff)); | ||||||
|  | 		if (dlen < 0) { | ||||||
|  | 			if (dlen == -EINVAL) | ||||||
|  | 				goto opaque_seq; | ||||||
|  | 
 | ||||||
|  | 			return dlen; | ||||||
|  | 		} | ||||||
|  | 		r = ext2fs_dirhash(version, buff, dlen, seed, ret_hash, | ||||||
|  | 				   ret_minor_hash); | ||||||
|  | 		return r; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | opaque_seq: | ||||||
|  | 	return ext2fs_dirhash(version, name, len, seed, ret_hash, | ||||||
|  | 			      ret_minor_hash); | ||||||
|  | } | ||||||
|  | @ -184,6 +184,7 @@ | ||||||
| #define EXT2_ET_CORRUPT_JOURNAL_SB               (2133571504L) | #define EXT2_ET_CORRUPT_JOURNAL_SB               (2133571504L) | ||||||
| #define EXT2_ET_INODE_CORRUPTED                  (2133571505L) | #define EXT2_ET_INODE_CORRUPTED                  (2133571505L) | ||||||
| #define EXT2_ET_EA_INODE_CORRUPTED               (2133571506L) | #define EXT2_ET_EA_INODE_CORRUPTED               (2133571506L) | ||||||
|  | #define EXT2_ET_NO_GDESC                         (2133571507L) | ||||||
| extern const struct error_table et_ext2_error_table; | extern const struct error_table et_ext2_error_table; | ||||||
| extern void initialize_ext2_error_table(void); | extern void initialize_ext2_error_table(void); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -351,6 +351,7 @@ struct ext2_dx_tail { | ||||||
| /* EXT4_EOFBLOCKS_FL 0x00400000 was here */ | /* EXT4_EOFBLOCKS_FL 0x00400000 was here */ | ||||||
| #define FS_NOCOW_FL			0x00800000 /* Do not cow file */ | #define FS_NOCOW_FL			0x00800000 /* Do not cow file */ | ||||||
| #define EXT4_SNAPFILE_FL		0x01000000  /* Inode is a snapshot */ | #define EXT4_SNAPFILE_FL		0x01000000  /* Inode is a snapshot */ | ||||||
|  | #define FS_DAX_FL			0x02000000 /* Inode is DAX */ | ||||||
| #define EXT4_SNAPFILE_DELETED_FL	0x04000000  /* Snapshot is being deleted */ | #define EXT4_SNAPFILE_DELETED_FL	0x04000000  /* Snapshot is being deleted */ | ||||||
| #define EXT4_SNAPFILE_SHRUNK_FL		0x08000000  /* Snapshot shrink has completed */ | #define EXT4_SNAPFILE_SHRUNK_FL		0x08000000  /* Snapshot shrink has completed */ | ||||||
| #define EXT4_INLINE_DATA_FL		0x10000000 /* Inode has inline data */ | #define EXT4_INLINE_DATA_FL		0x10000000 /* Inode has inline data */ | ||||||
|  | @ -698,8 +699,8 @@ struct ext2_super_block { | ||||||
| /*060*/	__u32	s_feature_incompat;	/* incompatible feature set */ | /*060*/	__u32	s_feature_incompat;	/* incompatible feature set */ | ||||||
| 	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */ | 	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */ | ||||||
| /*068*/	__u8	s_uuid[16];		/* 128-bit uuid for volume */ | /*068*/	__u8	s_uuid[16];		/* 128-bit uuid for volume */ | ||||||
| /*078*/	char	s_volume_name[EXT2_LABEL_LEN];	/* volume name */ | /*078*/	__u8	s_volume_name[EXT2_LABEL_LEN];	/* volume name, no NUL? */ | ||||||
| /*088*/	char	s_last_mounted[64];	/* directory where last mounted */ | /*088*/	__u8	s_last_mounted[64];	/* directory last mounted on, no NUL? */ | ||||||
| /*0c8*/	__u32	s_algorithm_usage_bitmap; /* For compression */ | /*0c8*/	__u32	s_algorithm_usage_bitmap; /* For compression */ | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Performance hints.  Directory preallocation should only | 	 * Performance hints.  Directory preallocation should only | ||||||
|  | @ -747,18 +748,18 @@ struct ext2_super_block { | ||||||
| 	__u32	s_first_error_time;	/* first time an error happened */ | 	__u32	s_first_error_time;	/* first time an error happened */ | ||||||
| 	__u32	s_first_error_ino;	/* inode involved in first error */ | 	__u32	s_first_error_ino;	/* inode involved in first error */ | ||||||
| /*1a0*/	__u64	s_first_error_block;	/* block involved in first error */ | /*1a0*/	__u64	s_first_error_block;	/* block involved in first error */ | ||||||
| 	__u8	s_first_error_func[32];	/* function where the error happened */ | 	__u8	s_first_error_func[32];	/* function where error hit, no NUL? */ | ||||||
| /*1c8*/	__u32	s_first_error_line;	/* line number where error happened */ | /*1c8*/	__u32	s_first_error_line;	/* line number where error happened */ | ||||||
| 	__u32	s_last_error_time;	/* most recent time of an error */ | 	__u32	s_last_error_time;	/* most recent time of an error */ | ||||||
| /*1d0*/	__u32	s_last_error_ino;	/* inode involved in last error */ | /*1d0*/	__u32	s_last_error_ino;	/* inode involved in last error */ | ||||||
| 	__u32	s_last_error_line;	/* line number where error happened */ | 	__u32	s_last_error_line;	/* line number where error happened */ | ||||||
| 	__u64	s_last_error_block;	/* block involved of last error */ | 	__u64	s_last_error_block;	/* block involved of last error */ | ||||||
| /*1e0*/	__u8	s_last_error_func[32];	/* function where the error happened */ | /*1e0*/	__u8	s_last_error_func[32];	/* function where error hit, no NUL? */ | ||||||
| #define EXT4_S_ERR_END ext4_offsetof(struct ext2_super_block, s_mount_opts) | #define EXT4_S_ERR_END ext4_offsetof(struct ext2_super_block, s_mount_opts) | ||||||
| /*200*/	__u8	s_mount_opts[64]; | /*200*/	__u8	s_mount_opts[64];	/* default mount options, no NUL? */ | ||||||
| /*240*/	__u32	s_usr_quota_inum;	/* inode number of user quota file */ | /*240*/	__u32	s_usr_quota_inum;	/* inode number of user quota file */ | ||||||
| 	__u32	s_grp_quota_inum;	/* inode number of group quota file */ | 	__u32	s_grp_quota_inum;	/* inode number of group quota file */ | ||||||
| 	__u32	s_overhead_blocks;	/* overhead blocks/clusters in fs */ | 	__u32	s_overhead_clusters;	/* overhead blocks/clusters in fs */ | ||||||
| /*24c*/	__u32	s_backup_bgs[2];	/* If sparse_super2 enabled */ | /*24c*/	__u32	s_backup_bgs[2];	/* If sparse_super2 enabled */ | ||||||
| /*254*/	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */ | /*254*/	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */ | ||||||
| /*258*/	__u8	s_encrypt_pw_salt[16];	/* Salt used for string2key algorithm */ | /*258*/	__u8	s_encrypt_pw_salt[16];	/* Salt used for string2key algorithm */ | ||||||
|  | @ -771,7 +772,8 @@ struct ext2_super_block { | ||||||
| 	__u8	s_lastcheck_hi; | 	__u8	s_lastcheck_hi; | ||||||
| 	__u8	s_first_error_time_hi; | 	__u8	s_first_error_time_hi; | ||||||
| 	__u8	s_last_error_time_hi; | 	__u8	s_last_error_time_hi; | ||||||
| 	__u8	s_pad[2]; | 	__u8	s_first_error_errcode; | ||||||
|  | 	__u8    s_last_error_errcode; | ||||||
| /*27c*/ __le16	s_encoding;		/* Filename charset encoding */ | /*27c*/ __le16	s_encoding;		/* Filename charset encoding */ | ||||||
| 	__le16	s_encoding_flags;	/* Filename charset encoding flags */ | 	__le16	s_encoding_flags;	/* Filename charset encoding flags */ | ||||||
| 	__le32	s_reserved[95];		/* Padding to the end of the block */ | 	__le32	s_reserved[95];		/* Padding to the end of the block */ | ||||||
|  | @ -779,6 +781,7 @@ struct ext2_super_block { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START) | #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START) | ||||||
|  | #define EXT2_LEN_STR(buf) (int)sizeof(buf), (char *)buf | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Codes for operating systems |  * Codes for operating systems | ||||||
|  | @ -828,6 +831,8 @@ struct ext2_super_block { | ||||||
| /* #define EXT2_FEATURE_COMPAT_EXCLUDE_INODE	0x0080 not used, legacy */ | /* #define EXT2_FEATURE_COMPAT_EXCLUDE_INODE	0x0080 not used, legacy */ | ||||||
| #define EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP	0x0100 | #define EXT2_FEATURE_COMPAT_EXCLUDE_BITMAP	0x0100 | ||||||
| #define EXT4_FEATURE_COMPAT_SPARSE_SUPER2	0x0200 | #define EXT4_FEATURE_COMPAT_SPARSE_SUPER2	0x0200 | ||||||
|  | #define EXT4_FEATURE_COMPAT_FAST_COMMIT		0x0400 | ||||||
|  | #define EXT4_FEATURE_COMPAT_STABLE_INODES	0x0800 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001 | #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001 | ||||||
|  | @ -867,7 +872,7 @@ struct ext2_super_block { | ||||||
| #define EXT4_FEATURE_INCOMPAT_LARGEDIR		0x4000 /* >2GB or 3-lvl htree */ | #define EXT4_FEATURE_INCOMPAT_LARGEDIR		0x4000 /* >2GB or 3-lvl htree */ | ||||||
| #define EXT4_FEATURE_INCOMPAT_INLINE_DATA	0x8000 /* data in inode */ | #define EXT4_FEATURE_INCOMPAT_INLINE_DATA	0x8000 /* data in inode */ | ||||||
| #define EXT4_FEATURE_INCOMPAT_ENCRYPT		0x10000 | #define EXT4_FEATURE_INCOMPAT_ENCRYPT		0x10000 | ||||||
| #define EXT4_FEATURE_INCOMPAT_FNAME_ENCODING	0x20000 | #define EXT4_FEATURE_INCOMPAT_CASEFOLD		0x20000 | ||||||
| 
 | 
 | ||||||
| #define EXT4_FEATURE_COMPAT_FUNCS(name, ver, flagname) \ | #define EXT4_FEATURE_COMPAT_FUNCS(name, ver, flagname) \ | ||||||
| static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \ | static inline int ext2fs_has_feature_##name(struct ext2_super_block *sb) \ | ||||||
|  | @ -929,6 +934,8 @@ EXT4_FEATURE_COMPAT_FUNCS(dir_index,		2, DIR_INDEX) | ||||||
| EXT4_FEATURE_COMPAT_FUNCS(lazy_bg,		2, LAZY_BG) | EXT4_FEATURE_COMPAT_FUNCS(lazy_bg,		2, LAZY_BG) | ||||||
| EXT4_FEATURE_COMPAT_FUNCS(exclude_bitmap,	2, EXCLUDE_BITMAP) | EXT4_FEATURE_COMPAT_FUNCS(exclude_bitmap,	2, EXCLUDE_BITMAP) | ||||||
| EXT4_FEATURE_COMPAT_FUNCS(sparse_super2,	4, SPARSE_SUPER2) | EXT4_FEATURE_COMPAT_FUNCS(sparse_super2,	4, SPARSE_SUPER2) | ||||||
|  | EXT4_FEATURE_COMPAT_FUNCS(fast_commit,		4, FAST_COMMIT) | ||||||
|  | EXT4_FEATURE_COMPAT_FUNCS(stable_inodes,	4, STABLE_INODES) | ||||||
| 
 | 
 | ||||||
| EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super,	2, SPARSE_SUPER) | EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super,	2, SPARSE_SUPER) | ||||||
| EXT4_FEATURE_RO_COMPAT_FUNCS(large_file,	2, LARGE_FILE) | EXT4_FEATURE_RO_COMPAT_FUNCS(large_file,	2, LARGE_FILE) | ||||||
|  | @ -961,7 +968,7 @@ EXT4_FEATURE_INCOMPAT_FUNCS(csum_seed,		4, CSUM_SEED) | ||||||
| EXT4_FEATURE_INCOMPAT_FUNCS(largedir,		4, LARGEDIR) | EXT4_FEATURE_INCOMPAT_FUNCS(largedir,		4, LARGEDIR) | ||||||
| EXT4_FEATURE_INCOMPAT_FUNCS(inline_data,	4, INLINE_DATA) | EXT4_FEATURE_INCOMPAT_FUNCS(inline_data,	4, INLINE_DATA) | ||||||
| EXT4_FEATURE_INCOMPAT_FUNCS(encrypt,		4, ENCRYPT) | EXT4_FEATURE_INCOMPAT_FUNCS(encrypt,		4, ENCRYPT) | ||||||
| EXT4_FEATURE_INCOMPAT_FUNCS(fname_encoding,	4, FNAME_ENCODING) | EXT4_FEATURE_INCOMPAT_FUNCS(casefold,		4, CASEFOLD) | ||||||
| 
 | 
 | ||||||
| #define EXT2_FEATURE_COMPAT_SUPP	0 | #define EXT2_FEATURE_COMPAT_SUPP	0 | ||||||
| #define EXT2_FEATURE_INCOMPAT_SUPP    (EXT2_FEATURE_INCOMPAT_FILETYPE| \ | #define EXT2_FEATURE_INCOMPAT_SUPP    (EXT2_FEATURE_INCOMPAT_FILETYPE| \ | ||||||
|  | @ -1112,9 +1119,9 @@ struct ext2_dir_entry_tail { | ||||||
| struct mmp_struct { | struct mmp_struct { | ||||||
| 	__u32	mmp_magic;		/* Magic number for MMP */ | 	__u32	mmp_magic;		/* Magic number for MMP */ | ||||||
| 	__u32	mmp_seq;		/* Sequence no. updated periodically */ | 	__u32	mmp_seq;		/* Sequence no. updated periodically */ | ||||||
| 	__u64	mmp_time;		/* Time last updated */ | 	__u64	mmp_time;		/* Time last updated (seconds) */ | ||||||
| 	char	mmp_nodename[64];	/* Node which last updated MMP block */ | 	__u8	mmp_nodename[64];	/* Node updating MMP block, no NUL? */ | ||||||
| 	char	mmp_bdevname[32];	/* Bdev which last updated MMP block */ | 	__u8	mmp_bdevname[32];	/* Bdev updating MMP block, no NUL? */ | ||||||
| 	__u16	mmp_check_interval;	/* Changed mmp_check_interval */ | 	__u16	mmp_check_interval;	/* Changed mmp_check_interval */ | ||||||
| 	__u16	mmp_pad1; | 	__u16	mmp_pad1; | ||||||
| 	__u32	mmp_pad2[226]; | 	__u32	mmp_pad2[226]; | ||||||
|  | @ -1146,11 +1153,8 @@ struct mmp_struct { | ||||||
|  */ |  */ | ||||||
| #define EXT4_INLINE_DATA_DOTDOT_SIZE	(4) | #define EXT4_INLINE_DATA_DOTDOT_SIZE	(4) | ||||||
| 
 | 
 | ||||||
| #define EXT4_ENC_ASCII		0 | #define EXT4_ENC_UTF8_12_1	1 | ||||||
| #define EXT4_ENC_UTF8_11_0	1 |  | ||||||
| 
 | 
 | ||||||
| #define EXT4_ENC_STRICT_MODE_FL			(1 << 0) /* Reject invalid sequences */ | #define EXT4_ENC_STRICT_MODE_FL			(1 << 0) /* Reject invalid sequences */ | ||||||
| #define EXT4_UTF8_NORMALIZATION_TYPE_NFKD	(1 << 1) |  | ||||||
| #define EXT4_UTF8_CASEFOLD_TYPE_NFKDCF		(1 << 4) |  | ||||||
| 
 | 
 | ||||||
| #endif	/* _LINUX_EXT2_FS_H */ | #endif	/* _LINUX_EXT2_FS_H */ | ||||||
|  |  | ||||||
|  | @ -198,6 +198,8 @@ typedef struct ext2_file *ext2_file_t; | ||||||
| #define EXT2_FLAG_IGNORE_CSUM_ERRORS	0x200000 | #define EXT2_FLAG_IGNORE_CSUM_ERRORS	0x200000 | ||||||
| #define EXT2_FLAG_SHARE_DUP		0x400000 | #define EXT2_FLAG_SHARE_DUP		0x400000 | ||||||
| #define EXT2_FLAG_IGNORE_SB_ERRORS	0x800000 | #define EXT2_FLAG_IGNORE_SB_ERRORS	0x800000 | ||||||
|  | #define EXT2_FLAG_BBITMAP_TAIL_PROBLEM	0x1000000 | ||||||
|  | #define EXT2_FLAG_IBITMAP_TAIL_PROBLEM	0x2000000 | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Special flag in the ext2 inode i_flag field that means that this is |  * Special flag in the ext2 inode i_flag field that means that this is | ||||||
|  | @ -302,7 +304,7 @@ struct struct_ext2_filsys { | ||||||
| 	/* hashmap for SHA of data blocks */ | 	/* hashmap for SHA of data blocks */ | ||||||
| 	struct ext2fs_hashmap* block_sha_map; | 	struct ext2fs_hashmap* block_sha_map; | ||||||
| 
 | 
 | ||||||
| 	const struct nls_table *encoding; | 	const struct ext2fs_nls_table *encoding; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #if EXT2_FLAT_INCLUDES | #if EXT2_FLAT_INCLUDES | ||||||
|  | @ -603,7 +605,9 @@ typedef struct ext2_icount *ext2_icount_t; | ||||||
| 					 EXT2_FEATURE_COMPAT_RESIZE_INODE|\ | 					 EXT2_FEATURE_COMPAT_RESIZE_INODE|\ | ||||||
| 					 EXT2_FEATURE_COMPAT_DIR_INDEX|\ | 					 EXT2_FEATURE_COMPAT_DIR_INDEX|\ | ||||||
| 					 EXT2_FEATURE_COMPAT_EXT_ATTR|\ | 					 EXT2_FEATURE_COMPAT_EXT_ATTR|\ | ||||||
| 					 EXT4_FEATURE_COMPAT_SPARSE_SUPER2) | 					 EXT4_FEATURE_COMPAT_SPARSE_SUPER2|\ | ||||||
|  | 					 EXT4_FEATURE_COMPAT_FAST_COMMIT|\ | ||||||
|  | 					 EXT4_FEATURE_COMPAT_STABLE_INODES) | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_MMP | #ifdef CONFIG_MMP | ||||||
| #define EXT4_LIB_INCOMPAT_MMP		EXT4_FEATURE_INCOMPAT_MMP | #define EXT4_LIB_INCOMPAT_MMP		EXT4_FEATURE_INCOMPAT_MMP | ||||||
|  | @ -622,7 +626,7 @@ typedef struct ext2_icount *ext2_icount_t; | ||||||
| 					 EXT4_FEATURE_INCOMPAT_64BIT|\ | 					 EXT4_FEATURE_INCOMPAT_64BIT|\ | ||||||
| 					 EXT4_FEATURE_INCOMPAT_INLINE_DATA|\ | 					 EXT4_FEATURE_INCOMPAT_INLINE_DATA|\ | ||||||
| 					 EXT4_FEATURE_INCOMPAT_ENCRYPT|\ | 					 EXT4_FEATURE_INCOMPAT_ENCRYPT|\ | ||||||
| 					 EXT4_FEATURE_INCOMPAT_FNAME_ENCODING|\ | 					 EXT4_FEATURE_INCOMPAT_CASEFOLD|\ | ||||||
| 					 EXT4_FEATURE_INCOMPAT_CSUM_SEED|\ | 					 EXT4_FEATURE_INCOMPAT_CSUM_SEED|\ | ||||||
| 					 EXT4_FEATURE_INCOMPAT_LARGEDIR) | 					 EXT4_FEATURE_INCOMPAT_LARGEDIR) | ||||||
| 
 | 
 | ||||||
|  | @ -900,7 +904,9 @@ extern int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group); | ||||||
| extern blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs, | extern blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs, | ||||||
| 					 struct ext2_inode *inode); | 					 struct ext2_inode *inode); | ||||||
| extern blk64_t ext2fs_inode_i_blocks(ext2_filsys fs, | extern blk64_t ext2fs_inode_i_blocks(ext2_filsys fs, | ||||||
| 					 struct ext2_inode *inode); | 				     struct ext2_inode *inode); | ||||||
|  | extern blk64_t ext2fs_get_stat_i_blocks(ext2_filsys fs, | ||||||
|  | 					struct ext2_inode *inode); | ||||||
| extern blk64_t ext2fs_blocks_count(struct ext2_super_block *super); | extern blk64_t ext2fs_blocks_count(struct ext2_super_block *super); | ||||||
| extern void ext2fs_blocks_count_set(struct ext2_super_block *super, | extern void ext2fs_blocks_count_set(struct ext2_super_block *super, | ||||||
| 				    blk64_t blk); | 				    blk64_t blk); | ||||||
|  | @ -1072,6 +1078,9 @@ extern errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs, | ||||||
| 					  struct ext2_dir_entry *dirent, | 					  struct ext2_dir_entry *dirent, | ||||||
| 					  struct ext2_dx_countlimit **cc, | 					  struct ext2_dx_countlimit **cc, | ||||||
| 					  int *offset); | 					  int *offset); | ||||||
|  | extern errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, | ||||||
|  | 				struct ext2_dir_entry *dirent, | ||||||
|  | 				__u32 *crc, struct ext2_dx_tail **ret_t); | ||||||
| extern errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, | extern errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, | ||||||
| 					      ext2_ino_t inum, | 					      ext2_ino_t inum, | ||||||
| 					      struct ext3_extent_header *eh); | 					      struct ext3_extent_header *eh); | ||||||
|  | @ -1181,7 +1190,7 @@ extern errcode_t ext2fs_dirhash(int version, const char *name, int len, | ||||||
| 				ext2_dirhash_t *ret_minor_hash); | 				ext2_dirhash_t *ret_minor_hash); | ||||||
| 
 | 
 | ||||||
| extern errcode_t ext2fs_dirhash2(int version, const char *name, int len, | extern errcode_t ext2fs_dirhash2(int version, const char *name, int len, | ||||||
| 				 const struct nls_table *charset, | 				 const struct ext2fs_nls_table *charset, | ||||||
| 				 int hash_flags, | 				 int hash_flags, | ||||||
| 				 const __u32 *seed, | 				 const __u32 *seed, | ||||||
| 				 ext2_dirhash_t *ret_hash, | 				 ext2_dirhash_t *ret_hash, | ||||||
|  | @ -1429,6 +1438,8 @@ errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap, | ||||||
| 					void *in); | 					void *in); | ||||||
| errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, | errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, | ||||||
| 					   ext2fs_block_bitmap *bitmap); | 					   ext2fs_block_bitmap *bitmap); | ||||||
|  | errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, | ||||||
|  | 				     blk64_t end, blk64_t *out); | ||||||
| 
 | 
 | ||||||
| /* get_num_dirs.c */ | /* get_num_dirs.c */ | ||||||
| extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs); | extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs); | ||||||
|  | @ -1594,6 +1605,9 @@ extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino, | ||||||
| extern errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, ext2_ino_t dir_ino, | extern errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, ext2_ino_t dir_ino, | ||||||
| 				ext2_ino_t parent_ino, __u32 *iblock); | 				ext2_ino_t parent_ino, __u32 *iblock); | ||||||
| 
 | 
 | ||||||
|  | /* nls_utf8.c */ | ||||||
|  | extern const struct ext2fs_nls_table *ext2fs_load_nls_table(int encoding); | ||||||
|  | 
 | ||||||
| /* mkdir.c */ | /* mkdir.c */ | ||||||
| extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | ||||||
| 			      const char *name); | 			      const char *name); | ||||||
|  | @ -1751,6 +1765,8 @@ extern errcode_t ext2fs_get_arrayzero(unsigned long count, | ||||||
| extern errcode_t ext2fs_free_mem(void *ptr); | extern errcode_t ext2fs_free_mem(void *ptr); | ||||||
| extern errcode_t ext2fs_resize_mem(unsigned long old_size, | extern errcode_t ext2fs_resize_mem(unsigned long old_size, | ||||||
| 				   unsigned long size, void *ptr); | 				   unsigned long size, void *ptr); | ||||||
|  | extern errcode_t ext2fs_resize_array(unsigned long old_count, unsigned long count, | ||||||
|  | 				     unsigned long size, void *ptr); | ||||||
| extern void ext2fs_mark_super_dirty(ext2_filsys fs); | extern void ext2fs_mark_super_dirty(ext2_filsys fs); | ||||||
| extern void ext2fs_mark_changed(ext2_filsys fs); | extern void ext2fs_mark_changed(ext2_filsys fs); | ||||||
| extern int ext2fs_test_changed(ext2_filsys fs); | extern int ext2fs_test_changed(ext2_filsys fs); | ||||||
|  | @ -1834,7 +1850,8 @@ _INLINE_ errcode_t ext2fs_get_memzero(unsigned long size, void *ptr) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| _INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size, void *ptr) | _INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size, | ||||||
|  | 				    void *ptr) | ||||||
| { | { | ||||||
| 	if (count && (~0UL)/count < size) | 	if (count && (~0UL)/count < size) | ||||||
| 		return EXT2_ET_NO_MEMORY; | 		return EXT2_ET_NO_MEMORY; | ||||||
|  | @ -1889,6 +1906,36 @@ _INLINE_ errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_siz | ||||||
| 	memcpy(ptr, &p, sizeof(p)); | 	memcpy(ptr, &p, sizeof(p)); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  *  Resize array.  The 'ptr' arg must point to a pointer. | ||||||
|  |  */ | ||||||
|  | _INLINE_ errcode_t ext2fs_resize_array(unsigned long size, | ||||||
|  | 				       unsigned long old_count, | ||||||
|  | 				       unsigned long count, void *ptr) | ||||||
|  | { | ||||||
|  | 	unsigned long old_size; | ||||||
|  | 	errcode_t retval; | ||||||
|  | 
 | ||||||
|  | 	if (count && (~0UL)/count < size) | ||||||
|  | 		return EXT2_ET_NO_MEMORY; | ||||||
|  | 
 | ||||||
|  | 	size *= count; | ||||||
|  | 	old_size = size * old_count; | ||||||
|  | 	retval = ext2fs_resize_mem(old_size, size, ptr); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 
 | ||||||
|  | 	if (size > old_size) { | ||||||
|  | 		void *p; | ||||||
|  | 
 | ||||||
|  | 		memcpy(&p, ptr, sizeof(p)); | ||||||
|  | 		memset((char *)p + old_size, 0, size - old_size); | ||||||
|  | 		memcpy(ptr, &p, sizeof(p)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
| #endif	/* Custom memory routines */ | #endif	/* Custom memory routines */ | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -2010,7 +2057,13 @@ _INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs, | ||||||
| 
 | 
 | ||||||
| _INLINE_ int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks) | _INLINE_ int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks) | ||||||
| { | { | ||||||
| 	return blocks * ((fs->blocksize - 8) / sizeof(struct ext2_dx_entry)); | 	int csum_size = 0; | ||||||
|  | 
 | ||||||
|  | 	if ((EXT2_SB(fs->super)->s_feature_ro_compat & | ||||||
|  | 	     EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) != 0) | ||||||
|  | 		csum_size = sizeof(struct ext2_dx_tail); | ||||||
|  | 	return blocks * ((fs->blocksize - (8 + csum_size)) / | ||||||
|  | 						sizeof(struct ext2_dx_entry)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  |  | ||||||
|  | @ -92,6 +92,20 @@ struct ext2_inode_cache_ent { | ||||||
| 	struct ext2_inode	*inode; | 	struct ext2_inode	*inode; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * NLS defintions | ||||||
|  |  */ | ||||||
|  | struct ext2fs_nls_table { | ||||||
|  | 	int version; | ||||||
|  | 	const struct ext2fs_nls_ops *ops; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct ext2fs_nls_ops { | ||||||
|  | 	int (*casefold)(const struct ext2fs_nls_table *charset, | ||||||
|  | 			const unsigned char *str, size_t len, | ||||||
|  | 			unsigned char *dest, size_t dlen); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /* Function prototypes */ | /* Function prototypes */ | ||||||
| 
 | 
 | ||||||
| extern int ext2fs_process_dir_block(ext2_filsys  	fs, | extern int ext2fs_process_dir_block(ext2_filsys  	fs, | ||||||
|  |  | ||||||
|  | @ -1550,14 +1550,15 @@ errcode_t ext2fs_xattr_set(struct ext2_xattr_handle *h, | ||||||
| 						       new_value, &value_len); | 						       new_value, &value_len); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			goto out; | 			goto out; | ||||||
| 	} else | 	} else if (value_len) | ||||||
| 		memcpy(new_value, value, value_len); | 		memcpy(new_value, value, value_len); | ||||||
| 
 | 
 | ||||||
| 	/* Imitate kernel behavior by skipping update if value is the same. */ | 	/* Imitate kernel behavior by skipping update if value is the same. */ | ||||||
| 	for (x = h->attrs; x < h->attrs + h->count; x++) { | 	for (x = h->attrs; x < h->attrs + h->count; x++) { | ||||||
| 		if (!strcmp(x->name, name)) { | 		if (!strcmp(x->name, name)) { | ||||||
| 			if (!x->ea_ino && x->value_len == value_len && | 			if (!x->ea_ino && x->value_len == value_len && | ||||||
| 			    !memcmp(x->value, new_value, value_len)) { | 			    (!value_len || | ||||||
|  | 			     !memcmp(x->value, new_value, value_len))) { | ||||||
| 				ret = 0; | 				ret = 0; | ||||||
| 				goto out; | 				goto out; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -808,7 +808,8 @@ errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, | ||||||
| 			   blk64_t start, blk64_t len) | 			   blk64_t start, blk64_t len) | ||||||
| { | { | ||||||
| 	struct ext2_inode	inode_buf; | 	struct ext2_inode	inode_buf; | ||||||
| 	blk64_t			blk, x; | 	blk64_t			blk, x, zero_blk = 0, last = 0; | ||||||
|  | 	int			zero_len = 0; | ||||||
| 	errcode_t		err = 0; | 	errcode_t		err = 0; | ||||||
| 
 | 
 | ||||||
| 	if (((flags & EXT2_FALLOCATE_FORCE_INIT) && | 	if (((flags & EXT2_FALLOCATE_FORCE_INIT) && | ||||||
|  | @ -848,15 +849,32 @@ errcode_t ext2fs_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, | ||||||
| 		if (x) | 		if (x) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		err = ext2fs_bmap2(fs, ino, inode, NULL, | 		err = ext2fs_bmap2(fs, ino, inode, NULL, BMAP_ALLOC, | ||||||
| 				   BMAP_ALLOC | BMAP_UNINIT | BMAP_ZERO, blk, | 				   blk, 0, &x); | ||||||
| 				   0, &x); |  | ||||||
| 		if (err) | 		if (err) | ||||||
| 			return err; | 			goto errout; | ||||||
|  | 		if ((zero_len && (x != last+1)) || | ||||||
|  | 		    (zero_len >= 65536)) { | ||||||
|  | 			err = ext2fs_zero_blocks2(fs, zero_blk, zero_len, | ||||||
|  | 						  NULL, NULL); | ||||||
|  | 			zero_len = 0; | ||||||
|  | 			if (err) | ||||||
|  | 				goto errout; | ||||||
|  | 		} | ||||||
|  | 		if (zero_len == 0) { | ||||||
|  | 			zero_blk = x; | ||||||
|  | 			zero_len = 1; | ||||||
|  | 		} else { | ||||||
|  | 			zero_len++; | ||||||
|  | 		} | ||||||
|  | 		last = x; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	if (inode == &inode_buf) | 	if (inode == &inode_buf) | ||||||
| 		ext2fs_write_inode(fs, ino, inode); | 		ext2fs_write_inode(fs, ino, inode); | ||||||
|  | errout: | ||||||
|  | 	if (zero_len) | ||||||
|  | 		ext2fs_zero_blocks2(fs, zero_blk, zero_len, NULL, NULL); | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -799,7 +799,7 @@ errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, | ||||||
| 	ext2fs_generic_bitmap_64 bmap, cmap; | 	ext2fs_generic_bitmap_64 bmap, cmap; | ||||||
| 	ext2fs_block_bitmap	gen_bmap = *bitmap, gen_cmap; | 	ext2fs_block_bitmap	gen_bmap = *bitmap, gen_cmap; | ||||||
| 	errcode_t		retval; | 	errcode_t		retval; | ||||||
| 	blk64_t			i, b_end, c_end, n, ratio; | 	blk64_t			i, next, b_end, c_end; | ||||||
| 
 | 
 | ||||||
| 	bmap = (ext2fs_generic_bitmap_64) gen_bmap; | 	bmap = (ext2fs_generic_bitmap_64) gen_bmap; | ||||||
| 	if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(gen_bmap)) | 	if (fs->cluster_ratio_bits == ext2fs_get_bitmap_granularity(gen_bmap)) | ||||||
|  | @ -816,18 +816,13 @@ errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, | ||||||
| 	bmap->end = bmap->real_end; | 	bmap->end = bmap->real_end; | ||||||
| 	c_end = cmap->end; | 	c_end = cmap->end; | ||||||
| 	cmap->end = cmap->real_end; | 	cmap->end = cmap->real_end; | ||||||
| 	n = 0; |  | ||||||
| 	ratio = 1ULL << fs->cluster_ratio_bits; |  | ||||||
| 	while (i < bmap->real_end) { | 	while (i < bmap->real_end) { | ||||||
| 		if (ext2fs_test_block_bitmap2(gen_bmap, i)) { | 		retval = ext2fs_find_first_set_block_bitmap2(gen_bmap, | ||||||
| 			ext2fs_mark_block_bitmap2(gen_cmap, i); | 						i, bmap->real_end, &next); | ||||||
| 			i += ratio - n; | 		if (retval) | ||||||
| 			n = 0; | 			break; | ||||||
| 			continue; | 		ext2fs_mark_block_bitmap2(gen_cmap, next); | ||||||
| 		} | 		i = EXT2FS_C2B(fs, EXT2FS_B2C(fs, next) + 1); | ||||||
| 		i++; n++; |  | ||||||
| 		if (n >= ratio) |  | ||||||
| 			n = 0; |  | ||||||
| 	} | 	} | ||||||
| 	bmap->end = b_end; | 	bmap->end = b_end; | ||||||
| 	cmap->end = c_end; | 	cmap->end = c_end; | ||||||
|  | @ -945,3 +940,38 @@ errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap, | ||||||
| 
 | 
 | ||||||
| 	return ENOENT; | 	return ENOENT; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start, | ||||||
|  | 				     blk64_t end, blk64_t *out) | ||||||
|  | { | ||||||
|  | 	blk64_t		next; | ||||||
|  | 	blk64_t		tot_set = 0; | ||||||
|  | 	errcode_t	retval; | ||||||
|  | 
 | ||||||
|  | 	while (start < end) { | ||||||
|  | 		retval = ext2fs_find_first_set_block_bitmap2(fs->block_map, | ||||||
|  | 							start, end, &next); | ||||||
|  | 		if (retval) { | ||||||
|  | 			if (retval == ENOENT) | ||||||
|  | 				retval = 0; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		start = next; | ||||||
|  | 
 | ||||||
|  | 		retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map, | ||||||
|  | 							start, end, &next); | ||||||
|  | 		if (retval == 0) { | ||||||
|  | 			tot_set += next - start; | ||||||
|  | 			start  = next + 1; | ||||||
|  | 		} else if (retval == ENOENT) { | ||||||
|  | 			retval = 0; | ||||||
|  | 			tot_set += end - start + 1; | ||||||
|  | 			break; | ||||||
|  | 		} else | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!retval) | ||||||
|  | 		*out = EXT2FS_NUM_B2C(fs, tot_set); | ||||||
|  | 	return retval; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,22 @@ | ||||||
| #include "hashmap.h" | #include "hashmap.h" | ||||||
| #include <string.h> | #include <string.h> | ||||||
| 
 | 
 | ||||||
|  | struct ext2fs_hashmap { | ||||||
|  | 	uint32_t size; | ||||||
|  | 	uint32_t(*hash)(const void *key, size_t len); | ||||||
|  | 	void(*free)(void*); | ||||||
|  | 	struct ext2fs_hashmap_entry *first; | ||||||
|  | 	struct ext2fs_hashmap_entry *last; | ||||||
|  | #if __GNUC_PREREQ (4, 8) | ||||||
|  | #pragma GCC diagnostic push | ||||||
|  | #pragma GCC diagnostic ignored "-Wpedantic" | ||||||
|  | #endif | ||||||
|  | 	struct ext2fs_hashmap_entry *entries[0]; | ||||||
|  | #if __GNUC_PREREQ (4, 8) | ||||||
|  | #pragma GCC diagnostic pop | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| uint32_t ext2fs_djb2_hash(const void *str, size_t size) | uint32_t ext2fs_djb2_hash(const void *str, size_t size) | ||||||
| { | { | ||||||
| 	int c; | 	int c; | ||||||
|  |  | ||||||
|  | @ -13,27 +13,15 @@ | ||||||
| #endif | #endif | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| struct ext2fs_hashmap { | struct ext2fs_hashmap; | ||||||
| 	uint32_t size; | 
 | ||||||
| 	uint32_t(*hash)(const void *key, size_t len); | struct ext2fs_hashmap_entry { | ||||||
| 	void(*free)(void*); | 	void *data; | ||||||
| 	struct ext2fs_hashmap_entry *first; | 	const void *key; | ||||||
| 	struct ext2fs_hashmap_entry *last; | 	size_t key_len; | ||||||
| 	struct ext2fs_hashmap_entry { | 	struct ext2fs_hashmap_entry *next; | ||||||
| 		void *data; | 	struct ext2fs_hashmap_entry *list_next; | ||||||
| 		const void *key; | 	struct ext2fs_hashmap_entry *list_prev; | ||||||
| 		size_t key_len; |  | ||||||
| 		struct ext2fs_hashmap_entry *next; |  | ||||||
| 		struct ext2fs_hashmap_entry *list_next; |  | ||||||
| 		struct ext2fs_hashmap_entry *list_prev; |  | ||||||
| #if __GNUC_PREREQ (4, 8) |  | ||||||
| #pragma GCC diagnostic push |  | ||||||
| #pragma GCC diagnostic ignored "-Wpedantic" |  | ||||||
| #endif |  | ||||||
| 	} *entries[0]; |  | ||||||
| #if __GNUC_PREREQ (4, 8) |  | ||||||
| #pragma GCC diagnostic pop |  | ||||||
| #endif |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct ext2fs_hashmap *ext2fs_hashmap_create( | struct ext2fs_hashmap *ext2fs_hashmap_create( | ||||||
|  |  | ||||||
|  | @ -190,6 +190,9 @@ errcode_t ext2fs_initialize(const char *name, int flags, | ||||||
| 	assign_field(s_encoding); | 	assign_field(s_encoding); | ||||||
| 	assign_field(s_encoding_flags); | 	assign_field(s_encoding_flags); | ||||||
| 
 | 
 | ||||||
|  | //	if (ext2fs_has_feature_casefold(param))
 | ||||||
|  | //		fs->encoding = ext2fs_load_nls_table(param->s_encoding);
 | ||||||
|  | 
 | ||||||
| 	if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { | 	if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { | ||||||
| 		retval = EXT2_ET_UNSUPP_FEATURE; | 		retval = EXT2_ET_UNSUPP_FEATURE; | ||||||
| 		goto cleanup; | 		goto cleanup; | ||||||
|  |  | ||||||
|  | @ -309,6 +309,7 @@ errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, | ||||||
| { | { | ||||||
| 	scan->current_group = group - 1; | 	scan->current_group = group - 1; | ||||||
| 	scan->groups_left = scan->fs->group_desc_count - group; | 	scan->groups_left = scan->fs->group_desc_count - group; | ||||||
|  | 	scan->bad_block_ptr = 0; | ||||||
| 	return get_next_blockgroup(scan); | 	return get_next_blockgroup(scan); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -332,6 +333,12 @@ static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, | ||||||
| 	if (blk == 0) | 	if (blk == 0) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
|  | 	/* Make sure bad_block_ptr is still valid */ | ||||||
|  | 	if (scan->bad_block_ptr >= bb->num) { | ||||||
|  | 		scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * If the current block is greater than the bad block listed | 	 * If the current block is greater than the bad block listed | ||||||
| 	 * in the bad block list, then advance the pointer until this | 	 * in the bad block list, then advance the pointer until this | ||||||
|  | @ -967,10 +974,6 @@ errcode_t ext2fs_write_inode2(ext2_filsys fs, ext2_ino_t ino, | ||||||
| 		if ((offset + length) > fs->blocksize) | 		if ((offset + length) > fs->blocksize) | ||||||
| 			clen = fs->blocksize - offset; | 			clen = fs->blocksize - offset; | ||||||
| 
 | 
 | ||||||
| 		if (!fs->icache) { |  | ||||||
| 			retval = EXT2_ET_GDESC_READ; |  | ||||||
| 			goto errout; |  | ||||||
| 		} |  | ||||||
| 		if (fs->icache->buffer_blk != block_nr) { | 		if (fs->icache->buffer_blk != block_nr) { | ||||||
| 			retval = io_channel_read_blk64(fs->io, block_nr, 1, | 			retval = io_channel_read_blk64(fs->io, block_nr, 1, | ||||||
| 						     fs->icache->buffer); | 						     fs->icache->buffer); | ||||||
|  |  | ||||||
|  | @ -22,8 +22,8 @@ | ||||||
| #define KERN_ERR "" | #define KERN_ERR "" | ||||||
| #define KERN_DEBUG "" | #define KERN_DEBUG "" | ||||||
| 
 | 
 | ||||||
| #define READ 0 | #define REQ_OP_READ 0 | ||||||
| #define WRITE 1 | #define REQ_OP_WRITE 1 | ||||||
| 
 | 
 | ||||||
| #define cpu_to_be32(n) htonl(n) | #define cpu_to_be32(n) htonl(n) | ||||||
| #define be32_to_cpu(n) ntohl(n) | #define be32_to_cpu(n) ntohl(n) | ||||||
|  | @ -37,14 +37,14 @@ typedef struct kdev_s *kdev_t; | ||||||
| struct buffer_head; | struct buffer_head; | ||||||
| struct inode; | struct inode; | ||||||
| 
 | 
 | ||||||
|  | typedef unsigned int gfp_t; | ||||||
| #define GFP_KERNEL	0 | #define GFP_KERNEL	0 | ||||||
| #define JFS_TAG_SIZE32	JBD_TAG_SIZE32 | #define GFP_NOFS	0 | ||||||
| #define JFS_BARRIER	0 | #define __GFP_NOFAIL	0 | ||||||
|  | #define JBD2_TAG_SIZE32	JBD_TAG_SIZE32 | ||||||
|  | #define JBD2_BARRIER	0 | ||||||
| typedef __u64 u64; | typedef __u64 u64; | ||||||
| #define JFS_CRC32_CHKSUM	JBD2_CRC32_CHKSUM |  | ||||||
| #define JFS_CRC32_CHKSUM_SIZE	JBD2_CRC32_CHKSUM_SIZE |  | ||||||
| #define put_bh(x)	brelse(x) | #define put_bh(x)	brelse(x) | ||||||
| #define be64_to_cpu(x)	ext2fs_be64_to_cpu(x) |  | ||||||
| 
 | 
 | ||||||
| static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)), | static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)), | ||||||
| 				__u32 crc, const void *address, | 				__u32 crc, const void *address, | ||||||
|  | @ -56,7 +56,6 @@ static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)), | ||||||
| #define spin_lock_init(x) | #define spin_lock_init(x) | ||||||
| #define spin_lock(x) | #define spin_lock(x) | ||||||
| #define spin_unlock(x) | #define spin_unlock(x) | ||||||
| #define yield() |  | ||||||
| #define SLAB_HWCACHE_ALIGN	0 | #define SLAB_HWCACHE_ALIGN	0 | ||||||
| #define SLAB_TEMPORARY		0 | #define SLAB_TEMPORARY		0 | ||||||
| #define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\ | #define KMEM_CACHE(__struct, __flags) kmem_cache_create(#__struct,\ | ||||||
|  | @ -65,6 +64,7 @@ static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)), | ||||||
| 
 | 
 | ||||||
| #define blkdev_issue_flush(kdev, a, b)	sync_blockdev(kdev) | #define blkdev_issue_flush(kdev, a, b)	sync_blockdev(kdev) | ||||||
| #define is_power_of_2(x)	((x) != 0 && (((x) & ((x) - 1)) == 0)) | #define is_power_of_2(x)	((x) != 0 && (((x) & ((x) - 1)) == 0)) | ||||||
|  | #define pr_emerg(fmt) | ||||||
| 
 | 
 | ||||||
| struct journal_s | struct journal_s | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -24,7 +24,7 @@ | ||||||
| #define __FUNCTION__ "" | #define __FUNCTION__ "" | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #define journal_oom_retry 1 | #define journal_oom_retry 0 | ||||||
| 
 | 
 | ||||||
| #ifdef __STDC__ | #ifdef __STDC__ | ||||||
| #ifdef CONFIG_JBD_DEBUG | #ifdef CONFIG_JBD_DEBUG | ||||||
|  | @ -73,13 +73,13 @@ extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry); | ||||||
| #define jbd_rep_kmalloc(size, flags) \ | #define jbd_rep_kmalloc(size, flags) \ | ||||||
| 	__jbd_kmalloc(__FUNCTION__, (size), (flags), 1) | 	__jbd_kmalloc(__FUNCTION__, (size), (flags), 1) | ||||||
| 
 | 
 | ||||||
| #define JFS_MIN_JOURNAL_BLOCKS 1024 | #define JBD2_MIN_JOURNAL_BLOCKS 1024 | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Internal structures used by the logging mechanism: |  * Internal structures used by the logging mechanism: | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #define JFS_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ | #define JBD2_MAGIC_NUMBER 0xc03b3998U /* The first 4 bytes of /dev/random! */ | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * On-disk structures |  * On-disk structures | ||||||
|  | @ -89,20 +89,20 @@ extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry); | ||||||
|  * Descriptor block types: |  * Descriptor block types: | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #define JFS_DESCRIPTOR_BLOCK	1 | #define JBD2_DESCRIPTOR_BLOCK	1 | ||||||
| #define JFS_COMMIT_BLOCK	2 | #define JBD2_COMMIT_BLOCK	2 | ||||||
| #define JFS_SUPERBLOCK_V1	3 | #define JBD2_SUPERBLOCK_V1	3 | ||||||
| #define JFS_SUPERBLOCK_V2	4 | #define JBD2_SUPERBLOCK_V2	4 | ||||||
| #define JFS_REVOKE_BLOCK	5 | #define JBD2_REVOKE_BLOCK	5 | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Standard header for all descriptor blocks: |  * Standard header for all descriptor blocks: | ||||||
|  */ |  */ | ||||||
| typedef struct journal_header_s | typedef struct journal_header_s | ||||||
| { | { | ||||||
| 	__u32		h_magic; | 	__be32		h_magic; | ||||||
| 	__u32		h_blocktype; | 	__be32		h_blocktype; | ||||||
| 	__u32		h_sequence; | 	__be32		h_sequence; | ||||||
| } journal_header_t; | } journal_header_t; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -135,15 +135,15 @@ typedef struct journal_header_s | ||||||
|  * Checksum v1, v2, and v3 are mutually exclusive features. |  * Checksum v1, v2, and v3 are mutually exclusive features. | ||||||
|  */ |  */ | ||||||
| struct commit_header { | struct commit_header { | ||||||
| 	__u32		h_magic; | 	__be32		h_magic; | ||||||
| 	__u32		h_blocktype; | 	__be32		h_blocktype; | ||||||
| 	__u32		h_sequence; | 	__be32		h_sequence; | ||||||
| 	unsigned char	h_chksum_type; | 	unsigned char	h_chksum_type; | ||||||
| 	unsigned char	h_chksum_size; | 	unsigned char	h_chksum_size; | ||||||
| 	unsigned char	h_padding[2]; | 	unsigned char	h_padding[2]; | ||||||
| 	__u32		h_chksum[JBD2_CHECKSUM_BYTES]; | 	__be32		h_chksum[JBD2_CHECKSUM_BYTES]; | ||||||
| 	__u64		h_commit_sec; | 	__be64		h_commit_sec; | ||||||
| 	__u32		h_commit_nsec; | 	__be32		h_commit_nsec; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -151,22 +151,22 @@ struct commit_header { | ||||||
|  */ |  */ | ||||||
| typedef struct journal_block_tag3_s | typedef struct journal_block_tag3_s | ||||||
| { | { | ||||||
| 	__u32		t_blocknr;	/* The on-disk block number */ | 	__be32		t_blocknr;	/* The on-disk block number */ | ||||||
| 	__u32		t_flags;	/* See below */ | 	__be32		t_flags;	/* See below */ | ||||||
| 	__u32		t_blocknr_high; /* most-significant high 32bits. */ | 	__be32		t_blocknr_high; /* most-significant high 32bits. */ | ||||||
| 	__u32		t_checksum;	/* crc32c(uuid+seq+block) */ | 	__be32		t_checksum;	/* crc32c(uuid+seq+block) */ | ||||||
| } journal_block_tag3_t; | } journal_block_tag3_t; | ||||||
| 
 | 
 | ||||||
| typedef struct journal_block_tag_s | typedef struct journal_block_tag_s | ||||||
| { | { | ||||||
| 	__u32		t_blocknr;	/* The on-disk block number */ | 	__be32		t_blocknr;	/* The on-disk block number */ | ||||||
| 	__u16		t_checksum;	/* truncated crc32c(uuid+seq+block) */ | 	__be16		t_checksum;	/* truncated crc32c(uuid+seq+block) */ | ||||||
| 	__u16		t_flags;	/* See below */ | 	__be16		t_flags;	/* See below */ | ||||||
| 	__u32		t_blocknr_high; /* most-significant high 32bits. */ | 	__be32		t_blocknr_high; /* most-significant high 32bits. */ | ||||||
| } journal_block_tag_t; | } journal_block_tag_t; | ||||||
| 
 | 
 | ||||||
| /* Tail of descriptor block, for checksumming */ | /* Tail of descriptor or revoke block, for checksumming */ | ||||||
| struct journal_block_tail { | struct jbd2_journal_block_tail { | ||||||
| 	__be32		t_checksum; | 	__be32		t_checksum; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | @ -177,24 +177,19 @@ struct journal_block_tail { | ||||||
| typedef struct journal_revoke_header_s | typedef struct journal_revoke_header_s | ||||||
| { | { | ||||||
| 	journal_header_t r_header; | 	journal_header_t r_header; | ||||||
| 	int		 r_count;	/* Count of bytes used in the block */ | 	__be32		 r_count;	/* Count of bytes used in the block */ | ||||||
| } journal_revoke_header_t; | } jbd2_journal_revoke_header_t; | ||||||
| 
 |  | ||||||
| /* Tail of revoke block, for checksumming */ |  | ||||||
| struct journal_revoke_tail { |  | ||||||
| 	__be32		r_checksum; |  | ||||||
| }; |  | ||||||
| 
 | 
 | ||||||
| /* Definitions for the journal tag flags word: */ | /* Definitions for the journal tag flags word: */ | ||||||
| #define JFS_FLAG_ESCAPE		1	/* on-disk block is escaped */ | #define JBD2_FLAG_ESCAPE		1	/* on-disk block is escaped */ | ||||||
| #define JFS_FLAG_SAME_UUID	2	/* block has same uuid as previous */ | #define JBD2_FLAG_SAME_UUID	2	/* block has same uuid as previous */ | ||||||
| #define JFS_FLAG_DELETED	4	/* block deleted by this transaction */ | #define JBD2_FLAG_DELETED	4	/* block deleted by this transaction */ | ||||||
| #define JFS_FLAG_LAST_TAG	8	/* last tag in this descriptor block */ | #define JBD2_FLAG_LAST_TAG	8	/* last tag in this descriptor block */ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| #define UUID_SIZE 16 | #define UUID_SIZE 16 | ||||||
| #define JFS_USERS_MAX 48 | #define JBD2_USERS_MAX 48 | ||||||
| #define JFS_USERS_SIZE (UUID_SIZE * JFS_USERS_MAX) | #define JBD2_USERS_SIZE (UUID_SIZE * JBD2_USERS_MAX) | ||||||
| /*
 | /*
 | ||||||
|  * The journal superblock.  All fields are in big-endian byte order. |  * The journal superblock.  All fields are in big-endian byte order. | ||||||
|  */ |  */ | ||||||
|  | @ -205,14 +200,14 @@ typedef struct journal_superblock_s | ||||||
| 
 | 
 | ||||||
| /* 0x000C */ | /* 0x000C */ | ||||||
| 	/* Static information describing the journal */ | 	/* Static information describing the journal */ | ||||||
| 	__u32	s_blocksize;		/* journal device blocksize */ | 	__be32	s_blocksize;		/* journal device blocksize */ | ||||||
| 	__u32	s_maxlen;		/* total blocks in journal file */ | 	__be32	s_maxlen;		/* total blocks in journal file */ | ||||||
| 	__u32	s_first;		/* first block of log information */ | 	__be32	s_first;		/* first block of log information */ | ||||||
| 
 | 
 | ||||||
| /* 0x0018 */ | /* 0x0018 */ | ||||||
| 	/* Dynamic information describing the current state of the log */ | 	/* Dynamic information describing the current state of the log */ | ||||||
| 	__u32	s_sequence;		/* first commit ID expected in log */ | 	__be32	s_sequence;		/* first commit ID expected in log */ | ||||||
| 	__u32	s_start;		/* blocknr of start of log */ | 	__be32	s_start;		/* blocknr of start of log */ | ||||||
| 
 | 
 | ||||||
| /* 0x0020 */ | /* 0x0020 */ | ||||||
| 	/* Error value, as set by journal_abort(). */ | 	/* Error value, as set by journal_abort(). */ | ||||||
|  | @ -220,63 +215,63 @@ typedef struct journal_superblock_s | ||||||
| 
 | 
 | ||||||
| /* 0x0024 */ | /* 0x0024 */ | ||||||
| 	/* Remaining fields are only valid in a version-2 superblock */ | 	/* Remaining fields are only valid in a version-2 superblock */ | ||||||
| 	__u32	s_feature_compat; 	/* compatible feature set */ | 	__be32	s_feature_compat; 	/* compatible feature set */ | ||||||
| 	__u32	s_feature_incompat; 	/* incompatible feature set */ | 	__be32	s_feature_incompat; 	/* incompatible feature set */ | ||||||
| 	__u32	s_feature_ro_compat; 	/* readonly-compatible feature set */ | 	__be32	s_feature_ro_compat; 	/* readonly-compatible feature set */ | ||||||
| /* 0x0030 */ | /* 0x0030 */ | ||||||
| 	__u8	s_uuid[16];		/* 128-bit uuid for journal */ | 	__u8	s_uuid[16];		/* 128-bit uuid for journal */ | ||||||
| 
 | 
 | ||||||
| /* 0x0040 */ | /* 0x0040 */ | ||||||
| 	__u32	s_nr_users;		/* Nr of filesystems sharing log */ | 	__be32	s_nr_users;		/* Nr of filesystems sharing log */ | ||||||
| 
 | 
 | ||||||
| 	__u32	s_dynsuper;		/* Blocknr of dynamic superblock copy*/ | 	__be32	s_dynsuper;		/* Blocknr of dynamic superblock copy*/ | ||||||
| 
 | 
 | ||||||
| /* 0x0048 */ | /* 0x0048 */ | ||||||
| 	__u32	s_max_transaction;	/* Limit of journal blocks per trans.*/ | 	__be32	s_max_transaction;	/* Limit of journal blocks per trans.*/ | ||||||
| 	__u32	s_max_trans_data;	/* Limit of data blocks per trans. */ | 	__be32	s_max_trans_data;	/* Limit of data blocks per trans. */ | ||||||
| 
 | 
 | ||||||
| /* 0x0050 */ | /* 0x0050 */ | ||||||
| 	__u8	s_checksum_type;	/* checksum type */ | 	__u8	s_checksum_type;	/* checksum type */ | ||||||
| 	__u8	s_padding2[3]; | 	__u8	s_padding2[3]; | ||||||
| 	__u32	s_padding[42]; | 	__be32	s_padding[42]; | ||||||
| 	__u32	s_checksum;		/* crc32c(superblock) */ | 	__be32	s_checksum;		/* crc32c(superblock) */ | ||||||
| 
 | 
 | ||||||
| /* 0x0100 */ | /* 0x0100 */ | ||||||
| 	__u8	s_users[JFS_USERS_SIZE];		/* ids of all fs'es sharing the log */ | 	__u8	s_users[JBD2_USERS_SIZE];		/* ids of all fs'es sharing the log */ | ||||||
| 
 | 
 | ||||||
| /* 0x0400 */ | /* 0x0400 */ | ||||||
| } journal_superblock_t; | } journal_superblock_t; | ||||||
| 
 | 
 | ||||||
| #define JFS_HAS_COMPAT_FEATURE(j,mask)					\ | #define JBD2_HAS_COMPAT_FEATURE(j,mask)					\ | ||||||
| 	((j)->j_format_version >= 2 &&					\ | 	((j)->j_format_version >= 2 &&					\ | ||||||
| 	 ((j)->j_superblock->s_feature_compat & ext2fs_cpu_to_be32((mask)))) | 	 ((j)->j_superblock->s_feature_compat & ext2fs_cpu_to_be32((mask)))) | ||||||
| #define JFS_HAS_RO_COMPAT_FEATURE(j,mask)				\ | #define JBD2_HAS_RO_COMPAT_FEATURE(j,mask)				\ | ||||||
| 	((j)->j_format_version >= 2 &&					\ | 	((j)->j_format_version >= 2 &&					\ | ||||||
| 	 ((j)->j_superblock->s_feature_ro_compat & ext2fs_cpu_to_be32((mask)))) | 	 ((j)->j_superblock->s_feature_ro_compat & ext2fs_cpu_to_be32((mask)))) | ||||||
| #define JFS_HAS_INCOMPAT_FEATURE(j,mask)				\ | #define JBD2_HAS_INCOMPAT_FEATURE(j,mask)				\ | ||||||
| 	((j)->j_format_version >= 2 &&					\ | 	((j)->j_format_version >= 2 &&					\ | ||||||
| 	 ((j)->j_superblock->s_feature_incompat & ext2fs_cpu_to_be32((mask)))) | 	 ((j)->j_superblock->s_feature_incompat & ext2fs_cpu_to_be32((mask)))) | ||||||
| 
 | 
 | ||||||
| #define JFS_FEATURE_COMPAT_CHECKSUM		0x00000001 | #define JBD2_FEATURE_COMPAT_CHECKSUM		0x00000001 | ||||||
| 
 | 
 | ||||||
| #define JFS_FEATURE_INCOMPAT_REVOKE		0x00000001 | #define JBD2_FEATURE_INCOMPAT_REVOKE		0x00000001 | ||||||
| #define JFS_FEATURE_INCOMPAT_64BIT		0x00000002 | #define JBD2_FEATURE_INCOMPAT_64BIT		0x00000002 | ||||||
| #define JFS_FEATURE_INCOMPAT_ASYNC_COMMIT	0x00000004 | #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT	0x00000004 | ||||||
| #define JFS_FEATURE_INCOMPAT_CSUM_V2		0x00000008 | #define JBD2_FEATURE_INCOMPAT_CSUM_V2		0x00000008 | ||||||
| #define JFS_FEATURE_INCOMPAT_CSUM_V3		0x00000010 | #define JBD2_FEATURE_INCOMPAT_CSUM_V3		0x00000010 | ||||||
| 
 | 
 | ||||||
| /* Features known to this kernel version: */ | /* Features known to this kernel version: */ | ||||||
| #define JFS_KNOWN_COMPAT_FEATURES	0 | #define JBD2_KNOWN_COMPAT_FEATURES	0 | ||||||
| #define JFS_KNOWN_ROCOMPAT_FEATURES	0 | #define JBD2_KNOWN_ROCOMPAT_FEATURES	0 | ||||||
| #define JFS_KNOWN_INCOMPAT_FEATURES	(JFS_FEATURE_INCOMPAT_REVOKE|\ | #define JBD2_KNOWN_INCOMPAT_FEATURES	(JBD2_FEATURE_INCOMPAT_REVOKE|\ | ||||||
| 					 JFS_FEATURE_INCOMPAT_ASYNC_COMMIT|\ | 					 JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT| \ | ||||||
| 					 JFS_FEATURE_INCOMPAT_64BIT|\ | 					 JBD2_FEATURE_INCOMPAT_64BIT|\ | ||||||
| 					 JFS_FEATURE_INCOMPAT_CSUM_V2|\ | 					 JBD2_FEATURE_INCOMPAT_CSUM_V2|	\ | ||||||
| 					 JFS_FEATURE_INCOMPAT_CSUM_V3) | 					 JBD2_FEATURE_INCOMPAT_CSUM_V3) | ||||||
| 
 | 
 | ||||||
| #ifdef NO_INLINE_FUNCS | #ifdef NO_INLINE_FUNCS | ||||||
| extern size_t journal_tag_bytes(journal_t *journal); | extern size_t journal_tag_bytes(journal_t *journal); | ||||||
| extern int journal_has_csum_v2or3(journal_t *journal); | extern int jbd2_journal_has_csum_v2or3(journal_t *journal); | ||||||
| extern int tid_gt(tid_t x, tid_t y) EXT2FS_ATTR((unused)); | extern int tid_gt(tid_t x, tid_t y) EXT2FS_ATTR((unused)); | ||||||
| extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused)); | extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused)); | ||||||
| #endif | #endif | ||||||
|  | @ -301,94 +296,94 @@ extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused)); | ||||||
| #endif /* INCLUDE_INLINE_FUNCS */ | #endif /* INCLUDE_INLINE_FUNCS */ | ||||||
| 
 | 
 | ||||||
| /* journal feature predicate functions */ | /* journal feature predicate functions */ | ||||||
| #define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \ | #define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \ | ||||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j); \ | _INLINE_ int jbd2_has_feature_##name(journal_t *j); \ | ||||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j) \ | _INLINE_ int jbd2_has_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	return ((j)->j_format_version >= 2 && \ | 	return ((j)->j_format_version >= 2 && \ | ||||||
| 		((j)->j_superblock->s_feature_compat & \ | 		((j)->j_superblock->s_feature_compat & \ | ||||||
| 		 ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname)) != 0); \ | 		 ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname)) != 0); \ | ||||||
| } \ | } \ | ||||||
| _INLINE_ void jfs_set_feature_##name(journal_t *j); \ | _INLINE_ void jbd2_set_feature_##name(journal_t *j); \ | ||||||
| _INLINE_ void jfs_set_feature_##name(journal_t *j) \ | _INLINE_ void jbd2_set_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	(j)->j_superblock->s_feature_compat |= \ | 	(j)->j_superblock->s_feature_compat |= \ | ||||||
| 		ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \ | 		ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \ | ||||||
| } \ | } \ | ||||||
| _INLINE_ void jfs_clear_feature_##name(journal_t *j); \ | _INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ | ||||||
| _INLINE_ void jfs_clear_feature_##name(journal_t *j) \ | _INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	(j)->j_superblock->s_feature_compat &= \ | 	(j)->j_superblock->s_feature_compat &= \ | ||||||
| 		~ext2fs_cpu_to_be32(JFS_FEATURE_COMPAT_##flagname); \ | 		~ext2fs_cpu_to_be32(JBD2_FEATURE_COMPAT_##flagname); \ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | #define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | ||||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j);	\ | _INLINE_ int jbd2_has_feature_##name(journal_t *j);	\ | ||||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j) \ | _INLINE_ int jbd2_has_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	return ((j)->j_format_version >= 2 && \ | 	return ((j)->j_format_version >= 2 && \ | ||||||
| 		((j)->j_superblock->s_feature_ro_compat & \ | 		((j)->j_superblock->s_feature_ro_compat & \ | ||||||
| 		 ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname)) != 0); \ | 		 ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname)) != 0); \ | ||||||
| } \ | } \ | ||||||
| _INLINE_ void jfs_set_feature_##name(journal_t *j); \ | _INLINE_ void jbd2_set_feature_##name(journal_t *j); \ | ||||||
| _INLINE_ void jfs_set_feature_##name(journal_t *j) \ | _INLINE_ void jbd2_set_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	(j)->j_superblock->s_feature_ro_compat |= \ | 	(j)->j_superblock->s_feature_ro_compat |= \ | ||||||
| 		ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \ | 		ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \ | ||||||
| } \ | } \ | ||||||
| _INLINE_ void jfs_clear_feature_##name(journal_t *j); \ | _INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ | ||||||
| _INLINE_ void jfs_clear_feature_##name(journal_t *j) \ | _INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	(j)->j_superblock->s_feature_ro_compat &= \ | 	(j)->j_superblock->s_feature_ro_compat &= \ | ||||||
| 		~ext2fs_cpu_to_be32(JFS_FEATURE_RO_COMPAT_##flagname); \ | 		~ext2fs_cpu_to_be32(JBD2_FEATURE_RO_COMPAT_##flagname); \ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | #define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | ||||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j); \ | _INLINE_ int jbd2_has_feature_##name(journal_t *j); \ | ||||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j) \ | _INLINE_ int jbd2_has_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	return ((j)->j_format_version >= 2 && \ | 	return ((j)->j_format_version >= 2 && \ | ||||||
| 		((j)->j_superblock->s_feature_incompat & \ | 		((j)->j_superblock->s_feature_incompat & \ | ||||||
| 		 ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname)) != 0); \ | 		 ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname)) != 0); \ | ||||||
| } \ | } \ | ||||||
| _INLINE_ void jfs_set_feature_##name(journal_t *j); \ | _INLINE_ void jbd2_set_feature_##name(journal_t *j); \ | ||||||
| _INLINE_ void jfs_set_feature_##name(journal_t *j) \ | _INLINE_ void jbd2_set_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	(j)->j_superblock->s_feature_incompat |= \ | 	(j)->j_superblock->s_feature_incompat |= \ | ||||||
| 		ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \ | 		ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ | ||||||
| } \ | } \ | ||||||
| _INLINE_ void jfs_clear_feature_##name(journal_t *j); \ | _INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ | ||||||
| _INLINE_ void jfs_clear_feature_##name(journal_t *j) \ | _INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ | ||||||
| { \ | { \ | ||||||
| 	(j)->j_superblock->s_feature_incompat &= \ | 	(j)->j_superblock->s_feature_incompat &= \ | ||||||
| 		~ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \ | 		~ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #else | #else | ||||||
| #define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \ | #define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \ | ||||||
| extern int jfs_has_feature_##name(journal_t *j); \ | extern int jbd2_has_feature_##name(journal_t *j); \ | ||||||
| extern void jfs_set_feature_##name(journal_t *j); \ | extern void jbd2_set_feature_##name(journal_t *j); \ | ||||||
| extern void jfs_clear_feature_##name(journal_t *j); | extern void jbd2_clear_feature_##name(journal_t *j); | ||||||
| 
 | 
 | ||||||
| #define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | #define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | ||||||
| extern int jfs_has_feature_##name(journal_t *j); \ | extern int jbd2_has_feature_##name(journal_t *j); \ | ||||||
| extern void jfs_set_feature_##name(journal_t *j); \ | extern void jbd2_set_feature_##name(journal_t *j); \ | ||||||
| extern void jfs_clear_feature_##name(journal_t *j); | extern void jbd2_clear_feature_##name(journal_t *j); | ||||||
| 
 | 
 | ||||||
| #define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | #define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | ||||||
| extern int jfs_has_feature_##name(journal_t *j); \ | extern int jbd2_has_feature_##name(journal_t *j); \ | ||||||
| extern void jfs_set_feature_##name(journal_t *j); \ | extern void jbd2_set_feature_##name(journal_t *j); \ | ||||||
| extern void jfs_clear_feature_##name(journal_t *j); | extern void jbd2_clear_feature_##name(journal_t *j); | ||||||
| 
 | 
 | ||||||
| #endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */ | #endif /* (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) */ | ||||||
| 
 | 
 | ||||||
| JFS_FEATURE_COMPAT_FUNCS(checksum,		CHECKSUM) | JBD2_FEATURE_COMPAT_FUNCS(checksum,		CHECKSUM) | ||||||
| 
 | 
 | ||||||
| JFS_FEATURE_INCOMPAT_FUNCS(revoke,		REVOKE) | JBD2_FEATURE_INCOMPAT_FUNCS(revoke,		REVOKE) | ||||||
| JFS_FEATURE_INCOMPAT_FUNCS(64bit,		64BIT) | JBD2_FEATURE_INCOMPAT_FUNCS(64bit,		64BIT) | ||||||
| JFS_FEATURE_INCOMPAT_FUNCS(async_commit,	ASYNC_COMMIT) | JBD2_FEATURE_INCOMPAT_FUNCS(async_commit,	ASYNC_COMMIT) | ||||||
| JFS_FEATURE_INCOMPAT_FUNCS(csum2,		CSUM_V2) | JBD2_FEATURE_INCOMPAT_FUNCS(csum2,		CSUM_V2) | ||||||
| JFS_FEATURE_INCOMPAT_FUNCS(csum3,		CSUM_V3) | JBD2_FEATURE_INCOMPAT_FUNCS(csum3,		CSUM_V3) | ||||||
| 
 | 
 | ||||||
| #if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) | #if (defined(E2FSCK_INCLUDE_INLINE_FUNCS) || !defined(NO_INLINE_FUNCS)) | ||||||
| /*
 | /*
 | ||||||
|  | @ -398,23 +393,23 @@ _INLINE_ size_t journal_tag_bytes(journal_t *journal) | ||||||
| { | { | ||||||
| 	size_t sz; | 	size_t sz; | ||||||
| 
 | 
 | ||||||
| 	if (jfs_has_feature_csum3(journal)) | 	if (jbd2_has_feature_csum3(journal)) | ||||||
| 		return sizeof(journal_block_tag3_t); | 		return sizeof(journal_block_tag3_t); | ||||||
| 
 | 
 | ||||||
| 	sz = sizeof(journal_block_tag_t); | 	sz = sizeof(journal_block_tag_t); | ||||||
| 
 | 
 | ||||||
| 	if (jfs_has_feature_csum2(journal)) | 	if (jbd2_has_feature_csum2(journal)) | ||||||
| 		sz += sizeof(__u16); | 		sz += sizeof(__u16); | ||||||
| 
 | 
 | ||||||
| 	if (jfs_has_feature_64bit(journal)) | 	if (jbd2_has_feature_64bit(journal)) | ||||||
| 		return sz; | 		return sz; | ||||||
| 
 | 
 | ||||||
| 	return sz - sizeof(__u32); | 	return sz - sizeof(__u32); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| _INLINE_ int journal_has_csum_v2or3(journal_t *journal) | _INLINE_ int jbd2_journal_has_csum_v2or3(journal_t *journal) | ||||||
| { | { | ||||||
| 	if (jfs_has_feature_csum2(journal) || jfs_has_feature_csum3(journal)) | 	if (jbd2_has_feature_csum2(journal) || jbd2_has_feature_csum3(journal)) | ||||||
| 		return 1; | 		return 1; | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
|  | @ -18,6 +18,155 @@ | ||||||
| 
 | 
 | ||||||
| #include "ext2_fs.h" | #include "ext2_fs.h" | ||||||
| #include "ext2fs.h" | #include "ext2fs.h" | ||||||
|  | #include "ext2fsP.h" | ||||||
|  | 
 | ||||||
|  | #define EXT2_DX_ROOT_OFF 24 | ||||||
|  | 
 | ||||||
|  | struct dx_frame { | ||||||
|  | 	__u8 *buf; | ||||||
|  | 	blk64_t pblock; | ||||||
|  | 	struct ext2_dx_countlimit *head; | ||||||
|  | 	struct ext2_dx_entry *entries; | ||||||
|  | 	struct ext2_dx_entry *at; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct dx_lookup_info { | ||||||
|  | 	const char *name; | ||||||
|  | 	int namelen; | ||||||
|  | 	int hash_alg; | ||||||
|  | 	__u32 hash; | ||||||
|  | 	int levels; | ||||||
|  | 	struct dx_frame frames[EXT4_HTREE_LEVEL]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static errcode_t alloc_dx_frame(ext2_filsys fs, struct dx_frame *frame) | ||||||
|  | { | ||||||
|  | 	return ext2fs_get_mem(fs->blocksize, &frame->buf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void dx_release(struct dx_lookup_info *info) | ||||||
|  | { | ||||||
|  | //	struct ext2_dx_root_info *root;
 | ||||||
|  | 	int level; | ||||||
|  | 
 | ||||||
|  | 	for (level = 0; level < info->levels; level++) { | ||||||
|  | 		if (info->frames[level].buf == NULL) | ||||||
|  | 			break; | ||||||
|  | 		ext2fs_free_mem(&(info->frames[level].buf)); | ||||||
|  | 	} | ||||||
|  | 	info->levels = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void dx_search_entry(struct dx_frame *frame, int count, __u32 hash) | ||||||
|  | { | ||||||
|  | 	struct ext2_dx_entry *p, *q, *m; | ||||||
|  | 
 | ||||||
|  | 	p = frame->entries + 1; | ||||||
|  | 	q = frame->entries + count - 1; | ||||||
|  | 	while (p <= q) { | ||||||
|  | 		m = p + (q - p) / 2; | ||||||
|  | 		if (ext2fs_le32_to_cpu(m->hash) > hash) | ||||||
|  | 			q = m - 1; | ||||||
|  | 		else | ||||||
|  | 			p = m + 1; | ||||||
|  | 	} | ||||||
|  | 	frame->at = p - 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static errcode_t load_logical_dir_block(ext2_filsys fs, ext2_ino_t dir, | ||||||
|  | 					struct ext2_inode *diri, blk64_t block, | ||||||
|  | 					blk64_t *pblk, void *buf) | ||||||
|  | { | ||||||
|  | 	errcode_t errcode; | ||||||
|  | 	int ret_flags; | ||||||
|  | 
 | ||||||
|  | 	errcode = ext2fs_bmap2(fs, dir, diri, NULL, 0, block, &ret_flags, | ||||||
|  | 			       pblk); | ||||||
|  | 	if (errcode) | ||||||
|  | 		return errcode; | ||||||
|  | 	if (ret_flags & BMAP_RET_UNINIT) | ||||||
|  | 		return EXT2_ET_DIR_CORRUPTED; | ||||||
|  | 	return ext2fs_read_dir_block4(fs, *pblk, buf, 0, dir); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static errcode_t dx_lookup(ext2_filsys fs, ext2_ino_t dir, | ||||||
|  | 			   struct ext2_inode *diri, struct dx_lookup_info *info) | ||||||
|  | { | ||||||
|  | 	struct ext2_dx_root_info *root; | ||||||
|  | 	errcode_t errcode; | ||||||
|  | 	int level = 0; | ||||||
|  | 	int count, limit; | ||||||
|  | 	int hash_alg; | ||||||
|  | 	int hash_flags = diri->i_flags & EXT4_CASEFOLD_FL; | ||||||
|  | 	__u32 minor_hash; | ||||||
|  | 	struct dx_frame *frame; | ||||||
|  | 
 | ||||||
|  | 	errcode = alloc_dx_frame(fs, &(info->frames[0])); | ||||||
|  | 	if (errcode) | ||||||
|  | 		return errcode; | ||||||
|  | 	info->levels = 1; | ||||||
|  | 
 | ||||||
|  | 	errcode = load_logical_dir_block(fs, dir, diri, 0, | ||||||
|  | 					 &(info->frames[0].pblock), | ||||||
|  | 					 info->frames[0].buf); | ||||||
|  | 	if (errcode) | ||||||
|  | 		goto out_err; | ||||||
|  | 	root = (struct ext2_dx_root_info*)(info->frames[0].buf + EXT2_DX_ROOT_OFF); | ||||||
|  | 	hash_alg = root->hash_version; | ||||||
|  | 	if (hash_alg != EXT2_HASH_TEA && hash_alg != EXT2_HASH_HALF_MD4 && | ||||||
|  | 	    hash_alg != EXT2_HASH_LEGACY) { | ||||||
|  | 		errcode = EXT2_ET_DIRHASH_UNSUPP; | ||||||
|  | 		goto out_err; | ||||||
|  | 	} | ||||||
|  | 	if (hash_alg <= EXT2_HASH_TEA && | ||||||
|  | 	    fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH) | ||||||
|  | 		hash_alg += 3; | ||||||
|  | 	if (root->indirect_levels >= ext2_dir_htree_level(fs)) { | ||||||
|  | 		errcode = EXT2_ET_DIR_CORRUPTED; | ||||||
|  | 		goto out_err; | ||||||
|  | 	} | ||||||
|  | 	info->hash_alg = hash_alg; | ||||||
|  | 
 | ||||||
|  | 	errcode = ext2fs_dirhash2(hash_alg, info->name, info->namelen, | ||||||
|  | 				  fs->encoding, hash_flags, | ||||||
|  | 				  fs->super->s_hash_seed, &info->hash, | ||||||
|  | 				  &minor_hash); | ||||||
|  | 	if (errcode) | ||||||
|  | 		goto out_err; | ||||||
|  | 
 | ||||||
|  | 	for (level = 0; level <= root->indirect_levels; level++) { | ||||||
|  | 		frame = &(info->frames[level]); | ||||||
|  | 		if (level > 0) { | ||||||
|  | 			errcode = alloc_dx_frame(fs, frame); | ||||||
|  | 			if (errcode) | ||||||
|  | 				goto out_err; | ||||||
|  | 			info->levels++; | ||||||
|  | 
 | ||||||
|  | 			errcode = load_logical_dir_block(fs, dir, diri, | ||||||
|  | 				ext2fs_le32_to_cpu(info->frames[level-1].at->block) & 0x0fffffff, | ||||||
|  | 				&(frame->pblock), frame->buf); | ||||||
|  | 			if (errcode) | ||||||
|  | 				goto out_err; | ||||||
|  | 		} | ||||||
|  | 		errcode = ext2fs_get_dx_countlimit(fs, (struct ext2_dir_entry*)frame->buf, | ||||||
|  | 						   &(frame->head), NULL); | ||||||
|  | 		if (errcode) | ||||||
|  | 			goto out_err; | ||||||
|  | 		count = ext2fs_le16_to_cpu(frame->head->count); | ||||||
|  | 		limit = ext2fs_le16_to_cpu(frame->head->limit); | ||||||
|  | 		frame->entries = (struct ext2_dx_entry *)(frame->head); | ||||||
|  | 		if (!count || count > limit) { | ||||||
|  | 			errcode = EXT2_ET_DIR_CORRUPTED; | ||||||
|  | 			goto out_err; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		dx_search_entry(frame, count, info->hash); | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | out_err: | ||||||
|  | 	dx_release(info); | ||||||
|  | 	return errcode; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| struct link_struct  { | struct link_struct  { | ||||||
| 	ext2_filsys	fs; | 	ext2_filsys	fs; | ||||||
|  | @ -31,7 +180,9 @@ struct link_struct  { | ||||||
| 	struct ext2_super_block *sb; | 	struct ext2_super_block *sb; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static int link_proc(struct ext2_dir_entry *dirent, | static int link_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), | ||||||
|  | 		     int entru EXT2FS_ATTR((unused)), | ||||||
|  | 		     struct ext2_dir_entry *dirent, | ||||||
| 		     int	offset, | 		     int	offset, | ||||||
| 		     int	blocksize, | 		     int	blocksize, | ||||||
| 		     char	*buf, | 		     char	*buf, | ||||||
|  | @ -42,7 +193,6 @@ static int link_proc(struct ext2_dir_entry *dirent, | ||||||
| 	unsigned int rec_len, min_rec_len, curr_rec_len; | 	unsigned int rec_len, min_rec_len, curr_rec_len; | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 	int csum_size = 0; | 	int csum_size = 0; | ||||||
| 	struct ext2_dir_entry_tail *t; |  | ||||||
| 
 | 
 | ||||||
| 	if (ls->done) | 	if (ls->done) | ||||||
| 		return DIRENT_ABORT; | 		return DIRENT_ABORT; | ||||||
|  | @ -70,40 +220,6 @@ static int link_proc(struct ext2_dir_entry *dirent, | ||||||
| 		ret = DIRENT_CHANGED; | 		ret = DIRENT_CHANGED; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/*
 |  | ||||||
| 	 * Since ext2fs_link blows away htree data, we need to be |  | ||||||
| 	 * careful -- if metadata_csum is enabled and we're passed in |  | ||||||
| 	 * a dirent that contains htree data, we need to create the |  | ||||||
| 	 * fake entry at the end of the block that hides the checksum. |  | ||||||
| 	 */ |  | ||||||
| 
 |  | ||||||
| 	/* De-convert a dx_node block */ |  | ||||||
| 	if (csum_size && |  | ||||||
| 	    curr_rec_len == ls->fs->blocksize && |  | ||||||
| 	    !dirent->inode) { |  | ||||||
| 		curr_rec_len -= csum_size; |  | ||||||
| 		ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent); |  | ||||||
| 		if (ls->err) |  | ||||||
| 			return DIRENT_ABORT; |  | ||||||
| 		t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize); |  | ||||||
| 		ext2fs_initialize_dirent_tail(ls->fs, t); |  | ||||||
| 		ret = DIRENT_CHANGED; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* De-convert a dx_root block */ |  | ||||||
| 	if (csum_size && |  | ||||||
| 	    curr_rec_len == ls->fs->blocksize - EXT2_DIR_REC_LEN(1) && |  | ||||||
| 	    offset == EXT2_DIR_REC_LEN(1) && |  | ||||||
| 	    dirent->name[0] == '.' && dirent->name[1] == '.') { |  | ||||||
| 		curr_rec_len -= csum_size; |  | ||||||
| 		ls->err = ext2fs_set_rec_len(ls->fs, curr_rec_len, dirent); |  | ||||||
| 		if (ls->err) |  | ||||||
| 			return DIRENT_ABORT; |  | ||||||
| 		t = EXT2_DIRENT_TAIL(buf, ls->fs->blocksize); |  | ||||||
| 		ext2fs_initialize_dirent_tail(ls->fs, t); |  | ||||||
| 		ret = DIRENT_CHANGED; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * If the directory entry is used, see if we can split the | 	 * If the directory entry is used, see if we can split the | ||||||
| 	 * directory entry to make room for the new name.  If so, | 	 * directory entry to make room for the new name.  If so, | ||||||
|  | @ -144,6 +260,343 @@ static int link_proc(struct ext2_dir_entry *dirent, | ||||||
| 	return DIRENT_ABORT|DIRENT_CHANGED; | 	return DIRENT_ABORT|DIRENT_CHANGED; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static errcode_t add_dirent_to_buf(ext2_filsys fs, e2_blkcnt_t blockcnt, | ||||||
|  | 				   char *buf, ext2_ino_t dir, | ||||||
|  | 				   struct ext2_inode *diri, const char *name, | ||||||
|  | 				   ext2_ino_t ino, int flags, blk64_t *pblkp) | ||||||
|  | { | ||||||
|  | 	struct dir_context ctx; | ||||||
|  | 	struct link_struct ls; | ||||||
|  | 	errcode_t retval; | ||||||
|  | 
 | ||||||
|  | 	retval = load_logical_dir_block(fs, dir, diri, blockcnt, pblkp, buf); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	ctx.errcode = 0; | ||||||
|  | 	ctx.func = link_proc; | ||||||
|  | 	ctx.dir = dir; | ||||||
|  | 	ctx.flags = DIRENT_FLAG_INCLUDE_EMPTY; | ||||||
|  | 	ctx.buf = buf; | ||||||
|  | 	ctx.priv_data = &ls; | ||||||
|  | 
 | ||||||
|  | 	ls.fs = fs; | ||||||
|  | 	ls.name = name; | ||||||
|  | 	ls.namelen = strlen(name); | ||||||
|  | 	ls.inode = ino; | ||||||
|  | 	ls.flags = flags; | ||||||
|  | 	ls.done = 0; | ||||||
|  | 	ls.sb = fs->super; | ||||||
|  | 	ls.blocksize = fs->blocksize; | ||||||
|  | 	ls.err = 0; | ||||||
|  | 
 | ||||||
|  | 	ext2fs_process_dir_block(fs, pblkp, blockcnt, 0, 0, &ctx); | ||||||
|  | 	if (ctx.errcode) | ||||||
|  | 		return ctx.errcode; | ||||||
|  | 	if (ls.err) | ||||||
|  | 		return ls.err; | ||||||
|  | 	if (!ls.done) | ||||||
|  | 		return EXT2_ET_DIR_NO_SPACE; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct dx_hash_map { | ||||||
|  | 	__u32 hash; | ||||||
|  | 	int size; | ||||||
|  | 	int off; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static EXT2_QSORT_TYPE dx_hash_map_cmp(const void *ap, const void *bp) | ||||||
|  | { | ||||||
|  | 	const struct dx_hash_map *a = ap, *b = bp; | ||||||
|  | 
 | ||||||
|  | 	if (a->hash < b->hash) | ||||||
|  | 		return -1; | ||||||
|  | 	if (a->hash > b->hash) | ||||||
|  | 		return 1; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static errcode_t dx_move_dirents(ext2_filsys fs, struct dx_hash_map *map, | ||||||
|  | 				 int count, __u8 *from, __u8 *to) | ||||||
|  | { | ||||||
|  | 	struct ext2_dir_entry *de; | ||||||
|  | 	int i; | ||||||
|  | 	int rec_len = 0; | ||||||
|  | 	errcode_t retval; | ||||||
|  | 	int csum_size = 0; | ||||||
|  | 	__u8 *base = to; | ||||||
|  | 
 | ||||||
|  | 	if (ext2fs_has_feature_metadata_csum(fs->super)) | ||||||
|  | 		csum_size = sizeof(struct ext2_dir_entry_tail); | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < count; i++) { | ||||||
|  | 		de = (struct ext2_dir_entry*)(from + map[i].off); | ||||||
|  | 		rec_len = EXT2_DIR_REC_LEN(ext2fs_dirent_name_len(de)); | ||||||
|  | 		memcpy(to, de, rec_len); | ||||||
|  | 		retval = ext2fs_set_rec_len(fs, rec_len, (struct ext2_dir_entry*)to); | ||||||
|  | 		if (retval) | ||||||
|  | 			return retval; | ||||||
|  | 		to += rec_len; | ||||||
|  | 	} | ||||||
|  | 	/*
 | ||||||
|  | 	 * Update rec_len of the last dir entry to stretch to the end of block | ||||||
|  | 	 */ | ||||||
|  | 	to -= rec_len; | ||||||
|  | 	rec_len = fs->blocksize - (to - base) - csum_size; | ||||||
|  | 	retval = ext2fs_set_rec_len(fs, rec_len, (struct ext2_dir_entry*)to); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	if (csum_size) | ||||||
|  | 		ext2fs_initialize_dirent_tail(fs, | ||||||
|  | 				EXT2_DIRENT_TAIL(base, fs->blocksize)); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static errcode_t dx_insert_entry(ext2_filsys fs, ext2_ino_t dir, | ||||||
|  | 				 struct dx_lookup_info *info, int level, | ||||||
|  | 				 __u32 hash, blk64_t lblk) | ||||||
|  | { | ||||||
|  | 	int pcount; | ||||||
|  | 	struct ext2_dx_entry *top, *new; | ||||||
|  | 
 | ||||||
|  | 	pcount = ext2fs_le16_to_cpu(info->frames[level].head->count); | ||||||
|  | 	top = info->frames[level].entries + pcount; | ||||||
|  | 	new = info->frames[level].at + 1; | ||||||
|  | 	memmove(new + 1, new, (char *)top - (char *)new); | ||||||
|  | 	new->hash = ext2fs_cpu_to_le32(hash); | ||||||
|  | 	new->block = ext2fs_cpu_to_le32(lblk); | ||||||
|  | 	info->frames[level].head->count = ext2fs_cpu_to_le16(pcount + 1); | ||||||
|  | 	return ext2fs_write_dir_block4(fs, info->frames[level].pblock, | ||||||
|  | 				       info->frames[level].buf, 0, dir); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static errcode_t dx_split_leaf(ext2_filsys fs, ext2_ino_t dir, | ||||||
|  | 			       struct ext2_inode *diri, | ||||||
|  | 			       struct dx_lookup_info *info, __u8 *buf, | ||||||
|  | 			       blk64_t leaf_pblk, blk64_t new_lblk, | ||||||
|  | 			       blk64_t new_pblk) | ||||||
|  | { | ||||||
|  | 	int hash_flags = diri->i_flags & EXT4_CASEFOLD_FL; | ||||||
|  | 	struct ext2_dir_entry *de; | ||||||
|  | 	void *buf2; | ||||||
|  | 	errcode_t retval = 0; | ||||||
|  | 	int rec_len; | ||||||
|  | 	int offset, move_size; | ||||||
|  | 	int i, count = 0; | ||||||
|  | 	struct dx_hash_map *map; | ||||||
|  | 	int continued; | ||||||
|  | 	__u32 minor_hash; | ||||||
|  | 
 | ||||||
|  | 	retval = ext2fs_get_mem(fs->blocksize, &buf2); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	retval = ext2fs_get_array(fs->blocksize / 12, | ||||||
|  | 				  sizeof(struct dx_hash_map), &map); | ||||||
|  | 	if (retval) { | ||||||
|  | 		ext2fs_free_mem(&buf2); | ||||||
|  | 		return retval; | ||||||
|  | 	} | ||||||
|  | 	for (offset = 0; offset < fs->blocksize; offset += rec_len) { | ||||||
|  | 		de = (struct ext2_dir_entry*)(buf + offset); | ||||||
|  | 		retval = ext2fs_get_rec_len(fs, de, &rec_len); | ||||||
|  | 		if (retval) | ||||||
|  | 			goto out; | ||||||
|  | 		if (ext2fs_dirent_name_len(de) > 0 && de->inode) { | ||||||
|  | 			map[count].off = offset; | ||||||
|  | 			map[count].size = rec_len; | ||||||
|  | 			retval = ext2fs_dirhash2(info->hash_alg, de->name, | ||||||
|  | 					ext2fs_dirent_name_len(de), | ||||||
|  | 					fs->encoding, hash_flags, | ||||||
|  | 					fs->super->s_hash_seed, | ||||||
|  | 					&(map[count].hash), | ||||||
|  | 					&minor_hash); | ||||||
|  | 			if (retval) | ||||||
|  | 				goto out; | ||||||
|  | 			count++; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	qsort(map, count, sizeof(struct dx_hash_map), dx_hash_map_cmp); | ||||||
|  | 	move_size = 0; | ||||||
|  | 	/* Find place to split block */ | ||||||
|  | 	for (i = count - 1; i >= 0; i--) { | ||||||
|  | 		if (move_size + map[i].size / 2 > fs->blocksize / 2) | ||||||
|  | 			break; | ||||||
|  | 		move_size += map[i].size; | ||||||
|  | 	} | ||||||
|  | 	/* Let i be the first entry to move */ | ||||||
|  | 	i++; | ||||||
|  | 	/* Move selected directory entries to new block */ | ||||||
|  | 	retval = dx_move_dirents(fs, map + i, count - i, buf, buf2); | ||||||
|  | 	if (retval) | ||||||
|  | 		goto out; | ||||||
|  | 	retval = ext2fs_write_dir_block4(fs, new_pblk, buf2, 0, dir); | ||||||
|  | 	if (retval) | ||||||
|  | 		goto out; | ||||||
|  | 	/* Repack remaining entries in the old block */ | ||||||
|  | 	retval = dx_move_dirents(fs, map, i, buf, buf2); | ||||||
|  | 	if (retval) | ||||||
|  | 		goto out; | ||||||
|  | 	retval = ext2fs_write_dir_block4(fs, leaf_pblk, buf2, 0, dir); | ||||||
|  | 	if (retval) | ||||||
|  | 		goto out; | ||||||
|  | 	/* Update parent node */ | ||||||
|  | 	continued = map[i].hash == map[i-1].hash; | ||||||
|  | 	retval = dx_insert_entry(fs, dir, info, info->levels - 1, | ||||||
|  | 				 map[i].hash + continued, new_lblk); | ||||||
|  | out: | ||||||
|  | 	ext2fs_free_mem(&buf2); | ||||||
|  | 	ext2fs_free_mem(&map); | ||||||
|  | 	return retval; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static errcode_t dx_grow_tree(ext2_filsys fs, ext2_ino_t dir, | ||||||
|  | 			      struct ext2_inode *diri, | ||||||
|  | 			      struct dx_lookup_info *info, __u8 *buf, | ||||||
|  | 			      blk64_t leaf_pblk) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	errcode_t retval; | ||||||
|  | 	ext2_off64_t size = EXT2_I_SIZE(diri); | ||||||
|  | 	blk64_t lblk, pblk; | ||||||
|  | 	struct ext2_dir_entry *de; | ||||||
|  | 	struct ext2_dx_countlimit *head; | ||||||
|  | 	int csum_size = 0; | ||||||
|  | 	int count; | ||||||
|  | 
 | ||||||
|  | 	if (ext2fs_has_feature_metadata_csum(fs->super)) | ||||||
|  | 		csum_size = sizeof(struct ext2_dx_tail); | ||||||
|  | 
 | ||||||
|  | 	/* Find level which can accommodate new child */ | ||||||
|  | 	for (i = info->levels - 1; i >= 0; i--) | ||||||
|  | 		if (ext2fs_le16_to_cpu(info->frames[i].head->count) < | ||||||
|  | 		    ext2fs_le16_to_cpu(info->frames[i].head->limit)) | ||||||
|  | 			break; | ||||||
|  | 	/* Need to grow tree depth? */ | ||||||
|  | 	if (i < 0 && info->levels >= ext2_dir_htree_level(fs)) | ||||||
|  | 		return EXT2_ET_DIR_NO_SPACE; | ||||||
|  | 	lblk = size / fs->blocksize; | ||||||
|  | 	size += fs->blocksize; | ||||||
|  | 	retval = ext2fs_inode_size_set(fs, diri, size); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	retval = ext2fs_fallocate(fs, | ||||||
|  | 			EXT2_FALLOCATE_FORCE_INIT | EXT2_FALLOCATE_ZERO_BLOCKS, | ||||||
|  | 			dir, diri, 0, lblk, 1); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	retval = ext2fs_write_inode(fs, dir, diri); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	retval = ext2fs_bmap2(fs, dir, diri, NULL, 0, lblk, NULL, &pblk); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	/* Only leaf addition needed? */ | ||||||
|  | 	if (i == info->levels - 1) | ||||||
|  | 		return dx_split_leaf(fs, dir, diri, info, buf, leaf_pblk, | ||||||
|  | 				     lblk, pblk); | ||||||
|  | 
 | ||||||
|  | 	de = (struct ext2_dir_entry*)buf; | ||||||
|  | 	de->inode = 0; | ||||||
|  | 	ext2fs_dirent_set_name_len(de, 0); | ||||||
|  | 	ext2fs_dirent_set_file_type(de, 0); | ||||||
|  | 	retval = ext2fs_set_rec_len(fs, fs->blocksize, de); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	head = (struct ext2_dx_countlimit*)(buf + 8); | ||||||
|  | 	count = ext2fs_le16_to_cpu(info->frames[i+1].head->count); | ||||||
|  | 	/* Growing tree depth? */ | ||||||
|  | 	if (i < 0) { | ||||||
|  | 		struct ext2_dx_root_info *root; | ||||||
|  | 
 | ||||||
|  | 		memcpy(head, info->frames[0].entries, | ||||||
|  | 		       count * sizeof(struct ext2_dx_entry)); | ||||||
|  | 		head->limit = ext2fs_cpu_to_le16( | ||||||
|  | 				(fs->blocksize - (8 + csum_size)) / | ||||||
|  | 				sizeof(struct ext2_dx_entry)); | ||||||
|  | 		/* head->count gets set by memcpy above to correct value */ | ||||||
|  | 
 | ||||||
|  | 		/* Now update tree root */ | ||||||
|  | 		info->frames[0].head->count = ext2fs_cpu_to_le16(1); | ||||||
|  | 		info->frames[0].entries[0].block = ext2fs_cpu_to_le32(lblk); | ||||||
|  | 		root = (struct ext2_dx_root_info*)(info->frames[0].buf + EXT2_DX_ROOT_OFF); | ||||||
|  | 		root->indirect_levels++; | ||||||
|  | 	} else { | ||||||
|  | 		/* Splitting internal node in two */ | ||||||
|  | 		int count1 = count / 2; | ||||||
|  | 		int count2 = count - count1; | ||||||
|  | 		__u32 split_hash = ext2fs_le32_to_cpu(info->frames[i+1].entries[count1].hash); | ||||||
|  | 
 | ||||||
|  | 		memcpy(head, info->frames[i+1].entries + count1, | ||||||
|  | 		       count2 * sizeof(struct ext2_dx_entry)); | ||||||
|  | 		head->count = ext2fs_cpu_to_le16(count2); | ||||||
|  | 		head->limit = ext2fs_cpu_to_le16( | ||||||
|  | 				(fs->blocksize - (8ULL + csum_size)) / | ||||||
|  | 				sizeof(struct ext2_dx_entry)); | ||||||
|  | 		info->frames[i+1].head->count = ext2fs_cpu_to_le16(count1); | ||||||
|  | 
 | ||||||
|  | 		/* Update parent node */ | ||||||
|  | 		retval = dx_insert_entry(fs, dir, info, i, split_hash, lblk); | ||||||
|  | 		if (retval) | ||||||
|  | 			return retval; | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 	/* Writeout split block / updated root */ | ||||||
|  | 	retval = ext2fs_write_dir_block4(fs, info->frames[i+1].pblock, | ||||||
|  | 					 info->frames[i+1].buf, 0, dir); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	/* Writeout new tree block */ | ||||||
|  | 	retval = ext2fs_write_dir_block4(fs, pblk, buf, 0, dir); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static errcode_t dx_link(ext2_filsys fs, ext2_ino_t dir, | ||||||
|  | 			 struct ext2_inode *diri, const char *name, | ||||||
|  | 			 ext2_ino_t ino, int flags) | ||||||
|  | { | ||||||
|  | 	struct dx_lookup_info dx_info; | ||||||
|  | 	errcode_t retval; | ||||||
|  | 	void *blockbuf; | ||||||
|  | 	int restart = 0; | ||||||
|  | 	blk64_t leaf_pblk; | ||||||
|  | 
 | ||||||
|  | 	retval = ext2fs_get_mem(fs->blocksize, &blockbuf); | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  | 
 | ||||||
|  | 	dx_info.name = name; | ||||||
|  | 	dx_info.namelen = strlen(name); | ||||||
|  | again: | ||||||
|  | 	retval = dx_lookup(fs, dir, diri, &dx_info); | ||||||
|  | 	if (retval) | ||||||
|  | 		goto free_buf; | ||||||
|  | 
 | ||||||
|  | 	retval = add_dirent_to_buf(fs, | ||||||
|  | 		ext2fs_le32_to_cpu(dx_info.frames[dx_info.levels-1].at->block) & 0x0fffffff, | ||||||
|  | 		blockbuf, dir, diri, name, ino, flags, &leaf_pblk); | ||||||
|  | 	/*
 | ||||||
|  | 	 * Success or error other than ENOSPC...? We are done. We may need upto | ||||||
|  | 	 * two tries to add entry. One to split htree node and another to add | ||||||
|  | 	 * new leaf block. | ||||||
|  | 	 */ | ||||||
|  | 	if (restart >= dx_info.levels || retval != EXT2_ET_DIR_NO_SPACE) | ||||||
|  | 		goto free_frames; | ||||||
|  | 	retval = dx_grow_tree(fs, dir, diri, &dx_info, blockbuf, leaf_pblk); | ||||||
|  | 	if (retval) | ||||||
|  | 		goto free_frames; | ||||||
|  | 	/* Restart everything now that the tree is larger */ | ||||||
|  | 	restart++; | ||||||
|  | 	dx_release(&dx_info); | ||||||
|  | 	goto again; | ||||||
|  | free_frames: | ||||||
|  | 	dx_release(&dx_info); | ||||||
|  | free_buf: | ||||||
|  | 	ext2fs_free_mem(&blockbuf); | ||||||
|  | 	return retval; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Note: the low 3 bits of the flags field are used as the directory |  * Note: the low 3 bits of the flags field are used as the directory | ||||||
|  * entry filetype. |  * entry filetype. | ||||||
|  | @ -163,6 +616,12 @@ errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, | ||||||
| 	if (!(fs->flags & EXT2_FLAG_RW)) | 	if (!(fs->flags & EXT2_FLAG_RW)) | ||||||
| 		return EXT2_ET_RO_FILSYS; | 		return EXT2_ET_RO_FILSYS; | ||||||
| 
 | 
 | ||||||
|  | 	if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) | ||||||
|  | 		return retval; | ||||||
|  | 
 | ||||||
|  | 	if (inode.i_flags & EXT2_INDEX_FL) | ||||||
|  | 		return dx_link(fs, dir, &inode, name, ino, flags); | ||||||
|  | 
 | ||||||
| 	ls.fs = fs; | 	ls.fs = fs; | ||||||
| 	ls.name = name; | 	ls.name = name; | ||||||
| 	ls.namelen = name ? strlen(name) : 0; | 	ls.namelen = name ? strlen(name) : 0; | ||||||
|  | @ -173,8 +632,8 @@ errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, | ||||||
| 	ls.blocksize = fs->blocksize; | 	ls.blocksize = fs->blocksize; | ||||||
| 	ls.err = 0; | 	ls.err = 0; | ||||||
| 
 | 
 | ||||||
| 	retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, | 	retval = ext2fs_dir_iterate2(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, | ||||||
| 				    0, link_proc, &ls); | 				     NULL, link_proc, &ls); | ||||||
| 	if (retval) | 	if (retval) | ||||||
| 		return retval; | 		return retval; | ||||||
| 	if (ls.err) | 	if (ls.err) | ||||||
|  | @ -182,20 +641,5 @@ errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, | ||||||
| 
 | 
 | ||||||
| 	if (!ls.done) | 	if (!ls.done) | ||||||
| 		return EXT2_ET_DIR_NO_SPACE; | 		return EXT2_ET_DIR_NO_SPACE; | ||||||
| 
 |  | ||||||
| 	if ((retval = ext2fs_read_inode(fs, dir, &inode)) != 0) |  | ||||||
| 		return retval; |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * If this function changes to preserve the htree, remove the |  | ||||||
| 	 * two hunks in link_proc that shove checksum tails into the |  | ||||||
| 	 * former dx_root/dx_node blocks. |  | ||||||
| 	 */ |  | ||||||
| 	if (inode.i_flags & EXT2_INDEX_FL) { |  | ||||||
| 		inode.i_flags &= ~EXT2_INDEX_FL; |  | ||||||
| 		if ((retval = ext2fs_write_inode(fs, dir, &inode)) != 0) |  | ||||||
| 			return retval; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -43,6 +43,7 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | ||||||
| 	blk64_t			blk; | 	blk64_t			blk; | ||||||
| 	char			*block = 0; | 	char			*block = 0; | ||||||
| 	int			inline_data = 0; | 	int			inline_data = 0; | ||||||
|  | 	int			drop_refcount = 0; | ||||||
| 
 | 
 | ||||||
| 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | ||||||
| 
 | 
 | ||||||
|  | @ -143,6 +144,14 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Update accounting.... | ||||||
|  | 	 */ | ||||||
|  | 	if (!inline_data) | ||||||
|  | 		ext2fs_block_alloc_stats2(fs, blk, +1); | ||||||
|  | 	ext2fs_inode_alloc_stats2(fs, ino, +1, 1); | ||||||
|  | 	drop_refcount = 1; | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Link the directory into the filesystem hierarchy | 	 * Link the directory into the filesystem hierarchy | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -174,17 +183,16 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | ||||||
| 		if (retval) | 		if (retval) | ||||||
| 			goto cleanup; | 			goto cleanup; | ||||||
| 	} | 	} | ||||||
| 
 | 	drop_refcount = 0; | ||||||
| 	/*
 |  | ||||||
| 	 * Update accounting.... |  | ||||||
| 	 */ |  | ||||||
| 	if (!inline_data) |  | ||||||
| 		ext2fs_block_alloc_stats2(fs, blk, +1); |  | ||||||
| 	ext2fs_inode_alloc_stats2(fs, ino, +1, 1); |  | ||||||
| 
 | 
 | ||||||
| cleanup: | cleanup: | ||||||
| 	if (block) | 	if (block) | ||||||
| 		ext2fs_free_mem(&block); | 		ext2fs_free_mem(&block); | ||||||
|  | 	if (drop_refcount) { | ||||||
|  | 		if (!inline_data) | ||||||
|  | 			ext2fs_block_alloc_stats2(fs, blk, -1); | ||||||
|  | 		ext2fs_inode_alloc_stats2(fs, ino, -1, 1); | ||||||
|  | 	} | ||||||
| 	return retval; | 	return retval; | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, | ||||||
| 	errcode_t		retval; | 	errcode_t		retval; | ||||||
| 	journal_superblock_t	*jsb; | 	journal_superblock_t	*jsb; | ||||||
| 
 | 
 | ||||||
| 	if (num_blocks < JFS_MIN_JOURNAL_BLOCKS) | 	if (num_blocks < JBD2_MIN_JOURNAL_BLOCKS) | ||||||
| 		return EXT2_ET_JOURNAL_TOO_SMALL; | 		return EXT2_ET_JOURNAL_TOO_SMALL; | ||||||
| 
 | 
 | ||||||
| 	if ((retval = ext2fs_get_mem(fs->blocksize, &jsb))) | 	if ((retval = ext2fs_get_mem(fs->blocksize, &jsb))) | ||||||
|  | @ -60,11 +60,11 @@ errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, | ||||||
| 
 | 
 | ||||||
| 	memset (jsb, 0, fs->blocksize); | 	memset (jsb, 0, fs->blocksize); | ||||||
| 
 | 
 | ||||||
| 	jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); | 	jsb->s_header.h_magic = htonl(JBD2_MAGIC_NUMBER); | ||||||
| 	if (flags & EXT2_MKJOURNAL_V1_SUPER) | 	if (flags & EXT2_MKJOURNAL_V1_SUPER) | ||||||
| 		jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V1); | 		jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V1); | ||||||
| 	else | 	else | ||||||
| 		jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2); | 		jsb->s_header.h_blocktype = htonl(JBD2_SUPERBLOCK_V2); | ||||||
| 	jsb->s_blocksize = htonl(fs->blocksize); | 	jsb->s_blocksize = htonl(fs->blocksize); | ||||||
| 	jsb->s_maxlen = htonl(num_blocks); | 	jsb->s_maxlen = htonl(num_blocks); | ||||||
| 	jsb->s_nr_users = htonl(1); | 	jsb->s_nr_users = htonl(1); | ||||||
|  | @ -394,8 +394,8 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev) | ||||||
| 		return retval; | 		return retval; | ||||||
| 
 | 
 | ||||||
| 	jsb = (journal_superblock_t *) buf; | 	jsb = (journal_superblock_t *) buf; | ||||||
| 	if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || | 	if ((jsb->s_header.h_magic != (unsigned) ntohl(JBD2_MAGIC_NUMBER)) || | ||||||
| 	    (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) | 	    (jsb->s_header.h_blocktype != (unsigned) ntohl(JBD2_SUPERBLOCK_V2))) | ||||||
| 		return EXT2_ET_NO_JOURNAL_SB; | 		return EXT2_ET_NO_JOURNAL_SB; | ||||||
| 
 | 
 | ||||||
| 	if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize) | 	if (ntohl(jsb->s_blocksize) != (unsigned long) fs->blocksize) | ||||||
|  | @ -403,7 +403,7 @@ errcode_t ext2fs_add_journal_device(ext2_filsys fs, ext2_filsys journal_dev) | ||||||
| 
 | 
 | ||||||
| 	/* Check and see if this filesystem has already been added */ | 	/* Check and see if this filesystem has already been added */ | ||||||
| 	nr_users = ntohl(jsb->s_nr_users); | 	nr_users = ntohl(jsb->s_nr_users); | ||||||
| 	if (nr_users > JFS_USERS_MAX) | 	if (nr_users > JBD2_USERS_MAX) | ||||||
| 		return EXT2_ET_CORRUPT_JOURNAL_SB; | 		return EXT2_ET_CORRUPT_JOURNAL_SB; | ||||||
| 	for (i=0; i < nr_users; i++) { | 	for (i=0; i < nr_users; i++) { | ||||||
| 		if (memcmp(fs->super->s_uuid, | 		if (memcmp(fs->super->s_uuid, | ||||||
|  | @ -575,7 +575,7 @@ main(int argc, char **argv) | ||||||
| 		exit(1); | 		exit(1); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	retval = ext2fs_add_journal_inode(fs, JFS_MIN_JOURNAL_BLOCKS, 0); | 	retval = ext2fs_add_journal_inode(fs, JBD2_MIN_JOURNAL_BLOCKS, 0); | ||||||
| 	if (retval) { | 	if (retval) { | ||||||
| 		com_err(argv[0], retval, "while adding journal to %s", | 		com_err(argv[0], retval, "while adding journal to %s", | ||||||
| 			device_name); | 			device_name); | ||||||
|  |  | ||||||
|  | @ -59,8 +59,21 @@ errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf) | ||||||
| 	 * regardless of how the io_manager is doing reads, to avoid caching of | 	 * regardless of how the io_manager is doing reads, to avoid caching of | ||||||
| 	 * the MMP block by the io_manager or the VM.  It needs to be fresh. */ | 	 * the MMP block by the io_manager or the VM.  It needs to be fresh. */ | ||||||
| 	if (fs->mmp_fd <= 0) { | 	if (fs->mmp_fd <= 0) { | ||||||
| 		fs->mmp_fd = open(fs->device_name, O_RDWR | O_DIRECT); | 		int flags = O_RDWR | O_DIRECT; | ||||||
|  | 
 | ||||||
|  | retry: | ||||||
|  | 		fs->mmp_fd = open(fs->device_name, flags); | ||||||
| 		if (fs->mmp_fd < 0) { | 		if (fs->mmp_fd < 0) { | ||||||
|  | 			struct stat st; | ||||||
|  | 
 | ||||||
|  | 			/* Avoid O_DIRECT for filesystem image files if open
 | ||||||
|  | 			 * fails, since it breaks when running on tmpfs. */ | ||||||
|  | 			if (errno == EINVAL && (flags & O_DIRECT) && | ||||||
|  | 			    stat(fs->device_name, &st) == 0 && | ||||||
|  | 			    S_ISREG(st.st_mode)) { | ||||||
|  | 				flags &= ~O_DIRECT; | ||||||
|  | 				goto retry; | ||||||
|  | 			} | ||||||
| 			retval = EXT2_ET_MMP_OPEN_DIRECT; | 			retval = EXT2_ET_MMP_OPEN_DIRECT; | ||||||
| 			goto out; | 			goto out; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -81,7 +81,7 @@ static errcode_t nt_write_blk(io_channel channel, unsigned long block, int count | ||||||
| static errcode_t nt_write_blk64(io_channel channel, unsigned long long block, int count, const void* data); | static errcode_t nt_write_blk64(io_channel channel, unsigned long long block, int count, const void* data); | ||||||
| static errcode_t nt_flush(io_channel channel); | static errcode_t nt_flush(io_channel channel); | ||||||
| 
 | 
 | ||||||
| static struct struct_io_manager struct_nt_manager = { | struct struct_io_manager struct_nt_manager = { | ||||||
| 	.magic		= EXT2_ET_MAGIC_IO_MANAGER, | 	.magic		= EXT2_ET_MAGIC_IO_MANAGER, | ||||||
| 	.name		= "NT I/O Manager", | 	.name		= "NT I/O Manager", | ||||||
| 	.open		= nt_open, | 	.open		= nt_open, | ||||||
|  | @ -94,10 +94,7 @@ static struct struct_io_manager struct_nt_manager = { | ||||||
| 	.flush		= nt_flush | 	.flush		= nt_flush | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| io_manager nt_io_manager(void) | io_manager nt_io_manager = &struct_nt_manager; | ||||||
| { |  | ||||||
| 	return &struct_nt_manager; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| // Convert Win32 errors to unix errno
 | // Convert Win32 errors to unix errno
 | ||||||
| typedef struct { | typedef struct { | ||||||
|  | @ -530,7 +527,7 @@ static errcode_t nt_open(const char *name, int flags, io_channel *channel) | ||||||
| 
 | 
 | ||||||
| 	// Initialize data
 | 	// Initialize data
 | ||||||
| 	io->magic = EXT2_ET_MAGIC_IO_CHANNEL; | 	io->magic = EXT2_ET_MAGIC_IO_CHANNEL; | ||||||
| 	io->manager = nt_io_manager(); | 	io->manager = nt_io_manager; | ||||||
| 	strcpy(io->name, name); | 	strcpy(io->name, name); | ||||||
| 	io->block_size = EXT2_MIN_BLOCK_SIZE; | 	io->block_size = EXT2_MIN_BLOCK_SIZE; | ||||||
| 	io->refcount = 1; | 	io->refcount = 1; | ||||||
|  |  | ||||||
|  | @ -29,7 +29,6 @@ | ||||||
| 
 | 
 | ||||||
| #include "ext2_fs.h" | #include "ext2_fs.h" | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #include "ext2fs.h" | #include "ext2fs.h" | ||||||
| #include "e2image.h" | #include "e2image.h" | ||||||
| 
 | 
 | ||||||
|  | @ -135,6 +134,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | ||||||
| 	int		j; | 	int		j; | ||||||
| #endif | #endif | ||||||
| 	char		*time_env; | 	char		*time_env; | ||||||
|  | 	int		csum_retries = 0; | ||||||
| 
 | 
 | ||||||
| 	EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER); | 	EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER); | ||||||
| 
 | 
 | ||||||
|  | @ -223,6 +223,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | ||||||
| 		if (retval) | 		if (retval) | ||||||
| 			goto cleanup; | 			goto cleanup; | ||||||
| 	} | 	} | ||||||
|  | retry: | ||||||
| 	retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE, | 	retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE, | ||||||
| 				     fs->super); | 				     fs->super); | ||||||
| 	if (retval) | 	if (retval) | ||||||
|  | @ -234,8 +235,11 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | ||||||
| 		retval = 0; | 		retval = 0; | ||||||
| 		if (!ext2fs_verify_csum_type(fs, fs->super)) | 		if (!ext2fs_verify_csum_type(fs, fs->super)) | ||||||
| 			retval = EXT2_ET_UNKNOWN_CSUM; | 			retval = EXT2_ET_UNKNOWN_CSUM; | ||||||
| 		if (!ext2fs_superblock_csum_verify(fs, fs->super)) | 		if (!ext2fs_superblock_csum_verify(fs, fs->super)) { | ||||||
|  | 			if (csum_retries++ < 3) | ||||||
|  | 				goto retry; | ||||||
| 			retval = EXT2_ET_SB_CSUM_INVALID; | 			retval = EXT2_ET_SB_CSUM_INVALID; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| #ifdef WORDS_BIGENDIAN | #ifdef WORDS_BIGENDIAN | ||||||
|  | @ -395,6 +399,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | ||||||
| 	} | 	} | ||||||
| 	fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, | 	fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, | ||||||
| 					  EXT2_DESC_PER_BLOCK(fs->super)); | 					  EXT2_DESC_PER_BLOCK(fs->super)); | ||||||
|  | 	if (flags & EXT2_FLAG_SUPER_ONLY) | ||||||
|  | 		goto skip_read_bg; | ||||||
| 	retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, | 	retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, | ||||||
| 				&fs->group_desc); | 				&fs->group_desc); | ||||||
| 	if (retval) | 	if (retval) | ||||||
|  | @ -435,7 +441,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | ||||||
| 		gdp = (struct ext2_group_desc *) dest; | 		gdp = (struct ext2_group_desc *) dest; | ||||||
| 		for (j=0; j < groups_per_block*first_meta_bg; j++) { | 		for (j=0; j < groups_per_block*first_meta_bg; j++) { | ||||||
| 			gdp = ext2fs_group_desc(fs, fs->group_desc, j); | 			gdp = ext2fs_group_desc(fs, fs->group_desc, j); | ||||||
| 			ext2fs_swap_group_desc2(fs, gdp); | 			if (gdp) | ||||||
|  | 				ext2fs_swap_group_desc2(fs, gdp); | ||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
| 		dest += fs->blocksize*first_meta_bg; | 		dest += fs->blocksize*first_meta_bg; | ||||||
|  | @ -455,7 +462,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | ||||||
| 		for (j=0; j < groups_per_block; j++) { | 		for (j=0; j < groups_per_block; j++) { | ||||||
| 			gdp = ext2fs_group_desc(fs, fs->group_desc, | 			gdp = ext2fs_group_desc(fs, fs->group_desc, | ||||||
| 						i * groups_per_block + j); | 						i * groups_per_block + j); | ||||||
| 			ext2fs_swap_group_desc2(fs, gdp); | 			if (gdp) | ||||||
|  | 				ext2fs_swap_group_desc2(fs, gdp); | ||||||
| 		} | 		} | ||||||
| #endif | #endif | ||||||
| 		dest += fs->blocksize; | 		dest += fs->blocksize; | ||||||
|  | @ -481,7 +489,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | ||||||
| 		if (fs->flags & EXT2_FLAG_RW) | 		if (fs->flags & EXT2_FLAG_RW) | ||||||
| 			ext2fs_mark_super_dirty(fs); | 			ext2fs_mark_super_dirty(fs); | ||||||
| 	} | 	} | ||||||
| 
 | skip_read_bg: | ||||||
| 	if (ext2fs_has_feature_mmp(fs->super) && | 	if (ext2fs_has_feature_mmp(fs->super) && | ||||||
| 	    !(flags & EXT2_FLAG_SKIP_MMP) && | 	    !(flags & EXT2_FLAG_SKIP_MMP) && | ||||||
| 	    (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) { | 	    (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) { | ||||||
|  | @ -503,6 +511,9 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | ||||||
| 		ext2fs_set_feature_shared_blocks(fs->super); | 		ext2fs_set_feature_shared_blocks(fs->super); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | //	if (ext2fs_has_feature_casefold(fs->super))
 | ||||||
|  | //		fs->encoding = ext2fs_load_nls_table(fs->super->s_encoding);
 | ||||||
|  | 
 | ||||||
| 	fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; | 	fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; | ||||||
| 	*ret_fs = fs; | 	*ret_fs = fs; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -195,6 +195,16 @@ static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int bitmap_tail_verify(unsigned char *bitmap, int first, int last) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 
 | ||||||
|  | 	for (i = first; i <= last; i++) | ||||||
|  | 		if (bitmap[i] != 0xff) | ||||||
|  | 			return 0; | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | ||||||
| { | { | ||||||
| 	dgrp_t i; | 	dgrp_t i; | ||||||
|  | @ -203,6 +213,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | ||||||
| 	errcode_t retval; | 	errcode_t retval; | ||||||
| 	int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; | 	int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; | ||||||
| 	int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; | 	int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; | ||||||
|  | 	int tail_flags = 0; | ||||||
| 	int csum_flag; | 	int csum_flag; | ||||||
| 	unsigned int	cnt; | 	unsigned int	cnt; | ||||||
| 	blk64_t	blk; | 	blk64_t	blk; | ||||||
|  | @ -295,9 +306,10 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | ||||||
| 	for (i = 0; i < fs->group_desc_count; i++) { | 	for (i = 0; i < fs->group_desc_count; i++) { | ||||||
| 		if (block_bitmap) { | 		if (block_bitmap) { | ||||||
| 			blk = ext2fs_block_bitmap_loc(fs, i); | 			blk = ext2fs_block_bitmap_loc(fs, i); | ||||||
| 			if (csum_flag && | 			if ((csum_flag && | ||||||
| 			    ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) && | 			     ext2fs_bg_flags_test(fs, i, EXT2_BG_BLOCK_UNINIT) && | ||||||
| 			    ext2fs_group_desc_csum_verify(fs, i)) | 			     ext2fs_group_desc_csum_verify(fs, i)) || | ||||||
|  | 			    (blk >= ext2fs_blocks_count(fs->super))) | ||||||
| 				blk = 0; | 				blk = 0; | ||||||
| 			if (blk) { | 			if (blk) { | ||||||
| 				retval = io_channel_read_blk64(fs->io, blk, | 				retval = io_channel_read_blk64(fs->io, blk, | ||||||
|  | @ -315,6 +327,9 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | ||||||
| 					EXT2_ET_BLOCK_BITMAP_CSUM_INVALID; | 					EXT2_ET_BLOCK_BITMAP_CSUM_INVALID; | ||||||
| 					goto cleanup; | 					goto cleanup; | ||||||
| 				} | 				} | ||||||
|  | 				if (!bitmap_tail_verify((unsigned char *) block_bitmap, | ||||||
|  | 							block_nbytes, fs->blocksize - 1)) | ||||||
|  | 					tail_flags |= EXT2_FLAG_BBITMAP_TAIL_PROBLEM; | ||||||
| 			} else | 			} else | ||||||
| 				memset(block_bitmap, 0, block_nbytes); | 				memset(block_bitmap, 0, block_nbytes); | ||||||
| 			cnt = block_nbytes << 3; | 			cnt = block_nbytes << 3; | ||||||
|  | @ -322,13 +337,14 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | ||||||
| 					       blk_itr, cnt, block_bitmap); | 					       blk_itr, cnt, block_bitmap); | ||||||
| 			if (retval) | 			if (retval) | ||||||
| 				goto cleanup; | 				goto cleanup; | ||||||
| 			blk_itr += (blk64_t)block_nbytes << 3; | 			blk_itr += block_nbytes << 3; | ||||||
| 		} | 		} | ||||||
| 		if (inode_bitmap) { | 		if (inode_bitmap) { | ||||||
| 			blk = ext2fs_inode_bitmap_loc(fs, i); | 			blk = ext2fs_inode_bitmap_loc(fs, i); | ||||||
| 			if (csum_flag && | 			if ((csum_flag && | ||||||
| 			    ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) && | 			     ext2fs_bg_flags_test(fs, i, EXT2_BG_INODE_UNINIT) && | ||||||
| 			    ext2fs_group_desc_csum_verify(fs, i)) | 			     ext2fs_group_desc_csum_verify(fs, i)) || | ||||||
|  | 			    (blk >= ext2fs_blocks_count(fs->super))) | ||||||
| 				blk = 0; | 				blk = 0; | ||||||
| 			if (blk) { | 			if (blk) { | ||||||
| 				retval = io_channel_read_blk64(fs->io, blk, | 				retval = io_channel_read_blk64(fs->io, blk, | ||||||
|  | @ -347,6 +363,9 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | ||||||
| 					EXT2_ET_INODE_BITMAP_CSUM_INVALID; | 					EXT2_ET_INODE_BITMAP_CSUM_INVALID; | ||||||
| 					goto cleanup; | 					goto cleanup; | ||||||
| 				} | 				} | ||||||
|  | 				if (!bitmap_tail_verify((unsigned char *) inode_bitmap, | ||||||
|  | 							inode_nbytes, fs->blocksize - 1)) | ||||||
|  | 					tail_flags |= EXT2_FLAG_IBITMAP_TAIL_PROBLEM; | ||||||
| 			} else | 			} else | ||||||
| 				memset(inode_bitmap, 0, inode_nbytes); | 				memset(inode_bitmap, 0, inode_nbytes); | ||||||
| 			cnt = inode_nbytes << 3; | 			cnt = inode_nbytes << 3; | ||||||
|  | @ -366,19 +385,24 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| success_cleanup: | success_cleanup: | ||||||
| 	if (inode_bitmap) | 	if (inode_bitmap) { | ||||||
| 		ext2fs_free_mem(&inode_bitmap); | 		ext2fs_free_mem(&inode_bitmap); | ||||||
| 	if (block_bitmap) | 		fs->flags &= ~EXT2_FLAG_IBITMAP_TAIL_PROBLEM; | ||||||
|  | 	} | ||||||
|  | 	if (block_bitmap) { | ||||||
| 		ext2fs_free_mem(&block_bitmap); | 		ext2fs_free_mem(&block_bitmap); | ||||||
|  | 		fs->flags &= ~EXT2_FLAG_BBITMAP_TAIL_PROBLEM; | ||||||
|  | 	} | ||||||
|  | 	fs->flags |= tail_flags; | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| cleanup: | cleanup: | ||||||
| 	if (do_block) { | 	if (do_block) { | ||||||
| 		ext2fs_free_mem(&fs->block_map); | 		ext2fs_free_block_bitmap(fs->block_map); | ||||||
| 		fs->block_map = 0; | 		fs->block_map = 0; | ||||||
| 	} | 	} | ||||||
| 	if (do_inode) { | 	if (do_inode) { | ||||||
| 		ext2fs_free_mem(&fs->inode_map); | 		ext2fs_free_inode_bitmap(fs->inode_map); | ||||||
| 		fs->inode_map = 0; | 		fs->inode_map = 0; | ||||||
| 	} | 	} | ||||||
| 	if (inode_bitmap) | 	if (inode_bitmap) | ||||||
|  |  | ||||||
|  | @ -54,6 +54,7 @@ errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino, | ||||||
| 	int			fastlink, inlinelink; | 	int			fastlink, inlinelink; | ||||||
| 	unsigned int		target_len; | 	unsigned int		target_len; | ||||||
| 	char			*block_buf = 0; | 	char			*block_buf = 0; | ||||||
|  | 	int			drop_refcount = 0; | ||||||
| 
 | 
 | ||||||
| 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | ||||||
| 
 | 
 | ||||||
|  | @ -162,6 +163,14 @@ need_block: | ||||||
| 			goto cleanup; | 			goto cleanup; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * Update accounting.... | ||||||
|  | 	 */ | ||||||
|  | 	if (!fastlink && !inlinelink) | ||||||
|  | 		ext2fs_block_alloc_stats2(fs, blk, +1); | ||||||
|  | 	ext2fs_inode_alloc_stats2(fs, ino, +1, 0); | ||||||
|  | 	drop_refcount = 1; | ||||||
|  | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Link the symlink into the filesystem hierarchy | 	 * Link the symlink into the filesystem hierarchy | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -178,17 +187,16 @@ need_block: | ||||||
| 		if (retval) | 		if (retval) | ||||||
| 			goto cleanup; | 			goto cleanup; | ||||||
| 	} | 	} | ||||||
| 
 | 	drop_refcount = 0; | ||||||
| 	/*
 |  | ||||||
| 	 * Update accounting.... |  | ||||||
| 	 */ |  | ||||||
| 	if (!fastlink && !inlinelink) |  | ||||||
| 		ext2fs_block_alloc_stats2(fs, blk, +1); |  | ||||||
| 	ext2fs_inode_alloc_stats2(fs, ino, +1, 0); |  | ||||||
| 
 | 
 | ||||||
| cleanup: | cleanup: | ||||||
| 	if (block_buf) | 	if (block_buf) | ||||||
| 		ext2fs_free_mem(&block_buf); | 		ext2fs_free_mem(&block_buf); | ||||||
|  | 	if (drop_refcount) { | ||||||
|  | 		if (!fastlink && !inlinelink) | ||||||
|  | 			ext2fs_block_alloc_stats2(fs, blk, -1); | ||||||
|  | 		ext2fs_inode_alloc_stats2(fs, ino, -1, 0); | ||||||
|  | 	} | ||||||
| 	return retval; | 	return retval; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ | ||||||
| #include "ext2fs/ext2fs.h" | #include "ext2fs/ext2fs.h" | ||||||
| 
 | 
 | ||||||
| extern const char* FileSystemLabel[FS_MAX]; | extern const char* FileSystemLabel[FS_MAX]; | ||||||
| extern io_manager nt_io_manager(void); | extern io_manager nt_io_manager; | ||||||
| extern DWORD ext2_last_winerror(DWORD default_error); | extern DWORD ext2_last_winerror(DWORD default_error); | ||||||
| static float ext2_percent_start = 0.0f, ext2_percent_share = 0.5f; | static float ext2_percent_start = 0.0f, ext2_percent_share = 0.5f; | ||||||
| const float ext2_max_marker = 80.0f; | const float ext2_max_marker = 80.0f; | ||||||
|  | @ -172,6 +172,8 @@ const char* error_message(errcode_t error_code) | ||||||
| 	case EXT2_ET_INODE_CORRUPTED: | 	case EXT2_ET_INODE_CORRUPTED: | ||||||
| 	case EXT2_ET_EA_INODE_CORRUPTED: | 	case EXT2_ET_EA_INODE_CORRUPTED: | ||||||
| 		return "Inode is corrupted"; | 		return "Inode is corrupted"; | ||||||
|  | 	case EXT2_ET_NO_GDESC: | ||||||
|  | 		return "Group descriptors not loaded"; | ||||||
| 	default: | 	default: | ||||||
| 		if ((error_code > EXT2_ET_BASE) && error_code < (EXT2_ET_BASE + 1000)) { | 		if ((error_code > EXT2_ET_BASE) && error_code < (EXT2_ET_BASE + 1000)) { | ||||||
| 			static_sprintf(error_string, "Unknown ext2fs error %ld (EXT2_ET_BASE + %ld)", error_code, error_code - EXT2_ET_BASE); | 			static_sprintf(error_string, "Unknown ext2fs error %ld (EXT2_ET_BASE + %ld)", error_code, error_code - EXT2_ET_BASE); | ||||||
|  | @ -202,7 +204,7 @@ const char* GetExtFsLabel(DWORD DriveIndex, uint64_t PartitionOffset) | ||||||
| 	static char label[EXT2_LABEL_LEN + 1]; | 	static char label[EXT2_LABEL_LEN + 1]; | ||||||
| 	errcode_t r; | 	errcode_t r; | ||||||
| 	ext2_filsys ext2fs = NULL; | 	ext2_filsys ext2fs = NULL; | ||||||
| 	io_manager manager = nt_io_manager(); | 	io_manager manager = nt_io_manager; | ||||||
| 	char* volume_name = GetExtPartitionName(DriveIndex, PartitionOffset); | 	char* volume_name = GetExtPartitionName(DriveIndex, PartitionOffset); | ||||||
| 
 | 
 | ||||||
| 	if (volume_name == NULL) | 	if (volume_name == NULL) | ||||||
|  | @ -238,7 +240,7 @@ BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LP | ||||||
| 	char* volume_name = NULL; | 	char* volume_name = NULL; | ||||||
| 	int i, count; | 	int i, count; | ||||||
| 	struct ext2_super_block features = { 0 }; | 	struct ext2_super_block features = { 0 }; | ||||||
| 	io_manager manager = nt_io_manager(); | 	io_manager manager = nt_io_manager; | ||||||
| 	blk_t journal_size; | 	blk_t journal_size; | ||||||
| 	blk64_t size = 0, cur; | 	blk64_t size = 0, cur; | ||||||
| 	ext2_filsys ext2fs = NULL; | 	ext2_filsys ext2fs = NULL; | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -35,7 +35,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL | ||||||
| IDD_DIALOG DIALOGEX 12, 12, 232, 326 | IDD_DIALOG DIALOGEX 12, 12, 232, 326 | ||||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||||
| EXSTYLE WS_EX_ACCEPTFILES | EXSTYLE WS_EX_ACCEPTFILES | ||||||
| CAPTION "Rufus 3.14.1732" | CAPTION "Rufus 3.14.1733" | ||||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||||
| BEGIN | BEGIN | ||||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP |     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||||
|  | @ -397,8 +397,8 @@ END | ||||||
| // | // | ||||||
| 
 | 
 | ||||||
| VS_VERSION_INFO VERSIONINFO | VS_VERSION_INFO VERSIONINFO | ||||||
|  FILEVERSION 3,14,1732,0 |  FILEVERSION 3,14,1733,0 | ||||||
|  PRODUCTVERSION 3,14,1732,0 |  PRODUCTVERSION 3,14,1733,0 | ||||||
|  FILEFLAGSMASK 0x3fL |  FILEFLAGSMASK 0x3fL | ||||||
| #ifdef _DEBUG | #ifdef _DEBUG | ||||||
|  FILEFLAGS 0x1L |  FILEFLAGS 0x1L | ||||||
|  | @ -416,13 +416,13 @@ BEGIN | ||||||
|             VALUE "Comments", "https://rufus.ie" |             VALUE "Comments", "https://rufus.ie" | ||||||
|             VALUE "CompanyName", "Akeo Consulting" |             VALUE "CompanyName", "Akeo Consulting" | ||||||
|             VALUE "FileDescription", "Rufus" |             VALUE "FileDescription", "Rufus" | ||||||
|             VALUE "FileVersion", "3.14.1732" |             VALUE "FileVersion", "3.14.1733" | ||||||
|             VALUE "InternalName", "Rufus" |             VALUE "InternalName", "Rufus" | ||||||
|             VALUE "LegalCopyright", "© 2011-2021 Pete Batard (GPL v3)" |             VALUE "LegalCopyright", "© 2011-2021 Pete Batard (GPL v3)" | ||||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" |             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" | ||||||
|             VALUE "OriginalFilename", "rufus-3.14.exe" |             VALUE "OriginalFilename", "rufus-3.14.exe" | ||||||
|             VALUE "ProductName", "Rufus" |             VALUE "ProductName", "Rufus" | ||||||
|             VALUE "ProductVersion", "3.14.1732" |             VALUE "ProductVersion", "3.14.1733" | ||||||
|         END |         END | ||||||
|     END |     END | ||||||
|     BLOCK "VarFileInfo" |     BLOCK "VarFileInfo" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue