From 8a480350952f6f0fdbce54326b6d847e66368897 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 21 Jun 2009 21:07:38 -0400 Subject: Fix encoding for rec_len in directories for >= 64k blocksize file systems Previously e2fsprogs interpreted 0 for a rec_len of 65536 (which could occur if the directory block is completely empty in 64k blocksize filesystems), while the kernel interpreted 65535 to mean 65536. The kernel will accept both to mean 65536, and encodes 65535 to be 65536. This commit changes e2fsprogs to match. We add the encoding agreed upon for 128k and 256k filesystems, but we don't enable support for these larger block sizes, since they haven't been fully tested. Signed-off-by: "Theodore Ts'o" --- misc/e2image.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'misc/e2image.c') diff --git a/misc/e2image.c b/misc/e2image.c index dd2a1caa..83c1cca9 100644 --- a/misc/e2image.c +++ b/misc/e2image.c @@ -339,11 +339,14 @@ static void write_block(int fd, char *buf, int sparse_offset, int name_id[256]; +#define EXT4_MAX_REC_LEN ((1<<16)-1) + static void scramble_dir_block(ext2_filsys fs, blk_t blk, char *buf) { char *p, *end, *cp; struct ext2_dir_entry_2 *dirent; - int rec_len, id, len; + unsigned int rec_len; + int id, len; end = buf + fs->blocksize; for (p = buf; p < end-8; p += rec_len) { @@ -352,8 +355,10 @@ static void scramble_dir_block(ext2_filsys fs, blk_t blk, char *buf) #ifdef WORDS_BIGENDIAN rec_len = ext2fs_swab16(rec_len); #endif - rec_len = (rec_len || fs->blocksize < 65536) ? - rec_len : 65536; + if (rec_len == EXT4_MAX_REC_LEN || rec_len == 0) + rec_len = fs->blocksize; + else + rec_len = (rec_len & 65532) | ((rec_len & 3) << 16); #if 0 printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len); #endif @@ -363,8 +368,10 @@ static void scramble_dir_block(ext2_filsys fs, blk_t blk, char *buf) "bad rec_len (%d)\n", (unsigned long) blk, rec_len); rec_len = end - p; + (void) ext2fs_set_rec_len(fs, rec_len, + (struct ext2_dir_entry *) dirent); #ifdef WORDS_BIGENDIAN - dirent->rec_len = ext2fs_swab16(rec_len); + dirent->rec_len = ext2fs_swab16(dirent->rec_len); #endif continue; } -- cgit v1.2.3