1 /* vi: set sw=4 ts=4: */
3 * probe.c - identify a block device by its contents, and return a dev
4 * struct with the details
6 * Copyright (C) 1999 by Andries Brouwer
7 * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
8 * Copyright (C) 2001 by Andreas Dilger
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"
36 * This is a special case code to check for an MDRAID device. We do
37 * this special since it requires checking for a superblock at the end
40 static int check_mdraid(int fd
, unsigned char *ret_uuid
)
42 struct mdp_superblock_s
*md
;
47 return -BLKID_ERR_PARAM
;
49 offset
= (blkid_get_dev_size(fd
) & ~((blkid_loff_t
)65535)) - 65536;
51 if (blkid_llseek(fd
, offset
, 0) < 0 ||
52 read(fd
, buf
, 4096) != 4096)
55 /* Check for magic number */
56 if (memcmp("\251+N\374", buf
, 4))
57 return -BLKID_ERR_PARAM
;
63 /* The MD UUID is not contiguous in the superblock, make it so */
64 md
= (struct mdp_superblock_s
*)buf
;
65 if (md
->set_uuid0
|| md
->set_uuid1
|| md
->set_uuid2
|| md
->set_uuid3
) {
66 memcpy(ret_uuid
, &md
->set_uuid0
, 4);
67 memcpy(ret_uuid
, &md
->set_uuid1
, 12);
72 static void set_uuid(blkid_dev dev
, uuid_t uuid
)
76 if (!uuid_is_null(uuid
)) {
77 uuid_unparse(uuid
, str
);
78 blkid_set_tag(dev
, "UUID", str
, sizeof(str
));
82 static void get_ext2_info(blkid_dev dev
, unsigned char *buf
)
84 struct ext2_super_block
*es
= (struct ext2_super_block
*) buf
;
85 const char *label
= NULL
;
87 DBG(DEBUG_PROBE
, printf("ext2_sb.compat = %08X:%08X:%08X\n",
88 blkid_le32(es
->s_feature_compat
),
89 blkid_le32(es
->s_feature_incompat
),
90 blkid_le32(es
->s_feature_ro_compat
)));
92 if (strlen(es
->s_volume_name
))
93 label
= es
->s_volume_name
;
94 blkid_set_tag(dev
, "LABEL", label
, sizeof(es
->s_volume_name
));
96 set_uuid(dev
, es
->s_uuid
);
99 static int probe_ext3(int fd
__BLKID_ATTR((unused
)),
100 blkid_cache cache
__BLKID_ATTR((unused
)),
102 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
105 struct ext2_super_block
*es
;
107 es
= (struct ext2_super_block
*)buf
;
109 /* Distinguish between jbd and ext2/3 fs */
110 if (blkid_le32(es
->s_feature_incompat
) &
111 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)
112 return -BLKID_ERR_PARAM
;
114 /* Distinguish between ext3 and ext2 */
115 if (!(blkid_le32(es
->s_feature_compat
) &
116 EXT3_FEATURE_COMPAT_HAS_JOURNAL
))
117 return -BLKID_ERR_PARAM
;
119 get_ext2_info(dev
, buf
);
121 blkid_set_tag(dev
, "SEC_TYPE", "ext2", sizeof("ext2"));
126 static int probe_ext2(int fd
__BLKID_ATTR((unused
)),
127 blkid_cache cache
__BLKID_ATTR((unused
)),
129 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
132 struct ext2_super_block
*es
;
134 es
= (struct ext2_super_block
*)buf
;
136 /* Distinguish between jbd and ext2/3 fs */
137 if (blkid_le32(es
->s_feature_incompat
) &
138 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
)
139 return -BLKID_ERR_PARAM
;
141 get_ext2_info(dev
, buf
);
146 static int probe_jbd(int fd
__BLKID_ATTR((unused
)),
147 blkid_cache cache
__BLKID_ATTR((unused
)),
149 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
152 struct ext2_super_block
*es
= (struct ext2_super_block
*) buf
;
154 if (!(blkid_le32(es
->s_feature_incompat
) &
155 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV
))
156 return -BLKID_ERR_PARAM
;
158 get_ext2_info(dev
, buf
);
163 static int probe_vfat(int fd
__BLKID_ATTR((unused
)),
164 blkid_cache cache
__BLKID_ATTR((unused
)),
166 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
169 struct vfat_super_block
*vs
;
171 const char *label
= NULL
;
174 vs
= (struct vfat_super_block
*)buf
;
176 if (strncmp(vs
->vs_label
, "NO NAME", 7)) {
177 char *end
= vs
->vs_label
+ sizeof(vs
->vs_label
) - 1;
179 while (*end
== ' ' && end
>= vs
->vs_label
)
181 if (end
>= vs
->vs_label
) {
182 label
= vs
->vs_label
;
183 label_len
= end
- vs
->vs_label
+ 1;
187 /* We can't just print them as %04X, because they are unaligned */
188 sprintf(serno
, "%02X%02X-%02X%02X", vs
->vs_serno
[3], vs
->vs_serno
[2],
189 vs
->vs_serno
[1], vs
->vs_serno
[0]);
190 blkid_set_tag(dev
, "LABEL", label
, label_len
);
191 blkid_set_tag(dev
, "UUID", serno
, sizeof(serno
));
196 static int probe_msdos(int fd
__BLKID_ATTR((unused
)),
197 blkid_cache cache
__BLKID_ATTR((unused
)),
199 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
202 struct msdos_super_block
*ms
= (struct msdos_super_block
*) buf
;
204 const char *label
= NULL
;
207 if (strncmp(ms
->ms_label
, "NO NAME", 7)) {
208 char *end
= ms
->ms_label
+ sizeof(ms
->ms_label
) - 1;
210 while (*end
== ' ' && end
>= ms
->ms_label
)
212 if (end
>= ms
->ms_label
) {
213 label
= ms
->ms_label
;
214 label_len
= end
- ms
->ms_label
+ 1;
218 /* We can't just print them as %04X, because they are unaligned */
219 sprintf(serno
, "%02X%02X-%02X%02X", ms
->ms_serno
[3], ms
->ms_serno
[2],
220 ms
->ms_serno
[1], ms
->ms_serno
[0]);
221 blkid_set_tag(dev
, "UUID", serno
, 0);
222 blkid_set_tag(dev
, "LABEL", label
, label_len
);
223 blkid_set_tag(dev
, "SEC_TYPE", "msdos", sizeof("msdos"));
228 static int probe_xfs(int fd
__BLKID_ATTR((unused
)),
229 blkid_cache cache
__BLKID_ATTR((unused
)),
231 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
234 struct xfs_super_block
*xs
;
235 const char *label
= NULL
;
237 xs
= (struct xfs_super_block
*)buf
;
239 if (strlen(xs
->xs_fname
))
240 label
= xs
->xs_fname
;
241 blkid_set_tag(dev
, "LABEL", label
, sizeof(xs
->xs_fname
));
242 set_uuid(dev
, xs
->xs_uuid
);
246 static int probe_reiserfs(int fd
__BLKID_ATTR((unused
)),
247 blkid_cache cache
__BLKID_ATTR((unused
)),
249 const struct blkid_magic
*id
, unsigned char *buf
)
251 struct reiserfs_super_block
*rs
= (struct reiserfs_super_block
*) buf
;
252 unsigned int blocksize
;
253 const char *label
= NULL
;
255 blocksize
= blkid_le16(rs
->rs_blocksize
);
257 /* If the superblock is inside the journal, we have the wrong one */
258 if (id
->bim_kboff
/(blocksize
>>10) > blkid_le32(rs
->rs_journal_block
))
259 return -BLKID_ERR_BIG
;
261 /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
262 if (!strcmp(id
->bim_magic
, "ReIsEr2Fs") ||
263 !strcmp(id
->bim_magic
, "ReIsEr3Fs")) {
264 if (strlen(rs
->rs_label
))
265 label
= rs
->rs_label
;
266 set_uuid(dev
, rs
->rs_uuid
);
268 blkid_set_tag(dev
, "LABEL", label
, sizeof(rs
->rs_label
));
273 static int probe_jfs(int fd
__BLKID_ATTR((unused
)),
274 blkid_cache cache
__BLKID_ATTR((unused
)),
276 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
279 struct jfs_super_block
*js
;
280 const char *label
= NULL
;
282 js
= (struct jfs_super_block
*)buf
;
284 if (strlen((char *) js
->js_label
))
285 label
= (char *) js
->js_label
;
286 blkid_set_tag(dev
, "LABEL", label
, sizeof(js
->js_label
));
287 set_uuid(dev
, js
->js_uuid
);
291 static int probe_romfs(int fd
__BLKID_ATTR((unused
)),
292 blkid_cache cache
__BLKID_ATTR((unused
)),
294 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
297 struct romfs_super_block
*ros
;
298 const char *label
= NULL
;
300 ros
= (struct romfs_super_block
*)buf
;
302 if (strlen((char *) ros
->ros_volume
))
303 label
= (char *) ros
->ros_volume
;
304 blkid_set_tag(dev
, "LABEL", label
, 0);
308 static int probe_cramfs(int fd
__BLKID_ATTR((unused
)),
309 blkid_cache cache
__BLKID_ATTR((unused
)),
311 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
314 struct cramfs_super_block
*csb
;
315 const char *label
= NULL
;
317 csb
= (struct cramfs_super_block
*)buf
;
319 if (strlen((char *) csb
->name
))
320 label
= (char *) csb
->name
;
321 blkid_set_tag(dev
, "LABEL", label
, 0);
325 static int probe_swap0(int fd
__BLKID_ATTR((unused
)),
326 blkid_cache cache
__BLKID_ATTR((unused
)),
328 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
329 unsigned char *buf
__BLKID_ATTR((unused
)))
331 blkid_set_tag(dev
, "UUID", 0, 0);
332 blkid_set_tag(dev
, "LABEL", 0, 0);
336 static int probe_swap1(int fd
,
337 blkid_cache cache
__BLKID_ATTR((unused
)),
339 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
340 unsigned char *buf
__BLKID_ATTR((unused
)))
342 struct swap_id_block
*sws
;
344 probe_swap0(fd
, cache
, dev
, id
, buf
);
346 * Version 1 swap headers are always located at offset of 1024
347 * bytes, although the swap signature itself is located at the
348 * end of the page (which may vary depending on hardware
351 if (lseek(fd
, 1024, SEEK_SET
) < 0) return 1;
353 if (read(fd
, sws
, 1024) != 1024) {
358 /* arbitrary sanity check.. is there any garbage down there? */
359 if (sws
->sws_pad
[32] == 0 && sws
->sws_pad
[33] == 0) {
360 if (sws
->sws_volume
[0])
361 blkid_set_tag(dev
, "LABEL", (const char*)sws
->sws_volume
,
362 sizeof(sws
->sws_volume
));
363 if (sws
->sws_uuid
[0])
364 set_uuid(dev
, sws
->sws_uuid
);
372 * const udf_magic
[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
373 "NSR03", "TEA01", 0 };
375 static int probe_udf(int fd
, blkid_cache cache
__BLKID_ATTR((unused
)),
376 blkid_dev dev
__BLKID_ATTR((unused
)),
377 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
378 unsigned char *buf
__BLKID_ATTR((unused
)))
381 struct iso_volume_descriptor isosb
;
382 const char *const *m
;
384 /* determine the block size by scanning in 2K increments
385 (block sizes larger than 2K will be null padded) */
386 for (bs
= 1; bs
< 16; bs
++) {
387 lseek(fd
, bs
*2048+32768, SEEK_SET
);
388 if (read(fd
, (char *)&isosb
, sizeof(isosb
)) != sizeof(isosb
))
394 /* Scan up to another 64 blocks looking for additional VSD's */
395 for (j
= 1; j
< 64; j
++) {
397 lseek(fd
, j
*bs
*2048+32768, SEEK_SET
);
398 if (read(fd
, (char *)&isosb
, sizeof(isosb
))
402 /* If we find NSR0x then call it udf:
405 NSR03 for UDF 2.00 */
406 if (!strncmp(isosb
.id
, "NSR0", 4))
408 for (m
= udf_magic
; *m
; m
++)
409 if (!strncmp(*m
, isosb
.id
, 5))
417 static int probe_ocfs(int fd
__BLKID_ATTR((unused
)),
418 blkid_cache cache
__BLKID_ATTR((unused
)),
420 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
423 struct ocfs_volume_header ovh
;
424 struct ocfs_volume_label ovl
;
427 memcpy(&ovh
, buf
, sizeof(ovh
));
428 memcpy(&ovl
, buf
+512, sizeof(ovl
));
430 major
= ocfsmajor(ovh
);
432 blkid_set_tag(dev
, "SEC_TYPE", "ocfs1", sizeof("ocfs1"));
434 blkid_set_tag(dev
, "SEC_TYPE", "ntocfs", sizeof("ntocfs"));
436 blkid_set_tag(dev
, "LABEL", (const char*)ovl
.label
, ocfslabellen(ovl
));
437 blkid_set_tag(dev
, "MOUNT", (const char*)ovh
.mount
, ocfsmountlen(ovh
));
438 set_uuid(dev
, ovl
.vol_id
);
442 static int probe_ocfs2(int fd
__BLKID_ATTR((unused
)),
443 blkid_cache cache
__BLKID_ATTR((unused
)),
445 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
448 struct ocfs2_super_block
*osb
;
450 osb
= (struct ocfs2_super_block
*)buf
;
452 blkid_set_tag(dev
, "LABEL", (const char*)osb
->s_label
, sizeof(osb
->s_label
));
453 set_uuid(dev
, osb
->s_uuid
);
457 static int probe_oracleasm(int fd
__BLKID_ATTR((unused
)),
458 blkid_cache cache
__BLKID_ATTR((unused
)),
460 const struct blkid_magic
*id
__BLKID_ATTR((unused
)),
463 struct oracle_asm_disk_label
*dl
;
465 dl
= (struct oracle_asm_disk_label
*)buf
;
467 blkid_set_tag(dev
, "LABEL", dl
->dl_id
, sizeof(dl
->dl_id
));
472 * BLKID_BLK_OFFS is at least as large as the highest bim_kboff defined
473 * in the type_array table below + bim_kbalign.
475 * When probing for a lot of magics, we handle everything in 1kB buffers so
476 * that we don't have to worry about reading each combination of block sizes.
478 #define BLKID_BLK_OFFS 64 /* currently reiserfs */
481 * Various filesystem magics that we can check for. Note that kboff and
482 * sboff are in kilobytes and bytes respectively. All magics are in
483 * byte strings so we don't worry about endian issues.
485 static const struct blkid_magic type_array
[] = {
486 /* type kboff sboff len magic probe */
487 { "oracleasm", 0, 32, 8, "ORCLDISK", probe_oracleasm
},
488 { "ntfs", 0, 3, 8, "NTFS ", 0 },
489 { "jbd", 1, 0x38, 2, "\123\357", probe_jbd
},
490 { "ext3", 1, 0x38, 2, "\123\357", probe_ext3
},
491 { "ext2", 1, 0x38, 2, "\123\357", probe_ext2
},
492 { "reiserfs", 8, 0x34, 8, "ReIsErFs", probe_reiserfs
},
493 { "reiserfs", 64, 0x34, 9, "ReIsEr2Fs", probe_reiserfs
},
494 { "reiserfs", 64, 0x34, 9, "ReIsEr3Fs", probe_reiserfs
},
495 { "reiserfs", 64, 0x34, 8, "ReIsErFs", probe_reiserfs
},
496 { "reiserfs", 8, 20, 8, "ReIsErFs", probe_reiserfs
},
497 { "vfat", 0, 0x52, 5, "MSWIN", probe_vfat
},
498 { "vfat", 0, 0x52, 8, "FAT32 ", probe_vfat
},
499 { "vfat", 0, 0x36, 5, "MSDOS", probe_msdos
},
500 { "vfat", 0, 0x36, 8, "FAT16 ", probe_msdos
},
501 { "vfat", 0, 0x36, 8, "FAT12 ", probe_msdos
},
502 { "minix", 1, 0x10, 2, "\177\023", 0 },
503 { "minix", 1, 0x10, 2, "\217\023", 0 },
504 { "minix", 1, 0x10, 2, "\150\044", 0 },
505 { "minix", 1, 0x10, 2, "\170\044", 0 },
506 { "vxfs", 1, 0, 4, "\365\374\001\245", 0 },
507 { "xfs", 0, 0, 4, "XFSB", probe_xfs
},
508 { "romfs", 0, 0, 8, "-rom1fs-", probe_romfs
},
509 { "bfs", 0, 0, 4, "\316\372\173\033", 0 },
510 { "cramfs", 0, 0, 4, "E=\315\050", probe_cramfs
},
511 { "qnx4", 0, 4, 6, "QNX4FS", 0 },
512 { "udf", 32, 1, 5, "BEA01", probe_udf
},
513 { "udf", 32, 1, 5, "BOOT2", probe_udf
},
514 { "udf", 32, 1, 5, "CD001", probe_udf
},
515 { "udf", 32, 1, 5, "CDW02", probe_udf
},
516 { "udf", 32, 1, 5, "NSR02", probe_udf
},
517 { "udf", 32, 1, 5, "NSR03", probe_udf
},
518 { "udf", 32, 1, 5, "TEA01", probe_udf
},
519 { "iso9660", 32, 1, 5, "CD001", 0 },
520 { "iso9660", 32, 9, 5, "CDROM", 0 },
521 { "jfs", 32, 0, 4, "JFS1", probe_jfs
},
522 { "hfs", 1, 0, 2, "BD", 0 },
523 { "ufs", 8, 0x55c, 4, "T\031\001\000", 0 },
524 { "hpfs", 8, 0, 4, "I\350\225\371", 0 },
525 { "sysv", 0, 0x3f8, 4, "\020~\030\375", 0 },
526 { "swap", 0, 0xff6, 10, "SWAP-SPACE", probe_swap0
},
527 { "swap", 0, 0xff6, 10, "SWAPSPACE2", probe_swap1
},
528 { "swap", 0, 0x1ff6, 10, "SWAP-SPACE", probe_swap0
},
529 { "swap", 0, 0x1ff6, 10, "SWAPSPACE2", probe_swap1
},
530 { "swap", 0, 0x3ff6, 10, "SWAP-SPACE", probe_swap0
},
531 { "swap", 0, 0x3ff6, 10, "SWAPSPACE2", probe_swap1
},
532 { "swap", 0, 0x7ff6, 10, "SWAP-SPACE", probe_swap0
},
533 { "swap", 0, 0x7ff6, 10, "SWAPSPACE2", probe_swap1
},
534 { "swap", 0, 0xfff6, 10, "SWAP-SPACE", probe_swap0
},
535 { "swap", 0, 0xfff6, 10, "SWAPSPACE2", probe_swap1
},
536 { "ocfs", 0, 8, 9, "OracleCFS", probe_ocfs
},
537 { "ocfs2", 1, 0, 6, "OCFSV2", probe_ocfs2
},
538 { "ocfs2", 2, 0, 6, "OCFSV2", probe_ocfs2
},
539 { "ocfs2", 4, 0, 6, "OCFSV2", probe_ocfs2
},
540 { "ocfs2", 8, 0, 6, "OCFSV2", probe_ocfs2
},
541 { NULL
, 0, 0, 0, NULL
, NULL
}
545 * Verify that the data in dev is consistent with what is on the actual
546 * block device (using the devname field only). Normally this will be
547 * called when finding items in the cache, but for long running processes
548 * is also desirable to revalidate an item before use.
550 * If we are unable to revalidate the data, we return the old data and
551 * do not set the BLKID_BID_FL_VERIFIED flag on it.
553 blkid_dev
blkid_verify(blkid_cache cache
, blkid_dev dev
)
555 const struct blkid_magic
*id
;
556 unsigned char *bufs
[BLKID_BLK_OFFS
+ 1], *buf
;
566 diff
= now
- dev
->bid_time
;
568 if ((now
< dev
->bid_time
) ||
569 (diff
< BLKID_PROBE_MIN
) ||
570 (dev
->bid_flags
& BLKID_BID_FL_VERIFIED
&&
571 diff
< BLKID_PROBE_INTERVAL
))
575 printf("need to revalidate %s (time since last check %lu)\n",
576 dev
->bid_name
, diff
));
578 if (((fd
= open(dev
->bid_name
, O_RDONLY
)) < 0) ||
579 (fstat(fd
, &st
) < 0)) {
580 if (errno
== ENXIO
|| errno
== ENODEV
|| errno
== ENOENT
) {
584 /* We don't have read permission, just return cache data. */
586 printf("returning unverified data for %s\n",
591 memset(bufs
, 0, sizeof(bufs
));
594 * Iterate over the type array. If we already know the type,
595 * then try that first. If it doesn't work, then blow away
596 * the type information, and try again.
601 if (!dev
->bid_type
|| !strcmp(dev
->bid_type
, "mdraid")) {
604 if (check_mdraid(fd
, uuid
) == 0) {
610 for (id
= type_array
; id
->bim_type
; id
++) {
612 strcmp(id
->bim_type
, dev
->bid_type
))
615 idx
= id
->bim_kboff
+ (id
->bim_sboff
>> 10);
616 if (idx
> BLKID_BLK_OFFS
|| idx
< 0)
620 if (lseek(fd
, idx
<< 10, SEEK_SET
) < 0)
625 if (read(fd
, buf
, 1024) != 1024) {
632 if (memcmp(id
->bim_magic
, buf
+ (id
->bim_sboff
&0x3ff),
636 if ((id
->bim_probe
== NULL
) ||
637 (id
->bim_probe(fd
, cache
, dev
, id
, buf
) == 0)) {
643 if (!id
->bim_type
&& dev
->bid_type
) {
645 * Zap the device filesystem type and try again
647 blkid_set_tag(dev
, "TYPE", 0, 0);
648 blkid_set_tag(dev
, "SEC_TYPE", 0, 0);
649 blkid_set_tag(dev
, "LABEL", 0, 0);
650 blkid_set_tag(dev
, "UUID", 0, 0);
654 if (!dev
->bid_type
) {
661 dev
->bid_devno
= st
.st_rdev
;
662 dev
->bid_time
= time(NULL
);
663 dev
->bid_flags
|= BLKID_BID_FL_VERIFIED
;
664 cache
->bic_flags
|= BLKID_BIC_FL_CHANGED
;
666 blkid_set_tag(dev
, "TYPE", type
, 0);
668 DBG(DEBUG_PROBE
, printf("%s: devno 0x%04llx, type %s\n",
669 dev
->bid_name
, st
.st_rdev
, type
));
677 int blkid_known_fstype(const char *fstype
)
679 const struct blkid_magic
*id
;
681 for (id
= type_array
; id
->bim_type
; id
++) {
682 if (strcmp(fstype
, id
->bim_type
) == 0)
689 int main(int argc
, char **argv
)
695 blkid_debug_mask
= DEBUG_ALL
;
697 fprintf(stderr
, "Usage: %s device\n"
698 "Probe a single device to determine type\n", argv
[0]);
701 if ((ret
= blkid_get_cache(&cache
, bb_dev_null
)) != 0) {
702 fprintf(stderr
, "%s: error creating cache (%d)\n",
706 dev
= blkid_get_dev(cache
, argv
[1], BLKID_DEV_NORMAL
);
708 printf("%s: %s has an unsupported type\n", argv
[0], argv
[1]);
711 printf("%s is type %s\n", argv
[1], dev
->bid_type
?
712 dev
->bid_type
: "(null)");
714 printf("\tlabel is '%s'\n", dev
->bid_label
);
716 printf("\tuuid is %s\n", dev
->bid_uuid
);