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
;
109 /* Check for magic number */
110 if (memcmp("\251+N\374", buf
, 4) && memcmp("\374N+\251", buf
, 4))
111 return -BLKID_ERR_PARAM
;
117 /* The MD UUID is not contiguous in the superblock, make it so */
118 md
= (struct mdp_superblock_s
*)buf
;
119 if (md
->set_uuid0
|| md
->set_uuid1
|| md
->set_uuid2
|| md
->set_uuid3
) {
120 memcpy(ret_uuid
, &md
->set_uuid0
, 4);
121 memcpy(ret_uuid
+ 4, &md
->set_uuid1
, 12);
126 static void set_uuid(blkid_dev dev
, uuid_t uuid
, const char *tag
)
130 if (!uuid_is_null(uuid
)) {
131 uuid_unparse(uuid
, str
);
132 blkid_set_tag(dev
, tag
? tag
: "UUID", str
, sizeof(str
));
136 static void get_ext2_info(blkid_dev dev
, struct blkid_magic
*id
,
139 struct ext2_super_block
*es
= (struct ext2_super_block
*) buf
;
140 const char *label
= 0;
142 DBG(DEBUG_PROBE
, printf("ext2_sb.compat = %08X:%08X:%08X\n",
143 blkid_le32(es
->s_feature_compat
),
144 blkid_le32(es
->s_feature_incompat
),
145 blkid_le32(es
->s_feature_ro_compat
)));
147 if (strlen(es
->s_volume_name
))
148 label
= es
->s_volume_name
;
149 blkid_set_tag(dev
, "LABEL", label
, sizeof(es
->s_volume_name
));
151 set_uuid(dev
, es
->s_uuid
, 0);
153 if ((es
->s_feature_compat
& EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
154 !uuid_is_null(es
->s_journal_uuid
))
155 set_uuid(dev
, es
->s_journal_uuid
, "EXT_JOURNAL");
157 if (strcmp(id
->bim_type
, "ext2") &&
158 ((blkid_le32(es
->s_feature_incompat
) &
159 EXT2_FEATURE_INCOMPAT_UNSUPPORTED
) == 0))
160 blkid_set_tag(dev
, "SEC_TYPE", "ext2", sizeof("ext2"));
164 * Check to see if a filesystem is in /proc/filesystems.
165 * Returns 1 if found, 0 if not
167 static int fs_proc_check(const char *fs_name
)
170 char buf
[80], *cp
, *t
;
172 f
= fopen("/proc/filesystems", "r");
176 if (!fgets(buf
, sizeof(buf
), f
))
180 while (*cp
&& !isspace(*cp
))
183 while (*cp
&& isspace(*cp
))
185 if ((t
= strchr(cp
, '\n')) != NULL
)
187 if ((t
= strchr(cp
, '\t')) != NULL
)
189 if ((t
= strchr(cp
, ' ')) != NULL
)
191 if (!strcmp(fs_name
, cp
)) {
201 * Check to see if a filesystem is available as a module
202 * Returns 1 if found, 0 if not
204 static int check_for_modules(const char *fs_name
)
214 snprintf(buf
, sizeof(buf
), "/lib/modules/%s/modules.dep", uts
.release
);
220 namesz
= strlen(fs_name
);
223 if (!fgets(buf
, sizeof(buf
), f
))
225 if ((cp
= strchr(buf
, ':')) != NULL
)
229 if ((cp
= strrchr(buf
, '/')) != NULL
)
233 if (!strncmp(cp
, fs_name
, namesz
) &&
234 (!strcmp(cp
+ namesz
, ".ko") ||
235 !strcmp(cp
+ namesz
, ".ko.gz"))) {
245 static int linux_version_code(void)
249 static int version_code
= -1;
250 int major
, minor
, rev
;
254 if (version_code
> 0)
261 major
= strtol(cp
, &endptr
, 10);
262 if (cp
== endptr
|| *endptr
!= '.')
265 minor
= strtol(cp
, &endptr
, 10);
266 if (cp
== endptr
|| *endptr
!= '.')
269 rev
= strtol(cp
, &endptr
, 10);
272 version_code
= (((major
* 256) + minor
) * 256) + rev
;
279 #define EXT4_SUPPORTS_EXT2 (2 * 65536 + 6*256 + 29)
281 static int system_supports_ext2(void)
283 static time_t last_check
= 0;
285 time_t now
= time(0);
287 if (ret
!= -1 || (now
- last_check
) < 5)
290 ret
= (fs_proc_check("ext2") || check_for_modules("ext2"));
294 static int system_supports_ext4(void)
296 static time_t last_check
= 0;
298 time_t now
= time(0);
300 if (ret
!= -1 || (now
- last_check
) < 5)
303 ret
= (fs_proc_check("ext4") || check_for_modules("ext4"));
307 static int system_supports_ext4dev(void)
309 static time_t last_check
= 0;
311 time_t now
= time(0);
313 if (ret
!= -1 || (now
- last_check
) < 5)
316 ret
= (fs_proc_check("ext4dev") || check_for_modules("ext4dev"));
320 static int probe_ext4dev(struct blkid_probe
*probe
,
321 struct blkid_magic
*id
,
324 struct ext2_super_block
*es
;
325 es
= (struct ext2_super_block
*)buf
;
327 /* Distinguish from jbd */
328 if (blkid_le32(es
->s_feature_incompat
) &
329 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)
330 return -BLKID_ERR_PARAM
;
333 * If the filesystem does not have a journal and ext2 and ext4
334 * is not present, then force this to be detected as an
335 * ext4dev filesystem.
337 if (!(blkid_le32(es
->s_feature_compat
) &
338 EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
339 !system_supports_ext2() && !system_supports_ext4() &&
340 system_supports_ext4dev() &&
341 linux_version_code() >= EXT4_SUPPORTS_EXT2
)
345 * If the filesystem is marked as OK for use by in-development
346 * filesystem code, but ext4dev is not supported, and ext4 is,
347 * then don't call ourselves ext4dev, since we should be
348 * detected as ext4 in that case.
350 * If the filesystem is marked as in use by production
351 * filesystem, then it can only be used by ext4 and NOT by
352 * ext4dev, so always disclaim we are ext4dev in that case.
354 if (blkid_le32(es
->s_flags
) & EXT2_FLAGS_TEST_FILESYS
) {
355 if (!system_supports_ext4dev() && system_supports_ext4())
356 return -BLKID_ERR_PARAM
;
358 return -BLKID_ERR_PARAM
;
361 get_ext2_info(probe
->dev
, id
, buf
);
365 static int probe_ext4(struct blkid_probe
*probe
, struct blkid_magic
*id
,
368 struct ext2_super_block
*es
;
369 es
= (struct ext2_super_block
*)buf
;
371 /* Distinguish from jbd */
372 if (blkid_le32(es
->s_feature_incompat
) &
373 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)
374 return -BLKID_ERR_PARAM
;
377 * If the filesystem does not have a journal and ext2 is not
378 * present, then force this to be detected as an ext2
381 if (!(blkid_le32(es
->s_feature_compat
) &
382 EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
383 !system_supports_ext2() && system_supports_ext4() &&
384 linux_version_code() >= EXT4_SUPPORTS_EXT2
)
387 /* Ext4 has at least one feature which ext3 doesn't understand */
388 if (!(blkid_le32(es
->s_feature_ro_compat
) &
389 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED
) &&
390 !(blkid_le32(es
->s_feature_incompat
) &
391 EXT3_FEATURE_INCOMPAT_UNSUPPORTED
))
392 return -BLKID_ERR_PARAM
;
396 * If the filesystem is a OK for use by in-development
397 * filesystem code, and ext4dev is supported or ext4 is not
398 * supported, then don't call ourselves ext4, so we can redo
399 * the detection and mark the filesystem as ext4dev.
401 * If the filesystem is marked as in use by production
402 * filesystem, then it can only be used by ext4 and NOT by
405 if (blkid_le32(es
->s_flags
) & EXT2_FLAGS_TEST_FILESYS
) {
406 if (system_supports_ext4dev() || !system_supports_ext4())
407 return -BLKID_ERR_PARAM
;
409 get_ext2_info(probe
->dev
, id
, buf
);
413 static int probe_ext3(struct blkid_probe
*probe
, struct blkid_magic
*id
,
416 struct ext2_super_block
*es
;
417 es
= (struct ext2_super_block
*)buf
;
419 /* ext3 requires journal */
420 if (!(blkid_le32(es
->s_feature_compat
) &
421 EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
422 return -BLKID_ERR_PARAM
;
424 /* Any features which ext3 doesn't understand */
425 if ((blkid_le32(es
->s_feature_ro_compat
) &
426 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED
) ||
427 (blkid_le32(es
->s_feature_incompat
) &
428 EXT3_FEATURE_INCOMPAT_UNSUPPORTED
))
429 return -BLKID_ERR_PARAM
;
431 get_ext2_info(probe
->dev
, id
, buf
);
435 static int probe_ext2(struct blkid_probe
*probe
, struct blkid_magic
*id
,
438 struct ext2_super_block
*es
;
440 es
= (struct ext2_super_block
*)buf
;
442 /* Distinguish between ext3 and ext2 */
443 if ((blkid_le32(es
->s_feature_compat
) &
444 EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
445 return -BLKID_ERR_PARAM
;
447 /* Any features which ext2 doesn't understand */
448 if ((blkid_le32(es
->s_feature_ro_compat
) &
449 EXT2_FEATURE_RO_COMPAT_UNSUPPORTED
) ||
450 (blkid_le32(es
->s_feature_incompat
) &
451 EXT2_FEATURE_INCOMPAT_UNSUPPORTED
))
452 return -BLKID_ERR_PARAM
;
455 * If ext2 is not present, but ext4 or ext4dev are, then
456 * disclaim we are ext2
458 if (!system_supports_ext2() &&
459 (system_supports_ext4() || system_supports_ext4dev()) &&
460 linux_version_code() >= EXT4_SUPPORTS_EXT2
)
461 return -BLKID_ERR_PARAM
;
463 get_ext2_info(probe
->dev
, id
, buf
);
467 static int probe_jbd(struct blkid_probe
*probe
, struct blkid_magic
*id
,
470 struct ext2_super_block
*es
= (struct ext2_super_block
*) buf
;
472 if (!(blkid_le32(es
->s_feature_incompat
) &
473 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
))
474 return -BLKID_ERR_PARAM
;
476 get_ext2_info(probe
->dev
, id
, buf
);
481 #define FAT_ATTR_VOLUME_ID 0x08
482 #define FAT_ATTR_DIR 0x10
483 #define FAT_ATTR_LONG_NAME 0x0f
484 #define FAT_ATTR_MASK 0x3f
485 #define FAT_ENTRY_FREE 0xe5
487 static const char *no_name
= "NO NAME ";
489 static unsigned char *search_fat_label(struct vfat_dir_entry
*dir
, int count
)
493 for (i
= 0; i
< count
; i
++) {
494 if (dir
[i
].name
[0] == 0x00)
497 if ((dir
[i
].name
[0] == FAT_ENTRY_FREE
) ||
498 (dir
[i
].cluster_high
!= 0 || dir
[i
].cluster_low
!= 0) ||
499 ((dir
[i
].attr
& FAT_ATTR_MASK
) == FAT_ATTR_LONG_NAME
))
502 if ((dir
[i
].attr
& (FAT_ATTR_VOLUME_ID
| FAT_ATTR_DIR
)) ==
503 FAT_ATTR_VOLUME_ID
) {
510 /* FAT label extraction from the root directory taken from Kay
511 * Sievers's volume_id library */
512 static int probe_fat(struct blkid_probe
*probe
,
513 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
516 struct vfat_super_block
*vs
= (struct vfat_super_block
*) buf
;
517 struct msdos_super_block
*ms
= (struct msdos_super_block
*) buf
;
518 struct vfat_dir_entry
*dir
;
520 const unsigned char *label
= 0, *vol_label
= 0, *tmp
;
521 unsigned char *vol_serno
;
522 int label_len
= 0, maxloop
= 100;
523 __u16 sector_size
, dir_entries
, reserved
;
524 __u32 sect_count
, fat_size
, dir_size
, cluster_count
, fat_length
;
525 __u32 buf_size
, start_data_sect
, next
, root_start
, root_dir_entries
;
527 /* sector size check */
528 tmp
= (unsigned char *)&ms
->ms_sector_size
;
529 sector_size
= tmp
[0] + (tmp
[1] << 8);
530 if (sector_size
!= 0x200 && sector_size
!= 0x400 &&
531 sector_size
!= 0x800 && sector_size
!= 0x1000)
534 tmp
= (unsigned char *)&ms
->ms_dir_entries
;
535 dir_entries
= tmp
[0] + (tmp
[1] << 8);
536 reserved
= blkid_le16(ms
->ms_reserved
);
537 tmp
= (unsigned char *)&ms
->ms_sectors
;
538 sect_count
= tmp
[0] + (tmp
[1] << 8);
540 sect_count
= blkid_le32(ms
->ms_total_sect
);
542 fat_length
= blkid_le16(ms
->ms_fat_length
);
544 fat_length
= blkid_le32(vs
->vs_fat32_length
);
546 fat_size
= fat_length
* ms
->ms_fats
;
547 dir_size
= ((dir_entries
* sizeof(struct vfat_dir_entry
)) +
548 (sector_size
-1)) / sector_size
;
550 cluster_count
= sect_count
- (reserved
+ fat_size
+ dir_size
);
551 if (ms
->ms_cluster_size
== 0)
553 cluster_count
/= ms
->ms_cluster_size
;
555 if (cluster_count
> FAT32_MAX
)
558 if (ms
->ms_fat_length
) {
559 /* the label may be an attribute in the root directory */
560 root_start
= (reserved
+ fat_size
) * sector_size
;
561 root_dir_entries
= vs
->vs_dir_entries
[0] +
562 (vs
->vs_dir_entries
[1] << 8);
564 buf_size
= root_dir_entries
* sizeof(struct vfat_dir_entry
);
565 dir
= (struct vfat_dir_entry
*) get_buffer(probe
, root_start
,
568 vol_label
= search_fat_label(dir
, root_dir_entries
);
570 if (!vol_label
|| !memcmp(vol_label
, no_name
, 11))
571 vol_label
= ms
->ms_label
;
572 vol_serno
= ms
->ms_serno
;
574 blkid_set_tag(probe
->dev
, "SEC_TYPE", "msdos",
577 /* Search the FAT32 root dir for the label attribute */
578 buf_size
= vs
->vs_cluster_size
* sector_size
;
579 start_data_sect
= reserved
+ fat_size
;
581 next
= blkid_le32(vs
->vs_root_cluster
);
582 while (next
&& --maxloop
) {
584 __u64 next_off
, fat_entry_off
;
587 next_sect_off
= (next
- 2) * vs
->vs_cluster_size
;
588 next_off
= (__u64
) (start_data_sect
+ next_sect_off
) *
591 dir
= (struct vfat_dir_entry
*)
592 get_buffer(probe
, next_off
, buf_size
);
596 count
= buf_size
/ sizeof(struct vfat_dir_entry
);
598 vol_label
= search_fat_label(dir
, count
);
604 ((unsigned int) reserved
*
605 (unsigned int) sector_size
) +
606 (next
* sizeof(__u32
));
607 buf
= get_buffer(probe
, fat_entry_off
, buf_size
);
611 /* set next cluster */
612 next
= blkid_le32(*((__u32
*) buf
) & 0x0fffffff);
615 if (!vol_label
|| !memcmp(vol_label
, no_name
, 11))
616 vol_label
= vs
->vs_label
;
617 vol_serno
= vs
->vs_serno
;
620 if (vol_label
&& memcmp(vol_label
, no_name
, 11)) {
621 if ((label_len
= figure_label_len(vol_label
, 11)))
625 /* We can't just print them as %04X, because they are unaligned */
626 sprintf(serno
, "%02X%02X-%02X%02X", vol_serno
[3], vol_serno
[2],
627 vol_serno
[1], vol_serno
[0]);
629 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
, label_len
);
630 blkid_set_tag(probe
->dev
, "UUID", serno
, sizeof(serno
)-1);
636 * The FAT filesystem could be without a magic string in superblock
637 * (e.g. old floppies). This heuristic for FAT detection is inspired
638 * by http://vrfy.org/projects/volume_id/ and Linux kernel.
639 * [7-Jul-2005, Karel Zak <kzak@redhat.com>]
641 static int probe_fat_nomagic(struct blkid_probe
*probe
,
642 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
645 struct msdos_super_block
*ms
;
647 ms
= (struct msdos_super_block
*)buf
;
650 if (ms
->ms_heads
== 0)
653 /* cluster size check*/
654 if (ms
->ms_cluster_size
== 0 ||
655 (ms
->ms_cluster_size
& (ms
->ms_cluster_size
-1)))
659 if (ms
->ms_media
< 0xf8 && ms
->ms_media
!= 0xf0)
662 /* fat counts(Linux kernel expects at least 1 FAT table) */
667 * OS/2 and apparently DFSee will place a FAT12/16-like
668 * pseudo-superblock in the first 512 bytes of non-FAT
669 * filesystems --- at least JFS and HPFS, and possibly others.
670 * So we explicitly check for those filesystems at the
671 * FAT12/16 filesystem magic field identifier, and if they are
672 * present, we rule this out as a FAT filesystem, despite the
673 * FAT-like pseudo-header.
675 if ((memcmp(ms
->ms_magic
, "JFS ", 8) == 0) ||
676 (memcmp(ms
->ms_magic
, "HPFS ", 8) == 0))
679 return probe_fat(probe
, id
, buf
);
682 static int probe_ntfs(struct blkid_probe
*probe
,
683 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
686 struct ntfs_super_block
*ns
;
687 struct master_file_table_record
*mft
;
688 struct file_attribute
*attr
;
689 char uuid_str
[17], label_str
[129], *cp
;
690 int bytes_per_sector
, sectors_per_cluster
;
691 int mft_record_size
, attr_off
, attr_len
;
692 unsigned int i
, attr_type
, val_len
;
696 unsigned char *buf_mft
, *val
;
698 ns
= (struct ntfs_super_block
*) buf
;
700 bytes_per_sector
= ns
->bios_parameter_block
[0] +
701 (ns
->bios_parameter_block
[1] << 8);
702 sectors_per_cluster
= ns
->bios_parameter_block
[2];
704 if ((bytes_per_sector
< 512) || (sectors_per_cluster
== 0))
707 if (ns
->cluster_per_mft_record
< 0)
708 mft_record_size
= 1 << (0-ns
->cluster_per_mft_record
);
710 mft_record_size
= ns
->cluster_per_mft_record
*
711 sectors_per_cluster
* bytes_per_sector
;
712 nr_clusters
= blkid_le64(ns
->number_of_sectors
) / sectors_per_cluster
;
714 if ((blkid_le64(ns
->mft_cluster_location
) > nr_clusters
) ||
715 (blkid_le64(ns
->mft_mirror_cluster_location
) > nr_clusters
))
718 off
= blkid_le64(ns
->mft_mirror_cluster_location
) *
719 bytes_per_sector
* sectors_per_cluster
;
721 buf_mft
= get_buffer(probe
, off
, mft_record_size
);
725 if (memcmp(buf_mft
, "FILE", 4))
728 off
= blkid_le64(ns
->mft_cluster_location
) * bytes_per_sector
*
731 buf_mft
= get_buffer(probe
, off
, mft_record_size
);
735 if (memcmp(buf_mft
, "FILE", 4))
738 off
+= MFT_RECORD_VOLUME
* mft_record_size
;
740 buf_mft
= get_buffer(probe
, off
, mft_record_size
);
744 if (memcmp(buf_mft
, "FILE", 4))
747 mft
= (struct master_file_table_record
*) buf_mft
;
749 attr_off
= blkid_le16(mft
->attrs_offset
);
753 attr
= (struct file_attribute
*) (buf_mft
+ attr_off
);
754 attr_len
= blkid_le16(attr
->len
);
755 attr_type
= blkid_le32(attr
->type
);
756 val_off
= blkid_le16(attr
->value_offset
);
757 val_len
= blkid_le32(attr
->value_len
);
759 attr_off
+= attr_len
;
761 if ((attr_off
> mft_record_size
) ||
765 if (attr_type
== MFT_RECORD_ATTR_END
)
768 if (attr_type
== MFT_RECORD_ATTR_VOLUME_NAME
) {
769 if (val_len
> sizeof(label_str
))
770 val_len
= sizeof(label_str
)-1;
772 for (i
=0, cp
=label_str
; i
< val_len
; i
+=2,cp
++) {
773 val
= ((__u8
*) attr
) + val_off
+ i
;
782 sprintf(uuid_str
, "%016llX", blkid_le64(ns
->volume_serial
));
783 blkid_set_tag(probe
->dev
, "UUID", uuid_str
, 0);
785 blkid_set_tag(probe
->dev
, "LABEL", label_str
, 0);
790 static int probe_xfs(struct blkid_probe
*probe
,
791 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
794 struct xfs_super_block
*xs
;
795 const char *label
= 0;
797 xs
= (struct xfs_super_block
*)buf
;
799 if (strlen(xs
->xs_fname
))
800 label
= xs
->xs_fname
;
801 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(xs
->xs_fname
));
802 set_uuid(probe
->dev
, xs
->xs_uuid
, 0);
806 static int probe_reiserfs(struct blkid_probe
*probe
,
807 struct blkid_magic
*id
, unsigned char *buf
)
809 struct reiserfs_super_block
*rs
= (struct reiserfs_super_block
*) buf
;
810 unsigned int blocksize
;
811 const char *label
= 0;
813 blocksize
= blkid_le16(rs
->rs_blocksize
);
815 /* The blocksize must be at least 1k */
816 if ((blocksize
>> 10) == 0)
817 return -BLKID_ERR_PARAM
;
819 /* If the superblock is inside the journal, we have the wrong one */
820 if (id
->bim_kboff
/(blocksize
>>10) > blkid_le32(rs
->rs_journal_block
))
821 return -BLKID_ERR_BIG
;
823 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
824 if (id
->bim_magic
[6] == '2' || id
->bim_magic
[6] == '3') {
825 if (strlen(rs
->rs_label
))
826 label
= rs
->rs_label
;
827 set_uuid(probe
->dev
, rs
->rs_uuid
, 0);
829 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(rs
->rs_label
));
834 static int probe_reiserfs4(struct blkid_probe
*probe
,
835 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
838 struct reiser4_super_block
*rs4
= (struct reiser4_super_block
*) buf
;
839 const unsigned char *label
= 0;
841 if (strlen((char *) rs4
->rs4_label
))
842 label
= rs4
->rs4_label
;
843 set_uuid(probe
->dev
, rs4
->rs4_uuid
, 0);
844 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
,
845 sizeof(rs4
->rs4_label
));
850 static int probe_jfs(struct blkid_probe
*probe
,
851 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
854 struct jfs_super_block
*js
;
855 const char *label
= 0;
857 js
= (struct jfs_super_block
*)buf
;
859 if (blkid_le32(js
->js_bsize
) != (1U << blkid_le16(js
->js_l2bsize
)))
862 if (blkid_le32(js
->js_pbsize
) != (1U << blkid_le16(js
->js_l2pbsize
)))
865 if ((blkid_le16(js
->js_l2bsize
) - blkid_le16(js
->js_l2pbsize
)) !=
866 blkid_le16(js
->js_l2bfactor
))
869 if (strlen((char *) js
->js_label
))
870 label
= (char *) js
->js_label
;
871 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(js
->js_label
));
872 set_uuid(probe
->dev
, js
->js_uuid
, 0);
876 static int probe_zfs(struct blkid_probe
*probe
__BLKID_ATTR((unused
)),
877 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
878 unsigned char *buf
__BLKID_ATTR((unused
)))
882 const char *pool_name
= 0;
884 /* read nvpair data for pool name, pool GUID (complex) */
885 blkid_set_tag(probe
->dev
, "LABEL", pool_name
, sizeof(pool_name
));
886 set_uuid(probe
->dev
, pool_guid
, 0);
891 static int probe_luks(struct blkid_probe
*probe
,
892 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
897 /* 168 is the offset to the 40 character uuid:
898 * http://luks.endorphin.org/LUKS-on-disk-format.pdf */
899 strncpy(uuid
, (char *) buf
+168, 40);
900 blkid_set_tag(probe
->dev
, "UUID", uuid
, sizeof(uuid
));
904 static int probe_romfs(struct blkid_probe
*probe
,
905 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
908 struct romfs_super_block
*ros
;
909 const char *label
= 0;
911 ros
= (struct romfs_super_block
*)buf
;
913 if (strlen((char *) ros
->ros_volume
))
914 label
= (char *) ros
->ros_volume
;
915 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
919 static int probe_cramfs(struct blkid_probe
*probe
,
920 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
923 struct cramfs_super_block
*csb
;
924 const char *label
= 0;
926 csb
= (struct cramfs_super_block
*)buf
;
928 if (strlen((char *) csb
->name
))
929 label
= (char *) csb
->name
;
930 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
934 static int probe_swap0(struct blkid_probe
*probe
,
935 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
936 unsigned char *buf
__BLKID_ATTR((unused
)))
938 blkid_set_tag(probe
->dev
, "UUID", 0, 0);
939 blkid_set_tag(probe
->dev
, "LABEL", 0, 0);
943 static int probe_swap1(struct blkid_probe
*probe
,
944 struct blkid_magic
*id
,
945 unsigned char *buf
__BLKID_ATTR((unused
)))
947 struct swap_id_block
*sws
;
949 probe_swap0(probe
, id
, buf
);
951 * Version 1 swap headers are always located at offset of 1024
952 * bytes, although the swap signature itself is located at the
953 * end of the page (which may vary depending on hardware
956 sws
= (struct swap_id_block
*) get_buffer(probe
, 1024, 1024);
960 /* check for wrong version or zeroed pagecount, for sanity */
961 if (!memcmp(id
->bim_magic
, "SWAPSPACE2", id
->bim_len
) &&
962 (sws
->sws_version
!= 1 || sws
->sws_lastpage
== 0))
965 /* arbitrary sanity check.. is there any garbage down there? */
966 if (sws
->sws_pad
[32] == 0 && sws
->sws_pad
[33] == 0) {
967 if (sws
->sws_volume
[0])
968 blkid_set_tag(probe
->dev
, "LABEL", sws
->sws_volume
,
969 sizeof(sws
->sws_volume
));
970 if (sws
->sws_uuid
[0])
971 set_uuid(probe
->dev
, sws
->sws_uuid
, 0);
976 static int probe_iso9660(struct blkid_probe
*probe
,
977 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
980 struct iso_volume_descriptor
*iso
;
981 const unsigned char *label
;
983 iso
= (struct iso_volume_descriptor
*) buf
;
984 label
= iso
->volume_id
;
986 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
,
987 figure_label_len(label
, 32));
993 *udf_magic
[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
994 "NSR03", "TEA01", 0 };
996 static int probe_udf(struct blkid_probe
*probe
,
997 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
998 unsigned char *buf
__BLKID_ATTR((unused
)))
1001 struct iso_volume_descriptor
*isosb
;
1004 /* determine the block size by scanning in 2K increments
1005 (block sizes larger than 2K will be null padded) */
1006 for (bs
= 1; bs
< 16; bs
++) {
1007 isosb
= (struct iso_volume_descriptor
*)
1008 get_buffer(probe
, (blkid_loff_t
) bs
*2048+32768,
1012 if (isosb
->vd_id
[0])
1016 /* Scan up to another 64 blocks looking for additional VSD's */
1017 for (j
= 1; j
< 64; j
++) {
1019 isosb
= (struct iso_volume_descriptor
*)
1020 get_buffer(probe
, j
*bs
*2048+32768,
1025 /* If we find NSR0x then call it udf:
1028 NSR03 for UDF 2.00 */
1029 if (!memcmp(isosb
->vd_id
, "NSR0", 4))
1030 return probe_iso9660(probe
, id
, buf
);
1031 for (m
= udf_magic
; *m
; m
++)
1032 if (!memcmp(*m
, isosb
->vd_id
, 5))
1040 static int probe_ocfs(struct blkid_probe
*probe
,
1041 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1044 struct ocfs_volume_header ovh
;
1045 struct ocfs_volume_label ovl
;
1048 memcpy(&ovh
, buf
, sizeof(ovh
));
1049 memcpy(&ovl
, buf
+512, sizeof(ovl
));
1051 major
= ocfsmajor(ovh
);
1053 blkid_set_tag(probe
->dev
,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
1054 else if (major
>= 9)
1055 blkid_set_tag(probe
->dev
,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
1057 blkid_set_tag(probe
->dev
, "LABEL", ovl
.label
, ocfslabellen(ovl
));
1058 blkid_set_tag(probe
->dev
, "MOUNT", ovh
.mount
, ocfsmountlen(ovh
));
1059 set_uuid(probe
->dev
, ovl
.vol_id
, 0);
1063 static int probe_ocfs2(struct blkid_probe
*probe
,
1064 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1067 struct ocfs2_super_block
*osb
;
1069 osb
= (struct ocfs2_super_block
*)buf
;
1071 blkid_set_tag(probe
->dev
, "LABEL", osb
->s_label
, sizeof(osb
->s_label
));
1072 set_uuid(probe
->dev
, osb
->s_uuid
, 0);
1076 static int probe_oracleasm(struct blkid_probe
*probe
,
1077 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1080 struct oracle_asm_disk_label
*dl
;
1082 dl
= (struct oracle_asm_disk_label
*)buf
;
1084 blkid_set_tag(probe
->dev
, "LABEL", dl
->dl_id
, sizeof(dl
->dl_id
));
1088 static int probe_gfs(struct blkid_probe
*probe
,
1089 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1092 struct gfs2_sb
*sbd
;
1093 const char *label
= 0;
1095 sbd
= (struct gfs2_sb
*)buf
;
1097 if (blkid_be32(sbd
->sb_fs_format
) == GFS_FORMAT_FS
&&
1098 blkid_be32(sbd
->sb_multihost_format
) == GFS_FORMAT_MULTI
)
1100 blkid_set_tag(probe
->dev
, "UUID", 0, 0);
1102 if (strlen(sbd
->sb_locktable
))
1103 label
= sbd
->sb_locktable
;
1104 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(sbd
->sb_locktable
));
1110 static int probe_gfs2(struct blkid_probe
*probe
,
1111 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1114 struct gfs2_sb
*sbd
;
1115 const char *label
= 0;
1117 sbd
= (struct gfs2_sb
*)buf
;
1119 if (blkid_be32(sbd
->sb_fs_format
) == GFS2_FORMAT_FS
&&
1120 blkid_be32(sbd
->sb_multihost_format
) == GFS2_FORMAT_MULTI
)
1122 blkid_set_tag(probe
->dev
, "UUID", 0, 0);
1124 if (strlen(sbd
->sb_locktable
))
1125 label
= sbd
->sb_locktable
;
1126 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(sbd
->sb_locktable
));
1132 static void unicode_16be_to_utf8(unsigned char *str
, int out_len
,
1133 const unsigned char *buf
, int in_len
)
1138 for (i
= j
= 0; i
+ 2 <= in_len
; i
+= 2) {
1139 c
= (buf
[i
] << 8) | buf
[i
+1];
1143 } else if (c
< 0x80) {
1146 str
[j
++] = (unsigned char) c
;
1147 } else if (c
< 0x800) {
1150 str
[j
++] = (unsigned char) (0xc0 | (c
>> 6));
1151 str
[j
++] = (unsigned char) (0x80 | (c
& 0x3f));
1155 str
[j
++] = (unsigned char) (0xe0 | (c
>> 12));
1156 str
[j
++] = (unsigned char) (0x80 | ((c
>> 6) & 0x3f));
1157 str
[j
++] = (unsigned char) (0x80 | (c
& 0x3f));
1163 static int probe_hfs(struct blkid_probe
*probe
__BLKID_ATTR((unused
)),
1164 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1167 struct hfs_mdb
*hfs
= (struct hfs_mdb
*)buf
;
1168 unsigned long long *uuid_ptr
;
1172 if ((memcmp(hfs
->embed_sig
, "H+", 2) == 0) ||
1173 (memcmp(hfs
->embed_sig
, "HX", 2) == 0))
1174 return 1; /* Not hfs, but an embedded HFS+ */
1176 uuid_ptr
= (unsigned long long *)hfs
->finder_info
.id
;
1177 uuid
= blkid_le64(*uuid_ptr
);
1179 sprintf(uuid_str
, "%016llX", uuid
);
1180 blkid_set_tag(probe
->dev
, "UUID", uuid_str
, 0);
1182 blkid_set_tag(probe
->dev
, "LABEL", (char *)hfs
->label
, hfs
->label_len
);
1187 static int probe_hfsplus(struct blkid_probe
*probe
,
1188 struct blkid_magic
*id
,
1191 struct hfsplus_extent extents
[HFSPLUS_EXTENT_COUNT
];
1192 struct hfsplus_bnode_descriptor
*descr
;
1193 struct hfsplus_bheader_record
*bnode
;
1194 struct hfsplus_catalog_key
*key
;
1195 struct hfsplus_vol_header
*hfsplus
;
1196 struct hfs_mdb
*sbd
= (struct hfs_mdb
*) buf
;
1197 unsigned int alloc_block_size
;
1198 unsigned int alloc_first_block
;
1199 unsigned int embed_first_block
;
1200 unsigned int off
= 0;
1201 unsigned int blocksize
;
1202 unsigned int cat_block
;
1203 unsigned int ext_block_start
;
1204 unsigned int ext_block_count
;
1205 unsigned int record_count
;
1206 unsigned int leaf_node_head
;
1207 unsigned int leaf_node_count
;
1208 unsigned int leaf_node_size
;
1209 unsigned int leaf_block
;
1210 unsigned int label_len
;
1211 unsigned long long *uuid_ptr
;
1212 __u64 leaf_off
, uuid
;
1213 char uuid_str
[17], label
[512];
1216 /* Check for a HFS+ volume embedded in a HFS volume */
1217 if (memcmp(sbd
->signature
, "BD", 2) == 0) {
1218 if ((memcmp(sbd
->embed_sig
, "H+", 2) != 0) &&
1219 (memcmp(sbd
->embed_sig
, "HX", 2) != 0))
1220 /* This must be an HFS volume, so fail */
1223 alloc_block_size
= blkid_be32(sbd
->al_blk_size
);
1224 alloc_first_block
= blkid_be16(sbd
->al_bl_st
);
1225 embed_first_block
= blkid_be16(sbd
->embed_startblock
);
1226 off
= (alloc_first_block
* 512) +
1227 (embed_first_block
* alloc_block_size
);
1228 buf
= get_buffer(probe
, off
+ (id
->bim_kboff
* 1024),
1233 hfsplus
= (struct hfsplus_vol_header
*) buf
;
1236 hfsplus
= (struct hfsplus_vol_header
*) buf
;
1238 if ((memcmp(hfsplus
->signature
, "H+", 2) != 0) &&
1239 (memcmp(hfsplus
->signature
, "HX", 2) != 0))
1242 uuid_ptr
= (unsigned long long *)hfsplus
->finder_info
.id
;
1243 uuid
= blkid_le64(*uuid_ptr
);
1245 sprintf(uuid_str
, "%016llX", uuid
);
1246 blkid_set_tag(probe
->dev
, "UUID", uuid_str
, 0);
1249 blocksize
= blkid_be32(hfsplus
->blocksize
);
1250 memcpy(extents
, hfsplus
->cat_file
.extents
, sizeof(extents
));
1251 cat_block
= blkid_be32(extents
[0].start_block
);
1253 buf
= get_buffer(probe
, off
+ ((__u64
) cat_block
* blocksize
), 0x2000);
1257 bnode
= (struct hfsplus_bheader_record
*)
1258 &buf
[sizeof(struct hfsplus_bnode_descriptor
)];
1260 leaf_node_head
= blkid_be32(bnode
->leaf_head
);
1261 leaf_node_size
= blkid_be16(bnode
->node_size
);
1262 leaf_node_count
= blkid_be32(bnode
->leaf_count
);
1263 if (leaf_node_count
== 0)
1266 leaf_block
= (leaf_node_head
* leaf_node_size
) / blocksize
;
1268 /* get physical location */
1269 for (ext
= 0; ext
< HFSPLUS_EXTENT_COUNT
; ext
++) {
1270 ext_block_start
= blkid_be32(extents
[ext
].start_block
);
1271 ext_block_count
= blkid_be32(extents
[ext
].block_count
);
1272 if (ext_block_count
== 0)
1275 /* this is our extent */
1276 if (leaf_block
< ext_block_count
)
1279 leaf_block
-= ext_block_count
;
1281 if (ext
== HFSPLUS_EXTENT_COUNT
)
1284 leaf_off
= (__u64
) (ext_block_start
+ leaf_block
) * blocksize
;
1286 buf
= get_buffer(probe
, off
+ leaf_off
, leaf_node_size
);
1290 descr
= (struct hfsplus_bnode_descriptor
*) buf
;
1291 record_count
= blkid_be16(descr
->num_recs
);
1292 if (record_count
== 0)
1295 if (descr
->type
!= HFS_NODE_LEAF
)
1298 key
= (struct hfsplus_catalog_key
*)
1299 &buf
[sizeof(struct hfsplus_bnode_descriptor
)];
1301 if (blkid_be32(key
->parent_id
) != HFSPLUS_POR_CNID
)
1304 label_len
= blkid_be16(key
->unicode_len
) * 2;
1305 unicode_16be_to_utf8((unsigned char *)label
, sizeof(label
),
1306 key
->unicode
, label_len
);
1307 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
1311 #define LVM2_LABEL_SIZE 512
1312 static unsigned int lvm2_calc_crc(const void *buf
, unsigned int size
)
1314 static const unsigned int crctab
[] = {
1315 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1316 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1317 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1318 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1320 unsigned int i
, crc
= 0xf597a6cf;
1321 const __u8
*data
= (const __u8
*) buf
;
1323 for (i
= 0; i
< size
; i
++) {
1325 crc
= (crc
>> 4) ^ crctab
[crc
& 0xf];
1326 crc
= (crc
>> 4) ^ crctab
[crc
& 0xf];
1331 static int probe_lvm2(struct blkid_probe
*probe
,
1332 struct blkid_magic
*id
,
1335 int sector
= (id
->bim_kboff
) << 1;
1336 struct lvm2_pv_label_header
*label
= (struct lvm2_pv_label_header
*)buf
;
1337 char *p
, *q
, uuid
[40];
1340 /* buf is at 0k or 1k offset; find label inside */
1341 if (memcmp(buf
, "LABELONE", 8) == 0) {
1342 label
= (struct lvm2_pv_label_header
*)buf
;
1343 } else if (memcmp(buf
+ 512, "LABELONE", 8) == 0) {
1344 label
= (struct lvm2_pv_label_header
*)(buf
+ 512);
1350 if (blkid_le64(label
->sector_xl
) != (unsigned) sector
) {
1352 printf("LVM2: label for sector %llu found at sector %d\n",
1353 blkid_le64(label
->sector_xl
), sector
));
1357 if (lvm2_calc_crc(&label
->offset_xl
, LVM2_LABEL_SIZE
-
1358 ((char *)&label
->offset_xl
- (char *)label
)) !=
1359 blkid_le32(label
->crc_xl
)) {
1361 printf("LVM2: label checksum incorrect at sector %d\n",
1366 for (i
=0, b
=1, p
=uuid
, q
= (char *) label
->pv_uuid
; i
< LVM2_ID_LEN
;
1373 blkid_set_tag(probe
->dev
, "UUID", uuid
, LVM2_ID_LEN
+6);
1378 static int probe_btrfs(struct blkid_probe
*probe
,
1379 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1382 struct btrfs_super_block
*bs
;
1383 const char *label
= 0;
1385 bs
= (struct btrfs_super_block
*)buf
;
1387 if (strlen(bs
->label
))
1389 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(bs
->label
));
1390 set_uuid(probe
->dev
, bs
->fsid
, 0);
1394 static int probe_f2fs(struct blkid_probe
*probe
,
1395 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1398 struct f2fs_super_block
*bs
;
1400 bs
= (struct f2fs_super_block
*)buf
;
1401 set_uuid(probe
->dev
, bs
->uuid
, 0);
1405 static uint64_t exfat_block_to_offset(const struct exfat_super_block
*sb
,
1408 return block
<< sb
->block_bits
;
1411 static uint64_t exfat_cluster_to_block(const struct exfat_super_block
*sb
,
1414 return sb
->cluster_block_start
+
1415 ((uint64_t)(cluster
- EXFAT_FIRST_DATA_CLUSTER
) << sb
->bpc_bits
);
1418 static uint64_t exfat_cluster_to_offset(const struct exfat_super_block
*sb
,
1421 return exfat_block_to_offset(sb
, exfat_cluster_to_block(sb
, cluster
));
1424 static uint32_t exfat_next_cluster(struct blkid_probe
*probe
,
1425 const struct exfat_super_block
*sb
,
1431 offset
= exfat_block_to_offset(sb
, sb
->fat_block_start
)
1432 + (uint64_t) cluster
* sizeof (cluster
);
1433 next
= (uint32_t *)get_buffer(probe
, offset
, sizeof (uint32_t));
1435 return next
? *next
: 0;
1438 static struct exfat_entry_label
*find_exfat_entry_label(
1439 struct blkid_probe
*probe
, const struct exfat_super_block
*sb
)
1441 uint32_t cluster
= sb
->rootdir_cluster
;
1442 uint64_t offset
= exfat_cluster_to_offset(sb
, cluster
);
1444 const size_t max_iter
= 10000;
1447 for (; i
< max_iter
; ++i
) {
1448 entry
= (uint8_t *)get_buffer(probe
, offset
, EXFAT_ENTRY_SIZE
);
1451 if (entry
[0] == EXFAT_ENTRY_EOD
)
1453 if (entry
[0] == EXFAT_ENTRY_LABEL
)
1454 return (struct exfat_entry_label
*) entry
;
1456 offset
+= EXFAT_ENTRY_SIZE
;
1457 if (offset
% CLUSTER_SIZE(sb
) == 0) {
1458 cluster
= exfat_next_cluster(probe
, sb
, cluster
);
1459 if (cluster
< EXFAT_FIRST_DATA_CLUSTER
)
1461 if (cluster
> EXFAT_LAST_DATA_CLUSTER
)
1463 offset
= exfat_cluster_to_offset(sb
, cluster
);
1470 static int probe_exfat(struct blkid_probe
*probe
, struct blkid_magic
*id
,
1473 struct exfat_super_block
*sb
;
1474 struct exfat_entry_label
*label
;
1477 sb
= (struct exfat_super_block
*)buf
;
1478 if (!sb
|| !CLUSTER_SIZE(sb
)) {
1479 DBG(DEBUG_PROBE
, printf("bad exfat superblock.\n"));
1480 return errno
? - errno
: 1;
1483 label
= find_exfat_entry_label(probe
, sb
);
1485 blkid_set_tag(probe
->dev
, "LABEL", label
->name
, label
->length
);
1487 blkid_set_tag(probe
->dev
, "LABEL", "disk", 4);
1490 memset(uuid
, 0, sizeof (uuid
));
1491 snprintf(uuid
, sizeof (uuid
), "%02hhX%02hhX-%02hhX%02hhX",
1492 sb
->volume_serial
[3], sb
->volume_serial
[2],
1493 sb
->volume_serial
[1], sb
->volume_serial
[0]);
1494 blkid_set_tag(probe
->dev
, "UUID", uuid
, strlen(uuid
));
1500 * Various filesystem magics that we can check for. Note that kboff and
1501 * sboff are in kilobytes and bytes respectively. All magics are in
1502 * byte strings so we don't worry about endian issues.
1504 static struct blkid_magic type_array
[] = {
1505 /* type kboff sboff len magic probe */
1506 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm
},
1507 { "ntfs", 0, 3, 8, "NTFS ", probe_ntfs
},
1508 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd
},
1509 { "ext4dev", 1, 0x38, 2, "\123\357", probe_ext4dev
},
1510 { "ext4", 1, 0x38, 2, "\123\357", probe_ext4
},
1511 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3
},
1512 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2
},
1513 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs
},
1514 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs
},
1515 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs
},
1516 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs
},
1517 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs
},
1518 { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4
},
1519 { "gfs2", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs2
},
1520 { "gfs", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs
},
1521 { "vfat", 0, 0x52, 5, "MSWIN", probe_fat
},
1522 { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat
},
1523 { "vfat", 0, 0x36, 5, "MSDOS", probe_fat
},
1524 { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat
},
1525 { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat
},
1526 { "vfat", 0, 0, 1, "\353", probe_fat_nomagic
},
1527 { "vfat", 0, 0, 1, "\351", probe_fat_nomagic
},
1528 { "vfat", 0, 0x1fe, 2, "\125\252", probe_fat_nomagic
},
1529 { "minix", 1, 0x10, 2, "\177\023", 0 },
1530 { "minix", 1, 0x10, 2, "\217\023", 0 },
1531 { "minix", 1, 0x10, 2, "\150\044", 0 },
1532 { "minix", 1, 0x10, 2, "\170\044", 0 },
1533 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
1534 { "xfs", 0, 0, 4, "XFSB", probe_xfs
},
1535 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs
},
1536 { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
1537 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs
},
1538 { "qnx4", 0, 4, 6, "QNX4FS", 0 },
1539 { "udf", 32, 1, 5, "BEA01", probe_udf
},
1540 { "udf", 32, 1, 5, "BOOT2", probe_udf
},
1541 { "udf", 32, 1, 5, "CD001", probe_udf
},
1542 { "udf", 32, 1, 5, "CDW02", probe_udf
},
1543 { "udf", 32, 1, 5, "NSR02", probe_udf
},
1544 { "udf", 32, 1, 5, "NSR03", probe_udf
},
1545 { "udf", 32, 1, 5, "TEA01", probe_udf
},
1546 { "iso9660", 32, 1, 5, "CD001", probe_iso9660
},
1547 { "iso9660", 32, 9, 5, "CDROM", probe_iso9660
},
1548 { "jfs", 32, 0, 4, "JFS1", probe_jfs
},
1549 /* ZFS has 128 root blocks (#4 is the first used), check only 6 of them */
1550 { "zfs", 128, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1551 { "zfs", 128, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1552 { "zfs", 132, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1553 { "zfs", 132, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1554 { "zfs", 136, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1555 { "zfs", 136, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1556 { "zfs", 384, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1557 { "zfs", 384, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1558 { "zfs", 388, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1559 { "zfs", 388, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1560 { "zfs", 392, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1561 { "zfs", 392, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1562 { "hfsplus", 1, 0, 2, "BD", probe_hfsplus
},
1563 { "hfsplus", 1, 0, 2, "H+", probe_hfsplus
},
1564 { "hfsplus", 1, 0, 2, "HX", probe_hfsplus
},
1565 { "hfs", 1, 0, 2, "BD", probe_hfs
},
1566 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
1567 { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
1568 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
1569 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0
},
1570 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1
},
1571 { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1
},
1572 { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1
},
1573 { "swsuspend", 0, 0xff6, 9, "ULSUSPEND", probe_swap1
},
1574 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0
},
1575 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1
},
1576 { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1
},
1577 { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1
},
1578 { "swsuspend", 0, 0x1ff6, 9, "ULSUSPEND", probe_swap1
},
1579 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0
},
1580 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1
},
1581 { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1
},
1582 { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1
},
1583 { "swsuspend", 0, 0x3ff6, 9, "ULSUSPEND", probe_swap1
},
1584 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0
},
1585 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1
},
1586 { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1
},
1587 { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1
},
1588 { "swsuspend", 0, 0x7ff6, 9, "ULSUSPEND", probe_swap1
},
1589 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0
},
1590 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1
},
1591 { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1
},
1592 { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1
},
1593 { "swsuspend", 0, 0xfff6, 9, "ULSUSPEND", probe_swap1
},
1594 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs
},
1595 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2
},
1596 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2
},
1597 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2
},
1598 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2
},
1599 { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks
},
1600 { "squashfs", 0, 0, 4, "sqsh", 0 },
1601 { "squashfs", 0, 0, 4, "hsqs", 0 },
1602 { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2
},
1603 { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2
},
1604 { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2
},
1605 { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2
},
1606 { "btrfs", 64, 0x40, 8, "_BHRfS_M", probe_btrfs
},
1607 { "f2fs", 1, 0, 4, "\x10\x20\xf5\xf2", probe_f2fs
},
1608 { "exfat", 0, 3, 8, "EXFAT ", probe_exfat
},
1609 { NULL
, 0, 0, 0, NULL
, NULL
}
1613 * Verify that the data in dev is consistent with what is on the actual
1614 * block device (using the devname field only). Normally this will be
1615 * called when finding items in the cache, but for long running processes
1616 * is also desirable to revalidate an item before use.
1618 * If we are unable to revalidate the data, we return the old data and
1619 * do not set the BLKID_BID_FL_VERIFIED flag on it.
1621 blkid_dev
blkid_verify(blkid_cache cache
, blkid_dev dev
)
1623 struct blkid_magic
*id
;
1624 struct blkid_probe probe
;
1625 blkid_tag_iterate iter
;
1627 const char *type
, *value
;
1637 diff
= difftime(now
, dev
->bid_time
);
1639 if (stat(dev
->bid_name
, &st
) < 0) {
1641 printf("blkid_verify: error %s (%d) while "
1642 "trying to stat %s\n", strerror(errno
), errno
,
1645 if ((errno
== EPERM
) || (errno
== EACCES
) || (errno
== ENOENT
)) {
1646 /* We don't have read permission, just return cache data. */
1647 DBG(DEBUG_PROBE
, printf("returning unverified data for %s\n",
1651 blkid_free_dev(dev
);
1655 if ((now
>= dev
->bid_time
) &&
1656 (st
.st_mtime
<= dev
->bid_time
) &&
1657 ((diff
< BLKID_PROBE_MIN
) ||
1658 (dev
->bid_flags
& BLKID_BID_FL_VERIFIED
&&
1659 diff
< BLKID_PROBE_INTERVAL
)))
1663 printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
1664 "time since last check %lu)\n",
1665 dev
->bid_name
, (unsigned long)dev
->bid_time
,
1666 (unsigned long)st
.st_mtime
, (unsigned long)diff
));
1668 if ((probe
.fd
= open(dev
->bid_name
, O_RDONLY
)) < 0) {
1669 DBG(DEBUG_PROBE
, printf("blkid_verify: error %s (%d) while "
1670 "opening %s\n", strerror(errno
), errno
,
1675 probe
.cache
= cache
;
1682 * Iterate over the type array. If we already know the type,
1683 * then try that first. If it doesn't work, then blow away
1684 * the type information, and try again.
1689 if (!dev
->bid_type
|| !strcmp(dev
->bid_type
, "mdraid")) {
1692 if (check_mdraid(probe
.fd
, uuid
) == 0) {
1693 set_uuid(dev
, uuid
, 0);
1698 for (id
= type_array
; id
->bim_type
; id
++) {
1699 if (dev
->bid_type
&&
1700 strcmp(id
->bim_type
, dev
->bid_type
))
1703 idx
= id
->bim_kboff
+ (id
->bim_sboff
>> 10);
1704 buf
= get_buffer(&probe
, (__u64
) idx
<< 10, 1024);
1708 if (memcmp(id
->bim_magic
, buf
+ (id
->bim_sboff
& 0x3ff),
1712 if ((id
->bim_probe
== NULL
) ||
1713 (id
->bim_probe(&probe
, id
, buf
) == 0)) {
1714 type
= id
->bim_type
;
1719 if (!id
->bim_type
&& dev
->bid_type
) {
1721 * Zap the device filesystem information and try again
1724 printf("previous fs type %s not valid, "
1725 "trying full probe\n", dev
->bid_type
));
1726 iter
= blkid_tag_iterate_begin(dev
);
1727 while (blkid_tag_next(iter
, &type
, &value
) == 0)
1728 blkid_set_tag(dev
, type
, 0, 0);
1729 blkid_tag_iterate_end(iter
);
1733 if (!dev
->bid_type
) {
1734 blkid_free_dev(dev
);
1741 dev
->bid_devno
= st
.st_rdev
;
1742 dev
->bid_time
= time(0);
1743 dev
->bid_flags
|= BLKID_BID_FL_VERIFIED
;
1744 cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
1746 blkid_set_tag(dev
, "TYPE", type
, 0);
1748 DBG(DEBUG_PROBE
, printf("%s: devno 0x%04llx, type %s\n",
1749 dev
->bid_name
, (long long)st
.st_rdev
, type
));
1760 int blkid_known_fstype(const char *fstype
)
1762 struct blkid_magic
*id
;
1764 for (id
= type_array
; id
->bim_type
; id
++) {
1765 if (strcmp(fstype
, id
->bim_type
) == 0)
1772 int main(int argc
, char **argv
)
1779 fprintf(stderr
, "Usage: %s device\n"
1780 "Probe a single device to determine type\n", argv
[0]);
1783 if ((ret
= blkid_get_cache(&cache
, "/dev/null")) != 0) {
1784 fprintf(stderr
, "%s: error creating cache (%d)\n",
1788 dev
= blkid_get_dev(cache
, argv
[1], BLKID_DEV_NORMAL
);
1790 printf("%s: %s has an unsupported type\n", argv
[0], argv
[1]);
1793 printf("TYPE='%s'\n", dev
->bid_type
? dev
->bid_type
: "(null)");
1795 printf("LABEL='%s'\n", dev
->bid_label
);
1797 printf("UUID='%s'\n", dev
->bid_uuid
);
1799 blkid_free_dev(dev
);