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\csum.c" /> | ||||
|     <ClCompile Include="..\src\ext2fs\dirblock.c" /> | ||||
|     <ClCompile Include="..\src\ext2fs\dirhash.c" /> | ||||
|     <ClCompile Include="..\src\ext2fs\dir_iterate.c" /> | ||||
|     <ClCompile Include="..\src\ext2fs\extent.c" /> | ||||
|     <ClCompile Include="..\src\ext2fs\ext_attr.c" /> | ||||
|  |  | |||
|  | @ -162,6 +162,9 @@ | |||
|     <ClCompile Include="..\src\ext2fs\namei.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\src\ext2fs\dirhash.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\src\ext2fs\ext2_fs.h"> | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| noinst_LIBRARIES = libext2fs.a | ||||
| 
 | ||||
| libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c       \ | ||||
| 	bitmaps.c bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c         \ | ||||
| 	crc32c.c csum.c dirblock.c dir_iterate.c extent.c ext_attr.c extent.c fallocate.c fileio.c       \ | ||||
| libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c bitmaps.c   \ | ||||
| 	bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c crc32c.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 \ | ||||
| 	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 | ||||
|  |  | |||
|  | @ -104,7 +104,7 @@ am_libext2fs_a_OBJECTS = libext2fs_a-alloc.$(OBJEXT) \ | |||
| 	libext2fs_a-block.$(OBJEXT) libext2fs_a-bmap.$(OBJEXT) \
 | ||||
