probe.c revision 05a6edf4fdf3beb93d22116cf4ec39d161ab2790
1/* 2 * probe.c - identify a block device by its contents, and return a dev 3 * struct with the details 4 * 5 * Copyright (C) 1999 by Andries Brouwer 6 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o 7 * Copyright (C) 2001 by Andreas Dilger 8 * 9 * %Begin-Header% 10 * This file may be redistributed under the terms of the 11 * GNU Lesser General Public License. 12 * %End-Header% 13 */ 14 15#include <stdio.h> 16#include <string.h> 17#include <stdlib.h> 18#include <unistd.h> 19#include <fcntl.h> 20#include <sys/types.h> 21#ifdef HAVE_SYS_STAT_H 22#include <sys/stat.h> 23#endif 24#ifdef HAVE_SYS_MKDEV_H 25#include <sys/mkdev.h> 26#endif 27#ifdef HAVE_ERRNO_H 28#include <errno.h> 29#endif 30#include "blkidP.h" 31#include "uuid/uuid.h" 32#include "probe.h" 33 34/* 35 * This is a special case code to check for an MDRAID device. We do 36 * this special since it requires checking for a superblock at the end 37 * of the device. 38 */ 39static int check_mdraid(int fd, unsigned char *ret_uuid) 40{ 41 struct mdp_superblock_s *md; 42 blkid_loff_t offset; 43 char buf[4096]; 44 45 if (fd < 0) 46 return -BLKID_ERR_PARAM; 47 48 offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; 49 50 if (blkid_llseek(fd, offset, 0) < 0 || 51 read(fd, buf, 4096) != 4096) 52 return -BLKID_ERR_IO; 53 54 /* Check for magic number */ 55 if (memcmp("\251+N\374", buf, 4)) 56 return -BLKID_ERR_PARAM; 57 58 if (!ret_uuid) 59 return 0; 60 *ret_uuid = 0; 61 62 /* The MD UUID is not contiguous in the superblock, make it so */ 63 md = (struct mdp_superblock_s *)buf; 64 if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { 65 memcpy(ret_uuid, &md->set_uuid0, 4); 66 memcpy(ret_uuid, &md->set_uuid1, 12); 67 } 68 return 0; 69} 70 71static void set_uuid(blkid_dev dev, uuid_t uuid) 72{ 73 char str[37]; 74 75 if (!uuid_is_null(uuid)) { 76 uuid_unparse(uuid, str); 77 blkid_set_tag(dev, "UUID", str, sizeof(str)); 78 } 79} 80 81static void get_ext2_info(blkid_dev dev, unsigned char *buf) 82{ 83 struct ext2_super_block *es = (struct ext2_super_block *) buf; 84 const char *label = 0; 85 86 DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", 87 blkid_le32(es->s_feature_compat), 88 blkid_le32(es->s_feature_incompat), 89 blkid_le32(es->s_feature_ro_compat))); 90 91 if (strlen(es->s_volume_name)) 92 label = es->s_volume_name; 93 blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); 94 95 set_uuid(dev, es->s_uuid); 96} 97 98static int probe_ext3(int fd __BLKID_ATTR((unused)), 99 blkid_cache cache __BLKID_ATTR((unused)), 100 blkid_dev dev, 101 struct blkid_magic *id __BLKID_ATTR((unused)), 102 unsigned char *buf) 103{ 104 struct ext2_super_block *es; 105 106 es = (struct ext2_super_block *)buf; 107 108 /* Distinguish between jbd and ext2/3 fs */ 109 if (blkid_le32(es->s_feature_incompat) & 110 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) 111 return -BLKID_ERR_PARAM; 112 113 /* Distinguish between ext3 and ext2 */ 114 if (!(blkid_le32(es->s_feature_compat) & 115 EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 116 return -BLKID_ERR_PARAM; 117 118 get_ext2_info(dev, buf); 119 120 blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2")); 121 122 return 0; 123} 124 125static int probe_ext2(int fd __BLKID_ATTR((unused)), 126 blkid_cache cache __BLKID_ATTR((unused)), 127 blkid_dev dev, 128 struct blkid_magic *id __BLKID_ATTR((unused)), 129 unsigned char *buf) 130{ 131 struct ext2_super_block *es; 132 133 es = (struct ext2_super_block *)buf; 134 135 /* Distinguish between jbd and ext2/3 fs */ 136 if (blkid_le32(es->s_feature_incompat) & 137 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) 138 return -BLKID_ERR_PARAM; 139 140 /* Distinguish between ext3 and ext2 */ 141 if ((blkid_le32(es->s_feature_compat) & 142 EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 143 return -BLKID_ERR_PARAM; 144 145 get_ext2_info(dev, buf); 146 147 return 0; 148} 149 150static int probe_jbd(int fd __BLKID_ATTR((unused)), 151 blkid_cache cache __BLKID_ATTR((unused)), 152 blkid_dev dev, 153 struct blkid_magic *id __BLKID_ATTR((unused)), 154 unsigned char *buf) 155{ 156 struct ext2_super_block *es = (struct ext2_super_block *) buf; 157 158 if (!(blkid_le32(es->s_feature_incompat) & 159 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) 160 return -BLKID_ERR_PARAM; 161 162 get_ext2_info(dev, buf); 163 164 return 0; 165} 166 167static int probe_vfat(int fd __BLKID_ATTR((unused)), 168 blkid_cache cache __BLKID_ATTR((unused)), 169 blkid_dev dev, 170 struct blkid_magic *id __BLKID_ATTR((unused)), 171 unsigned char *buf) 172{ 173 struct vfat_super_block *vs; 174 char serno[10]; 175 const char *label = 0; 176 int label_len = 0; 177 178 vs = (struct vfat_super_block *)buf; 179 180 if (strncmp(vs->vs_label, "NO NAME", 7)) { 181 char *end = vs->vs_label + sizeof(vs->vs_label) - 1; 182 183 while (*end == ' ' && end >= vs->vs_label) 184 --end; 185 if (end >= vs->vs_label) { 186 label = vs->vs_label; 187 label_len = end - vs->vs_label + 1; 188 } 189 } 190 191 /* We can't just print them as %04X, because they are unaligned */ 192 sprintf(serno, "%02X%02X-%02X%02X", vs->vs_serno[3], vs->vs_serno[2], 193 vs->vs_serno[1], vs->vs_serno[0]); 194 blkid_set_tag(dev, "LABEL", label, label_len); 195 blkid_set_tag(dev, "UUID", serno, sizeof(serno)); 196 197 return 0; 198} 199 200static int probe_msdos(int fd __BLKID_ATTR((unused)), 201 blkid_cache cache __BLKID_ATTR((unused)), 202 blkid_dev dev, 203 struct blkid_magic *id __BLKID_ATTR((unused)), 204 unsigned char *buf) 205{ 206 struct msdos_super_block *ms = (struct msdos_super_block *) buf; 207 char serno[10]; 208 const char *label = 0; 209 int label_len = 0; 210 211 if (strncmp(ms->ms_label, "NO NAME", 7)) { 212 char *end = ms->ms_label + sizeof(ms->ms_label) - 1; 213 214 while (*end == ' ' && end >= ms->ms_label) 215 --end; 216 if (end >= ms->ms_label) { 217 label = ms->ms_label; 218 label_len = end - ms->ms_label + 1; 219 } 220 } 221 222 /* We can't just print them as %04X, because they are unaligned */ 223 sprintf(serno, "%02X%02X-%02X%02X", ms->ms_serno[3], ms->ms_serno[2], 224 ms->ms_serno[1], ms->ms_serno[0]); 225 blkid_set_tag(dev, "UUID", serno, 0); 226 blkid_set_tag(dev, "LABEL", label, label_len); 227 blkid_set_tag(dev, "SEC_TYPE", "msdos", sizeof("msdos")); 228 229 return 0; 230} 231 232static int probe_xfs(int fd __BLKID_ATTR((unused)), 233 blkid_cache cache __BLKID_ATTR((unused)), 234 blkid_dev dev, 235 struct blkid_magic *id __BLKID_ATTR((unused)), 236 unsigned char *buf) 237{ 238 struct xfs_super_block *xs; 239 const char *label = 0; 240 241 xs = (struct xfs_super_block *)buf; 242 243 if (strlen(xs->xs_fname)) 244 label = xs->xs_fname; 245 blkid_set_tag(dev, "LABEL", label, sizeof(xs->xs_fname)); 246 set_uuid(dev, xs->xs_uuid); 247 return 0; 248} 249 250static int probe_reiserfs(int fd __BLKID_ATTR((unused)), 251 blkid_cache cache __BLKID_ATTR((unused)), 252 blkid_dev dev, 253 struct blkid_magic *id, unsigned char *buf) 254{ 255 struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; 256 unsigned int blocksize; 257 const char *label = 0; 258 259 blocksize = blkid_le16(rs->rs_blocksize); 260 261 /* If the superblock is inside the journal, we have the wrong one */ 262 if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) 263 return -BLKID_ERR_BIG; 264 265 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ 266 if (!strcmp(id->bim_magic, "ReIsEr2Fs") || 267 !strcmp(id->bim_magic, "ReIsEr3Fs")) { 268 if (strlen(rs->rs_label)) 269 label = rs->rs_label; 270 set_uuid(dev, rs->rs_uuid); 271 } 272 blkid_set_tag(dev, "LABEL", label, sizeof(rs->rs_label)); 273 274 return 0; 275} 276 277static int probe_jfs(int fd __BLKID_ATTR((unused)), 278 blkid_cache cache __BLKID_ATTR((unused)), 279 blkid_dev dev, 280 struct blkid_magic *id __BLKID_ATTR((unused)), 281 unsigned char *buf) 282{ 283 struct jfs_super_block *js; 284 const char *label = 0; 285 286 js = (struct jfs_super_block *)buf; 287 288 if (strlen((char *) js->js_label)) 289 label = (char *) js->js_label; 290 blkid_set_tag(dev, "LABEL", label, sizeof(js->js_label)); 291 set_uuid(dev, js->js_uuid); 292 return 0; 293} 294 295static int probe_romfs(int fd __BLKID_ATTR((unused)), 296 blkid_cache cache __BLKID_ATTR((unused)), 297 blkid_dev dev, 298 struct blkid_magic *id __BLKID_ATTR((unused)), 299 unsigned char *buf) 300{ 301 struct romfs_super_block *ros; 302 const char *label = 0; 303 304 ros = (struct romfs_super_block *)buf; 305 306 if (strlen((char *) ros->ros_volume)) 307 label = (char *) ros->ros_volume; 308 blkid_set_tag(dev, "LABEL", label, 0); 309 return 0; 310} 311 312static int probe_cramfs(int fd __BLKID_ATTR((unused)), 313 blkid_cache cache __BLKID_ATTR((unused)), 314 blkid_dev dev, 315 struct blkid_magic *id __BLKID_ATTR((unused)), 316 unsigned char *buf) 317{ 318 struct cramfs_super_block *csb; 319 const char *label = 0; 320 321 csb = (struct cramfs_super_block *)buf; 322 323 if (strlen((char *) csb->name)) 324 label = (char *) csb->name; 325 blkid_set_tag(dev, "LABEL", label, 0); 326 return 0; 327} 328 329static int probe_swap0(int fd __BLKID_ATTR((unused)), 330 blkid_cache cache __BLKID_ATTR((unused)), 331 blkid_dev dev, 332 struct blkid_magic *id __BLKID_ATTR((unused)), 333 unsigned char *buf __BLKID_ATTR((unused))) 334{ 335 blkid_set_tag(dev, "UUID", 0, 0); 336 blkid_set_tag(dev, "LABEL", 0, 0); 337 return 0; 338} 339 340static int probe_swap1(int fd, 341 blkid_cache cache __BLKID_ATTR((unused)), 342 blkid_dev dev, 343 struct blkid_magic *id __BLKID_ATTR((unused)), 344 unsigned char *buf __BLKID_ATTR((unused))) 345{ 346 struct swap_id_block *sws; 347 348 probe_swap0(fd, cache, dev, id, buf); 349 /* 350 * Version 1 swap headers are always located at offset of 1024 351 * bytes, although the swap signature itself is located at the 352 * end of the page (which may vary depending on hardware 353 * pagesize). 354 */ 355 if (lseek(fd, 1024, SEEK_SET) < 0) return 1; 356 if (!(sws = (struct swap_id_block *)malloc(1024))) return 1; 357 if (read(fd, sws, 1024) != 1024) { 358 free(sws); 359 return 1; 360 } 361 362 /* arbitrary sanity check.. is there any garbage down there? */ 363 if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) { 364 if (sws->sws_volume[0]) 365 blkid_set_tag(dev, "LABEL", sws->sws_volume, 366 sizeof(sws->sws_volume)); 367 if (sws->sws_uuid[0]) 368 set_uuid(dev, sws->sws_uuid); 369 } 370 free(sws); 371 372 return 0; 373} 374 375static const char 376*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", 377 "NSR03", "TEA01", 0 }; 378 379static int probe_udf(int fd, blkid_cache cache __BLKID_ATTR((unused)), 380 blkid_dev dev __BLKID_ATTR((unused)), 381 struct blkid_magic *id __BLKID_ATTR((unused)), 382 unsigned char *buf __BLKID_ATTR((unused))) 383{ 384 int j, bs; 385 struct iso_volume_descriptor isosb; 386 const char ** m; 387 388 /* determine the block size by scanning in 2K increments 389 (block sizes larger than 2K will be null padded) */ 390 for (bs = 1; bs < 16; bs++) { 391 lseek(fd, bs*2048+32768, SEEK_SET); 392 if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb)) 393 return 1; 394 if (isosb.id[0]) 395 break; 396 } 397 398 /* Scan up to another 64 blocks looking for additional VSD's */ 399 for (j = 1; j < 64; j++) { 400 if (j > 1) { 401 lseek(fd, j*bs*2048+32768, SEEK_SET); 402 if (read(fd, (char *)&isosb, sizeof(isosb)) 403 != sizeof(isosb)) 404 return 1; 405 } 406 /* If we find NSR0x then call it udf: 407 NSR01 for UDF 1.00 408 NSR02 for UDF 1.50 409 NSR03 for UDF 2.00 */ 410 if (!strncmp(isosb.id, "NSR0", 4)) 411 return 0; 412 for (m = udf_magic; *m; m++) 413 if (!strncmp(*m, isosb.id, 5)) 414 break; 415 if (*m == 0) 416 return 1; 417 } 418 return 1; 419} 420 421static int probe_ocfs(int fd __BLKID_ATTR((unused)), 422 blkid_cache cache __BLKID_ATTR((unused)), 423 blkid_dev dev, 424 struct blkid_magic *id __BLKID_ATTR((unused)), 425 unsigned char *buf) 426{ 427 struct ocfs_volume_header ovh; 428 struct ocfs_volume_label ovl; 429 __u32 major; 430 431 memcpy(&ovh, buf, sizeof(ovh)); 432 memcpy(&ovl, buf+512, sizeof(ovl)); 433 434 major = ocfsmajor(ovh); 435 if (major == 1) 436 blkid_set_tag(dev,"SEC_TYPE","ocfs1",sizeof("ocfs1")); 437 else if (major >= 9) 438 blkid_set_tag(dev,"SEC_TYPE","ntocfs",sizeof("ntocfs")); 439 440 blkid_set_tag(dev, "LABEL", ovl.label, ocfslabellen(ovl)); 441 blkid_set_tag(dev, "MOUNT", ovh.mount, ocfsmountlen(ovh)); 442 set_uuid(dev, ovl.vol_id); 443 return 0; 444} 445 446static int probe_ocfs2(int fd __BLKID_ATTR((unused)), 447 blkid_cache cache __BLKID_ATTR((unused)), 448 blkid_dev dev, 449 struct blkid_magic *id __BLKID_ATTR((unused)), 450 unsigned char *buf) 451{ 452 struct ocfs2_super_block *osb; 453 454 osb = (struct ocfs2_super_block *)buf; 455 456 blkid_set_tag(dev, "LABEL", osb->s_label, sizeof(osb->s_label)); 457 set_uuid(dev, osb->s_uuid); 458 return 0; 459} 460 461static int probe_oracleasm(int fd __BLKID_ATTR((unused)), 462 blkid_cache cache __BLKID_ATTR((unused)), 463 blkid_dev dev, 464 struct blkid_magic *id __BLKID_ATTR((unused)), 465 unsigned char *buf) 466{ 467 struct oracle_asm_disk_label *dl; 468 469 dl = (struct oracle_asm_disk_label *)buf; 470 471 blkid_set_tag(dev, "LABEL", dl->dl_id, sizeof(dl->dl_id)); 472 return 0; 473} 474 475/* 476 * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined 477 * in the type_array table below + bim_kbalign. 478 * 479 * When probing for a lot of magics, we handle everything in 1kB buffers so 480 * that we don't have to worry about reading each combination of block sizes. 481 */ 482#define BLKID_BLK_OFFS 64 /* currently reiserfs */ 483 484/* 485 * Various filesystem magics that we can check for. Note that kboff and 486 * sboff are in kilobytes and bytes respectively. All magics are in 487 * byte strings so we don't worry about endian issues. 488 */ 489static struct blkid_magic type_array[] = { 490/* type kboff sboff len magic probe */ 491 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm }, 492 { "ntfs", 0, 3, 8, "NTFS ", 0 }, 493 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, 494 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, 495 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, 496 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, 497 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, 498 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, 499 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, 500 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, 501 { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat }, 502 { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat }, 503 { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos }, 504 { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos }, 505 { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos }, 506 { "minix", 1, 0x10, 2, "\177\023", 0 }, 507 { "minix", 1, 0x10, 2, "\217\023", 0 }, 508 { "minix", 1, 0x10, 2, "\150\044", 0 }, 509 { "minix", 1, 0x10, 2, "\170\044", 0 }, 510 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, 511 { "xfs", 0, 0, 4, "XFSB", probe_xfs }, 512 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs }, 513 { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, 514 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs }, 515 { "qnx4", 0, 4, 6, "QNX4FS", 0 }, 516 { "udf", 32, 1, 5, "BEA01", probe_udf }, 517 { "udf", 32, 1, 5, "BOOT2", probe_udf }, 518 { "udf", 32, 1, 5, "CD001", probe_udf }, 519 { "udf", 32, 1, 5, "CDW02", probe_udf }, 520 { "udf", 32, 1, 5, "NSR02", probe_udf }, 521 { "udf", 32, 1, 5, "NSR03", probe_udf }, 522 { "udf", 32, 1, 5, "TEA01", probe_udf }, 523 { "iso9660", 32, 1, 5, "CD001", 0 }, 524 { "iso9660", 32, 9, 5, "CDROM", 0 }, 525 { "jfs", 32, 0, 4, "JFS1", probe_jfs }, 526 { "hfs", 1, 0, 2, "BD", 0 }, 527 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, 528 { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, 529 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, 530 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 }, 531 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 }, 532 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 }, 533 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 }, 534 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 }, 535 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 }, 536 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 }, 537 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 }, 538 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 }, 539 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 }, 540 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs }, 541 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 }, 542 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 }, 543 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 }, 544 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 }, 545 { NULL, 0, 0, 0, NULL, NULL } 546}; 547 548/* 549 * Verify that the data in dev is consistent with what is on the actual 550 * block device (using the devname field only). Normally this will be 551 * called when finding items in the cache, but for long running processes 552 * is also desirable to revalidate an item before use. 553 * 554 * If we are unable to revalidate the data, we return the old data and 555 * do not set the BLKID_BID_FL_VERIFIED flag on it. 556 */ 557blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) 558{ 559 struct blkid_magic *id; 560 unsigned char *bufs[BLKID_BLK_OFFS + 1], *buf; 561 const char *type; 562 struct stat st; 563 time_t diff, now; 564 int fd, idx; 565 566 if (!dev) 567 return NULL; 568 569 now = time(0); 570 diff = now - dev->bid_time; 571 572 if ((now < dev->bid_time) || 573 (diff < BLKID_PROBE_MIN) || 574 (dev->bid_flags & BLKID_BID_FL_VERIFIED && 575 diff < BLKID_PROBE_INTERVAL)) 576 return dev; 577 578 DBG(DEBUG_PROBE, 579 printf("need to revalidate %s (time since last check %lu)\n", 580 dev->bid_name, diff)); 581 582 if (((fd = open(dev->bid_name, O_RDONLY)) < 0) || 583 (fstat(fd, &st) < 0)) { 584 if (errno == ENXIO || errno == ENODEV || errno == ENOENT) { 585 blkid_free_dev(dev); 586 return NULL; 587 } 588 /* We don't have read permission, just return cache data. */ 589 DBG(DEBUG_PROBE, 590 printf("returning unverified data for %s\n", 591 dev->bid_name)); 592 return dev; 593 } 594 595 memset(bufs, 0, sizeof(bufs)); 596 597 /* 598 * Iterate over the type array. If we already know the type, 599 * then try that first. If it doesn't work, then blow away 600 * the type information, and try again. 601 * 602 */ 603try_again: 604 type = 0; 605 if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { 606 uuid_t uuid; 607 608 if (check_mdraid(fd, uuid) == 0) { 609 set_uuid(dev, uuid); 610 type = "mdraid"; 611 goto found_type; 612 } 613 } 614 for (id = type_array; id->bim_type; id++) { 615 if (dev->bid_type && 616 strcmp(id->bim_type, dev->bid_type)) 617 continue; 618 619 idx = id->bim_kboff + (id->bim_sboff >> 10); 620 if (idx > BLKID_BLK_OFFS || idx < 0) 621 continue; 622 buf = bufs[idx]; 623 if (!buf) { 624 if (lseek(fd, idx << 10, SEEK_SET) < 0) 625 continue; 626 627 if (!(buf = (unsigned char *)malloc(1024))) 628 continue; 629 630 if (read(fd, buf, 1024) != 1024) { 631 free(buf); 632 continue; 633 } 634 bufs[idx] = buf; 635 } 636 637 if (memcmp(id->bim_magic, buf + (id->bim_sboff&0x3ff), 638 id->bim_len)) 639 continue; 640 641 if ((id->bim_probe == NULL) || 642 (id->bim_probe(fd, cache, dev, id, buf) == 0)) { 643 type = id->bim_type; 644 goto found_type; 645 } 646 } 647 648 if (!id->bim_type && dev->bid_type) { 649 /* 650 * Zap the device filesystem type and try again 651 */ 652 blkid_set_tag(dev, "TYPE", 0, 0); 653 blkid_set_tag(dev, "SEC_TYPE", 0, 0); 654 blkid_set_tag(dev, "LABEL", 0, 0); 655 blkid_set_tag(dev, "UUID", 0, 0); 656 goto try_again; 657 } 658 659 if (!dev->bid_type) { 660 blkid_free_dev(dev); 661 return NULL; 662 } 663 664found_type: 665 if (dev && type) { 666 dev->bid_devno = st.st_rdev; 667 dev->bid_time = time(0); 668 dev->bid_flags |= BLKID_BID_FL_VERIFIED; 669 cache->bic_flags |= BLKID_BIC_FL_CHANGED; 670 671 blkid_set_tag(dev, "TYPE", type, 0); 672 673 DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n", 674 dev->bid_name, st.st_rdev, type)); 675 } 676 677 close(fd); 678 679 return dev; 680} 681 682int blkid_known_fstype(const char *fstype) 683{ 684 struct blkid_magic *id; 685 686 for (id = type_array; id->bim_type; id++) { 687 if (strcmp(fstype, id->bim_type) == 0) 688 return 1; 689 } 690 return 0; 691} 692 693#ifdef TEST_PROGRAM 694int main(int argc, char **argv) 695{ 696 blkid_dev dev; 697 blkid_cache cache; 698 int ret; 699 700 blkid_debug_mask = DEBUG_ALL; 701 if (argc != 2) { 702 fprintf(stderr, "Usage: %s device\n" 703 "Probe a single device to determine type\n", argv[0]); 704 exit(1); 705 } 706 if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { 707 fprintf(stderr, "%s: error creating cache (%d)\n", 708 argv[0], ret); 709 exit(1); 710 } 711 dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); 712 if (!dev) { 713 printf("%s: %s has an unsupported type\n", argv[0], argv[1]); 714 return (1); 715 } 716 printf("%s is type %s\n", argv[1], dev->bid_type ? 717 dev->bid_type : "(null)"); 718 if (dev->bid_label) 719 printf("\tlabel is '%s'\n", dev->bid_label); 720 if (dev->bid_uuid) 721 printf("\tuuid is %s\n", dev->bid_uuid); 722 723 blkid_free_dev(dev); 724 return (0); 725} 726#endif 727