X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lib%2Fext2fs%2Fcsum.c;h=9b0b7908e0f6ede0837256277f601b105c2d057d;hb=3ec53092ddb3fb0a44242ae3349b8f6ea14c220e;hp=e276c5de9175871d851c22c9f7d313e3760b9fb3;hpb=1eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3;p=tools%2Fe2fsprogs.git diff --git a/lib/ext2fs/csum.c b/lib/ext2fs/csum.c index e276c5d..9b0b790 100644 --- a/lib/ext2fs/csum.c +++ b/lib/ext2fs/csum.c @@ -30,28 +30,75 @@ #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); + + return ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)mmp, offset); +} + +int ext2fs_mmp_csum_verify(ext2_filsys fs, struct mmp_struct *mmp) +{ + __u32 calculated; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 1; + + calculated = ext2fs_mmp_csum(fs, mmp); + + return ext2fs_le32_to_cpu(mmp->mmp_checksum) == calculated; +} + +errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp) +{ + __u32 crc; + + if (!ext2fs_has_feature_metadata_csum(fs->super)) + return 0; + + crc = ext2fs_mmp_csum(fs, mmp); + mmp->mmp_checksum = ext2fs_cpu_to_le32(crc); + + return 0; +} + 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; } -static __u32 ext2fs_superblock_csum(ext2_filsys fs, struct ext2_super_block *sb) +static __u32 ext2fs_superblock_csum(ext2_filsys fs EXT2FS_ATTR((unused)), + struct ext2_super_block *sb) { int offset = offsetof(struct ext2_super_block, s_checksum); 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 (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, - EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag)) return 1; calculated = ext2fs_superblock_csum(fs, sb); @@ -59,13 +106,18 @@ int ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *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); @@ -74,15 +126,14 @@ errcode_t ext2fs_superblock_csum_set(ext2_filsys fs, return 0; } -static errcode_t ext2fs_ext_attr_block_csum(ext2_filsys fs, ext2_ino_t inum, +static errcode_t ext2fs_ext_attr_block_csum(ext2_filsys fs, + ext2_ino_t inum EXT2FS_ATTR((unused)), blk64_t block, struct ext2_ext_attr_header *hdr, __u32 *crc) { - errcode_t retval; char *buf = (char *)hdr; - __u32 gen, old_crc = hdr->h_checksum; - struct ext2_inode inode; + __u32 old_crc = hdr->h_checksum; hdr->h_checksum = 0; block = ext2fs_cpu_to_le64(block); @@ -101,8 +152,7 @@ int ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, __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); @@ -119,8 +169,7 @@ errcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, ext2_ino_t inum, 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); @@ -158,11 +207,11 @@ static errcode_t __get_dx_countlimit(ext2_filsys fs, if (rec_len == fs->blocksize && translate(dirent->name_len) == 0) count_offset = 8; else if (rec_len == 12) { - dp = (struct ext2_dir_entry *)(((void *)dirent) + rec_len); + dp = (struct ext2_dir_entry *)(((char *)dirent) + rec_len); rec_len = translate(dp->rec_len); if (rec_len != fs->blocksize - 12) return EXT2_ET_DB_NOT_FOUND; - root = (struct ext2_dx_root_info *)(((void *)dp + 12)); + root = (struct ext2_dx_root_info *)(((char *)dp + 12)); if (root->reserved_zero || root->info_length != sizeof(struct ext2_dx_root_info)) return EXT2_ET_DB_NOT_FOUND; @@ -170,7 +219,7 @@ static errcode_t __get_dx_countlimit(ext2_filsys fs, } else return EXT2_ET_DB_NOT_FOUND; - c = (struct ext2_dx_countlimit *)(((void *)dirent) + count_offset); + c = (struct ext2_dx_countlimit *)(((char *)dirent) + count_offset); max_sane_entries = (fs->blocksize - count_offset) / sizeof(struct ext2_dx_entry); if (ext2fs_le16_to_cpu(c->limit) > max_sane_entries || @@ -217,14 +266,15 @@ static errcode_t __get_dirent_tail(ext2_filsys fs, 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 *)(((void *)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; @@ -241,7 +291,8 @@ static errcode_t __get_dirent_tail(ext2_filsys fs, 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, @@ -283,7 +334,7 @@ int ext2fs_dirent_csum_verify(ext2_filsys fs, ext2_ino_t inum, * so the swapfs.c functions won't change the endianness. */ retval = ext2fs_dirent_csum(fs, inum, dirent, &calculated, - (void *)t - (void *)dirent); + (char *)t - (char *)dirent); if (retval) return 0; return ext2fs_le32_to_cpu(t->det_checksum) == calculated; @@ -302,7 +353,7 @@ static errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum, /* swapfs.c functions don't change the checksum endianness */ retval = ext2fs_dirent_csum(fs, inum, dirent, &crc, - (void *)t - (void *)dirent); + (char *)t - (char *)dirent); if (retval) return retval; t->det_checksum = ext2fs_cpu_to_le32(crc); @@ -398,8 +449,7 @@ static errcode_t ext2fs_dx_csum_set(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) @@ -413,8 +463,7 @@ int ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, 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) @@ -432,7 +481,7 @@ errcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum, static struct ext3_extent_tail *get_extent_tail(struct ext3_extent_header *h) { - return (struct ext3_extent_tail *)(((void *)h) + + return (struct ext3_extent_tail *)(((char *)h) + EXT3_EXTENT_TAIL_OFFSET(h)); } @@ -472,8 +521,7 @@ int ext2fs_extent_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, * 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); @@ -491,8 +539,7 @@ errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, ext2_ino_t inum, __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; /* @@ -513,13 +560,12 @@ int ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, 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; @@ -534,13 +580,12 @@ errcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group, 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; @@ -553,13 +598,12 @@ int ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, 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; @@ -574,13 +618,12 @@ errcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group, 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; @@ -592,7 +635,7 @@ static errcode_t ext2fs_inode_csum(ext2_filsys fs, ext2_ino_t inum, { __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; @@ -621,11 +664,10 @@ int ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum, { errcode_t retval; __u32 provided, calculated; - int has_hi; + 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 && @@ -641,7 +683,23 @@ int ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum, } else calculated &= 0xFFFF; - return provided == calculated; + if (provided == calculated) + return 1; + + /* + * If the checksum didn't match, it's possible it was due to + * the inode being all zero's. It's unlikely this is the + * case, but it can happen. So check for it here. (We only + * check the base inode since that's good enough, and it's not + * worth the bother to figure out how much of the extended + * inode, if any, is present.) + */ + for (cp = (char *) inode, i = 0; + i < sizeof(struct ext2_inode); + cp++, i++) + if (*cp) + return 0; + return 1; /* Inode must have been all zero's */ } errcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum, @@ -651,9 +709,7 @@ errcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum, __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 && @@ -670,53 +726,77 @@ errcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum, __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group) { + struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, + group); + size_t offset, size = EXT2_DESC_SIZE(fs->super); __u16 crc = 0; - struct ext2_group_desc *desc; - size_t size; - - size = fs->super->s_desc_size; - if (size < EXT2_MIN_DESC_SIZE) - size = EXT2_MIN_DESC_SIZE; - if (size > sizeof(struct ext4_group_desc)) { - /* This should never happen, but cap it for safety's sake */ - size = sizeof(struct ext4_group_desc); - } - - desc = ext2fs_group_desc(fs, fs->group_desc, group); - - if (fs->super->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) { - size_t offset = offsetof(struct ext2_group_desc, bg_checksum); - #ifdef WORDS_BIGENDIAN - struct ext4_group_desc swabdesc; + struct ext4_group_desc swabdesc; + size_t save_size = size; + const size_t ext4_bg_size = sizeof(struct ext4_group_desc); + struct ext2_group_desc *save_desc = desc; - /* Have to swab back to little-endian to do the checksum */ - memcpy(&swabdesc, desc, size); - ext2fs_swap_group_desc2(fs, - (struct ext2_group_desc *) &swabdesc); - desc = (struct ext2_group_desc *) &swabdesc; + /* Have to swab back to little-endian to do the checksum */ + if (size > ext4_bg_size) + size = ext4_bg_size; + memcpy(&swabdesc, desc, size); + ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc); + desc = (struct ext2_group_desc *) &swabdesc; + group = ext2fs_swab32(group); +#endif - group = ext2fs_swab32(group); + if (ext2fs_has_feature_metadata_csum(fs->super)) { + /* new metadata csum code */ + __u16 old_crc; + __u32 crc32; + + old_crc = desc->bg_checksum; + desc->bg_checksum = 0; + crc32 = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&group, + sizeof(group)); + crc32 = ext2fs_crc32c_le(crc32, (unsigned char *)desc, + size); + desc->bg_checksum = old_crc; +#ifdef WORDS_BIGENDIAN + if (save_size > ext4_bg_size) + crc32 = ext2fs_crc32c_le(crc32, + (unsigned char *)save_desc + ext4_bg_size, + save_size - ext4_bg_size); #endif - crc = ext2fs_crc16(~0, fs->super->s_uuid, - sizeof(fs->super->s_uuid)); - crc = ext2fs_crc16(crc, &group, sizeof(group)); - crc = ext2fs_crc16(crc, desc, offset); - offset += sizeof(desc->bg_checksum); /* skip checksum */ - /* for checksum of struct ext4_group_desc do the rest...*/ - if (offset < size) { - crc = ext2fs_crc16(crc, (char *)desc + offset, - size - offset); - } + crc = crc32 & 0xFFFF; + goto out; } + /* old crc16 code */ + offset = offsetof(struct ext2_group_desc, bg_checksum); + crc = ext2fs_crc16(~0, fs->super->s_uuid, + sizeof(fs->super->s_uuid)); + crc = ext2fs_crc16(crc, &group, sizeof(group)); + crc = ext2fs_crc16(crc, desc, offset); + offset += sizeof(desc->bg_checksum); /* skip checksum */ + /* for checksum of struct ext4_group_desc do the rest...*/ + if (offset < size) { + crc = ext2fs_crc16(crc, (char *)desc + offset, + size - offset); + } +#ifdef WORDS_BIGENDIAN + /* + * If the size of the bg descriptor is greater than 64 + * bytes, which is the size of the traditional ext4 bg + * descriptor, checksum the rest of the descriptor here + */ + if (save_size > ext4_bg_size) + crc = ext2fs_crc16(crc, (char *)save_desc + ext4_bg_size, + save_size - ext4_bg_size); +#endif + +out: return crc; } int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group) { - if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && + if (ext2fs_has_group_desc_csum(fs) && (ext2fs_bg_checksum(fs, group) != ext2fs_group_desc_csum(fs, group))) return 0; @@ -726,8 +806,7 @@ int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group) void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group) { - if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) + if (!ext2fs_has_group_desc_csum(fs)) return; /* ext2fs_bg_checksum_set() sets the actual checksum field but @@ -761,8 +840,7 @@ errcode_t ext2fs_set_gdt_csum(ext2_filsys fs) if (!fs->inode_map) return EXT2_ET_NO_INODE_BITMAP; - if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, - EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) + if (!ext2fs_has_group_desc_csum(fs)) return 0; for (i = 0; i < fs->group_desc_count; i++) { @@ -770,6 +848,11 @@ errcode_t ext2fs_set_gdt_csum(ext2_filsys fs) __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); @@ -804,21 +887,22 @@ void print_csum(const char *msg, ext2_filsys fs, dgrp_t group) { __u16 crc1, crc2, crc3; dgrp_t swabgroup; - struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, group); - size_t size; + struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, + group); + size_t size = EXT2_DESC_SIZE(fs->super); struct ext2_super_block *sb = fs->super; int offset = offsetof(struct ext2_group_desc, bg_checksum); #ifdef WORDS_BIGENDIAN struct ext4_group_desc swabdesc; + struct ext2_group_desc *save_desc = desc; + const size_t ext4_bg_size = sizeof(struct ext4_group_desc); + size_t save_size = size; #endif - size = fs->super->s_desc_size; - if (size < EXT2_MIN_DESC_SIZE) - size = EXT2_MIN_DESC_SIZE; - if (size > sizeof(struct ext4_group_desc)) - size = sizeof(struct ext4_group_desc); #ifdef WORDS_BIGENDIAN /* Have to swab back to little-endian to do the checksum */ + if (size > ext4_bg_size) + size = ext4_bg_size; memcpy(&swabdesc, desc, size); ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc); desc = (struct ext2_group_desc *) &swabdesc; @@ -835,8 +919,13 @@ void print_csum(const char *msg, ext2_filsys fs, dgrp_t group) /* for checksum of struct ext4_group_desc do the rest...*/ if (offset < size) crc3 = ext2fs_crc16(crc3, (char *)desc + offset, size - offset); +#ifdef WORDS_BIGENDIAN + if (save_size > ext4_bg_size) + crc3 = ext2fs_crc16(crc3, (char *)save_desc + ext4_bg_size, + save_size - ext4_bg_size); +#endif - printf("%s: UUID %s(%04x), grp %u(%04x): %04x=%04x\n", + printf("%s UUID %s=%04x, grp %u=%04x: %04x=%04x\n", msg, e2p_uuid2str(sb->s_uuid), crc1, group, crc2, crc3, ext2fs_group_desc_csum(fs, group)); } @@ -854,6 +943,11 @@ int main(int argc, char **argv) memset(¶m, 0, sizeof(param)); ext2fs_blocks_count_set(¶m, 32768); +#if 0 + param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT; + param.s_desc_size = 128; + csum_known = 0x5b6e; +#endif retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, test_io_manager, &fs); @@ -921,6 +1015,7 @@ int main(int argc, char **argv) printf("checksums for different data shouldn't match\n"); exit(1); } + ext2fs_free(fs); return 0; }