probe.c revision 9e7da0bdc1f426f553b72721c769a8ffe3c536da
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 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> 9 * 10 * %Begin-Header% 11 * This file may be redistributed under the terms of the 12 * GNU Lesser General Public License. 13 * %End-Header% 14 */ 15 16#include <stdio.h> 17#include <string.h> 18#include <stdlib.h> 19#include <unistd.h> 20#include <fcntl.h> 21#include <ctype.h> 22#include <sys/types.h> 23#ifdef HAVE_SYS_STAT_H 24#include <sys/stat.h> 25#endif 26#ifdef HAVE_SYS_MKDEV_H 27#include <sys/mkdev.h> 28#endif 29#ifdef __linux__ 30#include <sys/utsname.h> 31#endif 32#ifdef HAVE_ERRNO_H 33#include <errno.h> 34#endif 35#include "blkidP.h" 36#include "uuid/uuid.h" 37#include "probe.h" 38 39static int figure_label_len(const unsigned char *label, int len) 40{ 41 const unsigned char *end = label + len - 1; 42 43 while ((*end == ' ' || *end == 0) && end >= label) 44 --end; 45 if (end >= label) { 46 label = label; 47 return end - label + 1; 48 } 49 return 0; 50} 51 52static unsigned char *get_buffer(struct blkid_probe *pr, 53 blkid_loff_t off, size_t len) 54{ 55 ssize_t ret_read; 56 unsigned char *newbuf; 57 58 if (off + len <= SB_BUFFER_SIZE) { 59 if (!pr->sbbuf) { 60 pr->sbbuf = malloc(SB_BUFFER_SIZE); 61 if (!pr->sbbuf) 62 return NULL; 63 if (lseek(pr->fd, 0, SEEK_SET) < 0) 64 return NULL; 65 ret_read = read(pr->fd, pr->sbbuf, SB_BUFFER_SIZE); 66 if (ret_read < 0) 67 ret_read = 0; 68 pr->sb_valid = ret_read; 69 } 70 if (off+len > pr->sb_valid) 71 return NULL; 72 return pr->sbbuf + off; 73 } else { 74 if (len > pr->buf_max) { 75 newbuf = realloc(pr->buf, len); 76 if (newbuf == NULL) 77 return NULL; 78 pr->buf = newbuf; 79 pr->buf_max = len; 80 } 81 if (blkid_llseek(pr->fd, off, SEEK_SET) < 0) 82 return NULL; 83 ret_read = read(pr->fd, pr->buf, len); 84 if (ret_read != (ssize_t) len) 85 return NULL; 86 return pr->buf; 87 } 88} 89 90 91/* 92 * This is a special case code to check for an MDRAID device. We do 93 * this special since it requires checking for a superblock at the end 94 * of the device. 95 */ 96static int check_mdraid(int fd, unsigned char *ret_uuid) 97{ 98 struct mdp_superblock_s *md; 99 blkid_loff_t offset; 100 char buf[4096]; 101 102 if (fd < 0) 103 return -BLKID_ERR_PARAM; 104 105 offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536; 106 107 if (blkid_llseek(fd, offset, 0) < 0 || 108 read(fd, buf, 4096) != 4096) 109 return -BLKID_ERR_IO; 110 111 /* Check for magic number */ 112 if (memcmp("\251+N\374", buf, 4) && memcmp("\374N+\251", buf, 4)) 113 return -BLKID_ERR_PARAM; 114 115 if (!ret_uuid) 116 return 0; 117 *ret_uuid = 0; 118 119 /* The MD UUID is not contiguous in the superblock, make it so */ 120 md = (struct mdp_superblock_s *)buf; 121 if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) { 122 memcpy(ret_uuid, &md->set_uuid0, 4); 123 memcpy(ret_uuid + 4, &md->set_uuid1, 12); 124 } 125 return 0; 126} 127 128static void set_uuid(blkid_dev dev, uuid_t uuid, const char *tag) 129{ 130 char str[37]; 131 132 if (!uuid_is_null(uuid)) { 133 uuid_unparse(uuid, str); 134 blkid_set_tag(dev, tag ? tag : "UUID", str, sizeof(str)); 135 } 136} 137 138static void get_ext2_info(blkid_dev dev, struct blkid_magic *id, 139 unsigned char *buf) 140{ 141 struct ext2_super_block *es = (struct ext2_super_block *) buf; 142 const char *label = 0; 143 144 DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n", 145 blkid_le32(es->s_feature_compat), 146 blkid_le32(es->s_feature_incompat), 147 blkid_le32(es->s_feature_ro_compat))); 148 149 if (strlen(es->s_volume_name)) 150 label = es->s_volume_name; 151 blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name)); 152 153 set_uuid(dev, es->s_uuid, 0); 154 155 if ((es->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && 156 !uuid_is_null(es->s_journal_uuid)) 157 set_uuid(dev, es->s_journal_uuid, "EXT_JOURNAL"); 158 159 if (strcmp(id->bim_type, "ext2") && 160 ((blkid_le32(es->s_feature_incompat) & 161 EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0)) 162 blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2")); 163} 164 165/* 166 * Check to see if a filesystem is in /proc/filesystems. 167 * Returns 1 if found, 0 if not 168 */ 169static int fs_proc_check(const char *fs_name) 170{ 171 FILE *f; 172 char buf[80], *cp, *t; 173 174 f = fopen("/proc/filesystems", "r"); 175 if (!f) 176 return (0); 177 while (!feof(f)) { 178 if (!fgets(buf, sizeof(buf), f)) 179 break; 180 cp = buf; 181 if (!isspace(*cp)) { 182 while (*cp && !isspace(*cp)) 183 cp++; 184 } 185 while (*cp && isspace(*cp)) 186 cp++; 187 if ((t = strchr(cp, '\n')) != NULL) 188 *t = 0; 189 if ((t = strchr(cp, '\t')) != NULL) 190 *t = 0; 191 if ((t = strchr(cp, ' ')) != NULL) 192 *t = 0; 193 if (!strcmp(fs_name, cp)) { 194 fclose(f); 195 return (1); 196 } 197 } 198 fclose(f); 199 return (0); 200} 201 202/* 203 * Check to see if a filesystem is available as a module 204 * Returns 1 if found, 0 if not 205 */ 206static int check_for_modules(const char *fs_name) 207{ 208#ifdef __linux__ 209 struct utsname uts; 210 FILE *f; 211 char buf[1024], *cp, *t; 212 int i; 213 214 if (uname(&uts)) 215 return (0); 216 snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release); 217 218 f = fopen(buf, "r"); 219 if (!f) 220 return (0); 221 while (!feof(f)) { 222 if (!fgets(buf, sizeof(buf), f)) 223 break; 224 if ((cp = strchr(buf, ':')) != NULL) 225 *cp = 0; 226 else 227 continue; 228 if ((cp = strrchr(buf, '/')) != NULL) 229 cp++; 230 i = strlen(cp); 231 if (i > 3) { 232 t = cp + i - 3; 233 if (!strcmp(t, ".ko")) 234 *t = 0; 235 } 236 if (!strcmp(cp, fs_name)) { 237 fclose(f); 238 return (1); 239 } 240 } 241 fclose(f); 242#endif 243 return (0); 244} 245 246static int system_supports_ext4(void) 247{ 248 static time_t last_check = 0; 249 static int ret = -1; 250 time_t now = time(0); 251 252 if (ret != -1 || (now - last_check) < 5) 253 return ret; 254 last_check = now; 255 ret = (fs_proc_check("ext4") || check_for_modules("ext4")); 256 return ret; 257} 258 259static int system_supports_ext4dev(void) 260{ 261 static time_t last_check = 0; 262 static int ret = -1; 263 time_t now = time(0); 264 265 if (ret != -1 || (now - last_check) < 5) 266 return ret; 267 last_check = now; 268 ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev")); 269 return ret; 270} 271 272static int probe_ext4dev(struct blkid_probe *probe, 273 struct blkid_magic *id, 274 unsigned char *buf) 275{ 276 struct ext2_super_block *es; 277 es = (struct ext2_super_block *)buf; 278 279 /* Distinguish from jbd */ 280 if (blkid_le32(es->s_feature_incompat) & 281 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) 282 return -BLKID_ERR_PARAM; 283 284 /* ext4dev requires a journal */ 285 if (!(blkid_le32(es->s_feature_compat) & 286 EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 287 return -BLKID_ERR_PARAM; 288 289 /* 290 * If the filesystem is marked as OK for use by in-development 291 * filesystem code, but ext4dev is not supported, and ext4 is, 292 * then don't call ourselves ext4dev, since we should be 293 * detected as ext4 in that case. 294 * 295 * If the filesystem is marked as in use by production 296 * filesystem, then it can only be used by ext4 and NOT by 297 * ext4dev, so always disclaim we are ext4dev in that case. 298 */ 299 if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) { 300 if (!system_supports_ext4dev() && system_supports_ext4()) 301 return -BLKID_ERR_PARAM; 302 } else 303 return -BLKID_ERR_PARAM; 304 305 get_ext2_info(probe->dev, id, buf); 306 return 0; 307} 308 309static int probe_ext4(struct blkid_probe *probe, struct blkid_magic *id, 310 unsigned char *buf) 311{ 312 struct ext2_super_block *es; 313 es = (struct ext2_super_block *)buf; 314 315 /* Distinguish from jbd */ 316 if (blkid_le32(es->s_feature_incompat) & 317 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) 318 return -BLKID_ERR_PARAM; 319 320 /* ext4 requires journal */ 321 if (!(blkid_le32(es->s_feature_compat) & 322 EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 323 return -BLKID_ERR_PARAM; 324 325 /* Ext4 has at least one feature which ext3 doesn't understand */ 326 if (!(blkid_le32(es->s_feature_ro_compat) & 327 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) && 328 !(blkid_le32(es->s_feature_incompat) & 329 EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) 330 return -BLKID_ERR_PARAM; 331 332 /* 333 * If the filesystem is a OK for use by in-development 334 * filesystem code, and ext4dev is supported or ext4 is not 335 * supported, then don't call ourselves ext4, so we can redo 336 * the detection and mark the filesystem as ext4dev. 337 * 338 * If the filesystem is marked as in use by production 339 * filesystem, then it can only be used by ext4 and NOT by 340 * ext4dev. 341 */ 342 if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) { 343 if (system_supports_ext4dev() || !system_supports_ext4()) 344 return -BLKID_ERR_PARAM; 345 } 346 get_ext2_info(probe->dev, id, buf); 347 return 0; 348} 349 350static int probe_ext3(struct blkid_probe *probe, struct blkid_magic *id, 351 unsigned char *buf) 352{ 353 struct ext2_super_block *es; 354 es = (struct ext2_super_block *)buf; 355 356 /* ext3 requires journal */ 357 if (!(blkid_le32(es->s_feature_compat) & 358 EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 359 return -BLKID_ERR_PARAM; 360 361 /* Any features which ext3 doesn't understand */ 362 if ((blkid_le32(es->s_feature_ro_compat) & 363 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) || 364 (blkid_le32(es->s_feature_incompat) & 365 EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) 366 return -BLKID_ERR_PARAM; 367 368 get_ext2_info(probe->dev, id, buf); 369 return 0; 370} 371 372static int probe_ext2(struct blkid_probe *probe, struct blkid_magic *id, 373 unsigned char *buf) 374{ 375 struct ext2_super_block *es; 376 377 es = (struct ext2_super_block *)buf; 378 379 /* Distinguish between ext3 and ext2 */ 380 if ((blkid_le32(es->s_feature_compat) & 381 EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 382 return -BLKID_ERR_PARAM; 383 384 /* Any features which ext2 doesn't understand */ 385 if ((blkid_le32(es->s_feature_ro_compat) & 386 EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) || 387 (blkid_le32(es->s_feature_incompat) & 388 EXT2_FEATURE_INCOMPAT_UNSUPPORTED)) 389 return -BLKID_ERR_PARAM; 390 391 get_ext2_info(probe->dev, id, buf); 392 return 0; 393} 394 395static int probe_jbd(struct blkid_probe *probe, struct blkid_magic *id, 396 unsigned char *buf) 397{ 398 struct ext2_super_block *es = (struct ext2_super_block *) buf; 399 400 if (!(blkid_le32(es->s_feature_incompat) & 401 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) 402 return -BLKID_ERR_PARAM; 403 404 get_ext2_info(probe->dev, id, buf); 405 406 return 0; 407} 408 409#define FAT_ATTR_VOLUME_ID 0x08 410#define FAT_ATTR_DIR 0x10 411#define FAT_ATTR_LONG_NAME 0x0f 412#define FAT_ATTR_MASK 0x3f 413#define FAT_ENTRY_FREE 0xe5 414 415static const char *no_name = "NO NAME "; 416 417static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count) 418{ 419 int i; 420 421 for (i = 0; i < count; i++) { 422 if (dir[i].name[0] == 0x00) 423 break; 424 425 if ((dir[i].name[0] == FAT_ENTRY_FREE) || 426 (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) || 427 ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)) 428 continue; 429 430 if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == 431 FAT_ATTR_VOLUME_ID) { 432 return dir[i].name; 433 } 434 } 435 return 0; 436} 437 438/* FAT label extraction from the root directory taken from Kay 439 * Sievers's volume_id library */ 440static int probe_fat(struct blkid_probe *probe, 441 struct blkid_magic *id __BLKID_ATTR((unused)), 442 unsigned char *buf) 443{ 444 struct vfat_super_block *vs = (struct vfat_super_block *) buf; 445 struct msdos_super_block *ms = (struct msdos_super_block *) buf; 446 struct vfat_dir_entry *dir; 447 char serno[10]; 448 const unsigned char *label = 0, *vol_label = 0, *tmp; 449 unsigned char *vol_serno; 450 int label_len = 0, maxloop = 100; 451 __u16 sector_size, dir_entries, reserved; 452 __u32 sect_count, fat_size, dir_size, cluster_count, fat_length; 453 __u32 buf_size, start_data_sect, next, root_start, root_dir_entries; 454 455 /* sector size check */ 456 tmp = (unsigned char *)&ms->ms_sector_size; 457 sector_size = tmp[0] + (tmp[1] << 8); 458 if (sector_size != 0x200 && sector_size != 0x400 && 459 sector_size != 0x800 && sector_size != 0x1000) 460 return 1; 461 462 tmp = (unsigned char *)&ms->ms_dir_entries; 463 dir_entries = tmp[0] + (tmp[1] << 8); 464 reserved = blkid_le16(ms->ms_reserved); 465 tmp = (unsigned char *)&ms->ms_sectors; 466 sect_count = tmp[0] + (tmp[1] << 8); 467 if (sect_count == 0) 468 sect_count = blkid_le32(ms->ms_total_sect); 469 470 fat_length = blkid_le16(ms->ms_fat_length); 471 if (fat_length == 0) 472 fat_length = blkid_le32(vs->vs_fat32_length); 473 474 fat_size = fat_length * ms->ms_fats; 475 dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) + 476 (sector_size-1)) / sector_size; 477 478 cluster_count = sect_count - (reserved + fat_size + dir_size); 479 if (ms->ms_cluster_size == 0) 480 return 1; 481 cluster_count /= ms->ms_cluster_size; 482 483 if (cluster_count > FAT32_MAX) 484 return 1; 485 486 if (ms->ms_fat_length) { 487 /* the label may be an attribute in the root directory */ 488 root_start = (reserved + fat_size) * sector_size; 489 root_dir_entries = vs->vs_dir_entries[0] + 490 (vs->vs_dir_entries[1] << 8); 491 492 buf_size = root_dir_entries * sizeof(struct vfat_dir_entry); 493 dir = (struct vfat_dir_entry *) get_buffer(probe, root_start, 494 buf_size); 495 if (dir) 496 vol_label = search_fat_label(dir, root_dir_entries); 497 498 if (!vol_label || !memcmp(vol_label, no_name, 11)) 499 vol_label = ms->ms_label; 500 vol_serno = ms->ms_serno; 501 502 blkid_set_tag(probe->dev, "SEC_TYPE", "msdos", 503 sizeof("msdos")); 504 } else { 505 /* Search the FAT32 root dir for the label attribute */ 506 buf_size = vs->vs_cluster_size * sector_size; 507 start_data_sect = reserved + fat_size; 508 509 next = blkid_le32(vs->vs_root_cluster); 510 while (next && --maxloop) { 511 __u32 next_sect_off; 512 __u64 next_off, fat_entry_off; 513 int count; 514 515 next_sect_off = (next - 2) * vs->vs_cluster_size; 516 next_off = (start_data_sect + next_sect_off) * 517 sector_size; 518 519 dir = (struct vfat_dir_entry *) 520 get_buffer(probe, next_off, buf_size); 521 if (dir == NULL) 522 break; 523 524 count = buf_size / sizeof(struct vfat_dir_entry); 525 526 vol_label = search_fat_label(dir, count); 527 if (vol_label) 528 break; 529 530 /* get FAT entry */ 531 fat_entry_off = (reserved * sector_size) + 532 (next * sizeof(__u32)); 533 buf = get_buffer(probe, fat_entry_off, buf_size); 534 if (buf == NULL) 535 break; 536 537 /* set next cluster */ 538 next = blkid_le32(*((__u32 *) buf) & 0x0fffffff); 539 } 540 541 if (!vol_label || !memcmp(vol_label, no_name, 11)) 542 vol_label = vs->vs_label; 543 vol_serno = vs->vs_serno; 544 } 545 546 if (vol_label && memcmp(vol_label, no_name, 11)) { 547 if ((label_len = figure_label_len(vol_label, 11))) 548 label = vol_label; 549 } 550 551 /* We can't just print them as %04X, because they are unaligned */ 552 sprintf(serno, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2], 553 vol_serno[1], vol_serno[0]); 554 555 blkid_set_tag(probe->dev, "LABEL", (const char *) label, label_len); 556 blkid_set_tag(probe->dev, "UUID", serno, sizeof(serno)-1); 557 558 return 0; 559} 560 561/* 562 * The FAT filesystem could be without a magic string in superblock 563 * (e.g. old floppies). This heuristic for FAT detection is inspired 564 * by http://vrfy.org/projects/volume_id/ and Linux kernel. 565 * [7-Jul-2005, Karel Zak <kzak@redhat.com>] 566 */ 567static int probe_fat_nomagic(struct blkid_probe *probe, 568 struct blkid_magic *id __BLKID_ATTR((unused)), 569 unsigned char *buf) 570{ 571 struct msdos_super_block *ms; 572 573 ms = (struct msdos_super_block *)buf; 574 575 /* heads check */ 576 if (ms->ms_heads == 0) 577 return 1; 578 579 /* cluster size check*/ 580 if (ms->ms_cluster_size == 0 || 581 (ms->ms_cluster_size & (ms->ms_cluster_size-1))) 582 return 1; 583 584 /* media check */ 585 if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0) 586 return 1; 587 588 /* fat counts(Linux kernel expects at least 1 FAT table) */ 589 if (!ms->ms_fats) 590 return 1; 591 592 /* 593 * OS/2 and apparently DFSee will place a FAT12/16-like 594 * pseudo-superblock in the first 512 bytes of non-FAT 595 * filesystems --- at least JFS and HPFS, and possibly others. 596 * So we explicitly check for those filesystems at the 597 * FAT12/16 filesystem magic field identifier, and if they are 598 * present, we rule this out as a FAT filesystem, despite the 599 * FAT-like pseudo-header. 600 */ 601 if ((memcmp(ms->ms_magic, "JFS ", 8) == 0) || 602 (memcmp(ms->ms_magic, "HPFS ", 8) == 0)) 603 return 1; 604 605 return probe_fat(probe, id, buf); 606} 607 608static int probe_ntfs(struct blkid_probe *probe, 609 struct blkid_magic *id __BLKID_ATTR((unused)), 610 unsigned char *buf) 611{ 612 struct ntfs_super_block *ns; 613 struct master_file_table_record *mft; 614 struct file_attribute *attr; 615 char uuid_str[17], label_str[129], *cp; 616 int bytes_per_sector, sectors_per_cluster; 617 int mft_record_size, attr_off, attr_len; 618 unsigned int i, attr_type, val_len; 619 int val_off; 620 __u64 nr_clusters; 621 blkid_loff_t off; 622 unsigned char *buf_mft, *val; 623 624 ns = (struct ntfs_super_block *) buf; 625 626 bytes_per_sector = ns->bios_parameter_block[0] + 627 (ns->bios_parameter_block[1] << 8); 628 sectors_per_cluster = ns->bios_parameter_block[2]; 629 630 if ((bytes_per_sector < 512) || (sectors_per_cluster == 0)) 631 return 1; 632 633 if (ns->cluster_per_mft_record < 0) 634 mft_record_size = 1 << (0-ns->cluster_per_mft_record); 635 else 636 mft_record_size = ns->cluster_per_mft_record * 637 sectors_per_cluster * bytes_per_sector; 638 nr_clusters = blkid_le64(ns->number_of_sectors) / sectors_per_cluster; 639 640 if ((blkid_le64(ns->mft_cluster_location) > nr_clusters) || 641 (blkid_le64(ns->mft_mirror_cluster_location) > nr_clusters)) 642 return 1; 643 644 off = blkid_le64(ns->mft_mirror_cluster_location) * 645 bytes_per_sector * sectors_per_cluster; 646 647 buf_mft = get_buffer(probe, off, mft_record_size); 648 if (!buf_mft) 649 return 1; 650 651 if (memcmp(buf_mft, "FILE", 4)) 652 return 1; 653 654 off = blkid_le64(ns->mft_cluster_location) * bytes_per_sector * 655 sectors_per_cluster; 656 657 buf_mft = get_buffer(probe, off, mft_record_size); 658 if (!buf_mft) 659 return 1; 660 661 if (memcmp(buf_mft, "FILE", 4)) 662 return 1; 663 664 off += MFT_RECORD_VOLUME * mft_record_size; 665 666 buf_mft = get_buffer(probe, off, mft_record_size); 667 if (!buf_mft) 668 return 1; 669 670 if (memcmp(buf_mft, "FILE", 4)) 671 return 1; 672 673 mft = (struct master_file_table_record *) buf_mft; 674 675 attr_off = blkid_le16(mft->attrs_offset); 676 label_str[0] = 0; 677 678 while (1) { 679 attr = (struct file_attribute *) (buf_mft + attr_off); 680 attr_len = blkid_le16(attr->len); 681 attr_type = blkid_le32(attr->type); 682 val_off = blkid_le16(attr->value_offset); 683 val_len = blkid_le32(attr->value_len); 684 685 attr_off += attr_len; 686 687 if ((attr_off > mft_record_size) || 688 (attr_len == 0)) 689 break; 690 691 if (attr_type == MFT_RECORD_ATTR_END) 692 break; 693 694 if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) { 695 if (val_len > sizeof(label_str)) 696 val_len = sizeof(label_str)-1; 697 698 for (i=0, cp=label_str; i < val_len; i+=2,cp++) { 699 val = ((__u8 *) attr) + val_off + i; 700 *cp = val[0]; 701 if (val[1]) 702 *cp = '?'; 703 } 704 *cp = 0; 705 } 706 } 707 708 sprintf(uuid_str, "%016llX", blkid_le64(ns->volume_serial)); 709 blkid_set_tag(probe->dev, "UUID", uuid_str, 0); 710 if (label_str[0]) 711 blkid_set_tag(probe->dev, "LABEL", label_str, 0); 712 return 0; 713} 714 715 716static int probe_xfs(struct blkid_probe *probe, 717 struct blkid_magic *id __BLKID_ATTR((unused)), 718 unsigned char *buf) 719{ 720 struct xfs_super_block *xs; 721 const char *label = 0; 722 723 xs = (struct xfs_super_block *)buf; 724 725 if (strlen(xs->xs_fname)) 726 label = xs->xs_fname; 727 blkid_set_tag(probe->dev, "LABEL", label, sizeof(xs->xs_fname)); 728 set_uuid(probe->dev, xs->xs_uuid, 0); 729 return 0; 730} 731 732static int probe_reiserfs(struct blkid_probe *probe, 733 struct blkid_magic *id, unsigned char *buf) 734{ 735 struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf; 736 unsigned int blocksize; 737 const char *label = 0; 738 739 blocksize = blkid_le16(rs->rs_blocksize); 740 741 /* The blocksize must be at least 1k */ 742 if ((blocksize >> 10) == 0) 743 return -BLKID_ERR_PARAM; 744 745 /* If the superblock is inside the journal, we have the wrong one */ 746 if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block)) 747 return -BLKID_ERR_BIG; 748 749 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ 750 if (id->bim_magic[6] == '2' || id->bim_magic[6] == '3') { 751 if (strlen(rs->rs_label)) 752 label = rs->rs_label; 753 set_uuid(probe->dev, rs->rs_uuid, 0); 754 } 755 blkid_set_tag(probe->dev, "LABEL", label, sizeof(rs->rs_label)); 756 757 return 0; 758} 759 760static int probe_reiserfs4(struct blkid_probe *probe, 761 struct blkid_magic *id __BLKID_ATTR((unused)), 762 unsigned char *buf) 763{ 764 struct reiser4_super_block *rs4 = (struct reiser4_super_block *) buf; 765 const unsigned char *label = 0; 766 767 if (strlen((char *) rs4->rs4_label)) 768 label = rs4->rs4_label; 769 set_uuid(probe->dev, rs4->rs4_uuid, 0); 770 blkid_set_tag(probe->dev, "LABEL", (const char *) label, 771 sizeof(rs4->rs4_label)); 772 773 return 0; 774} 775 776static int probe_jfs(struct blkid_probe *probe, 777 struct blkid_magic *id __BLKID_ATTR((unused)), 778 unsigned char *buf) 779{ 780 struct jfs_super_block *js; 781 const char *label = 0; 782 783 js = (struct jfs_super_block *)buf; 784 785 if (blkid_le32(js->js_bsize) != (1 << blkid_le16(js->js_l2bsize))) 786 return 1; 787 788 if (blkid_le32(js->js_pbsize) != (1 << blkid_le16(js->js_l2pbsize))) 789 return 1; 790 791 if ((blkid_le16(js->js_l2bsize) - blkid_le16(js->js_l2pbsize)) != 792 blkid_le16(js->js_l2bfactor)) 793 return 1; 794 795 if (strlen((char *) js->js_label)) 796 label = (char *) js->js_label; 797 blkid_set_tag(probe->dev, "LABEL", label, sizeof(js->js_label)); 798 set_uuid(probe->dev, js->js_uuid, 0); 799 return 0; 800} 801 802static int probe_zfs(struct blkid_probe *probe, struct blkid_magic *id, 803 unsigned char *buf) 804{ 805#if 0 806 char *vdev_label; 807 const char *pool_name = 0; 808 809 /* read nvpair data for pool name, pool GUID (complex) */ 810 blkid_set_tag(probe->dev, "LABEL", pool_name, sizeof(pool_name)); 811 set_uuid(probe->dev, pool_guid, 0); 812#endif 813 return 0; 814} 815 816static int probe_luks(struct blkid_probe *probe, 817 struct blkid_magic *id __BLKID_ATTR((unused)), 818 unsigned char *buf) 819{ 820 char uuid[40]; 821 822 /* 168 is the offset to the 40 character uuid: 823 * http://luks.endorphin.org/LUKS-on-disk-format.pdf */ 824 strncpy(uuid, (char *) buf+168, 40); 825 blkid_set_tag(probe->dev, "UUID", uuid, sizeof(uuid)); 826 return 0; 827} 828 829static int probe_romfs(struct blkid_probe *probe, 830 struct blkid_magic *id __BLKID_ATTR((unused)), 831 unsigned char *buf) 832{ 833 struct romfs_super_block *ros; 834 const char *label = 0; 835 836 ros = (struct romfs_super_block *)buf; 837 838 if (strlen((char *) ros->ros_volume)) 839 label = (char *) ros->ros_volume; 840 blkid_set_tag(probe->dev, "LABEL", label, 0); 841 return 0; 842} 843 844static int probe_cramfs(struct blkid_probe *probe, 845 struct blkid_magic *id __BLKID_ATTR((unused)), 846 unsigned char *buf) 847{ 848 struct cramfs_super_block *csb; 849 const char *label = 0; 850 851 csb = (struct cramfs_super_block *)buf; 852 853 if (strlen((char *) csb->name)) 854 label = (char *) csb->name; 855 blkid_set_tag(probe->dev, "LABEL", label, 0); 856 return 0; 857} 858 859static int probe_swap0(struct blkid_probe *probe, 860 struct blkid_magic *id __BLKID_ATTR((unused)), 861 unsigned char *buf __BLKID_ATTR((unused))) 862{ 863 blkid_set_tag(probe->dev, "UUID", 0, 0); 864 blkid_set_tag(probe->dev, "LABEL", 0, 0); 865 return 0; 866} 867 868static int probe_swap1(struct blkid_probe *probe, 869 struct blkid_magic *id, 870 unsigned char *buf __BLKID_ATTR((unused))) 871{ 872 struct swap_id_block *sws; 873 874 probe_swap0(probe, id, buf); 875 /* 876 * Version 1 swap headers are always located at offset of 1024 877 * bytes, although the swap signature itself is located at the 878 * end of the page (which may vary depending on hardware 879 * pagesize). 880 */ 881 sws = (struct swap_id_block *) get_buffer(probe, 1024, 1024); 882 if (!sws) 883 return 1; 884 885 /* check for wrong version or zeroed pagecount, for sanity */ 886 if (!memcmp(id->bim_magic, "SWAPSPACE2", id->bim_len) && 887 (sws->sws_version != 1 || sws->sws_lastpage == 0)) 888 return 1; 889 890 /* arbitrary sanity check.. is there any garbage down there? */ 891 if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) { 892 if (sws->sws_volume[0]) 893 blkid_set_tag(probe->dev, "LABEL", sws->sws_volume, 894 sizeof(sws->sws_volume)); 895 if (sws->sws_uuid[0]) 896 set_uuid(probe->dev, sws->sws_uuid, 0); 897 } 898 return 0; 899} 900 901static int probe_iso9660(struct blkid_probe *probe, 902 struct blkid_magic *id __BLKID_ATTR((unused)), 903 unsigned char *buf) 904{ 905 struct iso_volume_descriptor *iso; 906 const unsigned char *label; 907 908 iso = (struct iso_volume_descriptor *) buf; 909 label = iso->volume_id; 910 911 blkid_set_tag(probe->dev, "LABEL", (const char *) label, 912 figure_label_len(label, 32)); 913 return 0; 914} 915 916 917static const char 918*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", 919 "NSR03", "TEA01", 0 }; 920 921static int probe_udf(struct blkid_probe *probe, 922 struct blkid_magic *id __BLKID_ATTR((unused)), 923 unsigned char *buf __BLKID_ATTR((unused))) 924{ 925 int j, bs; 926 struct iso_volume_descriptor *isosb; 927 const char ** m; 928 929 /* determine the block size by scanning in 2K increments 930 (block sizes larger than 2K will be null padded) */ 931 for (bs = 1; bs < 16; bs++) { 932 isosb = (struct iso_volume_descriptor *) 933 get_buffer(probe, bs*2048+32768, sizeof(isosb)); 934 if (!isosb) 935 return 1; 936 if (isosb->vd_id[0]) 937 break; 938 } 939 940 /* Scan up to another 64 blocks looking for additional VSD's */ 941 for (j = 1; j < 64; j++) { 942 if (j > 1) { 943 isosb = (struct iso_volume_descriptor *) 944 get_buffer(probe, j*bs*2048+32768, 945 sizeof(isosb)); 946 if (!isosb) 947 return 1; 948 } 949 /* If we find NSR0x then call it udf: 950 NSR01 for UDF 1.00 951 NSR02 for UDF 1.50 952 NSR03 for UDF 2.00 */ 953 if (!memcmp(isosb->vd_id, "NSR0", 4)) 954 return probe_iso9660(probe, id, buf); 955 for (m = udf_magic; *m; m++) 956 if (!memcmp(*m, isosb->vd_id, 5)) 957 break; 958 if (*m == 0) 959 return 1; 960 } 961 return 1; 962} 963 964static int probe_ocfs(struct blkid_probe *probe, 965 struct blkid_magic *id __BLKID_ATTR((unused)), 966 unsigned char *buf) 967{ 968 struct ocfs_volume_header ovh; 969 struct ocfs_volume_label ovl; 970 __u32 major; 971 972 memcpy(&ovh, buf, sizeof(ovh)); 973 memcpy(&ovl, buf+512, sizeof(ovl)); 974 975 major = ocfsmajor(ovh); 976 if (major == 1) 977 blkid_set_tag(probe->dev,"SEC_TYPE","ocfs1",sizeof("ocfs1")); 978 else if (major >= 9) 979 blkid_set_tag(probe->dev,"SEC_TYPE","ntocfs",sizeof("ntocfs")); 980 981 blkid_set_tag(probe->dev, "LABEL", ovl.label, ocfslabellen(ovl)); 982 blkid_set_tag(probe->dev, "MOUNT", ovh.mount, ocfsmountlen(ovh)); 983 set_uuid(probe->dev, ovl.vol_id, 0); 984 return 0; 985} 986 987static int probe_ocfs2(struct blkid_probe *probe, 988 struct blkid_magic *id __BLKID_ATTR((unused)), 989 unsigned char *buf) 990{ 991 struct ocfs2_super_block *osb; 992 993 osb = (struct ocfs2_super_block *)buf; 994 995 blkid_set_tag(probe->dev, "LABEL", osb->s_label, sizeof(osb->s_label)); 996 set_uuid(probe->dev, osb->s_uuid, 0); 997 return 0; 998} 999 1000static int probe_oracleasm(struct blkid_probe *probe, 1001 struct blkid_magic *id __BLKID_ATTR((unused)), 1002 unsigned char *buf) 1003{ 1004 struct oracle_asm_disk_label *dl; 1005 1006 dl = (struct oracle_asm_disk_label *)buf; 1007 1008 blkid_set_tag(probe->dev, "LABEL", dl->dl_id, sizeof(dl->dl_id)); 1009 return 0; 1010} 1011 1012static int probe_gfs(struct blkid_probe *probe, 1013 struct blkid_magic *id __BLKID_ATTR((unused)), 1014 unsigned char *buf) 1015{ 1016 struct gfs2_sb *sbd; 1017 const char *label = 0; 1018 1019 sbd = (struct gfs2_sb *)buf; 1020 1021 if (blkid_be32(sbd->sb_fs_format) == GFS_FORMAT_FS && 1022 blkid_be32(sbd->sb_multihost_format) == GFS_FORMAT_MULTI) 1023 { 1024 blkid_set_tag(probe->dev, "UUID", 0, 0); 1025 1026 if (strlen(sbd->sb_locktable)) 1027 label = sbd->sb_locktable; 1028 blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable)); 1029 return 0; 1030 } 1031 return 1; 1032} 1033 1034static int probe_gfs2(struct blkid_probe *probe, 1035 struct blkid_magic *id __BLKID_ATTR((unused)), 1036 unsigned char *buf) 1037{ 1038 struct gfs2_sb *sbd; 1039 const char *label = 0; 1040 1041 sbd = (struct gfs2_sb *)buf; 1042 1043 if (blkid_be32(sbd->sb_fs_format) == GFS2_FORMAT_FS && 1044 blkid_be32(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI) 1045 { 1046 blkid_set_tag(probe->dev, "UUID", 0, 0); 1047 1048 if (strlen(sbd->sb_locktable)) 1049 label = sbd->sb_locktable; 1050 blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable)); 1051 return 0; 1052 } 1053 return 1; 1054} 1055 1056static void unicode_16be_to_utf8(unsigned char *str, int out_len, 1057 const unsigned char *buf, int in_len) 1058{ 1059 int i, j; 1060 unsigned int c; 1061 1062 for (i = j = 0; i + 2 <= in_len; i += 2) { 1063 c = (buf[i] << 8) | buf[i+1]; 1064 if (c == 0) { 1065 str[j] = '\0'; 1066 break; 1067 } else if (c < 0x80) { 1068 if (j+1 >= out_len) 1069 break; 1070 str[j++] = (unsigned char) c; 1071 } else if (c < 0x800) { 1072 if (j+2 >= out_len) 1073 break; 1074 str[j++] = (unsigned char) (0xc0 | (c >> 6)); 1075 str[j++] = (unsigned char) (0x80 | (c & 0x3f)); 1076 } else { 1077 if (j+3 >= out_len) 1078 break; 1079 str[j++] = (unsigned char) (0xe0 | (c >> 12)); 1080 str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f)); 1081 str[j++] = (unsigned char) (0x80 | (c & 0x3f)); 1082 } 1083 } 1084 str[j] = '\0'; 1085} 1086 1087static int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)), 1088 struct blkid_magic *id __BLKID_ATTR((unused)), 1089 unsigned char *buf) 1090{ 1091 struct hfs_mdb *hfs = (struct hfs_mdb *) buf; 1092 char uuid_str[17]; 1093 __u64 uuid; 1094 1095 if ((memcmp(hfs->embed_sig, "H+", 2) == 0) || 1096 (memcmp(hfs->embed_sig, "HX", 2) == 0)) 1097 return 1; /* Not hfs, but an embedded HFS+ */ 1098 1099 uuid = blkid_le64(*((unsigned long long *) hfs->finder_info.id)); 1100 if (uuid) { 1101 sprintf(uuid_str, "%016llX", uuid); 1102 blkid_set_tag(probe->dev, "UUID", uuid_str, 0); 1103 } 1104 blkid_set_tag(probe->dev, "LABEL", hfs->label, hfs->label_len); 1105 return 0; 1106} 1107 1108 1109static int probe_hfsplus(struct blkid_probe *probe, 1110 struct blkid_magic *id, 1111 unsigned char *buf) 1112{ 1113 struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT]; 1114 struct hfsplus_bnode_descriptor *descr; 1115 struct hfsplus_bheader_record *bnode; 1116 struct hfsplus_catalog_key *key; 1117 struct hfsplus_vol_header *hfsplus; 1118 struct hfs_mdb *sbd = (struct hfs_mdb *) buf; 1119 unsigned int alloc_block_size; 1120 unsigned int alloc_first_block; 1121 unsigned int embed_first_block; 1122 unsigned int off = 0; 1123 unsigned int blocksize; 1124 unsigned int cat_block; 1125 unsigned int ext_block_start; 1126 unsigned int ext_block_count; 1127 unsigned int record_count; 1128 unsigned int leaf_node_head; 1129 unsigned int leaf_node_count; 1130 unsigned int leaf_node_size; 1131 unsigned int leaf_block; 1132 unsigned int label_len; 1133 int ext; 1134 __u64 leaf_off, uuid; 1135 char uuid_str[17], label[512]; 1136 1137 /* Check for a HFS+ volume embedded in a HFS volume */ 1138 if (memcmp(sbd->signature, "BD", 2) == 0) { 1139 if ((memcmp(sbd->embed_sig, "H+", 2) != 0) && 1140 (memcmp(sbd->embed_sig, "HX", 2) != 0)) 1141 /* This must be an HFS volume, so fail */ 1142 return 1; 1143 1144 alloc_block_size = blkid_be32(sbd->al_blk_size); 1145 alloc_first_block = blkid_be16(sbd->al_bl_st); 1146 embed_first_block = blkid_be16(sbd->embed_startblock); 1147 off = (alloc_first_block * 512) + 1148 (embed_first_block * alloc_block_size); 1149 buf = get_buffer(probe, off + (id->bim_kboff * 1024), 1150 sizeof(sbd)); 1151 if (!buf) 1152 return 1; 1153 1154 hfsplus = (struct hfsplus_vol_header *) buf; 1155 } 1156 1157 hfsplus = (struct hfsplus_vol_header *) buf; 1158 1159 if ((memcmp(hfsplus->signature, "H+", 2) != 0) && 1160 (memcmp(hfsplus->signature, "HX", 2) != 0)) 1161 return 1; 1162 1163 uuid = blkid_le64(*((unsigned long long *) hfsplus->finder_info.id)); 1164 if (uuid) { 1165 sprintf(uuid_str, "%016llX", uuid); 1166 blkid_set_tag(probe->dev, "UUID", uuid_str, 0); 1167 } 1168 1169 blocksize = blkid_be32(hfsplus->blocksize); 1170 memcpy(extents, hfsplus->cat_file.extents, sizeof(extents)); 1171 cat_block = blkid_be32(extents[0].start_block); 1172 1173 buf = get_buffer(probe, off + (cat_block * blocksize), 0x2000); 1174 if (!buf) 1175 return 0; 1176 1177 bnode = (struct hfsplus_bheader_record *) 1178 &buf[sizeof(struct hfsplus_bnode_descriptor)]; 1179 1180 leaf_node_head = blkid_be32(bnode->leaf_head); 1181 leaf_node_size = blkid_be16(bnode->node_size); 1182 leaf_node_count = blkid_be32(bnode->leaf_count); 1183 if (leaf_node_count == 0) 1184 return 0; 1185 1186 leaf_block = (leaf_node_head * leaf_node_size) / blocksize; 1187 1188 /* get physical location */ 1189 for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) { 1190 ext_block_start = blkid_be32(extents[ext].start_block); 1191 ext_block_count = blkid_be32(extents[ext].block_count); 1192 if (ext_block_count == 0) 1193 return 0; 1194 1195 /* this is our extent */ 1196 if (leaf_block < ext_block_count) 1197 break; 1198 1199 leaf_block -= ext_block_count; 1200 } 1201 if (ext == HFSPLUS_EXTENT_COUNT) 1202 return 0; 1203 1204 leaf_off = (ext_block_start + leaf_block) * blocksize; 1205 1206 buf = get_buffer(probe, off + leaf_off, leaf_node_size); 1207 if (!buf) 1208 return 0; 1209 1210 descr = (struct hfsplus_bnode_descriptor *) buf; 1211 record_count = blkid_be16(descr->num_recs); 1212 if (record_count == 0) 1213 return 0; 1214 1215 if (descr->type != HFS_NODE_LEAF) 1216 return 0; 1217 1218 key = (struct hfsplus_catalog_key *) 1219 &buf[sizeof(struct hfsplus_bnode_descriptor)]; 1220 1221 if (blkid_be32(key->parent_id) != HFSPLUS_POR_CNID) 1222 return 0; 1223 1224 label_len = blkid_be16(key->unicode_len) * 2; 1225 unicode_16be_to_utf8(label, sizeof(label), key->unicode, label_len); 1226 blkid_set_tag(probe->dev, "LABEL", label, 0); 1227 return 0; 1228} 1229 1230#define LVM2_LABEL_SIZE 512 1231static unsigned int lvm2_calc_crc(const void *buf, unsigned int size) 1232{ 1233 static const unsigned int crctab[] = { 1234 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 1235 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 1236 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 1237 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 1238 }; 1239 unsigned int i, crc = 0xf597a6cf; 1240 const __u8 *data = (const __u8 *) buf; 1241 1242 for (i = 0; i < size; i++) { 1243 crc ^= *data++; 1244 crc = (crc >> 4) ^ crctab[crc & 0xf]; 1245 crc = (crc >> 4) ^ crctab[crc & 0xf]; 1246 } 1247 return crc; 1248} 1249 1250static int probe_lvm2(struct blkid_probe *probe, 1251 struct blkid_magic *id, 1252 unsigned char *buf) 1253{ 1254 int sector = (id->bim_kboff) << 1; 1255 struct lvm2_pv_label_header *label= (struct lvm2_pv_label_header *)buf; 1256 char *p, *q, uuid[40]; 1257 unsigned int i, b; 1258 1259 /* buf is at 0k or 1k offset; find label inside */ 1260 if (memcmp(buf, "LABELONE", 8) == 0) { 1261 label = (struct lvm2_pv_label_header *)buf; 1262 } else if (memcmp(buf + 512, "LABELONE", 8) == 0) { 1263 label = (struct lvm2_pv_label_header *)(buf + 512); 1264 sector++; 1265 } else { 1266 return 1; 1267 } 1268 1269 if (blkid_le64(label->sector_xl) != (unsigned) sector) { 1270 DBG(DEBUG_PROBE, 1271 printf("LVM2: label for sector %llu found at sector %d\n", 1272 blkid_le64(label->sector_xl), sector)); 1273 return 1; 1274 } 1275 1276 if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE - 1277 ((char *)&label->offset_xl - (char *)label)) != 1278 blkid_le32(label->crc_xl)) { 1279 DBG(DEBUG_PROBE, 1280 printf("LVM2: label checksum incorrect at sector %d\n", 1281 sector)); 1282 return 1; 1283 } 1284 1285 for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i <= 32; 1286 i++, b <<= 1) { 1287 if (b & 0x4444440) 1288 *p++ = '-'; 1289 *p++ = *q++; 1290 } 1291 1292 blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6); 1293 1294 return 0; 1295} 1296/* 1297 * Various filesystem magics that we can check for. Note that kboff and 1298 * sboff are in kilobytes and bytes respectively. All magics are in 1299 * byte strings so we don't worry about endian issues. 1300 */ 1301static struct blkid_magic type_array[] = { 1302/* type kboff sboff len magic probe */ 1303 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm }, 1304 { "ntfs", 0, 3, 8, "NTFS ", probe_ntfs }, 1305 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd }, 1306 { "ext4dev", 1, 0x38, 2, "\123\357", probe_ext4dev }, 1307 { "ext4", 1, 0x38, 2, "\123\357", probe_ext4 }, 1308 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 }, 1309 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 }, 1310 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs }, 1311 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs }, 1312 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs }, 1313 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs }, 1314 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs }, 1315 { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4 }, 1316 { "gfs2", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs2 }, 1317 { "gfs", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs }, 1318 { "vfat", 0, 0x52, 5, "MSWIN", probe_fat }, 1319 { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat }, 1320 { "vfat", 0, 0x36, 5, "MSDOS", probe_fat }, 1321 { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat }, 1322 { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat }, 1323 { "vfat", 0, 0, 1, "\353", probe_fat_nomagic }, 1324 { "vfat", 0, 0, 1, "\351", probe_fat_nomagic }, 1325 { "vfat", 0, 0x1fe, 2, "\125\252", probe_fat_nomagic }, 1326 { "minix", 1, 0x10, 2, "\177\023", 0 }, 1327 { "minix", 1, 0x10, 2, "\217\023", 0 }, 1328 { "minix", 1, 0x10, 2, "\150\044", 0 }, 1329 { "minix", 1, 0x10, 2, "\170\044", 0 }, 1330 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 }, 1331 { "xfs", 0, 0, 4, "XFSB", probe_xfs }, 1332 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs }, 1333 { "bfs", 0, 0, 4, "\316\372\173\033", 0 }, 1334 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs }, 1335 { "qnx4", 0, 4, 6, "QNX4FS", 0 }, 1336 { "udf", 32, 1, 5, "BEA01", probe_udf }, 1337 { "udf", 32, 1, 5, "BOOT2", probe_udf }, 1338 { "udf", 32, 1, 5, "CD001", probe_udf }, 1339 { "udf", 32, 1, 5, "CDW02", probe_udf }, 1340 { "udf", 32, 1, 5, "NSR02", probe_udf }, 1341 { "udf", 32, 1, 5, "NSR03", probe_udf }, 1342 { "udf", 32, 1, 5, "TEA01", probe_udf }, 1343 { "iso9660", 32, 1, 5, "CD001", probe_iso9660 }, 1344 { "iso9660", 32, 9, 5, "CDROM", probe_iso9660 }, 1345 { "jfs", 32, 0, 4, "JFS1", probe_jfs }, 1346 { "zfs", 8, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", probe_zfs }, 1347 { "zfs", 8, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", probe_zfs }, 1348 { "zfs", 264, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", probe_zfs }, 1349 { "zfs", 264, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", probe_zfs }, 1350 { "hfsplus", 1, 0, 2, "BD", probe_hfsplus }, 1351 { "hfsplus", 1, 0, 2, "H+", probe_hfsplus }, 1352 { "hfsplus", 1, 0, 2, "HX", probe_hfsplus }, 1353 { "hfs", 1, 0, 2, "BD", probe_hfs }, 1354 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 }, 1355 { "hpfs", 8, 0, 4, "I\350\225\371", 0 }, 1356 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 }, 1357 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 }, 1358 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 }, 1359 { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1 }, 1360 { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1 }, 1361 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 }, 1362 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 }, 1363 { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1 }, 1364 { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1 }, 1365 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 }, 1366 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 }, 1367 { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1 }, 1368 { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1 }, 1369 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 }, 1370 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 }, 1371 { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1 }, 1372 { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1 }, 1373 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 }, 1374 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 }, 1375 { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1 }, 1376 { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1 }, 1377 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs }, 1378 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 }, 1379 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 }, 1380 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 }, 1381 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 }, 1382 { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks }, 1383 { "squashfs", 0, 0, 4, "sqsh", 0 }, 1384 { "squashfs", 0, 0, 4, "hsqs", 0 }, 1385 { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2 }, 1386 { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2 }, 1387 { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2 }, 1388 { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2 }, 1389 { NULL, 0, 0, 0, NULL, NULL } 1390}; 1391 1392/* 1393 * Verify that the data in dev is consistent with what is on the actual 1394 * block device (using the devname field only). Normally this will be 1395 * called when finding items in the cache, but for long running processes 1396 * is also desirable to revalidate an item before use. 1397 * 1398 * If we are unable to revalidate the data, we return the old data and 1399 * do not set the BLKID_BID_FL_VERIFIED flag on it. 1400 */ 1401blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev) 1402{ 1403 struct blkid_magic *id; 1404 struct blkid_probe probe; 1405 blkid_tag_iterate iter; 1406 unsigned char *buf; 1407 const char *type, *value; 1408 struct stat st; 1409 time_t diff, now; 1410 int idx; 1411 1412 if (!dev) 1413 return NULL; 1414 1415 now = time(0); 1416 diff = now - dev->bid_time; 1417 1418 if (stat(dev->bid_name, &st) < 0) { 1419 DBG(DEBUG_PROBE, 1420 printf("blkid_verify: error %s (%d) while " 1421 "trying to stat %s\n", strerror(errno), errno, 1422 dev->bid_name)); 1423 open_err: 1424 if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) { 1425 /* We don't have read permission, just return cache data. */ 1426 DBG(DEBUG_PROBE, printf("returning unverified data for %s\n", 1427 dev->bid_name)); 1428 return dev; 1429 } 1430 blkid_free_dev(dev); 1431 return NULL; 1432 } 1433 1434 if ((now >= dev->bid_time) && 1435 (st.st_mtime <= dev->bid_time) && 1436 ((diff < BLKID_PROBE_MIN) || 1437 (dev->bid_flags & BLKID_BID_FL_VERIFIED && 1438 diff < BLKID_PROBE_INTERVAL))) 1439 return dev; 1440 1441 DBG(DEBUG_PROBE, 1442 printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t" 1443 "time since last check %lu)\n", 1444 dev->bid_name, (unsigned long)dev->bid_time, 1445 (unsigned long)st.st_mtime, (unsigned long)diff)); 1446 1447 if ((probe.fd = open(dev->bid_name, O_RDONLY)) < 0) { 1448 DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while " 1449 "opening %s\n", strerror(errno), errno, 1450 dev->bid_name)); 1451 goto open_err; 1452 } 1453 1454 probe.cache = cache; 1455 probe.dev = dev; 1456 probe.sbbuf = 0; 1457 probe.buf = 0; 1458 probe.buf_max = 0; 1459 1460 /* 1461 * Iterate over the type array. If we already know the type, 1462 * then try that first. If it doesn't work, then blow away 1463 * the type information, and try again. 1464 * 1465 */ 1466try_again: 1467 type = 0; 1468 if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) { 1469 uuid_t uuid; 1470 1471 if (check_mdraid(probe.fd, uuid) == 0) { 1472 set_uuid(dev, uuid, 0); 1473 type = "mdraid"; 1474 goto found_type; 1475 } 1476 } 1477 for (id = type_array; id->bim_type; id++) { 1478 if (dev->bid_type && 1479 strcmp(id->bim_type, dev->bid_type)) 1480 continue; 1481 1482 idx = id->bim_kboff + (id->bim_sboff >> 10); 1483 buf = get_buffer(&probe, idx << 10, 1024); 1484 if (!buf) 1485 continue; 1486 1487 if (memcmp(id->bim_magic, buf + (id->bim_sboff & 0x3ff), 1488 id->bim_len)) 1489 continue; 1490 1491 if ((id->bim_probe == NULL) || 1492 (id->bim_probe(&probe, id, buf) == 0)) { 1493 type = id->bim_type; 1494 goto found_type; 1495 } 1496 } 1497 1498 if (!id->bim_type && dev->bid_type) { 1499 /* 1500 * Zap the device filesystem information and try again 1501 */ 1502 DBG(DEBUG_PROBE, 1503 printf("previous fs type %s not valid, " 1504 "trying full probe\n", dev->bid_type)); 1505 iter = blkid_tag_iterate_begin(dev); 1506 while (blkid_tag_next(iter, &type, &value) == 0) 1507 blkid_set_tag(dev, type, 0, 0); 1508 blkid_tag_iterate_end(iter); 1509 goto try_again; 1510 } 1511 1512 if (!dev->bid_type) { 1513 blkid_free_dev(dev); 1514 dev = 0; 1515 goto found_type; 1516 } 1517 1518found_type: 1519 if (dev && type) { 1520 dev->bid_devno = st.st_rdev; 1521 dev->bid_time = time(0); 1522 dev->bid_flags |= BLKID_BID_FL_VERIFIED; 1523 cache->bic_flags |= BLKID_BIC_FL_CHANGED; 1524 1525 blkid_set_tag(dev, "TYPE", type, 0); 1526 1527 DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n", 1528 dev->bid_name, (long long)st.st_rdev, type)); 1529 } 1530 1531 if (probe.sbbuf) 1532 free(probe.sbbuf); 1533 if (probe.buf) 1534 free(probe.buf); 1535 if (probe.fd >= 0) 1536 close(probe.fd); 1537 1538 return dev; 1539} 1540 1541int blkid_known_fstype(const char *fstype) 1542{ 1543 struct blkid_magic *id; 1544 1545 for (id = type_array; id->bim_type; id++) { 1546 if (strcmp(fstype, id->bim_type) == 0) 1547 return 1; 1548 } 1549 return 0; 1550} 1551 1552#ifdef TEST_PROGRAM 1553int main(int argc, char **argv) 1554{ 1555 blkid_dev dev; 1556 blkid_cache cache; 1557 int ret; 1558 1559 if (argc != 2) { 1560 fprintf(stderr, "Usage: %s device\n" 1561 "Probe a single device to determine type\n", argv[0]); 1562 exit(1); 1563 } 1564 if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) { 1565 fprintf(stderr, "%s: error creating cache (%d)\n", 1566 argv[0], ret); 1567 exit(1); 1568 } 1569 dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL); 1570 if (!dev) { 1571 printf("%s: %s has an unsupported type\n", argv[0], argv[1]); 1572 return (1); 1573 } 1574 printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)"); 1575 if (dev->bid_label) 1576 printf("LABEL='%s'\n", dev->bid_label); 1577 if (dev->bid_uuid) 1578 printf("UUID='%s'\n", dev->bid_uuid); 1579 1580 blkid_free_dev(dev); 1581 return (0); 1582} 1583#endif 1584