1 /* 2 * Copyright (C) 1999, 2001 by Andries Brouwer 3 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o 4 * Copyright (C) 2008 Karel Zak <kzak@redhat.com> 5 * 6 * This file may be redistributed under the terms of the 7 * GNU Lesser General Public License. 8 */ 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <unistd.h> 12 #include <string.h> 13 #include <errno.h> 14 #include <ctype.h> 15 #include <stdint.h> 16 #ifdef __linux__ 17 #include <sys/utsname.h> 18 #endif 19 #include <time.h> 20 21 #include "superblocks.h" 22 23 struct ext2_super_block { 24 uint32_t s_inodes_count; 25 uint32_t s_blocks_count; 26 uint32_t s_r_blocks_count; 27 uint32_t s_free_blocks_count; 28 uint32_t s_free_inodes_count; 29 uint32_t s_first_data_block; 30 uint32_t s_log_block_size; 31 uint32_t s_dummy3[7]; 32 unsigned char s_magic[2]; 33 uint16_t s_state; 34 uint16_t s_errors; 35 uint16_t s_minor_rev_level; 36 uint32_t s_lastcheck; 37 uint32_t s_checkinterval; 38 uint32_t s_creator_os; 39 uint32_t s_rev_level; 40 uint16_t s_def_resuid; 41 uint16_t s_def_resgid; 42 uint32_t s_first_ino; 43 uint16_t s_inode_size; 44 uint16_t s_block_group_nr; 45 uint32_t s_feature_compat; 46 uint32_t s_feature_incompat; 47 uint32_t s_feature_ro_compat; 48 unsigned char s_uuid[16]; 49 char s_volume_name[16]; 50 char s_last_mounted[64]; 51 uint32_t s_algorithm_usage_bitmap; 52 uint8_t s_prealloc_blocks; 53 uint8_t s_prealloc_dir_blocks; 54 uint16_t s_reserved_gdt_blocks; 55 uint8_t s_journal_uuid[16]; 56 uint32_t s_journal_inum; 57 uint32_t s_journal_dev; 58 uint32_t s_last_orphan; 59 uint32_t s_hash_seed[4]; 60 uint8_t s_def_hash_version; 61 uint8_t s_jnl_backup_type; 62 uint16_t s_reserved_word_pad; 63 uint32_t s_default_mount_opts; 64 uint32_t s_first_meta_bg; 65 uint32_t s_mkfs_time; 66 uint32_t s_jnl_blocks[17]; 67 uint32_t s_blocks_count_hi; 68 uint32_t s_r_blocks_count_hi; 69 uint32_t s_free_blocks_hi; 70 uint16_t s_min_extra_isize; 71 uint16_t s_want_extra_isize; 72 uint32_t s_flags; 73 uint16_t s_raid_stride; 74 uint16_t s_mmp_interval; 75 uint64_t s_mmp_block; 76 uint32_t s_raid_stripe_width; 77 uint32_t s_reserved[163]; 78 } __attribute__((packed)); 79 80 /* magic string */ 81 #define EXT_SB_MAGIC "\123\357" 82 /* supper block offset */ 83 #define EXT_SB_OFF 0x400 84 /* supper block offset in kB */ 85 #define EXT_SB_KBOFF (EXT_SB_OFF >> 10) 86 /* magic string offset within super block */ 87 #define EXT_MAG_OFF 0x38 88 89 90 91 /* for s_flags */ 92 #define EXT2_FLAGS_TEST_FILESYS 0x0004 93 94 /* for s_feature_compat */ 95 #define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 96 97 /* for s_feature_ro_compat */ 98 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 99 #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 100 #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004 101 #define EXT4_FEATURE_RO_COMPAT_HUGE_FILE 0x0008 102 #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 103 #define EXT4_FEATURE_RO_COMPAT_DIR_NLINK 0x0020 104 #define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE 0x0040 105 106 /* for s_feature_incompat */ 107 #define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 108 #define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 109 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008 110 #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 111 #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */ 112 #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 113 #define EXT4_FEATURE_INCOMPAT_MMP 0x0100 114 #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 115 116 #define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ 117 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ 118 EXT2_FEATURE_RO_COMPAT_BTREE_DIR) 119 #define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ 120 EXT2_FEATURE_INCOMPAT_META_BG) 121 #define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP 122 #define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP 123 124 #define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \ 125 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \ 126 EXT2_FEATURE_RO_COMPAT_BTREE_DIR) 127 #define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \ 128 EXT3_FEATURE_INCOMPAT_RECOVER| \ 129 EXT2_FEATURE_INCOMPAT_META_BG) 130 #define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP 131 #define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP 132 133 /* 134 * Starting in 2.6.29, ext4 can be used to support filesystems 135 * without a journal. 136 */ 137 #define EXT4_SUPPORTS_EXT2 KERNEL_VERSION(2, 6, 29) 138 139 /* 140 * reads superblock and returns: 141 * fc = feature_compat 142 * fi = feature_incompat 143 * frc = feature_ro_compat 144 */ 145 static struct ext2_super_block *ext_get_super( 146 blkid_probe pr, uint32_t *fc, uint32_t *fi, uint32_t *frc) 147 { 148 struct ext2_super_block *es; 149 150 es = (struct ext2_super_block *) 151 blkid_probe_get_buffer(pr, EXT_SB_OFF, 0x200); 152 if (!es) 153 return NULL; 154 if (fc) 155 *fc = le32_to_cpu(es->s_feature_compat); 156 if (fi) 157 *fi = le32_to_cpu(es->s_feature_incompat); 158 if (frc) 159 *frc = le32_to_cpu(es->s_feature_ro_compat); 160 161 return es; 162 } 163 164 static void ext_get_info(blkid_probe pr, int ver, struct ext2_super_block *es) 165 { 166 #if 0 167 struct blkid_chain *chn = blkid_probe_get_chain(pr); 168 #endif 169 170 DBG(PROBE, ul_debug("ext2_sb.compat = %08X:%08X:%08X", 171 le32_to_cpu(es->s_feature_compat), 172 le32_to_cpu(es->s_feature_incompat), 173 le32_to_cpu(es->s_feature_ro_compat))); 174 175 if (strlen(es->s_volume_name)) 176 blkid_probe_set_label(pr, (unsigned char *) es->s_volume_name, 177 sizeof(es->s_volume_name)); 178 blkid_probe_set_uuid(pr, es->s_uuid); 179 180 if (le32_to_cpu(es->s_feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) 181 blkid_probe_set_uuid_as(pr, es->s_journal_uuid, "EXT_JOURNAL"); 182 183 #if 0 184 if (ver != 2 && (chn->flags & BLKID_SUBLKS_SECTYPE) && 185 ((le32_to_cpu(es->s_feature_incompat) & EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0)) 186 blkid_probe_set_value(pr, "SEC_TYPE", 187 (unsigned char *) "ext2", 188 sizeof("ext2")); 189 #endif 190 191 blkid_probe_sprintf_version(pr, "%u.%u", 192 le32_to_cpu(es->s_rev_level), 193 le16_to_cpu(es->s_minor_rev_level)); 194 } 195 196 197 static int probe_jbd(blkid_probe pr, 198 const struct blkid_idmag *mag __attribute__((__unused__))) 199 { 200 struct ext2_super_block *es; 201 uint32_t fi; 202 203 es = ext_get_super(pr, NULL, &fi, NULL); 204 if (!es) 205 return errno ? -errno : 1; 206 if (!(fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) 207 return 1; 208 209 ext_get_info(pr, 2, es); 210 blkid_probe_set_uuid_as(pr, es->s_uuid, "LOGUUID"); 211 212 return 0; 213 } 214 215 static int probe_ext2(blkid_probe pr, 216 const struct blkid_idmag *mag __attribute__((__unused__))) 217 { 218 struct ext2_super_block *es; 219 uint32_t fc, frc, fi; 220 221 es = ext_get_super(pr, &fc, &fi, &frc); 222 if (!es) 223 return errno ? -errno : 1; 224 225 /* Distinguish between ext3 and ext2 */ 226 if (fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) 227 return 1; 228 229 /* Any features which ext2 doesn't understand */ 230 if ((frc & EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) || 231 (fi & EXT2_FEATURE_INCOMPAT_UNSUPPORTED)) 232 return 1; 233 234 ext_get_info(pr, 2, es); 235 return 0; 236 } 237 238 static int probe_ext3(blkid_probe pr, 239 const struct blkid_idmag *mag __attribute__((__unused__))) 240 { 241 struct ext2_super_block *es; 242 uint32_t fc, frc, fi; 243 244 es = ext_get_super(pr, &fc, &fi, &frc); 245 if (!es) 246 return errno ? -errno : 1; 247 248 /* ext3 requires journal */ 249 if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 250 return 1; 251 252 /* Any features which ext3 doesn't understand */ 253 if ((frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) || 254 (fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) 255 return 1; 256 257 ext_get_info(pr, 3, es); 258 return 0; 259 } 260 261 262 static int probe_ext4dev(blkid_probe pr, 263 const struct blkid_idmag *mag __attribute__((__unused__))) 264 { 265 struct ext2_super_block *es; 266 uint32_t fc, frc, fi; 267 268 es = ext_get_super(pr, &fc, &fi, &frc); 269 if (!es) 270 return errno ? -errno : 1; 271 272 /* Distinguish from jbd */ 273 if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) 274 return 1; 275 276 if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) 277 return 1; 278 279 ext_get_info(pr, 4, es); 280 return 0; 281 } 282 283 static int probe_ext4(blkid_probe pr, 284 const struct blkid_idmag *mag __attribute__((__unused__))) 285 { 286 struct ext2_super_block *es; 287 uint32_t fc, frc, fi; 288 289 es = ext_get_super(pr, &fc, &fi, &frc); 290 if (!es) 291 return errno ? -errno : 1; 292 293 /* Distinguish from jbd */ 294 if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) 295 return 1; 296 297 /* Ext4 has at least one feature which ext3 doesn't understand */ 298 if (!(frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) && 299 !(fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) 300 return 1; 301 302 /* 303 * If the filesystem is a OK for use by in-development 304 * filesystem code, and ext4dev is supported or ext4 is not 305 * supported, then don't call ourselves ext4, so we can redo 306 * the detection and mark the filesystem as ext4dev. 307 * 308 * If the filesystem is marked as in use by production 309 * filesystem, then it can only be used by ext4 and NOT by 310 * ext4dev. 311 */ 312 if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) 313 return 1; 314 315 ext_get_info(pr, 4, es); 316 return 0; 317 } 318 319 #define BLKID_EXT_MAGICS \ 320 { \ 321 { \ 322 .magic = EXT_SB_MAGIC, \ 323 .len = sizeof(EXT_SB_MAGIC) - 1, \ 324 .kboff = EXT_SB_KBOFF, \ 325 .sboff = EXT_MAG_OFF \ 326 }, \ 327 { NULL } \ 328 } 329 330 const struct blkid_idinfo jbd_idinfo = 331 { 332 .name = "jbd", 333 .usage = BLKID_USAGE_OTHER, 334 .probefunc = probe_jbd, 335 .magics = BLKID_EXT_MAGICS 336 }; 337 338 const struct blkid_idinfo ext2_idinfo = 339 { 340 .name = "ext2", 341 .usage = BLKID_USAGE_FILESYSTEM, 342 .probefunc = probe_ext2, 343 .magics = BLKID_EXT_MAGICS 344 }; 345 346 const struct blkid_idinfo ext3_idinfo = 347 { 348 .name = "ext3", 349 .usage = BLKID_USAGE_FILESYSTEM, 350 .probefunc = probe_ext3, 351 .magics = BLKID_EXT_MAGICS 352 }; 353 354 const struct blkid_idinfo ext4_idinfo = 355 { 356 .name = "ext4", 357 .usage = BLKID_USAGE_FILESYSTEM, 358 .probefunc = probe_ext4, 359 .magics = BLKID_EXT_MAGICS 360 }; 361 362 const struct blkid_idinfo ext4dev_idinfo = 363 { 364 .name = "ext4dev", 365 .usage = BLKID_USAGE_FILESYSTEM, 366 .probefunc = probe_ext4dev, 367 .magics = BLKID_EXT_MAGICS 368 }; 369 370
This page was automatically generated by LXR 0.3.1. • OpenWrt