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.
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_STAT_H
25 #ifdef HAVE_SYS_MKDEV_H
26 #include <sys/mkdev.h>
32 #include "uuid/uuid.h"
35 static int figure_label_len(const unsigned char *label
, int len
)
37 const unsigned char *end
= label
+ len
- 1;
39 while ((*end
== ' ' || *end
== 0) && end
>= label
)
43 return end
- label
+ 1;
48 static unsigned char *get_buffer(struct blkid_probe
*pr
,
49 unsigned off
, size_t len
)
52 unsigned char *newbuf
;
54 if (off
+ len
<= SB_BUFFER_SIZE
) {
56 pr
->sbbuf
= malloc(SB_BUFFER_SIZE
);
59 if (lseek(pr
->fd
, 0, SEEK_SET
) < 0)
61 ret_read
= read(pr
->fd
, pr
->sbbuf
, SB_BUFFER_SIZE
);
64 pr
->sb_valid
= ret_read
;
66 if (off
+len
> pr
->sb_valid
)
68 return pr
->sbbuf
+ off
;
70 if (len
> pr
->buf_max
) {
71 newbuf
= realloc(pr
->buf
, len
);
77 if (lseek(pr
->fd
, off
, SEEK_SET
) < 0)
79 ret_read
= read(pr
->fd
, pr
->buf
, len
);
80 if (ret_read
!= (ssize_t
) len
)
88 * This is a special case code to check for an MDRAID device. We do
89 * this special since it requires checking for a superblock at the end
92 static int check_mdraid(int fd
, unsigned char *ret_uuid
)
94 struct mdp_superblock_s
*md
;
99 return -BLKID_ERR_PARAM
;
101 offset
= (blkid_get_dev_size(fd
) & ~((blkid_loff_t
)65535)) - 65536;
103 if (blkid_llseek(fd
, offset
, 0) < 0 ||
104 read(fd
, buf
, 4096) != 4096)
105 return -BLKID_ERR_IO
;
107 /* Check for magic number */
108 if (memcmp("\251+N\374", buf
, 4))
109 return -BLKID_ERR_PARAM
;
115 /* The MD UUID is not contiguous in the superblock, make it so */
116 md
= (struct mdp_superblock_s
*)buf
;
117 if (md
->set_uuid0
|| md
->set_uuid1
|| md
->set_uuid2
|| md
->set_uuid3
) {
118 memcpy(ret_uuid
, &md
->set_uuid0
, 4);
119 memcpy(ret_uuid
, &md
->set_uuid1
, 12);
124 static void set_uuid(blkid_dev dev
, uuid_t uuid
, char *tag
)
128 if (!uuid_is_null(uuid
)) {
129 uuid_unparse(uuid
, str
);
130 blkid_set_tag(dev
, tag
? tag
: "UUID", str
, sizeof(str
));
134 static void get_ext2_info(blkid_dev dev
, unsigned char *buf
)
136 struct ext2_super_block
*es
= (struct ext2_super_block
*) buf
;
137 const char *label
= 0;
139 DBG(DEBUG_PROBE
, printf("ext2_sb.compat = %08X:%08X:%08X\n",
140 blkid_le32(es
->s_feature_compat
),
141 blkid_le32(es
->s_feature_incompat
),
142 blkid_le32(es
->s_feature_ro_compat
)));
144 if (strlen(es
->s_volume_name
))
145 label
= es
->s_volume_name
;
146 blkid_set_tag(dev
, "LABEL", label
, sizeof(es
->s_volume_name
));
148 set_uuid(dev
, es
->s_uuid
, 0);
151 static int probe_ext3(struct blkid_probe
*probe
,
152 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
155 struct ext2_super_block
*es
;
157 es
= (struct ext2_super_block
*)buf
;
159 /* Distinguish between jbd and ext2/3 fs */
160 if (blkid_le32(es
->s_feature_incompat
) &
161 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)
162 return -BLKID_ERR_PARAM
;
164 /* Distinguish between ext3 and ext2 */
165 if (!(blkid_le32(es
->s_feature_compat
) &
166 EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
167 return -BLKID_ERR_PARAM
;
169 get_ext2_info(probe
->dev
, buf
);
171 if ((es
->s_feature_compat
& EXT3_FEATURE_COMPAT_HAS_JOURNAL
) &&
172 !uuid_is_null(es
->s_journal_uuid
))
173 set_uuid(probe
->dev
, es
->s_journal_uuid
, "EXT_JOURNAL");
175 blkid_set_tag(probe
->dev
, "SEC_TYPE", "ext2", sizeof("ext2"));
180 static int probe_ext2(struct blkid_probe
*probe
,
181 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
184 struct ext2_super_block
*es
;
186 es
= (struct ext2_super_block
*)buf
;
188 /* Distinguish between jbd and ext2/3 fs */
189 if (blkid_le32(es
->s_feature_incompat
) &
190 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)
191 return -BLKID_ERR_PARAM
;
193 /* Distinguish between ext3 and ext2 */
194 if ((blkid_le32(es
->s_feature_compat
) &
195 EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
196 return -BLKID_ERR_PARAM
;
198 get_ext2_info(probe
->dev
, buf
);
203 static int probe_jbd(struct blkid_probe
*probe
,
204 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
207 struct ext2_super_block
*es
= (struct ext2_super_block
*) buf
;
209 if (!(blkid_le32(es
->s_feature_incompat
) &
210 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
))
211 return -BLKID_ERR_PARAM
;
213 get_ext2_info(probe
->dev
, buf
);
218 #define FAT_ATTR_VOLUME_ID 0x08
219 #define FAT_ATTR_DIR 0x10
220 #define FAT_ATTR_LONG_NAME 0x0f
221 #define FAT_ATTR_MASK 0x3f
222 #define FAT_ENTRY_FREE 0xe5
224 static char *no_name
= "NO NAME ";
226 static unsigned char *search_fat_label(struct vfat_dir_entry
*dir
, int count
)
230 for (i
= 0; i
< count
; i
++) {
231 if (dir
[i
].name
[0] == 0x00)
234 if ((dir
[i
].name
[0] == FAT_ENTRY_FREE
) ||
235 (dir
[i
].cluster_high
!= 0 || dir
[i
].cluster_low
!= 0) ||
236 ((dir
[i
].attr
& FAT_ATTR_MASK
) == FAT_ATTR_LONG_NAME
))
239 if ((dir
[i
].attr
& (FAT_ATTR_VOLUME_ID
| FAT_ATTR_DIR
)) ==
240 FAT_ATTR_VOLUME_ID
) {
247 /* FAT label extraction from the root directory taken from Kay
248 * Sievers's volume_id library */
249 static int probe_fat(struct blkid_probe
*probe
,
250 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
253 struct vfat_super_block
*vs
= (struct vfat_super_block
*) buf
;
254 struct msdos_super_block
*ms
= (struct msdos_super_block
*) buf
;
255 struct vfat_dir_entry
*dir
;
257 const unsigned char *label
= 0, *vol_label
= 0;
258 unsigned char *vol_serno
;
259 int label_len
= 0, maxloop
= 100;
260 __u16 sector_size
, dir_entries
, reserved
;
261 __u32 sect_count
, fat_size
, dir_size
, cluster_count
, fat_length
;
262 __u32 buf_size
, start_data_sect
, next
, root_start
, root_dir_entries
;
264 /* sector size check */
265 sector_size
= blkid_le16(*((__u16
*) &ms
->ms_sector_size
));
266 if (sector_size
!= 0x200 && sector_size
!= 0x400 &&
267 sector_size
!= 0x800 && sector_size
!= 0x1000)
270 dir_entries
= blkid_le16(*((__u16
*) &ms
->ms_dir_entries
));
271 reserved
= blkid_le16(ms
->ms_reserved
);
272 sect_count
= blkid_le16(*((__u16
*) &ms
->ms_sectors
));
274 sect_count
= blkid_le32(ms
->ms_total_sect
);
276 fat_length
= blkid_le16(ms
->ms_fat_length
);
278 fat_length
= blkid_le32(vs
->vs_fat32_length
);
280 fat_size
= fat_length
* ms
->ms_fats
;
281 dir_size
= ((dir_entries
* sizeof(struct vfat_dir_entry
)) +
282 (sector_size
-1)) / sector_size
;
284 cluster_count
= sect_count
- (reserved
+ fat_size
+ dir_size
);
285 cluster_count
/= ms
->ms_cluster_size
;
287 if (cluster_count
> FAT32_MAX
)
290 if (ms
->ms_fat_length
) {
291 /* the label may be an attribute in the root directory */
292 root_start
= (reserved
+ fat_size
) * sector_size
;
293 root_dir_entries
= vs
->vs_dir_entries
[0] +
294 (vs
->vs_dir_entries
[1] << 8);
296 buf_size
= root_dir_entries
* sizeof(struct vfat_dir_entry
);
297 dir
= (struct vfat_dir_entry
*) get_buffer(probe
, root_start
,
300 vol_label
= search_fat_label(dir
, root_dir_entries
);
302 if (!vol_label
|| !memcmp(vol_label
, no_name
, 11))
303 vol_label
= ms
->ms_label
;
304 vol_serno
= ms
->ms_serno
;
306 blkid_set_tag(probe
->dev
, "SEC_TYPE", "msdos",
309 /* Search the FAT32 root dir for the label attribute */
310 buf_size
= vs
->vs_cluster_size
* sector_size
;
311 start_data_sect
= reserved
+ fat_size
;
313 next
= blkid_le32(vs
->vs_root_cluster
);
314 while (next
&& --maxloop
) {
316 __u64 next_off
, fat_entry_off
;
319 next_sect_off
= (next
- 2) * vs
->vs_cluster_size
;
320 next_off
= (start_data_sect
+ next_sect_off
) *
323 dir
= (struct vfat_dir_entry
*)
324 get_buffer(probe
, next_off
, buf_size
);
328 count
= buf_size
/ sizeof(struct vfat_dir_entry
);
330 vol_label
= search_fat_label(dir
, count
);
335 fat_entry_off
= (reserved
* sector_size
) +
336 (next
* sizeof(__u32
));
337 buf
= get_buffer(probe
, fat_entry_off
, buf_size
);
341 /* set next cluster */
342 next
= blkid_le32(*((__u32
*) buf
) & 0x0fffffff);
345 if (!vol_label
|| !memcmp(vol_label
, no_name
, 11))
346 vol_label
= vs
->vs_label
;
347 vol_serno
= vs
->vs_serno
;
350 if (vol_label
&& memcmp(vol_label
, no_name
, 11)) {
352 label_len
= figure_label_len(vol_label
, 11);
355 /* We can't just print them as %04X, because they are unaligned */
356 sprintf(serno
, "%02X%02X-%02X%02X", vol_serno
[3], vol_serno
[2],
357 vol_serno
[1], vol_serno
[0]);
359 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
, label_len
);
360 blkid_set_tag(probe
->dev
, "UUID", serno
, sizeof(serno
)-1);
366 * The FAT filesystem could be without a magic string in superblock
367 * (e.g. old floppies). This heuristic for FAT detection is inspired
368 * by http://vrfy.org/projects/volume_id/ and Linux kernel.
369 * [7-Jul-2005, Karel Zak <kzak@redhat.com>]
371 static int probe_fat_nomagic(struct blkid_probe
*probe
,
372 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
375 struct vfat_super_block
*vs
;
377 vs
= (struct vfat_super_block
*)buf
;
380 if (vs
->vs_heads
== 0)
383 /* cluster size check*/
384 if (vs
->vs_cluster_size
== 0 ||
385 (vs
->vs_cluster_size
& (vs
->vs_cluster_size
-1)))
389 if (vs
->vs_media
< 0xf8 && vs
->vs_media
!= 0xf0)
392 /* fat counts(Linux kernel expects at least 1 FAT table) */
396 return probe_fat(probe
, id
, buf
);
399 static int probe_xfs(struct blkid_probe
*probe
,
400 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
403 struct xfs_super_block
*xs
;
404 const char *label
= 0;
406 xs
= (struct xfs_super_block
*)buf
;
408 if (strlen(xs
->xs_fname
))
409 label
= xs
->xs_fname
;
410 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(xs
->xs_fname
));
411 set_uuid(probe
->dev
, xs
->xs_uuid
, 0);
415 static int probe_reiserfs(struct blkid_probe
*probe
,
416 struct blkid_magic
*id
, unsigned char *buf
)
418 struct reiserfs_super_block
*rs
= (struct reiserfs_super_block
*) buf
;
419 unsigned int blocksize
;
420 const char *label
= 0;
422 blocksize
= blkid_le16(rs
->rs_blocksize
);
424 /* If the superblock is inside the journal, we have the wrong one */
425 if (id
->bim_kboff
/(blocksize
>>10) > blkid_le32(rs
->rs_journal_block
))
426 return -BLKID_ERR_BIG
;
428 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
429 if (id
->bim_magic
[6] == '2' || id
->bim_magic
[6] == '3') {
430 if (strlen(rs
->rs_label
))
431 label
= rs
->rs_label
;
432 set_uuid(probe
->dev
, rs
->rs_uuid
, 0);
434 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(rs
->rs_label
));
439 static int probe_reiserfs4(struct blkid_probe
*probe
,
440 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
443 struct reiser4_super_block
*rs4
= (struct reiser4_super_block
*) buf
;
444 const unsigned char *label
= 0;
446 if (strlen((char *) rs4
->rs4_label
))
447 label
= rs4
->rs4_label
;
448 set_uuid(probe
->dev
, rs4
->rs4_uuid
, 0);
449 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
,
450 sizeof(rs4
->rs4_label
));
455 static int probe_jfs(struct blkid_probe
*probe
,
456 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
459 struct jfs_super_block
*js
;
460 const char *label
= 0;
462 js
= (struct jfs_super_block
*)buf
;
464 if (strlen((char *) js
->js_label
))
465 label
= (char *) js
->js_label
;
466 blkid_set_tag(probe
->dev
, "LABEL", label
, sizeof(js
->js_label
));
467 set_uuid(probe
->dev
, js
->js_uuid
, 0);
471 static int probe_romfs(struct blkid_probe
*probe
,
472 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
475 struct romfs_super_block
*ros
;
476 const char *label
= 0;
478 ros
= (struct romfs_super_block
*)buf
;
480 if (strlen((char *) ros
->ros_volume
))
481 label
= (char *) ros
->ros_volume
;
482 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
486 static int probe_cramfs(struct blkid_probe
*probe
,
487 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
490 struct cramfs_super_block
*csb
;
491 const char *label
= 0;
493 csb
= (struct cramfs_super_block
*)buf
;
495 if (strlen((char *) csb
->name
))
496 label
= (char *) csb
->name
;
497 blkid_set_tag(probe
->dev
, "LABEL", label
, 0);
501 static int probe_swap0(struct blkid_probe
*probe
,
502 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
503 unsigned char *buf
__BLKID_ATTR((unused
)))
505 blkid_set_tag(probe
->dev
, "UUID", 0, 0);
506 blkid_set_tag(probe
->dev
, "LABEL", 0, 0);
510 static int probe_swap1(struct blkid_probe
*probe
,
511 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
512 unsigned char *buf
__BLKID_ATTR((unused
)))
514 struct swap_id_block
*sws
;
516 probe_swap0(probe
, id
, buf
);
518 * Version 1 swap headers are always located at offset of 1024
519 * bytes, although the swap signature itself is located at the
520 * end of the page (which may vary depending on hardware
523 sws
= (struct swap_id_block
*) get_buffer(probe
, 1024, 1024);
527 /* arbitrary sanity check.. is there any garbage down there? */
528 if (sws
->sws_pad
[32] == 0 && sws
->sws_pad
[33] == 0) {
529 if (sws
->sws_volume
[0])
530 blkid_set_tag(probe
->dev
, "LABEL", sws
->sws_volume
,
531 sizeof(sws
->sws_volume
));
532 if (sws
->sws_uuid
[0])
533 set_uuid(probe
->dev
, sws
->sws_uuid
, 0);
538 static int probe_iso9660(struct blkid_probe
*probe
,
539 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
542 struct iso_volume_descriptor
*iso
;
543 const unsigned char *label
;
545 iso
= (struct iso_volume_descriptor
*) buf
;
546 label
= iso
->volume_id
;
548 blkid_set_tag(probe
->dev
, "LABEL", (const char *) label
,
549 figure_label_len(label
, 32));
555 *udf_magic
[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
556 "NSR03", "TEA01", 0 };
558 static int probe_udf(struct blkid_probe
*probe
,
559 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
560 unsigned char *buf
__BLKID_ATTR((unused
)))
563 struct iso_volume_descriptor
*isosb
;
566 /* determine the block size by scanning in 2K increments
567 (block sizes larger than 2K will be null padded) */
568 for (bs
= 1; bs
< 16; bs
++) {
569 isosb
= (struct iso_volume_descriptor
*)
570 get_buffer(probe
, bs
*2048+32768, sizeof(isosb
));
577 /* Scan up to another 64 blocks looking for additional VSD's */
578 for (j
= 1; j
< 64; j
++) {
580 isosb
= (struct iso_volume_descriptor
*)
581 get_buffer(probe
, j
*bs
*2048+32768,
586 /* If we find NSR0x then call it udf:
589 NSR03 for UDF 2.00 */
590 if (!strncmp(isosb
->vd_id
, "NSR0", 4))
592 for (m
= udf_magic
; *m
; m
++)
593 if (!strncmp(*m
, isosb
->vd_id
, 5))
601 static int probe_ocfs(struct blkid_probe
*probe
,
602 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
605 struct ocfs_volume_header ovh
;
606 struct ocfs_volume_label ovl
;
609 memcpy(&ovh
, buf
, sizeof(ovh
));
610 memcpy(&ovl
, buf
+512, sizeof(ovl
));
612 major
= ocfsmajor(ovh
);
614 blkid_set_tag(probe
->dev
,"SEC_TYPE","ocfs1",sizeof("ocfs1"));
616 blkid_set_tag(probe
->dev
,"SEC_TYPE","ntocfs",sizeof("ntocfs"));
618 blkid_set_tag(probe
->dev
, "LABEL", ovl
.label
, ocfslabellen(ovl
));
619 blkid_set_tag(probe
->dev
, "MOUNT", ovh
.mount
, ocfsmountlen(ovh
));
620 set_uuid(probe
->dev
, ovl
.vol_id
, 0);
624 static int probe_ocfs2(struct blkid_probe
*probe
,
625 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
628 struct ocfs2_super_block
*osb
;
630 osb
= (struct ocfs2_super_block
*)buf
;
632 blkid_set_tag(probe
->dev
, "LABEL", osb
->s_label
, sizeof(osb
->s_label
));
633 set_uuid(probe
->dev
, osb
->s_uuid
, 0);
637 static int probe_oracleasm(struct blkid_probe
*probe
,
638 struct blkid_magic
*id
__BLKID_ATTR((unused
)),
641 struct oracle_asm_disk_label
*dl
;
643 dl
= (struct oracle_asm_disk_label
*)buf
;
645 blkid_set_tag(probe
->dev
, "LABEL", dl
->dl_id
, sizeof(dl
->dl_id
));
650 * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
651 * in the type_array table below + bim_kbalign.
653 * When probing for a lot of magics, we handle everything in 1kB buffers so
654 * that we don't have to worry about reading each combination of block sizes.
656 #define BLKID_BLK_OFFS 64 /* currently reiserfs */
659 * Various filesystem magics that we can check for. Note that kboff and
660 * sboff are in kilobytes and bytes respectively. All magics are in
661 * byte strings so we don't worry about endian issues.
663 static struct blkid_magic type_array
[] = {
664 /* type kboff sboff len magic probe */
665 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm
},
666 { "ntfs", 0, 3, 8, "NTFS ", 0 },
667 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd
},
668 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3
},
669 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2
},
670 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs
},
671 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs
},
672 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs
},
673 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs
},
674 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs
},
675 { "reiser4", 64, 0, 7, "ReIsEr4", probe_reiserfs4
},
676 { "vfat", 0, 0x52, 5, "MSWIN", probe_fat
},
677 { "vfat", 0, 0x52, 8, "FAT32 ", probe_fat
},
678 { "vfat", 0, 0x36, 5, "MSDOS", probe_fat
},
679 { "vfat", 0, 0x36, 8, "FAT16 ", probe_fat
},
680 { "vfat", 0, 0x36, 8, "FAT12 ", probe_fat
},
681 { "vfat", 0, 0, 2, "\353\220", probe_fat_nomagic
},
682 { "vfat", 0, 0, 1, "\351", probe_fat_nomagic
},
683 { "minix", 1, 0x10, 2, "\177\023", 0 },
684 { "minix", 1, 0x10, 2, "\217\023", 0 },
685 { "minix", 1, 0x10, 2, "\150\044", 0 },
686 { "minix", 1, 0x10, 2, "\170\044", 0 },
687 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
688 { "xfs", 0, 0, 4, "XFSB", probe_xfs
},
689 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs
},
690 { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
691 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs
},
692 { "qnx4", 0, 4, 6, "QNX4FS", 0 },
693 { "udf", 32, 1, 5, "BEA01", probe_udf
},
694 { "udf", 32, 1, 5, "BOOT2", probe_udf
},
695 { "udf", 32, 1, 5, "CD001", probe_udf
},
696 { "udf", 32, 1, 5, "CDW02", probe_udf
},
697 { "udf", 32, 1, 5, "NSR02", probe_udf
},
698 { "udf", 32, 1, 5, "NSR03", probe_udf
},
699 { "udf", 32, 1, 5, "TEA01", probe_udf
},
700 { "iso9660", 32, 1, 5, "CD001", probe_iso9660
},
701 { "iso9660", 32, 9, 5, "CDROM", probe_iso9660
},
702 { "jfs", 32, 0, 4, "JFS1", probe_jfs
},
703 { "hfs", 1, 0, 2, "BD", 0 },
704 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
705 { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
706 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
707 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0
},
708 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1
},
709 { "swsuspend", 0, 0xff6, 9, "S1SUSPEND", probe_swap1
},
710 { "swsuspend", 0, 0xff6, 9, "S2SUSPEND", probe_swap1
},
711 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0
},
712 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1
},
713 { "swsuspend", 0, 0x1ff6, 9, "S1SUSPEND", probe_swap1
},
714 { "swsuspend", 0, 0x1ff6, 9, "S2SUSPEND", probe_swap1
},
715 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0
},
716 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1
},
717 { "swsuspend", 0, 0x3ff6, 9, "S1SUSPEND", probe_swap1
},
718 { "swsuspend", 0, 0x3ff6, 9, "S2SUSPEND", probe_swap1
},
719 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0
},
720 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1
},
721 { "swsuspend", 0, 0x7ff6, 9, "S1SUSPEND", probe_swap1
},
722 { "swsuspend", 0, 0x7ff6, 9, "S2SUSPEND", probe_swap1
},
723 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0
},
724 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1
},
725 { "swsuspend", 0, 0xfff6, 9, "S1SUSPEND", probe_swap1
},
726 { "swsuspend", 0, 0xfff6, 9, "S2SUSPEND", probe_swap1
},
727 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs
},
728 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2
},
729 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2
},
730 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2
},
731 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2
},
732 { NULL
, 0, 0, 0, NULL
, NULL
}
736 * Verify that the data in dev is consistent with what is on the actual
737 * block device (using the devname field only). Normally this will be
738 * called when finding items in the cache, but for long running processes
739 * is also desirable to revalidate an item before use.
741 * If we are unable to revalidate the data, we return the old data and
742 * do not set the BLKID_BID_FL_VERIFIED flag on it.
744 blkid_dev
blkid_verify(blkid_cache cache
, blkid_dev dev
)
746 struct blkid_magic
*id
;
747 struct blkid_probe probe
;
748 blkid_tag_iterate iter
;
750 const char *type
, *value
;
759 diff
= now
- dev
->bid_time
;
761 if ((now
> dev
->bid_time
) && (diff
> 0) &&
762 ((diff
< BLKID_PROBE_MIN
) ||
763 (dev
->bid_flags
& BLKID_BID_FL_VERIFIED
&&
764 diff
< BLKID_PROBE_INTERVAL
)))
768 printf("need to revalidate %s (time since last check %lu)\n",
769 dev
->bid_name
, diff
));
771 if (((probe
.fd
= open(dev
->bid_name
, O_RDONLY
)) < 0) ||
772 (fstat(probe
.fd
, &st
) < 0)) {
773 if (errno
== ENXIO
|| errno
== ENODEV
|| errno
== ENOENT
) {
777 /* We don't have read permission, just return cache data. */
779 printf("returning unverified data for %s\n",
791 * Iterate over the type array. If we already know the type,
792 * then try that first. If it doesn't work, then blow away
793 * the type information, and try again.
798 if (!dev
->bid_type
|| !strcmp(dev
->bid_type
, "mdraid")) {
801 if (check_mdraid(probe
.fd
, uuid
) == 0) {
802 set_uuid(dev
, uuid
, 0);
807 for (id
= type_array
; id
->bim_type
; id
++) {
809 strcmp(id
->bim_type
, dev
->bid_type
))
812 idx
= id
->bim_kboff
+ (id
->bim_sboff
>> 10);
813 buf
= get_buffer(&probe
, idx
<< 10, 1024);
817 if (memcmp(id
->bim_magic
, buf
+ (id
->bim_sboff
&0x3ff),
821 if ((id
->bim_probe
== NULL
) ||
822 (id
->bim_probe(&probe
, id
, buf
) == 0)) {
828 if (!id
->bim_type
&& dev
->bid_type
) {
830 * Zap the device filesystem information and try again
832 iter
= blkid_tag_iterate_begin(dev
);
833 while (blkid_tag_next(iter
, &type
, &value
) == 0)
834 blkid_set_tag(dev
, type
, 0, 0);
835 blkid_tag_iterate_end(iter
);
839 if (!dev
->bid_type
) {
846 dev
->bid_devno
= st
.st_rdev
;
847 dev
->bid_time
= time(0);
848 dev
->bid_flags
|= BLKID_BID_FL_VERIFIED
;
849 cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
851 blkid_set_tag(dev
, "TYPE", type
, 0);
853 DBG(DEBUG_PROBE
, printf("%s: devno 0x%04llx, type %s\n",
854 dev
->bid_name
, st
.st_rdev
, type
));
866 int blkid_known_fstype(const char *fstype
)
868 struct blkid_magic
*id
;
870 for (id
= type_array
; id
->bim_type
; id
++) {
871 if (strcmp(fstype
, id
->bim_type
) == 0)
878 int main(int argc
, char **argv
)
885 fprintf(stderr
, "Usage: %s device\n"
886 "Probe a single device to determine type\n", argv
[0]);
889 if ((ret
= blkid_get_cache(&cache
, "/dev/null")) != 0) {
890 fprintf(stderr
, "%s: error creating cache (%d)\n",
894 dev
= blkid_get_dev(cache
, argv
[1], BLKID_DEV_NORMAL
);
896 printf("%s: %s has an unsupported type\n", argv
[0], argv
[1]);
899 printf("TYPE='%s'\n", dev
->bid_type
? dev
->bid_type
: "(null)");
901 printf("LABEL='%s'\n", dev
->bid_label
);
903 printf("UUID='%s'\n", dev
->bid_uuid
);