struct ext2_super_block *sb = ctx->fs->super;
struct ext2_inode_large *inode;
struct ext2_ext_attr_entry *entry;
- char *start, *end;
+ char *start;
unsigned int storage_size, remain;
- int problem = 0;
+ problem_t problem = 0;
inode = (struct ext2_inode_large *) pctx->inode;
storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
inode->i_extra_isize;
start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
inode->i_extra_isize + sizeof(__u32);
- end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
entry = (struct ext2_ext_attr_entry *) start;
/* scan all entry's headers first */
remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
/* check value size */
- if (entry->e_value_size == 0 || entry->e_value_size > remain) {
+ if (entry->e_value_size > remain) {
pctx->num = entry->e_value_size;
problem = PR_1_ATTR_VALUE_SIZE;
goto fix;
retval = ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
if (retval)
return;
- if (((dirent->name_len & 0xFF) != 1) ||
+ if ((ext2fs_dirent_name_len(dirent) != 1) ||
(dirent->name[0] != '.') ||
(dirent->inode != pctx->ino) ||
(rec_len < 12) ||
retval = ext2fs_get_rec_len(ctx->fs, dirent, &rec_len);
if (retval)
return;
- if (((dirent->name_len & 0xFF) != 2) ||
+ if ((ext2fs_dirent_name_len(dirent) != 2) ||
(dirent->name[0] != '.') ||
(dirent->name[1] != '.') ||
(rec_len < 12) ||
}
}
-extern void e2fsck_setup_tdb_icount(e2fsck_t ctx, int flags,
- ext2_icount_t *ret)
+void e2fsck_setup_tdb_icount(e2fsck_t ctx, int flags,
+ ext2_icount_t *ret)
{
unsigned int threshold;
ext2_ino_t num_dirs;
busted_fs_time = 1;
if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) &&
- !(fs->super->s_mmp_block <= fs->super->s_first_data_block ||
- fs->super->s_mmp_block >= fs->super->s_blocks_count))
+ fs->super->s_mmp_block > fs->super->s_first_data_block &&
+ fs->super->s_mmp_block < ext2fs_blocks_count(fs->super))
ext2fs_mark_block_bitmap2(ctx->block_found_map,
fs->super->s_mmp_block);
inode_size, "pass1");
}
} else if (ino < EXT2_FIRST_INODE(fs->super)) {
- int problem = 0;
+ problem_t problem = 0;
ext2fs_mark_inode_bitmap2(ctx->inode_used_map, ino);
if (ino == EXT2_BOOT_LOADER_INO) {
static void scan_extent_node(e2fsck_t ctx, struct problem_context *pctx,
struct process_block_struct *pb,
- blk64_t start_block,
+ blk64_t start_block, blk64_t end_block,
+ blk64_t eof_block,
ext2_extent_handle_t ehandle)
{
struct ext2fs_extent extent;
- blk64_t blk;
+ blk64_t blk, last_lblk;
e2_blkcnt_t blockcnt;
unsigned int i;
int is_dir, is_leaf;
- errcode_t problem;
+ problem_t problem;
struct ext2_extent_info info;
int failed_csum;
failed_csum = 0;
is_leaf = extent.e_flags & EXT2_EXTENT_FLAGS_LEAF;
is_dir = LINUX_S_ISDIR(pctx->inode->i_mode);
+ last_lblk = extent.e_lblk + extent.e_len - 1;
problem = 0;
/* Ask to clear a corrupt extent block */
problem = PR_1_EXTENT_BAD_START_BLK;
else if (extent.e_lblk < start_block)
problem = PR_1_OUT_OF_ORDER_EXTENTS;
+ else if ((end_block && last_lblk > end_block) &&
+ (!(extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT &&
+ last_lblk > eof_block)))
+ problem = PR_1_EXTENT_END_OUT_OF_BOUNDS;
else if (is_leaf && extent.e_len == 0)
problem = PR_1_EXTENT_LENGTH_ZERO;
else if (is_leaf &&
(extent.e_pblk + extent.e_len) >
ext2fs_blocks_count(ctx->fs->super))
problem = PR_1_EXTENT_ENDS_BEYOND;
+ else if (is_leaf && is_dir &&
+ ((extent.e_lblk + extent.e_len) >
+ (1 << (21 - ctx->fs->super->s_log_block_size))))
+ problem = PR_1_TOOBIG_DIR;
/* Corrupt but passes checks? Ask to fix checksum. */
if (failed_csum) {
}
if (problem) {
- report_problem:
+report_problem:
pctx->blk = extent.e_pblk;
pctx->blk2 = extent.e_lblk;
pctx->num = extent.e_len;
+ pctx->blkcount = extent.e_lblk + extent.e_len;
if (fix_problem(ctx, problem, pctx)) {
fix_problem_now:
e2fsck_read_bitmaps(ctx);
pctx->str = "ext2fs_extent_delete";
return;
}
+ ext2fs_extent_fix_parents(ehandle);
pctx->errcode = ext2fs_extent_get(ehandle,
EXT2_EXTENT_CURRENT,
&extent);
}
if (!is_leaf) {
+ blk64_t lblk = extent.e_lblk;
+
blk = extent.e_pblk;
pctx->errcode = ext2fs_extent_get(ehandle,
EXT2_EXTENT_DOWN, &extent);
goto report_problem;
return;
}
- scan_extent_node(ctx, pctx, pb, extent.e_lblk, ehandle);
+ /* The next extent should match this index's logical start */
+ if (extent.e_lblk != lblk) {
+ struct ext2_extent_info e_info;
+
+ ext2fs_extent_get_info(ehandle, &e_info);
+ pctx->blk = lblk;
+ pctx->blk2 = extent.e_lblk;
+ pctx->num = e_info.curr_level - 1;
+ problem = PR_1_EXTENT_INDEX_START_INVALID;
+ if (fix_problem(ctx, problem, pctx))
+ ext2fs_extent_fix_parents(ehandle);
+ }
+ scan_extent_node(ctx, pctx, pb, extent.e_lblk,
+ last_lblk, eof_block, ehandle);
if (pctx->errcode)
return;
pctx->errcode = ext2fs_extent_get(ehandle,
}
pb->fragmented = 1;
}
- while (is_dir && ++pb->last_db_block < extent.e_lblk) {
+ while (is_dir && (++pb->last_db_block <
+ (e2_blkcnt_t) extent.e_lblk)) {
pctx->errcode = ext2fs_add_dir_block2(ctx->fs->dblist,
pb->ino, 0,
pb->last_db_block);
(EXT2FS_B2C(ctx->fs, blk) ==
EXT2FS_B2C(ctx->fs, pb->previous_block)) &&
(blk & EXT2FS_CLUSTER_MASK(ctx->fs)) ==
- (blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) {
+ ((unsigned) blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) {
mark_block_used(ctx, blk);
pb->num_blocks++;
}
if (is_dir && extent.e_len > 0)
pb->last_db_block = blockcnt - 1;
pb->previous_block = extent.e_pblk + extent.e_len - 1;
- start_block = pb->last_block = extent.e_lblk + extent.e_len - 1;
+ start_block = pb->last_block = last_lblk;
if (is_leaf && !is_dir &&
!(extent.e_flags & EXT2_EXTENT_FLAGS_UNINIT))
- pb->last_init_lblock = extent.e_lblk + extent.e_len - 1;
+ pb->last_init_lblock = last_lblk;
next:
pctx->errcode = ext2fs_extent_get(ehandle,
EXT2_EXTENT_NEXT_SIB,
ext2_filsys fs = ctx->fs;
ext2_ino_t ino = pctx->ino;
errcode_t retval;
+ blk64_t eof_lblk;
pctx->errcode = ext2fs_extent_open2(fs, ino, inode, &ehandle);
if (pctx->errcode) {
ctx->extent_depth_count[info.max_depth]++;
}
- scan_extent_node(ctx, pctx, pb, 0, ehandle);
+ eof_lblk = ((EXT2_I_SIZE(inode) + fs->blocksize - 1) >>
+ EXT2_BLOCK_SIZE_BITS(fs->super)) - 1;
+ scan_extent_node(ctx, pctx, pb, 0, 0, eof_lblk, ehandle);
if (pctx->errcode &&
fix_problem(ctx, PR_1_EXTENT_ITERATE_FAILURE, pctx)) {
pb->num_blocks = 0;
struct process_block_struct pb;
ext2_ino_t ino = pctx->ino;
struct ext2_inode *inode = pctx->inode;
- int bad_size = 0;
+ unsigned bad_size = 0;
int dirty_inode = 0;
int extent_fs;
__u64 size;
}
pctx->num = 0;
}
- if (LINUX_S_ISREG(inode->i_mode) && EXT2_I_SIZE(inode) >= 0x80000000UL)
+ if (LINUX_S_ISREG(inode->i_mode) &&
+ ext2fs_needs_large_file_feature(EXT2_I_SIZE(inode)))
ctx->large_files++;
if ((pb.num_blocks != ext2fs_inode_i_blocks(fs, inode)) ||
((fs->super->s_feature_ro_compat &
struct problem_context *pctx;
blk64_t blk = *block_nr;
int ret_code = 0;
- int problem = 0;
+ problem_t problem = 0;
e2fsck_t ctx;
p = (struct process_block_struct *) priv_data;
(EXT2FS_B2C(ctx->fs, blk) ==
EXT2FS_B2C(ctx->fs, p->previous_block)) &&
(blk & EXT2FS_CLUSTER_MASK(ctx->fs)) ==
- (blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) {
+ ((unsigned) blockcnt & EXT2FS_CLUSTER_MASK(ctx->fs)))) {
mark_block_used(ctx, blk);
p->num_blocks++;
}
return 0;
}
-static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
+static void new_table_block(e2fsck_t ctx, blk64_t first_block, dgrp_t group,
const char *name, int num, blk64_t *new_block)
{
ext2_filsys fs = ctx->fs;
dgrp_t last_grp;
blk64_t old_block = *new_block;
blk64_t last_block;
- int i, is_flexbg, flexbg, flexbg_size;
+ dgrp_t flexbg;
+ unsigned flexbg_size;
+ int i, is_flexbg;
char *buf;
struct problem_context pctx;
ext2_filsys fs = ctx->fs;
blk64_t b;
dgrp_t i;
- int j;
+ unsigned int j;
struct problem_context pctx;
clear_problem_context(&pctx);