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