summaryrefslogtreecommitdiff
path: root/misc/e2image.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-06-21 21:07:38 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-06-21 21:07:38 -0400
commit8a480350952f6f0fdbce54326b6d847e66368897 (patch)
tree8f09d26e06335f00dec8166acaae425cc30c3523 /misc/e2image.c
parent8a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1b (diff)
downloade2fsprogs-8a480350952f6f0fdbce54326b6d847e66368897.tar.gz
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" <tytso@mit.edu>
Diffstat (limited to 'misc/e2image.c')
-rw-r--r--misc/e2image.c15
1 files changed, 11 insertions, 4 deletions
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;
}