1ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos/* 2ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * csum.c --- checksumming of ext3 structures 3ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * 4ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * Copyright (C) 2006 Cluster File Systems, Inc. 5470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o * Copyright (C) 2006, 2007 by Andreas Dilger <adilger@clusterfs.com> 6ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * 7ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * %Begin-Header% 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 9543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 10ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * %End-Header% 11ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos */ 12ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 13d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h" 140eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#if HAVE_SYS_TYPES_H 150eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#include <sys/types.h> 160eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o#endif 170eeec8ac61bf1eaa31533b2be825cd75580829c9Theodore Ts'o 18ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include "ext2_fs.h" 19ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include "ext2fs.h" 20ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include "crc16.h" 21ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#include <assert.h> 22ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 23ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#ifndef offsetof 24ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 25ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#endif 26ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 27ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#ifdef DEBUG 28ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#define STATIC 29ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#else 30ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#define STATIC static 31ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#endif 32ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 332ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wongvoid ext2fs_init_csum_seed(ext2_filsys fs) 342ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wong{ 352ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wong if (ext2fs_has_feature_csum_seed(fs->super)) 362ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wong fs->csum_seed = fs->super->s_checksum_seed; 372ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wong else if (ext2fs_has_feature_metadata_csum(fs->super)) 382ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wong fs->csum_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid, 392ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wong sizeof(fs->super->s_uuid)); 402ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wong} 412ed0adbce68c0bbe7e1fc2cf23f009327f10441bDarrick J. Wong 42a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wongstatic __u32 ext2fs_mmp_csum(ext2_filsys fs, struct mmp_struct *mmp) 43a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong{ 44a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong int offset = offsetof(struct mmp_struct, mmp_checksum); 45a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 46a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)mmp, offset); 47a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong} 48a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 49a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wongint ext2fs_mmp_csum_verify(ext2_filsys fs, struct mmp_struct *mmp) 50a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong{ 51a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong __u32 calculated; 52a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 5377b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 54a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return 1; 55a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 56a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong calculated = ext2fs_mmp_csum(fs, mmp); 57a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 58a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return ext2fs_le32_to_cpu(mmp->mmp_checksum) == calculated; 59a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong} 60a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 61a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wongerrcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp) 62a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong{ 63a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong __u32 crc; 64a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 6577b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 66a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return 0; 67a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 68a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong crc = ext2fs_mmp_csum(fs, mmp); 69a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong mmp->mmp_checksum = ext2fs_cpu_to_le32(crc); 70a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 71a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return 0; 72a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong} 73a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 741eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wongint ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb) 751eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong{ 7677b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 771eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong return 1; 781eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong 791eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong return sb->s_checksum_type == EXT2_CRC32C_CHKSUM; 801eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong} 811eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong 82894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'ostatic __u32 ext2fs_superblock_csum(ext2_filsys fs EXT2FS_ATTR((unused)), 83894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o struct ext2_super_block *sb) 84d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong{ 85d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong int offset = offsetof(struct ext2_super_block, s_checksum); 86d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 87d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return ext2fs_crc32c_le(~0, (unsigned char *)sb, offset); 88d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong} 89d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 902432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong/* NOTE: The input to this function MUST be in LE order */ 91d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wongint ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb) 92d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong{ 932432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong __u32 flag, calculated; 94d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 952432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong if (fs->flags & EXT2_FLAG_SWAP_BYTES) 962432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM; 972432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong else 982432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); 992432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong 1002432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag)) 101d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return 1; 102d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 103d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong calculated = ext2fs_superblock_csum(fs, sb); 104d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 105d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return ext2fs_le32_to_cpu(sb->s_checksum) == calculated; 106d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong} 107d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 1082432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong/* NOTE: The input to this function MUST be in LE order */ 109d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wongerrcode_t ext2fs_superblock_csum_set(ext2_filsys fs, 110d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong struct ext2_super_block *sb) 111d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong{ 1122432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong __u32 flag, crc; 113d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 1142432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong if (fs->flags & EXT2_FLAG_SWAP_BYTES) 1152432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM; 1162432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong else 1172432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); 1182432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong 1192432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag)) 120d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return 0; 121d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 122d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong crc = ext2fs_superblock_csum(fs, sb); 123d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong sb->s_checksum = ext2fs_cpu_to_le32(crc); 124d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 125d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return 0; 126d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong} 127d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 128894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'ostatic errcode_t ext2fs_ext_attr_block_csum(ext2_filsys fs, 129894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o ext2_ino_t inum EXT2FS_ATTR((unused)), 13039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong blk64_t block, 13139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong struct ext2_ext_attr_header *hdr, 13239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong __u32 *crc) 13339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{ 13439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong char *buf = (char *)hdr; 1351b8c4c1b45482363e29bd4cca483d84645f8ac9dAndreas Dilger __u32 old_crc = hdr->h_checksum; 13639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 13739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong hdr->h_checksum = 0; 13839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong block = ext2fs_cpu_to_le64(block); 13939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&block, 14039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong sizeof(block)); 14139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, fs->blocksize); 14239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong hdr->h_checksum = old_crc; 14339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 14439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 0; 14539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong} 14639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 14739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wongint ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, 14839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong blk64_t block, 14939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong struct ext2_ext_attr_header *hdr) 15039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{ 15139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong __u32 calculated; 15239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong errcode_t retval; 15339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 15477b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 15539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 1; 15639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 15739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &calculated); 15839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong if (retval) 15939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 0; 16039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 16139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return ext2fs_le32_to_cpu(hdr->h_checksum) == calculated; 16239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong} 16339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 16439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wongerrcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, ext2_ino_t inum, 16539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong blk64_t block, 16639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong struct ext2_ext_attr_header *hdr) 16739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{ 16839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong errcode_t retval; 16939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong __u32 crc; 17039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 17177b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 17239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 0; 17339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 17439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &crc); 17539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong if (retval) 17639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return retval; 17739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong hdr->h_checksum = ext2fs_cpu_to_le32(crc); 17839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 0; 17939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong} 18039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 181dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic __u16 do_nothing16(__u16 x) 182dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 183dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return x; 184dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 185dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 186dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic __u16 disk_to_host16(__u16 x) 187dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 188dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return ext2fs_le16_to_cpu(x); 189dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 190dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 191dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t __get_dx_countlimit(ext2_filsys fs, 192dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent, 193dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit **cc, 194dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int *offset, 195dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int need_swab) 196dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 197dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dp; 198dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_root_info *root; 199dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit *c; 200dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int count_offset, max_sane_entries; 201dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong unsigned int rec_len; 202dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16); 203dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 204dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong rec_len = translate(dirent->rec_len); 205dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 206dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (rec_len == fs->blocksize && translate(dirent->name_len) == 0) 207dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count_offset = 8; 208dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong else if (rec_len == 12) { 209894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o dp = (struct ext2_dir_entry *)(((char *)dirent) + rec_len); 210dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong rec_len = translate(dp->rec_len); 211dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (rec_len != fs->blocksize - 12) 212dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DB_NOT_FOUND; 213894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o root = (struct ext2_dx_root_info *)(((char *)dp + 12)); 214dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (root->reserved_zero || 215dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong root->info_length != sizeof(struct ext2_dx_root_info)) 216dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DB_NOT_FOUND; 217dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count_offset = 32; 218dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong } else 219dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DB_NOT_FOUND; 220dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 221894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o c = (struct ext2_dx_countlimit *)(((char *)dirent) + count_offset); 222dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong max_sane_entries = (fs->blocksize - count_offset) / 223dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong sizeof(struct ext2_dx_entry); 224dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (ext2fs_le16_to_cpu(c->limit) > max_sane_entries || 225dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong ext2fs_le16_to_cpu(c->count) > max_sane_entries) 226dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 227dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 228dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (offset) 229dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *offset = count_offset; 230dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (cc) 231dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *cc = c; 232dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 233dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 0; 234dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 235dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 236dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongerrcode_t ext2fs_get_dx_countlimit(ext2_filsys fs, 237dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent, 238dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit **cc, 239dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int *offset) 240dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 241dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return __get_dx_countlimit(fs, dirent, cc, offset, 0); 242dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 243dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 24481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongvoid ext2fs_initialize_dirent_tail(ext2_filsys fs, 24581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail *t) 24681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 24781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong memset(t, 0, sizeof(struct ext2_dir_entry_tail)); 24881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong ext2fs_set_rec_len(fs, sizeof(struct ext2_dir_entry_tail), 24981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong (struct ext2_dir_entry *)t); 25081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong t->det_reserved_name_len = EXT2_DIR_NAME_LEN_CSUM; 25181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 25281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 25381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t __get_dirent_tail(ext2_filsys fs, 25481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent, 25581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail **tt, 25681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong int need_swab) 25781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 25881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *d; 25981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong void *top; 26081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail *t; 26181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong unsigned int rec_len; 26281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong errcode_t retval = 0; 26381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16); 26481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 26581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong d = dirent; 26681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong top = EXT2_DIRENT_TAIL(dirent, fs->blocksize); 26781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 26881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong rec_len = translate(d->rec_len); 26981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong while (rec_len && !(rec_len & 0x3)) { 270894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o d = (struct ext2_dir_entry *)(((char *)d) + rec_len); 27181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if ((void *)d >= top) 27281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong break; 27381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong rec_len = translate(d->rec_len); 27481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong } 27581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 27681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (d != top) 27781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 27881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 27981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong t = (struct ext2_dir_entry_tail *)d; 28081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (t->det_reserved_zero1 || 28181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong translate(t->det_rec_len) != sizeof(struct ext2_dir_entry_tail) || 28281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong translate(t->det_reserved_name_len) != EXT2_DIR_NAME_LEN_CSUM) 28381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 28481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 28581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (tt) 28681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong *tt = t; 28781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return retval; 28881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 28981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 29081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent) 29181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 29281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return __get_dirent_tail(fs, dirent, NULL, 0) == 0; 29381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 29481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 29581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum, 29681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent, __u32 *crc, 29781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong int size) 29881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 29981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong errcode_t retval; 30081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong char *buf = (char *)dirent; 30181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong __u32 gen; 30281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_inode inode; 30381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 30481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = ext2fs_read_inode(fs, inum, &inode); 30581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 30681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return retval; 30781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 30881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong inum = ext2fs_cpu_to_le32(inum); 30981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong gen = ext2fs_cpu_to_le32(inode.i_generation); 31081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, 31181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong sizeof(inum)); 31281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); 31381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); 31481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 31581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 31681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 31781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 31881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dirent_csum_verify(ext2_filsys fs, ext2_ino_t inum, 31981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent) 32081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 32181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong errcode_t retval; 32281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong __u32 calculated; 32381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail *t; 32481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 32581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = __get_dirent_tail(fs, dirent, &t, 1); 32681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 32781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 1; 32881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 32981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong /* 33081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong * The checksum field is overlaid with the dirent->name field 33181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong * so the swapfs.c functions won't change the endianness. 33281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong */ 33381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = ext2fs_dirent_csum(fs, inum, dirent, &calculated, 334894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o (char *)t - (char *)dirent); 33581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 33681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 33781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_le32_to_cpu(t->det_checksum) == calculated; 33881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 33981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 34081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum, 34181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent) 34281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 34381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong errcode_t retval; 34481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong __u32 crc; 34581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail *t; 34681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 34781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = __get_dirent_tail(fs, dirent, &t, 1); 34881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 34981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return retval; 35081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 35181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong /* swapfs.c functions don't change the checksum endianness */ 35281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = ext2fs_dirent_csum(fs, inum, dirent, &crc, 353894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o (char *)t - (char *)dirent); 35481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 35581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return retval; 35681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong t->det_checksum = ext2fs_cpu_to_le32(crc); 35781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 35881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 35981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 360dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, 361dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent, 362dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u32 *crc, int count_offset, int count, 363dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_tail *t) 364dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 365dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong errcode_t retval; 366dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong char *buf = (char *)dirent; 367dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int size; 368dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u32 old_csum, gen; 369dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_inode inode; 370dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 371dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong size = count_offset + (count * sizeof(struct ext2_dx_entry)); 372dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong old_csum = t->dt_checksum; 373dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t->dt_checksum = 0; 374dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 375dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = ext2fs_read_inode(fs, inum, &inode); 376dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 377dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return retval; 378dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 379dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong inum = ext2fs_cpu_to_le32(inum); 380dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong gen = ext2fs_cpu_to_le32(inode.i_generation); 381dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, 382dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong sizeof(inum)); 383dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); 384dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); 385dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)t, 386dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong sizeof(struct ext2_dx_tail)); 387dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t->dt_checksum = old_csum; 388dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 389dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 0; 390dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 391dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 392dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum, 393dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent) 394dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 395dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u32 calculated; 396dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong errcode_t retval; 397dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit *c; 398dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_tail *t; 399dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int count_offset, limit, count; 400dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 401dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); 402dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 403dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 1; 404dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong limit = ext2fs_le16_to_cpu(c->limit); 405dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count = ext2fs_le16_to_cpu(c->count); 406dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > 407dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong fs->blocksize - sizeof(struct ext2_dx_tail)) 408dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 0; 409dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong /* htree structs are accessed in LE order */ 410dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); 411dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, count_offset, 412dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count, t); 413dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 414dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 0; 415dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 416dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return ext2fs_le32_to_cpu(t->dt_checksum) == calculated; 417dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 418dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 419dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum, 420dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent) 421dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 422dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u32 crc; 423dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong errcode_t retval = 0; 424dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit *c; 425dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_tail *t; 426dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int count_offset, limit, count; 427dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 428dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); 429dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 430dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return retval; 431dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong limit = ext2fs_le16_to_cpu(c->limit); 432dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count = ext2fs_le16_to_cpu(c->count); 433dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > 434dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong fs->blocksize - sizeof(struct ext2_dx_tail)) 435dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 436dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); 437dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 438dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong /* htree structs are accessed in LE order */ 439dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = ext2fs_dx_csum(fs, inum, dirent, &crc, count_offset, count, t); 440dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 441dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return retval; 442dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t->dt_checksum = ext2fs_cpu_to_le32(crc); 443dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return retval; 444dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 445dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 44681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, 44781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent) 44881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 44977b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 45081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 1; 45181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 45281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (__get_dirent_tail(fs, dirent, NULL, 1) == 0) 45381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_dirent_csum_verify(fs, inum, dirent); 45481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0) 45581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_dx_csum_verify(fs, inum, dirent); 45681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 45781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 45881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 45981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 46081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongerrcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum, 46181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent) 46281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 46377b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 46481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 46581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 46681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (__get_dirent_tail(fs, dirent, NULL, 1) == 0) 46781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_dirent_csum_set(fs, inum, dirent); 46881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0) 46981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_dx_csum_set(fs, inum, dirent); 47081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 47181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) 47281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 47381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 47481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 47581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 47641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong#define EXT3_EXTENT_TAIL_OFFSET(hdr) (sizeof(struct ext3_extent_header) + \ 47741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong (sizeof(struct ext3_extent) * ext2fs_le16_to_cpu((hdr)->eh_max))) 47841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 47941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongstatic struct ext3_extent_tail *get_extent_tail(struct ext3_extent_header *h) 48041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{ 481894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o return (struct ext3_extent_tail *)(((char *)h) + 48241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong EXT3_EXTENT_TAIL_OFFSET(h)); 48341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong} 48441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 48541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongstatic errcode_t ext2fs_extent_block_csum(ext2_filsys fs, ext2_ino_t inum, 48641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_header *eh, 48741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong __u32 *crc) 48841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{ 48941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong int size; 49041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong __u32 gen; 49141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong errcode_t retval; 49241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext2_inode inode; 49341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 49441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong size = EXT3_EXTENT_TAIL_OFFSET(eh) + offsetof(struct ext3_extent_tail, 49541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong et_checksum); 49641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 49741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong retval = ext2fs_read_inode(fs, inum, &inode); 49841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong if (retval) 49941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return retval; 50041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong inum = ext2fs_cpu_to_le32(inum); 50141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong gen = ext2fs_cpu_to_le32(inode.i_generation); 50241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, 50341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong sizeof(inum)); 50441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); 50541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)eh, size); 50641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 50741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return 0; 50841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong} 50941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 51041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongint ext2fs_extent_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, 51141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_header *eh) 51241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{ 51341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong errcode_t retval; 51441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong __u32 provided, calculated; 51541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_tail *t = get_extent_tail(eh); 51641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 51741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong /* 51841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong * The extent tree structures are accessed in LE order, so we must 51941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong * swap the checksum bytes here. 52041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong */ 52177b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 52241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return 1; 52341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 52441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong provided = ext2fs_le32_to_cpu(t->et_checksum); 52541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong retval = ext2fs_extent_block_csum(fs, inum, eh, &calculated); 52641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong if (retval) 52741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return 0; 52841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 52941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return provided == calculated; 53041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong} 53141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 53241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongerrcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, ext2_ino_t inum, 53341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_header *eh) 53441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{ 53541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong errcode_t retval; 53641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong __u32 crc; 53741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_tail *t = get_extent_tail(eh); 53841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 53977b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 54041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return 0; 54141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 54241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong /* 54341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong * The extent tree structures are accessed in LE order, so we must 54441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong * swap the checksum bytes here. 54541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong */ 54641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong retval = ext2fs_extent_block_csum(fs, inum, eh, &crc); 54741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong if (retval) 54841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return retval; 54941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong t->et_checksum = ext2fs_cpu_to_le32(crc); 55041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return retval; 55141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong} 55241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 553a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wongint ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, 554a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong char *bitmap, int size) 555a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong{ 556a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong struct ext4_group_desc *gdp = (struct ext4_group_desc *) 557a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong ext2fs_group_desc(fs, fs->group_desc, group); 558a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong __u32 provided, calculated; 559a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 56077b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 561a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong return 1; 562a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong provided = gdp->bg_inode_bitmap_csum_lo; 563a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, 564a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong size); 565a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) 566a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong provided |= (__u32)gdp->bg_inode_bitmap_csum_hi << 16; 567a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong else 568a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong calculated &= 0xFFFF; 569a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 570a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong return provided == calculated; 571a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong} 572a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 573a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wongerrcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group, 574a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong char *bitmap, int size) 575a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong{ 576a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong __u32 crc; 577a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong struct ext4_group_desc *gdp = (struct ext4_group_desc *) 578a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong ext2fs_group_desc(fs, fs->group_desc, group); 579a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 58077b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 581a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong return 0; 582a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 583a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size); 584a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong gdp->bg_inode_bitmap_csum_lo = crc & 0xFFFF; 585a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) 586a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong gdp->bg_inode_bitmap_csum_hi = crc >> 16; 587a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 588a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong return 0; 589a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong} 590a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 591e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wongint ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, 592e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong char *bitmap, int size) 593e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong{ 594e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong struct ext4_group_desc *gdp = (struct ext4_group_desc *) 595e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong ext2fs_group_desc(fs, fs->group_desc, group); 596e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong __u32 provided, calculated; 597e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 59877b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 599e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong return 1; 600e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong provided = gdp->bg_block_bitmap_csum_lo; 601e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, 602e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong size); 603e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION) 604e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong provided |= (__u32)gdp->bg_block_bitmap_csum_hi << 16; 605e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong else 606e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong calculated &= 0xFFFF; 607e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 608e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong return provided == calculated; 609e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong} 610e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 611e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wongerrcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group, 612e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong char *bitmap, int size) 613e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong{ 614e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong __u32 crc; 615e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong struct ext4_group_desc *gdp = (struct ext4_group_desc *) 616e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong ext2fs_group_desc(fs, fs->group_desc, group); 617e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 61877b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 619e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong return 0; 620e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 621e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size); 622e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong gdp->bg_block_bitmap_csum_lo = crc & 0xFFFF; 623e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION) 624e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong gdp->bg_block_bitmap_csum_hi = crc >> 16; 625e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 626e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong return 0; 627e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong} 628e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 62937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongstatic errcode_t ext2fs_inode_csum(ext2_filsys fs, ext2_ino_t inum, 63037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong struct ext2_inode_large *inode, 63137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 *crc, int has_hi) 63237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{ 63337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 gen; 63437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong struct ext2_inode_large *desc = inode; 63537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong size_t size = fs->super->s_inode_size; 63637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u16 old_lo; 63737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u16 old_hi = 0; 63837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 63937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong old_lo = inode->i_checksum_lo; 64037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_lo = 0; 64137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (has_hi) { 64237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong old_hi = inode->i_checksum_hi; 64337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_hi = 0; 64437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong } 64537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 64637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inum = ext2fs_cpu_to_le32(inum); 64737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong gen = inode->i_generation; 64837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, 64937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong sizeof(inum)); 65037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); 65137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)desc, size); 65237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 65337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_lo = old_lo; 65437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (has_hi) 65537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_hi = old_hi; 65637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 0; 65737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong} 65837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 65937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongint ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum, 66037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong struct ext2_inode_large *inode) 66137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{ 66237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong errcode_t retval; 66337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 provided, calculated; 664894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o unsigned int i, has_hi; 66597fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o char *cp; 66637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 667c0495d96fd1f7015e7beb3d9363cbe949d133173Theodore Ts'o if (!ext2fs_has_feature_metadata_csum(fs->super)) 66837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 1; 66937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 67037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE && 67137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END); 67237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 67337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong provided = ext2fs_le16_to_cpu(inode->i_checksum_lo); 67437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong retval = ext2fs_inode_csum(fs, inum, inode, &calculated, has_hi); 67537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (retval) 67637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 0; 67737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (has_hi) { 67837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 hi = ext2fs_le16_to_cpu(inode->i_checksum_hi); 67937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong provided |= hi << 16; 68037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong } else 68137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong calculated &= 0xFFFF; 68237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 68397fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o if (provided == calculated) 68497fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o return 1; 68597fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o 68697fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o /* 68797fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * If the checksum didn't match, it's possible it was due to 68897fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * the inode being all zero's. It's unlikely this is the 68997fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * case, but it can happen. So check for it here. (We only 69097fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * check the base inode since that's good enough, and it's not 69197fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * worth the bother to figure out how much of the extended 69297fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * inode, if any, is present.) 69397fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o */ 69497fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o for (cp = (char *) inode, i = 0; 69597fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o i < sizeof(struct ext2_inode); 69697fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o cp++, i++) 69797fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o if (*cp) 69897fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o return 0; 69997fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o return 1; /* Inode must have been all zero's */ 70037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong} 70137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 70237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongerrcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum, 70337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong struct ext2_inode_large *inode) 70437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{ 70537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong errcode_t retval; 70637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 crc; 70737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong int has_hi; 70837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 709c0495d96fd1f7015e7beb3d9363cbe949d133173Theodore Ts'o if (!ext2fs_has_feature_metadata_csum(fs->super)) 71037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 0; 71137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 71237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE && 71337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END); 71437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 71537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong retval = ext2fs_inode_csum(fs, inum, inode, &crc, has_hi); 71637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (retval) 71737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return retval; 71837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_lo = ext2fs_cpu_to_le16(crc & 0xFFFF); 71937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (has_hi) 72037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_hi = ext2fs_cpu_to_le16(crc >> 16); 72137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 0; 72237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong} 72337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 72487141781aabb4dc01359428d2feecdc7f43eeac0Theodore Ts'o__u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group) 725ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 7262bc30417541deffca795db8ec4e7f7ccb616dc3fAndreas Dilger struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, 7272bc30417541deffca795db8ec4e7f7ccb616dc3fAndreas Dilger group); 72871715a5a9ad409df162dbb58a4c3b6fd2c5868d5Theodore Ts'o size_t offset, size = EXT2_DESC_SIZE(fs->super); 729ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos __u16 crc = 0; 730ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#ifdef WORDS_BIGENDIAN 7315b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong struct ext4_group_desc swabdesc; 7322ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o size_t save_size = size; 7332ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o const size_t ext4_bg_size = sizeof(struct ext4_group_desc); 7342ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o struct ext2_group_desc *save_desc = desc; 735ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 7365b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong /* Have to swab back to little-endian to do the checksum */ 7372ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o if (size > ext4_bg_size) 7382ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o size = ext4_bg_size; 7395b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong memcpy(&swabdesc, desc, size); 7402ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc); 7415b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong desc = (struct ext2_group_desc *) &swabdesc; 7425b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong group = ext2fs_swab32(group); 743ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#endif 7445b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong 74577b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (ext2fs_has_feature_metadata_csum(fs->super)) { 7465b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong /* new metadata csum code */ 7475b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong __u16 old_crc; 7485b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong __u32 crc32; 7495b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong 7505b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong old_crc = desc->bg_checksum; 7515b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong desc->bg_checksum = 0; 7525b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc32 = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&group, 7535b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong sizeof(group)); 7545b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc32 = ext2fs_crc32c_le(crc32, (unsigned char *)desc, 7555b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong size); 7565b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong desc->bg_checksum = old_crc; 757b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#ifdef WORDS_BIGENDIAN 758b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o if (save_size > ext4_bg_size) 7592ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o crc32 = ext2fs_crc32c_le(crc32, 7602432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong (unsigned char *)save_desc + ext4_bg_size, 7612432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong save_size - ext4_bg_size); 762b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#endif 7635b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = crc32 & 0xFFFF; 7645b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong goto out; 765ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos } 766ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 7675b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong /* old crc16 code */ 7682ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o offset = offsetof(struct ext2_group_desc, bg_checksum); 7695b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = ext2fs_crc16(~0, fs->super->s_uuid, 7705b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong sizeof(fs->super->s_uuid)); 7715b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = ext2fs_crc16(crc, &group, sizeof(group)); 7725b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = ext2fs_crc16(crc, desc, offset); 7735b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong offset += sizeof(desc->bg_checksum); /* skip checksum */ 7745b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong /* for checksum of struct ext4_group_desc do the rest...*/ 7755b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong if (offset < size) { 7765b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = ext2fs_crc16(crc, (char *)desc + offset, 7775b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong size - offset); 7785b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong } 7792ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o#ifdef WORDS_BIGENDIAN 7802ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o /* 7812ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o * If the size of the bg descriptor is greater than 64 7822ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o * bytes, which is the size of the traditional ext4 bg 7832ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o * descriptor, checksum the rest of the descriptor here 7842ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o */ 7852ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o if (save_size > ext4_bg_size) 7862ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o crc = ext2fs_crc16(crc, (char *)save_desc + ext4_bg_size, 7872ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o save_size - ext4_bg_size); 7882ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o#endif 7895b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong 7905b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wongout: 791ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return crc; 792ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 793ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 794ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosint ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group) 795ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 7965b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong if (ext2fs_has_group_desc_csum(fs) && 797d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson (ext2fs_bg_checksum(fs, group) != 7984729455f0a68f2fa0a83ec8460d1d4bccba9dcfaTheodore Ts'o ext2fs_group_desc_csum(fs, group))) 799ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return 0; 800ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 801ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return 1; 802ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 803ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 804ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosvoid ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group) 805ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 8065b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong if (!ext2fs_has_group_desc_csum(fs)) 807d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson return; 808d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson 809d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson /* ext2fs_bg_checksum_set() sets the actual checksum field but 810d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson * does not calculate the checksum itself. */ 811d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_checksum_set(fs, group, ext2fs_group_desc_csum(fs, group)); 812ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 813ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 814ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosstatic __u32 find_last_inode_ingrp(ext2fs_inode_bitmap bitmap, 815ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos __u32 inodes_per_grp, dgrp_t grp_no) 816ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 817ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos ext2_ino_t i, start_ino, end_ino; 818ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 819ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos start_ino = grp_no * inodes_per_grp + 1; 820ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos end_ino = start_ino + inodes_per_grp - 1; 821ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 822ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos for (i = end_ino; i >= start_ino; i--) { 8238f82ef9860339039b54a324be137fbc09b762358Valerie Aurora Henson if (ext2fs_fast_test_inode_bitmap2(bitmap, i)) 824ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return i - start_ino + 1; 825ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos } 826ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return inodes_per_grp; 827ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 828ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 829ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos/* update the bitmap flags, set the itable high watermark, and calculate 830ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * checksums for the group descriptors */ 831f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilgererrcode_t ext2fs_set_gdt_csum(ext2_filsys fs) 832ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 833ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos struct ext2_super_block *sb = fs->super; 8348895f43a60269464f654e9d87c28768875cd703aTheodore Ts'o int dirty = 0; 835ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos dgrp_t i; 836ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 837f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger if (!fs->inode_map) 838f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger return EXT2_ET_NO_INODE_BITMAP; 839f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger 8405b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong if (!ext2fs_has_group_desc_csum(fs)) 841f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger return 0; 842ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 843d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson for (i = 0; i < fs->group_desc_count; i++) { 844d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o __u32 old_csum = ext2fs_bg_checksum(fs, i); 845d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o __u32 old_unused = ext2fs_bg_itable_unused(fs, i); 846d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o __u32 old_flags = ext2fs_bg_flags(fs, i); 847d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o __u32 old_free_inodes_count = ext2fs_bg_free_inodes_count(fs, i); 848c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong __u32 old_free_blocks_count = ext2fs_bg_free_blocks_count(fs, i); 849c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong 850c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong if (old_free_blocks_count == sb->s_blocks_per_group && 851c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong i != fs->group_desc_count - 1) 852c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT); 853ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 854d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson if (old_free_inodes_count == sb->s_inodes_per_group) { 855d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT); 856d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_itable_unused_set(fs, i, sb->s_inodes_per_group); 85716b851cdae98244e117fe91d93b267fcad1102b3Theodore Ts'o } else { 858d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson int unused = 859d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson sb->s_inodes_per_group - 860ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos find_last_inode_ingrp(fs->inode_map, 861d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson sb->s_inodes_per_group, i); 862d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson 863d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT); 864d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_itable_unused_set(fs, i, unused); 865ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos } 866ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 867ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos ext2fs_group_desc_csum_set(fs, i); 868d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson if (old_flags != ext2fs_bg_flags(fs, i)) 86980fc4e698a308de22ace6179f45e0bb67befa74bAndreas Dilger dirty = 1; 870d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson if (old_unused != ext2fs_bg_itable_unused(fs, i)) 87180fc4e698a308de22ace6179f45e0bb67befa74bAndreas Dilger dirty = 1; 872d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson if (old_csum != ext2fs_bg_checksum(fs, i)) 873ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos dirty = 1; 874ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos } 875ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos if (dirty) 876ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos ext2fs_mark_super_dirty(fs); 877f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger return 0; 878ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 879470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 880470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#ifdef DEBUG 881c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen#include "e2p/e2p.h" 882c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen 883470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'ovoid print_csum(const char *msg, ext2_filsys fs, dgrp_t group) 884470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o{ 885470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o __u16 crc1, crc2, crc3; 886470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o dgrp_t swabgroup; 887b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, 888b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o group); 889b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o size_t size = EXT2_DESC_SIZE(fs->super); 890470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o struct ext2_super_block *sb = fs->super; 8911d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o int offset = offsetof(struct ext2_group_desc, bg_checksum); 892470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#ifdef WORDS_BIGENDIAN 8931d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o struct ext4_group_desc swabdesc; 894b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o struct ext2_group_desc *save_desc = desc; 895b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o const size_t ext4_bg_size = sizeof(struct ext4_group_desc); 896b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o size_t save_size = size; 8971d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o#endif 898470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 8991d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o#ifdef WORDS_BIGENDIAN 900470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o /* Have to swab back to little-endian to do the checksum */ 901b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o if (size > ext4_bg_size) 902b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o size = ext4_bg_size; 9031d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o memcpy(&swabdesc, desc, size); 9041d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc); 9051d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o desc = (struct ext2_group_desc *) &swabdesc; 906470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 907470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o swabgroup = ext2fs_swab32(group); 908470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#else 909470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o swabgroup = group; 910470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#endif 911470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 912470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o crc1 = ext2fs_crc16(~0, sb->s_uuid, sizeof(fs->super->s_uuid)); 913470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o crc2 = ext2fs_crc16(crc1, &swabgroup, sizeof(swabgroup)); 9141d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o crc3 = ext2fs_crc16(crc2, desc, offset); 9151d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o offset += sizeof(desc->bg_checksum); /* skip checksum */ 9161d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o /* for checksum of struct ext4_group_desc do the rest...*/ 9171d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o if (offset < size) 9181d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o crc3 = ext2fs_crc16(crc3, (char *)desc + offset, size - offset); 919b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#ifdef WORDS_BIGENDIAN 920b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o if (save_size > ext4_bg_size) 921b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o crc3 = ext2fs_crc16(crc3, (char *)save_desc + ext4_bg_size, 922b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o save_size - ext4_bg_size); 923b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#endif 9241d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o 925f797cf3e37b476aac593fe9a9f4630448d335332Andreas Dilger printf("%s UUID %s=%04x, grp %u=%04x: %04x=%04x\n", 926562f264243f4d4385910b6f06872730214977736Theodore Ts'o msg, e2p_uuid2str(sb->s_uuid), crc1, group, crc2, crc3, 927c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen ext2fs_group_desc_csum(fs, group)); 928470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o} 929470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 930470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'ounsigned char sb_uuid[16] = { 0x4f, 0x25, 0xe8, 0xcf, 0xe7, 0x97, 0x48, 0x23, 931470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 0xbe, 0xfa, 0xa7, 0x88, 0x4b, 0xae, 0xec, 0xdb }; 932470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 933470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'oint main(int argc, char **argv) 934470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o{ 935470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o struct ext2_super_block param; 936470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o errcode_t retval; 937470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o ext2_filsys fs; 938470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o int i; 939470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o __u16 csum1, csum2, csum_known = 0xd3a4; 940470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 941470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o memset(¶m, 0, sizeof(param)); 9424efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson ext2fs_blocks_count_set(¶m, 32768); 943b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#if 0 944b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT; 945b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o param.s_desc_size = 128; 946b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o csum_known = 0x5b6e; 947b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#endif 948470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 9498f82ef9860339039b54a324be137fbc09b762358Valerie Aurora Henson retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, 950470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o test_io_manager, &fs); 951470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (retval) { 952470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o com_err("setup", retval, 953470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o "While initializing filesystem"); 954470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 955470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 956470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o memcpy(fs->super->s_uuid, sb_uuid, 16); 957470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o fs->super->s_feature_ro_compat = EXT4_FEATURE_RO_COMPAT_GDT_CSUM; 958470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 959470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o for (i=0; i < fs->group_desc_count; i++) { 960d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_block_bitmap_loc_set(fs, i, 124); 961d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_inode_bitmap_loc_set(fs, i, 125); 962d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_inode_table_loc_set(fs, i, 126); 963d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_free_blocks_count_set(fs, i, 31119); 964d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_free_inodes_count_set(fs, i, 15701); 965d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_used_dirs_count_set(fs, i, 2); 966e633b58ac75f2f544b7d6572e37d4b63da31e59cEric Sandeen ext2fs_bg_flags_zap(fs, i); 967470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o }; 968470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 969470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum1 = ext2fs_group_desc_csum(fs, 0); 970470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum0000", fs, 0); 971470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 972470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 != csum_known) { 973470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksum for group 0 should be %04x\n", csum_known); 974470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 975470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 976470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum2 = ext2fs_group_desc_csum(fs, 1); 977470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum0001", fs, 1); 978470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 == csum2) { 979470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums for different groups shouldn't match\n"); 980470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 981470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 982470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum2 = ext2fs_group_desc_csum(fs, 2); 983470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csumffff", fs, 2); 984470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 == csum2) { 985470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums for different groups shouldn't match\n"); 986470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 987470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 988d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_checksum_set(fs, 0, csum1); 989470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum2 = ext2fs_group_desc_csum(fs, 0); 990470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum_set", fs, 0); 991470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 != csum2) { 992470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums should not depend on checksum field\n"); 993470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 994470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 995470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (!ext2fs_group_desc_csum_verify(fs, 0)) { 996470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums should verify against gd_checksum\n"); 997470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 998470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 999470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o memset(fs->super->s_uuid, 0x30, sizeof(fs->super->s_uuid)); 1000470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("new_uuid", fs, 0); 1001470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (ext2fs_group_desc_csum_verify(fs, 0) != 0) { 1002470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums for different filesystems shouldn't match\n"); 1003470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 1004470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 1005d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson csum1 = ext2fs_group_desc_csum(fs, 0); 1006d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_checksum_set(fs, 0, csum1); 1007470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum_new", fs, 0); 1008d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_free_blocks_count_set(fs, 0, 1); 1009470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum2 = ext2fs_group_desc_csum(fs, 0); 1010470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum_blk", fs, 0); 1011470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 == csum2) { 1012470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums for different data shouldn't match\n"); 1013470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 1014470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 1015470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 1016470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o return 0; 1017470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o} 1018470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#endif 1019