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.
23 #include <sys/types.h>
24 #ifdef HAVE_SYS_STAT_H
27 #ifdef HAVE_SYS_MKDEV_H
28 #include <sys/mkdev.h>
31 #include <sys/utsname.h>
37 #include "uuid/uuid.h"
40 static int figure_label_len(const unsigned char *label
, int len
)
42 const unsigned char *end
= label
+ len
- 1;
44 while ((*end
== ' ' || *end
== 0) && end
>= label
)
47 return end
- label
+ 1;
51 static unsigned char *get_buffer(struct blkid_probe
*pr
,
52 blkid_loff_t off
, size_t len
)
55 unsigned char *newbuf
;
57 if (off
+ len
<= SB_BUFFER_SIZE
) {
59 pr
->sbbuf
= malloc(SB_BUFFER_SIZE
);
62 if (lseek(pr
->fd
, 0, SEEK_SET
) < 0)
64 ret_read
= read(pr
->fd
, pr
->sbbuf
, SB_BUFFER_SIZE
);
67 pr
->sb_valid
= ret_read
;
69 if (off
+len
> pr
->sb_valid
)
71 return pr
->sbbuf
+ off
;
73 if (len
> pr
->buf_max
) {
74 newbuf
= realloc(pr
->buf
, len
);
80 if (blkid_llseek(pr
->fd
, off
, SEEK_SET
) < 0)
82 ret_read
= read(pr
->fd
, pr
->buf
, len
);
83 if (ret_read
!= (ssize_t
) len
)
91 * This is a special case code to check for an MDRAID device. We do
92 * this special since it requires checking for a superblock at the end
95 static int check_mdraid(int fd
, unsigned char *ret_uuid
)
97 struct mdp_superblock_s
*md
;
102 return -BLKID_ERR_PARAM
;
104 offset
= (blkid_get_dev_size(fd
) & ~((blkid_loff_t
)65535)) - 65536;
106 if (blkid_llseek(fd
, offset
, 0) < 0 ||
107 read(fd
, buf
, 4096) != 4096)
108 return -BLKID_ERR_IO
;
110 /* Check for magic number */
111 if (memcmp("\251+N\374", buf
, 4) && memcmp("\374N+\251", buf
, 4))
112 return -BLKID_ERR_PARAM
;
118 /* The MD UUID is not contiguous in the superblock, make it so */
119 md
= (struct mdp_superblock_s
*)buf
;
120 if (md
->set_uuid0
|| md
->set_uuid1
|| md
->set_uuid2
|| md
->set_uuid3
) {
121 memcpy(ret_uuid
, &md
->set_uuid0
, 4);
122 memcpy(ret_uuid
+ 4, &md
->set_uuid1
, 12);
127 static void set_uuid(blkid_dev dev
, uuid_t uuid
, const char *tag
)
131 if (!uuid_is_null(uuid
)) {
132 uuid_unparse(uuid
, str
);
133 blkid_set_tag(dev
, tag
? tag
: "UUID", str
, sizeof(str
));
137 static void get_ext2_info(blkid_dev dev
, struct blkid_magic
*id
,
140 struct ext2_super_block
*es
= (struct ext2_super_block
*) buf
;
141 const char *label
= 0;
143 DBG(DEBUG_PROBE
, printf("ext2_sb.compat = %08X:%08X:%08X\n",
144 blkid_le32(es
->s_feature_compat
),
145 blkid_le32(es
->s_feature_incompat
),
146 blkid_le32(es
->s_feature_ro_compat
)));
148 if (strlen(es
->s_volume_name
))
149 label
= es
->s_volume_name
;
150 blkid_set_tag(dev
, "LABEL", label
, sizeof(es
->s_volume_name
));
152 set_uuid(dev
, es
->s_uuid
, 0);
154 if ((es
->s_feature_compat
& EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
155 !uuid_is_null(es
->s_journal_uuid
))
156 set_uuid(dev
, es
->s_journal_uuid
, "EXT_JOURNAL");
158 if (strcmp(id
->bim_type
, "ext2") &&
159 ((blkid_le32(es
->s_feature_incompat
) &
160 EXT2_FEATURE_INCOMPAT_UNSUPPORTED
) == 0))
161 blkid_set_tag(dev
, "SEC_TYPE", "ext2", sizeof("ext2"));
165 * Check to see if a filesystem is in /proc/filesystems.
166 * Returns 1 if found, 0 if not
168 static int fs_proc_check(const char *fs_name
)
171 char buf
[80], *cp
, *t
;
173 f
= fopen("/proc/filesystems", "r");
177 if (!fgets(buf
, sizeof(buf
), f
))
181 while (*cp
&& !isspace(*cp
))
184 while (*cp
&& isspace(*cp
))
186 if ((t
= strchr(cp
, '\n')) != NULL
)
188 if ((t
= strchr(cp
, '\t')) != NULL
)
190 if ((t
= strchr(cp
, ' ')) != NULL
)
192 if (!strcmp(fs_name
, cp
)) {
202 * Check to see if a filesystem is available as a module
203 * Returns 1 if found, 0 if not
205 static int check_for_modules(const char *fs_name
)
215 snprintf(buf
, sizeof(buf
), "/lib/modules/%s/modules.dep", uts
.release
);
221 namesz
= strlen(fs_name
);
224 if (!fgets(buf
, sizeof(buf
), f
))
226 if ((cp
= strchr(buf
, ':')) != NULL
)
230 if ((cp
= strrchr(buf
, '/')) != NULL
)
234 if (!strncmp(cp
, fs_name
, namesz
) &&
235 (!strcmp(cp
+ namesz
, ".ko") ||
236 !strcmp(cp
+ namesz
, ".ko.gz"))) {
246 static int linux_version_code(void)
250 static int version_code
= -1;
251 int major
, minor
, rev
;
255 if (version_code
> 0)
262 major
= strtol(cp
, &endptr
, 10);
263 if (cp
== endptr
|| *endptr
!= '.')
266 minor
= strtol(cp
, &endptr
, 10);
267 if (cp
== endptr
|| *endptr
!= '.')
270 rev
= strtol(cp
, &endptr
, 10);
273 version_code
= (((major
* 256) + minor
) * 256) + rev
;
280 #define EXT4_SUPPORTS_EXT2 (2 * 65536 + 6*256 + 29)
282 static int system_supports_ext2(void)
284 static time_t last_check
= 0;
286 time_t now
= time(0);
288 if (ret
!= -1 || (now
- last_check
) < 5)
291 ret
= (fs_proc_check("ext2") || check_for_modules("ext2"));
295 static int system_supports_ext4(void)
297 static time_t last_check
= 0;
299 time_t now
= time(0);
301 if (ret
!= -1 || (now
- last_check
) < 5)
304 ret
= (fs_proc_check("ext4") || check_for_modules("ext4"));
308 static int system_supports_ext4dev(void)
310 static time_t last_check
= 0;
312 time_t now
= time(0);
314 if (ret
!= -1 || (now
- last_check
) < 5)
317 ret
= (fs_proc_check("ext4dev") || check_for_modules("ext4dev"));
321 static int probe_ext4dev(struct blkid_probe
*probe
,
322 struct blkid_magic
*id
,
325 struct ext2_super_block
*es
;
326 es
= (struct ext2_super_block
*)buf
;
328 /* Distinguish from jbd */
329 if (blkid_le32(es
->s_feature_incompat
) &
330 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)
331 return -BLKID_ERR_PARAM
;
334 * If the filesystem does not have a journal and ext2 and ext4
335 * is not present, then force this to be detected as an
336 * ext4dev filesystem.
338 if (!(blkid_le32(es
->s_feature_compat
) &
339 EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
340 !system_supports_ext2() && !system_supports_ext4() &&
341 system_supports_ext4dev() &&
342 linux_version_code() >= EXT4_SUPPORTS_EXT2
)
346 * If the filesystem is marked as OK for use by in-development
347 * filesystem code, but ext4dev is not supported, and ext4 is,
348 * then don't call ourselves ext4dev, since we should be
349 * detected as ext4 in that case.
351 * If the filesystem is marked as in use by production
352 * filesystem, then it can only be used by ext4 and NOT by
353 * ext4dev, so always disclaim we are ext4dev in that case.
355 if (blkid_le32(es
->s_flags
) & EXT2_FLAGS_TEST_FILESYS
) {
356 if (!system_supports_ext4dev() && system_supports_ext4())
357 return -BLKID_ERR_PARAM
;
359 return -BLKID_ERR_PARAM
;
362 get_ext2_info(probe
->dev
, id
, buf
);
366 static int probe_ext4(struct blkid_probe
*probe
, struct blkid_magic
*id
,
369 struct ext2_super_block
*es
;
370 es
= (struct ext2_super_block
*)buf
;
372 /* Distinguish from jbd */
373 if (blkid_le32(es
->s_feature_incompat
) &
374 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)
375 return -BLKID_ERR_PARAM
;
378 * If the filesystem does not have a journal and ext2 is not
379 * present, then force this to be detected as an ext2
382 if (!(blkid_le32(es
->s_feature_compat
) &
383 EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
384 !system_supports_ext2() && system_supports_ext4() &&
385 linux_version_code() >= EXT4_SUPPORTS_EXT2
)
388 /* Ext4 has at least one feature which ext3 doesn't understand */
389 if (!(blkid_le32(es
->s_feature_ro_compat
) &
390 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED
) &&
391 !(blkid_le32(es
->s_feature_incompat
) &
392 EXT3_FEATURE_INCOMPAT_UNSUPPORTED
))
393 return -BLKID_ERR_PARAM
;
397 * If the filesystem is a OK for use by in-development
398 * filesystem code, and ext4dev is supported or ext4 is not
399 * supported, then don't call ourselves ext4, so we can redo
400 * the detection and mark the filesystem as ext4dev.
402 * If the filesystem is marked as in use by production
403 * filesystem, then it can only be used by ext4 and NOT by
406 if (blkid_le32(es
->s_flags
) & EXT2_FLAGS_TEST_FILESYS
) {
407 if (system_supports_ext4dev() || !system_supports_ext4())
408 return -BLKID_ERR_PARAM
;
410 get_ext2_info(probe
->dev
, id
, buf
);
414 static int probe_ext3(struct blkid_probe
*probe
, struct blkid_magic
*id
,
417 struct ext2_super_block
*es
;
418 es
= (struct ext2_super_block
*)buf
;
420 /* ext3 requires journal */
421 if (!(blkid_le32(es
->s_feature_compat
) &
422 EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
423 return -BLKID_ERR_PARAM
;
425 /* Any features which ext3 doesn't understand */
426 if ((blkid_le32(es
->s_feature_ro_compat
) &
427 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED
) ||
428 (blkid_le32(es
->s_feature_incompat
) &
429 EXT3_FEATURE_INCOMPAT_UNSUPPORTED
))
430 return -BLKID_ERR_PARAM
;
432 get_ext2_info(probe
->dev
, id
, buf
);
436 static int probe_ext2(struct blkid_probe
*probe
, struct blkid_magic
*id
,
439 struct ext2_super_block
*es
;
441 es
= (struct ext2_super_block
*)buf
;
443 /* Distinguish between ext3 and ext2 */
444 if ((blkid_le32(es
->s_feature_compat
) &
445 EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
446 return -BLKID_ERR_PARAM
;
448 /* Any features which ext2 doesn't understand */
449 if ((blkid_le32(es
->s_feature_ro_compat
) &
450 EXT2_FEATURE_RO_COMPAT_UNSUPPORTED
) ||
451 (blkid_le32(es
->s_feature_incompat
) &
452 EXT2_FEATURE_INCOMPAT_UNSUPPORTED
))
453 return -BLKID_ERR_PARAM
;
456 * If ext2 is not present, but ext4 or ext4dev are, then
457 * disclaim we are ext2
459 if (!system_supports_ext2() &&
460 (system_supports_ext4() || system_supports_ext4dev()) &&
461 linux_version_code() >= EXT4_SUPPORTS_EXT2
)
462 return -BLKID_ERR_PARAM
;
464 get_ext2_info(probe
->dev
, id
, buf
);
468 static int probe_jbd(struct blkid_probe
*probe
, struct blkid_magic
*id
,
471 struct ext2_super_block
*es
= (struct ext2_super_block
*) buf
;
473 if (!(blkid_le32(es
->s_feature_incompat
) &
474 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
))
475 return -BLKID_ERR_PARAM
;
477 get_ext2_info(probe
->dev
, id
, buf
);
482 #define FAT_ATTR_VOLUME_ID 0x08
483 #define FAT_ATTR_DIR 0x10
484 #define FAT_ATTR_LONG_NAME 0x0f
485 #define FAT_ATTR_MASK 0x3f
486 #define FAT_ENTRY_FREE 0xe5
488 static const char *no_name
= "NO NAME ";
490 static unsigned char *search_fat_label(struct vfat_dir_entry
*dir
, int count
)
494 for (i
= 0; i
< count
; i
++) {
495 if (dir
[i
].name
[0] == 0x00)
498 if ((dir
[i
].name
[0] == FAT_ENTRY_FREE
) ||
499 (dir
[i
].cluster_high
!= 0 || dir
[i
].cluster_low
!= 0) ||
500 ((dir
[i
].attr
& FAT_ATTR_MASK
) == FAT_ATTR_LONG_NAME
))
503 if ((dir
[i
].attr
& (FAT_ATTR_VOLUME_ID
| FAT_ATTR_DIR
)) ==
504 FAT_ATTR_VOLUME_ID
) {
511 /* FAT label extraction from the root directory taken from Kay
512 * Sievers's volume_id library */
513 static int probe_fat(struct blkid_probe
*probe
,
514 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
517 struct vfat_super_block
*vs
= (struct vfat_super_block
*) buf
;
518 struct msdos_super_block
*ms
= (struct msdos_super_block
*) buf
;
519 struct vfat_dir_entry
*dir
;
521 const unsigned char *label
= 0, *vol_label
= 0, *tmp
;
522 unsigned char *vol_serno
;
523 int label_len
= 0, maxloop
= 100;
524 __u16 sector_size
, dir_entries
, reserved
;
525 __u32 sect_count
, fat_size
, dir_size
, cluster_count
, fat_length
;
526 __u32 buf_size
, start_data_sect
, next
, root_start
, root_dir_entries
;
528 /* sector size check */
529 tmp
= (unsigned char *)&ms
->ms_sector_size
;
530 sector_size
= tmp
[0] + (tmp
[1] << 8);
531 if (sector_size
!= 0x200 && sector_size
!= 0x400 &&
532 sector_size
!= 0x800 && sector_size
!= 0x1000)
535 tmp
= (unsigned char *)&ms
->ms_dir_entries
;
536 dir_entries
= tmp
[0] + (tmp
[1] << 8);
537 reserved
= blkid_le16(ms
->ms_reserved
);
538 tmp
= (unsigned char *)&ms
->ms_sectors
;
539 sect_count
= tmp
[0] + (tmp
[1] << 8);
541 sect_count
= blkid_le32(ms
->ms_total_sect
);
543 fat_length
= blkid_le16(ms
->ms_fat_length
);
545 fat_length
= blkid_le32(vs
->vs_fat32_length
);
547 fat_size
= fat_length
* ms
->ms_fats
;
548 dir_size
= ((dir_entries
* sizeof(struct vfat_dir_entry
)) +
549 (sector_size
-1)) / sector_size
;
551 cluster_count
= sect_count
- (reserved
+ fat_size
+ dir_size
);
552 if (ms
->ms_cluster_size
== 0)
554 cluster_count
/= ms
->ms_cluster_size
;
556 if (cluster_count
> FAT32_MAX
)
559 if (ms
->ms_fat_length
) {
560 /* the label may be an attribute in the root directory */
561 root_start
= (reserved
+ fat_size
) * sector_size
;
562 root_dir_entries
= vs
->vs_dir_entries
[0] +
563 (vs
->vs_dir_entries
[1] << 8);
565 buf_size
= root_dir_entries
* sizeof(struct vfat_dir_entry
);
566 dir
= (struct vfat_dir_entry
*) get_buffer(probe
, root_start
,
569 vol_label
= search_fat_label(dir
, root_dir_entries
);
571 if (!vol_label
|| !memcmp(vol_label
, no_name
, 11))
572 vol_label
= ms
->ms_label
;
573 vol_serno
= ms
->ms_serno
;
575 blkid_set_tag(probe
->dev
, "SEC_TYPE", "msdos",
578 /* Search the FAT32 root dir for the label attribute */
579 buf_size
= vs
->vs_cluster_size
* sector_size
;
580 start_data_sect
= reserved
+ fat_size
;
582 next
= blkid_le32(vs
->vs_root_cluster
);
583 while (next
&& --maxloop
) {
585 __u64 next_off
, fat_entry_off
;
588 next_sect_off
= (next
- 2) * vs
->vs_cluster_size
;
589 next_off
= (__u64
) (start_data_sect
+ next_sect_off
) *
592 dir
= (struct vfat_dir_entry
*)
593 get_buffer(probe
, next_off
, buf_size
);
597 count
= buf_size
/ sizeof(struct vfat_dir_entry
);
599 vol_label
= search_fat_label(dir
, count
);
605 ((unsigned int) reserved
*
606 (unsigned int) sector_size
) +
607 (next
* sizeof(__u32
));
608 buf
= get_buffer(probe
, fat_entry_off
, buf_size
);
612 /* set next cluster */
613 next
= blkid_le32(*((__u32
*) buf
) & 0x0fffffff);
616 if (!vol_label
|| !memcmp(vol_label
, no_name
, 11))
617 vol_label
= vs
->vs_label
;
618 vol_serno
= vs
->vs_serno
;
621 if (vol_label
&& memcmp(vol_label
, no_name
, 11)) {
622 if ((label_len
= figure_label_len(vol_label
, 11)))
626 /* We can't just print them as %04X, because they are unaligned */
627 sprintf(serno
, "%02X%02X-%02X%02X", vol_serno
[3], vol_serno
[2],
628 vol_serno
[1], vol_serno
[0]);
630 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
, label_len
);
631 blkid_set_tag(probe
->dev
, "UUID", serno
, sizeof(serno
)-1);
637 * The FAT filesystem could be without a magic string in superblock
638 * (e.g. old floppies). This heuristic for FAT detection is inspired
639 * by http://vrfy.org/projects/volume_id/ and Linux kernel.
640 * [7-Jul-2005, Karel Zak <kzak@redhat.com>]
642 static int probe_fat_nomagic(struct blkid_probe
*probe
,
643 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
646 struct msdos_super_block
*ms
;
648 ms
= (struct msdos_super_block
*)buf
;
651 if (ms
->ms_heads
== 0)
654 /* cluster size check*/
655 if (ms
->ms_cluster_size
== 0 ||
656 (ms
->ms_cluster_size
& (ms
->ms_cluster_size
-1)))
660 if (ms
->ms_media
< 0xf8 && ms
->ms_media
!= 0xf0)
663 /* fat counts(Linux kernel expects at least 1 FAT table) */
668 * OS/2 and apparently DFSee will place a FAT12/16-like
669 * pseudo-superblock in the first 512 bytes of non-FAT
670 * filesystems --- at least JFS and HPFS, and possibly others.
671 * So we explicitly check for those filesystems at the
672 * FAT12/16 filesystem magic field identifier, and if they are
673 * present, we rule this out as a FAT filesystem, despite the
674 * FAT-like pseudo-header.
676 if ((memcmp(ms
->ms_magic
, "JFS ", 8) == 0) ||
677 (memcmp(ms
->ms_magic
, "HPFS ", 8) == 0))
680 return probe_fat(probe
, id
, buf
);
683 static int probe_ntfs(struct blkid_probe
*probe
,
684 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
687 struct ntfs_super_block
*ns
;
688 struct master_file_table_record
*mft
;
689 struct file_attribute
*attr
;
690 char uuid_str
[17], label_str
[129], *cp
;
691 int bytes_per_sector
, sectors_per_cluster
;
692 int mft_record_size
, attr_off
, attr_len
;
693 unsigned int i
, attr_type
, val_len
;
697 unsigned char *buf_mft
, *val
;
699 ns
= (struct ntfs_super_block
*) buf
;
701 bytes_per_sector
= ns
->bios_parameter_block
[0] +
702 (ns
->bios_parameter_block
[1] << 8);
703 sectors_per_cluster
= ns
->bios_parameter_block
[2];
705 if ((bytes_per_sector
< 512) || (sectors_per_cluster
== 0))
708 if (ns
->cluster_per_mft_record
< 0)
709 mft_record_size
= 1 << (0-ns
->cluster_per_mft_record
);
711 mft_record_size
= ns
->cluster_per_mft_record
*
712 sectors_per_cluster
* bytes_per_sector
;
713 nr_clusters
= blkid_le64(ns
->number_of_sectors
) / sectors_per_cluster
;
715 if ((blkid_le64(ns
->mft_cluster_location
) > nr_clusters
) ||
716 (blkid_le64(ns
->mft_mirror_cluster_location
) > nr_clusters
))
719 off
= blkid_le64(ns
->mft_mirror_cluster_location
) *
720 bytes_per_sector
* sectors_per_cluster
;
722 buf_mft
= get_buffer(probe
, off
, mft_record_size
);
726 if (memcmp(buf_mft
, "FILE", 4))
729 off
= blkid_le64(ns
->mft_cluster_location
) * bytes_per_sector
*
732 buf_mft
= get_buffer(probe
, off
, mft_record_size
);
736 if (memcmp(buf_mft
, "FILE", 4))
739 off
+= MFT_RECORD_VOLUME
* mft_record_size
;
741 buf_mft
= get_buffer(probe
, off
, mft_record_size
);
745 if (memcmp(buf_mft
, "FILE", 4))
748 mft
= (struct master_file_table_record
*) buf_mft
;
750 attr_off
= blkid_le16(mft
->attrs_offset
);
754 attr
= (struct file_attribute
*) (buf_mft
+ attr_off
);
755 attr_len
= blkid_le16(attr
->len
);
756 attr_type
= blkid_le32(attr
->type
);
757 val_off
= blkid_le16(attr
->value_offset
);
758 val_len
= blkid_le32(attr
->value_len
);
760 attr_off
+= attr_len
;
762 if ((attr_off
> mft_record_size
) ||
766 if (attr_type
== MFT_RECORD_ATTR_END
)
769 if (attr_type
== MFT_RECORD_ATTR_VOLUME_NAME
) {
770 if (val_len
> sizeof(label_str
))
771 val_len
= sizeof(label_str
)-1;
773 for (i
=0, cp
=label_str
; i
< val_len
; i
+=2,cp
++) {
774 val
= ((__u8
*) attr
) + val_off
+ i
;
783 sprintf(uuid_str
, "%016llX", blkid_le64(ns
->volume_serial
));
784 blkid_set_tag(probe
->dev
, "UUID", uuid_str
, 0);
786 blkid_set_tag(probe
->dev
, "LABEL", label_str
, 0);
791 static int probe_xfs(struct blkid_probe
*probe
,
792 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
795 struct xfs_super_block
*xs
;
796 const char *label
= 0;
798 xs
= (struct xfs_super_block
*)buf
;
800 if (strlen(xs
->xs_fname
))
801 label
= xs
->xs_fname
;
802 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(xs
->xs_fname
));
803 set_uuid(probe
->dev
, xs
->xs_uuid
, 0);
807 static int probe_reiserfs(struct blkid_probe
*probe
,
808 struct blkid_magic
*id
, unsigned char *buf
)
810 struct reiserfs_super_block
*rs
= (struct reiserfs_super_block
*) buf
;
811 unsigned int blocksize
;
812 const char *label
= 0;
814 blocksize
= blkid_le16(rs
->rs_blocksize
);
816 /* The blocksize must be at least 1k */
817 if ((blocksize
>> 10) == 0)
818 return -BLKID_ERR_PARAM
;
820 /* If the superblock is inside the journal, we have the wrong one */
821 if (id
->bim_kboff
/(blocksize
>>10) > blkid_le32(rs
->rs_journal_block
))
822 return -BLKID_ERR_BIG
;
824 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
825 if (id
->bim_magic
[6] == '2' || id
->bim_magic
[6] == '3') {
826 if (strlen(rs
->rs_label
))
827 label
= rs
->rs_label
;
828 set_uuid(probe
->dev
, rs
->rs_uuid
, 0);
830 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(rs
->rs_label
));
835 static int probe_reiserfs4(struct blkid_probe
*probe
,
836 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
839 struct reiser4_super_block
*rs4
= (struct reiser4_super_block
*) buf
;
840 const unsigned char *label
= 0;
842 if (strlen((char *) rs4
->rs4_label
))
843 label
= rs4
->rs4_label
;
844 set_uuid(probe
->dev
, rs4
->rs4_uuid
, 0);
845 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
,
846 sizeof(rs4
->rs4_label
));
851 static int probe_jfs(struct blkid_probe
*probe
,
852 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
855 struct jfs_super_block
*js
;
856 const char *label
= 0;
858 js
= (struct jfs_super_block
*)buf
;
860 if (blkid_le32(js
->js_bsize
) != (1 << blkid_le16(js
->js_l2bsize
)))
863 if (blkid_le32(js
->js_pbsize
) != (1 << blkid_le16(js
->js_l2pbsize
)))
866 if ((blkid_le16(js
->js_l2bsize
) - blkid_le16(js
->js_l2pbsize
)) !=
867 blkid_le16(js
->js_l2bfactor
))
870 if (strlen((char *) js
->js_label
))
871 label
= (char *) js
->js_label
;
872 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(js
->js_label
));
873 set_uuid(probe
->dev
, js
->js_uuid
, 0);
877 static int probe_zfs(struct blkid_probe
*probe
__BLKID_ATTR((unused
)),
878 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
879 unsigned char *buf
__BLKID_ATTR((unused
)))
883 const char *pool_name
= 0;
885 /* read nvpair data for pool name, pool GUID (complex) */
886 blkid_set_tag(probe
->dev
, "LABEL", pool_name
, sizeof(pool_name
));
887 set_uuid(probe
->dev
, pool_guid
, 0);
892 static int probe_luks(struct blkid_probe
*probe
,
893 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
898 /* 168 is the offset to the 40 character uuid:
899 * http://luks.endorphin.org/LUKS-on-disk-format.pdf */
900 strncpy(uuid
, (char *) buf
+168, 40);
901 blkid_set_tag(probe
->dev
, "UUID", uuid
, sizeof(uuid
));
905 static int probe_romfs(struct blkid_probe
*probe
,
906 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
909 struct romfs_super_block
*ros
;
910 const char *label
= 0;
912 ros
= (struct romfs_super_block
*)buf
;
914 if (strlen((char *) ros
->ros_volume
))
915 label
= (char *) ros
->ros_volume
;
916 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
920 static int probe_cramfs(struct blkid_probe
*probe
,
921 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
924 struct cramfs_super_block
*csb
;
925 const char *label
= 0;
927 csb
= (struct cramfs_super_block
*)buf
;
929 if (strlen((char *) csb
->name
))
930 label
= (char *) csb
->name
;
931 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
935 static int probe_swap0(struct blkid_probe
*probe
,
936 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
937 unsigned char *buf
__BLKID_ATTR((unused
)))
939 blkid_set_tag(probe
->dev
, "UUID", 0, 0);
940 blkid_set_tag(probe
->dev
, "LABEL", 0, 0);
944 static int probe_swap1(struct blkid_probe
*probe
,
945 struct blkid_magic
*id
,
946 unsigned char *buf
__BLKID_ATTR((unused
)))
948 struct swap_id_block
*sws
;
950 probe_swap0(probe
, id
, buf
);
952 * Version 1 swap headers are always located at offset of 1024
953 * bytes, although the swap signature itself is located at the
954 * end of the page (which may vary depending on hardware
957 sws
= (struct swap_id_block
*) get_buffer(probe
, 1024, 1024);
961 /* check for wrong version or zeroed pagecount, for sanity */
962 if (!memcmp(id
->bim_magic
, "SWAPSPACE2", id
->bim_len
) &&
963 (sws
->sws_version
!= 1 || sws
->sws_lastpage
== 0))
966 /* arbitrary sanity check.. is there any garbage down there? */
967 if (sws
->sws_pad
[32] == 0 && sws
->sws_pad
[33] == 0) {
968 if (sws
->sws_volume
[0])
969 blkid_set_tag(probe
->dev
, "LABEL", sws
->sws_volume
,
970 sizeof(sws
->sws_volume
));
971 if (sws
->sws_uuid
[0])
972 set_uuid(probe
->dev
, sws
->sws_uuid
, 0);
977 static int probe_iso9660(struct blkid_probe
*probe
,
978 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
981 struct iso_volume_descriptor
*iso
;
982 const unsigned char *label
;
984 iso
= (struct iso_volume_descriptor
*) buf
;
985 label
= iso
->volume_id
;
987 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
,
988 figure_label_len(label
, 32));
994 *udf_magic
[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
995 "NSR03", "TEA01", 0 };
997 static int probe_udf(struct blkid_probe
*probe
,
998 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
999 unsigned char *buf
__BLKID_ATTR((unused
)))
1002 struct iso_volume_descriptor
*isosb
;
1005 /* determine the block size by scanning in 2K increments
1006 (block sizes larger than 2K will be null padded) */
1007 for (bs
= 1; bs
< 16; bs
++) {
1008 isosb
= (struct iso_volume_descriptor
*)
1009 get_buffer(probe
, (blkid_loff_t
) bs
*2048+32768,
1013 if (isosb
->vd_id
[0])
1017 /* Scan up to another 64 blocks looking for additional VSD's */
1018 for (j
= 1; j
< 64; j
++) {
1020 isosb
= (struct iso_volume_descriptor
*)
1021 get_buffer(probe
, j
*bs
*2048+32768,
1026 /* If we find NSR0x then call it udf:
1029 NSR03 for UDF 2.00 */
1030 if (!memcmp(isosb
->vd_id
, "NSR0", 4))
1031 return probe_iso9660(probe
, id
, buf
);
1032 for (m
= udf_magic
; *m
; m
++)
1033 if (!memcmp(*m
, isosb
->vd_id
, 5))
1041 static int probe_ocfs(struct blkid_probe
*probe
,
1042 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1045 struct ocfs_volume_header ovh
;
1046 struct ocfs_volume_label ovl
;
1049 memcpy(&ovh
, buf
, sizeof(ovh
));
1050 memcpy(&ovl
, buf
+512, sizeof(ovl
));
1052 major
= ocfsmajor(ovh
);
1054 blkid_set_tag(probe
->dev
,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
1055 else if (major
>= 9)
1056 blkid_set_tag(probe
->dev
,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
1058 blkid_set_tag(probe
->dev
, "LABEL", ovl
.label
, ocfslabellen(ovl
));
1059 blkid_set_tag(probe
->dev
, "MOUNT", ovh
.mount
, ocfsmountlen(ovh
));
1060 set_uuid(probe
->dev
, ovl
.vol_id
, 0);
1064 static int probe_ocfs2(struct blkid_probe
*probe
,
1065 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1068 struct ocfs2_super_block
*osb
;
1070 osb
= (struct ocfs2_super_block
*)buf
;
1072 blkid_set_tag(probe
->dev
, "LABEL", osb
->s_label
, sizeof(osb
->s_label
));
1073 set_uuid(probe
->dev
, osb
->s_uuid
, 0);
1077 static int probe_oracleasm(struct blkid_probe
*probe
,
1078 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1081 struct oracle_asm_disk_label
*dl
;
1083 dl
= (struct oracle_asm_disk_label
*)buf
;
1085 blkid_set_tag(probe
->dev
, "LABEL", dl
->dl_id
, sizeof(dl
->dl_id
));
1089 static int probe_gfs(struct blkid_probe
*probe
,
1090 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1093 struct gfs2_sb
*sbd
;
1094 const char *label
= 0;
1096 sbd
= (struct gfs2_sb
*)buf
;
1098 if (blkid_be32(sbd
->sb_fs_format
) == GFS_FORMAT_FS
&&
1099 blkid_be32(sbd
->sb_multihost_format
) == GFS_FORMAT_MULTI
)
1101 blkid_set_tag(probe
->dev
, "UUID", 0, 0);
1103 if (strlen(sbd
->sb_locktable
))
1104 label
= sbd
->sb_locktable
;
1105 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(sbd
->sb_locktable
));
1111 static int probe_gfs2(struct blkid_probe
*probe
,
1112 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1115 struct gfs2_sb
*sbd
;
1116 const char *label
= 0;
1118 sbd
= (struct gfs2_sb
*)buf
;
1120 if (blkid_be32(sbd
->sb_fs_format
) == GFS2_FORMAT_FS
&&
1121 blkid_be32(sbd
->sb_multihost_format
) == GFS2_FORMAT_MULTI
)
1123 blkid_set_tag(probe
->dev
, "UUID", 0, 0);
1125 if (strlen(sbd
->sb_locktable
))
1126 label
= sbd
->sb_locktable
;
1127 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(sbd
->sb_locktable
));
1133 static void unicode_16be_to_utf8(unsigned char *str
, int out_len
,
1134 const unsigned char *buf
, int in_len
)
1139 for (i
= j
= 0; i
+ 2 <= in_len
; i
+= 2) {
1140 c
= (buf
[i
] << 8) | buf
[i
+1];
1144 } else if (c
< 0x80) {
1147 str
[j
++] = (unsigned char) c
;
1148 } else if (c
< 0x800) {
1151 str
[j
++] = (unsigned char) (0xc0 | (c
>> 6));
1152 str
[j
++] = (unsigned char) (0x80 | (c
& 0x3f));
1156 str
[j
++] = (unsigned char) (0xe0 | (c
>> 12));
1157 str
[j
++] = (unsigned char) (0x80 | ((c
>> 6) & 0x3f));
1158 str
[j
++] = (unsigned char) (0x80 | (c
& 0x3f));
1164 static int probe_hfs(struct blkid_probe
*probe
__BLKID_ATTR((unused
)),
1165 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1168 struct hfs_mdb
*hfs
= (struct hfs_mdb
*)buf
;
1169 unsigned long long *uuid_ptr
;
1173 if ((memcmp(hfs
->embed_sig
, "H+", 2) == 0) ||
1174 (memcmp(hfs
->embed_sig
, "HX", 2) == 0))
1175 return 1; /* Not hfs, but an embedded HFS+ */
1177 uuid_ptr
= (unsigned long long *)hfs
->finder_info
.id
;
1178 uuid
= blkid_le64(*uuid_ptr
);
1180 sprintf(uuid_str
, "%016llX", uuid
);
1181 blkid_set_tag(probe
->dev
, "UUID", uuid_str
, 0);
1183 blkid_set_tag(probe
->dev
, "LABEL", (char *)hfs
->label
, hfs
->label_len
);
1188 static int probe_hfsplus(struct blkid_probe
*probe
,
1189 struct blkid_magic
*id
,
1192 struct hfsplus_extent extents
[HFSPLUS_EXTENT_COUNT
];
1193 struct hfsplus_bnode_descriptor
*descr
;
1194 struct hfsplus_bheader_record
*bnode
;
1195 struct hfsplus_catalog_key
*key
;
1196 struct hfsplus_vol_header
*hfsplus
;
1197 struct hfs_mdb
*sbd
= (struct hfs_mdb
*) buf
;
1198 unsigned int alloc_block_size
;
1199 unsigned int alloc_first_block
;
1200 unsigned int embed_first_block
;
1201 unsigned int off
= 0;
1202 unsigned int blocksize
;
1203 unsigned int cat_block
;
1204 unsigned int ext_block_start
;
1205 unsigned int ext_block_count
;
1206 unsigned int record_count
;
1207 unsigned int leaf_node_head
;
1208 unsigned int leaf_node_count
;
1209 unsigned int leaf_node_size
;
1210 unsigned int leaf_block
;
1211 unsigned int label_len
;
1212 unsigned long long *uuid_ptr
;
1213 __u64 leaf_off
, uuid
;
1214 char uuid_str
[17], label
[512];
1217 /* Check for a HFS+ volume embedded in a HFS volume */
1218 if (memcmp(sbd
->signature
, "BD", 2) == 0) {
1219 if ((memcmp(sbd
->embed_sig
, "H+", 2) != 0) &&
1220 (memcmp(sbd
->embed_sig
, "HX", 2) != 0))
1221 /* This must be an HFS volume, so fail */
1224 alloc_block_size
= blkid_be32(sbd
->al_blk_size
);
1225 alloc_first_block
= blkid_be16(sbd
->al_bl_st
);
1226 embed_first_block
= blkid_be16(sbd
->embed_startblock
);
1227 off
= (alloc_first_block
* 512) +
1228 (embed_first_block
* alloc_block_size
);
1229 buf
= get_buffer(probe
, off
+ (id
->bim_kboff
* 1024),
1234 hfsplus
= (struct hfsplus_vol_header
*) buf
;
1237 hfsplus
= (struct hfsplus_vol_header
*) buf
;
1239 if ((memcmp(hfsplus
->signature
, "H+", 2) != 0) &&
1240 (memcmp(hfsplus
->signature
, "HX", 2) != 0))
1243 uuid_ptr
= (unsigned long long *)hfsplus
->finder_info
.id
;
1244 uuid
= blkid_le64(*uuid_ptr
);
1246 sprintf(uuid_str
, "%016llX", uuid
);
1247 blkid_set_tag(probe
->dev
, "UUID", uuid_str
, 0);
1250 blocksize
= blkid_be32(hfsplus
->blocksize
);
1251 memcpy(extents
, hfsplus
->cat_file
.extents
, sizeof(extents
));
1252 cat_block
= blkid_be32(extents
[0].start_block
);
1254 buf
= get_buffer(probe
, off
+ ((__u64
) cat_block
* blocksize
), 0x2000);
1258 bnode
= (struct hfsplus_bheader_record
*)
1259 &buf
[sizeof(struct hfsplus_bnode_descriptor
)];
1261 leaf_node_head
= blkid_be32(bnode
->leaf_head
);
1262 leaf_node_size
= blkid_be16(bnode
->node_size
);
1263 leaf_node_count
= blkid_be32(bnode
->leaf_count
);
1264 if (leaf_node_count
== 0)
1267 leaf_block
= (leaf_node_head
* leaf_node_size
) / blocksize
;
1269 /* get physical location */
1270 for (ext
= 0; ext
< HFSPLUS_EXTENT_COUNT
; ext
++) {
1271 ext_block_start
= blkid_be32(extents
[ext
].start_block
);
1272 ext_block_count
= blkid_be32(extents
[ext
].block_count
);
1273 if (ext_block_count
== 0)
1276 /* this is our extent */
1277 if (leaf_block
< ext_block_count
)
1280 leaf_block
-= ext_block_count
;
1282 if (ext
== HFSPLUS_EXTENT_COUNT
)
1285 leaf_off
= (__u64
) (ext_block_start
+ leaf_block
) * blocksize
;
1287 buf
= get_buffer(probe
, off
+ leaf_off
, leaf_node_size
);
1291 descr
= (struct hfsplus_bnode_descriptor
*) buf
;
1292 record_count
= blkid_be16(descr
->num_recs
);
1293 if (record_count
== 0)
1296 if (descr
->type
!= HFS_NODE_LEAF
)
1299 key
= (struct hfsplus_catalog_key
*)
1300 &buf
[sizeof(struct hfsplus_bnode_descriptor
)];
1302 if (blkid_be32(key
->parent_id
) != HFSPLUS_POR_CNID
)
1305 label_len
= blkid_be16(key
->unicode_len
) * 2;
1306 unicode_16be_to_utf8((unsigned char *)label
, sizeof(label
),
1307 key
->unicode
, label_len
);
1308 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
1312 #define LVM2_LABEL_SIZE 512
1313 static unsigned int lvm2_calc_crc(const void *buf
, unsigned int size
)
1315 static const unsigned int crctab
[] = {
1316 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1317 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1318 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1319 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1321 unsigned int i
, crc
= 0xf597a6cf;
1322 const __u8
*data
= (const __u8
*) buf
;
1324 for (i
= 0; i
< size
; i
++) {
1326 crc
= (crc
>> 4) ^ crctab
[crc
& 0xf];
1327 crc
= (crc
>> 4) ^ crctab
[crc
& 0xf];
1332 static int probe_lvm2(struct blkid_probe
*probe
,
1333 struct blkid_magic
*id
,
1336 int sector
= (id
->bim_kboff
) << 1;
1337 struct lvm2_pv_label_header
*label
= (struct lvm2_pv_label_header
*)buf
;
1338 char *p
, *q
, uuid
[40];
1341 /* buf is at 0k or 1k offset; find label inside */
1342 if (memcmp(buf
, "LABELONE", 8) == 0) {
1343 label
= (struct lvm2_pv_label_header
*)buf
;
1344 } else if (memcmp(buf
+ 512, "LABELONE", 8) == 0) {
1345 label
= (struct lvm2_pv_label_header
*)(buf
+ 512);
1351 if (blkid_le64(label
->sector_xl
) != (unsigned) sector
) {
1353 printf("LVM2: label for sector %llu found at sector %d\n",
1354 blkid_le64(label
->sector_xl
), sector
));
1358 if (lvm2_calc_crc(&label
->offset_xl
, LVM2_LABEL_SIZE
-
1359 ((char *)&label
->offset_xl
- (char *)label
)) !=
1360 blkid_le32(label
->crc_xl
)) {
1362 printf("LVM2: label checksum incorrect at sector %d\n",
1367 for (i
=0, b
=1, p
=uuid
, q
= (char *) label
->pv_uuid
; i
< LVM2_ID_LEN
;
1374 blkid_set_tag(probe
->dev
, "UUID", uuid
, LVM2_ID_LEN
+6);
1379 static int probe_btrfs(struct blkid_probe
*probe
,
1380 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1383 struct btrfs_super_block
*bs
;
1384 const char *label
= 0;
1386 bs
= (struct btrfs_super_block
*)buf
;
1388 if (strlen(bs
->label
))
1390 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(bs
->label
));
1391 set_uuid(probe
->dev
, bs
->fsid
, 0);
1395 * Various filesystem magics that we can check for. Note that kboff and
1396 * sboff are in kilobytes and bytes respectively. All magics are in
1397 * byte strings so we don't worry about endian issues.
1399 static struct blkid_magic type_array
[] = {
1400 /* type kboff sboff len magic probe */
1401 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm
},
1402 { "ntfs", 0, 3, 8, "NTFS ", probe_ntfs
},
1403 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd
},
1404 { "ext4dev", 1, 0x38, 2, "\123\357", probe_ext4dev
},
1405 { "ext4", 1, 0x38, 2, "\123\357", probe_ext4
},
1406 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3
},
1407 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2
},
1408 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs
},
1409 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs
},
1410 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs
},
1411 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs
},
1412 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs
},
1413 { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4
},
1414 { "gfs2", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs2
},
1415 { "gfs", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs
},
1416 { "vfat", 0, 0x52, 5, "MSWIN", probe_fat
},
1417 { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat
},
1418 { "vfat", 0, 0x36, 5, "MSDOS", probe_fat
},
1419 { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat
},
1420 { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat
},
1421 { "vfat", 0, 0, 1, "\353", probe_fat_nomagic
},
1422 { "vfat", 0, 0, 1, "\351", probe_fat_nomagic
},
1423 { "vfat", 0, 0x1fe, 2, "\125\252", probe_fat_nomagic
},
1424 { "minix", 1, 0x10, 2, "\177\023", 0 },
1425 { "minix", 1, 0x10, 2, "\217\023", 0 },
1426 { "minix", 1, 0x10, 2, "\150\044", 0 },
1427 { "minix", 1, 0x10, 2, "\170\044", 0 },
1428 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
1429 { "xfs", 0, 0, 4, "XFSB", probe_xfs
},
1430 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs
},
1431 { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
1432 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs
},
1433 { "qnx4", 0, 4, 6, "QNX4FS", 0 },
1434 { "udf", 32, 1, 5, "BEA01", probe_udf
},
1435 { "udf", 32, 1, 5, "BOOT2", probe_udf
},
1436 { "udf", 32, 1, 5, "CD001", probe_udf
},
1437 { "udf", 32, 1, 5, "CDW02", probe_udf
},
1438 { "udf", 32, 1, 5, "NSR02", probe_udf
},
1439 { "udf", 32, 1, 5, "NSR03", probe_udf
},
1440 { "udf", 32, 1, 5, "TEA01", probe_udf
},
1441 { "iso9660", 32, 1, 5, "CD001", probe_iso9660
},
1442 { "iso9660", 32, 9, 5, "CDROM", probe_iso9660
},
1443 { "jfs", 32, 0, 4, "JFS1", probe_jfs
},
1444 /* ZFS has 128 root blocks (#4 is the first used), check only 6 of them */
1445 { "zfs", 128, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1446 { "zfs", 128, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1447 { "zfs", 132, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1448 { "zfs", 132, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1449 { "zfs", 136, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1450 { "zfs", 136, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1451 { "zfs", 384, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1452 { "zfs", 384, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1453 { "zfs", 388, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1454 { "zfs", 388, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1455 { "zfs", 392, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1456 { "zfs", 392, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1457 { "hfsplus", 1, 0, 2, "BD", probe_hfsplus
},
1458 { "hfsplus", 1, 0, 2, "H+", probe_hfsplus
},
1459 { "hfsplus", 1, 0, 2, "HX", probe_hfsplus
},
1460 { "hfs", 1, 0, 2, "BD", probe_hfs
},
1461 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
1462 { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
1463 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
1464 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0
},
1465 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1
},
1466 { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1
},
1467 { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1
},
1468 { "swsuspend", 0, 0xff6, 9, "ULSUSPEND", probe_swap1
},
1469 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0
},
1470 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1
},
1471 { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1
},
1472 { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1
},
1473 { "swsuspend", 0, 0x1ff6, 9, "ULSUSPEND", probe_swap1
},
1474 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0
},
1475 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1
},
1476 { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1
},
1477 { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1
},
1478 { "swsuspend", 0, 0x3ff6, 9, "ULSUSPEND", probe_swap1
},
1479 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0
},
1480 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1
},
1481 { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1
},
1482 { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1
},
1483 { "swsuspend", 0, 0x7ff6, 9, "ULSUSPEND", probe_swap1
},
1484 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0
},
1485 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1
},
1486 { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1
},
1487 { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1
},
1488 { "swsuspend", 0, 0xfff6, 9, "ULSUSPEND", probe_swap1
},
1489 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs
},
1490 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2
},
1491 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2
},
1492 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2
},
1493 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2
},
1494 { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks
},
1495 { "squashfs", 0, 0, 4, "sqsh", 0 },
1496 { "squashfs", 0, 0, 4, "hsqs", 0 },
1497 { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2
},
1498 { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2
},
1499 { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2
},
1500 { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2
},
1501 { "btrfs", 64, 0x40, 8, "_BHRfS_M", probe_btrfs
},
1502 { NULL
, 0, 0, 0, NULL
, NULL
}
1506 * Verify that the data in dev is consistent with what is on the actual
1507 * block device (using the devname field only). Normally this will be
1508 * called when finding items in the cache, but for long running processes
1509 * is also desirable to revalidate an item before use.
1511 * If we are unable to revalidate the data, we return the old data and
1512 * do not set the BLKID_BID_FL_VERIFIED flag on it.
1514 blkid_dev
blkid_verify(blkid_cache cache
, blkid_dev dev
)
1516 struct blkid_magic
*id
;
1517 struct blkid_probe probe
;
1518 blkid_tag_iterate iter
;
1520 const char *type
, *value
;
1529 diff
= now
- dev
->bid_time
;
1531 if (stat(dev
->bid_name
, &st
) < 0) {
1533 printf("blkid_verify: error %s (%d) while "
1534 "trying to stat %s\n", strerror(errno
), errno
,
1537 if ((errno
== EPERM
) || (errno
== EACCES
) || (errno
== ENOENT
)) {
1538 /* We don't have read permission, just return cache data. */
1539 DBG(DEBUG_PROBE
, printf("returning unverified data for %s\n",
1543 blkid_free_dev(dev
);
1547 if ((now
>= dev
->bid_time
) &&
1548 (st
.st_mtime
<= dev
->bid_time
) &&
1549 ((diff
< BLKID_PROBE_MIN
) ||
1550 (dev
->bid_flags
& BLKID_BID_FL_VERIFIED
&&
1551 diff
< BLKID_PROBE_INTERVAL
)))
1555 printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
1556 "time since last check %lu)\n",
1557 dev
->bid_name
, (unsigned long)dev
->bid_time
,
1558 (unsigned long)st
.st_mtime
, (unsigned long)diff
));
1560 if ((probe
.fd
= open(dev
->bid_name
, O_RDONLY
)) < 0) {
1561 DBG(DEBUG_PROBE
, printf("blkid_verify: error %s (%d) while "
1562 "opening %s\n", strerror(errno
), errno
,
1567 probe
.cache
= cache
;
1574 * Iterate over the type array. If we already know the type,
1575 * then try that first. If it doesn't work, then blow away
1576 * the type information, and try again.
1581 if (!dev
->bid_type
|| !strcmp(dev
->bid_type
, "mdraid")) {
1584 if (check_mdraid(probe
.fd
, uuid
) == 0) {
1585 set_uuid(dev
, uuid
, 0);
1590 for (id
= type_array
; id
->bim_type
; id
++) {
1591 if (dev
->bid_type
&&
1592 strcmp(id
->bim_type
, dev
->bid_type
))
1595 idx
= id
->bim_kboff
+ (id
->bim_sboff
>> 10);
1596 buf
= get_buffer(&probe
, (__u64
) idx
<< 10, 1024);
1600 if (memcmp(id
->bim_magic
, buf
+ (id
->bim_sboff
& 0x3ff),
1604 if ((id
->bim_probe
== NULL
) ||
1605 (id
->bim_probe(&probe
, id
, buf
) == 0)) {
1606 type
= id
->bim_type
;
1611 if (!id
->bim_type
&& dev
->bid_type
) {
1613 * Zap the device filesystem information and try again
1616 printf("previous fs type %s not valid, "
1617 "trying full probe\n", dev
->bid_type
));
1618 iter
= blkid_tag_iterate_begin(dev
);
1619 while (blkid_tag_next(iter
, &type
, &value
) == 0)
1620 blkid_set_tag(dev
, type
, 0, 0);
1621 blkid_tag_iterate_end(iter
);
1625 if (!dev
->bid_type
) {
1626 blkid_free_dev(dev
);
1633 dev
->bid_devno
= st
.st_rdev
;
1634 dev
->bid_time
= time(0);
1635 dev
->bid_flags
|= BLKID_BID_FL_VERIFIED
;
1636 cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
1638 blkid_set_tag(dev
, "TYPE", type
, 0);
1640 DBG(DEBUG_PROBE
, printf("%s: devno 0x%04llx, type %s\n",
1641 dev
->bid_name
, (long long)st
.st_rdev
, type
));
1652 int blkid_known_fstype(const char *fstype
)
1654 struct blkid_magic
*id
;
1656 for (id
= type_array
; id
->bim_type
; id
++) {
1657 if (strcmp(fstype
, id
->bim_type
) == 0)
1664 int main(int argc
, char **argv
)
1671 fprintf(stderr
, "Usage: %s device\n"
1672 "Probe a single device to determine type\n", argv
[0]);
1675 if ((ret
= blkid_get_cache(&cache
, "/dev/null")) != 0) {
1676 fprintf(stderr
, "%s: error creating cache (%d)\n",
1680 dev
= blkid_get_dev(cache
, argv
[1], BLKID_DEV_NORMAL
);
1682 printf("%s: %s has an unsupported type\n", argv
[0], argv
[1]);
1685 printf("TYPE='%s'\n", dev
->bid_type
? dev
->bid_type
: "(null)");
1687 printf("LABEL='%s'\n", dev
->bid_label
);
1689 printf("UUID='%s'\n", dev
->bid_uuid
);
1691 blkid_free_dev(dev
);