csum.c revision 77b3e9871877fce9908b0696250787fd6ea61af9
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 33a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wongstatic __u32 ext2fs_mmp_csum(ext2_filsys fs, struct mmp_struct *mmp) 34a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong{ 35a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong int offset = offsetof(struct mmp_struct, mmp_checksum); 36a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 37a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)mmp, offset); 38a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong} 39a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 40a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wongint ext2fs_mmp_csum_verify(ext2_filsys fs, struct mmp_struct *mmp) 41a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong{ 42a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong __u32 calculated; 43a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 4477b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 45a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return 1; 46a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 47a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong calculated = ext2fs_mmp_csum(fs, mmp); 48a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 49a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return ext2fs_le32_to_cpu(mmp->mmp_checksum) == calculated; 50a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong} 51a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 52a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wongerrcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp) 53a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong{ 54a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong __u32 crc; 55a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 5677b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 57a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return 0; 58a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 59a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong crc = ext2fs_mmp_csum(fs, mmp); 60a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong mmp->mmp_checksum = ext2fs_cpu_to_le32(crc); 61a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 62a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong return 0; 63a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong} 64a9620d8b308271ace63dd0787555fa715d09e0f8Darrick J. Wong 651eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wongint ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb) 661eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong{ 6777b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 681eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong return 1; 691eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong 701eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong return sb->s_checksum_type == EXT2_CRC32C_CHKSUM; 711eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong} 721eedf3e52c2ae8f7ad2ad9c010ce5293e0b19ae3Darrick J. Wong 73894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'ostatic __u32 ext2fs_superblock_csum(ext2_filsys fs EXT2FS_ATTR((unused)), 74894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o struct ext2_super_block *sb) 75d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong{ 76d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong int offset = offsetof(struct ext2_super_block, s_checksum); 77d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 78d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return ext2fs_crc32c_le(~0, (unsigned char *)sb, offset); 79d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong} 80d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 812432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong/* NOTE: The input to this function MUST be in LE order */ 82d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wongint ext2fs_superblock_csum_verify(ext2_filsys fs, struct ext2_super_block *sb) 83d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong{ 842432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong __u32 flag, calculated; 85d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 862432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong if (fs->flags & EXT2_FLAG_SWAP_BYTES) 872432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM; 882432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong else 892432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); 902432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong 912432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag)) 92d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return 1; 93d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 94d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong calculated = ext2fs_superblock_csum(fs, sb); 95d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 96d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return ext2fs_le32_to_cpu(sb->s_checksum) == calculated; 97d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong} 98d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 992432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong/* NOTE: The input to this function MUST be in LE order */ 100d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wongerrcode_t ext2fs_superblock_csum_set(ext2_filsys fs, 101d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong struct ext2_super_block *sb) 102d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong{ 1032432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong __u32 flag, crc; 104d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 1052432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong if (fs->flags & EXT2_FLAG_SWAP_BYTES) 1062432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong flag = EXT4_FEATURE_RO_COMPAT_METADATA_CSUM; 1072432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong else 1082432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong flag = ext2fs_cpu_to_le32(EXT4_FEATURE_RO_COMPAT_METADATA_CSUM); 1092432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong 1102432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, flag)) 111d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return 0; 112d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 113d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong crc = ext2fs_superblock_csum(fs, sb); 114d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong sb->s_checksum = ext2fs_cpu_to_le32(crc); 115d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 116d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong return 0; 117d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong} 118d4ca3e40cabd4ec5124ab9aa958fa9e5337aed39Darrick J. Wong 119894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'ostatic errcode_t ext2fs_ext_attr_block_csum(ext2_filsys fs, 120894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o ext2_ino_t inum EXT2FS_ATTR((unused)), 12139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong blk64_t block, 12239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong struct ext2_ext_attr_header *hdr, 12339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong __u32 *crc) 12439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{ 12539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong char *buf = (char *)hdr; 1261b8c4c1b45482363e29bd4cca483d84645f8ac9dAndreas Dilger __u32 old_crc = hdr->h_checksum; 12739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 12839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong hdr->h_checksum = 0; 12939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong block = ext2fs_cpu_to_le64(block); 13039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&block, 13139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong sizeof(block)); 13239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, fs->blocksize); 13339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong hdr->h_checksum = old_crc; 13439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 13539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 0; 13639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong} 13739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 13839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wongint ext2fs_ext_attr_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, 13939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong blk64_t block, 14039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong struct ext2_ext_attr_header *hdr) 14139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{ 14239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong __u32 calculated; 14339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong errcode_t retval; 14439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 14577b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 14639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 1; 14739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 14839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &calculated); 14939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong if (retval) 15039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 0; 15139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 15239f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return ext2fs_le32_to_cpu(hdr->h_checksum) == calculated; 15339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong} 15439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 15539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wongerrcode_t ext2fs_ext_attr_block_csum_set(ext2_filsys fs, ext2_ino_t inum, 15639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong blk64_t block, 15739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong struct ext2_ext_attr_header *hdr) 15839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong{ 15939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong errcode_t retval; 16039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong __u32 crc; 16139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 16277b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 16339f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 0; 16439f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 16539f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong retval = ext2fs_ext_attr_block_csum(fs, inum, block, hdr, &crc); 16639f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong if (retval) 16739f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return retval; 16839f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong hdr->h_checksum = ext2fs_cpu_to_le32(crc); 16939f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong return 0; 17039f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong} 17139f5659ae3a0d9105ecddddfda2800b7002febc3Darrick J. Wong 172dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic __u16 do_nothing16(__u16 x) 173dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 174dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return x; 175dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 176dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 177dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic __u16 disk_to_host16(__u16 x) 178dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 179dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return ext2fs_le16_to_cpu(x); 180dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 181dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 182dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t __get_dx_countlimit(ext2_filsys fs, 183dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent, 184dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit **cc, 185dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int *offset, 186dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int need_swab) 187dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 188dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dp; 189dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_root_info *root; 190dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit *c; 191dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int count_offset, max_sane_entries; 192dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong unsigned int rec_len; 193dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16); 194dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 195dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong rec_len = translate(dirent->rec_len); 196dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 197dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (rec_len == fs->blocksize && translate(dirent->name_len) == 0) 198dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count_offset = 8; 199dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong else if (rec_len == 12) { 200894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o dp = (struct ext2_dir_entry *)(((char *)dirent) + rec_len); 201dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong rec_len = translate(dp->rec_len); 202dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (rec_len != fs->blocksize - 12) 203dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DB_NOT_FOUND; 204894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o root = (struct ext2_dx_root_info *)(((char *)dp + 12)); 205dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (root->reserved_zero || 206dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong root->info_length != sizeof(struct ext2_dx_root_info)) 207dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DB_NOT_FOUND; 208dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count_offset = 32; 209dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong } else 210dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DB_NOT_FOUND; 211dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 212894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o c = (struct ext2_dx_countlimit *)(((char *)dirent) + count_offset); 213dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong max_sane_entries = (fs->blocksize - count_offset) / 214dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong sizeof(struct ext2_dx_entry); 215dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (ext2fs_le16_to_cpu(c->limit) > max_sane_entries || 216dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong ext2fs_le16_to_cpu(c->count) > max_sane_entries) 217dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 218dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 219dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (offset) 220dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *offset = count_offset; 221dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (cc) 222dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *cc = c; 223dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 224dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 0; 225dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 226dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 227dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongerrcode_t ext2fs_get_dx_countlimit(ext2_filsys fs, 228dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent, 229dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit **cc, 230dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int *offset) 231dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 232dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return __get_dx_countlimit(fs, dirent, cc, offset, 0); 233dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 234dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 23581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongvoid ext2fs_initialize_dirent_tail(ext2_filsys fs, 23681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail *t) 23781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 23881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong memset(t, 0, sizeof(struct ext2_dir_entry_tail)); 23981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong ext2fs_set_rec_len(fs, sizeof(struct ext2_dir_entry_tail), 24081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong (struct ext2_dir_entry *)t); 24181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong t->det_reserved_name_len = EXT2_DIR_NAME_LEN_CSUM; 24281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 24381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 24481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t __get_dirent_tail(ext2_filsys fs, 24581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent, 24681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail **tt, 24781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong int need_swab) 24881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 24981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *d; 25081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong void *top; 25181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail *t; 25281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong unsigned int rec_len; 25381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong errcode_t retval = 0; 25481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong __u16 (*translate)(__u16) = (need_swab ? disk_to_host16 : do_nothing16); 25581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 25681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong d = dirent; 25781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong top = EXT2_DIRENT_TAIL(dirent, fs->blocksize); 25881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 25981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong rec_len = translate(d->rec_len); 26081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong while (rec_len && !(rec_len & 0x3)) { 261894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o d = (struct ext2_dir_entry *)(((char *)d) + rec_len); 26281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if ((void *)d >= top) 26381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong break; 26481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong rec_len = translate(d->rec_len); 26581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong } 26681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 26781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (d != top) 26881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 26981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 27081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong t = (struct ext2_dir_entry_tail *)d; 27181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (t->det_reserved_zero1 || 27281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong translate(t->det_rec_len) != sizeof(struct ext2_dir_entry_tail) || 27381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong translate(t->det_reserved_name_len) != EXT2_DIR_NAME_LEN_CSUM) 27481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 27581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 27681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (tt) 27781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong *tt = t; 27881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return retval; 27981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 28081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 28181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dirent_has_tail(ext2_filsys fs, struct ext2_dir_entry *dirent) 28281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 28381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return __get_dirent_tail(fs, dirent, NULL, 0) == 0; 28481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 28581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 28681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t ext2fs_dirent_csum(ext2_filsys fs, ext2_ino_t inum, 28781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent, __u32 *crc, 28881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong int size) 28981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 29081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong errcode_t retval; 29181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong char *buf = (char *)dirent; 29281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong __u32 gen; 29381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_inode inode; 29481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 29581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = ext2fs_read_inode(fs, inum, &inode); 29681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 29781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return retval; 29881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 29981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong inum = ext2fs_cpu_to_le32(inum); 30081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong gen = ext2fs_cpu_to_le32(inode.i_generation); 30181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, 30281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong sizeof(inum)); 30381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); 30481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); 30581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 30681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 30781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 30881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 30981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dirent_csum_verify(ext2_filsys fs, ext2_ino_t inum, 31081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent) 31181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 31281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong errcode_t retval; 31381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong __u32 calculated; 31481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail *t; 31581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 31681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = __get_dirent_tail(fs, dirent, &t, 1); 31781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 31881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 1; 31981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 32081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong /* 32181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong * The checksum field is overlaid with the dirent->name field 32281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong * so the swapfs.c functions won't change the endianness. 32381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong */ 32481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = ext2fs_dirent_csum(fs, inum, dirent, &calculated, 325894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o (char *)t - (char *)dirent); 32681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 32781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 32881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_le32_to_cpu(t->det_checksum) == calculated; 32981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 33081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 33181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongstatic errcode_t ext2fs_dirent_csum_set(ext2_filsys fs, ext2_ino_t inum, 33281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent) 33381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 33481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong errcode_t retval; 33581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong __u32 crc; 33681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry_tail *t; 33781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 33881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = __get_dirent_tail(fs, dirent, &t, 1); 33981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 34081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return retval; 34181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 34281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong /* swapfs.c functions don't change the checksum endianness */ 34381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong retval = ext2fs_dirent_csum(fs, inum, dirent, &crc, 344894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o (char *)t - (char *)dirent); 34581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (retval) 34681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return retval; 34781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong t->det_checksum = ext2fs_cpu_to_le32(crc); 34881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 34981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 35081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 351dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum, 352dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent, 353dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u32 *crc, int count_offset, int count, 354dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_tail *t) 355dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 356dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong errcode_t retval; 357dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong char *buf = (char *)dirent; 358dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int size; 359dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u32 old_csum, gen; 360dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_inode inode; 361dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 362dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong size = count_offset + (count * sizeof(struct ext2_dx_entry)); 363dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong old_csum = t->dt_checksum; 364dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t->dt_checksum = 0; 365dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 366dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = ext2fs_read_inode(fs, inum, &inode); 367dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 368dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return retval; 369dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 370dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong inum = ext2fs_cpu_to_le32(inum); 371dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong gen = ext2fs_cpu_to_le32(inode.i_generation); 372dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, 373dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong sizeof(inum)); 374dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); 375dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)buf, size); 376dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)t, 377dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong sizeof(struct ext2_dx_tail)); 378dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t->dt_checksum = old_csum; 379dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 380dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 0; 381dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 382dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 383dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic int ext2fs_dx_csum_verify(ext2_filsys fs, ext2_ino_t inum, 384dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent) 385dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 386dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u32 calculated; 387dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong errcode_t retval; 388dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit *c; 389dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_tail *t; 390dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int count_offset, limit, count; 391dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 392dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); 393dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 394dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 1; 395dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong limit = ext2fs_le16_to_cpu(c->limit); 396dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count = ext2fs_le16_to_cpu(c->count); 397dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > 398dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong fs->blocksize - sizeof(struct ext2_dx_tail)) 399dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 0; 400dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong /* htree structs are accessed in LE order */ 401dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); 402dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = ext2fs_dx_csum(fs, inum, dirent, &calculated, count_offset, 403dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count, t); 404dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 405dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return 0; 406dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 407dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return ext2fs_le32_to_cpu(t->dt_checksum) == calculated; 408dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 409dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 410dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wongstatic errcode_t ext2fs_dx_csum_set(ext2_filsys fs, ext2_ino_t inum, 411dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dir_entry *dirent) 412dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong{ 413dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong __u32 crc; 414dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong errcode_t retval = 0; 415dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_countlimit *c; 416dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong struct ext2_dx_tail *t; 417dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong int count_offset, limit, count; 418dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 419dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = __get_dx_countlimit(fs, dirent, &c, &count_offset, 1); 420dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 421dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return retval; 422dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong limit = ext2fs_le16_to_cpu(c->limit); 423dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong count = ext2fs_le16_to_cpu(c->count); 424dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (count_offset + (limit * sizeof(struct ext2_dx_entry)) > 425dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong fs->blocksize - sizeof(struct ext2_dx_tail)) 426dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 427dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t = (struct ext2_dx_tail *)(((struct ext2_dx_entry *)c) + limit); 428dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 429dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong /* htree structs are accessed in LE order */ 430dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong retval = ext2fs_dx_csum(fs, inum, dirent, &crc, count_offset, count, t); 431dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong if (retval) 432dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return retval; 433dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong t->dt_checksum = ext2fs_cpu_to_le32(crc); 434dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong return retval; 435dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong} 436dc96de09d7356ef25448134445753aabfc1097daDarrick J. Wong 43781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongint ext2fs_dir_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, 43881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent) 43981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 44077b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 44181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 1; 44281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 44381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (__get_dirent_tail(fs, dirent, NULL, 1) == 0) 44481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_dirent_csum_verify(fs, inum, dirent); 44581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0) 44681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_dx_csum_verify(fs, inum, dirent); 44781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 44881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 44981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 45081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 45181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wongerrcode_t ext2fs_dir_block_csum_set(ext2_filsys fs, ext2_ino_t inum, 45281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong struct ext2_dir_entry *dirent) 45381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong{ 45477b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 45581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 45681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 45781683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (__get_dirent_tail(fs, dirent, NULL, 1) == 0) 45881683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_dirent_csum_set(fs, inum, dirent); 45981683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (__get_dx_countlimit(fs, dirent, NULL, NULL, 1) == 0) 46081683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return ext2fs_dx_csum_set(fs, inum, dirent); 46181683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 46281683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong if (fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) 46381683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return 0; 46481683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong return EXT2_ET_DIR_NO_SPACE_FOR_CSUM; 46581683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong} 46681683c6a32045cf04d76a024e6f1753535b97c22Darrick J. Wong 46741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong#define EXT3_EXTENT_TAIL_OFFSET(hdr) (sizeof(struct ext3_extent_header) + \ 46841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong (sizeof(struct ext3_extent) * ext2fs_le16_to_cpu((hdr)->eh_max))) 46941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 47041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongstatic struct ext3_extent_tail *get_extent_tail(struct ext3_extent_header *h) 47141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{ 472894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o return (struct ext3_extent_tail *)(((char *)h) + 47341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong EXT3_EXTENT_TAIL_OFFSET(h)); 47441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong} 47541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 47641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongstatic errcode_t ext2fs_extent_block_csum(ext2_filsys fs, ext2_ino_t inum, 47741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_header *eh, 47841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong __u32 *crc) 47941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{ 48041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong int size; 48141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong __u32 gen; 48241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong errcode_t retval; 48341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext2_inode inode; 48441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 48541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong size = EXT3_EXTENT_TAIL_OFFSET(eh) + offsetof(struct ext3_extent_tail, 48641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong et_checksum); 48741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 48841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong retval = ext2fs_read_inode(fs, inum, &inode); 48941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong if (retval) 49041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return retval; 49141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong inum = ext2fs_cpu_to_le32(inum); 49241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong gen = ext2fs_cpu_to_le32(inode.i_generation); 49341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, 49441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong sizeof(inum)); 49541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); 49641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)eh, size); 49741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 49841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return 0; 49941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong} 50041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 50141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongint ext2fs_extent_block_csum_verify(ext2_filsys fs, ext2_ino_t inum, 50241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_header *eh) 50341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{ 50441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong errcode_t retval; 50541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong __u32 provided, calculated; 50641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_tail *t = get_extent_tail(eh); 50741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 50841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong /* 50941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong * The extent tree structures are accessed in LE order, so we must 51041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong * swap the checksum bytes here. 51141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong */ 51277b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 51341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return 1; 51441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 51541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong provided = ext2fs_le32_to_cpu(t->et_checksum); 51641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong retval = ext2fs_extent_block_csum(fs, inum, eh, &calculated); 51741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong if (retval) 51841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return 0; 51941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 52041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return provided == calculated; 52141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong} 52241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 52341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wongerrcode_t ext2fs_extent_block_csum_set(ext2_filsys fs, ext2_ino_t inum, 52441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_header *eh) 52541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong{ 52641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong errcode_t retval; 52741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong __u32 crc; 52841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong struct ext3_extent_tail *t = get_extent_tail(eh); 52941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 53077b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 53141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return 0; 53241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 53341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong /* 53441275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong * The extent tree structures are accessed in LE order, so we must 53541275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong * swap the checksum bytes here. 53641275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong */ 53741275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong retval = ext2fs_extent_block_csum(fs, inum, eh, &crc); 53841275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong if (retval) 53941275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return retval; 54041275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong t->et_checksum = ext2fs_cpu_to_le32(crc); 54141275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong return retval; 54241275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong} 54341275efeeebe46f68b7e3ffb3beb30ff479a2308Darrick J. Wong 544a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wongint ext2fs_inode_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, 545a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong char *bitmap, int size) 546a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong{ 547a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong struct ext4_group_desc *gdp = (struct ext4_group_desc *) 548a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong ext2fs_group_desc(fs, fs->group_desc, group); 549a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong __u32 provided, calculated; 550a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 55177b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 552a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong return 1; 553a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong provided = gdp->bg_inode_bitmap_csum_lo; 554a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, 555a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong size); 556a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) 557a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong provided |= (__u32)gdp->bg_inode_bitmap_csum_hi << 16; 558a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong else 559a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong calculated &= 0xFFFF; 560a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 561a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong return provided == calculated; 562a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong} 563a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 564a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wongerrcode_t ext2fs_inode_bitmap_csum_set(ext2_filsys fs, dgrp_t group, 565a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong char *bitmap, int size) 566a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong{ 567a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong __u32 crc; 568a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong struct ext4_group_desc *gdp = (struct ext4_group_desc *) 569a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong ext2fs_group_desc(fs, fs->group_desc, group); 570a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 57177b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 572a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong return 0; 573a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 574a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size); 575a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong gdp->bg_inode_bitmap_csum_lo = crc & 0xFFFF; 576a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong if (fs->super->s_desc_size >= EXT4_BG_INODE_BITMAP_CSUM_HI_END) 577a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong gdp->bg_inode_bitmap_csum_hi = crc >> 16; 578a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 579a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong return 0; 580a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong} 581a80ea34023e01b038314884dbf56165158b2b799Darrick J. Wong 582e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wongint ext2fs_block_bitmap_csum_verify(ext2_filsys fs, dgrp_t group, 583e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong char *bitmap, int size) 584e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong{ 585e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong struct ext4_group_desc *gdp = (struct ext4_group_desc *) 586e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong ext2fs_group_desc(fs, fs->group_desc, group); 587e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong __u32 provided, calculated; 588e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 58977b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 590e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong return 1; 591e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong provided = gdp->bg_block_bitmap_csum_lo; 592e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong calculated = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, 593e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong size); 594e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION) 595e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong provided |= (__u32)gdp->bg_block_bitmap_csum_hi << 16; 596e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong else 597e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong calculated &= 0xFFFF; 598e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 599e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong return provided == calculated; 600e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong} 601e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 602e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wongerrcode_t ext2fs_block_bitmap_csum_set(ext2_filsys fs, dgrp_t group, 603e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong char *bitmap, int size) 604e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong{ 605e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong __u32 crc; 606e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong struct ext4_group_desc *gdp = (struct ext4_group_desc *) 607e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong ext2fs_group_desc(fs, fs->group_desc, group); 608e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 60977b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (!ext2fs_has_feature_metadata_csum(fs->super)) 610e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong return 0; 611e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 612e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)bitmap, size); 613e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong gdp->bg_block_bitmap_csum_lo = crc & 0xFFFF; 614e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong if (fs->super->s_desc_size >= EXT4_BG_BLOCK_BITMAP_CSUM_HI_LOCATION) 615e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong gdp->bg_block_bitmap_csum_hi = crc >> 16; 616e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 617e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong return 0; 618e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong} 619e7dc95c6773fa0a49c54846ae609df1d8c2a7286Darrick J. Wong 62037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongstatic errcode_t ext2fs_inode_csum(ext2_filsys fs, ext2_ino_t inum, 62137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong struct ext2_inode_large *inode, 62237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 *crc, int has_hi) 62337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{ 62437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 gen; 62537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong struct ext2_inode_large *desc = inode; 62637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong size_t size = fs->super->s_inode_size; 62737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u16 old_lo; 62837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u16 old_hi = 0; 62937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 63037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong old_lo = inode->i_checksum_lo; 63137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_lo = 0; 63237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (has_hi) { 63337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong old_hi = inode->i_checksum_hi; 63437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_hi = 0; 63537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong } 63637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 63737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inum = ext2fs_cpu_to_le32(inum); 63837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong gen = inode->i_generation; 63937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong *crc = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&inum, 64037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong sizeof(inum)); 64137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)&gen, sizeof(gen)); 64237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong *crc = ext2fs_crc32c_le(*crc, (unsigned char *)desc, size); 64337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 64437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_lo = old_lo; 64537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (has_hi) 64637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_hi = old_hi; 64737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 0; 64837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong} 64937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 65037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongint ext2fs_inode_csum_verify(ext2_filsys fs, ext2_ino_t inum, 65137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong struct ext2_inode_large *inode) 65237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{ 65337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong errcode_t retval; 65437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 provided, calculated; 655894eaf85065f3a0ee023704eeba56799ec5bf6ebTheodore Ts'o unsigned int i, has_hi; 65697fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o char *cp; 65737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 65837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (fs->super->s_creator_os != EXT2_OS_LINUX || 65977b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong !ext2fs_has_feature_metadata_csum(fs->super)) 66037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 1; 66137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 66237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE && 66337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END); 66437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 66537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong provided = ext2fs_le16_to_cpu(inode->i_checksum_lo); 66637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong retval = ext2fs_inode_csum(fs, inum, inode, &calculated, has_hi); 66737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (retval) 66837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 0; 66937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (has_hi) { 67037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 hi = ext2fs_le16_to_cpu(inode->i_checksum_hi); 67137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong provided |= hi << 16; 67237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong } else 67337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong calculated &= 0xFFFF; 67437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 67597fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o if (provided == calculated) 67697fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o return 1; 67797fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o 67897fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o /* 67997fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * If the checksum didn't match, it's possible it was due to 68097fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * the inode being all zero's. It's unlikely this is the 68197fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * case, but it can happen. So check for it here. (We only 68297fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * check the base inode since that's good enough, and it's not 68397fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * worth the bother to figure out how much of the extended 68497fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o * inode, if any, is present.) 68597fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o */ 68697fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o for (cp = (char *) inode, i = 0; 68797fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o i < sizeof(struct ext2_inode); 68897fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o cp++, i++) 68997fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o if (*cp) 69097fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o return 0; 69197fac35094160261907eeb693498ef6ebd27283eTheodore Ts'o return 1; /* Inode must have been all zero's */ 69237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong} 69337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 69437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wongerrcode_t ext2fs_inode_csum_set(ext2_filsys fs, ext2_ino_t inum, 69537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong struct ext2_inode_large *inode) 69637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong{ 69737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong errcode_t retval; 69837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong __u32 crc; 69937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong int has_hi; 70037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 70137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (fs->super->s_creator_os != EXT2_OS_LINUX || 70277b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong !ext2fs_has_feature_metadata_csum(fs->super)) 70337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 0; 70437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 70537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong has_hi = (EXT2_INODE_SIZE(fs->super) > EXT2_GOOD_OLD_INODE_SIZE && 70637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_extra_isize >= EXT4_INODE_CSUM_HI_EXTRA_END); 70737d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 70837d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong retval = ext2fs_inode_csum(fs, inum, inode, &crc, has_hi); 70937d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (retval) 71037d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return retval; 71137d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_lo = ext2fs_cpu_to_le16(crc & 0xFFFF); 71237d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong if (has_hi) 71337d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong inode->i_checksum_hi = ext2fs_cpu_to_le16(crc >> 16); 71437d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong return 0; 71537d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong} 71637d82b6a95e1912c452e77e84ead61e2812d2721Darrick J. Wong 71787141781aabb4dc01359428d2feecdc7f43eeac0Theodore Ts'o__u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group) 718ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 7192bc30417541deffca795db8ec4e7f7ccb616dc3fAndreas Dilger struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, 7202bc30417541deffca795db8ec4e7f7ccb616dc3fAndreas Dilger group); 72171715a5a9ad409df162dbb58a4c3b6fd2c5868d5Theodore Ts'o size_t offset, size = EXT2_DESC_SIZE(fs->super); 722ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos __u16 crc = 0; 723ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#ifdef WORDS_BIGENDIAN 7245b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong struct ext4_group_desc swabdesc; 7252ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o size_t save_size = size; 7262ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o const size_t ext4_bg_size = sizeof(struct ext4_group_desc); 7272ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o struct ext2_group_desc *save_desc = desc; 728ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 7295b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong /* Have to swab back to little-endian to do the checksum */ 7302ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o if (size > ext4_bg_size) 7312ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o size = ext4_bg_size; 7325b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong memcpy(&swabdesc, desc, size); 7332ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc); 7345b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong desc = (struct ext2_group_desc *) &swabdesc; 7355b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong group = ext2fs_swab32(group); 736ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos#endif 7375b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong 73877b3e9871877fce9908b0696250787fd6ea61af9Darrick J. Wong if (ext2fs_has_feature_metadata_csum(fs->super)) { 7395b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong /* new metadata csum code */ 7405b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong __u16 old_crc; 7415b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong __u32 crc32; 7425b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong 7435b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong old_crc = desc->bg_checksum; 7445b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong desc->bg_checksum = 0; 7455b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc32 = ext2fs_crc32c_le(fs->csum_seed, (unsigned char *)&group, 7465b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong sizeof(group)); 7475b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc32 = ext2fs_crc32c_le(crc32, (unsigned char *)desc, 7485b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong size); 7495b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong desc->bg_checksum = old_crc; 750b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#ifdef WORDS_BIGENDIAN 751b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o if (save_size > ext4_bg_size) 7522ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o crc32 = ext2fs_crc32c_le(crc32, 7532432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong (unsigned char *)save_desc + ext4_bg_size, 7542432a41a58c03be4afdfb12f40e7b7cfe3255145Darrick J. Wong save_size - ext4_bg_size); 755b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#endif 7565b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = crc32 & 0xFFFF; 7575b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong goto out; 758ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos } 759ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 7605b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong /* old crc16 code */ 7612ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o offset = offsetof(struct ext2_group_desc, bg_checksum); 7625b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = ext2fs_crc16(~0, fs->super->s_uuid, 7635b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong sizeof(fs->super->s_uuid)); 7645b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = ext2fs_crc16(crc, &group, sizeof(group)); 7655b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = ext2fs_crc16(crc, desc, offset); 7665b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong offset += sizeof(desc->bg_checksum); /* skip checksum */ 7675b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong /* for checksum of struct ext4_group_desc do the rest...*/ 7685b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong if (offset < size) { 7695b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong crc = ext2fs_crc16(crc, (char *)desc + offset, 7705b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong size - offset); 7715b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong } 7722ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o#ifdef WORDS_BIGENDIAN 7732ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o /* 7742ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o * If the size of the bg descriptor is greater than 64 7752ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o * bytes, which is the size of the traditional ext4 bg 7762ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o * descriptor, checksum the rest of the descriptor here 7772ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o */ 7782ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o if (save_size > ext4_bg_size) 7792ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o crc = ext2fs_crc16(crc, (char *)save_desc + ext4_bg_size, 7802ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o save_size - ext4_bg_size); 7812ffccc82c4b9ed935e45118e325896b70e9e3eb0Theodore Ts'o#endif 7825b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong 7835b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wongout: 784ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return crc; 785ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 786ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 787ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosint ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group) 788ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 7895b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong if (ext2fs_has_group_desc_csum(fs) && 790d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson (ext2fs_bg_checksum(fs, group) != 7914729455f0a68f2fa0a83ec8460d1d4bccba9dcfaTheodore Ts'o ext2fs_group_desc_csum(fs, group))) 792ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return 0; 793ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 794ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return 1; 795ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 796ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 797ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosvoid ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group) 798ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 7995b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong if (!ext2fs_has_group_desc_csum(fs)) 800d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson return; 801d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson 802d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson /* ext2fs_bg_checksum_set() sets the actual checksum field but 803d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson * does not calculate the checksum itself. */ 804d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_checksum_set(fs, group, ext2fs_group_desc_csum(fs, group)); 805ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 806ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 807ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santosstatic __u32 find_last_inode_ingrp(ext2fs_inode_bitmap bitmap, 808ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos __u32 inodes_per_grp, dgrp_t grp_no) 809ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 810ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos ext2_ino_t i, start_ino, end_ino; 811ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 812ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos start_ino = grp_no * inodes_per_grp + 1; 813ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos end_ino = start_ino + inodes_per_grp - 1; 814ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 815ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos for (i = end_ino; i >= start_ino; i--) { 8168f82ef9860339039b54a324be137fbc09b762358Valerie Aurora Henson if (ext2fs_fast_test_inode_bitmap2(bitmap, i)) 817ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return i - start_ino + 1; 818ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos } 819ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos return inodes_per_grp; 820ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 821ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 822ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos/* update the bitmap flags, set the itable high watermark, and calculate 823ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos * checksums for the group descriptors */ 824f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilgererrcode_t ext2fs_set_gdt_csum(ext2_filsys fs) 825ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos{ 826ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos struct ext2_super_block *sb = fs->super; 8278895f43a60269464f654e9d87c28768875cd703aTheodore Ts'o int dirty = 0; 828ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos dgrp_t i; 829ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 830f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger if (!fs->inode_map) 831f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger return EXT2_ET_NO_INODE_BITMAP; 832f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger 8335b58dc2304f06953e1d8314ea570cc3befec95bcDarrick J. Wong if (!ext2fs_has_group_desc_csum(fs)) 834f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger return 0; 835ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 836d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson for (i = 0; i < fs->group_desc_count; i++) { 837d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o __u32 old_csum = ext2fs_bg_checksum(fs, i); 838d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o __u32 old_unused = ext2fs_bg_itable_unused(fs, i); 839d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o __u32 old_flags = ext2fs_bg_flags(fs, i); 840d32c915abfb224f6f6659e9cada7e9f759b7e3d2Theodore Ts'o __u32 old_free_inodes_count = ext2fs_bg_free_inodes_count(fs, i); 841c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong __u32 old_free_blocks_count = ext2fs_bg_free_blocks_count(fs, i); 842c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong 843c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong if (old_free_blocks_count == sb->s_blocks_per_group && 844c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong i != fs->group_desc_count - 1) 845c0ff3a21b6c3b30fbbe16280cf1808864f5803b7Darrick J. Wong ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT); 846ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 847d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson if (old_free_inodes_count == sb->s_inodes_per_group) { 848d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT); 849d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_itable_unused_set(fs, i, sb->s_inodes_per_group); 85016b851cdae98244e117fe91d93b267fcad1102b3Theodore Ts'o } else { 851d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson int unused = 852d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson sb->s_inodes_per_group - 853ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos find_last_inode_ingrp(fs->inode_map, 854d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson sb->s_inodes_per_group, i); 855d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson 856d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_flags_clear(fs, i, EXT2_BG_INODE_UNINIT); 857d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_itable_unused_set(fs, i, unused); 858ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos } 859ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos 860ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos ext2fs_group_desc_csum_set(fs, i); 861d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson if (old_flags != ext2fs_bg_flags(fs, i)) 86280fc4e698a308de22ace6179f45e0bb67befa74bAndreas Dilger dirty = 1; 863d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson if (old_unused != ext2fs_bg_itable_unused(fs, i)) 86480fc4e698a308de22ace6179f45e0bb67befa74bAndreas Dilger dirty = 1; 865d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson if (old_csum != ext2fs_bg_checksum(fs, i)) 866ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos dirty = 1; 867ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos } 868ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos if (dirty) 869ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos ext2fs_mark_super_dirty(fs); 870f628acea2671dda839fc086f1017718e41e34ecaAndreas Dilger return 0; 871ca2634a46ab9da85a3a015a7772770d9dbe5848eJose R. Santos} 872470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 873470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#ifdef DEBUG 874c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen#include "e2p/e2p.h" 875c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen 876470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'ovoid print_csum(const char *msg, ext2_filsys fs, dgrp_t group) 877470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o{ 878470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o __u16 crc1, crc2, crc3; 879470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o dgrp_t swabgroup; 880b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o struct ext2_group_desc *desc = ext2fs_group_desc(fs, fs->group_desc, 881b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o group); 882b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o size_t size = EXT2_DESC_SIZE(fs->super); 883470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o struct ext2_super_block *sb = fs->super; 8841d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o int offset = offsetof(struct ext2_group_desc, bg_checksum); 885470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#ifdef WORDS_BIGENDIAN 8861d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o struct ext4_group_desc swabdesc; 887b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o struct ext2_group_desc *save_desc = desc; 888b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o const size_t ext4_bg_size = sizeof(struct ext4_group_desc); 889b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o size_t save_size = size; 8901d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o#endif 891470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 8921d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o#ifdef WORDS_BIGENDIAN 893470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o /* Have to swab back to little-endian to do the checksum */ 894b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o if (size > ext4_bg_size) 895b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o size = ext4_bg_size; 8961d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o memcpy(&swabdesc, desc, size); 8971d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o ext2fs_swap_group_desc2(fs, (struct ext2_group_desc *) &swabdesc); 8981d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o desc = (struct ext2_group_desc *) &swabdesc; 899470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 900470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o swabgroup = ext2fs_swab32(group); 901470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#else 902470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o swabgroup = group; 903470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#endif 904470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 905470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o crc1 = ext2fs_crc16(~0, sb->s_uuid, sizeof(fs->super->s_uuid)); 906470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o crc2 = ext2fs_crc16(crc1, &swabgroup, sizeof(swabgroup)); 9071d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o crc3 = ext2fs_crc16(crc2, desc, offset); 9081d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o offset += sizeof(desc->bg_checksum); /* skip checksum */ 9091d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o /* for checksum of struct ext4_group_desc do the rest...*/ 9101d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o if (offset < size) 9111d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o crc3 = ext2fs_crc16(crc3, (char *)desc + offset, size - offset); 912b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#ifdef WORDS_BIGENDIAN 913b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o if (save_size > ext4_bg_size) 914b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o crc3 = ext2fs_crc16(crc3, (char *)save_desc + ext4_bg_size, 915b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o save_size - ext4_bg_size); 916b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#endif 9171d18a55c528adf997d8edee60bd8003c822c55e8Theodore Ts'o 918f797cf3e37b476aac593fe9a9f4630448d335332Andreas Dilger printf("%s UUID %s=%04x, grp %u=%04x: %04x=%04x\n", 919562f264243f4d4385910b6f06872730214977736Theodore Ts'o msg, e2p_uuid2str(sb->s_uuid), crc1, group, crc2, crc3, 920c816ecb204a32e67788738e050ff2b14a721672bEric Sandeen ext2fs_group_desc_csum(fs, group)); 921470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o} 922470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 923470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'ounsigned char sb_uuid[16] = { 0x4f, 0x25, 0xe8, 0xcf, 0xe7, 0x97, 0x48, 0x23, 924470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 0xbe, 0xfa, 0xa7, 0x88, 0x4b, 0xae, 0xec, 0xdb }; 925470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 926470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'oint main(int argc, char **argv) 927470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o{ 928470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o struct ext2_super_block param; 929470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o errcode_t retval; 930470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o ext2_filsys fs; 931470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o int i; 932470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o __u16 csum1, csum2, csum_known = 0xd3a4; 933470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 934470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o memset(¶m, 0, sizeof(param)); 9354efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson ext2fs_blocks_count_set(¶m, 32768); 936b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#if 0 937b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o param.s_feature_incompat |= EXT4_FEATURE_INCOMPAT_64BIT; 938b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o param.s_desc_size = 128; 939b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o csum_known = 0x5b6e; 940b3c2a638139b5da7f63f7ebe450860918d297a39Theodore Ts'o#endif 941470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 9428f82ef9860339039b54a324be137fbc09b762358Valerie Aurora Henson retval = ext2fs_initialize("test fs", EXT2_FLAG_64BITS, ¶m, 943470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o test_io_manager, &fs); 944470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (retval) { 945470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o com_err("setup", retval, 946470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o "While initializing filesystem"); 947470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 948470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 949470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o memcpy(fs->super->s_uuid, sb_uuid, 16); 950470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o fs->super->s_feature_ro_compat = EXT4_FEATURE_RO_COMPAT_GDT_CSUM; 951470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 952470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o for (i=0; i < fs->group_desc_count; i++) { 953d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_block_bitmap_loc_set(fs, i, 124); 954d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_inode_bitmap_loc_set(fs, i, 125); 955d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_inode_table_loc_set(fs, i, 126); 956d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_free_blocks_count_set(fs, i, 31119); 957d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_free_inodes_count_set(fs, i, 15701); 958d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_used_dirs_count_set(fs, i, 2); 959e633b58ac75f2f544b7d6572e37d4b63da31e59cEric Sandeen ext2fs_bg_flags_zap(fs, i); 960470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o }; 961470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 962470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum1 = ext2fs_group_desc_csum(fs, 0); 963470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum0000", fs, 0); 964470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 965470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 != csum_known) { 966470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksum for group 0 should be %04x\n", csum_known); 967470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 968470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 969470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum2 = ext2fs_group_desc_csum(fs, 1); 970470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum0001", fs, 1); 971470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 == csum2) { 972470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums for different groups shouldn't match\n"); 973470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 974470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 975470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum2 = ext2fs_group_desc_csum(fs, 2); 976470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csumffff", fs, 2); 977470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 == csum2) { 978470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums for different groups shouldn't match\n"); 979470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 980470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 981d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_checksum_set(fs, 0, csum1); 982470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum2 = ext2fs_group_desc_csum(fs, 0); 983470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum_set", fs, 0); 984470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 != csum2) { 985470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums should not depend on checksum field\n"); 986470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 987470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 988470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (!ext2fs_group_desc_csum_verify(fs, 0)) { 989470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums should verify against gd_checksum\n"); 990470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 991470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 992470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o memset(fs->super->s_uuid, 0x30, sizeof(fs->super->s_uuid)); 993470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("new_uuid", fs, 0); 994470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (ext2fs_group_desc_csum_verify(fs, 0) != 0) { 995470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums for different filesystems shouldn't match\n"); 996470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 997470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 998d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson csum1 = ext2fs_group_desc_csum(fs, 0); 999d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_checksum_set(fs, 0, csum1); 1000470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum_new", fs, 0); 1001d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson ext2fs_bg_free_blocks_count_set(fs, 0, 1); 1002470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o csum2 = ext2fs_group_desc_csum(fs, 0); 1003470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o print_csum("csum_blk", fs, 0); 1004470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o if (csum1 == csum2) { 1005470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o printf("checksums for different data shouldn't match\n"); 1006470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o exit(1); 1007470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o } 1008470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o 1009470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o return 0; 1010470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o} 1011470e737a872918afd9067de1ce92d571d5671d40Theodore Ts'o#endif 1012