Whamcloud - gitweb
Add support for with empty directory blocks in 64k blocksize filesystems
authorTheodore Ts'o <tytso@mit.edu>
Tue, 26 Aug 2008 01:08:19 +0000 (21:08 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 26 Aug 2008 01:08:19 +0000 (21:08 -0400)
The rec_len field in the directory entry is 16 bits, so if the
filesystem is completely empty, rec_len of 0 is used to designate
65536, for the case where the directory entry takes the entire 64k
block.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
debugfs/htree.c
e2fsck/pass1.c
e2fsck/pass2.c
e2fsck/problem.c
e2fsck/rehash.c
lib/ext2fs/dir_iterate.c
lib/ext2fs/dirblock.c
lib/ext2fs/link.c
lib/ext2fs/newdir.c
misc/e2image.c

index bee78d7..1659b63 100644 (file)
@@ -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;
 }
index 0e245dd..f2f72ed 100644 (file)
@@ -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)) {
index f4fa93e..1992479 100644 (file)
@@ -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++;
index 9d4c4e8..27e2bf0 100644 (file)
@@ -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 */
index e75774a..6c7d051 100644 (file)
@@ -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) &&
index 3e7b7b0..6bb536b 100644 (file)
  * 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) {
index fb20fa0..c61e001 100644 (file)
@@ -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);
index 5e0f4f3..b283488 100644 (file)
@@ -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);
index 3904d91..c2ca903 100644 (file)
@@ -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);
 
                /*
index 081c66f..358b361 100644 (file)
@@ -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