summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debugfs/htree.c22
-rw-r--r--e2fsck/pass1.c18
-rw-r--r--e2fsck/pass2.c60
-rw-r--r--e2fsck/problem.c2
-rw-r--r--e2fsck/rehash.c14
-rw-r--r--lib/ext2fs/dir_iterate.c41
-rw-r--r--lib/ext2fs/dirblock.c15
-rw-r--r--lib/ext2fs/link.c20
-rw-r--r--lib/ext2fs/newdir.c2
-rw-r--r--misc/e2image.c2
10 files changed, 121 insertions, 75 deletions
diff --git a/debugfs/htree.c b/debugfs/htree.c
index bee78d7e..1659b63f 100644
--- a/debugfs/htree.c
+++ b/debugfs/htree.c
@@ -39,7 +39,7 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
char tmp[EXT2_NAME_LEN + 16];
blk_t pblk;
ext2_dirhash_t hash, minor_hash;
- int hash_alg;
+ int rec_len, hash_alg;
errcode = ext2fs_bmap(fs, ino, inode, buf, 0, blk, &pblk);
if (errcode) {
@@ -62,10 +62,12 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
while (offset < fs->blocksize) {
dirent = (struct ext2_dir_entry *) (buf + offset);
- if (((offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+ if (((offset + rec_len) > fs->blocksize) ||
+ (rec_len < 8) ||
+ ((rec_len % 4) != 0) ||
+ (((dirent->name_len & 0xFF)+8) > rec_len)) {
fprintf(pager, "Corrupted directory block (%u)!\n", blk);
break;
}
@@ -80,7 +82,7 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
com_err("htree_dump_leaf_node", errcode,
"while calculating hash");
sprintf(tmp, "%u 0x%08x-%08x (%d) %s ", dirent->inode,
- hash, minor_hash, dirent->rec_len, name);
+ hash, minor_hash, rec_len, name);
thislen = strlen(tmp);
if (col + thislen > 80) {
fprintf(pager, "\n");
@@ -88,7 +90,7 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
}
fprintf(pager, "%s", tmp);
col += thislen;
- offset += dirent->rec_len;
+ offset += rec_len;
}
fprintf(pager, "\n");
}
@@ -373,6 +375,7 @@ static int search_dir_block(ext2_filsys fs, blk_t *blocknr,
struct ext2_dir_entry *dirent;
errcode_t errcode;
unsigned int offset = 0;
+ int rec_len;
if (blockcnt < 0)
return 0;
@@ -388,7 +391,8 @@ static int search_dir_block(ext2_filsys fs, blk_t *blocknr,
while (offset < fs->blocksize) {
dirent = (struct ext2_dir_entry *) (p->buf + offset);
-
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
if (dirent->inode &&
p->len == (dirent->name_len & 0xFF) &&
strncmp(p->search_name, dirent->name,
@@ -399,7 +403,7 @@ static int search_dir_block(ext2_filsys fs, blk_t *blocknr,
printf("offset %u\n", offset);
return BLOCK_ABORT;
}
- offset += dirent->rec_len;
+ offset += rec_len;
}
return 0;
}
diff --git a/e2fsck/pass1.c b/e2fsck/pass1.c
index 0e245dd0..f2f72edd 100644
--- a/e2fsck/pass1.c
+++ b/e2fsck/pass1.c
@@ -404,7 +404,7 @@ static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx,
const char *old_op;
errcode_t retval;
blk_t blk;
- int i, not_device = 0;
+ int i, rec_len, not_device = 0;
if (LINUX_S_ISDIR(inode->i_mode) || LINUX_S_ISREG(inode->i_mode) ||
LINUX_S_ISLNK(inode->i_mode) || inode->i_block[0] == 0)
@@ -434,20 +434,24 @@ static void check_is_really_dir(e2fsck_t ctx, struct problem_context *pctx,
return;
dirent = (struct ext2_dir_entry *) buf;
+ rec_len = (dirent->rec_len || ctx->fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
if (((dirent->name_len & 0xFF) != 1) ||
(dirent->name[0] != '.') ||
(dirent->inode != pctx->ino) ||
- (dirent->rec_len < 12) ||
- (dirent->rec_len % 4) ||
- (dirent->rec_len >= ctx->fs->blocksize - 12))
+ (rec_len < 12) ||
+ (rec_len % 4) ||
+ (rec_len >= ctx->fs->blocksize - 12))
return;
- dirent = (struct ext2_dir_entry *) (buf + dirent->rec_len);
+ dirent = (struct ext2_dir_entry *) (buf + rec_len);
+ rec_len = (dirent->rec_len || ctx->fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
if (((dirent->name_len & 0xFF) != 2) ||
(dirent->name[0] != '.') ||
(dirent->name[1] != '.') ||
- (dirent->rec_len < 12) ||
- (dirent->rec_len % 4))
+ (rec_len < 12) ||
+ (rec_len % 4))
return;
if (fix_problem(ctx, PR_1_TREAT_AS_DIRECTORY, pctx)) {
diff --git a/e2fsck/pass2.c b/e2fsck/pass2.c
index f4fa93e5..1992479b 100644
--- a/e2fsck/pass2.c
+++ b/e2fsck/pass2.c
@@ -355,7 +355,7 @@ static int check_dot(e2fsck_t ctx,
struct ext2_dir_entry *nextdir;
int status = 0;
int created = 0;
- int new_len;
+ int rec_len, new_len;
int problem = 0;
if (!dirent->inode)
@@ -365,11 +365,13 @@ static int check_dot(e2fsck_t ctx,
problem = PR_2_1ST_NOT_DOT;
else if (dirent->name[1] != '\0')
problem = PR_2_DOT_NULL_TERM;
-
+
+ rec_len = (dirent->rec_len || ctx->fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
if (problem) {
if (fix_problem(ctx, problem, pctx)) {
- if (dirent->rec_len < 12)
- dirent->rec_len = 12;
+ if (rec_len < 12)
+ rec_len = dirent->rec_len = 12;
dirent->inode = ino;
dirent->name_len = 1;
dirent->name[0] = '.';
@@ -384,8 +386,8 @@ static int check_dot(e2fsck_t ctx,
status = 1;
}
}
- if (dirent->rec_len > 12) {
- new_len = dirent->rec_len - 12;
+ if (rec_len > 12) {
+ new_len = rec_len - 12;
if (new_len > 12) {
if (created ||
fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
@@ -411,7 +413,7 @@ static int check_dotdot(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
ext2_ino_t ino, struct problem_context *pctx)
{
- int problem = 0;
+ int rec_len, problem = 0;
if (!dirent->inode)
problem = PR_2_MISSING_DOT_DOT;
@@ -422,9 +424,11 @@ static int check_dotdot(e2fsck_t ctx,
else if (dirent->name[2] != '\0')
problem = PR_2_DOT_DOT_NULL_TERM;
+ rec_len = (dirent->rec_len || ctx->fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
if (problem) {
if (fix_problem(ctx, problem, pctx)) {
- if (dirent->rec_len < 12)
+ if (rec_len < 12)
dirent->rec_len = 12;
/*
* Note: we don't have the parent inode just
@@ -644,14 +648,18 @@ static void salvage_directory(ext2_filsys fs,
unsigned int *offset)
{
char *cp = (char *) dirent;
- int left = fs->blocksize - *offset - dirent->rec_len;
+ int left, rec_len;
unsigned int name_len = dirent->name_len & 0xFF;
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+ left = fs->blocksize - *offset - rec_len;
+
/*
* Special case of directory entry of size 8: copy what's left
* of the directory block up to cover up the invalid hole.
*/
- if ((left >= 12) && (dirent->rec_len == 8)) {
+ if ((left >= 12) && (rec_len == 8)) {
memmove(cp, cp+8, left);
memset(cp + left, 0, 8);
return;
@@ -662,7 +670,7 @@ static void salvage_directory(ext2_filsys fs,
* record length.
*/
if ((left < 0) &&
- (name_len + 8 <= dirent->rec_len + (unsigned) left) &&
+ (name_len + 8 <= rec_len + (unsigned) left) &&
dirent->inode <= fs->super->s_inodes_count &&
strnlen(dirent->name, name_len) == name_len) {
dirent->rec_len += left;
@@ -673,10 +681,10 @@ static void salvage_directory(ext2_filsys fs,
* of four, and not too big, such that it is valid, let the
* previous directory entry absorb the invalid one.
*/
- if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0 &&
- (*offset + dirent->rec_len <= fs->blocksize)) {
- prev->rec_len += dirent->rec_len;
- *offset += dirent->rec_len;
+ if (prev && rec_len && (rec_len % 4) == 0 &&
+ (*offset + rec_len <= fs->blocksize)) {
+ prev->rec_len += rec_len;
+ *offset += rec_len;
return;
}
/*
@@ -709,6 +717,7 @@ static int check_dir_block(ext2_filsys fs,
const char * old_op;
int dir_modified = 0;
int dot_state;
+ int rec_len;
blk_t block_nr = db->blk;
ext2_ino_t ino = db->ino;
ext2_ino_t subdir_parent;
@@ -800,6 +809,8 @@ static int check_dir_block(ext2_filsys fs,
dx_db->max_hash = 0;
dirent = (struct ext2_dir_entry *) buf;
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
limit = (struct ext2_dx_countlimit *) (buf+8);
if (db->blockcnt == 0) {
root = (struct ext2_dx_root_info *) (buf + 24);
@@ -819,7 +830,7 @@ static int check_dir_block(ext2_filsys fs,
dx_dir->hashversion += 3;
dx_dir->depth = root->indirect_levels + 1;
} else if ((dirent->inode == 0) &&
- (dirent->rec_len == fs->blocksize) &&
+ (rec_len == fs->blocksize) &&
(dirent->name_len == 0) &&
(ext2fs_le16_to_cpu(limit->limit) ==
((fs->blocksize-8) /
@@ -837,12 +848,14 @@ out_htree:
problem = 0;
dirent = (struct ext2_dir_entry *) (buf + offset);
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
cd->pctx.dirent = dirent;
cd->pctx.num = offset;
- if (((offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 12) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+ if (((offset + rec_len) > fs->blocksize) ||
+ (rec_len < 12) ||
+ ((rec_len % 4) != 0) ||
+ (((dirent->name_len & 0xFF)+8) > rec_len)) {
if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
salvage_directory(fs, dirent, prev, &offset);
dir_modified++;
@@ -1092,7 +1105,10 @@ out_htree:
ctx->fs_total_count++;
next:
prev = dirent;
- offset += dirent->rec_len;
+ if (dir_modified)
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+ offset += rec_len;
dot_state++;
} while (offset < fs->blocksize);
#if 0
@@ -1112,7 +1128,7 @@ out_htree:
}
#endif /* ENABLE_HTREE */
if (offset != fs->blocksize) {
- cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
+ cd->pctx.num = rec_len - fs->blocksize + offset;
if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
dirent->rec_len = cd->pctx.num;
dir_modified++;
diff --git a/e2fsck/problem.c b/e2fsck/problem.c
index 9d4c4e86..27e2bf0f 100644
--- a/e2fsck/problem.c
+++ b/e2fsck/problem.c
@@ -1136,7 +1136,7 @@ static struct e2fsck_problem problem_table[] = {
/* Directory entry for '.' is big. Split? */
{ PR_2_SPLIT_DOT,
- N_("@d @e for '.' is big. "),
+ N_("@d @e for '.' in %p (%i) is big.\n"),
PROMPT_SPLIT, PR_NO_OK },
/* Illegal FIFO inode */
diff --git a/e2fsck/rehash.c b/e2fsck/rehash.c
index e75774a1..6c7d0510 100644
--- a/e2fsck/rehash.c
+++ b/e2fsck/rehash.c
@@ -89,7 +89,7 @@ static int fill_dir_block(ext2_filsys fs,
struct ext2_dir_entry *dirent;
char *dir;
unsigned int offset, dir_offset;
- int hash_alg;
+ int rec_len, hash_alg;
if (blockcnt < 0)
return 0;
@@ -117,14 +117,16 @@ static int fill_dir_block(ext2_filsys fs,
dir_offset = 0;
while (dir_offset < fs->blocksize) {
dirent = (struct ext2_dir_entry *) (dir + dir_offset);
- if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+ if (((dir_offset + rec_len) > fs->blocksize) ||
+ (rec_len < 8) ||
+ ((rec_len % 4) != 0) ||
+ (((dirent->name_len & 0xFF)+8) > rec_len)) {
fd->err = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT;
}
- dir_offset += dirent->rec_len;
+ dir_offset += rec_len;
if (dirent->inode == 0)
continue;
if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
diff --git a/lib/ext2fs/dir_iterate.c b/lib/ext2fs/dir_iterate.c
index 3e7b7b06..6bb536b0 100644
--- a/lib/ext2fs/dir_iterate.c
+++ b/lib/ext2fs/dir_iterate.c
@@ -29,16 +29,20 @@
* undeleted entry. Returns 1 if the deleted entry looks valid, zero
* if not valid.
*/
-static int ext2fs_validate_entry(char *buf, int offset, int final_offset)
+static int ext2fs_validate_entry(ext2_filsys fs, char *buf, int offset,
+ int final_offset)
{
struct ext2_dir_entry *dirent;
+ int rec_len;
while (offset < final_offset) {
dirent = (struct ext2_dir_entry *)(buf + offset);
- offset += dirent->rec_len;
- if ((dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len))
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+ offset += rec_len;
+ if ((rec_len < 8) ||
+ ((rec_len % 4) != 0) ||
+ (((dirent->name_len & 0xFF)+8) > rec_len))
return 0;
}
return (offset == final_offset);
@@ -144,7 +148,7 @@ int ext2fs_process_dir_block(ext2_filsys fs,
int ret = 0;
int changed = 0;
int do_abort = 0;
- int entry, size;
+ int rec_len, entry, size;
struct ext2_dir_entry *dirent;
if (blockcnt < 0)
@@ -158,10 +162,12 @@ int ext2fs_process_dir_block(ext2_filsys fs,
while (offset < fs->blocksize) {
dirent = (struct ext2_dir_entry *) (ctx->buf + offset);
- if (((offset + dirent->rec_len) > fs->blocksize) ||
- (dirent->rec_len < 8) ||
- ((dirent->rec_len % 4) != 0) ||
- (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+ if (((offset + rec_len) > fs->blocksize) ||
+ (rec_len < 8) ||
+ ((rec_len % 4) != 0) ||
+ (((dirent->name_len & 0xFF)+8) > rec_len)) {
ctx->errcode = EXT2_ET_DIR_CORRUPTED;
return BLOCK_ABORT;
}
@@ -178,33 +184,36 @@ int ext2fs_process_dir_block(ext2_filsys fs,
if (entry < DIRENT_OTHER_FILE)
entry++;
- if (ret & DIRENT_CHANGED)
+ if (ret & DIRENT_CHANGED) {
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
changed++;
+ }
if (ret & DIRENT_ABORT) {
do_abort++;
break;
}
next:
if (next_real_entry == offset)
- next_real_entry += dirent->rec_len;
+ next_real_entry += rec_len;
if (ctx->flags & DIRENT_FLAG_INCLUDE_REMOVED) {
size = ((dirent->name_len & 0xFF) + 11) & ~3;
- if (dirent->rec_len != size) {
+ if (rec_len != size) {
unsigned int final_offset;
- final_offset = offset + dirent->rec_len;
+ final_offset = offset + rec_len;
offset += size;
while (offset < final_offset &&
- !ext2fs_validate_entry(ctx->buf,
+ !ext2fs_validate_entry(fs, ctx->buf,
offset,
final_offset))
offset += 4;
continue;
}
}
- offset += dirent->rec_len;
+ offset += rec_len;
}
if (changed) {
diff --git a/lib/ext2fs/dirblock.c b/lib/ext2fs/dirblock.c
index fb20fa0e..c61e001c 100644
--- a/lib/ext2fs/dirblock.c
+++ b/lib/ext2fs/dirblock.c
@@ -46,12 +46,12 @@ errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
if (flags & EXT2_DIRBLOCK_V2_STRUCT)
dirent->name_len = ext2fs_swab16(dirent->name_len);
#endif
- rec_len = dirent->rec_len;
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
if ((rec_len < 8) || (rec_len % 4)) {
rec_len = 8;
retval = EXT2_ET_DIR_CORRUPTED;
- }
- if (((name_len & 0xFF) + 8) > dirent->rec_len)
+ } else if (((name_len & 0xFF) + 8) > rec_len)
retval = EXT2_ET_DIR_CORRUPTED;
p += rec_len;
}
@@ -72,6 +72,7 @@ errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
errcode_t retval;
char *p, *end;
char *buf = 0;
+ int rec_len;
struct ext2_dir_entry *dirent;
retval = ext2fs_get_mem(fs->blocksize, &buf);
@@ -82,12 +83,14 @@ errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
end = buf + fs->blocksize;
while (p < end) {
dirent = (struct ext2_dir_entry *) p;
- if ((dirent->rec_len < 8) ||
- (dirent->rec_len % 4)) {
+ rec_len = (dirent->rec_len || fs->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+ if ((rec_len < 8) ||
+ (rec_len % 4)) {
ext2fs_free_mem(&buf);
return (EXT2_ET_DIR_CORRUPTED);
}
- p += dirent->rec_len;
+ p += rec_len;
dirent->inode = ext2fs_swab32(dirent->inode);
dirent->rec_len = ext2fs_swab16(dirent->rec_len);
dirent->name_len = ext2fs_swab16(dirent->name_len);
diff --git a/lib/ext2fs/link.c b/lib/ext2fs/link.c
index 5e0f4f3c..b2834889 100644
--- a/lib/ext2fs/link.c
+++ b/lib/ext2fs/link.c
@@ -24,6 +24,7 @@ struct link_struct {
ext2_ino_t inode;
int flags;
int done;
+ unsigned int blocksize;
struct ext2_super_block *sb;
};
@@ -35,20 +36,24 @@ static int link_proc(struct ext2_dir_entry *dirent,
{
struct link_struct *ls = (struct link_struct *) priv_data;
struct ext2_dir_entry *next;
- int rec_len, min_rec_len;
+ int rec_len, min_rec_len, curr_rec_len;
int ret = 0;
rec_len = EXT2_DIR_REC_LEN(ls->namelen);
+ curr_rec_len = (dirent->rec_len || ls->blocksize < 65536) ?
+ dirent->rec_len : 65536;
+
/*
* See if the following directory entry (if any) is unused;
* if so, absorb it into this one.
*/
- next = (struct ext2_dir_entry *) (buf + offset + dirent->rec_len);
- if ((offset + dirent->rec_len < blocksize - 8) &&
+ next = (struct ext2_dir_entry *) (buf + offset + curr_rec_len);
+ if ((offset + curr_rec_len < blocksize - 8) &&
(next->inode == 0) &&
- (offset + dirent->rec_len + next->rec_len <= blocksize)) {
+ (offset + curr_rec_len + next->rec_len <= blocksize)) {
dirent->rec_len += next->rec_len;
+ curr_rec_len = dirent->rec_len;
ret = DIRENT_CHANGED;
}
@@ -59,9 +64,9 @@ static int link_proc(struct ext2_dir_entry *dirent,
*/
if (dirent->inode) {
min_rec_len = EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
- if (dirent->rec_len < (min_rec_len + rec_len))
+ if (curr_rec_len < (min_rec_len + rec_len))
return ret;
- rec_len = dirent->rec_len - min_rec_len;
+ rec_len = curr_rec_len - min_rec_len;
dirent->rec_len = min_rec_len;
next = (struct ext2_dir_entry *) (buf + offset +
dirent->rec_len);
@@ -75,7 +80,7 @@ static int link_proc(struct ext2_dir_entry *dirent,
* If we get this far, then the directory entry is not used.
* See if we can fit the request entry in. If so, do it.
*/
- if (dirent->rec_len < rec_len)
+ if (curr_rec_len < rec_len)
return ret;
dirent->inode = ls->inode;
dirent->name_len = ls->namelen;
@@ -112,6 +117,7 @@ errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
ls.flags = flags;
ls.done = 0;
ls.sb = fs->super;
+ ls.blocksize = fs->blocksize;
retval = ext2fs_dir_iterate(fs, dir, DIRENT_FLAG_INCLUDE_EMPTY,
0, link_proc, &ls);
diff --git a/lib/ext2fs/newdir.c b/lib/ext2fs/newdir.c
index 3904d911..c2ca9034 100644
--- a/lib/ext2fs/newdir.c
+++ b/lib/ext2fs/newdir.c
@@ -53,7 +53,7 @@ errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
dir->inode = dir_ino;
dir->name_len = 1 | filetype;
dir->name[0] = '.';
- rec_len = dir->rec_len - EXT2_DIR_REC_LEN(1);
+ rec_len = fs->blocksize - EXT2_DIR_REC_LEN(1);
dir->rec_len = EXT2_DIR_REC_LEN(1);
/*
diff --git a/misc/e2image.c b/misc/e2image.c
index 081c66f7..358b3614 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -350,6 +350,8 @@ 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 0
printf("rec_len = %d, name_len = %d\n", rec_len, dirent->name_len);
#endif