int i;
/*
- * If the index flag is set, then this is a bogus
+ * If the index or extents flag is set, then this is a bogus
* device/fifo/socket
*/
- if (inode->i_flags & EXT2_INDEX_FL)
+ if (inode->i_flags & (EXT2_INDEX_FL | EXT4_EXTENTS_FL))
return 0;
/*
{
unsigned int buflen;
unsigned int len;
- int i;
- ext2_extent_handle_t handle;
- struct ext2_extent_info info;
- struct ext2fs_extent extent;
if ((inode->i_size_high || inode->i_size == 0) ||
(inode->i_flags & EXT2_INDEX_FL))
return 0;
- if (inode->i_flags & EXT4_EXTENTS_FL) {
- if (inode->i_flags & EXT4_INLINE_DATA_FL)
- return 0;
- if (inode->i_size > fs->blocksize)
- return 0;
- if (ext2fs_extent_open2(fs, ino, inode, &handle))
- return 0;
- i = 0;
- if (ext2fs_extent_get_info(handle, &info) ||
- (info.num_entries != 1) ||
- (info.max_depth != 0))
- goto exit_extent;
- if (ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent) ||
- (extent.e_lblk != 0) ||
- (extent.e_len != 1) ||
- (extent.e_pblk < fs->super->s_first_data_block) ||
- (extent.e_pblk >= ext2fs_blocks_count(fs->super)))
- goto exit_extent;
- i = 1;
- exit_extent:
- ext2fs_extent_free(handle);
- return i;
- }
-
if (inode->i_flags & EXT4_INLINE_DATA_FL) {
size_t inline_size;
+ if (inode->i_flags & EXT4_EXTENTS_FL)
+ return 0;
if (ext2fs_inline_data_size(fs, ino, &inline_size))
return 0;
if (inode->i_size != inline_size)
}
if (ext2fs_is_fast_symlink(inode)) {
- if (inode->i_size >= sizeof(inode->i_block))
+ if (inode->i_flags & EXT4_EXTENTS_FL)
return 0;
-
buf = (char *)inode->i_block;
buflen = sizeof(inode->i_block);
} else {
- if ((inode->i_size >= fs->blocksize) ||
- (inode->i_block[0] < fs->super->s_first_data_block) ||
- (inode->i_block[0] >= ext2fs_blocks_count(fs->super)))
- return 0;
+ ext2_extent_handle_t handle;
+ struct ext2_extent_info info;
+ struct ext2fs_extent extent;
+ blk64_t blk;
+ int i;
- for (i = 1; i < EXT2_N_BLOCKS; i++)
- if (inode->i_block[i])
+ if (inode->i_flags & EXT4_EXTENTS_FL) {
+ if (ext2fs_extent_open2(fs, ino, inode, &handle))
+ return 0;
+ if (ext2fs_extent_get_info(handle, &info) ||
+ (info.num_entries != 1) ||
+ (info.max_depth != 0)) {
+ ext2fs_extent_free(handle);
return 0;
+ }
+ if (ext2fs_extent_get(handle, EXT2_EXTENT_ROOT,
+ &extent) ||
+ (extent.e_lblk != 0) ||
+ (extent.e_len != 1)) {
+ ext2fs_extent_free(handle);
+ return 0;
+ }
+ blk = extent.e_pblk;
+ ext2fs_extent_free(handle);
+ } else {
+ blk = inode->i_block[0];
+
+ for (i = 1; i < EXT2_N_BLOCKS; i++)
+ if (inode->i_block[i])
+ return 0;
+ }
- if (io_channel_read_blk64(fs->io, inode->i_block[0], 1, buf))
+ if (blk < fs->super->s_first_data_block ||
+ blk >= ext2fs_blocks_count(fs->super))
+ return 0;
+
+ if (io_channel_read_blk64(fs->io, blk, 1, buf))
return 0;
buflen = fs->blocksize;
return 0;
if (len != inode->i_size)
- if ((inode->i_flags & EXT4_ENCRYPT_FL) == 0)
- return 0;
+ return 0;
return 1;
}
case EXT2_ET_NO_INLINE_DATA:
case EXT2_ET_EXT_ATTR_CSUM_INVALID:
case EXT2_ET_EA_BAD_VALUE_OFFSET:
+ case EXT2_ET_EA_INODE_CORRUPTED:
/* broken EA or no system.data EA; truncate */
if (fix_problem(ctx, PR_1_INLINE_DATA_NO_ATTR,
&pctx)) {
clear_problem_context(&pctx);
if (ext2fs_fast_test_block_bitmap2(ctx->block_found_map, block)) {
+ if (ext2fs_has_feature_shared_blocks(ctx->fs->super) &&
+ !(ctx->options & E2F_OPT_UNSHARE_BLOCKS)) {
+ return;
+ }
if (!ctx->block_dup_map) {
pctx.errcode = e2fsck_allocate_block_bitmap(ctx->fs,
_("multiply claimed block map"),
size = EXT2_I_SIZE(inode);
if ((pb.last_init_lblock >= 0) &&
- /* allow allocated blocks to end of PAGE_SIZE */
+ /* if size is smaller than expected by the block count,
+ * allow allocated blocks to end of PAGE_SIZE.
+ * last_init_lblock is the last in-use block, so it is
+ * the minimum expected file size, but +1 because it is
+ * the base-zero block number and not the block count. */
(size < (__u64)pb.last_init_lblock * fs->blocksize) &&
- (pb.last_init_lblock / blkpg * blkpg != pb.last_init_lblock ||
- size < (__u64)(pb.last_init_lblock & ~(blkpg-1)) *
+ ((pb.last_init_lblock + 1) / blkpg * blkpg !=
+ (pb.last_init_lblock + 1) ||
+ size < (__u64)(pb.last_init_lblock & ~(blkpg - 1)) *
fs->blocksize))
bad_size = 3;
else if (!(extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) &&