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
>= label
&& (*end
== ' ' || *end
== 0))
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 (es
->s_volume_name
[0])
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);
901 blkid_set_tag(probe
->dev
, "UUID", uuid
, 40);
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 void unicode_16le_to_utf8(unsigned char *str
, int out_len
,
1165 const unsigned char *buf
, int in_len
)
1170 for (i
= j
= 0; i
+ 2 <= in_len
; i
+= 2) {
1171 c
= (buf
[i
+1] << 8) | buf
[i
];
1175 } else if (c
< 0x80) {
1178 str
[j
++] = (unsigned char) c
;
1179 } else if (c
< 0x800) {
1182 str
[j
++] = (unsigned char) (0xc0 | (c
>> 6));
1183 str
[j
++] = (unsigned char) (0x80 | (c
& 0x3f));
1187 str
[j
++] = (unsigned char) (0xe0 | (c
>> 12));
1188 str
[j
++] = (unsigned char) (0x80 | ((c
>> 6) & 0x3f));
1189 str
[j
++] = (unsigned char) (0x80 | (c
& 0x3f));
1195 static int probe_hfs(struct blkid_probe
*probe
__BLKID_ATTR((unused
)),
1196 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1199 struct hfs_mdb
*hfs
= (struct hfs_mdb
*)buf
;
1200 unsigned long long *uuid_ptr
;
1204 if ((memcmp(hfs
->embed_sig
, "H+", 2) == 0) ||
1205 (memcmp(hfs
->embed_sig
, "HX", 2) == 0))
1206 return 1; /* Not hfs, but an embedded HFS+ */
1208 uuid_ptr
= (unsigned long long *)hfs
->finder_info
.id
;
1209 uuid
= blkid_le64(*uuid_ptr
);
1211 sprintf(uuid_str
, "%016llX", uuid
);
1212 blkid_set_tag(probe
->dev
, "UUID", uuid_str
, 0);
1214 blkid_set_tag(probe
->dev
, "LABEL", (char *)hfs
->label
, hfs
->label_len
);
1219 #define HFSPLUS_SECTOR_SIZE 512
1221 static int probe_hfsplus(struct blkid_probe
*probe
,
1222 struct blkid_magic
*id
,
1225 struct hfsplus_extent extents
[HFSPLUS_EXTENT_COUNT
];
1226 struct hfsplus_bnode_descriptor
*descr
;
1227 struct hfsplus_bheader_record
*bnode
;
1228 struct hfsplus_catalog_key
*key
;
1229 struct hfsplus_vol_header
*hfsplus
;
1230 struct hfs_mdb
*sbd
= (struct hfs_mdb
*) buf
;
1231 unsigned int alloc_block_size
;
1232 unsigned int alloc_first_block
;
1233 unsigned int embed_first_block
;
1234 unsigned int off
= 0;
1235 unsigned int blocksize
;
1236 unsigned int cat_block
;
1237 unsigned int ext_block_start
;
1238 unsigned int ext_block_count
;
1239 unsigned int record_count
;
1240 unsigned int leaf_node_head
;
1241 unsigned int leaf_node_count
;
1242 unsigned int leaf_node_size
;
1243 unsigned int leaf_block
;
1244 unsigned int label_len
;
1245 unsigned long long *uuid_ptr
;
1246 __u64 leaf_off
, uuid
;
1247 char uuid_str
[17], label
[512];
1250 /* Check for a HFS+ volume embedded in a HFS volume */
1251 if (memcmp(sbd
->signature
, "BD", 2) == 0) {
1252 if ((memcmp(sbd
->embed_sig
, "H+", 2) != 0) &&
1253 (memcmp(sbd
->embed_sig
, "HX", 2) != 0))
1254 /* This must be an HFS volume, so fail */
1257 alloc_block_size
= blkid_be32(sbd
->al_blk_size
);
1258 alloc_first_block
= blkid_be16(sbd
->al_bl_st
);
1259 embed_first_block
= blkid_be16(sbd
->embed_startblock
);
1260 off
= (alloc_first_block
* 512) +
1261 (embed_first_block
* alloc_block_size
);
1262 buf
= get_buffer(probe
, off
+ (id
->bim_kboff
* 1024),
1267 hfsplus
= (struct hfsplus_vol_header
*) buf
;
1270 hfsplus
= (struct hfsplus_vol_header
*) buf
;
1272 if ((memcmp(hfsplus
->signature
, "H+", 2) != 0) &&
1273 (memcmp(hfsplus
->signature
, "HX", 2) != 0))
1276 uuid_ptr
= (unsigned long long *)hfsplus
->finder_info
.id
;
1277 uuid
= blkid_le64(*uuid_ptr
);
1279 sprintf(uuid_str
, "%016llX", uuid
);
1280 blkid_set_tag(probe
->dev
, "UUID", uuid_str
, 0);
1283 blocksize
= blkid_be32(hfsplus
->blocksize
);
1284 if (blocksize
< HFSPLUS_SECTOR_SIZE
)
1287 memcpy(extents
, hfsplus
->cat_file
.extents
, sizeof(extents
));
1288 cat_block
= blkid_be32(extents
[0].start_block
);
1290 buf
= get_buffer(probe
, off
+ ((__u64
) cat_block
* blocksize
), 0x2000);
1294 bnode
= (struct hfsplus_bheader_record
*)
1295 &buf
[sizeof(struct hfsplus_bnode_descriptor
)];
1297 leaf_node_head
= blkid_be32(bnode
->leaf_head
);
1298 leaf_node_size
= blkid_be16(bnode
->node_size
);
1299 leaf_node_count
= blkid_be32(bnode
->leaf_count
);
1300 if (leaf_node_count
== 0)
1303 leaf_block
= (leaf_node_head
* leaf_node_size
) / blocksize
;
1305 /* get physical location */
1306 for (ext
= 0; ext
< HFSPLUS_EXTENT_COUNT
; ext
++) {
1307 ext_block_start
= blkid_be32(extents
[ext
].start_block
);
1308 ext_block_count
= blkid_be32(extents
[ext
].block_count
);
1309 if (ext_block_count
== 0)
1312 /* this is our extent */
1313 if (leaf_block
< ext_block_count
)
1316 leaf_block
-= ext_block_count
;
1318 if (ext
== HFSPLUS_EXTENT_COUNT
)
1321 leaf_off
= (__u64
) (ext_block_start
+ leaf_block
) * blocksize
;
1323 buf
= get_buffer(probe
, off
+ leaf_off
, leaf_node_size
);
1327 descr
= (struct hfsplus_bnode_descriptor
*) buf
;
1328 record_count
= blkid_be16(descr
->num_recs
);
1329 if (record_count
== 0)
1332 if (descr
->type
!= HFS_NODE_LEAF
)
1335 key
= (struct hfsplus_catalog_key
*)
1336 &buf
[sizeof(struct hfsplus_bnode_descriptor
)];
1338 if (blkid_be32(key
->parent_id
) != HFSPLUS_POR_CNID
)
1341 label_len
= blkid_be16(key
->unicode_len
) * 2;
1342 unicode_16be_to_utf8((unsigned char *)label
, sizeof(label
),
1343 key
->unicode
, label_len
);
1344 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
1348 #define LVM2_LABEL_SIZE 512
1349 static unsigned int lvm2_calc_crc(const void *buf
, unsigned int size
)
1351 static const unsigned int crctab
[] = {
1352 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1353 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1354 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1355 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1357 unsigned int i
, crc
= 0xf597a6cf;
1358 const __u8
*data
= (const __u8
*) buf
;
1360 for (i
= 0; i
< size
; i
++) {
1362 crc
= (crc
>> 4) ^ crctab
[crc
& 0xf];
1363 crc
= (crc
>> 4) ^ crctab
[crc
& 0xf];
1368 static int probe_lvm2(struct blkid_probe
*probe
,
1369 struct blkid_magic
*id
,
1372 int sector
= (id
->bim_kboff
) << 1;
1373 struct lvm2_pv_label_header
*label
= (struct lvm2_pv_label_header
*)buf
;
1374 char *p
, *q
, uuid
[40];
1377 /* buf is at 0k or 1k offset; find label inside */
1378 if (memcmp(buf
, "LABELONE", 8) == 0) {
1379 label
= (struct lvm2_pv_label_header
*)buf
;
1380 } else if (memcmp(buf
+ 512, "LABELONE", 8) == 0) {
1381 label
= (struct lvm2_pv_label_header
*)(buf
+ 512);
1387 if (blkid_le64(label
->sector_xl
) != (unsigned) sector
) {
1389 printf("LVM2: label for sector %llu found at sector %d\n",
1390 blkid_le64(label
->sector_xl
), sector
));
1394 if (lvm2_calc_crc(&label
->offset_xl
, LVM2_LABEL_SIZE
-
1395 ((char *)&label
->offset_xl
- (char *)label
)) !=
1396 blkid_le32(label
->crc_xl
)) {
1398 printf("LVM2: label checksum incorrect at sector %d\n",
1403 for (i
=0, b
=1, p
=uuid
, q
= (char *) label
->pv_uuid
; i
< LVM2_ID_LEN
;
1410 blkid_set_tag(probe
->dev
, "UUID", uuid
, LVM2_ID_LEN
+6);
1415 static int probe_btrfs(struct blkid_probe
*probe
,
1416 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1419 struct btrfs_super_block
*bs
;
1420 const char *label
= 0;
1422 bs
= (struct btrfs_super_block
*)buf
;
1424 if (strlen(bs
->label
))
1426 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(bs
->label
));
1427 set_uuid(probe
->dev
, bs
->fsid
, 0);
1431 static int probe_f2fs(struct blkid_probe
*probe
,
1432 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1435 struct f2fs_super_block
*bs
;
1437 bs
= (struct f2fs_super_block
*)buf
;
1438 set_uuid(probe
->dev
, bs
->uuid
, 0);
1442 static uint64_t exfat_block_to_offset(const struct exfat_super_block
*sb
,
1445 return block
<< sb
->block_bits
;
1448 static uint64_t exfat_cluster_to_block(const struct exfat_super_block
*sb
,
1451 return sb
->cluster_block_start
+
1452 ((uint64_t)(cluster
- EXFAT_FIRST_DATA_CLUSTER
) << sb
->bpc_bits
);
1455 static uint64_t exfat_cluster_to_offset(const struct exfat_super_block
*sb
,
1458 return exfat_block_to_offset(sb
, exfat_cluster_to_block(sb
, cluster
));
1461 static uint32_t exfat_next_cluster(struct blkid_probe
*probe
,
1462 const struct exfat_super_block
*sb
,
1468 offset
= exfat_block_to_offset(sb
, sb
->fat_block_start
)
1469 + (uint64_t) cluster
* sizeof (cluster
);
1470 next
= (uint32_t *)get_buffer(probe
, offset
, sizeof (uint32_t));
1472 return next
? *next
: 0;
1475 static struct exfat_entry_label
*find_exfat_entry_label(
1476 struct blkid_probe
*probe
, const struct exfat_super_block
*sb
)
1478 uint32_t cluster
= sb
->rootdir_cluster
;
1479 uint64_t offset
= exfat_cluster_to_offset(sb
, cluster
);
1481 const size_t max_iter
= 10000;
1484 for (; i
< max_iter
; ++i
) {
1485 entry
= (uint8_t *)get_buffer(probe
, offset
, EXFAT_ENTRY_SIZE
);
1488 if (entry
[0] == EXFAT_ENTRY_EOD
)
1490 if (entry
[0] == EXFAT_ENTRY_LABEL
)
1491 return (struct exfat_entry_label
*) entry
;
1493 offset
+= EXFAT_ENTRY_SIZE
;
1494 if (offset
% CLUSTER_SIZE(sb
) == 0) {
1495 cluster
= exfat_next_cluster(probe
, sb
, cluster
);
1496 if (cluster
< EXFAT_FIRST_DATA_CLUSTER
)
1498 if (cluster
> EXFAT_LAST_DATA_CLUSTER
)
1500 offset
= exfat_cluster_to_offset(sb
, cluster
);
1507 static int probe_exfat(struct blkid_probe
*probe
,
1508 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
1511 struct exfat_super_block
*sb
;
1512 struct exfat_entry_label
*label
;
1515 sb
= (struct exfat_super_block
*)buf
;
1516 if (!sb
|| CLUSTER_SIZE(sb
) == 0) {
1517 DBG(DEBUG_PROBE
, printf("bad exfat superblock.\n"));
1518 return errno
? - errno
: 1;
1521 label
= find_exfat_entry_label(probe
, sb
);
1523 unsigned char utf8_label
[128];
1524 unicode_16le_to_utf8(utf8_label
, sizeof(utf8_label
), label
->name
, label
->length
* 2);
1525 blkid_set_tag(probe
->dev
, "LABEL", (char *) utf8_label
, 0);
1527 blkid_set_tag(probe
->dev
, "LABEL", "disk", 4);
1530 memset(uuid
, 0, sizeof (uuid
));
1531 snprintf(uuid
, sizeof (uuid
), "%02hhX%02hhX-%02hhX%02hhX",
1532 sb
->volume_serial
[3], sb
->volume_serial
[2],
1533 sb
->volume_serial
[1], sb
->volume_serial
[0]);
1534 blkid_set_tag(probe
->dev
, "UUID", uuid
, strlen(uuid
));
1540 * Various filesystem magics that we can check for. Note that kboff and
1541 * sboff are in kilobytes and bytes respectively. All magics are in
1542 * byte strings so we don't worry about endian issues.
1544 static struct blkid_magic type_array
[] = {
1545 /* type kboff sboff len magic probe */
1546 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm
},
1547 { "ntfs", 0, 3, 8, "NTFS ", probe_ntfs
},
1548 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd
},
1549 { "ext4dev", 1, 0x38, 2, "\123\357", probe_ext4dev
},
1550 { "ext4", 1, 0x38, 2, "\123\357", probe_ext4
},
1551 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3
},
1552 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2
},
1553 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs
},
1554 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs
},
1555 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs
},
1556 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs
},
1557 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs
},
1558 { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4
},
1559 { "gfs2", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs2
},
1560 { "gfs", 64, 0, 4, "\x01\x16\x19\x70", probe_gfs
},
1561 { "vfat", 0, 0x52, 5, "MSWIN", probe_fat
},
1562 { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat
},
1563 { "vfat", 0, 0x36, 5, "MSDOS", probe_fat
},
1564 { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat
},
1565 { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat
},
1566 { "vfat", 0, 0, 1, "\353", probe_fat_nomagic
},
1567 { "vfat", 0, 0, 1, "\351", probe_fat_nomagic
},
1568 { "vfat", 0, 0x1fe, 2, "\125\252", probe_fat_nomagic
},
1569 { "minix", 1, 0x10, 2, "\177\023", 0 },
1570 { "minix", 1, 0x10, 2, "\217\023", 0 },
1571 { "minix", 1, 0x10, 2, "\150\044", 0 },
1572 { "minix", 1, 0x10, 2, "\170\044", 0 },
1573 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
1574 { "xfs", 0, 0, 4, "XFSB", probe_xfs
},
1575 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs
},
1576 { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
1577 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs
},
1578 { "qnx4", 0, 4, 6, "QNX4FS", 0 },
1579 { "udf", 32, 1, 5, "BEA01", probe_udf
},
1580 { "udf", 32, 1, 5, "BOOT2", probe_udf
},
1581 { "udf", 32, 1, 5, "CD001", probe_udf
},
1582 { "udf", 32, 1, 5, "CDW02", probe_udf
},
1583 { "udf", 32, 1, 5, "NSR02", probe_udf
},
1584 { "udf", 32, 1, 5, "NSR03", probe_udf
},
1585 { "udf", 32, 1, 5, "TEA01", probe_udf
},
1586 { "iso9660", 32, 1, 5, "CD001", probe_iso9660
},
1587 { "iso9660", 32, 9, 5, "CDROM", probe_iso9660
},
1588 { "jfs", 32, 0, 4, "JFS1", probe_jfs
},
1589 /* ZFS has 128 root blocks (#4 is the first used), check only 6 of them */
1590 { "zfs", 128, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1591 { "zfs", 128, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1592 { "zfs", 132, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1593 { "zfs", 132, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1594 { "zfs", 136, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1595 { "zfs", 136, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1596 { "zfs", 384, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1597 { "zfs", 384, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1598 { "zfs", 388, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1599 { "zfs", 388, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1600 { "zfs", 392, 0, 8, "\0\0\0\0\0\xba\xb1\x0c", probe_zfs
},
1601 { "zfs", 392, 0, 8, "\x0c\xb1\xba\0\0\0\0\0", probe_zfs
},
1602 { "hfsplus", 1, 0, 2, "BD", probe_hfsplus
},
1603 { "hfsplus", 1, 0, 2, "H+", probe_hfsplus
},
1604 { "hfsplus", 1, 0, 2, "HX", probe_hfsplus
},
1605 { "hfs", 1, 0, 2, "BD", probe_hfs
},
1606 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
1607 { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
1608 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
1609 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0
},
1610 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1
},
1611 { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1
},
1612 { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1
},
1613 { "swsuspend", 0, 0xff6, 9, "ULSUSPEND", probe_swap1
},
1614 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0
},
1615 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1
},
1616 { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1
},
1617 { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1
},
1618 { "swsuspend", 0, 0x1ff6, 9, "ULSUSPEND", probe_swap1
},
1619 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0
},
1620 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1
},
1621 { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1
},
1622 { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1
},
1623 { "swsuspend", 0, 0x3ff6, 9, "ULSUSPEND", probe_swap1
},
1624 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0
},
1625 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1
},
1626 { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1
},
1627 { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1
},
1628 { "swsuspend", 0, 0x7ff6, 9, "ULSUSPEND", probe_swap1
},
1629 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0
},
1630 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1
},
1631 { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1
},
1632 { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1
},
1633 { "swsuspend", 0, 0xfff6, 9, "ULSUSPEND", probe_swap1
},
1634 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs
},
1635 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2
},
1636 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2
},
1637 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2
},
1638 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2
},
1639 { "crypt_LUKS", 0, 0, 6, "LUKS\xba\xbe", probe_luks
},
1640 { "squashfs", 0, 0, 4, "sqsh", 0 },
1641 { "squashfs", 0, 0, 4, "hsqs", 0 },
1642 { "lvm2pv", 0, 0x218, 8, "LVM2 001", probe_lvm2
},
1643 { "lvm2pv", 0, 0x018, 8, "LVM2 001", probe_lvm2
},
1644 { "lvm2pv", 1, 0x018, 8, "LVM2 001", probe_lvm2
},
1645 { "lvm2pv", 1, 0x218, 8, "LVM2 001", probe_lvm2
},
1646 { "btrfs", 64, 0x40, 8, "_BHRfS_M", probe_btrfs
},
1647 { "f2fs", 1, 0, 4, "\x10\x20\xf5\xf2", probe_f2fs
},
1648 { "exfat", 0, 3, 8, "EXFAT ", probe_exfat
},
1649 { NULL
, 0, 0, 0, NULL
, NULL
}
1653 * Verify that the data in dev is consistent with what is on the actual
1654 * block device (using the devname field only). Normally this will be
1655 * called when finding items in the cache, but for long running processes
1656 * is also desirable to revalidate an item before use.
1658 * If we are unable to revalidate the data, we return the old data and
1659 * do not set the BLKID_BID_FL_VERIFIED flag on it.
1661 blkid_dev
blkid_verify(blkid_cache cache
, blkid_dev dev
)
1663 struct blkid_magic
*id
;
1664 struct blkid_probe probe
;
1665 blkid_tag_iterate iter
;
1667 const char *type
, *value
;
1677 diff
= difftime(now
, dev
->bid_time
);
1679 if (stat(dev
->bid_name
, &st
) < 0) {
1681 printf("blkid_verify: error %s (%d) while "
1682 "trying to stat %s\n", strerror(errno
), errno
,
1685 if ((errno
== EPERM
) || (errno
== EACCES
) || (errno
== ENOENT
)) {
1686 /* We don't have read permission, just return cache data. */
1687 DBG(DEBUG_PROBE
, printf("returning unverified data for %s\n",
1691 blkid_free_dev(dev
);
1695 if ((now
>= dev
->bid_time
) &&
1696 (st
.st_mtime
<= dev
->bid_time
) &&
1697 ((diff
< BLKID_PROBE_MIN
) ||
1698 (dev
->bid_flags
& BLKID_BID_FL_VERIFIED
&&
1699 diff
< BLKID_PROBE_INTERVAL
)))
1703 printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
1704 "time since last check %lu)\n",
1705 dev
->bid_name
, (unsigned long)dev
->bid_time
,
1706 (unsigned long)st
.st_mtime
, (unsigned long)diff
));
1708 if ((probe
.fd
= open(dev
->bid_name
, O_RDONLY
)) < 0) {
1709 DBG(DEBUG_PROBE
, printf("blkid_verify: error %s (%d) while "
1710 "opening %s\n", strerror(errno
), errno
,
1715 probe
.cache
= cache
;
1722 * Iterate over the type array. If we already know the type,
1723 * then try that first. If it doesn't work, then blow away
1724 * the type information, and try again.
1729 if (!dev
->bid_type
|| !strcmp(dev
->bid_type
, "mdraid")) {
1732 if (check_mdraid(probe
.fd
, uuid
) == 0) {
1733 set_uuid(dev
, uuid
, 0);
1738 for (id
= type_array
; id
->bim_type
; id
++) {
1739 if (dev
->bid_type
&&
1740 strcmp(id
->bim_type
, dev
->bid_type
))
1743 idx
= id
->bim_kboff
+ (id
->bim_sboff
>> 10);
1744 buf
= get_buffer(&probe
, (__u64
) idx
<< 10, 1024);
1748 if (memcmp(id
->bim_magic
, buf
+ (id
->bim_sboff
& 0x3ff),
1752 if ((id
->bim_probe
== NULL
) ||
1753 (id
->bim_probe(&probe
, id
, buf
) == 0)) {
1754 type
= id
->bim_type
;
1759 if (!id
->bim_type
&& dev
->bid_type
) {
1761 * Zap the device filesystem information and try again
1764 printf("previous fs type %s not valid, "
1765 "trying full probe\n", dev
->bid_type
));
1766 iter
= blkid_tag_iterate_begin(dev
);
1767 while (blkid_tag_next(iter
, &type
, &value
) == 0)
1768 blkid_set_tag(dev
, type
, 0, 0);
1769 blkid_tag_iterate_end(iter
);
1773 if (!dev
->bid_type
) {
1774 blkid_free_dev(dev
);
1781 dev
->bid_devno
= st
.st_rdev
;
1782 dev
->bid_time
= time(0);
1783 dev
->bid_flags
|= BLKID_BID_FL_VERIFIED
;
1784 cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
1786 blkid_set_tag(dev
, "TYPE", type
, 0);
1788 DBG(DEBUG_PROBE
, printf("%s: devno 0x%04llx, type %s\n",
1789 dev
->bid_name
, (long long)st
.st_rdev
, type
));
1800 int blkid_known_fstype(const char *fstype
)
1802 struct blkid_magic
*id
;
1804 for (id
= type_array
; id
->bim_type
; id
++) {
1805 if (strcmp(fstype
, id
->bim_type
) == 0)
1812 int main(int argc
, char **argv
)
1819 fprintf(stderr
, "Usage: %s device\n"
1820 "Probe a single device to determine type\n", argv
[0]);
1823 if ((ret
= blkid_get_cache(&cache
, "/dev/null")) != 0) {
1824 fprintf(stderr
, "%s: error creating cache (%d)\n",
1828 dev
= blkid_get_dev(cache
, argv
[1], BLKID_DEV_NORMAL
);
1830 printf("%s: %s has an unsupported type\n", argv
[0], argv
[1]);
1833 printf("TYPE='%s'\n", dev
->bid_type
? dev
->bid_type
: "(null)");
1835 printf("LABEL='%s'\n", dev
->bid_label
);
1837 printf("UUID='%s'\n", dev
->bid_uuid
);
1839 blkid_free_dev(dev
);