| 	libext2fs_a-closefs.$(OBJEXT) libext2fs_a-crc16.$(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-ext_attr.$(OBJEXT) libext2fs_a-extent.$(OBJEXT) \
 | ||||
| 	libext2fs_a-fallocate.$(OBJEXT) libext2fs_a-fileio.$(OBJEXT) \
 | ||||
|  | @ -271,9 +271,9 @@ top_build_prefix = @top_build_prefix@ | |||
| top_builddir = @top_builddir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| noinst_LIBRARIES = libext2fs.a | ||||
| libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c       \
 | ||||
| 	bitmaps.c bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c         \
 | ||||
| 	crc32c.c csum.c dirblock.c dir_iterate.c extent.c ext_attr.c extent.c fallocate.c fileio.c       \
 | ||||
| libext2fs_a_SOURCES = alloc.c alloc_sb.c alloc_stats.c alloc_tables.c badblocks.c bb_inode.c bitmaps.c   \
 | ||||
| 	bitops.c blkmap64_ba.c blkmap64_rb.c blknum.c block.c bmap.c closefs.c crc16.c crc32c.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 \
 | ||||
| 	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 | ||||
|  | @ -442,6 +442,12 @@ libext2fs_a-dirblock.o: 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` | ||||
| 
 | ||||
| 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 | ||||
| 	$(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)); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 | ||||
|  */ | ||||
|  | @ -185,9 +201,42 @@ struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, | |||
| 					  struct opaque_ext2_group_desc *gdp, | ||||
| 					  dgrp_t group) | ||||
| { | ||||
| 	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 */ | ||||
|  |  | |||
|  | @ -293,6 +293,11 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags) | |||
| 
 | ||||
| 	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; | ||||
| 	feature_incompat = fs->super->s_feature_incompat; | ||||
| 
 | ||||
|  | @ -328,19 +333,23 @@ errcode_t ext2fs_flush2(ext2_filsys fs, int flags) | |||
| 	retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow); | ||||
| 	if (retval) | ||||
| 		goto errout; | ||||
| 	memcpy(super_shadow, fs->super, sizeof(struct ext2_super_block)); | ||||
| 	ext2fs_swap_super(super_shadow); | ||||
| 
 | ||||
| 	if (((fs->flags & EXT2_FLAG_SUPER_ONLY) == 0) && | ||||
| 	    !ext2fs_has_feature_journal_dev(fs->super)) { | ||||
| 		retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, | ||||
| 					  &group_shadow); | ||||
| 		if (retval) | ||||
| 			goto errout; | ||||
| 	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); | ||||
| 		for (j = 0; j < fs->group_desc_count; j++) { | ||||
| 			gdp = ext2fs_group_desc(fs, group_shadow, j); | ||||
| 			ext2fs_swap_group_desc2(fs, gdp); | ||||
| 		} | ||||
| 	} | ||||
| #else | ||||
| 	super_shadow = fs->super; | ||||
| 	group_shadow = fs->group_desc; | ||||
|  |  | |||
|  | @ -266,14 +266,15 @@ static errcode_t __get_dirent_tail(ext2_filsys fs, | |||
| 	d = dirent; | ||||
| 	top = EXT2_DIRENT_TAIL(dirent, fs->blocksize); | ||||
| 
 | ||||
| 	while ((void *) d < top) { | ||||
| 		rec_len = translate(d->rec_len); | ||||
| 	while (rec_len && !(rec_len & 0x3)) { | ||||
| 		if ((rec_len < 8) || (rec_len & 0x03)) | ||||
| 			return EXT2_ET_DIR_CORRUPTED; | ||||
| 		d = (struct ext2_dir_entry *)(((char *)d) + rec_len); | ||||
| 		if ((void *)d >= top) | ||||
| 			break; | ||||
| 		rec_len = translate(d->rec_len); | ||||
| 	} | ||||
| 
 | ||||
| 	if ((char *)d > ((char *)dirent + fs->blocksize)) | ||||
| 			return EXT2_ET_DIR_CORRUPTED; | ||||
| 	if (d != top) | ||||
| 		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) | ||||
| { | ||||
| 	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, | ||||
|  | @ -358,20 +360,31 @@ static errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum, | |||
| 	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, | ||||
| 				__u32 *crc, int count_offset, int count, | ||||
| 				struct ext2_dx_tail *t) | ||||
| 			 __u32 *crc, struct ext2_dx_tail **ret_t) | ||||
| { | ||||
| 	errcode_t retval; | ||||
| 	char *buf = (char *)dirent; | ||||
| 	int size; | ||||
| 	__u32 old_csum, gen; | ||||
| 	__u32 gen, dummy_csum = 0; | ||||
| 	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)); | ||||
| 	old_csum = t->dt_checksum; | ||||
| 	t->dt_checksum = 0; | ||||
| 
 | ||||
| 	retval = ext2fs_read_inode(fs, inum, &inode); | ||||
| 	if (retval) | ||||
|  | @ -383,10 +396,11 @@ static errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, | |||
| 				sizeof(inum)); | ||||
| 	*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 *)t, | ||||
| 				sizeof(struct ext2_dx_tail)); | ||||
| 	t->dt_checksum = old_csum; | ||||
| 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)t, 4); | ||||
| 	*crc = ext2fs_crc32c_le(*crc, (unsigned char *)&dummy_csum, 4); | ||||
| 
 | ||||
| 	if (ret_t) | ||||
| 		*ret_t = t; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -395,22 +409,9 @@ static int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum, | |||
| { | ||||
| 	__u32 calculated; | ||||
| 	errcode_t retval; | ||||
| 	struct ext2_dx_countlimit *c; | ||||
| 	struct ext2_dx_tail *t; | ||||
| 	int count_offset, limit, count; | ||||
| 
 | ||||
| 	retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); | ||||
| 	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); | ||||
| 	retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, &t); | ||||
| 	if (retval) | ||||
| 		return 0; | ||||
| 
 | ||||
|  | @ -422,22 +423,9 @@ static errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum, | |||
| { | ||||
| 	__u32 crc; | ||||
| 	errcode_t retval = 0; | ||||
| 	struct ext2_dx_countlimit *c; | ||||
| 	struct ext2_dx_tail *t; | ||||
| 	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; | ||||
| 	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); | ||||
| 	retval = ext2fs_dx_csum(fs, inum, dirent, &crc, &t); | ||||
| 	if (retval) | ||||
| 		return retval; | ||||
| 	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_INODE_CORRUPTED                  (2133571505L) | ||||
| #define EXT2_ET_EA_INODE_CORRUPTED               (2133571506L) | ||||
| #define EXT2_ET_NO_GDESC                         (2133571507L) | ||||
| extern const struct error_table et_ext2_error_table; | ||||
| extern void initialize_ext2_error_table(void); | ||||
| 
 | ||||
|  |  | |||
|  | @ -351,6 +351,7 @@ struct ext2_dx_tail { | |||
| /* EXT4_EOFBLOCKS_FL 0x00400000 was here */ | ||||
| #define FS_NOCOW_FL			0x00800000 /* Do not cow file */ | ||||
| #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_SHRUNK_FL		0x08000000  /* Snapshot shrink has completed */ | ||||
| #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 */ | ||||
| 	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */ | ||||
| /*068*/	__u8	s_uuid[16];		/* 128-bit uuid for volume */ | ||||
| /*078*/	char	s_volume_name[EXT2_LABEL_LEN];	/* volume name */ | ||||
| /*088*/	char	s_last_mounted[64];	/* directory where last mounted */ | ||||
| /*078*/	__u8	s_volume_name[EXT2_LABEL_LEN];	/* volume name, no NUL? */ | ||||
| /*088*/	__u8	s_last_mounted[64];	/* directory last mounted on, no NUL? */ | ||||
| /*0c8*/	__u32	s_algorithm_usage_bitmap; /* For compression */ | ||||
| 	/*
 | ||||
| 	 * 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_ino;	/* inode 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 */ | ||||
| 	__u32	s_last_error_time;	/* most recent time of an error */ | ||||
| /*1d0*/	__u32	s_last_error_ino;	/* inode involved in last error */ | ||||
| 	__u32	s_last_error_line;	/* line number where error happened */ | ||||
| 	__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) | ||||
| /*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 */ | ||||
| 	__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 */ | ||||
| /*254*/	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */ | ||||
| /*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_first_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 */ | ||||
| 	__le16	s_encoding_flags;	/* Filename charset encoding flags */ | ||||
| 	__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 EXT2_LEN_STR(buf) (int)sizeof(buf), (char *)buf | ||||
| 
 | ||||
| /*
 | ||||
|  * 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_BITMAP	0x0100 | ||||
| #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 | ||||
|  | @ -867,7 +872,7 @@ struct ext2_super_block { | |||
| #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_ENCRYPT		0x10000 | ||||
| #define EXT4_FEATURE_INCOMPAT_FNAME_ENCODING	0x20000 | ||||
| #define EXT4_FEATURE_INCOMPAT_CASEFOLD		0x20000 | ||||
| 
 | ||||
| #define EXT4_FEATURE_COMPAT_FUNCS(name, ver, flagname) \ | ||||
| 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(exclude_bitmap,	2, EXCLUDE_BITMAP) | ||||
| 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(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(inline_data,	4, INLINE_DATA) | ||||
| 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_INCOMPAT_SUPP    (EXT2_FEATURE_INCOMPAT_FILETYPE| \ | ||||
|  | @ -1112,9 +1119,9 @@ struct ext2_dir_entry_tail { | |||
| struct mmp_struct { | ||||
| 	__u32	mmp_magic;		/* Magic number for MMP */ | ||||
| 	__u32	mmp_seq;		/* Sequence no. updated periodically */ | ||||
| 	__u64	mmp_time;		/* Time last updated */ | ||||
| 	char	mmp_nodename[64];	/* Node which last updated MMP block */ | ||||
| 	char	mmp_bdevname[32];	/* Bdev which last updated MMP block */ | ||||
| 	__u64	mmp_time;		/* Time last updated (seconds) */ | ||||
| 	__u8	mmp_nodename[64];	/* Node updating MMP block, no NUL? */ | ||||
| 	__u8	mmp_bdevname[32];	/* Bdev updating MMP block, no NUL? */ | ||||
| 	__u16	mmp_check_interval;	/* Changed mmp_check_interval */ | ||||
| 	__u16	mmp_pad1; | ||||
| 	__u32	mmp_pad2[226]; | ||||
|  | @ -1146,11 +1153,8 @@ struct mmp_struct { | |||
|  */ | ||||
| #define EXT4_INLINE_DATA_DOTDOT_SIZE	(4) | ||||
| 
 | ||||
| #define EXT4_ENC_ASCII		0 | ||||
| #define EXT4_ENC_UTF8_11_0	1 | ||||
| #define EXT4_ENC_UTF8_12_1	1 | ||||
| 
 | ||||
| #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 */ | ||||
|  |  | |||
|  | @ -198,6 +198,8 @@ typedef struct ext2_file *ext2_file_t; | |||
| #define EXT2_FLAG_IGNORE_CSUM_ERRORS	0x200000 | ||||
| #define EXT2_FLAG_SHARE_DUP		0x400000 | ||||
| #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 | ||||
|  | @ -302,7 +304,7 @@ struct struct_ext2_filsys { | |||
| 	/* hashmap for SHA of data blocks */ | ||||
| 	struct ext2fs_hashmap* block_sha_map; | ||||
| 
 | ||||
| 	const struct nls_table *encoding; | ||||
| 	const struct ext2fs_nls_table *encoding; | ||||
| }; | ||||
| 
 | ||||
| #if EXT2_FLAT_INCLUDES | ||||
|  | @ -603,7 +605,9 @@ typedef struct ext2_icount *ext2_icount_t; | |||
| 					 EXT2_FEATURE_COMPAT_RESIZE_INODE|\ | ||||
| 					 EXT2_FEATURE_COMPAT_DIR_INDEX|\ | ||||
| 					 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 | ||||
| #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_INLINE_DATA|\ | ||||
| 					 EXT4_FEATURE_INCOMPAT_ENCRYPT|\ | ||||
| 					 EXT4_FEATURE_INCOMPAT_FNAME_ENCODING|\ | ||||
| 					 EXT4_FEATURE_INCOMPAT_CASEFOLD|\ | ||||
| 					 EXT4_FEATURE_INCOMPAT_CSUM_SEED|\ | ||||
| 					 EXT4_FEATURE_INCOMPAT_LARGEDIR) | ||||
| 
 | ||||
|  | @ -901,6 +905,8 @@ extern blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs, | |||
| 					 struct ext2_inode *inode); | ||||
| extern blk64_t ext2fs_inode_i_blocks(ext2_filsys fs, | ||||
| 				     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 void ext2fs_blocks_count_set(struct ext2_super_block *super, | ||||
| 				    blk64_t blk); | ||||
|  | @ -1072,6 +1078,9 @@ extern errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs, | |||
| 					  struct ext2_dir_entry *dirent, | ||||
| 					  struct ext2_dx_countlimit **cc, | ||||
| 					  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, | ||||
| 					      ext2_ino_t inum, | ||||
| 					      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); | ||||
| 
 | ||||
| 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, | ||||
| 				 const __u32 *seed, | ||||
| 				 ext2_dirhash_t *ret_hash, | ||||
|  | @ -1429,6 +1438,8 @@ errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap, | |||
| 					void *in); | ||||
| errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, | ||||
| 					   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 */ | ||||
| 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, | ||||
| 				ext2_ino_t parent_ino, __u32 *iblock); | ||||
| 
 | ||||
| /* nls_utf8.c */ | ||||
| extern const struct ext2fs_nls_table *ext2fs_load_nls_table(int encoding); | ||||
| 
 | ||||
| /* mkdir.c */ | ||||
| extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | ||||
| 			      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_resize_mem(unsigned long old_size, | ||||
| 				   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_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; | ||||
| } | ||||
| 
 | ||||
| _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) | ||||
| 		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)); | ||||
| 	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 */ | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -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) | ||||
| { | ||||
| 	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; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * 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 */ | ||||
| 
 | ||||
| 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); | ||||
| 		if (ret) | ||||
| 			goto out; | ||||
| 	} else | ||||
| 	} else if (value_len) | ||||
| 		memcpy(new_value, value, value_len); | ||||
| 
 | ||||
| 	/* Imitate kernel behavior by skipping update if value is the same. */ | ||||
| 	for (x = h->attrs; x < h->attrs + h->count; x++) { | ||||
| 		if (!strcmp(x->name, name)) { | ||||
| 			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; | ||||
| 				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) | ||||
| { | ||||
| 	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; | ||||
| 
 | ||||
| 	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) | ||||
| 			continue; | ||||
| 
 | ||||
| 		err = ext2fs_bmap2(fs, ino, inode, NULL, | ||||
| 				   BMAP_ALLOC | BMAP_UNINIT | BMAP_ZERO, blk, | ||||
| 				   0, &x); | ||||
| 		err = ext2fs_bmap2(fs, ino, inode, NULL, BMAP_ALLOC, | ||||
| 				   blk, 0, &x); | ||||
| 		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: | ||||
| 	if (inode == &inode_buf) | ||||
| 		ext2fs_write_inode(fs, ino, inode); | ||||
| errout: | ||||
| 	if (zero_len) | ||||
| 		ext2fs_zero_blocks2(fs, zero_blk, zero_len, NULL, NULL); | ||||
| 	return err; | ||||
| } | ||||
|  |  | |||
|  | @ -799,7 +799,7 @@ errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs, | |||
| 	ext2fs_generic_bitmap_64 bmap, cmap; | ||||
| 	ext2fs_block_bitmap	gen_bmap = *bitmap, gen_cmap; | ||||
| 	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; | ||||
| 	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; | ||||
| 	c_end = cmap->end; | ||||
| 	cmap->end = cmap->real_end; | ||||
| 	n = 0; | ||||
| 	ratio = 1ULL << fs->cluster_ratio_bits; | ||||
| 	while (i < bmap->real_end) { | ||||
| 		if (ext2fs_test_block_bitmap2(gen_bmap, i)) { | ||||
| 			ext2fs_mark_block_bitmap2(gen_cmap, i); | ||||
| 			i += ratio - n; | ||||
| 			n = 0; | ||||
| 			continue; | ||||
| 		} | ||||
| 		i++; n++; | ||||
| 		if (n >= ratio) | ||||
| 			n = 0; | ||||
| 		retval = ext2fs_find_first_set_block_bitmap2(gen_bmap, | ||||
| 						i, bmap->real_end, &next); | ||||
| 		if (retval) | ||||
| 			break; | ||||
| 		ext2fs_mark_block_bitmap2(gen_cmap, next); | ||||
| 		i = EXT2FS_C2B(fs, EXT2FS_B2C(fs, next) + 1); | ||||
| 	} | ||||
| 	bmap->end = b_end; | ||||
| 	cmap->end = c_end; | ||||
|  | @ -945,3 +940,38 @@ errcode_t ext2fs_find_first_set_generic_bmap(ext2fs_generic_bitmap bitmap, | |||
| 
 | ||||
| 	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 <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) | ||||
| { | ||||
| 	int c; | ||||
|  |  | |||
|  | @ -13,27 +13,15 @@ | |||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| 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; | ||||
| 	struct ext2fs_hashmap_entry { | ||||
| struct ext2fs_hashmap; | ||||
| 
 | ||||
| struct ext2fs_hashmap_entry { | ||||
| 	void *data; | ||||
| 	const void *key; | ||||
| 	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( | ||||
|  |  | |||
|  | @ -190,6 +190,9 @@ errcode_t ext2fs_initialize(const char *name, int flags, | |||
| 	assign_field(s_encoding); | ||||
| 	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) { | ||||
| 		retval = EXT2_ET_UNSUPP_FEATURE; | ||||
| 		goto cleanup; | ||||
|  |  | |||
|  | @ -309,6 +309,7 @@ errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, | |||
| { | ||||
| 	scan->current_group = group - 1; | ||||
| 	scan->groups_left = scan->fs->group_desc_count - group; | ||||
| 	scan->bad_block_ptr = 0; | ||||
| 	return get_next_blockgroup(scan); | ||||
| } | ||||
| 
 | ||||
|  | @ -332,6 +333,12 @@ static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, | |||
| 	if (blk == 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 | ||||
| 	 * 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) | ||||
| 			clen = fs->blocksize - offset; | ||||
| 
 | ||||
| 		if (!fs->icache) { | ||||
| 			retval = EXT2_ET_GDESC_READ; | ||||
| 			goto errout; | ||||
| 		} | ||||
| 		if (fs->icache->buffer_blk != block_nr) { | ||||
| 			retval = io_channel_read_blk64(fs->io, block_nr, 1, | ||||
| 						     fs->icache->buffer); | ||||
|  |  | |||
|  | @ -22,8 +22,8 @@ | |||
| #define KERN_ERR "" | ||||
| #define KERN_DEBUG "" | ||||
| 
 | ||||
| #define READ 0 | ||||
| #define WRITE 1 | ||||
| #define REQ_OP_READ 0 | ||||
| #define REQ_OP_WRITE 1 | ||||
| 
 | ||||
| #define cpu_to_be32(n) htonl(n) | ||||
| #define be32_to_cpu(n) ntohl(n) | ||||
|  | @ -37,14 +37,14 @@ typedef struct kdev_s *kdev_t; | |||
| struct buffer_head; | ||||
| struct inode; | ||||
| 
 | ||||
| typedef unsigned int gfp_t; | ||||
| #define GFP_KERNEL	0 | ||||
| #define JFS_TAG_SIZE32	JBD_TAG_SIZE32 | ||||
| #define JFS_BARRIER	0 | ||||
| #define GFP_NOFS	0 | ||||
| #define __GFP_NOFAIL	0 | ||||
| #define JBD2_TAG_SIZE32	JBD_TAG_SIZE32 | ||||
| #define JBD2_BARRIER	0 | ||||
| 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 be64_to_cpu(x)	ext2fs_be64_to_cpu(x) | ||||
| 
 | ||||
| static inline __u32 jbd2_chksum(journal_t *j EXT2FS_ATTR((unused)), | ||||
| 				__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(x) | ||||
| #define spin_unlock(x) | ||||
| #define yield() | ||||
| #define SLAB_HWCACHE_ALIGN	0 | ||||
| #define SLAB_TEMPORARY		0 | ||||
| #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 is_power_of_2(x)	((x) != 0 && (((x) & ((x) - 1)) == 0)) | ||||
| #define pr_emerg(fmt) | ||||
| 
 | ||||
| struct journal_s | ||||
| { | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ | |||
| #define __FUNCTION__ "" | ||||
| #endif | ||||
| 
 | ||||
| #define journal_oom_retry 1 | ||||
| #define journal_oom_retry 0 | ||||
| 
 | ||||
| #ifdef __STDC__ | ||||
| #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) \ | ||||
| 	__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: | ||||
|  */ | ||||
| 
 | ||||
| #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 | ||||
|  | @ -89,20 +89,20 @@ extern void * __jbd_kmalloc (char *where, size_t size, int flags, int retry); | |||
|  * Descriptor block types: | ||||
|  */ | ||||
| 
 | ||||
| #define JFS_DESCRIPTOR_BLOCK	1 | ||||
| #define JFS_COMMIT_BLOCK	2 | ||||
| #define JFS_SUPERBLOCK_V1	3 | ||||
| #define JFS_SUPERBLOCK_V2	4 | ||||
| #define JFS_REVOKE_BLOCK	5 | ||||
| #define JBD2_DESCRIPTOR_BLOCK	1 | ||||
| #define JBD2_COMMIT_BLOCK	2 | ||||
| #define JBD2_SUPERBLOCK_V1	3 | ||||
| #define JBD2_SUPERBLOCK_V2	4 | ||||
| #define JBD2_REVOKE_BLOCK	5 | ||||
| 
 | ||||
| /*
 | ||||
|  * Standard header for all descriptor blocks: | ||||
|  */ | ||||
| typedef struct journal_header_s | ||||
| { | ||||
| 	__u32		h_magic; | ||||
| 	__u32		h_blocktype; | ||||
| 	__u32		h_sequence; | ||||
| 	__be32		h_magic; | ||||
| 	__be32		h_blocktype; | ||||
| 	__be32		h_sequence; | ||||
| } journal_header_t; | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -135,15 +135,15 @@ typedef struct journal_header_s | |||
|  * Checksum v1, v2, and v3 are mutually exclusive features. | ||||
|  */ | ||||
| struct commit_header { | ||||
| 	__u32		h_magic; | ||||
| 	__u32		h_blocktype; | ||||
| 	__u32		h_sequence; | ||||
| 	__be32		h_magic; | ||||
| 	__be32		h_blocktype; | ||||
| 	__be32		h_sequence; | ||||
| 	unsigned char	h_chksum_type; | ||||
| 	unsigned char	h_chksum_size; | ||||
| 	unsigned char	h_padding[2]; | ||||
| 	__u32		h_chksum[JBD2_CHECKSUM_BYTES]; | ||||
| 	__u64		h_commit_sec; | ||||
| 	__u32		h_commit_nsec; | ||||
| 	__be32		h_chksum[JBD2_CHECKSUM_BYTES]; | ||||
| 	__be64		h_commit_sec; | ||||
| 	__be32		h_commit_nsec; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -151,22 +151,22 @@ struct commit_header { | |||
|  */ | ||||
| typedef struct journal_block_tag3_s | ||||
| { | ||||
| 	__u32		t_blocknr;	/* The on-disk block number */ | ||||
| 	__u32		t_flags;	/* See below */ | ||||
| 	__u32		t_blocknr_high; /* most-significant high 32bits. */ | ||||
| 	__u32		t_checksum;	/* crc32c(uuid+seq+block) */ | ||||
| 	__be32		t_blocknr;	/* The on-disk block number */ | ||||
| 	__be32		t_flags;	/* See below */ | ||||
| 	__be32		t_blocknr_high; /* most-significant high 32bits. */ | ||||
| 	__be32		t_checksum;	/* crc32c(uuid+seq+block) */ | ||||
| } journal_block_tag3_t; | ||||
| 
 | ||||
| typedef struct journal_block_tag_s | ||||
| { | ||||
| 	__u32		t_blocknr;	/* The on-disk block number */ | ||||
| 	__u16		t_checksum;	/* truncated crc32c(uuid+seq+block) */ | ||||
| 	__u16		t_flags;	/* See below */ | ||||
| 	__u32		t_blocknr_high; /* most-significant high 32bits. */ | ||||
| 	__be32		t_blocknr;	/* The on-disk block number */ | ||||
| 	__be16		t_checksum;	/* truncated crc32c(uuid+seq+block) */ | ||||
| 	__be16		t_flags;	/* See below */ | ||||
| 	__be32		t_blocknr_high; /* most-significant high 32bits. */ | ||||
| } journal_block_tag_t; | ||||
| 
 | ||||
| /* Tail of descriptor block, for checksumming */ | ||||
| struct journal_block_tail { | ||||
| /* Tail of descriptor or revoke block, for checksumming */ | ||||
| struct jbd2_journal_block_tail { | ||||
| 	__be32		t_checksum; | ||||
| }; | ||||
| 
 | ||||
|  | @ -177,24 +177,19 @@ struct journal_block_tail { | |||
| typedef struct journal_revoke_header_s | ||||
| { | ||||
| 	journal_header_t r_header; | ||||
| 	int		 r_count;	/* Count of bytes used in the block */ | ||||
| } journal_revoke_header_t; | ||||
| 
 | ||||
| /* Tail of revoke block, for checksumming */ | ||||
| struct journal_revoke_tail { | ||||
| 	__be32		r_checksum; | ||||
| }; | ||||
| 	__be32		 r_count;	/* Count of bytes used in the block */ | ||||
| } jbd2_journal_revoke_header_t; | ||||
| 
 | ||||
| /* Definitions for the journal tag flags word: */ | ||||
| #define JFS_FLAG_ESCAPE		1	/* on-disk block is escaped */ | ||||
| #define JFS_FLAG_SAME_UUID	2	/* block has same uuid as previous */ | ||||
| #define JFS_FLAG_DELETED	4	/* block deleted by this transaction */ | ||||
| #define JFS_FLAG_LAST_TAG	8	/* last tag in this descriptor block */ | ||||
| #define JBD2_FLAG_ESCAPE		1	/* on-disk block is escaped */ | ||||
| #define JBD2_FLAG_SAME_UUID	2	/* block has same uuid as previous */ | ||||
| #define JBD2_FLAG_DELETED	4	/* block deleted by this transaction */ | ||||
| #define JBD2_FLAG_LAST_TAG	8	/* last tag in this descriptor block */ | ||||
| 
 | ||||
| 
 | ||||
| #define UUID_SIZE 16 | ||||
| #define JFS_USERS_MAX 48 | ||||
| #define JFS_USERS_SIZE (UUID_SIZE * JFS_USERS_MAX) | ||||
| #define JBD2_USERS_MAX 48 | ||||
| #define JBD2_USERS_SIZE (UUID_SIZE * JBD2_USERS_MAX) | ||||
| /*
 | ||||
|  * The journal superblock.  All fields are in big-endian byte order. | ||||
|  */ | ||||
|  | @ -205,14 +200,14 @@ typedef struct journal_superblock_s | |||
| 
 | ||||
| /* 0x000C */ | ||||
| 	/* Static information describing the journal */ | ||||
| 	__u32	s_blocksize;		/* journal device blocksize */ | ||||
| 	__u32	s_maxlen;		/* total blocks in journal file */ | ||||
| 	__u32	s_first;		/* first block of log information */ | ||||
| 	__be32	s_blocksize;		/* journal device blocksize */ | ||||
| 	__be32	s_maxlen;		/* total blocks in journal file */ | ||||
| 	__be32	s_first;		/* first block of log information */ | ||||
| 
 | ||||
| /* 0x0018 */ | ||||
| 	/* Dynamic information describing the current state of the log */ | ||||
| 	__u32	s_sequence;		/* first commit ID expected in log */ | ||||
| 	__u32	s_start;		/* blocknr of start of log */ | ||||
| 	__be32	s_sequence;		/* first commit ID expected in log */ | ||||
| 	__be32	s_start;		/* blocknr of start of log */ | ||||
| 
 | ||||
| /* 0x0020 */ | ||||
| 	/* Error value, as set by journal_abort(). */ | ||||
|  | @ -220,63 +215,63 @@ typedef struct journal_superblock_s | |||
| 
 | ||||
| /* 0x0024 */ | ||||
| 	/* Remaining fields are only valid in a version-2 superblock */ | ||||
| 	__u32	s_feature_compat; 	/* compatible feature set */ | ||||
| 	__u32	s_feature_incompat; 	/* incompatible feature set */ | ||||
| 	__u32	s_feature_ro_compat; 	/* readonly-compatible feature set */ | ||||
| 	__be32	s_feature_compat; 	/* compatible feature set */ | ||||
| 	__be32	s_feature_incompat; 	/* incompatible feature set */ | ||||
| 	__be32	s_feature_ro_compat; 	/* readonly-compatible feature set */ | ||||
| /* 0x0030 */ | ||||
| 	__u8	s_uuid[16];		/* 128-bit uuid for journal */ | ||||
| 
 | ||||
| /* 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 */ | ||||
| 	__u32	s_max_transaction;	/* Limit of journal blocks per trans.*/ | ||||
| 	__u32	s_max_trans_data;	/* Limit of data blocks per trans. */ | ||||
| 	__be32	s_max_transaction;	/* Limit of journal blocks per trans.*/ | ||||
| 	__be32	s_max_trans_data;	/* Limit of data blocks per trans. */ | ||||
| 
 | ||||
| /* 0x0050 */ | ||||
| 	__u8	s_checksum_type;	/* checksum type */ | ||||
| 	__u8	s_padding2[3]; | ||||
| 	__u32	s_padding[42]; | ||||
| 	__u32	s_checksum;		/* crc32c(superblock) */ | ||||
| 	__be32	s_padding[42]; | ||||
| 	__be32	s_checksum;		/* crc32c(superblock) */ | ||||
| 
 | ||||
| /* 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 */ | ||||
| } journal_superblock_t; | ||||
| 
 | ||||
| #define JFS_HAS_COMPAT_FEATURE(j,mask)					\ | ||||
| #define JBD2_HAS_COMPAT_FEATURE(j,mask)					\ | ||||
| 	((j)->j_format_version >= 2 &&					\ | ||||
| 	 ((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_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_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 JFS_FEATURE_INCOMPAT_64BIT		0x00000002 | ||||
| #define JFS_FEATURE_INCOMPAT_ASYNC_COMMIT	0x00000004 | ||||
| #define JFS_FEATURE_INCOMPAT_CSUM_V2		0x00000008 | ||||
| #define JFS_FEATURE_INCOMPAT_CSUM_V3		0x00000010 | ||||
| #define JBD2_FEATURE_INCOMPAT_REVOKE		0x00000001 | ||||
| #define JBD2_FEATURE_INCOMPAT_64BIT		0x00000002 | ||||
| #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT	0x00000004 | ||||
| #define JBD2_FEATURE_INCOMPAT_CSUM_V2		0x00000008 | ||||
| #define JBD2_FEATURE_INCOMPAT_CSUM_V3		0x00000010 | ||||
| 
 | ||||
| /* Features known to this kernel version: */ | ||||
| #define JFS_KNOWN_COMPAT_FEATURES	0 | ||||
| #define JFS_KNOWN_ROCOMPAT_FEATURES	0 | ||||
| #define JFS_KNOWN_INCOMPAT_FEATURES	(JFS_FEATURE_INCOMPAT_REVOKE|\ | ||||
| 					 JFS_FEATURE_INCOMPAT_ASYNC_COMMIT|\ | ||||
| 					 JFS_FEATURE_INCOMPAT_64BIT|\ | ||||
| 					 JFS_FEATURE_INCOMPAT_CSUM_V2|\ | ||||
| 					 JFS_FEATURE_INCOMPAT_CSUM_V3) | ||||
| #define JBD2_KNOWN_COMPAT_FEATURES	0 | ||||
| #define JBD2_KNOWN_ROCOMPAT_FEATURES	0 | ||||
| #define JBD2_KNOWN_INCOMPAT_FEATURES	(JBD2_FEATURE_INCOMPAT_REVOKE|\ | ||||
| 					 JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT| \ | ||||
| 					 JBD2_FEATURE_INCOMPAT_64BIT|\ | ||||
| 					 JBD2_FEATURE_INCOMPAT_CSUM_V2|	\ | ||||
| 					 JBD2_FEATURE_INCOMPAT_CSUM_V3) | ||||
| 
 | ||||
| #ifdef NO_INLINE_FUNCS | ||||
| 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_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused)); | ||||
| #endif | ||||
|  | @ -301,94 +296,94 @@ extern int tid_geq(tid_t x, tid_t y) EXT2FS_ATTR((unused)); | |||
| #endif /* INCLUDE_INLINE_FUNCS */ | ||||
| 
 | ||||
| /* journal feature predicate functions */ | ||||
| #define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \ | ||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j); \ | ||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j) \ | ||||
| #define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \ | ||||
| _INLINE_ int jbd2_has_feature_##name(journal_t *j); \ | ||||
| _INLINE_ int jbd2_has_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	return ((j)->j_format_version >= 2 && \ | ||||
| 		((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 jfs_set_feature_##name(journal_t *j) \ | ||||
| _INLINE_ void jbd2_set_feature_##name(journal_t *j); \ | ||||
| _INLINE_ void jbd2_set_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	(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 jfs_clear_feature_##name(journal_t *j) \ | ||||
| _INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ | ||||
| _INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	(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) \ | ||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j);	\ | ||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j) \ | ||||
| #define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | ||||
| _INLINE_ int jbd2_has_feature_##name(journal_t *j);	\ | ||||
| _INLINE_ int jbd2_has_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	return ((j)->j_format_version >= 2 && \ | ||||
| 		((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 jfs_set_feature_##name(journal_t *j) \ | ||||
| _INLINE_ void jbd2_set_feature_##name(journal_t *j); \ | ||||
| _INLINE_ void jbd2_set_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	(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 jfs_clear_feature_##name(journal_t *j) \ | ||||
| _INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ | ||||
| _INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	(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) \ | ||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j); \ | ||||
| _INLINE_ int jfs_has_feature_##name(journal_t *j) \ | ||||
| #define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | ||||
| _INLINE_ int jbd2_has_feature_##name(journal_t *j); \ | ||||
| _INLINE_ int jbd2_has_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	return ((j)->j_format_version >= 2 && \ | ||||
| 		((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 jfs_set_feature_##name(journal_t *j) \ | ||||
| _INLINE_ void jbd2_set_feature_##name(journal_t *j); \ | ||||
| _INLINE_ void jbd2_set_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	(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 jfs_clear_feature_##name(journal_t *j) \ | ||||
| _INLINE_ void jbd2_clear_feature_##name(journal_t *j); \ | ||||
| _INLINE_ void jbd2_clear_feature_##name(journal_t *j) \ | ||||
| { \ | ||||
| 	(j)->j_superblock->s_feature_incompat &= \ | ||||
| 		~ext2fs_cpu_to_be32(JFS_FEATURE_INCOMPAT_##flagname); \ | ||||
| 		~ext2fs_cpu_to_be32(JBD2_FEATURE_INCOMPAT_##flagname); \ | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| #define JFS_FEATURE_COMPAT_FUNCS(name, flagname) \ | ||||
| extern int jfs_has_feature_##name(journal_t *j); \ | ||||
| extern void jfs_set_feature_##name(journal_t *j); \ | ||||
| extern void jfs_clear_feature_##name(journal_t *j); | ||||
| #define JBD2_FEATURE_COMPAT_FUNCS(name, flagname) \ | ||||
| extern int jbd2_has_feature_##name(journal_t *j); \ | ||||
| extern void jbd2_set_feature_##name(journal_t *j); \ | ||||
| extern void jbd2_clear_feature_##name(journal_t *j); | ||||
| 
 | ||||
| #define JFS_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | ||||
| extern int jfs_has_feature_##name(journal_t *j); \ | ||||
| extern void jfs_set_feature_##name(journal_t *j); \ | ||||
| extern void jfs_clear_feature_##name(journal_t *j); | ||||
| #define JBD2_FEATURE_RO_COMPAT_FUNCS(name, flagname) \ | ||||
| extern int jbd2_has_feature_##name(journal_t *j); \ | ||||
| extern void jbd2_set_feature_##name(journal_t *j); \ | ||||
| extern void jbd2_clear_feature_##name(journal_t *j); | ||||
| 
 | ||||
| #define JFS_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | ||||
| extern int jfs_has_feature_##name(journal_t *j); \ | ||||
| extern void jfs_set_feature_##name(journal_t *j); \ | ||||
| extern void jfs_clear_feature_##name(journal_t *j); | ||||
| #define JBD2_FEATURE_INCOMPAT_FUNCS(name, flagname) \ | ||||
| extern int jbd2_has_feature_##name(journal_t *j); \ | ||||
| extern void jbd2_set_feature_##name(journal_t *j); \ | ||||
| extern void jbd2_clear_feature_##name(journal_t *j); | ||||
| 
 | ||||
| #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) | ||||
| JFS_FEATURE_INCOMPAT_FUNCS(64bit,		64BIT) | ||||
| JFS_FEATURE_INCOMPAT_FUNCS(async_commit,	ASYNC_COMMIT) | ||||
| JFS_FEATURE_INCOMPAT_FUNCS(csum2,		CSUM_V2) | ||||
| JFS_FEATURE_INCOMPAT_FUNCS(csum3,		CSUM_V3) | ||||
| JBD2_FEATURE_INCOMPAT_FUNCS(revoke,		REVOKE) | ||||
| JBD2_FEATURE_INCOMPAT_FUNCS(64bit,		64BIT) | ||||
| JBD2_FEATURE_INCOMPAT_FUNCS(async_commit,	ASYNC_COMMIT) | ||||
| JBD2_FEATURE_INCOMPAT_FUNCS(csum2,		CSUM_V2) | ||||
| JBD2_FEATURE_INCOMPAT_FUNCS(csum3,		CSUM_V3) | ||||
| 
 | ||||
| #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; | ||||
| 
 | ||||
| 	if (jfs_has_feature_csum3(journal)) | ||||
| 	if (jbd2_has_feature_csum3(journal)) | ||||
| 		return sizeof(journal_block_tag3_t); | ||||
| 
 | ||||
| 	sz = sizeof(journal_block_tag_t); | ||||
| 
 | ||||
| 	if (jfs_has_feature_csum2(journal)) | ||||
| 	if (jbd2_has_feature_csum2(journal)) | ||||
| 		sz += sizeof(__u16); | ||||
| 
 | ||||
| 	if (jfs_has_feature_64bit(journal)) | ||||
| 	if (jbd2_has_feature_64bit(journal)) | ||||
| 		return sz; | ||||
| 
 | ||||
| 	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 0; | ||||
|  |  | |||
|  | @ -18,6 +18,155 @@ | |||
| 
 | ||||
| #include "ext2_fs.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  { | ||||
| 	ext2_filsys	fs; | ||||
|  | @ -31,7 +180,9 @@ struct link_struct  { | |||
| 	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	blocksize, | ||||
| 		     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; | ||||
| 	int ret = 0; | ||||
| 	int csum_size = 0; | ||||
| 	struct ext2_dir_entry_tail *t; | ||||
| 
 | ||||
| 	if (ls->done) | ||||
| 		return DIRENT_ABORT; | ||||
|  | @ -70,40 +220,6 @@ static int link_proc(struct ext2_dir_entry *dirent, | |||
| 		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 | ||||
| 	 * 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; | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
|  * 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)) | ||||
| 		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.name = name; | ||||
| 	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.err = 0; | ||||
| 
 | ||||
| 	retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, | ||||
| 				    0, link_proc, &ls); | ||||
| 	retval = ext2fs_dir_iterate2(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY, | ||||
| 				     NULL, link_proc, &ls); | ||||
| 	if (retval) | ||||
| 		return retval; | ||||
| 	if (ls.err) | ||||
|  | @ -182,20 +641,5 @@ errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name, | |||
| 
 | ||||
| 	if (!ls.done) | ||||
| 		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; | ||||
| } | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | |||
| 	blk64_t			blk; | ||||
| 	char			*block = 0; | ||||
| 	int			inline_data = 0; | ||||
| 	int			drop_refcount = 0; | ||||
| 
 | ||||
| 	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 | ||||
| 	 */ | ||||
|  | @ -174,17 +183,16 @@ errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum, | |||
| 		if (retval) | ||||
| 			goto cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Update accounting.... | ||||
| 	 */ | ||||
| 	if (!inline_data) | ||||
| 		ext2fs_block_alloc_stats2(fs, blk, +1); | ||||
| 	ext2fs_inode_alloc_stats2(fs, ino, +1, 1); | ||||
| 	drop_refcount = 0; | ||||
| 
 | ||||
| cleanup: | ||||
| 	if (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; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ errcode_t ext2fs_create_journal_superblock(ext2_filsys fs, | |||
| 	errcode_t		retval; | ||||
| 	journal_superblock_t	*jsb; | ||||
| 
 | ||||
| 	if (num_blocks < JFS_MIN_JOURNAL_BLOCKS) | ||||
| 	if (num_blocks < JBD2_MIN_JOURNAL_BLOCKS) | ||||
| 		return EXT2_ET_JOURNAL_TOO_SMALL; | ||||
| 
 | ||||
| 	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); | ||||
| 
 | ||||
| 	jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER); | ||||
| 	jsb->s_header.h_magic = htonl(JBD2_MAGIC_NUMBER); | ||||
| 	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 | ||||
| 		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_maxlen = htonl(num_blocks); | ||||
| 	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; | ||||
| 
 | ||||
| 	jsb = (journal_superblock_t *) buf; | ||||
| 	if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) || | ||||
| 	    (jsb->s_header.h_blocktype != (unsigned) ntohl(JFS_SUPERBLOCK_V2))) | ||||
| 	if ((jsb->s_header.h_magic != (unsigned) ntohl(JBD2_MAGIC_NUMBER)) || | ||||
| 	    (jsb->s_header.h_blocktype != (unsigned) ntohl(JBD2_SUPERBLOCK_V2))) | ||||
| 		return EXT2_ET_NO_JOURNAL_SB; | ||||
| 
 | ||||
| 	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 */ | ||||
| 	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; | ||||
| 	for (i=0; i < nr_users; i++) { | ||||
| 		if (memcmp(fs->super->s_uuid, | ||||
|  | @ -575,7 +575,7 @@ main(int argc, char **argv) | |||
| 		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) { | ||||
| 		com_err(argv[0], retval, "while adding journal to %s", | ||||
| 			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 | ||||
| 	 * the MMP block by the io_manager or the VM.  It needs to be fresh. */ | ||||
| 	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) { | ||||
| 			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; | ||||
| 			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_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, | ||||
| 	.name		= "NT I/O Manager", | ||||
| 	.open		= nt_open, | ||||
|  | @ -94,10 +94,7 @@ static struct struct_io_manager struct_nt_manager = { | |||
| 	.flush		= nt_flush | ||||
| }; | ||||
| 
 | ||||
| io_manager nt_io_manager(void) | ||||
| { | ||||
| 	return &struct_nt_manager; | ||||
| } | ||||
| io_manager nt_io_manager = &struct_nt_manager; | ||||
| 
 | ||||
| // Convert Win32 errors to unix errno
 | ||||
| typedef struct { | ||||
|  | @ -530,7 +527,7 @@ static errcode_t nt_open(const char *name, int flags, io_channel *channel) | |||
| 
 | ||||
| 	// Initialize data
 | ||||
| 	io->magic = EXT2_ET_MAGIC_IO_CHANNEL; | ||||
| 	io->manager = nt_io_manager(); | ||||
| 	io->manager = nt_io_manager; | ||||
| 	strcpy(io->name, name); | ||||
| 	io->block_size = EXT2_MIN_BLOCK_SIZE; | ||||
| 	io->refcount = 1; | ||||
|  |  | |||
|  | @ -29,7 +29,6 @@ | |||
| 
 | ||||
| #include "ext2_fs.h" | ||||
| 
 | ||||
| 
 | ||||
| #include "ext2fs.h" | ||||
| #include "e2image.h" | ||||
| 
 | ||||
|  | @ -135,6 +134,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | |||
| 	int		j; | ||||
| #endif | ||||
| 	char		*time_env; | ||||
| 	int		csum_retries = 0; | ||||
| 
 | ||||
| 	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) | ||||
| 			goto cleanup; | ||||
| 	} | ||||
| retry: | ||||
| 	retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE, | ||||
| 				     fs->super); | ||||
| 	if (retval) | ||||
|  | @ -234,9 +235,12 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | |||
| 		retval = 0; | ||||
| 		if (!ext2fs_verify_csum_type(fs, fs->super)) | ||||
| 			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; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| #ifdef WORDS_BIGENDIAN | ||||
| 	fs->flags |= EXT2_FLAG_SWAP_BYTES; | ||||
|  | @ -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, | ||||
| 					  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, | ||||
| 				&fs->group_desc); | ||||
| 	if (retval) | ||||
|  | @ -435,6 +441,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | |||
| 		gdp = (struct ext2_group_desc *) dest; | ||||
| 		for (j=0; j < groups_per_block*first_meta_bg; j++) { | ||||
| 			gdp = ext2fs_group_desc(fs, fs->group_desc, j); | ||||
| 			if (gdp) | ||||
| 				ext2fs_swap_group_desc2(fs, gdp); | ||||
| 		} | ||||
| #endif | ||||
|  | @ -455,6 +462,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | |||
| 		for (j=0; j < groups_per_block; j++) { | ||||
| 			gdp = ext2fs_group_desc(fs, fs->group_desc, | ||||
| 						i * groups_per_block + j); | ||||
| 			if (gdp) | ||||
| 				ext2fs_swap_group_desc2(fs, gdp); | ||||
| 		} | ||||
| #endif | ||||
|  | @ -481,7 +489,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options, | |||
| 		if (fs->flags & EXT2_FLAG_RW) | ||||
| 			ext2fs_mark_super_dirty(fs); | ||||
| 	} | ||||
| 
 | ||||
| skip_read_bg: | ||||
| 	if (ext2fs_has_feature_mmp(fs->super) && | ||||
| 	    !(flags & EXT2_FLAG_SKIP_MMP) && | ||||
| 	    (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); | ||||
| 	} | ||||
| 
 | ||||
| //	if (ext2fs_has_feature_casefold(fs->super))
 | ||||
| //		fs->encoding = ext2fs_load_nls_table(fs->super->s_encoding);
 | ||||
| 
 | ||||
| 	fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; | ||||
| 	*ret_fs = fs; | ||||
| 
 | ||||
|  |  | |||
|  | @ -195,6 +195,16 @@ static errcode_t mark_uninit_bg_group_blocks(ext2_filsys fs) | |||
| 	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) | ||||
| { | ||||
| 	dgrp_t i; | ||||
|  | @ -203,6 +213,7 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | |||
| 	errcode_t retval; | ||||
| 	int block_nbytes = EXT2_CLUSTERS_PER_GROUP(fs->super) / 8; | ||||
| 	int inode_nbytes = EXT2_INODES_PER_GROUP(fs->super) / 8; | ||||
| 	int tail_flags = 0; | ||||
| 	int csum_flag; | ||||
| 	unsigned int	cnt; | ||||
| 	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++) { | ||||
| 		if (block_bitmap) { | ||||
| 			blk = ext2fs_block_bitmap_loc(fs, i); | ||||
| 			if (csum_flag && | ||||
| 			if ((csum_flag && | ||||
| 			     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; | ||||
| 			if (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; | ||||
| 					goto cleanup; | ||||
| 				} | ||||
| 				if (!bitmap_tail_verify((unsigned char *) block_bitmap, | ||||
| 							block_nbytes, fs->blocksize - 1)) | ||||
| 					tail_flags |= EXT2_FLAG_BBITMAP_TAIL_PROBLEM; | ||||
| 			} else | ||||
| 				memset(block_bitmap, 0, block_nbytes); | ||||
| 			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); | ||||
| 			if (retval) | ||||
| 				goto cleanup; | ||||
| 			blk_itr += (blk64_t)block_nbytes << 3; | ||||
| 			blk_itr += block_nbytes << 3; | ||||
| 		} | ||||
| 		if (inode_bitmap) { | ||||
| 			blk = ext2fs_inode_bitmap_loc(fs, i); | ||||
| 			if (csum_flag && | ||||
| 			if ((csum_flag && | ||||
| 			     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; | ||||
| 			if (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; | ||||
| 					goto cleanup; | ||||
| 				} | ||||
| 				if (!bitmap_tail_verify((unsigned char *) inode_bitmap, | ||||
| 							inode_nbytes, fs->blocksize - 1)) | ||||
| 					tail_flags |= EXT2_FLAG_IBITMAP_TAIL_PROBLEM; | ||||
| 			} else | ||||
| 				memset(inode_bitmap, 0, inode_nbytes); | ||||
| 			cnt = inode_nbytes << 3; | ||||
|  | @ -366,19 +385,24 @@ static errcode_t read_bitmaps(ext2_filsys fs, int do_inode, int do_block) | |||
| 	} | ||||
| 
 | ||||
| success_cleanup: | ||||
| 	if (inode_bitmap) | ||||
| 	if (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); | ||||
| 		fs->flags &= ~EXT2_FLAG_BBITMAP_TAIL_PROBLEM; | ||||
| 	} | ||||
| 	fs->flags |= tail_flags; | ||||
| 	return 0; | ||||
| 
 | ||||
| cleanup: | ||||
| 	if (do_block) { | ||||
| 		ext2fs_free_mem(&fs->block_map); | ||||
| 		ext2fs_free_block_bitmap(fs->block_map); | ||||
| 		fs->block_map = 0; | ||||
| 	} | ||||
| 	if (do_inode) { | ||||
| 		ext2fs_free_mem(&fs->inode_map); | ||||
| 		ext2fs_free_inode_bitmap(fs->inode_map); | ||||
| 		fs->inode_map = 0; | ||||
| 	} | ||||
| 	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; | ||||
| 	unsigned int		target_len; | ||||
| 	char			*block_buf = 0; | ||||
| 	int			drop_refcount = 0; | ||||
| 
 | ||||
| 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); | ||||
| 
 | ||||
|  | @ -162,6 +163,14 @@ need_block: | |||
| 			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 | ||||
| 	 */ | ||||
|  | @ -178,17 +187,16 @@ need_block: | |||
| 		if (retval) | ||||
| 			goto cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Update accounting.... | ||||
| 	 */ | ||||
| 	if (!fastlink && !inlinelink) | ||||
| 		ext2fs_block_alloc_stats2(fs, blk, +1); | ||||
| 	ext2fs_inode_alloc_stats2(fs, ino, +1, 0); | ||||
| 	drop_refcount = 0; | ||||
| 
 | ||||
| cleanup: | ||||
| 	if (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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ | |||
| #include "ext2fs/ext2fs.h" | ||||
| 
 | ||||
| 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); | ||||
| static float ext2_percent_start = 0.0f, ext2_percent_share = 0.5f; | ||||
| 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_EA_INODE_CORRUPTED: | ||||
| 		return "Inode is corrupted"; | ||||
| 	case EXT2_ET_NO_GDESC: | ||||
| 		return "Group descriptors not loaded"; | ||||
| 	default: | ||||
| 		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); | ||||
|  | @ -202,7 +204,7 @@ const char* GetExtFsLabel(DWORD DriveIndex, uint64_t PartitionOffset) | |||
| 	static char label[EXT2_LABEL_LEN + 1]; | ||||
| 	errcode_t r; | ||||
| 	ext2_filsys ext2fs = NULL; | ||||
| 	io_manager manager = nt_io_manager(); | ||||
| 	io_manager manager = nt_io_manager; | ||||
| 	char* volume_name = GetExtPartitionName(DriveIndex, PartitionOffset); | ||||
| 
 | ||||
| 	if (volume_name == NULL) | ||||
|  | @ -238,7 +240,7 @@ BOOL FormatExtFs(DWORD DriveIndex, uint64_t PartitionOffset, DWORD BlockSize, LP | |||
| 	char* volume_name = NULL; | ||||
| 	int i, count; | ||||
| 	struct ext2_super_block features = { 0 }; | ||||
| 	io_manager manager = nt_io_manager(); | ||||
| 	io_manager manager = nt_io_manager; | ||||
| 	blk_t journal_size; | ||||
| 	blk64_t size = 0, cur; | ||||
| 	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 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_ACCEPTFILES | ||||
| CAPTION "Rufus 3.14.1732" | ||||
| CAPTION "Rufus 3.14.1733" | ||||
| FONT 9, "Segoe UI Symbol", 400, 0, 0x0 | ||||
| BEGIN | ||||
|     LTEXT           "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP | ||||
|  | @ -397,8 +397,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 3,14,1732,0 | ||||
|  PRODUCTVERSION 3,14,1732,0 | ||||
|  FILEVERSION 3,14,1733,0 | ||||
|  PRODUCTVERSION 3,14,1733,0 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -416,13 +416,13 @@ BEGIN | |||
|             VALUE "Comments", "https://rufus.ie" | ||||
|             VALUE "CompanyName", "Akeo Consulting" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "3.14.1732" | ||||
|             VALUE "FileVersion", "3.14.1733" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011-2021 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" | ||||
|             VALUE "OriginalFilename", "rufus-3.14.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "3.14.1732" | ||||
|             VALUE "ProductVersion", "3.14.1733" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue