LINUX_S_ISLNK(inode->i_mode) || inode->i_block[0] == 0)
return;
- for (i=0; i < EXT2_N_BLOCKS; i++) {
- blk = inode->i_block[i];
- if (!blk)
- continue;
- if (i >= 4)
- not_device++;
-
- if (blk < ctx->fs->super->s_first_data_block ||
- blk >= ext2fs_blocks_count(ctx->fs->super) ||
- ext2fs_fast_test_block_bitmap2(ctx->block_found_map, blk))
- return; /* Invalid block, can't be dir */
+ /*
+ * Check the block numbers in the i_block array for validity:
+ * zero blocks are skipped (but the first one cannot be zero -
+ * see above), other blocks are checked against the first and
+ * max data blocks (from the the superblock) and against the
+ * block bitmap. Any invalid block found means this cannot be
+ * a directory.
+ *
+ * If there are non-zero blocks past the fourth entry, then
+ * this cannot be a device file: we remember that for the next
+ * check.
+ *
+ * For extent mapped files, we don't do any sanity checking:
+ * just try to get the phys block of logical block 0 and run
+ * with it.
+ */
+
+ extent_fs = (ctx->fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS);
+ if (extent_fs && (inode->i_flags & EXT4_EXTENTS_FL)) {
+ /* extent mapped */
+ if (ext2fs_bmap(ctx->fs, pctx->ino, inode, 0, 0, 0,
+ &blk))
+ return;
+ /* device files are never extent mapped */
+ not_device++;
+ } else {
+ for (i=0; i < EXT2_N_BLOCKS; i++) {
+ blk = inode->i_block[i];
+ if (!blk)
+ continue;
+ if (i >= 4)
+ not_device++;
+
+ if (blk < ctx->fs->super->s_first_data_block ||
- blk >= ctx->fs->super->s_blocks_count ||
- ext2fs_fast_test_block_bitmap(ctx->block_found_map,
- blk))
++ blk >= ext2fs_blocks_count(ctx->fs->super) ||
++ ext2fs_fast_test_block_bitmap2(ctx->block_found_map,
++ blk))
+ return; /* Invalid block, can't be dir */
+ }
+ blk = inode->i_block[0];
}
+ /*
+ * If the mode says this is a device file and the i_links_count field
+ * is sane and we have not ruled it out as a device file previously,
+ * we declare it a device file, not a directory.
+ */
if ((LINUX_S_ISCHR(inode->i_mode) || LINUX_S_ISBLK(inode->i_mode)) &&
(inode->i_links_count == 1) && !not_device)
return;
}
count++;
if ((count == fs->super->s_blocks_per_group) ||
- (blk == fs->super->s_blocks_count-1)) {
- fs->group_desc[group].bg_free_blocks_count =
- group_free;
+ (blk == ext2fs_blocks_count(fs->super)-1)) {
+ ext2fs_bg_free_blocks_count_set(fs, group, group_free);
ext2fs_group_desc_csum_set(fs, group);
group++;
+ if (group >= fs->group_desc_count)
+ break;
count = 0;
group_free = 0;
- uninit = (fs->group_desc[group].bg_flags &
- EXT2_BG_BLOCK_UNINIT);
+ uninit = (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT)
+ );
ext2fs_super_and_bgd_loc(fs, group, &super_blk,
&old_desc_blk,
&new_desc_blk, 0);
count++;
if ((count == fs->super->s_inodes_per_group) ||
(ino == fs->super->s_inodes_count)) {
- fs->group_desc[group].bg_free_inodes_count =
- group_free;
+ ext2fs_bg_free_inodes_count_set(fs, group, group_free);
ext2fs_group_desc_csum_set(fs, group);
group++;
+ if (group >= fs->group_desc_count)
+ break;
count = 0;
group_free = 0;
- uninit = (fs->group_desc[group].bg_flags &
- EXT2_BG_INODE_UNINIT);
+ uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT);
}
}
fs->super->s_free_inodes_count = total_free;