2 * probe.c - identify a block device by its contents, and return a dev
3 * struct with the details
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>
11 * This file may be redistributed under the terms of the
12 * GNU Lesser General Public License.
22 #include <sys/types.h>
23 #ifdef HAVE_SYS_STAT_H
26 #ifdef HAVE_SYS_MKDEV_H
27 #include <sys/mkdev.h>
30 #include <sys/utsname.h>
36 #include "uuid/uuid.h"
39 extern int probe_exfat(struct blkid_probe *probe,
40 struct blkid_magic *id __BLKID_ATTR((unused)),
43 static int figure_label_len(const unsigned char *label, int len)
45 const unsigned char *end = label + len - 1;
47 while ((*end == ' ' || *end == 0) && end >= label)
51 return end - label + 1;
56 static unsigned char *get_buffer(struct blkid_probe *pr,
57 blkid_loff_t off, size_t len)
60 unsigned char *newbuf;
62 if (off + len <= SB_BUFFER_SIZE) {
64 pr->sbbuf = malloc(SB_BUFFER_SIZE);
67 if (lseek(pr->fd, 0, SEEK_SET) < 0)
69 ret_read = read(pr->fd, pr->sbbuf, SB_BUFFER_SIZE);
72 pr->sb_valid = ret_read;
74 if (off+len > pr->sb_valid)
76 return pr->sbbuf + off;
78 if (len > pr->buf_max) {
79 newbuf = realloc(pr->buf, len);
85 if (blkid_llseek(pr->fd, off, SEEK_SET) < 0)
87 ret_read = read(pr->fd, pr->buf, len);
88 if (ret_read != (ssize_t) len)
94 unsigned char *blkid_probe_get_buffer(struct blkid_probe *pr,
95 blkid_loff_t off, size_t len)
97 return get_buffer(pr, off, len);
101 * This is a special case code to check for an MDRAID device. We do
102 * this special since it requires checking for a superblock at the end
105 static int check_mdraid(int fd, unsigned char *ret_uuid)
107 struct mdp_superblock_s *md;
112 return -BLKID_ERR_PARAM;
114 offset = (blkid_get_dev_size(fd) & ~((blkid_loff_t)65535)) - 65536;
116 if (blkid_llseek(fd, offset, 0) < 0 ||
117 read(fd, buf, 4096) != 4096)
118 return -BLKID_ERR_IO;
120 /* Check for magic number */
121 if (memcmp("\251+N\374", buf, 4) && memcmp("\374N+\251", buf, 4))
122 return -BLKID_ERR_PARAM;
128 /* The MD UUID is not contiguous in the superblock, make it so */
129 md = (struct mdp_superblock_s *)buf;
130 if (md->set_uuid0 || md->set_uuid1 || md->set_uuid2 || md->set_uuid3) {
131 memcpy(ret_uuid, &md->set_uuid0, 4);
132 memcpy(ret_uuid + 4, &md->set_uuid1, 12);
137 static void set_uuid(blkid_dev dev, uuid_t uuid, const char *tag)
141 if (!uuid_is_null(uuid)) {
142 uuid_unparse(uuid, str);
143 blkid_set_tag(dev, tag ? tag : "UUID", str, sizeof(str));
147 static void get_ext2_info(blkid_dev dev, struct blkid_magic *id,
150 struct ext2_super_block *es = (struct ext2_super_block *) buf;
151 const char *label = 0;
153 DBG(DEBUG_PROBE, printf("ext2_sb.compat = %08X:%08X:%08X\n",
154 blkid_le32(es->s_feature_compat),
155 blkid_le32(es->s_feature_incompat),
156 blkid_le32(es->s_feature_ro_compat)));
158 if (strlen(es->s_volume_name))
159 label = es->s_volume_name;
160 blkid_set_tag(dev, "LABEL", label, sizeof(es->s_volume_name));
162 set_uuid(dev, es->s_uuid, 0);
164 if ((es->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
165 !uuid_is_null(es->s_journal_uuid))
166 set_uuid(dev, es->s_journal_uuid, "EXT_JOURNAL");
168 if (strcmp(id->bim_type, "ext2") &&
169 ((blkid_le32(es->s_feature_incompat) &
170 EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0))
171 blkid_set_tag(dev, "SEC_TYPE", "ext2", sizeof("ext2"));
175 * Check to see if a filesystem is in /proc/filesystems.
176 * Returns 1 if found, 0 if not
178 static int fs_proc_check(const char *fs_name)
181 char buf[80], *cp, *t;
183 f = fopen("/proc/filesystems", "r");
187 if (!fgets(buf, sizeof(buf), f))
191 while (*cp && !isspace(*cp))
194 while (*cp && isspace(*cp))
196 if ((t = strchr(cp, '\n')) != NULL)
198 if ((t = strchr(cp, '\t')) != NULL)
200 if ((t = strchr(cp, ' ')) != NULL)
202 if (!strcmp(fs_name, cp)) {
212 * Check to see if a filesystem is available as a module
213 * Returns 1 if found, 0 if not
215 static int check_for_modules(const char *fs_name)
225 snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
231 namesz = strlen(fs_name);
234 if (!fgets(buf, sizeof(buf), f))
236 if ((cp = strchr(buf, ':')) != NULL)
240 if ((cp = strrchr(buf, '/')) != NULL)
244 if (!strncmp(cp, fs_name, namesz) &&
245 (!strcmp(cp + namesz, ".ko") ||
246 !strcmp(cp + namesz, ".ko.gz"))) {
256 static int linux_version_code()
260 static version_code = -1;
261 int major, minor, rev;
265 if (version_code > 0)
272 major = strtol(cp, &endptr, 10);
273 if (cp == endptr || *endptr != '.')
276 minor = strtol(cp, &endptr, 10);
277 if (cp == endptr || *endptr != '.')
280 rev = strtol(cp, &endptr, 10);
283 version_code = (((major * 256) + minor) * 256) + rev;
290 #define EXT4_SUPPORTS_EXT2 (2 * 65536 + 6*256 + 29)
292 static int system_supports_ext2(void)
294 static time_t last_check = 0;
296 time_t now = time(0);
298 if (ret != -1 || (now - last_check) < 5)
301 ret = (fs_proc_check("ext2") || check_for_modules("ext2"));
305 static int system_supports_ext4(void)
307 static time_t last_check = 0;
309 time_t now = time(0);
311 if (ret != -1 || (now - last_check) < 5)
314 ret = (fs_proc_check("ext4") || check_for_modules("ext4"));
318 static int system_supports_ext4dev(void)
320 static time_t last_check = 0;
322 time_t now = time(0);
324 if (ret != -1 || (now - last_check) < 5)
327 ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev"));
331 static int probe_ext4dev(struct blkid_probe *probe,
332 struct blkid_magic *id,
335 struct ext2_super_block *es;
336 es = (struct ext2_super_block *)buf;
338 /* Distinguish from jbd */
339 if (blkid_le32(es->s_feature_incompat) &
340 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
341 return -BLKID_ERR_PARAM;
344 * If the filesystem does not have a journal and ext2 and ext4
345 * is not present, then force this to be detected as an
346 * ext4dev filesystem.
348 if (!(blkid_le32(es->s_feature_compat) &
349 EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
350 !system_supports_ext2() && !system_supports_ext4() &&
351 system_supports_ext4dev() &&
352 linux_version_code() >= EXT4_SUPPORTS_EXT2)
356 * If the filesystem is marked as OK for use by in-development
357 * filesystem code, but ext4dev is not supported, and ext4 is,
358 * then don't call ourselves ext4dev, since we should be
359 * detected as ext4 in that case.
361 * If the filesystem is marked as in use by production
362 * filesystem, then it can only be used by ext4 and NOT by
363 * ext4dev, so always disclaim we are ext4dev in that case.
365 if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
366 if (!system_supports_ext4dev() && system_supports_ext4())
367 return -BLKID_ERR_PARAM;
369 return -BLKID_ERR_PARAM;
372 get_ext2_info(probe->dev, id, buf);
376 static int probe_ext4(struct blkid_probe *probe, struct blkid_magic *id,
379 struct ext2_super_block *es;
380 es = (struct ext2_super_block *)buf;
382 /* Distinguish from jbd */
383 if (blkid_le32(es->s_feature_incompat) &
384 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
385 return -BLKID_ERR_PARAM;
388 * If the filesystem does not have a journal and ext2 is not
389 * present, then force this to be detected as an ext2
392 if (!(blkid_le32(es->s_feature_compat) &
393 EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
394 !system_supports_ext2() && system_supports_ext4() &&
395 linux_version_code() >= EXT4_SUPPORTS_EXT2)
398 /* Ext4 has at least one feature which ext3 doesn't understand */
399 if (!(blkid_le32(es->s_feature_ro_compat) &
400 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) &&
401 !(blkid_le32(es->s_feature_incompat) &
402 EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
403 return -BLKID_ERR_PARAM;
407 * If the filesystem is a OK for use by in-development
408 * filesystem code, and ext4dev is supported or ext4 is not
409 * supported, then don't call ourselves ext4, so we can redo
410 * the detection and mark the filesystem as ext4dev.
412 * If the filesystem is marked as in use by production
413 * filesystem, then it can only be used by ext4 and NOT by
416 if (blkid_le32(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) {
417 if (system_supports_ext4dev() || !system_supports_ext4())
418 return -BLKID_ERR_PARAM;
420 get_ext2_info(probe->dev, id, buf);
424 static int probe_ext3(struct blkid_probe *probe, struct blkid_magic *id,
427 struct ext2_super_block *es;
428 es = (struct ext2_super_block *)buf;
430 /* ext3 requires journal */
431 if (!(blkid_le32(es->s_feature_compat) &
432 EXT3_FEATURE_COMPAT_HAS_JOURNAL))
433 return -BLKID_ERR_PARAM;
435 /* Any features which ext3 doesn't understand */
436 if ((blkid_le32(es->s_feature_ro_compat) &
437 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) ||
438 (blkid_le32(es->s_feature_incompat) &
439 EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
440 return -BLKID_ERR_PARAM;
442 get_ext2_info(probe->dev, id, buf);
446 static int probe_ext2(struct blkid_probe *probe, struct blkid_magic *id,
449 struct ext2_super_block *es;
451 es = (struct ext2_super_block *)buf;
453 /* Distinguish between ext3 and ext2 */
454 if ((blkid_le32(es->s_feature_compat) &
455 EXT3_FEATURE_COMPAT_HAS_JOURNAL))
456 return -BLKID_ERR_PARAM;
458 /* Any features which ext2 doesn't understand */
459 if ((blkid_le32(es->s_feature_ro_compat) &
460 EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) ||
461 (blkid_le32(es->s_feature_incompat) &
462 EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
463 return -BLKID_ERR_PARAM;
466 * If ext2 is not present, but ext4 or ext4dev are, then
467 * disclaim we are ext2
469 if (!system_supports_ext2() &&
470 (system_supports_ext4() || system_supports_ext4dev()) &&
471 linux_version_code() >= EXT4_SUPPORTS_EXT2)
472 return -BLKID_ERR_PARAM;
474 get_ext2_info(probe->dev, id, buf);
478 static int probe_jbd(struct blkid_probe *probe, struct blkid_magic *id,
481 struct ext2_super_block *es = (struct ext2_super_block *) buf;
483 if (!(blkid_le32(es->s_feature_incompat) &
484 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
485 return -BLKID_ERR_PARAM;
487 get_ext2_info(probe->dev, id, buf);
492 #define FAT_ATTR_VOLUME_ID 0x08
493 #define FAT_ATTR_DIR 0x10
494 #define FAT_ATTR_LONG_NAME 0x0f
495 #define FAT_ATTR_MASK 0x3f
496 #define FAT_ENTRY_FREE 0xe5
498 static const char *no_name = "NO NAME ";
500 static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count)
504 for (i = 0; i < count; i++) {
505 if (dir[i].name[0] == 0x00)
508 if ((dir[i].name[0] == FAT_ENTRY_FREE) ||
509 (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) ||
510 ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
513 if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
514 FAT_ATTR_VOLUME_ID) {
521 /* FAT label extraction from the root directory taken from Kay
522 * Sievers's volume_id library */
523 static int probe_fat(struct blkid_probe *probe,
524 struct blkid_magic *id __BLKID_ATTR((unused)),
527 struct vfat_super_block *vs = (struct vfat_super_block *) buf;
528 struct msdos_super_block *ms = (struct msdos_super_block *) buf;
529 struct vfat_dir_entry *dir;
531 const unsigned char *label = 0, *vol_label = 0, *tmp;
532 unsigned char *vol_serno;
533 int label_len = 0, maxloop = 100;
534 __u16 sector_size, dir_entries, reserved;
535 __u32 sect_count, fat_size, dir_size, cluster_count, fat_length;
536 __u32 buf_size, start_data_sect, next, root_start, root_dir_entries;
538 /* sector size check */
539 tmp = (unsigned char *)&ms->ms_sector_size;
540 sector_size = tmp[0] + (tmp[1] << 8);
541 if (sector_size != 0x200 && sector_size != 0x400 &&
542 sector_size != 0x800 && sector_size != 0x1000)
545 tmp = (unsigned char *)&ms->ms_dir_entries;
546 dir_entries = tmp[0] + (tmp[1] << 8);
547 reserved = blkid_le16(ms->ms_reserved);
548 tmp = (unsigned char *)&ms->ms_sectors;
549 sect_count = tmp[0] + (tmp[1] << 8);
551 sect_count = blkid_le32(ms->ms_total_sect);
553 fat_length = blkid_le16(ms->ms_fat_length);
555 fat_length = blkid_le32(vs->vs_fat32_length);
557 fat_size = fat_length * ms->ms_fats;
558 dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
559 (sector_size-1)) / sector_size;
561 cluster_count = sect_count - (reserved + fat_size + dir_size);
562 if (ms->ms_cluster_size == 0)
564 cluster_count /= ms->ms_cluster_size;
566 if (cluster_count > FAT32_MAX)
569 if (ms->ms_fat_length) {
570 /* the label may be an attribute in the root directory */
571 root_start = (reserved + fat_size) * sector_size;
572 root_dir_entries = vs->vs_dir_entries[0] +
573 (vs->vs_dir_entries[1] << 8);
575 buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
576 dir = (struct vfat_dir_entry *) get_buffer(probe, root_start,
579 vol_label = search_fat_label(dir, root_dir_entries);
581 if (!vol_label || !memcmp(vol_label, no_name, 11))
582 vol_label = ms->ms_label;
583 vol_serno = ms->ms_serno;
585 blkid_set_tag(probe->dev, "SEC_TYPE", "msdos",
588 /* Search the FAT32 root dir for the label attribute */
589 buf_size = vs->vs_cluster_size * sector_size;
590 start_data_sect = reserved + fat_size;
592 next = blkid_le32(vs->vs_root_cluster);
593 while (next && --maxloop) {
595 __u64 next_off, fat_entry_off;
598 next_sect_off = (next - 2) * vs->vs_cluster_size;
599 next_off = (start_data_sect + next_sect_off) *
602 dir = (struct vfat_dir_entry *)
603 get_buffer(probe, next_off, buf_size);
607 count = buf_size / sizeof(struct vfat_dir_entry);
609 vol_label = search_fat_label(dir, count);
614 fat_entry_off = (reserved * sector_size) +
615 (next * sizeof(__u32));
616 buf = get_buffer(probe, fat_entry_off, buf_size);
620 /* set next cluster */
621 next = blkid_le32(*((__u32 *) buf) & 0x0fffffff);
624 if (!vol_label || !memcmp(vol_label, no_name, 11))
625 vol_label = vs->vs_label;
626 vol_serno = vs->vs_serno;
629 if (vol_label && memcmp(vol_label, no_name, 11)) {
630 if ((label_len = figure_label_len(vol_label, 11)))
634 /* We can't just print them as %04X, because they are unaligned */
635 sprintf(serno, "%02X%02X-%02X%02X", vol_serno[3], vol_serno[2],
636 vol_serno[1], vol_serno[0]);
638 blkid_set_tag(probe->dev, "LABEL", (const char *) label, label_len);
639 blkid_set_tag(probe->dev, "UUID", serno, sizeof(serno)-1);
645 * The FAT filesystem could be without a magic string in superblock
646 * (e.g. old floppies). This heuristic for FAT detection is inspired
647 * by http://vrfy.org/projects/volume_id/ and Linux kernel.
648 * [7-Jul-2005, Karel Zak <kzak@redhat.com>]
650 static int probe_fat_nomagic(struct blkid_probe *probe,
651 struct blkid_magic *id __BLKID_ATTR((unused)),
654 struct msdos_super_block *ms;
656 ms = (struct msdos_super_block *)buf;
659 if (ms->ms_heads == 0)
662 /* cluster size check*/
663 if (ms->ms_cluster_size == 0 ||
664 (ms->ms_cluster_size & (ms->ms_cluster_size-1)))
668 if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0)
671 /* fat counts(Linux kernel expects at least 1 FAT table) */
676 * OS/2 and apparently DFSee will place a FAT12/16-like
677 * pseudo-superblock in the first 512 bytes of non-FAT
678 * filesystems --- at least JFS and HPFS, and possibly others.
679 * So we explicitly check for those filesystems at the
680 * FAT12/16 filesystem magic field identifier, and if they are
681 * present, we rule this out as a FAT filesystem, despite the
682 * FAT-like pseudo-header.
684 if ((memcmp(ms->ms_magic, "JFS ", 8) == 0) ||
685 (memcmp(ms->ms_magic, "HPFS ", 8) == 0))
688 return probe_fat(probe, id, buf);
691 static int probe_ntfs(struct blkid_probe *probe,
692 struct blkid_magic *id __BLKID_ATTR((unused)),
695 struct ntfs_super_block *ns;
696 struct master_file_table_record *mft;
697 struct file_attribute *attr;
698 char uuid_str[17], label_str[129], *cp;
699 int bytes_per_sector, sectors_per_cluster;
700 int mft_record_size, attr_off, attr_len;
701 unsigned int i, attr_type, val_len;
705 unsigned char *buf_mft, *val;
707 ns = (struct ntfs_super_block *) buf;
709 bytes_per_sector = ns->bios_parameter_block[0] +
710 (ns->bios_parameter_block[1] << 8);
711 sectors_per_cluster = ns->bios_parameter_block[2];
713 if ((bytes_per_sector < 512) || (sectors_per_cluster == 0))
716 if (ns->cluster_per_mft_record < 0)
717 mft_record_size = 1 << (0-ns->cluster_per_mft_record);
719 mft_record_size = ns->cluster_per_mft_record *
720 sectors_per_cluster * bytes_per_sector;
721 nr_clusters = blkid_le64(ns->number_of_sectors) / sectors_per_cluster;
723 if ((blkid_le64(ns->mft_cluster_location) > nr_clusters) ||
724 (blkid_le64(ns->mft_mirror_cluster_location) > nr_clusters))
727 off = blkid_le64(ns->mft_mirror_cluster_location) *
728 bytes_per_sector * sectors_per_cluster;
730 buf_mft = get_buffer(probe, off, mft_record_size);
734 if (memcmp(buf_mft, "FILE", 4))
737 off = blkid_le64(ns->mft_cluster_location) * bytes_per_sector *
740 buf_mft = get_buffer(probe, off, mft_record_size);
744 if (memcmp(buf_mft, "FILE", 4))
747 off += MFT_RECORD_VOLUME * mft_record_size;
749 buf_mft = get_buffer(probe, off, mft_record_size);
753 if (memcmp(buf_mft, "FILE", 4))
756 mft = (struct master_file_table_record *) buf_mft;
758 attr_off = blkid_le16(mft->attrs_offset);
762 attr = (struct file_attribute *) (buf_mft + attr_off);
763 attr_len = blkid_le16(attr->len);
764 attr_type = blkid_le32(attr->type);
765 val_off = blkid_le16(attr->value_offset);
766 val_len = blkid_le32(attr->value_len);
768 attr_off += attr_len;
770 if ((attr_off > mft_record_size) ||
774 if (attr_type == MFT_RECORD_ATTR_END)
777 if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
778 if (val_len > sizeof(label_str))
779 val_len = sizeof(label_str)-1;
781 for (i=0, cp=label_str; i < val_len; i+=2,cp++) {
782 val = ((__u8 *) attr) + val_off + i;
791 sprintf(uuid_str, "%016llX", blkid_le64(ns->volume_serial));
792 blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
794 blkid_set_tag(probe->dev, "LABEL", label_str, 0);
799 static int probe_xfs(struct blkid_probe *probe,
800 struct blkid_magic *id __BLKID_ATTR((unused)),
803 struct xfs_super_block *xs;
804 const char *label = 0;
806 xs = (struct xfs_super_block *)buf;
808 if (strlen(xs->xs_fname))
809 label = xs->xs_fname;
810 blkid_set_tag(probe->dev, "LABEL", label, sizeof(xs->xs_fname));
811 set_uuid(probe->dev, xs->xs_uuid, 0);
815 static int probe_reiserfs(struct blkid_probe *probe,
816 struct blkid_magic *id, unsigned char *buf)
818 struct reiserfs_super_block *rs = (struct reiserfs_super_block *) buf;
819 unsigned int blocksize;
820 const char *label = 0;
822 blocksize = blkid_le16(rs->rs_blocksize);
824 /* The blocksize must be at least 1k */
825 if ((blocksize >> 10) == 0)
826 return -BLKID_ERR_PARAM;
828 /* If the superblock is inside the journal, we have the wrong one */
829 if (id->bim_kboff/(blocksize>>10) > blkid_le32(rs->rs_journal_block))
830 return -BLKID_ERR_BIG;
832 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
833 if (id->bim_magic[6] == '2' || id->bim_magic[6] == '3') {
834 if (strlen(rs->rs_label))
835 label = rs->rs_label;
836 set_uuid(probe->dev, rs->rs_uuid, 0);
838 blkid_set_tag(probe->dev, "LABEL", label, sizeof(rs->rs_label));
843 static int probe_reiserfs4(struct blkid_probe *probe,
844 struct blkid_magic *id __BLKID_ATTR((unused)),
847 struct reiser4_super_block *rs4 = (struct reiser4_super_block *) buf;
848 const unsigned char *label = 0;
850 if (strlen((char *) rs4->rs4_label))
851 label = rs4->rs4_label;
852 set_uuid(probe->dev, rs4->rs4_uuid, 0);
853 blkid_set_tag(probe->dev, "LABEL", (const char *) label,
854 sizeof(rs4->rs4_label));
859 static int probe_jfs(struct blkid_probe *probe,
860 struct blkid_magic *id __BLKID_ATTR((unused)),
863 struct jfs_super_block *js;
864 const char *label = 0;
866 js = (struct jfs_super_block *)buf;
868 if (blkid_le32(js->js_bsize) != (1 << blkid_le16(js->js_l2bsize)))
871 if (blkid_le32(js->js_pbsize) != (1 << blkid_le16(js->js_l2pbsize)))
874 if ((blkid_le16(js->js_l2bsize) - blkid_le16(js->js_l2pbsize)) !=
875 blkid_le16(js->js_l2bfactor))
878 if (strlen((char *) js->js_label))
879 label = (char *) js->js_label;
880 blkid_set_tag(probe->dev, "LABEL", label, sizeof(js->js_label));
881 set_uuid(probe->dev, js->js_uuid, 0);
885 static int probe_zfs(struct blkid_probe *probe, struct blkid_magic *id,
890 const char *pool_name = 0;
892 /* read nvpair data for pool name, pool GUID (complex) */
893 blkid_set_tag(probe->dev, "LABEL", pool_name, sizeof(pool_name));
894 set_uuid(probe->dev, pool_guid, 0);
899 static int probe_luks(struct blkid_probe *probe,
900 struct blkid_magic *id __BLKID_ATTR((unused)),
905 /* 168 is the offset to the 40 character uuid:
906 * http://luks.endorphin.org/LUKS-on-disk-format.pdf */
907 strncpy(uuid, (char *) buf+168, 40);
908 blkid_set_tag(probe->dev, "UUID", uuid, sizeof(uuid));
912 static int probe_romfs(struct blkid_probe *probe,
913 struct blkid_magic *id __BLKID_ATTR((unused)),
916 struct romfs_super_block *ros;
917 const char *label = 0;
919 ros = (struct romfs_super_block *)buf;
921 if (strlen((char *) ros->ros_volume))
922 label = (char *) ros->ros_volume;
923 blkid_set_tag(probe->dev, "LABEL", label, 0);
927 static int probe_cramfs(struct blkid_probe *probe,
928 struct blkid_magic *id __BLKID_ATTR((unused)),
931 struct cramfs_super_block *csb;
932 const char *label = 0;
934 csb = (struct cramfs_super_block *)buf;
936 if (strlen((char *) csb->name))
937 label = (char *) csb->name;
938 blkid_set_tag(probe->dev, "LABEL", label, 0);
942 static int probe_swap0(struct blkid_probe *probe,
943 struct blkid_magic *id __BLKID_ATTR((unused)),
944 unsigned char *buf __BLKID_ATTR((unused)))
946 blkid_set_tag(probe->dev, "UUID", 0, 0);
947 blkid_set_tag(probe->dev, "LABEL", 0, 0);
951 static int probe_swap1(struct blkid_probe *probe,
952 struct blkid_magic *id,
953 unsigned char *buf __BLKID_ATTR((unused)))
955 struct swap_id_block *sws;
957 probe_swap0(probe, id, buf);
959 * Version 1 swap headers are always located at offset of 1024
960 * bytes, although the swap signature itself is located at the
961 * end of the page (which may vary depending on hardware
964 sws = (struct swap_id_block *) get_buffer(probe, 1024, 1024);
968 /* check for wrong version or zeroed pagecount, for sanity */
969 if (!memcmp(id->bim_magic, "SWAPSPACE2", id->bim_len) &&
970 (sws->sws_version != 1 || sws->sws_lastpage == 0))
973 /* arbitrary sanity check.. is there any garbage down there? */
974 if (sws->sws_pad[32] == 0 && sws->sws_pad[33] == 0) {
975 if (sws->sws_volume[0])
976 blkid_set_tag(probe->dev, "LABEL", sws->sws_volume,
977 sizeof(sws->sws_volume));
978 if (sws->sws_uuid[0])
979 set_uuid(probe->dev, sws->sws_uuid, 0);
984 static int probe_iso9660(struct blkid_probe *probe,
985 struct blkid_magic *id __BLKID_ATTR((unused)),
988 struct iso_volume_descriptor *iso;
989 const unsigned char *label;
991 iso = (struct iso_volume_descriptor *) buf;
992 label = iso->volume_id;
994 blkid_set_tag(probe->dev, "LABEL", (const char *) label,
995 figure_label_len(label, 32));
1001 *udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
1002 "NSR03", "TEA01", 0 };
1004 static int probe_udf(struct blkid_probe *probe,
1005 struct blkid_magic *id __BLKID_ATTR((unused)),
1006 unsigned char *buf __BLKID_ATTR((unused)))
1009 struct iso_volume_descriptor *isosb;
1012 /* determine the block size by scanning in 2K increments
1013 (block sizes larger than 2K will be null padded) */
1014 for (bs = 1; bs < 16; bs++) {
1015 isosb = (struct iso_volume_descriptor *)
1016 get_buffer(probe, bs*2048+32768, sizeof(isosb));
1019 if (isosb->vd_id[0])
1023 /* Scan up to another 64 blocks looking for additional VSD's */
1024 for (j = 1; j < 64; j++) {
1026 isosb = (struct iso_volume_descriptor *)
1027 get_buffer(probe, j*bs*2048+32768,
1032 /* If we find NSR0x then call it udf:
1035 NSR03 for UDF 2.00 */
1036 if (!memcmp(isosb->vd_id, "NSR0", 4))
1037 return probe_iso9660(probe, id, buf);
1038 for (m = udf_magic; *m; m++)
1039 if (!memcmp(*m, isosb->vd_id, 5))
1047 static int probe_ocfs(struct blkid_probe *probe,
1048 struct blkid_magic *id __BLKID_ATTR((unused)),
1051 struct ocfs_volume_header ovh;
1052 struct ocfs_volume_label ovl;
1055 memcpy(&ovh, buf, sizeof(ovh));
1056 memcpy(&ovl, buf+512, sizeof(ovl));
1058 major = ocfsmajor(ovh);
1060 blkid_set_tag(probe->dev,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
1061 else if (major >= 9)
1062 blkid_set_tag(probe->dev,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
1064 blkid_set_tag(probe->dev, "LABEL", ovl.label, ocfslabellen(ovl));
1065 blkid_set_tag(probe->dev, "MOUNT", ovh.mount, ocfsmountlen(ovh));
1066 set_uuid(probe->dev, ovl.vol_id, 0);
1070 static int probe_ocfs2(struct blkid_probe *probe,
1071 struct blkid_magic *id __BLKID_ATTR((unused)),
1074 struct ocfs2_super_block *osb;
1076 osb = (struct ocfs2_super_block *)buf;
1078 blkid_set_tag(probe->dev, "LABEL", osb->s_label, sizeof(osb->s_label));
1079 set_uuid(probe->dev, osb->s_uuid, 0);
1083 static int probe_oracleasm(struct blkid_probe *probe,
1084 struct blkid_magic *id __BLKID_ATTR((unused)),
1087 struct oracle_asm_disk_label *dl;
1089 dl = (struct oracle_asm_disk_label *)buf;
1091 blkid_set_tag(probe->dev, "LABEL", dl->dl_id, sizeof(dl->dl_id));
1095 static int probe_gfs(struct blkid_probe *probe,
1096 struct blkid_magic *id __BLKID_ATTR((unused)),
1099 struct gfs2_sb *sbd;
1100 const char *label = 0;
1102 sbd = (struct gfs2_sb *)buf;
1104 if (blkid_be32(sbd->sb_fs_format) == GFS_FORMAT_FS &&
1105 blkid_be32(sbd->sb_multihost_format) == GFS_FORMAT_MULTI)
1107 blkid_set_tag(probe->dev, "UUID", 0, 0);
1109 if (strlen(sbd->sb_locktable))
1110 label = sbd->sb_locktable;
1111 blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
1117 static int probe_gfs2(struct blkid_probe *probe,
1118 struct blkid_magic *id __BLKID_ATTR((unused)),
1121 struct gfs2_sb *sbd;
1122 const char *label = 0;
1124 sbd = (struct gfs2_sb *)buf;
1126 if (blkid_be32(sbd->sb_fs_format) == GFS2_FORMAT_FS &&
1127 blkid_be32(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI)
1129 blkid_set_tag(probe->dev, "UUID", 0, 0);
1131 if (strlen(sbd->sb_locktable))
1132 label = sbd->sb_locktable;
1133 blkid_set_tag(probe->dev, "LABEL", label, sizeof(sbd->sb_locktable));
1139 static void unicode_16be_to_utf8(unsigned char *str, int out_len,
1140 const unsigned char *buf, int in_len)
1145 for (i = j = 0; i + 2 <= in_len; i += 2) {
1146 c = (buf[i] << 8) | buf[i+1];
1150 } else if (c < 0x80) {
1153 str[j++] = (unsigned char) c;
1154 } else if (c < 0x800) {
1157 str[j++] = (unsigned char) (0xc0 | (c >> 6));
1158 str[j++] = (unsigned char) (0x80 | (c & 0x3f));
1162 str[j++] = (unsigned char) (0xe0 | (c >> 12));
1163 str[j++] = (unsigned char) (0x80 | ((c >> 6) & 0x3f));
1164 str[j++] = (unsigned char) (0x80 | (c & 0x3f));
1170 static int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)),
1171 struct blkid_magic *id __BLKID_ATTR((unused)),
1174 struct hfs_mdb *hfs = (struct hfs_mdb *) buf;
1178 if ((memcmp(hfs->embed_sig, "H+", 2) == 0) ||
1179 (memcmp(hfs->embed_sig, "HX", 2) == 0))
1180 return 1; /* Not hfs, but an embedded HFS+ */
1182 uuid = blkid_le64(*((unsigned long long *) hfs->finder_info.id));
1184 sprintf(uuid_str, "%016llX", uuid);
1185 blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
1187 blkid_set_tag(probe->dev, "LABEL", hfs->label, hfs->label_len);
1192 static int probe_hfsplus(struct blkid_probe *probe,
1193 struct blkid_magic *id,
1196 struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
1197 struct hfsplus_bnode_descriptor *descr;
1198 struct hfsplus_bheader_record *bnode;
1199 struct hfsplus_catalog_key *key;
1200 struct hfsplus_vol_header *hfsplus;
1201 struct hfs_mdb *sbd = (struct hfs_mdb *) buf;
1202 unsigned int alloc_block_size;
1203 unsigned int alloc_first_block;
1204 unsigned int embed_first_block;
1205 unsigned int off = 0;
1206 unsigned int blocksize;
1207 unsigned int cat_block;
1208 unsigned int ext_block_start;
1209 unsigned int ext_block_count;
1210 unsigned int record_count;
1211 unsigned int leaf_node_head;
1212 unsigned int leaf_node_count;
1213 unsigned int leaf_node_size;
1214 unsigned int leaf_block;
1215 unsigned int label_len;
1217 __u64 leaf_off, uuid;
1218 char uuid_str[17], label[512];
1220 /* Check for a HFS+ volume embedded in a HFS volume */
1221 if (memcmp(sbd->signature, "BD", 2) == 0) {
1222 if ((memcmp(sbd->embed_sig, "H+", 2) != 0) &&
1223 (memcmp(sbd->embed_sig, "HX", 2) != 0))
1224 /* This must be an HFS volume, so fail */
1227 alloc_block_size = blkid_be32(sbd->al_blk_size);
1228 alloc_first_block = blkid_be16(sbd->al_bl_st);
1229 embed_first_block = blkid_be16(sbd->embed_startblock);
1230 off = (alloc_first_block * 512) +
1231 (embed_first_block * alloc_block_size);
1232 buf = get_buffer(probe, off + (id->bim_kboff * 1024),
1237 hfsplus = (struct hfsplus_vol_header *) buf;
1240 hfsplus = (struct hfsplus_vol_header *) buf;
1242 if ((memcmp(hfsplus->signature, "H+", 2) != 0) &&
1243 (memcmp(hfsplus->signature, "HX", 2) != 0))
1246 uuid = blkid_le64(*((unsigned long long *) hfsplus->finder_info.id));
1248 sprintf(uuid_str, "%016llX", uuid);
1249 blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
1252 blocksize = blkid_be32(hfsplus->blocksize);
1253 memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
1254 cat_block = blkid_be32(extents[0].start_block);
1256 buf = get_buffer(probe, off + (cat_block * blocksize), 0x2000);
1260 bnode = (struct hfsplus_bheader_record *)
1261 &buf[sizeof(struct hfsplus_bnode_descriptor)];
1263 leaf_node_head = blkid_be32(bnode->leaf_head);
1264 leaf_node_size = blkid_be16(bnode->node_size);
1265 leaf_node_count = blkid_be32(bnode->leaf_count);
1266 if (leaf_node_count == 0)
1269 leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
1271 /* get physical location */
1272 for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
1273 ext_block_start = blkid_be32(extents[ext].start_block);
1274 ext_block_count = blkid_be32(extents[ext].block_count);
1275 if (ext_block_count == 0)
1278 /* this is our extent */
1279 if (leaf_block < ext_block_count)
1282 leaf_block -= ext_block_count;
1284 if (ext == HFSPLUS_EXTENT_COUNT)
1287 leaf_off = (ext_block_start + leaf_block) * blocksize;
1289 buf = get_buffer(probe, off + leaf_off, leaf_node_size);
1293 descr = (struct hfsplus_bnode_descriptor *) buf;
1294 record_count = blkid_be16(descr->num_recs);
1295 if (record_count == 0)
1298 if (descr->type != HFS_NODE_LEAF)
1301 key = (struct hfsplus_catalog_key *)
1302 &buf[sizeof(struct hfsplus_bnode_descriptor)];
1304 if (blkid_be32(key->parent_id) != HFSPLUS_POR_CNID)
1307 label_len = blkid_be16(key->unicode_len) * 2;
1308 unicode_16be_to_utf8(label, sizeof(label), key->unicode, label_len);
1309 blkid_set_tag(probe->dev, "LABEL", label, 0);
1313 #define LVM2_LABEL_SIZE 512
1314 static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
1316 static const unsigned int crctab[] = {
1317 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1318 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1319 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1320 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1322 unsigned int i, crc = 0xf597a6cf;
1323 const __u8 *data = (const __u8 *) buf;
1325 for (i = 0; i < size; i++) {
1327 crc = (crc >> 4) ^ crctab[crc & 0xf];
1328 crc = (crc >> 4) ^ crctab[crc & 0xf];
1333 static int probe_lvm2(struct blkid_probe *probe,
1334 struct blkid_magic *id,
1337 int sector = (id->bim_kboff) << 1;
1338 struct lvm2_pv_label_header *label= (struct lvm2_pv_label_header *)buf;
1339 char *p, *q, uuid[40];
1342 /* buf is at 0k or 1k offset; find label inside */
1343 if (memcmp(buf, "LABELONE", 8) == 0) {
1344 label = (struct lvm2_pv_label_header *)buf;
1345 } else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
1346 label = (struct lvm2_pv_label_header *)(buf + 512);
1352 if (blkid_le64(label->sector_xl) != (unsigned) sector) {
1354 printf("LVM2: label for sector %llu found at sector %d\n",
1355 blkid_le64(label->sector_xl), sector));
1359 if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
1360 ((char *)&label->offset_xl - (char *)label)) !=
1361 blkid_le32(label->crc_xl)) {
1363 printf("LVM2: label checksum incorrect at sector %d\n",
1368 for (i=0, b=1, p=uuid, q= (char *) label->pv_uuid; i <= 32;
1375 blkid_set_tag(probe->dev, "UUID", uuid, LVM2_ID_LEN+6);
1380 static int probe_btrfs(struct blkid_probe *probe,
1381 struct blkid_magic *id,
1384 struct btrfs_super_block *bs;
1385 const char *label = 0;
1387 bs = (struct btrfs_super_block *)buf;
1389 if (strlen(bs->label))
1391 blkid_set_tag(probe->dev, "LABEL", label, sizeof(bs->label));
1392 set_uuid(probe->dev, bs->fsid, 0);
1396 * Various filesystem magics that we can check for. Note that kboff and
1397 * sboff are in kilobytes and bytes respectively. All magics are in
1398 * byte strings so we don't worry about endian issues.
1400 static struct blkid_magic type_array[] = {
1401 /* type kboff sboff len magic probe */
1402 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm },
1403 { "ntfs", 0, 3, 8, "NTFS ", probe_ntfs },
1404 { "exfat", 0, 3, 8, "EXFAT ", probe_exfat },
1405 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd },
1406 { "ext4dev", 1, 0x38, 2, "\123\357", probe_ext4dev },
1407 { "ext4", 1, 0x38, 2, "\123\357", probe_ext4 },
1408 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3 },
1409 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2 },
1410 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs },
1411 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs },
1412 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs },
1413 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs },
1414 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs },
1415 { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4 },
1416 { "gfs2", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs2 },
1417 { "gfs", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs },
1418 { "vfat", 0, 0x52, 5, "MSWIN", probe_fat },
1419 { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat },
1420 { "vfat", 0, 0x36, 5, "MSDOS", probe_fat },
1421 { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat },
1422 { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat },
1423 { "vfat", 0, 0, 1, "\353", probe_fat_nomagic },
1424 { "vfat", 0, 0, 1, "\351", probe_fat_nomagic },
1425 { "vfat", 0, 0x1fe, 2, "\125\252", probe_fat_nomagic },
1426 { "minix", 1, 0x10, 2, "\177\023", 0 },
1427 { "minix", 1, 0x10, 2, "\217\023", 0 },
1428 { "minix", 1, 0x10, 2, "\150\044", 0 },
1429 { "minix", 1, 0x10, 2, "\170\044", 0 },
1430 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
1431 { "xfs", 0, 0, 4, "XFSB", probe_xfs },
1432 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs },
1433 { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
1434 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs },
1435 { "qnx4", 0, 4, 6, "QNX4FS", 0 },
1436 { "udf", 32, 1, 5, "BEA01", probe_udf },
1437 { "udf", 32, 1, 5, "BOOT2", probe_udf },
1438 { "udf", 32, 1, 5, "CD001", probe_udf },
1439 { "udf", 32, 1, 5, "CDW02", probe_udf },
1440 { "udf", 32, 1, 5, "NSR02", probe_udf },
1441 { "udf", 32, 1, 5, "NSR03", probe_udf },
1442 { "udf", 32, 1, 5, "TEA01", probe_udf },
1443 { "iso9660", 32, 1, 5, "CD001", probe_iso9660 },
1444 { "iso9660", 32, 9, 5, "CDROM", probe_iso9660 },
1445 { "jfs", 32, 0, 4, "JFS1", probe_jfs },
1446 { "zfs", 8, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", probe_zfs },
1447 { "zfs", 8, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", probe_zfs },
1448 { "zfs", 264, 0, 8, "\0\0\x02\xf5\xb0\x07\xb1\x0c", probe_zfs },
1449 { "zfs", 264, 0, 8, "\x0c\xb1\x07\xb0\xf5\x02\0\0", probe_zfs },
1450 { "hfsplus", 1, 0, 2, "BD", probe_hfsplus },
1451 { "hfsplus", 1, 0, 2, "H+", probe_hfsplus },
1452 { "hfsplus", 1, 0, 2, "HX", probe_hfsplus },
1453 { "hfs", 1, 0, 2, "BD", probe_hfs },
1454 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
1455 { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
1456 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
1457 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0 },
1458 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1 },
1459 { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1 },
1460 { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1 },
1461 { "swsuspend", 0, 0xff6, 9, "ULSUSPEND", probe_swap1 },
1462 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0 },
1463 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1 },
1464 { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1 },
1465 { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1 },
1466 { "swsuspend", 0, 0x1ff6, 9, "ULSUSPEND", probe_swap1 },
1467 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0 },
1468 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1 },
1469 { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1 },
1470 { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1 },
1471 { "swsuspend", 0, 0x3ff6, 9, "ULSUSPEND", probe_swap1 },
1472 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0 },
1473 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1 },
1474 { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1 },
1475 { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1 },
1476 { "swsuspend", 0, 0x7ff6, 9, "ULSUSPEND", probe_swap1 },
1477 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0 },
1478 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1 },
1479 { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1 },
1480 { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1 },
1481 { "swsuspend", 0, 0xfff6, 9, "ULSUSPEND", probe_swap1 },
1482 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs },
1483 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2 },
1484 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2 },
1485 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2 },
1486 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2 },
1487 { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks },
1488 { "squashfs", 0, 0, 4, "sqsh", 0 },
1489 { "squashfs", 0, 0, 4, "hsqs", 0 },
1490 { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2 },
1491 { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2 },
1492 { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2 },
1493 { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2 },
1494 { "btrfs", 64, 0x40, 8, "_BHRfS_M", probe_btrfs },
1495 { NULL, 0, 0, 0, NULL, NULL }
1499 * Verify that the data in dev is consistent with what is on the actual
1500 * block device (using the devname field only). Normally this will be
1501 * called when finding items in the cache, but for long running processes
1502 * is also desirable to revalidate an item before use.
1504 * If we are unable to revalidate the data, we return the old data and
1505 * do not set the BLKID_BID_FL_VERIFIED flag on it.
1507 blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
1509 struct blkid_magic *id;
1510 struct blkid_probe probe;
1511 blkid_tag_iterate iter;
1513 const char *type, *value;
1523 diff = difftime(now, dev->bid_time);
1525 if (stat(dev->bid_name, &st) < 0) {
1527 printf("blkid_verify: error %s (%d) while "
1528 "trying to stat %s\n", strerror(errno), errno,
1531 if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) {
1532 /* We don't have read permission, just return cache data. */
1533 DBG(DEBUG_PROBE, printf("returning unverified data for %s\n",
1537 blkid_free_dev(dev);
1541 if ((now >= dev->bid_time) &&
1542 (st.st_mtime <= dev->bid_time) &&
1543 ((diff < BLKID_PROBE_MIN) ||
1544 (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
1545 diff < BLKID_PROBE_INTERVAL)))
1549 printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
1550 "time since last check %lu)\n",
1551 dev->bid_name, (unsigned long)dev->bid_time,
1552 (unsigned long)st.st_mtime, (unsigned long)diff));
1554 if ((probe.fd = open(dev->bid_name, O_RDONLY)) < 0) {
1555 DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while "
1556 "opening %s\n", strerror(errno), errno,
1561 probe.cache = cache;
1568 * Iterate over the type array. If we already know the type,
1569 * then try that first. If it doesn't work, then blow away
1570 * the type information, and try again.
1575 if (!dev->bid_type || !strcmp(dev->bid_type, "mdraid")) {
1578 if (check_mdraid(probe.fd, uuid) == 0) {
1579 set_uuid(dev, uuid, 0);
1584 for (id = type_array; id->bim_type; id++) {
1585 if (dev->bid_type &&
1586 strcmp(id->bim_type, dev->bid_type))
1589 idx = id->bim_kboff + (id->bim_sboff >> 10);
1590 buf = get_buffer(&probe, idx << 10, 1024);
1594 if (memcmp(id->bim_magic, buf + (id->bim_sboff & 0x3ff),
1598 if ((id->bim_probe == NULL) ||
1599 (id->bim_probe(&probe, id, buf) == 0)) {
1600 type = id->bim_type;
1605 if (!id->bim_type && dev->bid_type) {
1607 * Zap the device filesystem information and try again
1610 printf("previous fs type %s not valid, "
1611 "trying full probe\n", dev->bid_type));
1612 iter = blkid_tag_iterate_begin(dev);
1613 while (blkid_tag_next(iter, &type, &value) == 0)
1614 blkid_set_tag(dev, type, 0, 0);
1615 blkid_tag_iterate_end(iter);
1619 if (!dev->bid_type) {
1620 blkid_free_dev(dev);
1627 dev->bid_devno = st.st_rdev;
1628 dev->bid_time = time(0);
1629 dev->bid_flags |= BLKID_BID_FL_VERIFIED;
1630 cache->bic_flags |= BLKID_BIC_FL_CHANGED;
1632 blkid_set_tag(dev, "TYPE", type, 0);
1634 DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
1635 dev->bid_name, (long long)st.st_rdev, type));
1646 int blkid_known_fstype(const char *fstype)
1648 struct blkid_magic *id;
1650 for (id = type_array; id->bim_type; id++) {
1651 if (strcmp(fstype, id->bim_type) == 0)
1658 int main(int argc, char **argv)
1665 fprintf(stderr, "Usage: %s device\n"
1666 "Probe a single device to determine type\n", argv[0]);
1669 if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
1670 fprintf(stderr, "%s: error creating cache (%d)\n",
1674 dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
1676 printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
1679 printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)");
1681 printf("LABEL='%s'\n", dev->bid_label);
1683 printf("UUID='%s'\n", dev->bid_uuid);
1685 blkid_free_dev(dev);