diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-18 21:08:49 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-18 21:08:49 +0000 |
commit | de7684a309ad20c1b889d048d741cb1dd52245f7 (patch) | |
tree | efae3387e1978cdd128ff2a922b734d0e9d0180f | |
parent | 27dd495b98a6135554b1d839fefe436ba3c6ca71 (diff) | |
download | busybox-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.
43 files changed, 4632 insertions, 20 deletions
@@ -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 | ||
456 | endif # KBUILD_EXTMOD | 457 | endif # 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 | ||
561 | static 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 | |||
574 | static void tune2fs_clean_up(void) | 560 | static 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 | |||
21 | char *get_devname_from_label(const char *spec); | ||
22 | char *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 | ||
153 | config 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 | |||
153 | config FREERAMDISK | 164 | config 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 | ||
389 | config VOLUMEID | ||
390 | bool "Routines for detecting label and uuid on common filesystems" | ||
391 | default n | ||
392 | help | ||
393 | TODO | ||
394 | |||
395 | config FEATURE_VOLUMEID_EXT | ||
396 | bool "Ext filesystem" | ||
397 | default n | ||
398 | depends on VOLUMEID | ||
399 | help | ||
400 | TODO | ||
401 | |||
402 | config FEATURE_VOLUMEID_REISERFS | ||
403 | bool "Reiser filesystem" | ||
404 | default n | ||
405 | depends on VOLUMEID | ||
406 | help | ||
407 | TODO | ||
408 | |||
409 | config FEATURE_VOLUMEID_FAT | ||
410 | bool "fat filesystem" | ||
411 | default n | ||
412 | depends on VOLUMEID | ||
413 | help | ||
414 | TODO | ||
415 | |||
416 | config FEATURE_VOLUMEID_HFS | ||
417 | bool "hfs filesystem" | ||
418 | default n | ||
419 | depends on VOLUMEID | ||
420 | help | ||
421 | TODO | ||
422 | |||
423 | config FEATURE_VOLUMEID_JFS | ||
424 | bool "jfs filesystem" | ||
425 | default n | ||
426 | depends on VOLUMEID | ||
427 | help | ||
428 | TODO | ||
429 | |||
430 | config FEATURE_VOLUMEID_UFS | ||
431 | bool "ufs filesystem" | ||
432 | default n | ||
433 | depends on VOLUMEID | ||
434 | help | ||
435 | TODO | ||
436 | |||
437 | config FEATURE_VOLUMEID_XFS | ||
438 | bool "xfs filesystem" | ||
439 | default n | ||
440 | depends on VOLUMEID | ||
441 | help | ||
442 | TODO | ||
443 | |||
444 | config FEATURE_VOLUMEID_NTFS | ||
445 | bool "ntfs filesystem" | ||
446 | default n | ||
447 | depends on VOLUMEID | ||
448 | help | ||
449 | TODO | ||
450 | |||
451 | config FEATURE_VOLUMEID_ISO9660 | ||
452 | bool "iso9660 filesystem" | ||
453 | default n | ||
454 | depends on VOLUMEID | ||
455 | help | ||
456 | TODO | ||
457 | |||
458 | config FEATURE_VOLUMEID_UDF | ||
459 | bool "udf filesystem" | ||
460 | default n | ||
461 | depends on VOLUMEID | ||
462 | help | ||
463 | TODO | ||
464 | |||
465 | config FEATURE_VOLUMEID_LUKS | ||
466 | bool "luks filesystem" | ||
467 | default n | ||
468 | depends on VOLUMEID | ||
469 | help | ||
470 | TODO | ||
471 | |||
472 | config FEATURE_VOLUMEID_LINUXSWAP | ||
473 | bool "linux swap filesystem" | ||
474 | default n | ||
475 | depends on VOLUMEID | ||
476 | help | ||
477 | TODO | ||
478 | |||
479 | config FEATURE_VOLUMEID_LVM | ||
480 | bool "lvm" | ||
481 | default n | ||
482 | depends on VOLUMEID | ||
483 | help | ||
484 | TODO | ||
485 | |||
486 | config FEATURE_VOLUMEID_CRAMFS | ||
487 | bool "cramfs filesystem" | ||
488 | default n | ||
489 | depends on VOLUMEID | ||
490 | help | ||
491 | TODO | ||
492 | |||
493 | config FEATURE_VOLUMEID_HPFS | ||
494 | bool "hpfs filesystem" | ||
495 | default n | ||
496 | depends on VOLUMEID | ||
497 | help | ||
498 | TODO | ||
499 | |||
500 | config FEATURE_VOLUMEID_ROMFS | ||
501 | bool "romfs filesystem" | ||
502 | default n | ||
503 | depends on VOLUMEID | ||
504 | help | ||
505 | TODO | ||
506 | |||
507 | config FEATURE_VOLUMEID_SYSV | ||
508 | bool "sysv filesystem" | ||
509 | default n | ||
510 | depends on VOLUMEID | ||
511 | help | ||
512 | TODO | ||
513 | |||
514 | config FEATURE_VOLUMEID_MINIX | ||
515 | bool "minix filesystem" | ||
516 | default n | ||
517 | depends on VOLUMEID | ||
518 | help | ||
519 | TODO | ||
520 | |||
521 | config FEATURE_VOLUMEID_MAC | ||
522 | bool "mac filesystem" | ||
523 | default n | ||
524 | depends on VOLUMEID | ||
525 | help | ||
526 | TODO | ||
527 | |||
528 | config FEATURE_VOLUMEID_MSDOS | ||
529 | bool "msdos filesystem" | ||
530 | default n | ||
531 | depends on VOLUMEID | ||
532 | help | ||
533 | TODO | ||
534 | |||
535 | config FEATURE_VOLUMEID_OCFS2 | ||
536 | bool "ocfs2 filesystem" | ||
537 | default n | ||
538 | depends on VOLUMEID | ||
539 | help | ||
540 | TODO | ||
541 | |||
542 | config FEATURE_VOLUMEID_HIGHPOINTRAID | ||
543 | bool "highpoint raid" | ||
544 | default n | ||
545 | depends on VOLUMEID | ||
546 | help | ||
547 | TODO | ||
548 | |||
549 | config FEATURE_VOLUMEID_ISWRAID | ||
550 | bool "intel raid" | ||
551 | default n | ||
552 | depends on VOLUMEID | ||
553 | help | ||
554 | TODO | ||
555 | |||
556 | config FEATURE_VOLUMEID_LSIRAID | ||
557 | bool "lsi raid" | ||
558 | default n | ||
559 | depends on VOLUMEID | ||
560 | help | ||
561 | TODO | ||
562 | |||
563 | config FEATURE_VOLUMEID_VIARAID | ||
564 | bool "via raid" | ||
565 | default n | ||
566 | depends on VOLUMEID | ||
567 | help | ||
568 | TODO | ||
569 | |||
570 | config FEATURE_VOLUMEID_SILICONRAID | ||
571 | bool "silicon raid" | ||
572 | default n | ||
573 | depends on VOLUMEID | ||
574 | help | ||
575 | TODO | ||
576 | |||
577 | config FEATURE_VOLUMEID_NVIDIARAID | ||
578 | bool "nvidia raid" | ||
579 | default n | ||
580 | depends on VOLUMEID | ||
581 | help | ||
582 | TODO | ||
583 | |||
584 | config FEATURE_VOLUMEID_PROMISERAID | ||
585 | bool "promise raid" | ||
586 | default n | ||
587 | depends on VOLUMEID | ||
588 | help | ||
589 | TODO | ||
590 | |||
591 | config FEATURE_VOLUMEID_LINUXRAID | ||
592 | bool "linuxraid" | ||
593 | default n | ||
594 | depends on VOLUMEID | ||
595 | help | ||
596 | TODO | ||
597 | |||
378 | config MOUNT | 598 | config 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 | ||
637 | config 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 | |||
417 | config FEATURE_MOUNT_NFS | 646 | config 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 | |||
10 | lib-$(CONFIG_FDFLUSH) +=freeramdisk.o | 10 | lib-$(CONFIG_FDFLUSH) +=freeramdisk.o |
11 | lib-$(CONFIG_FDFORMAT) +=fdformat.o | 11 | lib-$(CONFIG_FDFORMAT) +=fdformat.o |
12 | lib-$(CONFIG_FDISK) +=fdisk.o | 12 | lib-$(CONFIG_FDISK) +=fdisk.o |
13 | lib-$(CONFIG_FINDFS) +=findfs.o | ||
13 | lib-$(CONFIG_FREERAMDISK) +=freeramdisk.o | 14 | lib-$(CONFIG_FREERAMDISK) +=freeramdisk.o |
14 | lib-$(CONFIG_FSCK_MINIX) +=fsck_minix.o | 15 | lib-$(CONFIG_FSCK_MINIX) +=fsck_minix.o |
15 | lib-$(CONFIG_GETOPT) +=getopt.o | 16 | lib-$(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 | |||
14 | int findfs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | ||
15 | int 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 | ||
251 | static 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 */ |
249 | static void append_mount_options(char **oldopts, const char *newopts) | 268 | static 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 | |||
7 | lib-y:= | ||
8 | |||
9 | lib-$(CONFIG_FINDFS) += get_devname.o | ||
10 | lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o | ||
11 | |||
12 | lib-$(CONFIG_VOLUMEID) += volume_id.o util.o | ||
13 | lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o | ||
14 | lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o | ||
15 | lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o | ||
16 | lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o | ||
17 | lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o | ||
18 | lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o | ||
19 | lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o | ||
20 | lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o | ||
21 | lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o | ||
22 | lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o | ||
23 | lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o | ||
24 | lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o | ||
25 | lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o | ||
26 | lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o | ||
27 | lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o | ||
28 | lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o | ||
29 | lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o | ||
30 | lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o | ||
31 | lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o | ||
32 | lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o | ||
33 | lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o | ||
34 | lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o | ||
35 | lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o | ||
36 | lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o | ||
37 | lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o | ||
38 | lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o | ||
39 | lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o | ||
40 | lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o | ||
41 | lib-$(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 | |||
23 | struct 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 | |||
38 | int 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 | |||
23 | struct 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 | |||
46 | int 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 | |||
31 | struct 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 | |||
73 | struct 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 | |||
87 | static 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 | |||
121 | int 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 | |||
20 | static 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 */ | ||
29 | static int | ||
30 | get_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 | |||
65 | static void | ||
66 | uuidcache_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 | |||
86 | static void | ||
87 | uuidcache_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 | |||
128 | static void | ||
129 | uuidcache_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 | ||
142 | major 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 | |||
198 | static int | ||
199 | dev_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 | |||
225 | static void | ||
226 | uuidcache_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 | |||
261 | static void | ||
262 | uuidcache_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 | ||
275 | static char * | ||
276 | get_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 | |||
305 | static unsigned char | ||
306 | fromhex(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 | |||
315 | static char * | ||
316 | get_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 | |||
338 | static char * | ||
339 | get_spec_by_volume_label(const char *s, int *major, int *minor) | ||
340 | { | ||
341 | return get_spec_by_x(VOL, s, major, minor); | ||
342 | } | ||
343 | |||
344 | static 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 | |||
370 | char *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 | |||
386 | char *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 | |||
23 | struct 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 | |||
33 | struct 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 | |||
63 | struct 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 | |||
72 | struct 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 | |||
81 | struct 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 | |||
88 | struct hfsplus_extent { | ||
89 | uint32_t start_block; | ||
90 | uint32_t block_count; | ||
91 | } __attribute__((__packed__)); | ||
92 | |||
93 | #define HFSPLUS_EXTENT_COUNT 8 | ||
94 | struct 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 | |||
101 | struct 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 | |||
134 | int 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 | |||
23 | struct hpt37x_meta { | ||
24 | uint8_t filler1[32]; | ||
25 | uint32_t magic; | ||
26 | } __attribute__((packed)); | ||
27 | |||
28 | struct 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 | |||
40 | int 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 | |||
61 | int 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 | |||
23 | struct hpfs_super | ||
24 | { | ||
25 | uint8_t magic[4]; | ||
26 | uint8_t version; | ||
27 | } __attribute__((__packed__)); | ||
28 | |||
29 | #define HPFS_SUPERBLOCK_OFFSET 0x2000 | ||
30 | |||
31 | int 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 | |||
31 | struct 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 | |||
43 | struct 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 | |||
50 | int 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 | |||
23 | struct 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 | |||
34 | int 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 | |||
23 | struct 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 | |||
38 | int 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 | |||
23 | struct 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 | |||
45 | int 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 | |||
23 | struct 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 | |||
34 | int 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 | |||
68 | found: | ||
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 | |||
23 | struct lsi_meta { | ||
24 | uint8_t sig[6]; | ||
25 | } __attribute__((packed)); | ||
26 | |||
27 | #define LSI_SIGNATURE "$XIDE$" | ||
28 | |||
29 | int 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 | |||
33 | static 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 | |||
38 | struct 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 | |||
59 | int 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 | |||
23 | struct lvm1_super_block { | ||
24 | uint8_t id[2]; | ||
25 | } __attribute__((packed)); | ||
26 | |||
27 | struct 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 | |||
38 | int 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 | |||
63 | int 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 | |||
23 | struct mac_driver_desc { | ||
24 | uint8_t signature[2]; | ||
25 | uint16_t block_size; | ||
26 | uint32_t block_count; | ||
27 | } __attribute__((__packed__)); | ||
28 | |||
29 | struct 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 | |||
39 | int 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 | |||
23 | struct 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 | |||
39 | int 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 | |||
23 | struct 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 | |||
51 | int 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 | |||
23 | struct 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 | |||
50 | struct 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 | |||
63 | struct 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 | |||
75 | struct 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 | |||
87 | int 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 | |||
23 | struct 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 | |||
32 | int 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. | ||
30 | This is one has been simplified since we only care about the superblock. | ||
31 | */ | ||
32 | |||
33 | struct 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 | |||
83 | int 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 | |||
23 | struct 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 | |||
30 | int 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 | |||
24 | struct 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 | |||
40 | struct 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 | |||
51 | int 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 | |||
23 | struct romfs_super { | ||
24 | uint8_t magic[8]; | ||
25 | uint32_t size; | ||
26 | uint32_t checksum; | ||
27 | uint8_t name[0]; | ||
28 | } __attribute__((__packed__)); | ||
29 | |||
30 | int 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 | |||
23 | struct 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 | |||
44 | int 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 | |||
26 | struct 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 | |||
57 | struct 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 | |||
86 | int 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 | |||
23 | struct 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 | |||
50 | struct 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 | |||
58 | int 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 | |||
91 | blocksize: | ||
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 | |||
103 | nsr: | ||
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 | |||
122 | anchor: | ||
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 | |||
23 | struct 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 | |||
165 | int 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 | |||
23 | void 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 | |||
57 | static 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 | |||
80 | void 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 | |||
86 | void 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 | |||
92 | void 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 | ||
99 | static 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 | |||
109 | void 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 | |||
124 | void 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 | |||
129 | void 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 | |||
158 | set: | ||
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 | |||
190 | void *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 | |||
252 | void 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 | |||
23 | struct 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 | |||
39 | int 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 | |||
23 | typedef int (*raid_probe_fptr)(struct volume_id *id, uint64_t off, uint64_t size); | ||
24 | typedef int (*probe_fptr)(struct volume_id *id, uint64_t off); | ||
25 | |||
26 | static 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 | |||
53 | static 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 */ | ||
67 | static 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 */ | ||
80 | static 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 | |||
128 | int 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 */ | ||
168 | struct 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 */ | ||
184 | struct 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 | |||
204 | void 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 | |||
37 | enum 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 | |||
48 | struct 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 | |||
57 | struct 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 | |||
81 | struct volume_id *volume_id_open_node(const char *path); | ||
82 | int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size); | ||
83 | void 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 | |||
132 | enum uuid_format { | ||
133 | UUID_DCE_STRING, | ||
134 | UUID_DCE, | ||
135 | UUID_DOS, | ||
136 | UUID_NTFS, | ||
137 | UUID_HFS, | ||
138 | }; | ||
139 | |||
140 | enum endian { | ||
141 | LE = 0, | ||
142 | BE = 1 | ||
143 | }; | ||
144 | |||
145 | void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count); | ||
146 | void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id); | ||
147 | void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id); | ||
148 | void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count); | ||
149 | void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count); | ||
150 | void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count); | ||
151 | void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, enum uuid_format format); | ||
152 | void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len); | ||
153 | void volume_id_free_buffer(struct volume_id *id); | ||
154 | |||
155 | |||
156 | /* Probe routines */ | ||
157 | |||
158 | /* RAID */ | ||
159 | |||
160 | int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off); | ||
161 | int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size); | ||
162 | |||
163 | int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size); | ||
164 | |||
165 | int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size); | ||
166 | |||
167 | int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size); | ||
168 | |||
169 | int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size); | ||
170 | |||
171 | int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size); | ||
172 | |||
173 | int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size); | ||
174 | |||
175 | int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size); | ||
176 | |||
177 | int volume_id_probe_lvm1(struct volume_id *id, uint64_t off); | ||
178 | int volume_id_probe_lvm2(struct volume_id *id, uint64_t off); | ||
179 | |||
180 | /* FS */ | ||
181 | |||
182 | int volume_id_probe_cramfs(struct volume_id *id, uint64_t off); | ||
183 | |||
184 | int volume_id_probe_ext(struct volume_id *id, uint64_t off); | ||
185 | |||
186 | int volume_id_probe_vfat(struct volume_id *id, uint64_t off); | ||
187 | |||
188 | int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off); | ||
189 | |||
190 | int volume_id_probe_hpfs(struct volume_id *id, uint64_t off); | ||
191 | |||
192 | int volume_id_probe_iso9660(struct volume_id *id, uint64_t off); | ||
193 | |||
194 | int volume_id_probe_jfs(struct volume_id *id, uint64_t off); | ||
195 | |||
196 | int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off); | ||
197 | |||
198 | int volume_id_probe_luks(struct volume_id *id, uint64_t off); | ||
199 | |||
200 | int volume_id_probe_mac_partition_map(struct volume_id *id, uint64_t off); | ||
201 | |||
202 | int volume_id_probe_minix(struct volume_id *id, uint64_t off); | ||
203 | |||
204 | int volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off); | ||
205 | |||
206 | int volume_id_probe_ntfs(struct volume_id *id, uint64_t off); | ||
207 | |||
208 | int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off); | ||
209 | |||
210 | int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off); | ||
211 | |||
212 | int volume_id_probe_romfs(struct volume_id *id, uint64_t off); | ||
213 | |||
214 | int volume_id_probe_sysv(struct volume_id *id, uint64_t off); | ||
215 | |||
216 | int volume_id_probe_udf(struct volume_id *id, uint64_t off); | ||
217 | |||
218 | int volume_id_probe_ufs(struct volume_id *id, uint64_t off); | ||
219 | |||
220 | int 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 | |||
23 | struct 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 | |||
38 | int 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 | } | ||