aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-02-18 21:08:49 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-02-18 21:08:49 +0000
commitde7684a309ad20c1b889d048d741cb1dd52245f7 (patch)
treeefae3387e1978cdd128ff2a922b734d0e9d0180f
parent27dd495b98a6135554b1d839fefe436ba3c6ca71 (diff)
downloadbusybox-w32-de7684a309ad20c1b889d048d741cb1dd52245f7.tar.gz
busybox-w32-de7684a309ad20c1b889d048d741cb1dd52245f7.tar.bz2
busybox-w32-de7684a309ad20c1b889d048d741cb1dd52245f7.zip
support for mount by label (not yet tested)
Also adds findfs applet. Closes bug 1143.
-rw-r--r--Makefile1
-rw-r--r--e2fsprogs/old_e2fsprogs/tune2fs.c18
-rw-r--r--include/usage.h7
-rw-r--r--include/volume_id.h22
-rw-r--r--util-linux/Config.in229
-rw-r--r--util-linux/Kbuild1
-rw-r--r--util-linux/fdisk_sgi.c2
-rw-r--r--util-linux/findfs.c38
-rw-r--r--util-linux/mount.c32
-rw-r--r--util-linux/volume_id/Kbuild41
-rw-r--r--util-linux/volume_id/cramfs.c58
-rw-r--r--util-linux/volume_id/ext.c71
-rw-r--r--util-linux/volume_id/fat.c333
-rw-r--r--util-linux/volume_id/get_devname.c399
-rw-r--r--util-linux/volume_id/hfs.c292
-rw-r--r--util-linux/volume_id/highpoint.c86
-rw-r--r--util-linux/volume_id/hpfs.c50
-rw-r--r--util-linux/volume_id/iso9660.c118
-rw-r--r--util-linux/volume_id/isw_raid.c58
-rw-r--r--util-linux/volume_id/jfs.c59
-rw-r--r--util-linux/volume_id/linux_raid.c79
-rw-r--r--util-linux/volume_id/linux_swap.c73
-rw-r--r--util-linux/volume_id/lsi_raid.c52
-rw-r--r--util-linux/volume_id/luks.c76
-rw-r--r--util-linux/volume_id/lvm.c91
-rw-r--r--util-linux/volume_id/mac.c125
-rw-r--r--util-linux/volume_id/minix.c76
-rw-r--r--util-linux/volume_id/msdos.c196
-rw-r--r--util-linux/volume_id/ntfs.c193
-rw-r--r--util-linux/volume_id/nvidia_raid.c56
-rw-r--r--util-linux/volume_id/ocfs2.c105
-rw-r--r--util-linux/volume_id/promise_raid.c63
-rw-r--r--util-linux/volume_id/reiserfs.c105
-rw-r--r--util-linux/volume_id/romfs.c54
-rw-r--r--util-linux/volume_id/silicon_raid.c69
-rw-r--r--util-linux/volume_id/sysv.c125
-rw-r--r--util-linux/volume_id/udf.c172
-rw-r--r--util-linux/volume_id/ufs.c206
-rw-r--r--util-linux/volume_id/util.c260
-rw-r--r--util-linux/volume_id/via_raid.c68
-rw-r--r--util-linux/volume_id/volume_id.c214
-rw-r--r--util-linux/volume_id/volume_id_internal.h220
-rw-r--r--util-linux/volume_id/xfs.c59
43 files changed, 4632 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index 60edff9b4..0f21ccff3 100644
--- a/Makefile
+++ b/Makefile
@@ -452,6 +452,7 @@ libs-y := \
452 shell/ \ 452 shell/ \
453 sysklogd/ \ 453 sysklogd/ \
454 util-linux/ \ 454 util-linux/ \
455 util-linux/volume_id/ \
455 456
456endif # KBUILD_EXTMOD 457endif # KBUILD_EXTMOD
457 458
diff --git a/e2fsprogs/old_e2fsprogs/tune2fs.c b/e2fsprogs/old_e2fsprogs/tune2fs.c
index c5c84d68e..b7a1b21eb 100644
--- a/e2fsprogs/old_e2fsprogs/tune2fs.c
+++ b/e2fsprogs/old_e2fsprogs/tune2fs.c
@@ -557,20 +557,6 @@ static void parse_tune2fs_options(int argc, char **argv)
557 device_name = x_blkid_get_devname(argv[optind]); 557 device_name = x_blkid_get_devname(argv[optind]);
558} 558}
559 559
560#ifdef CONFIG_FINDFS
561static ATTRIBUTE_NORETURN void do_findfs(int argc, char **argv)
562{
563 if ((argc != 2) ||
564 (strncmp(argv[1], "LABEL=", 6) && strncmp(argv[1], "UUID=", 5)))
565 bb_show_usage();
566 device_name = x_blkid_get_devname(argv[1]);
567 puts(device_name);
568 exit(0);
569}
570#else
571#define do_findfs(x, y)
572#endif
573
574static void tune2fs_clean_up(void) 560static void tune2fs_clean_up(void)
575{ 561{
576 if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name); 562 if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name);
@@ -588,9 +574,7 @@ int tune2fs_main(int argc, char **argv)
588 if (ENABLE_FEATURE_CLEAN_UP) 574 if (ENABLE_FEATURE_CLEAN_UP)
589 atexit(tune2fs_clean_up); 575 atexit(tune2fs_clean_up);
590 576
591 if (ENABLE_FINDFS && (applet_name[0] == 'f')) /* findfs */ 577 if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */
592 do_findfs(argc, argv); /* no return */
593 else if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */
594 parse_e2label_options(argc, argv); 578 parse_e2label_options(argc, argv);
595 else 579 else
596 parse_tune2fs_options(argc, argv); /* tune2fs */ 580 parse_tune2fs_options(argc, argv); /* tune2fs */
diff --git a/include/usage.h b/include/usage.h
index 04ef1822e..d1878827b 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -1029,6 +1029,13 @@ USE_FEATURE_BRCTL_FANCY("\n" \
1029 " -t Get only headers\n" \ 1029 " -t Get only headers\n" \
1030 " -z Delete messages on server" 1030 " -z Delete messages on server"
1031 1031
1032#define findfs_trivial_usage \
1033 "LABEL=label or UUID=uuid"
1034#define findfs_full_usage \
1035 "Finds a filesystem device based on a label or UUID."
1036#define findfs_example_usage \
1037 "$ findfs LABEL=MyDevice"
1038
1032#define find_trivial_usage \ 1039#define find_trivial_usage \
1033 "[PATH...] [EXPRESSION]" 1040 "[PATH...] [EXPRESSION]"
1034#define find_full_usage \ 1041#define find_full_usage \
diff --git a/include/volume_id.h b/include/volume_id.h
new file mode 100644
index 000000000..99cb11ff6
--- /dev/null
+++ b/include/volume_id.h
@@ -0,0 +1,22 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21char *get_devname_from_label(const char *spec);
22char *get_devname_from_uuid(const char *spec);
diff --git a/util-linux/Config.in b/util-linux/Config.in
index 3b0f778cb..552ca0f31 100644
--- a/util-linux/Config.in
+++ b/util-linux/Config.in
@@ -150,6 +150,17 @@ config FEATURE_FDISK_ADVANCED
150 partition, and similarly evil things. Unless you have a very good 150 partition, and similarly evil things. Unless you have a very good
151 reason you would be wise to leave this disabled. 151 reason you would be wise to leave this disabled.
152 152
153config FINDFS
154 bool "findfs"
155 default n
156 select VOLUMEID
157 help
158 This is similar to the findfs program that is part of the e2fsprogs
159 package. However, the e2fsprogs version only support ext2/3. This
160 version supports those in addition to FAT, swap, and ReiserFS.
161 WARNING:
162 With all submodules selected, it will add ~11k to busybox.
163
153config FREERAMDISK 164config FREERAMDISK
154 bool "freeramdisk" 165 bool "freeramdisk"
155 default n 166 default n
@@ -375,6 +386,215 @@ config FEATURE_USE_TERMIOS
375 will be unable to determine the current screen size, and will be 386 will be unable to determine the current screen size, and will be
376 unable to move the cursor. 387 unable to move the cursor.
377 388
389config VOLUMEID
390 bool "Routines for detecting label and uuid on common filesystems"
391 default n
392 help
393 TODO
394
395config FEATURE_VOLUMEID_EXT
396 bool "Ext filesystem"
397 default n
398 depends on VOLUMEID
399 help
400 TODO
401
402config FEATURE_VOLUMEID_REISERFS
403 bool "Reiser filesystem"
404 default n
405 depends on VOLUMEID
406 help
407 TODO
408
409config FEATURE_VOLUMEID_FAT
410 bool "fat filesystem"
411 default n
412 depends on VOLUMEID
413 help
414 TODO
415
416config FEATURE_VOLUMEID_HFS
417 bool "hfs filesystem"
418 default n
419 depends on VOLUMEID
420 help
421 TODO
422
423config FEATURE_VOLUMEID_JFS
424 bool "jfs filesystem"
425 default n
426 depends on VOLUMEID
427 help
428 TODO
429
430config FEATURE_VOLUMEID_UFS
431 bool "ufs filesystem"
432 default n
433 depends on VOLUMEID
434 help
435 TODO
436
437config FEATURE_VOLUMEID_XFS
438 bool "xfs filesystem"
439 default n
440 depends on VOLUMEID
441 help
442 TODO
443
444config FEATURE_VOLUMEID_NTFS
445 bool "ntfs filesystem"
446 default n
447 depends on VOLUMEID
448 help
449 TODO
450
451config FEATURE_VOLUMEID_ISO9660
452 bool "iso9660 filesystem"
453 default n
454 depends on VOLUMEID
455 help
456 TODO
457
458config FEATURE_VOLUMEID_UDF
459 bool "udf filesystem"
460 default n
461 depends on VOLUMEID
462 help
463 TODO
464
465config FEATURE_VOLUMEID_LUKS
466 bool "luks filesystem"
467 default n
468 depends on VOLUMEID
469 help
470 TODO
471
472config FEATURE_VOLUMEID_LINUXSWAP
473 bool "linux swap filesystem"
474 default n
475 depends on VOLUMEID
476 help
477 TODO
478
479config FEATURE_VOLUMEID_LVM
480 bool "lvm"
481 default n
482 depends on VOLUMEID
483 help
484 TODO
485
486config FEATURE_VOLUMEID_CRAMFS
487 bool "cramfs filesystem"
488 default n
489 depends on VOLUMEID
490 help
491 TODO
492
493config FEATURE_VOLUMEID_HPFS
494 bool "hpfs filesystem"
495 default n
496 depends on VOLUMEID
497 help
498 TODO
499
500config FEATURE_VOLUMEID_ROMFS
501 bool "romfs filesystem"
502 default n
503 depends on VOLUMEID
504 help
505 TODO
506
507config FEATURE_VOLUMEID_SYSV
508 bool "sysv filesystem"
509 default n
510 depends on VOLUMEID
511 help
512 TODO
513
514config FEATURE_VOLUMEID_MINIX
515 bool "minix filesystem"
516 default n
517 depends on VOLUMEID
518 help
519 TODO
520
521config FEATURE_VOLUMEID_MAC
522 bool "mac filesystem"
523 default n
524 depends on VOLUMEID
525 help
526 TODO
527
528config FEATURE_VOLUMEID_MSDOS
529 bool "msdos filesystem"
530 default n
531 depends on VOLUMEID
532 help
533 TODO
534
535config FEATURE_VOLUMEID_OCFS2
536 bool "ocfs2 filesystem"
537 default n
538 depends on VOLUMEID
539 help
540 TODO
541
542config FEATURE_VOLUMEID_HIGHPOINTRAID
543 bool "highpoint raid"
544 default n
545 depends on VOLUMEID
546 help
547 TODO
548
549config FEATURE_VOLUMEID_ISWRAID
550 bool "intel raid"
551 default n
552 depends on VOLUMEID
553 help
554 TODO
555
556config FEATURE_VOLUMEID_LSIRAID
557 bool "lsi raid"
558 default n
559 depends on VOLUMEID
560 help
561 TODO
562
563config FEATURE_VOLUMEID_VIARAID
564 bool "via raid"
565 default n
566 depends on VOLUMEID
567 help
568 TODO
569
570config FEATURE_VOLUMEID_SILICONRAID
571 bool "silicon raid"
572 default n
573 depends on VOLUMEID
574 help
575 TODO
576
577config FEATURE_VOLUMEID_NVIDIARAID
578 bool "nvidia raid"
579 default n
580 depends on VOLUMEID
581 help
582 TODO
583
584config FEATURE_VOLUMEID_PROMISERAID
585 bool "promise raid"
586 default n
587 depends on VOLUMEID
588 help
589 TODO
590
591config FEATURE_VOLUMEID_LINUXRAID
592 bool "linuxraid"
593 default n
594 depends on VOLUMEID
595 help
596 TODO
597
378config MOUNT 598config MOUNT
379 bool "mount" 599 bool "mount"
380 default n 600 default n
@@ -414,6 +634,15 @@ config FEATURE_MOUNT_HELPERS
414 "sometype [-o opts] fs /mnt" if simple mount syscall fails. 634 "sometype [-o opts] fs /mnt" if simple mount syscall fails.
415 The idea is to use such virtual filesystems in /etc/fstab. 635 The idea is to use such virtual filesystems in /etc/fstab.
416 636
637config FEATURE_MOUNT_LABEL
638 bool " Support specifiying devices by label or UUID"
639 default n
640 depends on MOUNT
641 select FINDFS
642 help
643 This allows for specifying a device by label or uuid, rather than by
644 name. This feature utilizes the same functionality as findfs.
645
417config FEATURE_MOUNT_NFS 646config FEATURE_MOUNT_NFS
418 bool "Support mounting NFS file systems" 647 bool "Support mounting NFS file systems"
419 default n 648 default n
diff --git a/util-linux/Kbuild b/util-linux/Kbuild
index 4a18ff21f..c71186e86 100644
--- a/util-linux/Kbuild
+++ b/util-linux/Kbuild
@@ -10,6 +10,7 @@ lib-$(CONFIG_FBSET) +=fbset.o
10lib-$(CONFIG_FDFLUSH) +=freeramdisk.o 10lib-$(CONFIG_FDFLUSH) +=freeramdisk.o
11lib-$(CONFIG_FDFORMAT) +=fdformat.o 11lib-$(CONFIG_FDFORMAT) +=fdformat.o
12lib-$(CONFIG_FDISK) +=fdisk.o 12lib-$(CONFIG_FDISK) +=fdisk.o
13lib-$(CONFIG_FINDFS) +=findfs.o
13lib-$(CONFIG_FREERAMDISK) +=freeramdisk.o 14lib-$(CONFIG_FREERAMDISK) +=freeramdisk.o
14lib-$(CONFIG_FSCK_MINIX) +=fsck_minix.o 15lib-$(CONFIG_FSCK_MINIX) +=fsck_minix.o
15lib-$(CONFIG_GETOPT) +=getopt.o 16lib-$(CONFIG_GETOPT) +=getopt.o
diff --git a/util-linux/fdisk_sgi.c b/util-linux/fdisk_sgi.c
index 7826bb7cc..1fce0c1c7 100644
--- a/util-linux/fdisk_sgi.c
+++ b/util-linux/fdisk_sgi.c
@@ -781,7 +781,7 @@ create_sgilabel(void)
781 781
782 printf(msg_building_new_label, "SGI disklabel"); 782 printf(msg_building_new_label, "SGI disklabel");
783 783
784 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN); 784 sgi_other_endian = BB_LITTLE_ENDIAN;
785 res = ioctl(fd, BLKGETSIZE, &longsectors); 785 res = ioctl(fd, BLKGETSIZE, &longsectors);
786 if (!ioctl(fd, HDIO_GETGEO, &geometry)) { 786 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
787 g_heads = geometry.heads; 787 g_heads = geometry.heads;
diff --git a/util-linux/findfs.c b/util-linux/findfs.c
new file mode 100644
index 000000000..4f036425c
--- /dev/null
+++ b/util-linux/findfs.c
@@ -0,0 +1,38 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Support functions for mounting devices by label/uuid
4 *
5 * Copyright (C) 2006 by Jason Schoon <floydpink@gmail.com>
6 * Some portions cribbed from e2fsprogs, util-linux, dosfstools
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */
10
11#include "libbb.h"
12#include "volume_id.h"
13
14int findfs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
15int findfs_main(int argc, char **argv)
16{
17 char *tmp = NULL;
18
19 if (argc != 2)
20 bb_show_usage();
21
22 if (!strncmp(argv[1], "LABEL=", 6))
23 tmp = get_devname_from_label(argv[1] + 6);
24 else if (!strncmp(argv[1], "UUID=", 5))
25 tmp = get_devname_from_uuid(argv[1] + 5);
26 else if (!strncmp(argv[1], "/dev/", 5)) {
27 /* Just pass a device name right through. This might aid in some scripts
28 being able to call this unconditionally */
29 tmp = argv[1];
30 } else
31 bb_show_usage();
32
33 if (tmp) {
34 puts(tmp);
35 return 0;
36 }
37 return 1;
38}
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 8b3230935..b19c3a3ef 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -19,10 +19,13 @@
19*/ 19*/
20 20
21#include <mntent.h> 21#include <mntent.h>
22#include "libbb.h"
23#include <syslog.h> 22#include <syslog.h>
23#include "libbb.h"
24 24
25/* Needed for nfs support only... */ 25/* For FEATURE_MOUNT_LABEL only */
26#include "volume_id.h"
27
28/* Needed for nfs support only */
26#include <sys/utsname.h> 29#include <sys/utsname.h>
27#undef TRUE 30#undef TRUE
28#undef FALSE 31#undef FALSE
@@ -245,6 +248,22 @@ static int verbose_mount(const char *source, const char *target,
245#define verbose_mount(...) mount(__VA_ARGS__) 248#define verbose_mount(...) mount(__VA_ARGS__)
246#endif 249#endif
247 250
251static int resolve_mount_spec(char **fsname)
252{
253 char *tmp = NULL;
254
255 if (!strncmp(*fsname, "UUID=", 5))
256 tmp = get_devname_from_uuid(*fsname + 5);
257 else if (!strncmp(*fsname, "LABEL=", 6))
258 tmp = get_devname_from_label(*fsname + 6);
259
260 if (tmp) {
261 *fsname = tmp;
262 return 1;
263 }
264 return 0;
265}
266
248/* Append mount options to string */ 267/* Append mount options to string */
249static void append_mount_options(char **oldopts, const char *newopts) 268static void append_mount_options(char **oldopts, const char *newopts)
250{ 269{
@@ -1781,6 +1800,9 @@ int mount_main(int argc, char **argv)
1781 mtpair->mnt_dir = argv[1]; 1800 mtpair->mnt_dir = argv[1];
1782 mtpair->mnt_type = fstype; 1801 mtpair->mnt_type = fstype;
1783 mtpair->mnt_opts = cmdopts; 1802 mtpair->mnt_opts = cmdopts;
1803 if (ENABLE_FEATURE_MOUNT_LABEL) {
1804 resolve_mount_spec(&mtpair->mnt_fsname);
1805 }
1784 rc = singlemount(mtpair, 0); 1806 rc = singlemount(mtpair, 0);
1785 goto clean_up; 1807 goto clean_up;
1786 } 1808 }
@@ -1842,6 +1864,9 @@ int mount_main(int argc, char **argv)
1842 1864
1843 mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); 1865 mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
1844 append_mount_options(&(mtcur->mnt_opts), cmdopts); 1866 append_mount_options(&(mtcur->mnt_opts), cmdopts);
1867 if (ENABLE_FEATURE_MOUNT_LABEL) {
1868 resolve_mount_spec(&mtpair->mnt_fsname);
1869 }
1845 rc = singlemount(mtcur, 0); 1870 rc = singlemount(mtcur, 0);
1846 free(mtcur->mnt_opts); 1871 free(mtcur->mnt_opts);
1847 } 1872 }
@@ -1884,6 +1909,9 @@ int mount_main(int argc, char **argv)
1884 bb_error_msg_and_die(must_be_root); 1909 bb_error_msg_and_die(must_be_root);
1885 1910
1886 // Mount this thing. 1911 // Mount this thing.
1912 if (ENABLE_FEATURE_MOUNT_LABEL) {
1913 resolve_mount_spec(&mtpair->mnt_fsname);
1914 }
1887 1915
1888 // NFS mounts want this to be xrealloc-able 1916 // NFS mounts want this to be xrealloc-able
1889 mtcur->mnt_opts = xstrdup(mtcur->mnt_opts); 1917 mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
diff --git a/util-linux/volume_id/Kbuild b/util-linux/volume_id/Kbuild
new file mode 100644
index 000000000..c2eb01564
--- /dev/null
+++ b/util-linux/volume_id/Kbuild
@@ -0,0 +1,41 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
4#
5# Licensed under the GPL v2, see the file LICENSE in this tarball.
6
7lib-y:=
8
9lib-$(CONFIG_FINDFS) += get_devname.o
10lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o
11
12lib-$(CONFIG_VOLUMEID) += volume_id.o util.o
13lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o
14lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o
15lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o
16lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o
17lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o
18lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o
19lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o
20lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o
21lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o
22lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o
23lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o
24lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o
25lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o
26lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o
27lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o
28lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o
29lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o
30lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o
31lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o
32lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o
33lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o
34lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o
35lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o
36lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o
37lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o
38lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o
39lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o
40lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o
41lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o
diff --git a/util-linux/volume_id/cramfs.c b/util-linux/volume_id/cramfs.c
new file mode 100644
index 000000000..fd6e87522
--- /dev/null
+++ b/util-linux/volume_id/cramfs.c
@@ -0,0 +1,58 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct cramfs_super {
24 uint8_t magic[4];
25 uint32_t size;
26 uint32_t flags;
27 uint32_t future;
28 uint8_t signature[16];
29 struct cramfs_info {
30 uint32_t crc;
31 uint32_t edition;
32 uint32_t blocks;
33 uint32_t files;
34 } __attribute__((__packed__)) info;
35 uint8_t name[16];
36} __attribute__((__packed__));
37
38int volume_id_probe_cramfs(struct volume_id *id, uint64_t off)
39{
40 struct cramfs_super *cs;
41
42 dbg("probing at offset 0x%llx", (unsigned long long) off);
43
44 cs = volume_id_get_buffer(id, off, 0x200);
45 if (cs == NULL)
46 return -1;
47
48 if (memcmp(cs->magic, "\x45\x3d\xcd\x28", 4) == 0) {
49 volume_id_set_label_raw(id, cs->name, 16);
50 volume_id_set_label_string(id, cs->name, 16);
51
52 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
53 id->type = "cramfs";
54 return 0;
55 }
56
57 return -1;
58}
diff --git a/util-linux/volume_id/ext.c b/util-linux/volume_id/ext.c
new file mode 100644
index 000000000..3c07f5301
--- /dev/null
+++ b/util-linux/volume_id/ext.c
@@ -0,0 +1,71 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct ext2_super_block {
24 uint32_t inodes_count;
25 uint32_t blocks_count;
26 uint32_t r_blocks_count;
27 uint32_t free_blocks_count;
28 uint32_t free_inodes_count;
29 uint32_t first_data_block;
30 uint32_t log_block_size;
31 uint32_t dummy3[7];
32 uint8_t magic[2];
33 uint16_t state;
34 uint32_t dummy5[8];
35 uint32_t feature_compat;
36 uint32_t feature_incompat;
37 uint32_t feature_ro_compat;
38 uint8_t uuid[16];
39 uint8_t volume_name[16];
40} __attribute__((__packed__));
41
42#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
43#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
44#define EXT_SUPERBLOCK_OFFSET 0x400
45
46int volume_id_probe_ext(struct volume_id *id, uint64_t off)
47{
48 struct ext2_super_block *es;
49
50 dbg("probing at offset 0x%llx", (unsigned long long) off);
51
52 es = volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
53 if (es == NULL)
54 return -1;
55
56 if (es->magic[0] != 0123 ||
57 es->magic[1] != 0357)
58 return -1;
59
60 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
61 volume_id_set_label_raw(id, es->volume_name, 16);
62 volume_id_set_label_string(id, es->volume_name, 16);
63 volume_id_set_uuid(id, es->uuid, UUID_DCE);
64
65 if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0)
66 id->type = "ext3";
67 else
68 id->type = "ext2";
69
70 return 0;
71}
diff --git a/util-linux/volume_id/fat.c b/util-linux/volume_id/fat.c
new file mode 100644
index 000000000..4c2a91749
--- /dev/null
+++ b/util-linux/volume_id/fat.c
@@ -0,0 +1,333 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23#define FAT12_MAX 0xff5
24#define FAT16_MAX 0xfff5
25#define FAT_ATTR_VOLUME_ID 0x08
26#define FAT_ATTR_DIR 0x10
27#define FAT_ATTR_LONG_NAME 0x0f
28#define FAT_ATTR_MASK 0x3f
29#define FAT_ENTRY_FREE 0xe5
30
31struct vfat_super_block {
32 uint8_t boot_jump[3];
33 uint8_t sysid[8];
34 uint16_t sector_size;
35 uint8_t sectors_per_cluster;
36 uint16_t reserved;
37 uint8_t fats;
38 uint16_t dir_entries;
39 uint16_t sectors;
40 uint8_t media;
41 uint16_t fat_length;
42 uint16_t secs_track;
43 uint16_t heads;
44 uint32_t hidden;
45 uint32_t total_sect;
46 union {
47 struct fat_super_block {
48 uint8_t unknown[3];
49 uint8_t serno[4];
50 uint8_t label[11];
51 uint8_t magic[8];
52 uint8_t dummy2[192];
53 uint8_t pmagic[2];
54 } __attribute__((__packed__)) fat;
55 struct fat32_super_block {
56 uint32_t fat32_length;
57 uint16_t flags;
58 uint8_t version[2];
59 uint32_t root_cluster;
60 uint16_t insfo_sector;
61 uint16_t backup_boot;
62 uint16_t reserved2[6];
63 uint8_t unknown[3];
64 uint8_t serno[4];
65 uint8_t label[11];
66 uint8_t magic[8];
67 uint8_t dummy2[164];
68 uint8_t pmagic[2];
69 } __attribute__((__packed__)) fat32;
70 } __attribute__((__packed__)) type;
71} __attribute__((__packed__));
72
73struct vfat_dir_entry {
74 uint8_t name[11];
75 uint8_t attr;
76 uint16_t time_creat;
77 uint16_t date_creat;
78 uint16_t time_acc;
79 uint16_t date_acc;
80 uint16_t cluster_high;
81 uint16_t time_write;
82 uint16_t date_write;
83 uint16_t cluster_low;
84 uint32_t size;
85} __attribute__((__packed__));
86
87static uint8_t *get_attr_volume_id(struct vfat_dir_entry *dir, unsigned count)
88{
89 unsigned i;
90
91 for (i = 0; i < count; i++) {
92 /* end marker */
93 if (dir[i].name[0] == 0x00) {
94 dbg("end of dir");
95 break;
96 }
97
98 /* empty entry */
99 if (dir[i].name[0] == FAT_ENTRY_FREE)
100 continue;
101
102 /* long name */
103 if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
104 continue;
105
106 if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
107 /* labels do not have file data */
108 if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0)
109 continue;
110
111 dbg("found ATTR_VOLUME_ID id in root dir");
112 return dir[i].name;
113 }
114
115 dbg("skip dir entry");
116 }
117
118 return NULL;
119}
120
121int volume_id_probe_vfat(struct volume_id *id, uint64_t off)
122{
123 struct vfat_super_block *vs;
124 struct vfat_dir_entry *dir;
125 uint16_t sector_size;
126 uint16_t dir_entries;
127 uint32_t sect_count;
128 uint16_t reserved;
129 uint32_t fat_size;
130 uint32_t root_cluster;
131 uint32_t dir_size;
132 uint32_t cluster_count;
133 uint32_t fat_length;
134 uint64_t root_start;
135 uint32_t start_data_sect;
136 uint16_t root_dir_entries;
137 uint8_t *buf;
138 uint32_t buf_size;
139 uint8_t *label = NULL;
140 uint32_t next;
141 int maxloop;
142
143 dbg("probing at offset 0x%llx", (unsigned long long) off);
144
145 vs = volume_id_get_buffer(id, off, 0x200);
146 if (vs == NULL)
147 return -1;
148
149 /* believe only that's fat, don't trust the version
150 * the cluster_count will tell us
151 */
152 if (memcmp(vs->sysid, "NTFS", 4) == 0)
153 return -1;
154
155 if (memcmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
156 goto valid;
157
158 if (memcmp(vs->type.fat32.magic, "FAT32 ", 8) == 0)
159 goto valid;
160
161 if (memcmp(vs->type.fat.magic, "FAT16 ", 8) == 0)
162 goto valid;
163
164 if (memcmp(vs->type.fat.magic, "MSDOS", 5) == 0)
165 goto valid;
166
167 if (memcmp(vs->type.fat.magic, "FAT12 ", 8) == 0)
168 goto valid;
169
170 /*
171 * There are old floppies out there without a magic, so we check
172 * for well known values and guess if it's a fat volume
173 */
174
175 /* boot jump address check */
176 if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
177 vs->boot_jump[0] != 0xe9)
178 return -1;
179
180 /* heads check */
181 if (vs->heads == 0)
182 return -1;
183
184 /* cluster size check*/
185 if (vs->sectors_per_cluster == 0 ||
186 (vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
187 return -1;
188
189 /* media check */
190 if (vs->media < 0xf8 && vs->media != 0xf0)
191 return -1;
192
193 /* fat count*/
194 if (vs->fats != 2)
195 return -1;
196
197 valid:
198 /* sector size check */
199 sector_size = le16_to_cpu(vs->sector_size);
200 if (sector_size != 0x200 && sector_size != 0x400 &&
201 sector_size != 0x800 && sector_size != 0x1000)
202 return -1;
203
204 dbg("sector_size 0x%x", sector_size);
205 dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
206
207 dir_entries = le16_to_cpu(vs->dir_entries);
208 reserved = le16_to_cpu(vs->reserved);
209 dbg("reserved 0x%x", reserved);
210
211 sect_count = le16_to_cpu(vs->sectors);
212 if (sect_count == 0)
213 sect_count = le32_to_cpu(vs->total_sect);
214 dbg("sect_count 0x%x", sect_count);
215
216 fat_length = le16_to_cpu(vs->fat_length);
217 if (fat_length == 0)
218 fat_length = le32_to_cpu(vs->type.fat32.fat32_length);
219 dbg("fat_length 0x%x", fat_length);
220
221 fat_size = fat_length * vs->fats;
222 dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
223 (sector_size-1)) / sector_size;
224 dbg("dir_size 0x%x", dir_size);
225
226 cluster_count = sect_count - (reserved + fat_size + dir_size);
227 cluster_count /= vs->sectors_per_cluster;
228 dbg("cluster_count 0x%x", cluster_count);
229
230 if (cluster_count < FAT12_MAX) {
231 strcpy(id->type_version, "FAT12");
232 } else if (cluster_count < FAT16_MAX) {
233 strcpy(id->type_version, "FAT16");
234 } else {
235 strcpy(id->type_version, "FAT32");
236 goto fat32;
237 }
238
239 /* the label may be an attribute in the root directory */
240 root_start = (reserved + fat_size) * sector_size;
241 dbg("root dir start 0x%llx", (unsigned long long) root_start);
242 root_dir_entries = le16_to_cpu(vs->dir_entries);
243 dbg("expected entries 0x%x", root_dir_entries);
244
245 buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
246 buf = volume_id_get_buffer(id, off + root_start, buf_size);
247 if (buf == NULL)
248 goto found;
249
250 dir = (struct vfat_dir_entry*) buf;
251
252 label = get_attr_volume_id(dir, root_dir_entries);
253
254 vs = volume_id_get_buffer(id, off, 0x200);
255 if (vs == NULL)
256 return -1;
257
258 if (label != NULL && memcmp(label, "NO NAME ", 11) != 0) {
259 volume_id_set_label_raw(id, label, 11);
260 volume_id_set_label_string(id, label, 11);
261 } else if (memcmp(vs->type.fat.label, "NO NAME ", 11) != 0) {
262 volume_id_set_label_raw(id, vs->type.fat.label, 11);
263 volume_id_set_label_string(id, vs->type.fat.label, 11);
264 }
265 volume_id_set_uuid(id, vs->type.fat.serno, UUID_DOS);
266 goto found;
267
268 fat32:
269 /* FAT32 root dir is a cluster chain like any other directory */
270 buf_size = vs->sectors_per_cluster * sector_size;
271 root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
272 dbg("root dir cluster %u", root_cluster);
273 start_data_sect = reserved + fat_size;
274
275 next = root_cluster;
276 maxloop = 100;
277 while (--maxloop) {
278 uint32_t next_sect_off;
279 uint64_t next_off;
280 uint64_t fat_entry_off;
281 int count;
282
283 dbg("next cluster %u", next);
284 next_sect_off = (next - 2) * vs->sectors_per_cluster;
285 next_off = (start_data_sect + next_sect_off) * sector_size;
286 dbg("cluster offset 0x%llx", (unsigned long long) next_off);
287
288 /* get cluster */
289 buf = volume_id_get_buffer(id, off + next_off, buf_size);
290 if (buf == NULL)
291 goto found;
292
293 dir = (struct vfat_dir_entry*) buf;
294 count = buf_size / sizeof(struct vfat_dir_entry);
295 dbg("expected entries 0x%x", count);
296
297 label = get_attr_volume_id(dir, count);
298 if (label)
299 break;
300
301 /* get FAT entry */
302 fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t));
303 buf = volume_id_get_buffer(id, off + fat_entry_off, buf_size);
304 if (buf == NULL)
305 goto found;
306
307 /* set next cluster */
308 next = le32_to_cpu(*((uint32_t *) buf) & 0x0fffffff);
309 if (next == 0)
310 break;
311 }
312 if (maxloop == 0)
313 dbg("reached maximum follow count of root cluster chain, give up");
314
315 vs = volume_id_get_buffer(id, off, 0x200);
316 if (vs == NULL)
317 return -1;
318
319 if (label != NULL && memcmp(label, "NO NAME ", 11) != 0) {
320 volume_id_set_label_raw(id, label, 11);
321 volume_id_set_label_string(id, label, 11);
322 } else if (memcmp(vs->type.fat32.label, "NO NAME ", 11) != 0) {
323 volume_id_set_label_raw(id, vs->type.fat32.label, 11);
324 volume_id_set_label_string(id, vs->type.fat32.label, 11);
325 }
326 volume_id_set_uuid(id, vs->type.fat32.serno, UUID_DOS);
327
328 found:
329 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
330 id->type = "vfat";
331
332 return 0;
333}
diff --git a/util-linux/volume_id/get_devname.c b/util-linux/volume_id/get_devname.c
new file mode 100644
index 000000000..75060b0d8
--- /dev/null
+++ b/util-linux/volume_id/get_devname.c
@@ -0,0 +1,399 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Support functions for mounting devices by label/uuid
4 *
5 * Copyright (C) 2006 by Jason Schoon <floydpink@gmail.com>
6 * Some portions cribbed from e2fsprogs, util-linux, dosfstools
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */
10
11#include "volume_id_internal.h"
12
13#define BLKGETSIZE64 _IOR(0x12,114,size_t)
14
15#define PROC_PARTITIONS "/proc/partitions"
16#define PROC_CDROMS "/proc/sys/dev/cdrom/info"
17#define DEVLABELDIR "/dev"
18#define SYS_BLOCK "/sys/block"
19
20static struct uuidCache_s {
21 struct uuidCache_s *next;
22 char uuid[16];
23 char *device;
24 char *label;
25 int major, minor;
26} *uuidCache;
27
28/* for now, only ext2, ext3 and xfs are supported */
29static int
30get_label_uuid(const char *device, char **label, char **uuid, int iso_only)
31{
32 int rv = 1;
33 uint64_t size;
34 struct volume_id *vid;
35
36 vid = volume_id_open_node(device);
37
38 if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0) {
39 size = 0;
40 }
41
42#if ENABLE_FEATURE_VOLUMEID_ISO9660
43 if (iso_only ?
44 volume_id_probe_iso9660(vid, 0) != 0 :
45 volume_id_probe_all(vid, 0, size) != 0) {
46 goto ret;
47 }
48#else
49 if (volume_id_probe_all(vid, 0, size) != 0) {
50 goto ret;
51 }
52#endif
53
54 if (vid->label[0] != '\0') {
55 *label = xstrndup(vid->label, sizeof(vid->label));
56 *uuid = xstrndup(vid->uuid, sizeof(vid->uuid));
57 printf("Found label %s on %s (uuid:%s)\n", *label, device, *uuid);
58 rv = 0;
59 }
60 ret:
61 free_volume_id(vid);
62 return rv;
63}
64
65static void
66uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid)
67{
68 struct uuidCache_s *last;
69
70 if (!uuidCache) {
71 last = uuidCache = xzalloc(sizeof(*uuidCache));
72 } else {
73 for (last = uuidCache; last->next; last = last->next)
74 continue;
75 last->next = xzalloc(sizeof(*uuidCache));
76 last = last->next;
77 }
78 /*last->next = NULL; - xzalloc did it*/
79 last->label = label;
80 last->device = device;
81 last->major = major;
82 last->minor = minor;
83 memcpy(last->uuid, uuid, sizeof(last->uuid));
84}
85
86static void
87uuidcache_check_device(const char *device_name, int ma, int mi, int iso_only)
88{
89 char device[110];
90 char *uuid = NULL, *label = NULL;
91 char *ptr;
92 char *deviceDir = NULL;
93 int mustRemove = 0;
94 int mustRemoveDir = 0;
95 int i;
96
97 sprintf(device, "%s/%s", DEVLABELDIR, device_name);
98 if (access(device, F_OK)) {
99 ptr = device;
100 i = 0;
101 while (*ptr)
102 if (*ptr++ == '/')
103 i++;
104 if (i > 2) {
105 deviceDir = alloca(strlen(device) + 1);
106 strcpy(deviceDir, device);
107 ptr = deviceDir + (strlen(device) - 1);
108 while (*ptr != '/')
109 *ptr-- = '\0';
110 if (mkdir(deviceDir, 0644)) {
111 printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);
112 } else {
113 mustRemoveDir = 1;
114 }
115 }
116
117 mknod(device, S_IFBLK | 0600, makedev(ma, mi));
118 mustRemove = 1;
119 }
120 if (!get_label_uuid(device, &label, &uuid, iso_only))
121 uuidcache_addentry(strdup(device), ma, mi,
122 label, uuid);
123
124 if (mustRemove) unlink(device);
125 if (mustRemoveDir) rmdir(deviceDir);
126}
127
128static void
129uuidcache_init_partitions(void)
130{
131 char line[100];
132 int ma, mi;
133 unsigned long long sz;
134 FILE *procpt;
135 int firstPass;
136 int handleOnFirst;
137 char *chptr;
138
139 procpt = xfopen(PROC_PARTITIONS, "r");
140/*
141# cat /proc/partitions
142major minor #blocks name
143
144 8 0 293036184 sda
145 8 1 6835626 sda1
146 8 2 1 sda2
147 8 5 979933 sda5
148 8 6 15623181 sda6
149 8 7 97659103 sda7
150 8 8 171935631 sda8
151*/
152 for (firstPass = 1; firstPass >= 0; firstPass--) {
153 fseek(procpt, 0, SEEK_SET);
154
155 while (fgets(line, sizeof(line), procpt)) {
156 /* The original version of this code used sscanf, but
157 diet's sscanf is quite limited */
158 chptr = line;
159 if (*chptr != ' ') continue;
160 chptr++;
161
162 ma = bb_strtou(chptr, &chptr, 0);
163 if (ma < 0) continue;
164 chptr = skip_whitespace(chptr);
165
166 mi = bb_strtou(chptr, &chptr, 0);
167 if (mi < 0) continue;
168 chptr = skip_whitespace(chptr);
169
170 sz = bb_strtoull(chptr, &chptr, 0);
171 if ((long long)sz == -1LL) continue;
172 chptr = skip_whitespace(chptr);
173
174 /* skip extended partitions (heuristic: size 1) */
175 if (sz == 1)
176 continue;
177
178 *strchrnul(chptr, '\n') = '\0';
179 /* now chptr => device name */
180 if (!chptr[0])
181 continue;
182
183 /* look only at md devices on first pass */
184 handleOnFirst = (chptr[0] == 'm' && chptr[1] == 'd');
185 if (firstPass != handleOnFirst)
186 continue;
187
188 /* heuristic: partition name ends in a digit */
189 if (isdigit(chptr[strlen(chptr) - 1])) {
190 uuidcache_check_device(chptr, ma, mi, 0);
191 }
192 }
193 }
194
195 fclose(procpt);
196}
197
198static int
199dev_get_major_minor(char *device_name, int *major, int *minor)
200{
201 char * dev_path;
202 int fd;
203 char dev[7];
204 char *major_ptr, *minor_ptr;
205
206 dev_path = alloca(strlen(SYS_BLOCK) + strlen(device_name) + 6);
207 sprintf(dev_path, "%s/%s/dev", SYS_BLOCK, device_name);
208
209 fd = open(dev_path, O_RDONLY);
210 if (fd < 0) return 1;
211 full_read(fd, dev, sizeof(dev));
212 close(fd);
213
214 major_ptr = dev;
215 minor_ptr = strchr(dev, ':');
216 if (!minor_ptr) return 1;
217 *minor_ptr++ = '\0';
218
219 *major = strtol(major_ptr, NULL, 10);
220 *minor = strtol(minor_ptr, NULL, 10);
221
222 return 0;
223}
224
225static void
226uuidcache_init_cdroms(void)
227{
228 char line[100];
229 int ma, mi;
230 FILE *proccd;
231
232 proccd = fopen(PROC_CDROMS, "r");
233 if (!proccd) {
234 static smallint warn = 0;
235 if (!warn) {
236 warn = 1;
237 bb_error_msg("mount: could not open %s, so UUID and LABEL "
238 "conversion cannot be done for CD-Roms.",
239 PROC_CDROMS);
240 }
241 return;
242 }
243
244 while (fgets(line, sizeof(line), proccd)) {
245 const char *drive_name_string = "drive name:\t\t";
246 if (!strncmp(line, drive_name_string, strlen(drive_name_string))) {
247 char *device_name;
248 device_name = strtok(line + strlen(drive_name_string), "\t\n");
249 while (device_name) {
250 dev_get_major_minor(device_name, &ma, &mi);
251 uuidcache_check_device(device_name, ma, mi, 1);
252 device_name = strtok(NULL, "\t\n");
253 }
254 break;
255 }
256 }
257
258 fclose(proccd);
259}
260
261static void
262uuidcache_init(void)
263{
264 if (uuidCache)
265 return;
266
267 uuidcache_init_partitions();
268 uuidcache_init_cdroms();
269}
270
271#define UUID 1
272#define VOL 2
273
274#ifdef UNUSED
275static char *
276get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr)
277{
278 struct uuidCache_s *uc;
279
280 uuidcache_init();
281 uc = uuidCache;
282
283 while(uc) {
284 switch (n) {
285 case UUID:
286 if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) {
287 *majorPtr = uc->major;
288 *minorPtr = uc->minor;
289 return uc->device;
290 }
291 break;
292 case VOL:
293 if (!strcmp(t, uc->label)) {
294 *majorPtr = uc->major;
295 *minorPtr = uc->minor;
296 return uc->device;
297 }
298 break;
299 }
300 uc = uc->next;
301 }
302 return NULL;
303}
304
305static unsigned char
306fromhex(char c)
307{
308 if (isdigit(c))
309 return (c - '0');
310 if (islower(c))
311 return (c - 'a' + 10);
312 return (c - 'A' + 10);
313}
314
315static char *
316get_spec_by_uuid(const char *s, int * major, int * minor)
317{
318 unsigned char uuid[16];
319 int i;
320
321 if (strlen(s) != 36 ||
322 s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
323 goto bad_uuid;
324 for (i=0; i<16; i++) {
325 if (*s == '-') s++;
326 if (!isxdigit(s[0]) || !isxdigit(s[1]))
327 goto bad_uuid;
328 uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));
329 s += 2;
330 }
331 return get_spec_by_x(UUID, (char *)uuid, major, minor);
332
333 bad_uuid:
334 fprintf(stderr, _("mount: bad UUID"));
335 return 0;
336}
337
338static char *
339get_spec_by_volume_label(const char *s, int *major, int *minor)
340{
341 return get_spec_by_x(VOL, s, major, minor);
342}
343
344static int display_uuid_cache(void)
345{
346 struct uuidCache_s *u;
347 size_t i;
348
349 uuidcache_init();
350
351 u = uuidCache;
352 while (u) {
353 printf("%s %s ", u->device, u->label);
354 for (i = 0; i < sizeof(u->uuid); i++) {
355 if (i == 4 || i == 6 || i == 8 || i == 10)
356 printf("-");
357 printf("%x", u->uuid[i] & 0xff);
358 }
359 printf("\n");
360 u = u->next;
361 }
362
363 return 0;
364}
365#endif // UNUSED
366
367
368/* Used by mount and findfs */
369
370char *get_devname_from_label(const char *spec)
371{
372 struct uuidCache_s *uc;
373 int spec_len = strlen(spec);
374
375 uuidcache_init();
376 uc = uuidCache;
377 while (uc) {
378 if (uc->label && !strncmp(spec, uc->label, spec_len)) {
379 return xstrdup(uc->device);
380 }
381 uc = uc->next;
382 }
383 return NULL;
384}
385
386char *get_devname_from_uuid(const char *spec)
387{
388 struct uuidCache_s *uc;
389
390 uuidcache_init();
391 uc = uuidCache;
392 while (uc) {
393 if (!memcmp(spec, uc->uuid, sizeof(uc->uuid))) {
394 return xstrdup(uc->device);
395 }
396 uc = uc->next;
397 }
398 return NULL;
399}
diff --git a/util-linux/volume_id/hfs.c b/util-linux/volume_id/hfs.c
new file mode 100644
index 000000000..71a3df0b8
--- /dev/null
+++ b/util-linux/volume_id/hfs.c
@@ -0,0 +1,292 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct hfs_finder_info{
24 uint32_t boot_folder;
25 uint32_t start_app;
26 uint32_t open_folder;
27 uint32_t os9_folder;
28 uint32_t reserved;
29 uint32_t osx_folder;
30 uint8_t id[8];
31} __attribute__((__packed__));
32
33struct hfs_mdb {
34 uint8_t signature[2];
35 uint32_t cr_date;
36 uint32_t ls_Mod;
37 uint16_t atrb;
38 uint16_t nm_fls;
39 uint16_t vbm_st;
40 uint16_t alloc_ptr;
41 uint16_t nm_al_blks;
42 uint32_t al_blk_size;
43 uint32_t clp_size;
44 uint16_t al_bl_st;
45 uint32_t nxt_cnid;
46 uint16_t free_bks;
47 uint8_t label_len;
48 uint8_t label[27];
49 uint32_t vol_bkup;
50 uint16_t vol_seq_num;
51 uint32_t wr_cnt;
52 uint32_t xt_clump_size;
53 uint32_t ct_clump_size;
54 uint16_t num_root_dirs;
55 uint32_t file_count;
56 uint32_t dir_count;
57 struct hfs_finder_info finder_info;
58 uint8_t embed_sig[2];
59 uint16_t embed_startblock;
60 uint16_t embed_blockcount;
61} __attribute__((__packed__));
62
63struct hfsplus_bnode_descriptor {
64 uint32_t next;
65 uint32_t prev;
66 uint8_t type;
67 uint8_t height;
68 uint16_t num_recs;
69 uint16_t reserved;
70} __attribute__((__packed__));
71
72struct hfsplus_bheader_record {
73 uint16_t depth;
74 uint32_t root;
75 uint32_t leaf_count;
76 uint32_t leaf_head;
77 uint32_t leaf_tail;
78 uint16_t node_size;
79} __attribute__((__packed__));
80
81struct hfsplus_catalog_key {
82 uint16_t key_len;
83 uint32_t parent_id;
84 uint16_t unicode_len;
85 uint8_t unicode[255 * 2];
86} __attribute__((__packed__));
87
88struct hfsplus_extent {
89 uint32_t start_block;
90 uint32_t block_count;
91} __attribute__((__packed__));
92
93#define HFSPLUS_EXTENT_COUNT 8
94struct hfsplus_fork {
95 uint64_t total_size;
96 uint32_t clump_size;
97 uint32_t total_blocks;
98 struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
99} __attribute__((__packed__));
100
101struct hfsplus_vol_header {
102 uint8_t signature[2];
103 uint16_t version;
104 uint32_t attributes;
105 uint32_t last_mount_vers;
106 uint32_t reserved;
107 uint32_t create_date;
108 uint32_t modify_date;
109 uint32_t backup_date;
110 uint32_t checked_date;
111 uint32_t file_count;
112 uint32_t folder_count;
113 uint32_t blocksize;
114 uint32_t total_blocks;
115 uint32_t free_blocks;
116 uint32_t next_alloc;
117 uint32_t rsrc_clump_sz;
118 uint32_t data_clump_sz;
119 uint32_t next_cnid;
120 uint32_t write_count;
121 uint64_t encodings_bmp;
122 struct hfs_finder_info finder_info;
123 struct hfsplus_fork alloc_file;
124 struct hfsplus_fork ext_file;
125 struct hfsplus_fork cat_file;
126 struct hfsplus_fork attr_file;
127 struct hfsplus_fork start_file;
128} __attribute__((__packed__));
129
130#define HFS_SUPERBLOCK_OFFSET 0x400
131#define HFS_NODE_LEAF 0xff
132#define HFSPLUS_POR_CNID 1
133
134int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off)
135{
136 unsigned blocksize;
137 unsigned cat_block;
138 unsigned ext_block_start;
139 unsigned ext_block_count;
140 int ext;
141 unsigned leaf_node_head;
142 unsigned leaf_node_count;
143 unsigned leaf_node_size;
144 unsigned leaf_block;
145 uint64_t leaf_off;
146 unsigned alloc_block_size;
147 unsigned alloc_first_block;
148 unsigned embed_first_block;
149 unsigned record_count;
150 struct hfsplus_vol_header *hfsplus;
151 struct hfsplus_bnode_descriptor *descr;
152 struct hfsplus_bheader_record *bnode;
153 struct hfsplus_catalog_key *key;
154 unsigned label_len;
155 struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
156 struct hfs_mdb *hfs;
157 const uint8_t *buf;
158
159 dbg("probing at offset 0x%llx", (unsigned long long) off);
160
161 buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
162 if (buf == NULL)
163 return -1;
164
165 hfs = (struct hfs_mdb *) buf;
166 if (hfs->signature[0] != 'B' || hfs->signature[1] != 'D')
167 goto checkplus;
168
169 /* it may be just a hfs wrapper for hfs+ */
170 if (memcmp(hfs->embed_sig, "H+", 2) == 0) {
171 alloc_block_size = be32_to_cpu(hfs->al_blk_size);
172 dbg("alloc_block_size 0x%x", alloc_block_size);
173
174 alloc_first_block = be16_to_cpu(hfs->al_bl_st);
175 dbg("alloc_first_block 0x%x", alloc_first_block);
176
177 embed_first_block = be16_to_cpu(hfs->embed_startblock);
178 dbg("embed_first_block 0x%x", embed_first_block);
179
180 off += (alloc_first_block * 512) +
181 (embed_first_block * alloc_block_size);
182 dbg("hfs wrapped hfs+ found at offset 0x%llx", (unsigned long long) off);
183
184 buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
185 if (buf == NULL)
186 return -1;
187 goto checkplus;
188 }
189
190 if (hfs->label_len > 0 && hfs->label_len < 28) {
191 volume_id_set_label_raw(id, hfs->label, hfs->label_len);
192 volume_id_set_label_string(id, hfs->label, hfs->label_len) ;
193 }
194
195 volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS);
196
197 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
198 id->type = "hfs";
199
200 return 0;
201
202 checkplus:
203 hfsplus = (struct hfsplus_vol_header *) buf;
204 if (hfs->signature[0] == 'H')
205 if (hfs->signature[1] == '+' || hfs->signature[1] == 'X')
206 goto hfsplus;
207 return -1;
208
209 hfsplus:
210 volume_id_set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
211
212 blocksize = be32_to_cpu(hfsplus->blocksize);
213 dbg("blocksize %u", blocksize);
214
215 memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
216 cat_block = be32_to_cpu(extents[0].start_block);
217 dbg("catalog start block 0x%x", cat_block);
218
219 buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000);
220 if (buf == NULL)
221 goto found;
222
223 bnode = (struct hfsplus_bheader_record *)
224 &buf[sizeof(struct hfsplus_bnode_descriptor)];
225
226 leaf_node_head = be32_to_cpu(bnode->leaf_head);
227 dbg("catalog leaf node 0x%x", leaf_node_head);
228
229 leaf_node_size = be16_to_cpu(bnode->node_size);
230 dbg("leaf node size 0x%x", leaf_node_size);
231
232 leaf_node_count = be32_to_cpu(bnode->leaf_count);
233 dbg("leaf node count 0x%x", leaf_node_count);
234 if (leaf_node_count == 0)
235 goto found;
236
237 leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
238
239 /* get physical location */
240 for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
241 ext_block_start = be32_to_cpu(extents[ext].start_block);
242 ext_block_count = be32_to_cpu(extents[ext].block_count);
243 dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
244
245 if (ext_block_count == 0)
246 goto found;
247
248 /* this is our extent */
249 if (leaf_block < ext_block_count)
250 break;
251
252 leaf_block -= ext_block_count;
253 }
254 if (ext == HFSPLUS_EXTENT_COUNT)
255 goto found;
256 dbg("found block in extent %i", ext);
257
258 leaf_off = (ext_block_start + leaf_block) * blocksize;
259
260 buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size);
261 if (buf == NULL)
262 goto found;
263
264 descr = (struct hfsplus_bnode_descriptor *) buf;
265 dbg("descriptor type 0x%x", descr->type);
266
267 record_count = be16_to_cpu(descr->num_recs);
268 dbg("number of records %u", record_count);
269 if (record_count == 0)
270 goto found;
271
272 if (descr->type != HFS_NODE_LEAF)
273 goto found;
274
275 key = (struct hfsplus_catalog_key *)
276 &buf[sizeof(struct hfsplus_bnode_descriptor)];
277
278 dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
279 if (key->parent_id != cpu_to_be32(HFSPLUS_POR_CNID))
280 goto found;
281
282 label_len = be16_to_cpu(key->unicode_len) * 2;
283 dbg("label unicode16 len %i", label_len);
284 volume_id_set_label_raw(id, key->unicode, label_len);
285 volume_id_set_label_unicode16(id, key->unicode, BE, label_len);
286
287 found:
288 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
289 id->type = "hfsplus";
290
291 return 0;
292}
diff --git a/util-linux/volume_id/highpoint.c b/util-linux/volume_id/highpoint.c
new file mode 100644
index 000000000..de31a2a26
--- /dev/null
+++ b/util-linux/volume_id/highpoint.c
@@ -0,0 +1,86 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct hpt37x_meta {
24 uint8_t filler1[32];
25 uint32_t magic;
26} __attribute__((packed));
27
28struct hpt45x_meta {
29 uint32_t magic;
30} __attribute__((packed));
31
32#define HPT37X_CONFIG_OFF 0x1200
33#define HPT37X_MAGIC_OK 0x5a7816f0
34#define HPT37X_MAGIC_BAD 0x5a7816fd
35
36#define HPT45X_MAGIC_OK 0x5a7816f3
37#define HPT45X_MAGIC_BAD 0x5a7816fd
38
39
40int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off)
41{
42 struct hpt37x_meta *hpt;
43 uint32_t magic;
44
45 dbg("probing at offset 0x%llx", (unsigned long long) off);
46
47 hpt = volume_id_get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200);
48 if (hpt == NULL)
49 return -1;
50
51 magic = hpt->magic;
52 if (magic != cpu_to_le32(HPT37X_MAGIC_OK) && magic != cpu_to_le32(HPT37X_MAGIC_BAD))
53 return -1;
54
55 volume_id_set_usage(id, VOLUME_ID_RAID);
56 id->type = "highpoint_raid_member";
57
58 return 0;
59}
60
61int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size)
62{
63 struct hpt45x_meta *hpt;
64 uint64_t meta_off;
65 uint32_t magic;
66
67 dbg("probing at offset 0x%llx, size 0x%llx",
68 (unsigned long long) off, (unsigned long long) size);
69
70 if (size < 0x10000)
71 return -1;
72
73 meta_off = ((size / 0x200)-11) * 0x200;
74 hpt = volume_id_get_buffer(id, off + meta_off, 0x200);
75 if (hpt == NULL)
76 return -1;
77
78 magic = hpt->magic;
79 if (magic != cpu_to_le32(HPT45X_MAGIC_OK) && magic != cpu_to_le32(HPT45X_MAGIC_BAD))
80 return -1;
81
82 volume_id_set_usage(id, VOLUME_ID_RAID);
83 id->type = "highpoint_raid_member";
84
85 return 0;
86}
diff --git a/util-linux/volume_id/hpfs.c b/util-linux/volume_id/hpfs.c
new file mode 100644
index 000000000..b43fb79b5
--- /dev/null
+++ b/util-linux/volume_id/hpfs.c
@@ -0,0 +1,50 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct hpfs_super
24{
25 uint8_t magic[4];
26 uint8_t version;
27} __attribute__((__packed__));
28
29#define HPFS_SUPERBLOCK_OFFSET 0x2000
30
31int volume_id_probe_hpfs(struct volume_id *id, uint64_t off)
32{
33 struct hpfs_super *hs;
34
35 dbg("probing at offset 0x%llx", (unsigned long long) off);
36
37 hs = volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x200);
38 if (hs == NULL)
39 return -1;
40
41 if (memcmp(hs->magic, "\x49\xe8\x95\xf9", 4) == 0) {
42 sprintf(id->type_version, "%u", hs->version);
43
44 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
45 id->type = "hpfs";
46 return 0;
47 }
48
49 return -1;
50}
diff --git a/util-linux/volume_id/iso9660.c b/util-linux/volume_id/iso9660.c
new file mode 100644
index 000000000..fa9227746
--- /dev/null
+++ b/util-linux/volume_id/iso9660.c
@@ -0,0 +1,118 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23#define ISO_SUPERBLOCK_OFFSET 0x8000
24#define ISO_SECTOR_SIZE 0x800
25#define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
26#define ISO_VD_PRIMARY 0x1
27#define ISO_VD_SUPPLEMENTARY 0x2
28#define ISO_VD_END 0xff
29#define ISO_VD_MAX 16
30
31struct iso_volume_descriptor {
32 uint8_t vd_type;
33 uint8_t vd_id[5];
34 uint8_t vd_version;
35 uint8_t flags;
36 uint8_t system_id[32];
37 uint8_t volume_id[32];
38 uint8_t unused[8];
39 uint8_t space_size[8];
40 uint8_t escape_sequences[8];
41} __attribute__((__packed__));
42
43struct high_sierra_volume_descriptor {
44 uint8_t foo[8];
45 uint8_t type;
46 uint8_t id[4];
47 uint8_t version;
48} __attribute__((__packed__));
49
50int volume_id_probe_iso9660(struct volume_id *id, uint64_t off)
51{
52 uint8_t *buf;
53 struct iso_volume_descriptor *is;
54 struct high_sierra_volume_descriptor *hs;
55
56 dbg("probing at offset 0x%llx", (unsigned long long) off);
57
58 buf = volume_id_get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
59 if (buf == NULL)
60 return -1;
61
62 is = (struct iso_volume_descriptor *) buf;
63
64 if (memcmp(is->vd_id, "CD001", 5) == 0) {
65 int vd_offset;
66 int i;
67
68 dbg("read label from PVD");
69 volume_id_set_label_raw(id, is->volume_id, 32);
70 volume_id_set_label_string(id, is->volume_id, 32);
71
72 dbg("looking for SVDs");
73 vd_offset = ISO_VD_OFFSET;
74 for (i = 0; i < ISO_VD_MAX; i++) {
75 uint8_t svd_label[64];
76
77 is = volume_id_get_buffer(id, off + vd_offset, 0x200);
78 if (is == NULL || is->vd_type == ISO_VD_END)
79 break;
80 if (is->vd_type != ISO_VD_SUPPLEMENTARY)
81 continue;
82
83 dbg("found SVD at offset 0x%llx", (unsigned long long) (off + vd_offset));
84 if (memcmp(is->escape_sequences, "%/@", 3) == 0||
85 memcmp(is->escape_sequences, "%/C", 3) == 0||
86 memcmp(is->escape_sequences, "%/E", 3) == 0) {
87 dbg("Joliet extension found");
88 volume_id_set_unicode16((char *)svd_label, sizeof(svd_label), is->volume_id, BE, 32);
89 if (memcmp(id->label, svd_label, 16) == 0) {
90 dbg("SVD label is identical, use the possibly longer PVD one");
91 break;
92 }
93
94 volume_id_set_label_raw(id, is->volume_id, 32);
95 volume_id_set_label_string(id, svd_label, 32);
96 strcpy(id->type_version, "Joliet Extension");
97 goto found;
98 }
99 vd_offset += ISO_SECTOR_SIZE;
100 }
101 goto found;
102 }
103
104 hs = (struct high_sierra_volume_descriptor *) buf;
105
106 if (memcmp(hs->id, "CDROM", 5) == 0) {
107 strcpy(id->type_version, "High Sierra");
108 goto found;
109 }
110
111 return -1;
112
113 found:
114 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
115 id->type = "iso9660";
116
117 return 0;
118}
diff --git a/util-linux/volume_id/isw_raid.c b/util-linux/volume_id/isw_raid.c
new file mode 100644
index 000000000..8f55f49d9
--- /dev/null
+++ b/util-linux/volume_id/isw_raid.c
@@ -0,0 +1,58 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct isw_meta {
24 uint8_t sig[32];
25 uint32_t check_sum;
26 uint32_t mpb_size;
27 uint32_t family_num;
28 uint32_t generation_num;
29} __attribute__((packed));
30
31#define ISW_SIGNATURE "Intel Raid ISM Cfg Sig. "
32
33
34int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size)
35{
36 uint64_t meta_off;
37 struct isw_meta *isw;
38
39 dbg("probing at offset 0x%llx, size 0x%llx",
40 (unsigned long long) off, (unsigned long long) size);
41
42 if (size < 0x10000)
43 return -1;
44
45 meta_off = ((size / 0x200)-2) * 0x200;
46 isw = volume_id_get_buffer(id, off + meta_off, 0x200);
47 if (isw == NULL)
48 return -1;
49
50 if (memcmp(isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0)
51 return -1;
52
53 volume_id_set_usage(id, VOLUME_ID_RAID);
54 memcpy(id->type_version, &isw->sig[sizeof(ISW_SIGNATURE)-1], 6);
55 id->type = "isw_raid_member";
56
57 return 0;
58}
diff --git a/util-linux/volume_id/jfs.c b/util-linux/volume_id/jfs.c
new file mode 100644
index 000000000..28b4eb694
--- /dev/null
+++ b/util-linux/volume_id/jfs.c
@@ -0,0 +1,59 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct jfs_super_block {
24 uint8_t magic[4];
25 uint32_t version;
26 uint64_t size;
27 uint32_t bsize;
28 uint32_t dummy1;
29 uint32_t pbsize;
30 uint32_t dummy2[27];
31 uint8_t uuid[16];
32 uint8_t label[16];
33 uint8_t loguuid[16];
34} __attribute__((__packed__));
35
36#define JFS_SUPERBLOCK_OFFSET 0x8000
37
38int volume_id_probe_jfs(struct volume_id *id, uint64_t off)
39{
40 struct jfs_super_block *js;
41
42 dbg("probing at offset 0x%llx", (unsigned long long) off);
43
44 js = volume_id_get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200);
45 if (js == NULL)
46 return -1;
47
48 if (memcmp(js->magic, "JFS1", 4) != 0)
49 return -1;
50
51 volume_id_set_label_raw(id, js->label, 16);
52 volume_id_set_label_string(id, js->label, 16);
53 volume_id_set_uuid(id, js->uuid, UUID_DCE);
54
55 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
56 id->type = "jfs";
57
58 return 0;
59}
diff --git a/util-linux/volume_id/linux_raid.c b/util-linux/volume_id/linux_raid.c
new file mode 100644
index 000000000..bb9b3c5cf
--- /dev/null
+++ b/util-linux/volume_id/linux_raid.c
@@ -0,0 +1,79 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct mdp_super_block {
24 uint32_t md_magic;
25 uint32_t major_version;
26 uint32_t minor_version;
27 uint32_t patch_version;
28 uint32_t gvalid_words;
29 uint32_t set_uuid0;
30 uint32_t ctime;
31 uint32_t level;
32 uint32_t size;
33 uint32_t nr_disks;
34 uint32_t raid_disks;
35 uint32_t md_minor;
36 uint32_t not_persistent;
37 uint32_t set_uuid1;
38 uint32_t set_uuid2;
39 uint32_t set_uuid3;
40} __attribute__((packed));
41
42#define MD_RESERVED_BYTES 0x10000
43#define MD_MAGIC 0xa92b4efc
44
45int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size)
46{
47 uint64_t sboff;
48 uint8_t uuid[16];
49 struct mdp_super_block *mdp;
50
51 dbg("probing at offset 0x%llx, size 0x%llx",
52 (unsigned long long) off, (unsigned long long) size);
53
54 if (size < 0x10000)
55 return -1;
56
57 sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES;
58 mdp = volume_id_get_buffer(id, off + sboff, 0x800);
59 if (mdp == NULL)
60 return -1;
61
62 if (mdp->md_magic != cpu_to_le32(MD_MAGIC))
63 return -1;
64
65 memcpy(uuid, &mdp->set_uuid0, 4);
66 memcpy(&uuid[4], &mdp->set_uuid1, 12);
67 volume_id_set_uuid(id, uuid, UUID_DCE);
68
69 snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u.%u",
70 le32_to_cpu(mdp->major_version),
71 le32_to_cpu(mdp->minor_version),
72 le32_to_cpu(mdp->patch_version));
73
74 dbg("found raid signature");
75 volume_id_set_usage(id, VOLUME_ID_RAID);
76 id->type = "linux_raid_member";
77
78 return 0;
79}
diff --git a/util-linux/volume_id/linux_swap.c b/util-linux/volume_id/linux_swap.c
new file mode 100644
index 000000000..56b5d5085
--- /dev/null
+++ b/util-linux/volume_id/linux_swap.c
@@ -0,0 +1,73 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct swap_header_v1_2 {
24 uint8_t bootbits[1024];
25 uint32_t version;
26 uint32_t last_page;
27 uint32_t nr_badpages;
28 uint8_t uuid[16];
29 uint8_t volume_name[16];
30} __attribute__((__packed__));
31
32#define LARGEST_PAGESIZE 0x4000
33
34int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off)
35{
36 struct swap_header_v1_2 *sw;
37 const uint8_t *buf;
38 unsigned page;
39
40 dbg("probing at offset 0x%llx", (unsigned long long) off);
41
42 /* the swap signature is at the end of the PAGE_SIZE */
43 for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
44 buf = volume_id_get_buffer(id, off + page-10, 10);
45 if (buf == NULL)
46 return -1;
47
48 if (memcmp(buf, "SWAP-SPACE", 10) == 0) {
49 id->type_version[0] = '1';
50 id->type_version[1] = '\0';
51 goto found;
52 }
53
54 if (memcmp(buf, "SWAPSPACE2", 10) == 0) {
55 sw = volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2));
56 if (sw == NULL)
57 return -1;
58 id->type_version[0] = '2';
59 id->type_version[1] = '\0';
60 volume_id_set_label_raw(id, sw->volume_name, 16);
61 volume_id_set_label_string(id, sw->volume_name, 16);
62 volume_id_set_uuid(id, sw->uuid, UUID_DCE);
63 goto found;
64 }
65 }
66 return -1;
67
68found:
69 volume_id_set_usage(id, VOLUME_ID_OTHER);
70 id->type = "swap";
71
72 return 0;
73}
diff --git a/util-linux/volume_id/lsi_raid.c b/util-linux/volume_id/lsi_raid.c
new file mode 100644
index 000000000..0eab1c709
--- /dev/null
+++ b/util-linux/volume_id/lsi_raid.c
@@ -0,0 +1,52 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct lsi_meta {
24 uint8_t sig[6];
25} __attribute__((packed));
26
27#define LSI_SIGNATURE "$XIDE$"
28
29int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size)
30{
31 uint64_t meta_off;
32 struct lsi_meta *lsi;
33
34 dbg("probing at offset 0x%llx, size 0x%llx",
35 (unsigned long long) off, (unsigned long long) size);
36
37 if (size < 0x10000)
38 return -1;
39
40 meta_off = ((size / 0x200)-1) * 0x200;
41 lsi = volume_id_get_buffer(id, off + meta_off, 0x200);
42 if (lsi == NULL)
43 return -1;
44
45 if (memcmp(lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0)
46 return -1;
47
48 volume_id_set_usage(id, VOLUME_ID_RAID);
49 id->type = "lsi_mega_raid_member";
50
51 return 0;
52}
diff --git a/util-linux/volume_id/luks.c b/util-linux/volume_id/luks.c
new file mode 100644
index 000000000..e73ce3a03
--- /dev/null
+++ b/util-linux/volume_id/luks.c
@@ -0,0 +1,76 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 W. Michael Petullo <mike@flyn.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23#define SECTOR_SHIFT 9
24#define SECTOR_SIZE (1 << SECTOR_SHIFT)
25
26#define LUKS_CIPHERNAME_L 32
27#define LUKS_CIPHERMODE_L 32
28#define LUKS_HASHSPEC_L 32
29#define LUKS_DIGESTSIZE 20
30#define LUKS_SALTSIZE 32
31#define LUKS_NUMKEYS 8
32
33static const uint8_t LUKS_MAGIC[] = { 'L','U','K','S', 0xba, 0xbe };
34#define LUKS_MAGIC_L 6
35#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/SECTOR_SIZE+1)
36#define UUID_STRING_L 40
37
38struct luks_phdr {
39 uint8_t magic[LUKS_MAGIC_L];
40 uint16_t version;
41 uint8_t cipherName[LUKS_CIPHERNAME_L];
42 uint8_t cipherMode[LUKS_CIPHERMODE_L];
43 uint8_t hashSpec[LUKS_HASHSPEC_L];
44 uint32_t payloadOffset;
45 uint32_t keyBytes;
46 uint8_t mkDigest[LUKS_DIGESTSIZE];
47 uint8_t mkDigestSalt[LUKS_SALTSIZE];
48 uint32_t mkDigestIterations;
49 uint8_t uuid[UUID_STRING_L];
50 struct {
51 uint32_t active;
52 uint32_t passwordIterations;
53 uint8_t passwordSalt[LUKS_SALTSIZE];
54 uint32_t keyMaterialOffset;
55 uint32_t stripes;
56 } keyblock[LUKS_NUMKEYS];
57};
58
59int volume_id_probe_luks(struct volume_id *id, uint64_t off)
60{
61 struct luks_phdr *header;
62
63 header = volume_id_get_buffer(id, off, LUKS_PHDR_SIZE);
64 if (header == NULL)
65 return -1;
66
67 if (memcmp(header->magic, LUKS_MAGIC, LUKS_MAGIC_L))
68 return -1;
69
70 volume_id_set_usage(id, VOLUME_ID_CRYPTO);
71 volume_id_set_uuid(id, header->uuid, UUID_DCE_STRING);
72
73 id->type = "crypto_LUKS";
74
75 return 0;
76}
diff --git a/util-linux/volume_id/lvm.c b/util-linux/volume_id/lvm.c
new file mode 100644
index 000000000..baa8456db
--- /dev/null
+++ b/util-linux/volume_id/lvm.c
@@ -0,0 +1,91 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct lvm1_super_block {
24 uint8_t id[2];
25} __attribute__((packed));
26
27struct lvm2_super_block {
28 uint8_t id[8];
29 uint64_t sector_xl;
30 uint32_t crc_xl;
31 uint32_t offset_xl;
32 uint8_t type[8];
33} __attribute__((packed));
34
35#define LVM1_SB_OFF 0x400
36#define LVM1_MAGIC "HM"
37
38int volume_id_probe_lvm1(struct volume_id *id, uint64_t off)
39{
40 const uint8_t *buf;
41 struct lvm1_super_block *lvm;
42
43 dbg("probing at offset 0x%llx", (unsigned long long) off);
44
45 buf = volume_id_get_buffer(id, off + LVM1_SB_OFF, 0x800);
46 if (buf == NULL)
47 return -1;
48
49 lvm = (struct lvm1_super_block *) buf;
50
51 if (memcmp(lvm->id, LVM1_MAGIC, 2) != 0)
52 return -1;
53
54 volume_id_set_usage(id, VOLUME_ID_RAID);
55 id->type = "LVM1_member";
56
57 return 0;
58}
59
60#define LVM2_LABEL_ID "LABELONE"
61#define LVM2LABEL_SCAN_SECTORS 4
62
63int volume_id_probe_lvm2(struct volume_id *id, uint64_t off)
64{
65 const uint8_t *buf;
66 unsigned soff;
67 struct lvm2_super_block *lvm;
68
69 dbg("probing at offset 0x%llx", (unsigned long long) off);
70
71 buf = volume_id_get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200);
72 if (buf == NULL)
73 return -1;
74
75
76 for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
77 lvm = (struct lvm2_super_block *) &buf[soff];
78
79 if (memcmp(lvm->id, LVM2_LABEL_ID, 8) == 0)
80 goto found;
81 }
82
83 return -1;
84
85 found:
86 memcpy(id->type_version, lvm->type, 8);
87 volume_id_set_usage(id, VOLUME_ID_RAID);
88 id->type = "LVM2_member";
89
90 return 0;
91}
diff --git a/util-linux/volume_id/mac.c b/util-linux/volume_id/mac.c
new file mode 100644
index 000000000..94a99bee0
--- /dev/null
+++ b/util-linux/volume_id/mac.c
@@ -0,0 +1,125 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct mac_driver_desc {
24 uint8_t signature[2];
25 uint16_t block_size;
26 uint32_t block_count;
27} __attribute__((__packed__));
28
29struct mac_partition {
30 uint8_t signature[2];
31 uint16_t res1;
32 uint32_t map_count;
33 uint32_t start_block;
34 uint32_t block_count;
35 uint8_t name[32];
36 uint8_t type[32];
37} __attribute__((__packed__));
38
39int volume_id_probe_mac_partition_map(struct volume_id *id, uint64_t off)
40{
41 const uint8_t *buf;
42 struct mac_driver_desc *driver;
43 struct mac_partition *part;
44
45 dbg("probing at offset 0x%llx", (unsigned long long) off);
46
47 buf = volume_id_get_buffer(id, off, 0x200);
48 if (buf == NULL)
49 return -1;
50
51 part = (struct mac_partition *) buf;
52 if ((memcmp(part->signature, "PM", 2) == 0) &&
53 (memcmp(part->type, "Apple_partition_map", 19) == 0)) {
54 /* linux creates an own subdevice for the map
55 * just return the type if the drive header is missing */
56 volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
57 id->type = "mac_partition_map";
58 return 0;
59 }
60
61 driver = (struct mac_driver_desc *) buf;
62 if (memcmp(driver->signature, "ER", 2) == 0) {
63 /* we are on a main device, like a CD
64 * just try to probe the first partition from the map */
65 unsigned bsize = be16_to_cpu(driver->block_size);
66 int part_count;
67 int i;
68
69 /* get first entry of partition table */
70 buf = volume_id_get_buffer(id, off + bsize, 0x200);
71 if (buf == NULL)
72 return -1;
73
74 part = (struct mac_partition *) buf;
75 if (memcmp(part->signature, "PM", 2) != 0)
76 return -1;
77
78 part_count = be32_to_cpu(part->map_count);
79 dbg("expecting %d partition entries", part_count);
80
81 if (id->partitions != NULL)
82 free(id->partitions);
83 id->partitions =
84 malloc(part_count * sizeof(struct volume_id_partition));
85 if (id->partitions == NULL)
86 return -1;
87 memset(id->partitions, 0x00, sizeof(struct volume_id_partition));
88
89 id->partition_count = part_count;
90
91 for (i = 0; i < part_count; i++) {
92 uint64_t poff;
93 uint64_t plen;
94
95 buf = volume_id_get_buffer(id, off + ((i+1) * bsize), 0x200);
96 if (buf == NULL)
97 return -1;
98
99 part = (struct mac_partition *) buf;
100 if (memcmp(part->signature, "PM", 2) != 0)
101 return -1;
102
103 poff = be32_to_cpu(part->start_block) * bsize;
104 plen = be32_to_cpu(part->block_count) * bsize;
105 dbg("found '%s' partition entry at 0x%llx, len 0x%llx",
106 part->type, (unsigned long long) poff, (unsigned long long) plen);
107
108 id->partitions[i].off = poff;
109 id->partitions[i].len = plen;
110
111 if (memcmp(part->type, "Apple_Free", 10) == 0) {
112 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNUSED);
113 } else if (memcmp(part->type, "Apple_partition_map", 19) == 0) {
114 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_PARTITIONTABLE);
115 } else {
116 volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNPROBED);
117 }
118 }
119 volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
120 id->type = "mac_partition_map";
121 return 0;
122 }
123
124 return -1;
125}
diff --git a/util-linux/volume_id/minix.c b/util-linux/volume_id/minix.c
new file mode 100644
index 000000000..ede23cb24
--- /dev/null
+++ b/util-linux/volume_id/minix.c
@@ -0,0 +1,76 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct minix_super_block
24{
25 uint16_t s_ninodes;
26 uint16_t s_nzones;
27 uint16_t s_imap_blocks;
28 uint16_t s_zmap_blocks;
29 uint16_t s_firstdatazone;
30 uint16_t s_log_zone_size;
31 uint32_t s_max_size;
32 uint16_t s_magic;
33 uint16_t s_state;
34 uint32_t s_zones;
35} __attribute__((__packed__));
36
37#define MINIX_SUPERBLOCK_OFFSET 0x400
38
39int volume_id_probe_minix(struct volume_id *id, uint64_t off)
40{
41 struct minix_super_block *ms;
42
43 dbg("probing at offset 0x%llx", (unsigned long long) off);
44
45 ms = volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200);
46 if (ms == NULL)
47 return -1;
48
49 if (le16_to_cpu(ms->s_magic) == 0x137f) {
50 id->type_version[0] = '1';
51 goto found;
52 }
53
54 if (le16_to_cpu(ms->s_magic) == 0x1387) {
55 id->type_version[0] = '1';
56 goto found;
57 }
58
59 if (le16_to_cpu(ms->s_magic) == 0x2468) {
60 id->type_version[0] = '2';
61 goto found;
62 }
63
64 if (le16_to_cpu(ms->s_magic) == 0x2478) {
65 id->type_version[0] = '2';
66 goto found;
67 }
68
69 return -1;
70
71 found:
72 id->type_version[1] = '\0';
73 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
74 id->type = "minix";
75 return 0;
76}
diff --git a/util-linux/volume_id/msdos.c b/util-linux/volume_id/msdos.c
new file mode 100644
index 000000000..b4b6711dc
--- /dev/null
+++ b/util-linux/volume_id/msdos.c
@@ -0,0 +1,196 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct msdos_partition_entry {
24 uint8_t boot_ind;
25 uint8_t head;
26 uint8_t sector;
27 uint8_t cyl;
28 uint8_t sys_ind;
29 uint8_t end_head;
30 uint8_t end_sector;
31 uint8_t end_cyl;
32 uint32_t start_sect;
33 uint32_t nr_sects;
34} __attribute__((packed));
35
36#define MSDOS_MAGIC "\x55\xaa"
37#define MSDOS_PARTTABLE_OFFSET 0x1be
38#define MSDOS_SIG_OFF 0x1fe
39#define BSIZE 0x200
40#define DOS_EXTENDED_PARTITION 0x05
41#define LINUX_EXTENDED_PARTITION 0x85
42#define WIN98_EXTENDED_PARTITION 0x0f
43#define LINUX_RAID_PARTITION 0xfd
44#define is_extended(type) \
45 (type == DOS_EXTENDED_PARTITION || \
46 type == WIN98_EXTENDED_PARTITION || \
47 type == LINUX_EXTENDED_PARTITION)
48#define is_raid(type) \
49 (type == LINUX_RAID_PARTITION)
50
51int volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off)
52{
53 const uint8_t *buf;
54 int i;
55 uint64_t poff;
56 uint64_t plen;
57 uint64_t extended = 0;
58 uint64_t current;
59 uint64_t next;
60 int limit;
61 int empty = 1;
62 struct msdos_partition_entry *part;
63 struct volume_id_partition *p;
64
65 dbg("probing at offset 0x%llx", (unsigned long long) off);
66
67 buf = volume_id_get_buffer(id, off, 0x200);
68 if (buf == NULL)
69 return -1;
70
71 if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
72 return -1;
73
74 /* check flags on all entries for a valid partition table */
75 part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
76 for (i = 0; i < 4; i++) {
77 if (part[i].boot_ind != 0 &&
78 part[i].boot_ind != 0x80)
79 return -1;
80
81 if (part[i].nr_sects != 0)
82 empty = 0;
83 }
84 if (empty == 1)
85 return -1;
86
87 if (id->partitions != NULL)
88 free(id->partitions);
89 id->partitions = malloc(VOLUME_ID_PARTITIONS_MAX *
90 sizeof(struct volume_id_partition));
91 if (id->partitions == NULL)
92 return -1;
93 memset(id->partitions, 0x00,
94 VOLUME_ID_PARTITIONS_MAX * sizeof(struct volume_id_partition));
95
96 for (i = 0; i < 4; i++) {
97 poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
98 plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;
99
100 if (plen == 0)
101 continue;
102
103 p = &id->partitions[i];
104
105 p->partition_type_raw = part[i].sys_ind;
106
107 if (is_extended(part[i].sys_ind)) {
108 dbg("found extended partition at 0x%llx", (unsigned long long) poff);
109 volume_id_set_usage_part(p, VOLUME_ID_PARTITIONTABLE);
110 p->type = "msdos_extended_partition";
111 if (extended == 0)
112 extended = off + poff;
113 } else {
114 dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
115 part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
116
117 if (is_raid(part[i].sys_ind))
118 volume_id_set_usage_part(p, VOLUME_ID_RAID);
119 else
120 volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
121 }
122
123 p->off = off + poff;
124 p->len = plen;
125 id->partition_count = i+1;
126 }
127
128 next = extended;
129 current = extended;
130 limit = 50;
131
132 /* follow extended partition chain and add data partitions */
133 while (next != 0) {
134 if (limit-- == 0) {
135 dbg("extended chain limit reached");
136 break;
137 }
138
139 buf = volume_id_get_buffer(id, current, 0x200);
140 if (buf == NULL)
141 break;
142
143 part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
144
145 if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
146 break;
147
148 next = 0;
149
150 for (i = 0; i < 4; i++) {
151 poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
152 plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;
153
154 if (plen == 0)
155 continue;
156
157 if (is_extended(part[i].sys_ind)) {
158 dbg("found extended partition at 0x%llx", (unsigned long long) poff);
159 if (next == 0)
160 next = extended + poff;
161 } else {
162 dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
163 part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
164
165 /* we always start at the 5th entry */
166 while (id->partition_count < 4)
167 volume_id_set_usage_part(&id->partitions[id->partition_count++], VOLUME_ID_UNUSED);
168
169 p = &id->partitions[id->partition_count];
170
171 if (is_raid(part[i].sys_ind))
172 volume_id_set_usage_part(p, VOLUME_ID_RAID);
173 else
174 volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
175
176 p->off = current + poff;
177 p->len = plen;
178 id->partition_count++;
179
180 p->partition_type_raw = part[i].sys_ind;
181
182 if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
183 dbg("too many partitions");
184 next = 0;
185 }
186 }
187 }
188
189 current = next;
190 }
191
192 volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
193 id->type = "msdos_partition_table";
194
195 return 0;
196}
diff --git a/util-linux/volume_id/ntfs.c b/util-linux/volume_id/ntfs.c
new file mode 100644
index 000000000..cbd5d5bba
--- /dev/null
+++ b/util-linux/volume_id/ntfs.c
@@ -0,0 +1,193 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct ntfs_super_block {
24 uint8_t jump[3];
25 uint8_t oem_id[8];
26 uint16_t bytes_per_sector;
27 uint8_t sectors_per_cluster;
28 uint16_t reserved_sectors;
29 uint8_t fats;
30 uint16_t root_entries;
31 uint16_t sectors;
32 uint8_t media_type;
33 uint16_t sectors_per_fat;
34 uint16_t sectors_per_track;
35 uint16_t heads;
36 uint32_t hidden_sectors;
37 uint32_t large_sectors;
38 uint16_t unused[2];
39 uint64_t number_of_sectors;
40 uint64_t mft_cluster_location;
41 uint64_t mft_mirror_cluster_location;
42 int8_t cluster_per_mft_record;
43 uint8_t reserved1[3];
44 int8_t cluster_per_index_record;
45 uint8_t reserved2[3];
46 uint8_t volume_serial[8];
47 uint16_t checksum;
48} __attribute__((__packed__));
49
50struct master_file_table_record {
51 uint8_t magic[4];
52 uint16_t usa_ofs;
53 uint16_t usa_count;
54 uint64_t lsn;
55 uint16_t sequence_number;
56 uint16_t link_count;
57 uint16_t attrs_offset;
58 uint16_t flags;
59 uint32_t bytes_in_use;
60 uint32_t bytes_allocated;
61} __attribute__((__packed__));
62
63struct file_attribute {
64 uint32_t type;
65 uint32_t len;
66 uint8_t non_resident;
67 uint8_t name_len;
68 uint16_t name_offset;
69 uint16_t flags;
70 uint16_t instance;
71 uint32_t value_len;
72 uint16_t value_offset;
73} __attribute__((__packed__));
74
75struct volume_info {
76 uint64_t reserved;
77 uint8_t major_ver;
78 uint8_t minor_ver;
79} __attribute__((__packed__));
80
81#define MFT_RECORD_VOLUME 3
82#define MFT_RECORD_ATTR_VOLUME_NAME 0x60
83#define MFT_RECORD_ATTR_VOLUME_INFO 0x70
84#define MFT_RECORD_ATTR_OBJECT_ID 0x40
85#define MFT_RECORD_ATTR_END 0xffffffffu
86
87int volume_id_probe_ntfs(struct volume_id *id, uint64_t off)
88{
89 unsigned sector_size;
90 unsigned cluster_size;
91 uint64_t mft_cluster;
92 uint64_t mft_off;
93 unsigned mft_record_size;
94 unsigned attr_type;
95 unsigned attr_off;
96 unsigned attr_len;
97 unsigned val_off;
98 unsigned val_len;
99 struct master_file_table_record *mftr;
100 struct ntfs_super_block *ns;
101 const uint8_t *buf;
102 const uint8_t *val;
103
104 dbg("probing at offset 0x%llx", (unsigned long long) off);
105
106 ns = volume_id_get_buffer(id, off, 0x200);
107 if (ns == NULL)
108 return -1;
109
110 if (memcmp(ns->oem_id, "NTFS", 4) != 0)
111 return -1;
112
113 volume_id_set_uuid(id, ns->volume_serial, UUID_NTFS);
114
115 sector_size = le16_to_cpu(ns->bytes_per_sector);
116 cluster_size = ns->sectors_per_cluster * sector_size;
117 mft_cluster = le64_to_cpu(ns->mft_cluster_location);
118 mft_off = mft_cluster * cluster_size;
119
120 if (ns->cluster_per_mft_record < 0)
121 /* size = -log2(mft_record_size); normally 1024 Bytes */
122 mft_record_size = 1 << -ns->cluster_per_mft_record;
123 else
124 mft_record_size = ns->cluster_per_mft_record * cluster_size;
125
126 dbg("sectorsize 0x%x", sector_size);
127 dbg("clustersize 0x%x", cluster_size);
128 dbg("mftcluster %llu", (unsigned long long) mft_cluster);
129 dbg("mftoffset 0x%llx", (unsigned long long) mft_off);
130 dbg("cluster per mft_record %i", ns->cluster_per_mft_record);
131 dbg("mft record size %i", mft_record_size);
132
133 buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
134 mft_record_size);
135 if (buf == NULL)
136 goto found;
137
138 mftr = (struct master_file_table_record*) buf;
139
140 dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
141 if (memcmp(mftr->magic, "FILE", 4) != 0)
142 goto found;
143
144 attr_off = le16_to_cpu(mftr->attrs_offset);
145 dbg("file $Volume's attributes are at offset %i", attr_off);
146
147 while (1) {
148 struct file_attribute *attr;
149
150 attr = (struct file_attribute*) &buf[attr_off];
151 attr_type = le32_to_cpu(attr->type);
152 attr_len = le16_to_cpu(attr->len);
153 val_off = le16_to_cpu(attr->value_offset);
154 val_len = le32_to_cpu(attr->value_len);
155 attr_off += attr_len;
156
157 if (attr_len == 0)
158 break;
159
160 if (attr_off >= mft_record_size)
161 break;
162
163 if (attr_type == MFT_RECORD_ATTR_END)
164 break;
165
166 dbg("found attribute type 0x%x, len %i, at offset %i",
167 attr_type, attr_len, attr_off);
168
169 if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
170 struct volume_info *info;
171 dbg("found info, len %i", val_len);
172 info = (struct volume_info*) (((uint8_t *) attr) + val_off);
173 snprintf(id->type_version, sizeof(id->type_version)-1,
174 "%u.%u", info->major_ver, info->minor_ver);
175 }
176
177 if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
178 dbg("found label, len %i", val_len);
179 if (val_len > VOLUME_ID_LABEL_SIZE)
180 val_len = VOLUME_ID_LABEL_SIZE;
181
182 val = ((uint8_t *) attr) + val_off;
183 volume_id_set_label_raw(id, val, val_len);
184 volume_id_set_label_unicode16(id, val, LE, val_len);
185 }
186 }
187
188 found:
189 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
190 id->type = "ntfs";
191
192 return 0;
193}
diff --git a/util-linux/volume_id/nvidia_raid.c b/util-linux/volume_id/nvidia_raid.c
new file mode 100644
index 000000000..8619565c9
--- /dev/null
+++ b/util-linux/volume_id/nvidia_raid.c
@@ -0,0 +1,56 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct nvidia_meta {
24 uint8_t vendor[8];
25 uint32_t size;
26 uint32_t chksum;
27 uint16_t version;
28} __attribute__((packed));
29
30#define NVIDIA_SIGNATURE "NVIDIA"
31
32int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size)
33{
34 uint64_t meta_off;
35 struct nvidia_meta *nv;
36
37 dbg("probing at offset 0x%llx, size 0x%llx",
38 (unsigned long long) off, (unsigned long long) size);
39
40 if (size < 0x10000)
41 return -1;
42
43 meta_off = ((size / 0x200)-2) * 0x200;
44 nv = volume_id_get_buffer(id, off + meta_off, 0x200);
45 if (nv == NULL)
46 return -1;
47
48 if (memcmp(nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0)
49 return -1;
50
51 volume_id_set_usage(id, VOLUME_ID_RAID);
52 snprintf(id->type_version, sizeof(id->type_version)-1, "%u", le16_to_cpu(nv->version));
53 id->type = "nvidia_raid_member";
54
55 return 0;
56}
diff --git a/util-linux/volume_id/ocfs2.c b/util-linux/volume_id/ocfs2.c
new file mode 100644
index 000000000..bc490df57
--- /dev/null
+++ b/util-linux/volume_id/ocfs2.c
@@ -0,0 +1,105 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) Andre Masella <andre@masella.no-ip.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23/* All these values are taken from ocfs2-tools's ocfs2_fs.h */
24#define OCFS2_VOL_UUID_LEN 16
25#define OCFS2_MAX_VOL_LABEL_LEN 64
26#define OCFS2_SUPERBLOCK_OFFSET 0x2000
27
28
29/* This is the superblock. The OCFS2 header files have structs in structs.
30This is one has been simplified since we only care about the superblock.
31*/
32
33struct ocfs2_super_block {
34 uint8_t i_signature[8]; /* Signature for validation */
35 uint32_t i_generation; /* Generation number */
36 int16_t i_suballoc_slot; /* Slot suballocator this inode belongs to */
37 uint16_t i_suballoc_bit; /* Bit offset in suballocator block group */
38 uint32_t i_reserved0;
39 uint32_t i_clusters; /* Cluster count */
40 uint32_t i_uid; /* Owner UID */
41 uint32_t i_gid; /* Owning GID */
42 uint64_t i_size; /* Size in bytes */
43 uint16_t i_mode; /* File mode */
44 uint16_t i_links_count; /* Links count */
45 uint32_t i_flags; /* File flags */
46 uint64_t i_atime; /* Access time */
47 uint64_t i_ctime; /* Creation time */
48 uint64_t i_mtime; /* Modification time */
49 uint64_t i_dtime; /* Deletion time */
50 uint64_t i_blkno; /* Offset on disk, in blocks */
51 uint64_t i_last_eb_blk; /* Pointer to last extent block */
52 uint32_t i_fs_generation; /* Generation per fs-instance */
53 uint32_t i_atime_nsec;
54 uint32_t i_ctime_nsec;
55 uint32_t i_mtime_nsec;
56 uint64_t i_reserved1[9];
57 uint64_t i_pad1; /* Generic way to refer to this 64bit union */
58 /* Normally there is a union of the different block types, but we only care about the superblock. */
59 uint16_t s_major_rev_level;
60 uint16_t s_minor_rev_level;
61 uint16_t s_mnt_count;
62 int16_t s_max_mnt_count;
63 uint16_t s_state; /* File system state */
64 uint16_t s_errors; /* Behaviour when detecting errors */
65 uint32_t s_checkinterval; /* Max time between checks */
66 uint64_t s_lastcheck; /* Time of last check */
67 uint32_t s_creator_os; /* OS */
68 uint32_t s_feature_compat; /* Compatible feature set */
69 uint32_t s_feature_incompat; /* Incompatible feature set */
70 uint32_t s_feature_ro_compat; /* Readonly-compatible feature set */
71 uint64_t s_root_blkno; /* Offset, in blocks, of root directory dinode */
72 uint64_t s_system_dir_blkno; /* Offset, in blocks, of system directory dinode */
73 uint32_t s_blocksize_bits; /* Blocksize for this fs */
74 uint32_t s_clustersize_bits; /* Clustersize for this fs */
75 uint16_t s_max_slots; /* Max number of simultaneous mounts before tunefs required */
76 uint16_t s_reserved1;
77 uint32_t s_reserved2;
78 uint64_t s_first_cluster_group; /* Block offset of 1st cluster group header */
79 uint8_t s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */
80 uint8_t s_uuid[OCFS2_VOL_UUID_LEN]; /* 128-bit uuid */
81} __attribute__((__packed__));
82
83int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off)
84{
85 struct ocfs2_super_block *os;
86
87 dbg("probing at offset 0x%llx", (unsigned long long) off);
88
89 os = volume_id_get_buffer(id, off + OCFS2_SUPERBLOCK_OFFSET, 0x200);
90 if (os == NULL)
91 return -1;
92
93 if (memcmp(os->i_signature, "OCFSV2", 6) != 0) {
94 return -1;
95 }
96
97 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
98 volume_id_set_label_raw(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ?
99 OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE);
100 volume_id_set_label_string(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ?
101 OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE);
102 volume_id_set_uuid(id, os->s_uuid, UUID_DCE);
103 id->type = "ocfs2";
104 return 0;
105}
diff --git a/util-linux/volume_id/promise_raid.c b/util-linux/volume_id/promise_raid.c
new file mode 100644
index 000000000..9195c637b
--- /dev/null
+++ b/util-linux/volume_id/promise_raid.c
@@ -0,0 +1,63 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct promise_meta {
24 uint8_t sig[24];
25} __attribute__((packed));
26
27#define PDC_CONFIG_OFF 0x1200
28#define PDC_SIGNATURE "Promise Technology, Inc."
29
30int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size)
31{
32 static const unsigned short sectors[] = {
33 63, 255, 256, 16, 399
34 };
35
36 struct promise_meta *pdc;
37 unsigned i;
38
39 dbg("probing at offset 0x%llx, size 0x%llx",
40 (unsigned long long) off, (unsigned long long) size);
41
42 if (size < 0x40000)
43 return -1;
44
45 for (i = 0; i < ARRAY_SIZE(sectors); i++) {
46 uint64_t meta_off;
47
48 meta_off = ((size / 0x200) - sectors[i]) * 0x200;
49 pdc = volume_id_get_buffer(id, off + meta_off, 0x200);
50 if (pdc == NULL)
51 return -1;
52
53 if (memcmp(pdc->sig, PDC_SIGNATURE, sizeof(PDC_SIGNATURE)-1) == 0)
54 goto found;
55 }
56 return -1;
57
58 found:
59 volume_id_set_usage(id, VOLUME_ID_RAID);
60 id->type = "promise_fasttrack_raid_member";
61
62 return 0;
63}
diff --git a/util-linux/volume_id/reiserfs.c b/util-linux/volume_id/reiserfs.c
new file mode 100644
index 000000000..98ecec23a
--- /dev/null
+++ b/util-linux/volume_id/reiserfs.c
@@ -0,0 +1,105 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 * Copyright (C) 2005 Tobias Klauser <tklauser@access.unizh.ch>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include "volume_id_internal.h"
23
24struct reiserfs_super_block {
25 uint32_t blocks_count;
26 uint32_t free_blocks;
27 uint32_t root_block;
28 uint32_t journal_block;
29 uint32_t journal_dev;
30 uint32_t orig_journal_size;
31 uint32_t dummy2[5];
32 uint16_t blocksize;
33 uint16_t dummy3[3];
34 uint8_t magic[12];
35 uint32_t dummy4[5];
36 uint8_t uuid[16];
37 uint8_t label[16];
38} __attribute__((__packed__));
39
40struct reiser4_super_block {
41 uint8_t magic[16];
42 uint16_t dummy[2];
43 uint8_t uuid[16];
44 uint8_t label[16];
45 uint64_t dummy2;
46} __attribute__((__packed__));
47
48#define REISERFS1_SUPERBLOCK_OFFSET 0x2000
49#define REISERFS_SUPERBLOCK_OFFSET 0x10000
50
51int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off)
52{
53 struct reiserfs_super_block *rs;
54 struct reiser4_super_block *rs4;
55
56 dbg("probing at offset 0x%llx", (unsigned long long) off);
57
58 rs = volume_id_get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200);
59 if (rs == NULL)
60 return -1;
61
62 if (memcmp(rs->magic, "ReIsErFs", 8) == 0) {
63 strcpy(id->type_version, "3.5");
64 goto found;
65 }
66 if (memcmp(rs->magic, "ReIsEr2Fs", 9) == 0) {
67 strcpy(id->type_version, "3.6");
68 goto found_label;
69 }
70 if (memcmp(rs->magic, "ReIsEr3Fs", 9) == 0) {
71 strcpy(id->type_version, "JR");
72 goto found_label;
73 }
74
75 rs4 = (struct reiser4_super_block *) rs;
76 if (memcmp(rs4->magic, "ReIsEr4", 7) == 0) {
77 strcpy(id->type_version, "4");
78 volume_id_set_label_raw(id, rs4->label, 16);
79 volume_id_set_label_string(id, rs4->label, 16);
80 volume_id_set_uuid(id, rs4->uuid, UUID_DCE);
81 goto found;
82 }
83
84 rs = volume_id_get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200);
85 if (rs == NULL)
86 return -1;
87
88 if (memcmp(rs->magic, "ReIsErFs", 8) == 0) {
89 strcpy(id->type_version, "3.5");
90 goto found;
91 }
92
93 return -1;
94
95 found_label:
96 volume_id_set_label_raw(id, rs->label, 16);
97 volume_id_set_label_string(id, rs->label, 16);
98 volume_id_set_uuid(id, rs->uuid, UUID_DCE);
99
100 found:
101 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
102 id->type = "reiserfs";
103
104 return 0;
105}
diff --git a/util-linux/volume_id/romfs.c b/util-linux/volume_id/romfs.c
new file mode 100644
index 000000000..7c4fc0f70
--- /dev/null
+++ b/util-linux/volume_id/romfs.c
@@ -0,0 +1,54 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct romfs_super {
24 uint8_t magic[8];
25 uint32_t size;
26 uint32_t checksum;
27 uint8_t name[0];
28} __attribute__((__packed__));
29
30int volume_id_probe_romfs(struct volume_id *id, uint64_t off)
31{
32 struct romfs_super *rfs;
33
34 dbg("probing at offset 0x%llx", (unsigned long long) off);
35
36 rfs = volume_id_get_buffer(id, off, 0x200);
37 if (rfs == NULL)
38 return -1;
39
40 if (memcmp(rfs->magic, "-rom1fs-", 4) == 0) {
41 size_t len = strlen((char *)rfs->name);
42
43 if (len) {
44 volume_id_set_label_raw(id, rfs->name, len);
45 volume_id_set_label_string(id, rfs->name, len);
46 }
47
48 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
49 id->type = "romfs";
50 return 0;
51 }
52
53 return -1;
54}
diff --git a/util-linux/volume_id/silicon_raid.c b/util-linux/volume_id/silicon_raid.c
new file mode 100644
index 000000000..ea001745f
--- /dev/null
+++ b/util-linux/volume_id/silicon_raid.c
@@ -0,0 +1,69 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct silicon_meta {
24 uint8_t unknown0[0x2E];
25 uint8_t ascii_version[0x36 - 0x2E];
26 uint8_t diskname[0x56 - 0x36];
27 uint8_t unknown1[0x60 - 0x56];
28 uint32_t magic;
29 uint32_t unknown1a[0x6C - 0x64];
30 uint32_t array_sectors_low;
31 uint32_t array_sectors_high;
32 uint8_t unknown2[0x78 - 0x74];
33 uint32_t thisdisk_sectors;
34 uint8_t unknown3[0x100 - 0x7C];
35 uint8_t unknown4[0x104 - 0x100];
36 uint16_t product_id;
37 uint16_t vendor_id;
38 uint16_t minor_ver;
39 uint16_t major_ver;
40} __attribute__((packed));
41
42#define SILICON_MAGIC 0x2F000000
43
44int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size)
45{
46 uint64_t meta_off;
47 struct silicon_meta *sil;
48
49 dbg("probing at offset 0x%llx, size 0x%llx",
50 (unsigned long long) off, (unsigned long long) size);
51
52 if (size < 0x10000)
53 return -1;
54
55 meta_off = ((size / 0x200)-1) * 0x200;
56 sil = volume_id_get_buffer(id, off + meta_off, 0x200);
57 if (sil == NULL)
58 return -1;
59
60 if (sil->magic != cpu_to_le32(SILICON_MAGIC))
61 return -1;
62
63 volume_id_set_usage(id, VOLUME_ID_RAID);
64 snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u",
65 le16_to_cpu(sil->major_ver), le16_to_cpu(sil->minor_ver));
66 id->type = "silicon_medley_raid_member";
67
68 return 0;
69}
diff --git a/util-linux/volume_id/sysv.c b/util-linux/volume_id/sysv.c
new file mode 100644
index 000000000..71c0fd496
--- /dev/null
+++ b/util-linux/volume_id/sysv.c
@@ -0,0 +1,125 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23#define SYSV_NICINOD 100
24#define SYSV_NICFREE 50
25
26struct sysv_super
27{
28 uint16_t s_isize;
29 uint16_t s_pad0;
30 uint32_t s_fsize;
31 uint16_t s_nfree;
32 uint16_t s_pad1;
33 uint32_t s_free[SYSV_NICFREE];
34 uint16_t s_ninode;
35 uint16_t s_pad2;
36 uint16_t s_inode[SYSV_NICINOD];
37 uint8_t s_flock;
38 uint8_t s_ilock;
39 uint8_t s_fmod;
40 uint8_t s_ronly;
41 uint32_t s_time;
42 uint16_t s_dinfo[4];
43 uint32_t s_tfree;
44 uint16_t s_tinode;
45 uint16_t s_pad3;
46 uint8_t s_fname[6];
47 uint8_t s_fpack[6];
48 uint32_t s_fill[12];
49 uint32_t s_state;
50 uint32_t s_magic;
51 uint32_t s_type;
52} __attribute__((__packed__));
53
54#define XENIX_NICINOD 100
55#define XENIX_NICFREE 100
56
57struct xenix_super {
58 uint16_t s_isize;
59 uint32_t s_fsize;
60 uint16_t s_nfree;
61 uint32_t s_free[XENIX_NICFREE];
62 uint16_t s_ninode;
63 uint16_t s_inode[XENIX_NICINOD];
64 uint8_t s_flock;
65 uint8_t s_ilock;
66 uint8_t s_fmod;
67 uint8_t s_ronly;
68 uint32_t s_time;
69 uint32_t s_tfree;
70 uint16_t s_tinode;
71 uint16_t s_dinfo[4];
72 uint8_t s_fname[6];
73 uint8_t s_fpack[6];
74 uint8_t s_clean;
75 uint8_t s_fill[371];
76 uint32_t s_magic;
77 uint32_t s_type;
78} __attribute__((__packed__));
79
80#define SYSV_SUPERBLOCK_BLOCK 0x01
81#define SYSV_MAGIC 0xfd187e20
82#define XENIX_SUPERBLOCK_BLOCK 0x18
83#define XENIX_MAGIC 0x2b5544
84#define SYSV_MAX_BLOCKSIZE 0x800
85
86int volume_id_probe_sysv(struct volume_id *id, uint64_t off)
87{
88 struct sysv_super *vs;
89 struct xenix_super *xs;
90 unsigned boff;
91
92 dbg("probing at offset 0x%llx", (unsigned long long) off);
93
94 for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
95 vs = volume_id_get_buffer(id, off + (boff * SYSV_SUPERBLOCK_BLOCK), 0x200);
96 if (vs == NULL)
97 return -1;
98
99 if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) {
100 volume_id_set_label_raw(id, vs->s_fname, 6);
101 volume_id_set_label_string(id, vs->s_fname, 6);
102 id->type = "sysv";
103 goto found;
104 }
105 }
106
107 for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
108 xs = volume_id_get_buffer(id, off + (boff + XENIX_SUPERBLOCK_BLOCK), 0x200);
109 if (xs == NULL)
110 return -1;
111
112 if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) {
113 volume_id_set_label_raw(id, xs->s_fname, 6);
114 volume_id_set_label_string(id, xs->s_fname, 6);
115 id->type = "xenix";
116 goto found;
117 }
118 }
119
120 return -1;
121
122 found:
123 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
124 return 0;
125}
diff --git a/util-linux/volume_id/udf.c b/util-linux/volume_id/udf.c
new file mode 100644
index 000000000..5cdb49c31
--- /dev/null
+++ b/util-linux/volume_id/udf.c
@@ -0,0 +1,172 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct volume_descriptor {
24 struct descriptor_tag {
25 uint16_t id;
26 uint16_t version;
27 uint8_t checksum;
28 uint8_t reserved;
29 uint16_t serial;
30 uint16_t crc;
31 uint16_t crc_len;
32 uint32_t location;
33 } __attribute__((__packed__)) tag;
34 union {
35 struct anchor_descriptor {
36 uint32_t length;
37 uint32_t location;
38 } __attribute__((__packed__)) anchor;
39 struct primary_descriptor {
40 uint32_t seq_num;
41 uint32_t desc_num;
42 struct dstring {
43 uint8_t clen;
44 uint8_t c[31];
45 } __attribute__((__packed__)) ident;
46 } __attribute__((__packed__)) primary;
47 } __attribute__((__packed__)) type;
48} __attribute__((__packed__));
49
50struct volume_structure_descriptor {
51 uint8_t type;
52 uint8_t id[5];
53 uint8_t version;
54} __attribute__((__packed__));
55
56#define UDF_VSD_OFFSET 0x8000
57
58int volume_id_probe_udf(struct volume_id *id, uint64_t off)
59{
60 struct volume_descriptor *vd;
61 struct volume_structure_descriptor *vsd;
62 unsigned bs;
63 unsigned b;
64 unsigned type;
65 unsigned count;
66 unsigned loc;
67 unsigned clen;
68
69 dbg("probing at offset 0x%llx", (unsigned long long) off);
70
71 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
72 if (vsd == NULL)
73 return -1;
74
75 if (memcmp(vsd->id, "NSR02", 5) == 0)
76 goto blocksize;
77 if (memcmp(vsd->id, "NSR03", 5) == 0)
78 goto blocksize;
79 if (memcmp(vsd->id, "BEA01", 5) == 0)
80 goto blocksize;
81 if (memcmp(vsd->id, "BOOT2", 5) == 0)
82 goto blocksize;
83 if (memcmp(vsd->id, "CD001", 5) == 0)
84 goto blocksize;
85 if (memcmp(vsd->id, "CDW02", 5) == 0)
86 goto blocksize;
87 if (memcmp(vsd->id, "TEA03", 5) == 0)
88 goto blocksize;
89 return -1;
90
91blocksize:
92 /* search the next VSD to get the logical block size of the volume */
93 for (bs = 0x800; bs < 0x8000; bs += 0x800) {
94 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
95 if (vsd == NULL)
96 return -1;
97 dbg("test for blocksize: 0x%x", bs);
98 if (vsd->id[0] != '\0')
99 goto nsr;
100 }
101 return -1;
102
103nsr:
104 /* search the list of VSDs for a NSR descriptor */
105 for (b = 0; b < 64; b++) {
106 vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
107 if (vsd == NULL)
108 return -1;
109
110 dbg("vsd: %c%c%c%c%c",
111 vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
112
113 if (vsd->id[0] == '\0')
114 return -1;
115 if (memcmp(vsd->id, "NSR02", 5) == 0)
116 goto anchor;
117 if (memcmp(vsd->id, "NSR03", 5) == 0)
118 goto anchor;
119 }
120 return -1;
121
122anchor:
123 /* read anchor volume descriptor */
124 vd = volume_id_get_buffer(id, off + (256 * bs), 0x200);
125 if (vd == NULL)
126 return -1;
127
128 type = le16_to_cpu(vd->tag.id);
129 if (type != 2) /* TAG_ID_AVDP */
130 goto found;
131
132 /* get desriptor list address and block count */
133 count = le32_to_cpu(vd->type.anchor.length) / bs;
134 loc = le32_to_cpu(vd->type.anchor.location);
135 dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
136
137 /* pick the primary descriptor from the list */
138 for (b = 0; b < count; b++) {
139 vd = volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200);
140 if (vd == NULL)
141 return -1;
142
143 type = le16_to_cpu(vd->tag.id);
144 dbg("descriptor type %i", type);
145
146 /* check validity */
147 if (type == 0)
148 goto found;
149 if (le32_to_cpu(vd->tag.location) != loc + b)
150 goto found;
151
152 if (type == 1) /* TAG_ID_PVD */
153 goto pvd;
154 }
155 goto found;
156
157 pvd:
158 volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32);
159
160 clen = vd->type.primary.ident.clen;
161 dbg("label string charsize=%i bit", clen);
162 if (clen == 8)
163 volume_id_set_label_string(id, vd->type.primary.ident.c, 31);
164 else if (clen == 16)
165 volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE, 31);
166
167 found:
168 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
169 id->type = "udf";
170
171 return 0;
172}
diff --git a/util-linux/volume_id/ufs.c b/util-linux/volume_id/ufs.c
new file mode 100644
index 000000000..768670e9d
--- /dev/null
+++ b/util-linux/volume_id/ufs.c
@@ -0,0 +1,206 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct ufs_super_block {
24 uint32_t fs_link;
25 uint32_t fs_rlink;
26 uint32_t fs_sblkno;
27 uint32_t fs_cblkno;
28 uint32_t fs_iblkno;
29 uint32_t fs_dblkno;
30 uint32_t fs_cgoffset;
31 uint32_t fs_cgmask;
32 uint32_t fs_time;
33 uint32_t fs_size;
34 uint32_t fs_dsize;
35 uint32_t fs_ncg;
36 uint32_t fs_bsize;
37 uint32_t fs_fsize;
38 uint32_t fs_frag;
39 uint32_t fs_minfree;
40 uint32_t fs_rotdelay;
41 uint32_t fs_rps;
42 uint32_t fs_bmask;
43 uint32_t fs_fmask;
44 uint32_t fs_bshift;
45 uint32_t fs_fshift;
46 uint32_t fs_maxcontig;
47 uint32_t fs_maxbpg;
48 uint32_t fs_fragshift;
49 uint32_t fs_fsbtodb;
50 uint32_t fs_sbsize;
51 uint32_t fs_csmask;
52 uint32_t fs_csshift;
53 uint32_t fs_nindir;
54 uint32_t fs_inopb;
55 uint32_t fs_nspf;
56 uint32_t fs_optim;
57 uint32_t fs_npsect_state;
58 uint32_t fs_interleave;
59 uint32_t fs_trackskew;
60 uint32_t fs_id[2];
61 uint32_t fs_csaddr;
62 uint32_t fs_cssize;
63 uint32_t fs_cgsize;
64 uint32_t fs_ntrak;
65 uint32_t fs_nsect;
66 uint32_t fs_spc;
67 uint32_t fs_ncyl;
68 uint32_t fs_cpg;
69 uint32_t fs_ipg;
70 uint32_t fs_fpg;
71 struct ufs_csum {
72 uint32_t cs_ndir;
73 uint32_t cs_nbfree;
74 uint32_t cs_nifree;
75 uint32_t cs_nffree;
76 } __attribute__((__packed__)) fs_cstotal;
77 int8_t fs_fmod;
78 int8_t fs_clean;
79 int8_t fs_ronly;
80 int8_t fs_flags;
81 union {
82 struct {
83 int8_t fs_fsmnt[512];
84 uint32_t fs_cgrotor;
85 uint32_t fs_csp[31];
86 uint32_t fs_maxcluster;
87 uint32_t fs_cpc;
88 uint16_t fs_opostbl[16][8];
89 } __attribute__((__packed__)) fs_u1;
90 struct {
91 int8_t fs_fsmnt[468];
92 uint8_t fs_volname[32];
93 uint64_t fs_swuid;
94 int32_t fs_pad;
95 uint32_t fs_cgrotor;
96 uint32_t fs_ocsp[28];
97 uint32_t fs_contigdirs;
98 uint32_t fs_csp;
99 uint32_t fs_maxcluster;
100 uint32_t fs_active;
101 int32_t fs_old_cpc;
102 int32_t fs_maxbsize;
103 int64_t fs_sparecon64[17];
104 int64_t fs_sblockloc;
105 struct ufs2_csum_total {
106 uint64_t cs_ndir;
107 uint64_t cs_nbfree;
108 uint64_t cs_nifree;
109 uint64_t cs_nffree;
110 uint64_t cs_numclusters;
111 uint64_t cs_spare[3];
112 } __attribute__((__packed__)) fs_cstotal;
113 struct ufs_timeval {
114 int32_t tv_sec;
115 int32_t tv_usec;
116 } __attribute__((__packed__)) fs_time;
117 int64_t fs_size;
118 int64_t fs_dsize;
119 uint64_t fs_csaddr;
120 int64_t fs_pendingblocks;
121 int32_t fs_pendinginodes;
122 } __attribute__((__packed__)) fs_u2;
123 } fs_u11;
124 union {
125 struct {
126 int32_t fs_sparecon[53];
127 int32_t fs_reclaim;
128 int32_t fs_sparecon2[1];
129 int32_t fs_state;
130 uint32_t fs_qbmask[2];
131 uint32_t fs_qfmask[2];
132 } __attribute__((__packed__)) fs_sun;
133 struct {
134 int32_t fs_sparecon[53];
135 int32_t fs_reclaim;
136 int32_t fs_sparecon2[1];
137 uint32_t fs_npsect;
138 uint32_t fs_qbmask[2];
139 uint32_t fs_qfmask[2];
140 } __attribute__((__packed__)) fs_sunx86;
141 struct {
142 int32_t fs_sparecon[50];
143 int32_t fs_contigsumsize;
144 int32_t fs_maxsymlinklen;
145 int32_t fs_inodefmt;
146 uint32_t fs_maxfilesize[2];
147 uint32_t fs_qbmask[2];
148 uint32_t fs_qfmask[2];
149 int32_t fs_state;
150 } __attribute__((__packed__)) fs_44;
151 } fs_u2;
152 int32_t fs_postblformat;
153 int32_t fs_nrpos;
154 int32_t fs_postbloff;
155 int32_t fs_rotbloff;
156 uint32_t fs_magic;
157 uint8_t fs_space[1];
158} __attribute__((__packed__));
159
160#define UFS_MAGIC 0x00011954
161#define UFS2_MAGIC 0x19540119
162#define UFS_MAGIC_FEA 0x00195612
163#define UFS_MAGIC_LFN 0x00095014
164
165int volume_id_probe_ufs(struct volume_id *id, uint64_t off)
166{
167 static const short offsets[] = { 0, 8, 64, 256 };
168
169 uint32_t magic;
170 int i;
171 struct ufs_super_block *ufs;
172
173 dbg("probing at offset 0x%llx", (unsigned long long) off);
174
175 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
176 ufs = volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800);
177 if (ufs == NULL)
178 return -1;
179
180 dbg("offset 0x%x", offsets[i] * 0x400);
181 magic = ufs->fs_magic;
182 if ((magic == cpu_to_be32(UFS_MAGIC))
183 || (magic == cpu_to_be32(UFS2_MAGIC))
184 || (magic == cpu_to_be32(UFS_MAGIC_FEA))
185 || (magic == cpu_to_be32(UFS_MAGIC_LFN))
186 ) {
187 dbg("magic 0x%08x(be)", magic);
188 goto found;
189 }
190 if ((magic == cpu_to_le32(UFS_MAGIC))
191 || (magic == cpu_to_le32(UFS2_MAGIC))
192 || (magic == cpu_to_le32(UFS_MAGIC_FEA))
193 || (magic == cpu_to_le32(UFS_MAGIC_LFN))
194 ) {
195 dbg("magic 0x%08x(le)", magic);
196 goto found;
197 }
198 }
199 return -1;
200
201 found:
202 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
203 id->type = "ufs";
204
205 return 0;
206}
diff --git a/util-linux/volume_id/util.c b/util-linux/volume_id/util.c
new file mode 100644
index 000000000..d2265c249
--- /dev/null
+++ b/util-linux/volume_id/util.c
@@ -0,0 +1,260 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count)
24{
25 unsigned i, j;
26 uint16_t c;
27
28 j = 0;
29 for (i = 0; i + 2 <= count; i += 2) {
30 if (endianess == LE)
31 c = (buf[i+1] << 8) | buf[i];
32 else
33 c = (buf[i] << 8) | buf[i+1];
34 if (c == 0) {
35 str[j] = '\0';
36 break;
37 } else if (c < 0x80) {
38 if (j+1 >= len)
39 break;
40 str[j++] = (uint8_t) c;
41 } else if (c < 0x800) {
42 if (j+2 >= len)
43 break;
44 str[j++] = (uint8_t) (0xc0 | (c >> 6));
45 str[j++] = (uint8_t) (0x80 | (c & 0x3f));
46 } else {
47 if (j+3 >= len)
48 break;
49 str[j++] = (uint8_t) (0xe0 | (c >> 12));
50 str[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
51 str[j++] = (uint8_t) (0x80 | (c & 0x3f));
52 }
53 }
54 str[j] = '\0';
55}
56
57static const char *usage_to_string(enum volume_id_usage usage_id)
58{
59 switch (usage_id) {
60 case VOLUME_ID_FILESYSTEM:
61 return "filesystem";
62 case VOLUME_ID_PARTITIONTABLE:
63 return "partitiontable";
64 case VOLUME_ID_OTHER:
65 return "other";
66 case VOLUME_ID_RAID:
67 return "raid";
68 case VOLUME_ID_DISKLABEL:
69 return "disklabel";
70 case VOLUME_ID_CRYPTO:
71 return "crypto";
72 case VOLUME_ID_UNPROBED:
73 return "unprobed";
74 case VOLUME_ID_UNUSED:
75 return "unused";
76 }
77 return NULL;
78}
79
80void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id)
81{
82 part->usage_id = usage_id;
83 part->usage = usage_to_string(usage_id);
84}
85
86void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id)
87{
88 id->usage_id = usage_id;
89 id->usage = usage_to_string(usage_id);
90}
91
92void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count)
93{
94 memcpy(id->label_raw, buf, count);
95 id->label_raw_len = count;
96}
97
98#ifdef NOT_NEEDED
99static size_t strnlen(const char *s, size_t maxlen)
100{
101 size_t i;
102 if (!maxlen) return 0;
103 if (!s) return 0;
104 for (i = 0; *s && i < maxlen; ++s) ++i;
105 return i;
106}
107#endif
108
109void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count)
110{
111 unsigned i;
112
113 memcpy(id->label, buf, count);
114
115 /* remove trailing whitespace */
116 i = strnlen(id->label, count);
117 while (i--) {
118 if (!isspace(id->label[i]))
119 break;
120 }
121 id->label[i+1] = '\0';
122}
123
124void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count)
125{
126 volume_id_set_unicode16(id->label, sizeof(id->label), buf, endianess, count);
127}
128
129void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, enum uuid_format format)
130{
131 unsigned i;
132 unsigned count = 0;
133
134 switch(format) {
135 case UUID_DOS:
136 count = 4;
137 break;
138 case UUID_NTFS:
139 case UUID_HFS:
140 count = 8;
141 break;
142 case UUID_DCE:
143 count = 16;
144 break;
145 case UUID_DCE_STRING:
146 count = 36;
147 break;
148 }
149 memcpy(id->uuid_raw, buf, count);
150 id->uuid_raw_len = count;
151
152 /* if set, create string in the same format, the native platform uses */
153 for (i = 0; i < count; i++)
154 if (buf[i] != 0)
155 goto set;
156 return;
157
158set:
159 switch(format) {
160 case UUID_DOS:
161 sprintf(id->uuid, "%02X%02X-%02X%02X",
162 buf[3], buf[2], buf[1], buf[0]);
163 break;
164 case UUID_NTFS:
165 sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
166 buf[7], buf[6], buf[5], buf[4],
167 buf[3], buf[2], buf[1], buf[0]);
168 break;
169 case UUID_HFS:
170 sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
171 buf[0], buf[1], buf[2], buf[3],
172 buf[4], buf[5], buf[6], buf[7]);
173 break;
174 case UUID_DCE:
175 sprintf(id->uuid,
176 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
177 buf[0], buf[1], buf[2], buf[3],
178 buf[4], buf[5],
179 buf[6], buf[7],
180 buf[8], buf[9],
181 buf[10], buf[11], buf[12], buf[13], buf[14],buf[15]);
182 break;
183 case UUID_DCE_STRING:
184 memcpy(id->uuid, buf, count);
185 id->uuid[count] = '\0';
186 break;
187 }
188}
189
190void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
191{
192 ssize_t buf_len;
193
194 dbg("get buffer off 0x%llx(%llu), len 0x%zx", (unsigned long long) off, (unsigned long long) off, len);
195 /* check if requested area fits in superblock buffer */
196 if (off + len <= SB_BUFFER_SIZE) {
197 if (id->sbbuf == NULL) {
198 id->sbbuf = xmalloc(SB_BUFFER_SIZE);
199 }
200
201 /* check if we need to read */
202 if ((off + len) > id->sbbuf_len) {
203 dbg("read sbbuf len:0x%llx", (unsigned long long) (off + len));
204 xlseek(id->fd, 0, SEEK_SET);
205 buf_len = full_read(id->fd, id->sbbuf, off + len);
206 if (buf_len < 0) {
207 dbg("read failed (%s)", strerror(errno));
208 return NULL;
209 }
210 dbg("got 0x%zx (%zi) bytes", buf_len, buf_len);
211 id->sbbuf_len = buf_len;
212 if (buf_len < off + len) {
213 dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len);
214 return NULL;
215 }
216 }
217
218 return &(id->sbbuf[off]);
219 }
220
221 if (len > SEEK_BUFFER_SIZE) {
222 dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
223 return NULL;
224 }
225
226 /* get seek buffer */
227 if (id->seekbuf == NULL) {
228 id->seekbuf = xmalloc(SEEK_BUFFER_SIZE);
229 }
230
231 /* check if we need to read */
232 if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
233 dbg("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len);
234 xlseek(id->fd, off, SEEK_SET);
235 buf_len = full_read(id->fd, id->seekbuf, len);
236 if (buf_len < 0) {
237 dbg("read failed (%s)", strerror(errno));
238 return NULL;
239 }
240 dbg("got 0x%zx (%zi) bytes", buf_len, buf_len);
241 id->seekbuf_off = off;
242 id->seekbuf_len = buf_len;
243 if (buf_len < len) {
244 dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len);
245 return NULL;
246 }
247 }
248
249 return &(id->seekbuf[off - id->seekbuf_off]);
250}
251
252void volume_id_free_buffer(struct volume_id *id)
253{
254 free(id->sbbuf);
255 id->sbbuf = NULL;
256 id->sbbuf_len = 0;
257 free(id->seekbuf);
258 id->seekbuf = NULL;
259 id->seekbuf_len = 0;
260}
diff --git a/util-linux/volume_id/via_raid.c b/util-linux/volume_id/via_raid.c
new file mode 100644
index 000000000..a9bd5b7b9
--- /dev/null
+++ b/util-linux/volume_id/via_raid.c
@@ -0,0 +1,68 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct via_meta {
24 uint16_t signature;
25 uint8_t version_number;
26 struct via_array {
27 uint16_t disk_bits;
28 uint8_t disk_array_ex;
29 uint32_t capacity_low;
30 uint32_t capacity_high;
31 uint32_t serial_checksum;
32 } __attribute((packed)) array;
33 uint32_t serial_checksum[8];
34 uint8_t checksum;
35} __attribute__((packed));
36
37#define VIA_SIGNATURE 0xAA55
38
39int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size)
40{
41 uint64_t meta_off;
42 struct via_meta *via;
43
44 dbg("probing at offset 0x%llx, size 0x%llx",
45 (unsigned long long) off, (unsigned long long) size);
46
47 if (size < 0x10000)
48 return -1;
49
50 meta_off = ((size / 0x200)-1) * 0x200;
51
52 via = volume_id_get_buffer(id, off + meta_off, 0x200);
53 if (via == NULL)
54 return -1;
55
56 if (via->signature != cpu_to_le16(VIA_SIGNATURE))
57 return -1;
58
59 if (via->version_number > 1)
60 return -1;
61
62 volume_id_set_usage(id, VOLUME_ID_RAID);
63 id->type_version[0] = '0' + via->version_number;
64 id->type_version[1] = '\0';
65 id->type = "via_raid_member";
66
67 return 0;
68}
diff --git a/util-linux/volume_id/volume_id.c b/util-linux/volume_id/volume_id.c
new file mode 100644
index 000000000..809884a41
--- /dev/null
+++ b/util-linux/volume_id/volume_id.c
@@ -0,0 +1,214 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23typedef int (*raid_probe_fptr)(struct volume_id *id, uint64_t off, uint64_t size);
24typedef int (*probe_fptr)(struct volume_id *id, uint64_t off);
25
26static const raid_probe_fptr raid1[] = {
27#if ENABLE_FEATURE_VOLUMEID_LINUXRAID
28 volume_id_probe_linux_raid,
29#endif
30#if ENABLE_FEATURE_VOLUMEID_ISWRAID
31 volume_id_probe_intel_software_raid,
32#endif
33#if ENABLE_FEATURE_VOLUMEID_LSIRAID
34 volume_id_probe_lsi_mega_raid,
35#endif
36#if ENABLE_FEATURE_VOLUMEID_VIARAID
37 volume_id_probe_via_raid,
38#endif
39#if ENABLE_FEATURE_VOLUMEID_SILICONRAID
40 volume_id_probe_silicon_medley_raid,
41#endif
42#if ENABLE_FEATURE_VOLUMEID_NVIDIARAID
43 volume_id_probe_nvidia_raid,
44#endif
45#if ENABLE_FEATURE_VOLUMEID_PROMISERAID
46 volume_id_probe_promise_fasttrack_raid,
47#endif
48#if ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID
49 volume_id_probe_highpoint_45x_raid,
50#endif
51};
52
53static const probe_fptr raid2[] = {
54#if ENABLE_FEATURE_VOLUMEID_LVM
55 volume_id_probe_lvm1,
56 volume_id_probe_lvm2,
57#endif
58#if ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID
59 volume_id_probe_highpoint_37x_raid,
60#endif
61#if ENABLE_FEATURE_VOLUMEID_LUKS
62 volume_id_probe_luks,
63#endif
64};
65
66/* signature in the first block, only small buffer needed */
67static const probe_fptr fs1[] = {
68#if ENABLE_FEATURE_VOLUMEID_FAT
69 volume_id_probe_vfat,
70#endif
71#if ENABLE_FEATURE_VOLUMEID_MAC
72 volume_id_probe_mac_partition_map,
73#endif
74#if ENABLE_FEATURE_VOLUMEID_XFS
75 volume_id_probe_xfs,
76#endif
77};
78
79/* fill buffer with maximum */
80static const probe_fptr fs2[] = {
81#if ENABLE_FEATURE_VOLUMEID_LINUXSWAP
82 volume_id_probe_linux_swap,
83#endif
84#if ENABLE_FEATURE_VOLUMEID_EXT
85 volume_id_probe_ext,
86#endif
87#if ENABLE_FEATURE_VOLUMEID_REISERFS
88 volume_id_probe_reiserfs,
89#endif
90#if ENABLE_FEATURE_VOLUMEID_JFS
91 volume_id_probe_jfs,
92#endif
93#if ENABLE_FEATURE_VOLUMEID_UDF
94 volume_id_probe_udf,
95#endif
96#if ENABLE_FEATURE_VOLUMEID_ISO9660
97 volume_id_probe_iso9660,
98#endif
99#if ENABLE_FEATURE_VOLUMEID_HFS
100 volume_id_probe_hfs_hfsplus,
101#endif
102#if ENABLE_FEATURE_VOLUMEID_UFS
103 volume_id_probe_ufs,
104#endif
105#if ENABLE_FEATURE_VOLUMEID_NTFS
106 volume_id_probe_ntfs,
107#endif
108#if ENABLE_FEATURE_VOLUMEID_CRAMFS
109 volume_id_probe_cramfs,
110#endif
111#if ENABLE_FEATURE_VOLUMEID_ROMFS
112 volume_id_probe_romfs,
113#endif
114#if ENABLE_FEATURE_VOLUMEID_HPFS
115 volume_id_probe_hpfs,
116#endif
117#if ENABLE_FEATURE_VOLUMEID_SYSV
118 volume_id_probe_sysv,
119#endif
120#if ENABLE_FEATURE_VOLUMEID_MINIX
121 volume_id_probe_minix,
122#endif
123#if ENABLE_FEATURE_VOLUMEID_OCFS2
124 volume_id_probe_ocfs2,
125#endif
126};
127
128int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size)
129{
130 int i;
131
132 if (id == NULL)
133 return -EINVAL;
134
135 /* probe for raid first, cause fs probes may be successful on raid members */
136 if (size) {
137 for (i = 0; i < ARRAY_SIZE(raid1); i++)
138 if (raid1[i](id, off, size) == 0)
139 goto ret;
140 }
141
142 for (i = 0; i < ARRAY_SIZE(raid2); i++)
143 if (raid2[i](id, off) == 0)
144 goto ret;
145
146 /* signature in the first block, only small buffer needed */
147 for (i = 0; i < ARRAY_SIZE(fs1); i++)
148 if (fs1[i](id, off) == 0)
149 goto ret;
150
151 /* fill buffer with maximum */
152 volume_id_get_buffer(id, 0, SB_BUFFER_SIZE);
153
154 for (i = 0; i < ARRAY_SIZE(fs2); i++)
155 if (fs2[i](id, off) == 0)
156 goto ret;
157 return -1;
158
159 ret:
160 /* If the filestystem in recognized, we free the allocated buffers,
161 otherwise they will stay in place for the possible next probe call */
162 volume_id_free_buffer(id);
163
164 return 0;
165}
166
167/* open volume by device node */
168struct volume_id *volume_id_open_node(const char *path)
169{
170 struct volume_id *id;
171 int fd;
172
173 fd = xopen(path, O_RDONLY);
174 id = xzalloc(sizeof(struct volume_id));
175 id->fd = fd;
176 ///* close fd on device close */
177 //id->fd_close = 1;
178
179 return id;
180}
181
182#ifdef UNUSED
183/* open volume by major/minor */
184struct volume_id *volume_id_open_dev_t(dev_t devt)
185{
186 struct volume_id *id;
187 char *tmp_node[VOLUME_ID_PATH_MAX];
188
189 tmp_node = xasprintf("/dev/.volume_id-%u-%u-%u",
190 (unsigned)getpid(), (unsigned)major(devt), (unsigned)minor(devt));
191
192 /* create temporary node to open block device */
193 unlink(tmp_node);
194 if (mknod(tmp_node, (S_IFBLK | 0600), devt) != 0)
195 bb_perror_msg_and_die("cannot mknod(%s)", tmp_node);
196
197 id = volume_id_open_node(tmp_node);
198 unlink(tmp_node);
199 free(tmp_node);
200 return id;
201}
202#endif
203
204void free_volume_id(struct volume_id *id)
205{
206 if (id == NULL)
207 return;
208
209 //if (id->fd_close != 0) - always true
210 close(id->fd);
211 volume_id_free_buffer(id);
212 free(id->partitions);
213 free(id);
214}
diff --git a/util-linux/volume_id/volume_id_internal.h b/util-linux/volume_id/volume_id_internal.h
new file mode 100644
index 000000000..5a38562f4
--- /dev/null
+++ b/util-linux/volume_id/volume_id_internal.h
@@ -0,0 +1,220 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "libbb.h"
22#include "volume_id.h"
23
24
25#define dbg(...) ((void)0)
26
27
28/* volume_id.h */
29
30#define VOLUME_ID_VERSION 48
31
32#define VOLUME_ID_LABEL_SIZE 64
33#define VOLUME_ID_UUID_SIZE 36
34#define VOLUME_ID_FORMAT_SIZE 32
35#define VOLUME_ID_PARTITIONS_MAX 256
36
37enum volume_id_usage {
38 VOLUME_ID_UNUSED,
39 VOLUME_ID_UNPROBED,
40 VOLUME_ID_OTHER,
41 VOLUME_ID_FILESYSTEM,
42 VOLUME_ID_PARTITIONTABLE,
43 VOLUME_ID_RAID,
44 VOLUME_ID_DISKLABEL,
45 VOLUME_ID_CRYPTO,
46};
47
48struct volume_id_partition {
49 enum volume_id_usage usage_id;
50 const char *usage;
51 const char *type;
52 uint64_t off;
53 uint64_t len;
54 uint8_t partition_type_raw;
55};
56
57struct volume_id {
58 uint8_t label_raw[VOLUME_ID_LABEL_SIZE];
59 size_t label_raw_len;
60 char label[VOLUME_ID_LABEL_SIZE+1];
61 uint8_t uuid_raw[VOLUME_ID_UUID_SIZE];
62 size_t uuid_raw_len;
63 char uuid[VOLUME_ID_UUID_SIZE+1];
64 enum volume_id_usage usage_id;
65 const char *usage;
66 const char *type;
67 char type_version[VOLUME_ID_FORMAT_SIZE];
68
69 struct volume_id_partition *partitions;
70 size_t partition_count;
71
72 int fd;
73 uint8_t *sbbuf;
74 uint8_t *seekbuf;
75 size_t sbbuf_len;
76 uint64_t seekbuf_off;
77 size_t seekbuf_len;
78// int fd_close:1;
79};
80
81struct volume_id *volume_id_open_node(const char *path);
82int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size);
83void free_volume_id(struct volume_id *id);
84
85/* util.h */
86
87/* size of superblock buffer, reiserfs block is at 64k */
88#define SB_BUFFER_SIZE 0x11000
89/* size of seek buffer, FAT cluster is 32k max */
90#define SEEK_BUFFER_SIZE 0x10000
91
92#define bswap16(x) (uint16_t) ( \
93 (((uint16_t)(x) & 0x00ffu) << 8) | \
94 (((uint16_t)(x) & 0xff00u) >> 8))
95
96#define bswap32(x) (uint32_t) ( \
97 (((uint32_t)(x) & 0xff000000u) >> 24) | \
98 (((uint32_t)(x) & 0x00ff0000u) >> 8) | \
99 (((uint32_t)(x) & 0x0000ff00u) << 8) | \
100 (((uint32_t)(x) & 0x000000ffu) << 24))
101
102#define bswap64(x) (uint64_t) ( \
103 (((uint64_t)(x) & 0xff00000000000000ull) >> 56) | \
104 (((uint64_t)(x) & 0x00ff000000000000ull) >> 40) | \
105 (((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) | \
106 (((uint64_t)(x) & 0x000000ff00000000ull) >> 8) | \
107 (((uint64_t)(x) & 0x00000000ff000000ull) << 8) | \
108 (((uint64_t)(x) & 0x0000000000ff0000ull) << 24) | \
109 (((uint64_t)(x) & 0x000000000000ff00ull) << 40) | \
110 (((uint64_t)(x) & 0x00000000000000ffull) << 56))
111
112#if BB_LITTLE_ENDIAN
113#define le16_to_cpu(x) (x)
114#define le32_to_cpu(x) (x)
115#define le64_to_cpu(x) (x)
116#define be16_to_cpu(x) bswap16(x)
117#define be32_to_cpu(x) bswap32(x)
118#define cpu_to_le16(x) (x)
119#define cpu_to_le32(x) (x)
120#define cpu_to_be32(x) bswap32(x)
121#else
122#define le16_to_cpu(x) bswap16(x)
123#define le32_to_cpu(x) bswap32(x)
124#define le64_to_cpu(x) bswap64(x)
125#define be16_to_cpu(x) (x)
126#define be32_to_cpu(x) (x)
127#define cpu_to_le16(x) bswap16(x)
128#define cpu_to_le32(x) bswap32(x)
129#define cpu_to_be32(x) (x)
130#endif
131
132enum uuid_format {
133 UUID_DCE_STRING,
134 UUID_DCE,
135 UUID_DOS,
136 UUID_NTFS,
137 UUID_HFS,
138};
139
140enum endian {
141 LE = 0,
142 BE = 1
143};
144
145void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count);
146void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id);
147void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id);
148void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count);
149void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count);
150void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count);
151void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, enum uuid_format format);
152void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len);
153void volume_id_free_buffer(struct volume_id *id);
154
155
156/* Probe routines */
157
158/* RAID */
159
160int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off);
161int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size);
162
163int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size);
164
165int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size);
166
167int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size);
168
169int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size);
170
171int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size);
172
173int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size);
174
175int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size);
176
177int volume_id_probe_lvm1(struct volume_id *id, uint64_t off);
178int volume_id_probe_lvm2(struct volume_id *id, uint64_t off);
179
180/* FS */
181
182int volume_id_probe_cramfs(struct volume_id *id, uint64_t off);
183
184int volume_id_probe_ext(struct volume_id *id, uint64_t off);
185
186int volume_id_probe_vfat(struct volume_id *id, uint64_t off);
187
188int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off);
189
190int volume_id_probe_hpfs(struct volume_id *id, uint64_t off);
191
192int volume_id_probe_iso9660(struct volume_id *id, uint64_t off);
193
194int volume_id_probe_jfs(struct volume_id *id, uint64_t off);
195
196int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off);
197
198int volume_id_probe_luks(struct volume_id *id, uint64_t off);
199
200int volume_id_probe_mac_partition_map(struct volume_id *id, uint64_t off);
201
202int volume_id_probe_minix(struct volume_id *id, uint64_t off);
203
204int volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off);
205
206int volume_id_probe_ntfs(struct volume_id *id, uint64_t off);
207
208int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off);
209
210int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off);
211
212int volume_id_probe_romfs(struct volume_id *id, uint64_t off);
213
214int volume_id_probe_sysv(struct volume_id *id, uint64_t off);
215
216int volume_id_probe_udf(struct volume_id *id, uint64_t off);
217
218int volume_id_probe_ufs(struct volume_id *id, uint64_t off);
219
220int volume_id_probe_xfs(struct volume_id *id, uint64_t off);
diff --git a/util-linux/volume_id/xfs.c b/util-linux/volume_id/xfs.c
new file mode 100644
index 000000000..343ac7015
--- /dev/null
+++ b/util-linux/volume_id/xfs.c
@@ -0,0 +1,59 @@
1/*
2 * volume_id - reads filesystem label and uuid
3 *
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "volume_id_internal.h"
22
23struct xfs_super_block {
24 uint8_t magic[4];
25 uint32_t blocksize;
26 uint64_t dblocks;
27 uint64_t rblocks;
28 uint32_t dummy1[2];
29 uint8_t uuid[16];
30 uint32_t dummy2[15];
31 uint8_t fname[12];
32 uint32_t dummy3[2];
33 uint64_t icount;
34 uint64_t ifree;
35 uint64_t fdblocks;
36} __attribute__((__packed__));
37
38int volume_id_probe_xfs(struct volume_id *id, uint64_t off)
39{
40 struct xfs_super_block *xs;
41
42 dbg("probing at offset 0x%llx", (unsigned long long) off);
43
44 xs = volume_id_get_buffer(id, off, 0x200);
45 if (xs == NULL)
46 return -1;
47
48 if (memcmp(xs->magic, "XFSB", 4) != 0)
49 return -1;
50
51 volume_id_set_label_raw(id, xs->fname, 12);
52 volume_id_set_label_string(id, xs->fname, 12);
53 volume_id_set_uuid(id, xs->uuid, UUID_DCE);
54
55 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
56 id->type = "xfs";
57
58 return 0;
59}