#ifdef RESOURCE_TRACK
struct resource_track rtrack;
#endif
- struct dir_info *dir;
struct check_dir_struct cd;
struct dx_dir_info *dx_dir;
struct dx_dirblock_info *dx_db, *dx_parent;
if (!(ctx->options & E2F_OPT_PREEN))
fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
- cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
+ e2fsck_setup_tdb_icount(ctx, EXT2_ICOUNT_OPT_INCREMENT,
+ &ctx->inode_count);
+ if (ctx->inode_count)
+ cd.pctx.errcode = 0;
+ else
+ cd.pctx.errcode = ext2fs_create_icount2(fs,
+ EXT2_ICOUNT_OPT_INCREMENT,
0, ctx->inode_link_info,
&ctx->inode_count);
if (cd.pctx.errcode) {
* present. (If the root directory is not present, we will
* create it in pass 3.)
*/
- dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
- if (dir)
- dir->parent = EXT2_ROOT_INO;
+ (void) e2fsck_dir_info_set_parent(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
cd.buf = buf;
cd.ctx = ctx;
*/
static int check_dotdot(e2fsck_t ctx,
struct ext2_dir_entry *dirent,
- struct dir_info *dir, struct problem_context *pctx)
+ ext2_ino_t ino, struct problem_context *pctx)
{
- int problem = 0;
+ int problem = 0;
if (!dirent->inode)
problem = PR_2_MISSING_DOT_DOT;
}
return 0;
}
- dir->dotdot = dirent->inode;
+ if (e2fsck_dir_info_set_dotdot(ctx, ino, dirent->inode)) {
+ fix_problem(ctx, PR_2_NO_DIRINFO, pctx);
+ return -1;
+ }
return 0;
}
#ifdef DX_DEBUG
printf("Root node dump:\n");
- printf("\t Reserved zero: %d\n", root->reserved_zero);
+ printf("\t Reserved zero: %u\n", root->reserved_zero);
printf("\t Hash Version: %d\n", root->hash_version);
printf("\t Info length: %d\n", root->info_length);
printf("\t Indirect levels: %d\n", root->indirect_levels);
prev_hash = hash;
hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
#ifdef DX_DEBUG
- printf("Entry #%d: Hash 0x%08x, block %d\n", i,
+ printf("Entry #%d: Hash 0x%08x, block %u\n", i,
hash, ext2fs_le32_to_cpu(ent[i].block));
#endif
blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
/* Check to make sure the block is valid */
- if (blk > (blk_t) dx_dir->numblocks) {
+ if (blk >= (blk_t) dx_dir->numblocks) {
cd->pctx.blk = blk;
if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
&cd->pctx))
goto clear_and_exit;
+ continue;
}
if (hash < prev_hash &&
fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
{
char *cp = (char *) dirent;
int left = fs->blocksize - *offset - dirent->rec_len;
- int name_len = dirent->name_len & 0xFF;
+ unsigned int name_len = dirent->name_len & 0xFF;
/*
* Special case of directory entry of size 8: copy what's left
* record length.
*/
if ((left < 0) &&
- (name_len + 8 <= dirent->rec_len + left) &&
+ (name_len + 8 <= dirent->rec_len + (unsigned) left) &&
dirent->inode <= fs->super->s_inodes_count &&
strnlen(dirent->name, name_len) == name_len) {
dirent->rec_len += left;
struct ext2_db_entry *db,
void *priv_data)
{
- struct dir_info *subdir, *dir;
+ struct dir_info *subdir;
struct dx_dir_info *dx_dir;
#ifdef ENABLE_HTREE
struct dx_dirblock_info *dx_db = 0;
int dot_state;
blk_t block_nr = db->blk;
ext2_ino_t ino = db->ino;
+ ext2_ino_t subdir_parent;
__u16 links;
struct check_dir_struct *cd;
char *buf;
static dict_t de_dict;
struct problem_context pctx;
int dups_found = 0;
+ int ret;
cd = (struct check_dir_struct *) priv_data;
buf = cd->buf;
clear_htree(ctx, ino);
dx_dir->numblocks = 0;
dx_db = 0;
- }
+ }
dx_dir->hashversion = root->hash_version;
+ if ((dx_dir->hashversion <= EXT2_HASH_TEA) &&
+ (fs->super->s_flags & EXT2_FLAGS_UNSIGNED_HASH))
+ dx_dir->hashversion += 3;
dx_dir->depth = root->indirect_levels + 1;
} else if ((dirent->inode == 0) &&
(dirent->rec_len == fs->blocksize) &&
if (check_dot(ctx, dirent, ino, &cd->pctx))
dir_modified++;
} else if (dot_state == 1) {
- dir = e2fsck_get_dir_info(ctx, ino);
- if (!dir) {
- fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
+ ret = check_dotdot(ctx, dirent, ino, &cd->pctx);
+ if (ret < 0)
goto abort_free_dict;
- }
- if (check_dotdot(ctx, dirent, dir, &cd->pctx))
+ if (ret)
dir_modified++;
} else if (dirent->inode == ino) {
problem = PR_2_LINK_DOT;
if ((dot_state > 1) &&
(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
dirent->inode))) {
- subdir = e2fsck_get_dir_info(ctx, dirent->inode);
- if (!subdir) {
+ if (e2fsck_dir_info_get_parent(ctx, dirent->inode,
+ &subdir_parent)) {
cd->pctx.ino = dirent->inode;
fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
goto abort_free_dict;
}
- if (subdir->parent) {
- cd->pctx.ino2 = subdir->parent;
+ if (subdir_parent) {
+ cd->pctx.ino2 = subdir_parent;
if (fix_problem(ctx, PR_2_LINK_DIR,
&cd->pctx)) {
dirent->inode = 0;
goto next;
}
cd->pctx.ino2 = 0;
- } else
- subdir->parent = ino;
+ } else {
+ (void) e2fsck_dir_info_set_parent(ctx,
+ dirent->inode, ino);
+ }
}
if (dups_found) {
pctx.inode = &inode;
if (inode.i_file_acl &&
- !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
- fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
- inode.i_file_acl = 0;
+ !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
+ if (fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
+ inode.i_file_acl = 0;
#ifdef EXT2FS_ENABLE_SWAPFS
- /*
- * This is a special kludge to deal with long symlinks
- * on big endian systems. i_blocks had already been
- * decremented earlier in pass 1, but since i_file_acl
- * hadn't yet been cleared, ext2fs_read_inode()
- * assumed that the file was short symlink and would
- * not have byte swapped i_block[0]. Hence, we have
- * to byte-swap it here.
- */
- if (LINUX_S_ISLNK(inode.i_mode) &&
- (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
- (inode.i_blocks == fs->blocksize >> 9))
- inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
+ /*
+ * This is a special kludge to deal with long
+ * symlinks on big endian systems. i_blocks
+ * had already been decremented earlier in
+ * pass 1, but since i_file_acl hadn't yet
+ * been cleared, ext2fs_read_inode() assumed
+ * that the file was short symlink and would
+ * not have byte swapped i_block[0]. Hence,
+ * we have to byte-swap it here.
+ */
+ if (LINUX_S_ISLNK(inode.i_mode) &&
+ (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
+ (inode.i_blocks == fs->blocksize >> 9))
+ inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
#endif
- inode_modified++;
- } else
- not_fixed++;
+ inode_modified++;
+ } else
+ not_fixed++;
+ }
if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
!LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
}
switch (fs->super->s_creator_os) {
- case EXT2_OS_LINUX:
- frag = &inode.osd2.linux2.l_i_frag;
- fsize = &inode.osd2.linux2.l_i_fsize;
- break;
case EXT2_OS_HURD:
frag = &inode.osd2.hurd2.h_i_frag;
fsize = &inode.osd2.hurd2.h_i_fsize;
pctx.num = 0;
}
+ if ((fs->super->s_creator_os == EXT2_OS_LINUX) &&
+ !(fs->super->s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_HUGE_FILE) &&
+ (inode.osd2.linux2.l_i_blocks_hi != 0)) {
+ pctx.num = inode.osd2.linux2.l_i_blocks_hi;
+ if (fix_problem(ctx, PR_2_BLOCKS_HI_ZERO, &pctx)) {
+ inode.osd2.linux2.l_i_blocks_hi = 0;
+ inode_modified++;
+ }
+ }
+
if (inode.i_file_acl &&
((inode.i_file_acl < fs->super->s_first_data_block) ||
(inode.i_file_acl >= fs->super->s_blocks_count))) {
if (inode_modified)
e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
- if (!not_fixed)
+ if (!not_fixed && ctx->inode_bad_map)
ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
return 0;
}