#define STATIC static
#endif
+void ext2fs_init_csum_seed(ext2_filsys fs)
+{
+ if (ext2fs_has_feature_csum_seed(fs->super))
+ fs->csum_seed = fs->super->s_checksum_seed;
+ else if (ext2fs_has_feature_metadata_csum(fs->super) ||
+ ext2fs_has_feature_ea_inode(fs->super))
+ fs->csum_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid,
+ sizeof(fs->super->s_uuid));
+}
+
static __u32 ext2fs_mmp_csum(ext2_filsys fs, struct mmp_struct *mmp)
{
int offset = offsetof(struct mmp_struct, mmp_checksum);
{
__u32 calculated;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 1;
calculated = ext2fs_mmp_csum(fs, mmp);
{
__u32 crc;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 0;
crc = ext2fs_mmp_csum(fs, mmp);
int ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb)
{
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 1;
return sb->s_checksum_type == EXT2_CRC32C_CHKSUM;
return ext2fs_crc32c_le(~0, (unsigned char *)sb, offset);
}
+/* NOTE: The input to this function MUST be in LE order */
int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb)
{
- __u32 calculated;
+ __u32 flag, calculated;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+ flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+ else
+ flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+
+ if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag))
return 1;
calculated = ext2fs_superblock_csum(fs, sb);
return ext2fs_le32_to_cpu(sb->s_checksum) == calculated;
}
+/* NOTE: The input to this function MUST be in LE order */
errcode_t ext2fs_superblock_csum_set(ext2_filsys fs,
struct ext2_super_block *sb)
{
- __u32 crc;
+ __u32 flag, crc;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (fs->flags & EXT2_FLAG_SWAP_BYTES)
+ flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
+ else
+ flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+
+ if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag))
return 0;
crc = ext2fs_superblock_csum(fs, sb);
__u32 calculated;
errcode_t retval;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 1;
retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &calculated);
errcode_t retval;
__u32 crc;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 0;
retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &crc);
d = dirent;
top = EXT2_DIRENT_TAIL(dirent, fs->blocksize);
- rec_len = translate(d->rec_len);
- while (rec_len && !(rec_len & 0x3)) {
- d = (struct ext2_dir_entry *)(((char *)d) + rec_len);
- if ((void *)d >= top)
- break;
+ while ((void *) d < top) {
rec_len = translate(d->rec_len);
+ if ((rec_len < 8) || (rec_len & 0x03))
+ return EXT2_ET_DIR_CORRUPTED;
+ d = (struct ext2_dir_entry *)(((char *)d) + rec_len);
}
+ if ((char *)d > ((char *)dirent + fs->blocksize))
+ return EXT2_ET_DIR_CORRUPTED;
if (d != top)
return EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
int ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent)
{
- return __get_dirent_tail(fs, dirent, NULL, 0) == 0;
+ return __get_dirent_tail(fs, dirent, NULL, 0) !=
+ EXT2_ET_DIR_NO_SPACE_FOR_CSUM;
}
static errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum,
int ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum,
struct ext2_dir_entry *dirent)
{
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 1;
if (__get_dirent_tail(fs, dirent, NULL, 1) == 0)
errcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum,
struct ext2_dir_entry *dirent)
{
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 0;
if (__get_dirent_tail(fs, dirent, NULL, 1) == 0)
* The extent tree structures are accessed in LE order, so we must
* swap the checksum bytes here.
*/
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 1;
provided = ext2fs_le32_to_cpu(t->et_checksum);
__u32 crc;
struct ext3_extent_tail *t = get_extent_tail(eh);
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 0;
/*
ext2fs_group_desc(fs, fs->group_desc, group);
__u32 provided, calculated;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 1;
provided = gdp->bg_inode_bitmap_csum_lo;
calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
size);
- if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
+ if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
provided |= (__u32)gdp->bg_inode_bitmap_csum_hi << 16;
else
calculated &= 0xFFFF;
struct ext4_group_desc *gdp = (struct ext4_group_desc *)
ext2fs_group_desc(fs, fs->group_desc, group);
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 0;
crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
gdp->bg_inode_bitmap_csum_lo = crc & 0xFFFF;
- if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
+ if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_INODE_BITMAP_CSUM_HI_END)
gdp->bg_inode_bitmap_csum_hi = crc >> 16;
return 0;
ext2fs_group_desc(fs, fs->group_desc, group);
__u32 provided, calculated;
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 1;
provided = gdp->bg_block_bitmap_csum_lo;
calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap,
size);
- if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
+ if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
provided |= (__u32)gdp->bg_block_bitmap_csum_hi << 16;
else
calculated &= 0xFFFF;
struct ext4_group_desc *gdp = (struct ext4_group_desc *)
ext2fs_group_desc(fs, fs->group_desc, group);
- if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 0;
crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size);
gdp->bg_block_bitmap_csum_lo = crc & 0xFFFF;
- if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
+ if (EXT2_DESC_SIZE(fs->super) >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION)
gdp->bg_block_bitmap_csum_hi = crc >> 16;
return 0;
{
__u32 gen;
struct ext2_inode_large *desc = inode;
- size_t size = fs->super->s_inode_size;
+ size_t size = EXT2_INODE_SIZE(fs->super);
__u16 old_lo;
__u16 old_hi = 0;
unsigned int i, has_hi;
char *cp;
- if (fs->super->s_creator_os != EXT2_OS_LINUX ||
- !EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 1;
has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE &&
__u32 crc;
int has_hi;
- if (fs->super->s_creator_os != EXT2_OS_LINUX ||
- !EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
+ if (!ext2fs_has_feature_metadata_csum(fs->super))
return 0;
has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE &&
{
struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc,
group);
- size_t size = EXT2_DESC_SIZE(fs->super);
- size_t offset;
+ size_t offset, size = EXT2_DESC_SIZE(fs->super);
__u16 crc = 0;
#ifdef WORDS_BIGENDIAN
struct ext4_group_desc swabdesc;
group = ext2fs_swab32(group);
#endif
- if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
- EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
+ if (ext2fs_has_feature_metadata_csum(fs->super)) {
/* new metadata csum code */
__u16 old_crc;
__u32 crc32;
#ifdef WORDS_BIGENDIAN
if (save_size > ext4_bg_size)
crc32 = ext2fs_crc32c_le(crc32,
- (char *)save_desc + ext4_bg_size,
- save_size - ext4_bg_size);
+ (unsigned char *)save_desc + ext4_bg_size,
+ save_size - ext4_bg_size);
#endif
crc = crc32 & 0xFFFF;
goto out;
__u32 old_unused = ext2fs_bg_itable_unused(fs, i);
__u32 old_flags = ext2fs_bg_flags(fs, i);
__u32 old_free_inodes_count = ext2fs_bg_free_inodes_count(fs, i);
+ __u32 old_free_blocks_count = ext2fs_bg_free_blocks_count(fs, i);
+
+ if (old_free_blocks_count == sb->s_blocks_per_group &&
+ i != fs->group_desc_count - 1)
+ ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT);
if (old_free_inodes_count == sb->s_inodes_per_group) {
ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT);
printf("checksums for different data shouldn't match\n");
exit(1);
}
+ ext2fs_free(fs);
return 0;
}