support for mount by label (not yet tested)
Also adds findfs applet. Closes bug 1143.
This commit is contained in:
parent
27dd495b98
commit
de7684a309
1
Makefile
1
Makefile
@ -452,6 +452,7 @@ libs-y := \
|
||||
shell/ \
|
||||
sysklogd/ \
|
||||
util-linux/ \
|
||||
util-linux/volume_id/ \
|
||||
|
||||
endif # KBUILD_EXTMOD
|
||||
|
||||
|
@ -557,20 +557,6 @@ static void parse_tune2fs_options(int argc, char **argv)
|
||||
device_name = x_blkid_get_devname(argv[optind]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FINDFS
|
||||
static ATTRIBUTE_NORETURN void do_findfs(int argc, char **argv)
|
||||
{
|
||||
if ((argc != 2) ||
|
||||
(strncmp(argv[1], "LABEL=", 6) && strncmp(argv[1], "UUID=", 5)))
|
||||
bb_show_usage();
|
||||
device_name = x_blkid_get_devname(argv[1]);
|
||||
puts(device_name);
|
||||
exit(0);
|
||||
}
|
||||
#else
|
||||
#define do_findfs(x, y)
|
||||
#endif
|
||||
|
||||
static void tune2fs_clean_up(void)
|
||||
{
|
||||
if (ENABLE_FEATURE_CLEAN_UP && device_name) free(device_name);
|
||||
@ -588,9 +574,7 @@ int tune2fs_main(int argc, char **argv)
|
||||
if (ENABLE_FEATURE_CLEAN_UP)
|
||||
atexit(tune2fs_clean_up);
|
||||
|
||||
if (ENABLE_FINDFS && (applet_name[0] == 'f')) /* findfs */
|
||||
do_findfs(argc, argv); /* no return */
|
||||
else if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */
|
||||
if (ENABLE_E2LABEL && (applet_name[0] == 'e')) /* e2label */
|
||||
parse_e2label_options(argc, argv);
|
||||
else
|
||||
parse_tune2fs_options(argc, argv); /* tune2fs */
|
||||
|
@ -1029,6 +1029,13 @@ USE_FEATURE_BRCTL_FANCY("\n" \
|
||||
" -t Get only headers\n" \
|
||||
" -z Delete messages on server"
|
||||
|
||||
#define findfs_trivial_usage \
|
||||
"LABEL=label or UUID=uuid"
|
||||
#define findfs_full_usage \
|
||||
"Finds a filesystem device based on a label or UUID."
|
||||
#define findfs_example_usage \
|
||||
"$ findfs LABEL=MyDevice"
|
||||
|
||||
#define find_trivial_usage \
|
||||
"[PATH...] [EXPRESSION]"
|
||||
#define find_full_usage \
|
||||
|
22
include/volume_id.h
Normal file
22
include/volume_id.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
char *get_devname_from_label(const char *spec);
|
||||
char *get_devname_from_uuid(const char *spec);
|
@ -150,6 +150,17 @@ config FEATURE_FDISK_ADVANCED
|
||||
partition, and similarly evil things. Unless you have a very good
|
||||
reason you would be wise to leave this disabled.
|
||||
|
||||
config FINDFS
|
||||
bool "findfs"
|
||||
default n
|
||||
select VOLUMEID
|
||||
help
|
||||
This is similar to the findfs program that is part of the e2fsprogs
|
||||
package. However, the e2fsprogs version only support ext2/3. This
|
||||
version supports those in addition to FAT, swap, and ReiserFS.
|
||||
WARNING:
|
||||
With all submodules selected, it will add ~11k to busybox.
|
||||
|
||||
config FREERAMDISK
|
||||
bool "freeramdisk"
|
||||
default n
|
||||
@ -375,6 +386,215 @@ config FEATURE_USE_TERMIOS
|
||||
will be unable to determine the current screen size, and will be
|
||||
unable to move the cursor.
|
||||
|
||||
config VOLUMEID
|
||||
bool "Routines for detecting label and uuid on common filesystems"
|
||||
default n
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_EXT
|
||||
bool "Ext filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_REISERFS
|
||||
bool "Reiser filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_FAT
|
||||
bool "fat filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_HFS
|
||||
bool "hfs filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_JFS
|
||||
bool "jfs filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_UFS
|
||||
bool "ufs filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_XFS
|
||||
bool "xfs filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_NTFS
|
||||
bool "ntfs filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_ISO9660
|
||||
bool "iso9660 filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_UDF
|
||||
bool "udf filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_LUKS
|
||||
bool "luks filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_LINUXSWAP
|
||||
bool "linux swap filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_LVM
|
||||
bool "lvm"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_CRAMFS
|
||||
bool "cramfs filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_HPFS
|
||||
bool "hpfs filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_ROMFS
|
||||
bool "romfs filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_SYSV
|
||||
bool "sysv filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_MINIX
|
||||
bool "minix filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_MAC
|
||||
bool "mac filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_MSDOS
|
||||
bool "msdos filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_OCFS2
|
||||
bool "ocfs2 filesystem"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_HIGHPOINTRAID
|
||||
bool "highpoint raid"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_ISWRAID
|
||||
bool "intel raid"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_LSIRAID
|
||||
bool "lsi raid"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_VIARAID
|
||||
bool "via raid"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_SILICONRAID
|
||||
bool "silicon raid"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_NVIDIARAID
|
||||
bool "nvidia raid"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_PROMISERAID
|
||||
bool "promise raid"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config FEATURE_VOLUMEID_LINUXRAID
|
||||
bool "linuxraid"
|
||||
default n
|
||||
depends on VOLUMEID
|
||||
help
|
||||
TODO
|
||||
|
||||
config MOUNT
|
||||
bool "mount"
|
||||
default n
|
||||
@ -414,6 +634,15 @@ config FEATURE_MOUNT_HELPERS
|
||||
"sometype [-o opts] fs /mnt" if simple mount syscall fails.
|
||||
The idea is to use such virtual filesystems in /etc/fstab.
|
||||
|
||||
config FEATURE_MOUNT_LABEL
|
||||
bool " Support specifiying devices by label or UUID"
|
||||
default n
|
||||
depends on MOUNT
|
||||
select FINDFS
|
||||
help
|
||||
This allows for specifying a device by label or uuid, rather than by
|
||||
name. This feature utilizes the same functionality as findfs.
|
||||
|
||||
config FEATURE_MOUNT_NFS
|
||||
bool "Support mounting NFS file systems"
|
||||
default n
|
||||
|
@ -10,6 +10,7 @@ lib-$(CONFIG_FBSET) +=fbset.o
|
||||
lib-$(CONFIG_FDFLUSH) +=freeramdisk.o
|
||||
lib-$(CONFIG_FDFORMAT) +=fdformat.o
|
||||
lib-$(CONFIG_FDISK) +=fdisk.o
|
||||
lib-$(CONFIG_FINDFS) +=findfs.o
|
||||
lib-$(CONFIG_FREERAMDISK) +=freeramdisk.o
|
||||
lib-$(CONFIG_FSCK_MINIX) +=fsck_minix.o
|
||||
lib-$(CONFIG_GETOPT) +=getopt.o
|
||||
|
@ -781,7 +781,7 @@ create_sgilabel(void)
|
||||
|
||||
printf(msg_building_new_label, "SGI disklabel");
|
||||
|
||||
sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
|
||||
sgi_other_endian = BB_LITTLE_ENDIAN;
|
||||
res = ioctl(fd, BLKGETSIZE, &longsectors);
|
||||
if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
|
||||
g_heads = geometry.heads;
|
||||
|
38
util-linux/findfs.c
Normal file
38
util-linux/findfs.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* Support functions for mounting devices by label/uuid
|
||||
*
|
||||
* Copyright (C) 2006 by Jason Schoon <floydpink@gmail.com>
|
||||
* Some portions cribbed from e2fsprogs, util-linux, dosfstools
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
#include "volume_id.h"
|
||||
|
||||
int findfs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
||||
int findfs_main(int argc, char **argv)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
|
||||
if (argc != 2)
|
||||
bb_show_usage();
|
||||
|
||||
if (!strncmp(argv[1], "LABEL=", 6))
|
||||
tmp = get_devname_from_label(argv[1] + 6);
|
||||
else if (!strncmp(argv[1], "UUID=", 5))
|
||||
tmp = get_devname_from_uuid(argv[1] + 5);
|
||||
else if (!strncmp(argv[1], "/dev/", 5)) {
|
||||
/* Just pass a device name right through. This might aid in some scripts
|
||||
being able to call this unconditionally */
|
||||
tmp = argv[1];
|
||||
} else
|
||||
bb_show_usage();
|
||||
|
||||
if (tmp) {
|
||||
puts(tmp);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
@ -19,10 +19,13 @@
|
||||
*/
|
||||
|
||||
#include <mntent.h>
|
||||
#include "libbb.h"
|
||||
#include <syslog.h>
|
||||
#include "libbb.h"
|
||||
|
||||
/* Needed for nfs support only... */
|
||||
/* For FEATURE_MOUNT_LABEL only */
|
||||
#include "volume_id.h"
|
||||
|
||||
/* Needed for nfs support only */
|
||||
#include <sys/utsname.h>
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
@ -245,6 +248,22 @@ static int verbose_mount(const char *source, const char *target,
|
||||
#define verbose_mount(...) mount(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
static int resolve_mount_spec(char **fsname)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
|
||||
if (!strncmp(*fsname, "UUID=", 5))
|
||||
tmp = get_devname_from_uuid(*fsname + 5);
|
||||
else if (!strncmp(*fsname, "LABEL=", 6))
|
||||
tmp = get_devname_from_label(*fsname + 6);
|
||||
|
||||
if (tmp) {
|
||||
*fsname = tmp;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Append mount options to string */
|
||||
static void append_mount_options(char **oldopts, const char *newopts)
|
||||
{
|
||||
@ -1781,6 +1800,9 @@ int mount_main(int argc, char **argv)
|
||||
mtpair->mnt_dir = argv[1];
|
||||
mtpair->mnt_type = fstype;
|
||||
mtpair->mnt_opts = cmdopts;
|
||||
if (ENABLE_FEATURE_MOUNT_LABEL) {
|
||||
resolve_mount_spec(&mtpair->mnt_fsname);
|
||||
}
|
||||
rc = singlemount(mtpair, 0);
|
||||
goto clean_up;
|
||||
}
|
||||
@ -1842,6 +1864,9 @@ int mount_main(int argc, char **argv)
|
||||
|
||||
mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
|
||||
append_mount_options(&(mtcur->mnt_opts), cmdopts);
|
||||
if (ENABLE_FEATURE_MOUNT_LABEL) {
|
||||
resolve_mount_spec(&mtpair->mnt_fsname);
|
||||
}
|
||||
rc = singlemount(mtcur, 0);
|
||||
free(mtcur->mnt_opts);
|
||||
}
|
||||
@ -1884,6 +1909,9 @@ int mount_main(int argc, char **argv)
|
||||
bb_error_msg_and_die(must_be_root);
|
||||
|
||||
// Mount this thing.
|
||||
if (ENABLE_FEATURE_MOUNT_LABEL) {
|
||||
resolve_mount_spec(&mtpair->mnt_fsname);
|
||||
}
|
||||
|
||||
// NFS mounts want this to be xrealloc-able
|
||||
mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
|
||||
|
41
util-linux/volume_id/Kbuild
Normal file
41
util-linux/volume_id/Kbuild
Normal file
@ -0,0 +1,41 @@
|
||||
# Makefile for busybox
|
||||
#
|
||||
# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
|
||||
#
|
||||
# Licensed under the GPL v2, see the file LICENSE in this tarball.
|
||||
|
||||
lib-y:=
|
||||
|
||||
lib-$(CONFIG_FINDFS) += get_devname.o
|
||||
lib-$(CONFIG_FEATURE_MOUNT_LABEL) += get_devname.o
|
||||
|
||||
lib-$(CONFIG_VOLUMEID) += volume_id.o util.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_EXT) += ext.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_FAT) += fat.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_HFS) += hfs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_HIGHPOINTRAID) += highpoint.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_ISWRAID) += isw_raid.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_LSIRAID) += lsi_raid.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_VIARAID) += via_raid.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_SILICONRAID) += silicon_raid.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_NVIDIARAID) += nvidia_raid.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_PROMISERAID) += promise_raid.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_ISO9660) += iso9660.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_JFS) += jfs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_LINUXRAID) += linux_raid.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_LINUXSWAP) += linux_swap.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_LVM) += lvm.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_MAC) += mac.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_MSDOS) += msdos.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_NTFS) += ntfs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_REISERFS) += reiserfs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_UDF) += udf.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_UFS) += ufs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_XFS) += xfs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_CRAMFS) += cramfs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_HPFS) += hpfs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_ROMFS) += romfs.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_SYSV) += sysv.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_MINIX) += minix.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_LUKS) += luks.o
|
||||
lib-$(CONFIG_FEATURE_VOLUMEID_OCFS2) += ocfs2.o
|
58
util-linux/volume_id/cramfs.c
Normal file
58
util-linux/volume_id/cramfs.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct cramfs_super {
|
||||
uint8_t magic[4];
|
||||
uint32_t size;
|
||||
uint32_t flags;
|
||||
uint32_t future;
|
||||
uint8_t signature[16];
|
||||
struct cramfs_info {
|
||||
uint32_t crc;
|
||||
uint32_t edition;
|
||||
uint32_t blocks;
|
||||
uint32_t files;
|
||||
} __attribute__((__packed__)) info;
|
||||
uint8_t name[16];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
int volume_id_probe_cramfs(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct cramfs_super *cs;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
cs = volume_id_get_buffer(id, off, 0x200);
|
||||
if (cs == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(cs->magic, "\x45\x3d\xcd\x28", 4) == 0) {
|
||||
volume_id_set_label_raw(id, cs->name, 16);
|
||||
volume_id_set_label_string(id, cs->name, 16);
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "cramfs";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
71
util-linux/volume_id/ext.c
Normal file
71
util-linux/volume_id/ext.c
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct ext2_super_block {
|
||||
uint32_t inodes_count;
|
||||
uint32_t blocks_count;
|
||||
uint32_t r_blocks_count;
|
||||
uint32_t free_blocks_count;
|
||||
uint32_t free_inodes_count;
|
||||
uint32_t first_data_block;
|
||||
uint32_t log_block_size;
|
||||
uint32_t dummy3[7];
|
||||
uint8_t magic[2];
|
||||
uint16_t state;
|
||||
uint32_t dummy5[8];
|
||||
uint32_t feature_compat;
|
||||
uint32_t feature_incompat;
|
||||
uint32_t feature_ro_compat;
|
||||
uint8_t uuid[16];
|
||||
uint8_t volume_name[16];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x00000004
|
||||
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x00000008
|
||||
#define EXT_SUPERBLOCK_OFFSET 0x400
|
||||
|
||||
int volume_id_probe_ext(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct ext2_super_block *es;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
es = volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (es == NULL)
|
||||
return -1;
|
||||
|
||||
if (es->magic[0] != 0123 ||
|
||||
es->magic[1] != 0357)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
volume_id_set_label_raw(id, es->volume_name, 16);
|
||||
volume_id_set_label_string(id, es->volume_name, 16);
|
||||
volume_id_set_uuid(id, es->uuid, UUID_DCE);
|
||||
|
||||
if ((le32_to_cpu(es->feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0)
|
||||
id->type = "ext3";
|
||||
else
|
||||
id->type = "ext2";
|
||||
|
||||
return 0;
|
||||
}
|
333
util-linux/volume_id/fat.c
Normal file
333
util-linux/volume_id/fat.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
#define FAT12_MAX 0xff5
|
||||
#define FAT16_MAX 0xfff5
|
||||
#define FAT_ATTR_VOLUME_ID 0x08
|
||||
#define FAT_ATTR_DIR 0x10
|
||||
#define FAT_ATTR_LONG_NAME 0x0f
|
||||
#define FAT_ATTR_MASK 0x3f
|
||||
#define FAT_ENTRY_FREE 0xe5
|
||||
|
||||
struct vfat_super_block {
|
||||
uint8_t boot_jump[3];
|
||||
uint8_t sysid[8];
|
||||
uint16_t sector_size;
|
||||
uint8_t sectors_per_cluster;
|
||||
uint16_t reserved;
|
||||
uint8_t fats;
|
||||
uint16_t dir_entries;
|
||||
uint16_t sectors;
|
||||
uint8_t media;
|
||||
uint16_t fat_length;
|
||||
uint16_t secs_track;
|
||||
uint16_t heads;
|
||||
uint32_t hidden;
|
||||
uint32_t total_sect;
|
||||
union {
|
||||
struct fat_super_block {
|
||||
uint8_t unknown[3];
|
||||
uint8_t serno[4];
|
||||
uint8_t label[11];
|
||||
uint8_t magic[8];
|
||||
uint8_t dummy2[192];
|
||||
uint8_t pmagic[2];
|
||||
} __attribute__((__packed__)) fat;
|
||||
struct fat32_super_block {
|
||||
uint32_t fat32_length;
|
||||
uint16_t flags;
|
||||
uint8_t version[2];
|
||||
uint32_t root_cluster;
|
||||
uint16_t insfo_sector;
|
||||
uint16_t backup_boot;
|
||||
uint16_t reserved2[6];
|
||||
uint8_t unknown[3];
|
||||
uint8_t serno[4];
|
||||
uint8_t label[11];
|
||||
uint8_t magic[8];
|
||||
uint8_t dummy2[164];
|
||||
uint8_t pmagic[2];
|
||||
} __attribute__((__packed__)) fat32;
|
||||
} __attribute__((__packed__)) type;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct vfat_dir_entry {
|
||||
uint8_t name[11];
|
||||
uint8_t attr;
|
||||
uint16_t time_creat;
|
||||
uint16_t date_creat;
|
||||
uint16_t time_acc;
|
||||
uint16_t date_acc;
|
||||
uint16_t cluster_high;
|
||||
uint16_t time_write;
|
||||
uint16_t date_write;
|
||||
uint16_t cluster_low;
|
||||
uint32_t size;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
static uint8_t *get_attr_volume_id(struct vfat_dir_entry *dir, unsigned count)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* end marker */
|
||||
if (dir[i].name[0] == 0x00) {
|
||||
dbg("end of dir");
|
||||
break;
|
||||
}
|
||||
|
||||
/* empty entry */
|
||||
if (dir[i].name[0] == FAT_ENTRY_FREE)
|
||||
continue;
|
||||
|
||||
/* long name */
|
||||
if ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
|
||||
continue;
|
||||
|
||||
if ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
|
||||
/* labels do not have file data */
|
||||
if (dir[i].cluster_high != 0 || dir[i].cluster_low != 0)
|
||||
continue;
|
||||
|
||||
dbg("found ATTR_VOLUME_ID id in root dir");
|
||||
return dir[i].name;
|
||||
}
|
||||
|
||||
dbg("skip dir entry");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int volume_id_probe_vfat(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct vfat_super_block *vs;
|
||||
struct vfat_dir_entry *dir;
|
||||
uint16_t sector_size;
|
||||
uint16_t dir_entries;
|
||||
uint32_t sect_count;
|
||||
uint16_t reserved;
|
||||
uint32_t fat_size;
|
||||
uint32_t root_cluster;
|
||||
uint32_t dir_size;
|
||||
uint32_t cluster_count;
|
||||
uint32_t fat_length;
|
||||
uint64_t root_start;
|
||||
uint32_t start_data_sect;
|
||||
uint16_t root_dir_entries;
|
||||
uint8_t *buf;
|
||||
uint32_t buf_size;
|
||||
uint8_t *label = NULL;
|
||||
uint32_t next;
|
||||
int maxloop;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
vs = volume_id_get_buffer(id, off, 0x200);
|
||||
if (vs == NULL)
|
||||
return -1;
|
||||
|
||||
/* believe only that's fat, don't trust the version
|
||||
* the cluster_count will tell us
|
||||
*/
|
||||
if (memcmp(vs->sysid, "NTFS", 4) == 0)
|
||||
return -1;
|
||||
|
||||
if (memcmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
|
||||
goto valid;
|
||||
|
||||
if (memcmp(vs->type.fat32.magic, "FAT32 ", 8) == 0)
|
||||
goto valid;
|
||||
|
||||
if (memcmp(vs->type.fat.magic, "FAT16 ", 8) == 0)
|
||||
goto valid;
|
||||
|
||||
if (memcmp(vs->type.fat.magic, "MSDOS", 5) == 0)
|
||||
goto valid;
|
||||
|
||||
if (memcmp(vs->type.fat.magic, "FAT12 ", 8) == 0)
|
||||
goto valid;
|
||||
|
||||
/*
|
||||
* There are old floppies out there without a magic, so we check
|
||||
* for well known values and guess if it's a fat volume
|
||||
*/
|
||||
|
||||
/* boot jump address check */
|
||||
if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
|
||||
vs->boot_jump[0] != 0xe9)
|
||||
return -1;
|
||||
|
||||
/* heads check */
|
||||
if (vs->heads == 0)
|
||||
return -1;
|
||||
|
||||
/* cluster size check*/
|
||||
if (vs->sectors_per_cluster == 0 ||
|
||||
(vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
|
||||
return -1;
|
||||
|
||||
/* media check */
|
||||
if (vs->media < 0xf8 && vs->media != 0xf0)
|
||||
return -1;
|
||||
|
||||
/* fat count*/
|
||||
if (vs->fats != 2)
|
||||
return -1;
|
||||
|
||||
valid:
|
||||
/* sector size check */
|
||||
sector_size = le16_to_cpu(vs->sector_size);
|
||||
if (sector_size != 0x200 && sector_size != 0x400 &&
|
||||
sector_size != 0x800 && sector_size != 0x1000)
|
||||
return -1;
|
||||
|
||||
dbg("sector_size 0x%x", sector_size);
|
||||
dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
|
||||
|
||||
dir_entries = le16_to_cpu(vs->dir_entries);
|
||||
reserved = le16_to_cpu(vs->reserved);
|
||||
dbg("reserved 0x%x", reserved);
|
||||
|
||||
sect_count = le16_to_cpu(vs->sectors);
|
||||
if (sect_count == 0)
|
||||
sect_count = le32_to_cpu(vs->total_sect);
|
||||
dbg("sect_count 0x%x", sect_count);
|
||||
|
||||
fat_length = le16_to_cpu(vs->fat_length);
|
||||
if (fat_length == 0)
|
||||
fat_length = le32_to_cpu(vs->type.fat32.fat32_length);
|
||||
dbg("fat_length 0x%x", fat_length);
|
||||
|
||||
fat_size = fat_length * vs->fats;
|
||||
dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
|
||||
(sector_size-1)) / sector_size;
|
||||
dbg("dir_size 0x%x", dir_size);
|
||||
|
||||
cluster_count = sect_count - (reserved + fat_size + dir_size);
|
||||
cluster_count /= vs->sectors_per_cluster;
|
||||
dbg("cluster_count 0x%x", cluster_count);
|
||||
|
||||
if (cluster_count < FAT12_MAX) {
|
||||
strcpy(id->type_version, "FAT12");
|
||||
} else if (cluster_count < FAT16_MAX) {
|
||||
strcpy(id->type_version, "FAT16");
|
||||
} else {
|
||||
strcpy(id->type_version, "FAT32");
|
||||
goto fat32;
|
||||
}
|
||||
|
||||
/* the label may be an attribute in the root directory */
|
||||
root_start = (reserved + fat_size) * sector_size;
|
||||
dbg("root dir start 0x%llx", (unsigned long long) root_start);
|
||||
root_dir_entries = le16_to_cpu(vs->dir_entries);
|
||||
dbg("expected entries 0x%x", root_dir_entries);
|
||||
|
||||
buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
|
||||
buf = volume_id_get_buffer(id, off + root_start, buf_size);
|
||||
if (buf == NULL)
|
||||
goto found;
|
||||
|
||||
dir = (struct vfat_dir_entry*) buf;
|
||||
|
||||
label = get_attr_volume_id(dir, root_dir_entries);
|
||||
|
||||
vs = volume_id_get_buffer(id, off, 0x200);
|
||||
if (vs == NULL)
|
||||
return -1;
|
||||
|
||||
if (label != NULL && memcmp(label, "NO NAME ", 11) != 0) {
|
||||
volume_id_set_label_raw(id, label, 11);
|
||||
volume_id_set_label_string(id, label, 11);
|
||||
} else if (memcmp(vs->type.fat.label, "NO NAME ", 11) != 0) {
|
||||
volume_id_set_label_raw(id, vs->type.fat.label, 11);
|
||||
volume_id_set_label_string(id, vs->type.fat.label, 11);
|
||||
}
|
||||
volume_id_set_uuid(id, vs->type.fat.serno, UUID_DOS);
|
||||
goto found;
|
||||
|
||||
fat32:
|
||||
/* FAT32 root dir is a cluster chain like any other directory */
|
||||
buf_size = vs->sectors_per_cluster * sector_size;
|
||||
root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
|
||||
dbg("root dir cluster %u", root_cluster);
|
||||
start_data_sect = reserved + fat_size;
|
||||
|
||||
next = root_cluster;
|
||||
maxloop = 100;
|
||||
while (--maxloop) {
|
||||
uint32_t next_sect_off;
|
||||
uint64_t next_off;
|
||||
uint64_t fat_entry_off;
|
||||
int count;
|
||||
|
||||
dbg("next cluster %u", next);
|
||||
next_sect_off = (next - 2) * vs->sectors_per_cluster;
|
||||
next_off = (start_data_sect + next_sect_off) * sector_size;
|
||||
dbg("cluster offset 0x%llx", (unsigned long long) next_off);
|
||||
|
||||
/* get cluster */
|
||||
buf = volume_id_get_buffer(id, off + next_off, buf_size);
|
||||
if (buf == NULL)
|
||||
goto found;
|
||||
|
||||
dir = (struct vfat_dir_entry*) buf;
|
||||
count = buf_size / sizeof(struct vfat_dir_entry);
|
||||
dbg("expected entries 0x%x", count);
|
||||
|
||||
label = get_attr_volume_id(dir, count);
|
||||
if (label)
|
||||
break;
|
||||
|
||||
/* get FAT entry */
|
||||
fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t));
|
||||
buf = volume_id_get_buffer(id, off + fat_entry_off, buf_size);
|
||||
if (buf == NULL)
|
||||
goto found;
|
||||
|
||||
/* set next cluster */
|
||||
next = le32_to_cpu(*((uint32_t *) buf) & 0x0fffffff);
|
||||
if (next == 0)
|
||||
break;
|
||||
}
|
||||
if (maxloop == 0)
|
||||
dbg("reached maximum follow count of root cluster chain, give up");
|
||||
|
||||
vs = volume_id_get_buffer(id, off, 0x200);
|
||||
if (vs == NULL)
|
||||
return -1;
|
||||
|
||||
if (label != NULL && memcmp(label, "NO NAME ", 11) != 0) {
|
||||
volume_id_set_label_raw(id, label, 11);
|
||||
volume_id_set_label_string(id, label, 11);
|
||||
} else if (memcmp(vs->type.fat32.label, "NO NAME ", 11) != 0) {
|
||||
volume_id_set_label_raw(id, vs->type.fat32.label, 11);
|
||||
volume_id_set_label_string(id, vs->type.fat32.label, 11);
|
||||
}
|
||||
volume_id_set_uuid(id, vs->type.fat32.serno, UUID_DOS);
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "vfat";
|
||||
|
||||
return 0;
|
||||
}
|
399
util-linux/volume_id/get_devname.c
Normal file
399
util-linux/volume_id/get_devname.c
Normal file
@ -0,0 +1,399 @@
|
||||
/* vi: set sw=4 ts=4: */
|
||||
/*
|
||||
* Support functions for mounting devices by label/uuid
|
||||
*
|
||||
* Copyright (C) 2006 by Jason Schoon <floydpink@gmail.com>
|
||||
* Some portions cribbed from e2fsprogs, util-linux, dosfstools
|
||||
*
|
||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
#define BLKGETSIZE64 _IOR(0x12,114,size_t)
|
||||
|
||||
#define PROC_PARTITIONS "/proc/partitions"
|
||||
#define PROC_CDROMS "/proc/sys/dev/cdrom/info"
|
||||
#define DEVLABELDIR "/dev"
|
||||
#define SYS_BLOCK "/sys/block"
|
||||
|
||||
static struct uuidCache_s {
|
||||
struct uuidCache_s *next;
|
||||
char uuid[16];
|
||||
char *device;
|
||||
char *label;
|
||||
int major, minor;
|
||||
} *uuidCache;
|
||||
|
||||
/* for now, only ext2, ext3 and xfs are supported */
|
||||
static int
|
||||
get_label_uuid(const char *device, char **label, char **uuid, int iso_only)
|
||||
{
|
||||
int rv = 1;
|
||||
uint64_t size;
|
||||
struct volume_id *vid;
|
||||
|
||||
vid = volume_id_open_node(device);
|
||||
|
||||
if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0) {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
#if ENABLE_FEATURE_VOLUMEID_ISO9660
|
||||
if (iso_only ?
|
||||
volume_id_probe_iso9660(vid, 0) != 0 :
|
||||
volume_id_probe_all(vid, 0, size) != 0) {
|
||||
goto ret;
|
||||
}
|
||||
#else
|
||||
if (volume_id_probe_all(vid, 0, size) != 0) {
|
||||
goto ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (vid->label[0] != '\0') {
|
||||
*label = xstrndup(vid->label, sizeof(vid->label));
|
||||
*uuid = xstrndup(vid->uuid, sizeof(vid->uuid));
|
||||
printf("Found label %s on %s (uuid:%s)\n", *label, device, *uuid);
|
||||
rv = 0;
|
||||
}
|
||||
ret:
|
||||
free_volume_id(vid);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
uuidcache_addentry(char * device, int major, int minor, char *label, char *uuid)
|
||||
{
|
||||
struct uuidCache_s *last;
|
||||
|
||||
if (!uuidCache) {
|
||||
last = uuidCache = xzalloc(sizeof(*uuidCache));
|
||||
} else {
|
||||
for (last = uuidCache; last->next; last = last->next)
|
||||
continue;
|
||||
last->next = xzalloc(sizeof(*uuidCache));
|
||||
last = last->next;
|
||||
}
|
||||
/*last->next = NULL; - xzalloc did it*/
|
||||
last->label = label;
|
||||
last->device = device;
|
||||
last->major = major;
|
||||
last->minor = minor;
|
||||
memcpy(last->uuid, uuid, sizeof(last->uuid));
|
||||
}
|
||||
|
||||
static void
|
||||
uuidcache_check_device(const char *device_name, int ma, int mi, int iso_only)
|
||||
{
|
||||
char device[110];
|
||||
char *uuid = NULL, *label = NULL;
|
||||
char *ptr;
|
||||
char *deviceDir = NULL;
|
||||
int mustRemove = 0;
|
||||
int mustRemoveDir = 0;
|
||||
int i;
|
||||
|
||||
sprintf(device, "%s/%s", DEVLABELDIR, device_name);
|
||||
if (access(device, F_OK)) {
|
||||
ptr = device;
|
||||
i = 0;
|
||||
while (*ptr)
|
||||
if (*ptr++ == '/')
|
||||
i++;
|
||||
if (i > 2) {
|
||||
deviceDir = alloca(strlen(device) + 1);
|
||||
strcpy(deviceDir, device);
|
||||
ptr = deviceDir + (strlen(device) - 1);
|
||||
while (*ptr != '/')
|
||||
*ptr-- = '\0';
|
||||
if (mkdir(deviceDir, 0644)) {
|
||||
printf("mkdir: cannot create directory %s: %d\n", deviceDir, errno);
|
||||
} else {
|
||||
mustRemoveDir = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mknod(device, S_IFBLK | 0600, makedev(ma, mi));
|
||||
mustRemove = 1;
|
||||
}
|
||||
if (!get_label_uuid(device, &label, &uuid, iso_only))
|
||||
uuidcache_addentry(strdup(device), ma, mi,
|
||||
label, uuid);
|
||||
|
||||
if (mustRemove) unlink(device);
|
||||
if (mustRemoveDir) rmdir(deviceDir);
|
||||
}
|
||||
|
||||
static void
|
||||
uuidcache_init_partitions(void)
|
||||
{
|
||||
char line[100];
|
||||
int ma, mi;
|
||||
unsigned long long sz;
|
||||
FILE *procpt;
|
||||
int firstPass;
|
||||
int handleOnFirst;
|
||||
char *chptr;
|
||||
|
||||
procpt = xfopen(PROC_PARTITIONS, "r");
|
||||
/*
|
||||
# cat /proc/partitions
|
||||
major minor #blocks name
|
||||
|
||||
8 0 293036184 sda
|
||||
8 1 6835626 sda1
|
||||
8 2 1 sda2
|
||||
8 5 979933 sda5
|
||||
8 6 15623181 sda6
|
||||
8 7 97659103 sda7
|
||||
8 8 171935631 sda8
|
||||
*/
|
||||
for (firstPass = 1; firstPass >= 0; firstPass--) {
|
||||
fseek(procpt, 0, SEEK_SET);
|
||||
|
||||
while (fgets(line, sizeof(line), procpt)) {
|
||||
/* The original version of this code used sscanf, but
|
||||
diet's sscanf is quite limited */
|
||||
chptr = line;
|
||||
if (*chptr != ' ') continue;
|
||||
chptr++;
|
||||
|
||||
ma = bb_strtou(chptr, &chptr, 0);
|
||||
if (ma < 0) continue;
|
||||
chptr = skip_whitespace(chptr);
|
||||
|
||||
mi = bb_strtou(chptr, &chptr, 0);
|
||||
if (mi < 0) continue;
|
||||
chptr = skip_whitespace(chptr);
|
||||
|
||||
sz = bb_strtoull(chptr, &chptr, 0);
|
||||
if ((long long)sz == -1LL) continue;
|
||||
chptr = skip_whitespace(chptr);
|
||||
|
||||
/* skip extended partitions (heuristic: size 1) */
|
||||
if (sz == 1)
|
||||
continue;
|
||||
|
||||
*strchrnul(chptr, '\n') = '\0';
|
||||
/* now chptr => device name */
|
||||
if (!chptr[0])
|
||||
continue;
|
||||
|
||||
/* look only at md devices on first pass */
|
||||
handleOnFirst = (chptr[0] == 'm' && chptr[1] == 'd');
|
||||
if (firstPass != handleOnFirst)
|
||||
continue;
|
||||
|
||||
/* heuristic: partition name ends in a digit */
|
||||
if (isdigit(chptr[strlen(chptr) - 1])) {
|
||||
uuidcache_check_device(chptr, ma, mi, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(procpt);
|
||||
}
|
||||
|
||||
static int
|
||||
dev_get_major_minor(char *device_name, int *major, int *minor)
|
||||
{
|
||||
char * dev_path;
|
||||
int fd;
|
||||
char dev[7];
|
||||
char *major_ptr, *minor_ptr;
|
||||
|
||||
dev_path = alloca(strlen(SYS_BLOCK) + strlen(device_name) + 6);
|
||||
sprintf(dev_path, "%s/%s/dev", SYS_BLOCK, device_name);
|
||||
|
||||
fd = open(dev_path, O_RDONLY);
|
||||
if (fd < 0) return 1;
|
||||
full_read(fd, dev, sizeof(dev));
|
||||
close(fd);
|
||||
|
||||
major_ptr = dev;
|
||||
minor_ptr = strchr(dev, ':');
|
||||
if (!minor_ptr) return 1;
|
||||
*minor_ptr++ = '\0';
|
||||
|
||||
*major = strtol(major_ptr, NULL, 10);
|
||||
*minor = strtol(minor_ptr, NULL, 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
uuidcache_init_cdroms(void)
|
||||
{
|
||||
char line[100];
|
||||
int ma, mi;
|
||||
FILE *proccd;
|
||||
|
||||
proccd = fopen(PROC_CDROMS, "r");
|
||||
if (!proccd) {
|
||||
static smallint warn = 0;
|
||||
if (!warn) {
|
||||
warn = 1;
|
||||
bb_error_msg("mount: could not open %s, so UUID and LABEL "
|
||||
"conversion cannot be done for CD-Roms.",
|
||||
PROC_CDROMS);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), proccd)) {
|
||||
const char *drive_name_string = "drive name:\t\t";
|
||||
if (!strncmp(line, drive_name_string, strlen(drive_name_string))) {
|
||||
char *device_name;
|
||||
device_name = strtok(line + strlen(drive_name_string), "\t\n");
|
||||
while (device_name) {
|
||||
dev_get_major_minor(device_name, &ma, &mi);
|
||||
uuidcache_check_device(device_name, ma, mi, 1);
|
||||
device_name = strtok(NULL, "\t\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(proccd);
|
||||
}
|
||||
|
||||
static void
|
||||
uuidcache_init(void)
|
||||
{
|
||||
if (uuidCache)
|
||||
return;
|
||||
|
||||
uuidcache_init_partitions();
|
||||
uuidcache_init_cdroms();
|
||||
}
|
||||
|
||||
#define UUID 1
|
||||
#define VOL 2
|
||||
|
||||
#ifdef UNUSED
|
||||
static char *
|
||||
get_spec_by_x(int n, const char *t, int * majorPtr, int * minorPtr)
|
||||
{
|
||||
struct uuidCache_s *uc;
|
||||
|
||||
uuidcache_init();
|
||||
uc = uuidCache;
|
||||
|
||||
while(uc) {
|
||||
switch (n) {
|
||||
case UUID:
|
||||
if (!memcmp(t, uc->uuid, sizeof(uc->uuid))) {
|
||||
*majorPtr = uc->major;
|
||||
*minorPtr = uc->minor;
|
||||
return uc->device;
|
||||
}
|
||||
break;
|
||||
case VOL:
|
||||
if (!strcmp(t, uc->label)) {
|
||||
*majorPtr = uc->major;
|
||||
*minorPtr = uc->minor;
|
||||
return uc->device;
|
||||
}
|
||||
break;
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
fromhex(char c)
|
||||
{
|
||||
if (isdigit(c))
|
||||
return (c - '0');
|
||||
if (islower(c))
|
||||
return (c - 'a' + 10);
|
||||
return (c - 'A' + 10);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_spec_by_uuid(const char *s, int * major, int * minor)
|
||||
{
|
||||
unsigned char uuid[16];
|
||||
int i;
|
||||
|
||||
if (strlen(s) != 36 ||
|
||||
s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
|
||||
goto bad_uuid;
|
||||
for (i=0; i<16; i++) {
|
||||
if (*s == '-') s++;
|
||||
if (!isxdigit(s[0]) || !isxdigit(s[1]))
|
||||
goto bad_uuid;
|
||||
uuid[i] = ((fromhex(s[0])<<4) | fromhex(s[1]));
|
||||
s += 2;
|
||||
}
|
||||
return get_spec_by_x(UUID, (char *)uuid, major, minor);
|
||||
|
||||
bad_uuid:
|
||||
fprintf(stderr, _("mount: bad UUID"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_spec_by_volume_label(const char *s, int *major, int *minor)
|
||||
{
|
||||
return get_spec_by_x(VOL, s, major, minor);
|
||||
}
|
||||
|
||||
static int display_uuid_cache(void)
|
||||
{
|
||||
struct uuidCache_s *u;
|
||||
size_t i;
|
||||
|
||||
uuidcache_init();
|
||||
|
||||
u = uuidCache;
|
||||
while (u) {
|
||||
printf("%s %s ", u->device, u->label);
|
||||
for (i = 0; i < sizeof(u->uuid); i++) {
|
||||
if (i == 4 || i == 6 || i == 8 || i == 10)
|
||||
printf("-");
|
||||
printf("%x", u->uuid[i] & 0xff);
|
||||
}
|
||||
printf("\n");
|
||||
u = u->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // UNUSED
|
||||
|
||||
|
||||
/* Used by mount and findfs */
|
||||
|
||||
char *get_devname_from_label(const char *spec)
|
||||
{
|
||||
struct uuidCache_s *uc;
|
||||
int spec_len = strlen(spec);
|
||||
|
||||
uuidcache_init();
|
||||
uc = uuidCache;
|
||||
while (uc) {
|
||||
if (uc->label && !strncmp(spec, uc->label, spec_len)) {
|
||||
return xstrdup(uc->device);
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *get_devname_from_uuid(const char *spec)
|
||||
{
|
||||
struct uuidCache_s *uc;
|
||||
|
||||
uuidcache_init();
|
||||
uc = uuidCache;
|
||||
while (uc) {
|
||||
if (!memcmp(spec, uc->uuid, sizeof(uc->uuid))) {
|
||||
return xstrdup(uc->device);
|
||||
}
|
||||
uc = uc->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
292
util-linux/volume_id/hfs.c
Normal file
292
util-linux/volume_id/hfs.c
Normal file
@ -0,0 +1,292 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct hfs_finder_info{
|
||||
uint32_t boot_folder;
|
||||
uint32_t start_app;
|
||||
uint32_t open_folder;
|
||||
uint32_t os9_folder;
|
||||
uint32_t reserved;
|
||||
uint32_t osx_folder;
|
||||
uint8_t id[8];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct hfs_mdb {
|
||||
uint8_t signature[2];
|
||||
uint32_t cr_date;
|
||||
uint32_t ls_Mod;
|
||||
uint16_t atrb;
|
||||
uint16_t nm_fls;
|
||||
uint16_t vbm_st;
|
||||
uint16_t alloc_ptr;
|
||||
uint16_t nm_al_blks;
|
||||
uint32_t al_blk_size;
|
||||
uint32_t clp_size;
|
||||
uint16_t al_bl_st;
|
||||
uint32_t nxt_cnid;
|
||||
uint16_t free_bks;
|
||||
uint8_t label_len;
|
||||
uint8_t label[27];
|
||||
uint32_t vol_bkup;
|
||||
uint16_t vol_seq_num;
|
||||
uint32_t wr_cnt;
|
||||
uint32_t xt_clump_size;
|
||||
uint32_t ct_clump_size;
|
||||
uint16_t num_root_dirs;
|
||||
uint32_t file_count;
|
||||
uint32_t dir_count;
|
||||
struct hfs_finder_info finder_info;
|
||||
uint8_t embed_sig[2];
|
||||
uint16_t embed_startblock;
|
||||
uint16_t embed_blockcount;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct hfsplus_bnode_descriptor {
|
||||
uint32_t next;
|
||||
uint32_t prev;
|
||||
uint8_t type;
|
||||
uint8_t height;
|
||||
uint16_t num_recs;
|
||||
uint16_t reserved;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct hfsplus_bheader_record {
|
||||
uint16_t depth;
|
||||
uint32_t root;
|
||||
uint32_t leaf_count;
|
||||
uint32_t leaf_head;
|
||||
uint32_t leaf_tail;
|
||||
uint16_t node_size;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct hfsplus_catalog_key {
|
||||
uint16_t key_len;
|
||||
uint32_t parent_id;
|
||||
uint16_t unicode_len;
|
||||
uint8_t unicode[255 * 2];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct hfsplus_extent {
|
||||
uint32_t start_block;
|
||||
uint32_t block_count;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define HFSPLUS_EXTENT_COUNT 8
|
||||
struct hfsplus_fork {
|
||||
uint64_t total_size;
|
||||
uint32_t clump_size;
|
||||
uint32_t total_blocks;
|
||||
struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct hfsplus_vol_header {
|
||||
uint8_t signature[2];
|
||||
uint16_t version;
|
||||
uint32_t attributes;
|
||||
uint32_t last_mount_vers;
|
||||
uint32_t reserved;
|
||||
uint32_t create_date;
|
||||
uint32_t modify_date;
|
||||
uint32_t backup_date;
|
||||
uint32_t checked_date;
|
||||
uint32_t file_count;
|
||||
uint32_t folder_count;
|
||||
uint32_t blocksize;
|
||||
uint32_t total_blocks;
|
||||
uint32_t free_blocks;
|
||||
uint32_t next_alloc;
|
||||
uint32_t rsrc_clump_sz;
|
||||
uint32_t data_clump_sz;
|
||||
uint32_t next_cnid;
|
||||
uint32_t write_count;
|
||||
uint64_t encodings_bmp;
|
||||
struct hfs_finder_info finder_info;
|
||||
struct hfsplus_fork alloc_file;
|
||||
struct hfsplus_fork ext_file;
|
||||
struct hfsplus_fork cat_file;
|
||||
struct hfsplus_fork attr_file;
|
||||
struct hfsplus_fork start_file;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define HFS_SUPERBLOCK_OFFSET 0x400
|
||||
#define HFS_NODE_LEAF 0xff
|
||||
#define HFSPLUS_POR_CNID 1
|
||||
|
||||
int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
unsigned blocksize;
|
||||
unsigned cat_block;
|
||||
unsigned ext_block_start;
|
||||
unsigned ext_block_count;
|
||||
int ext;
|
||||
unsigned leaf_node_head;
|
||||
unsigned leaf_node_count;
|
||||
unsigned leaf_node_size;
|
||||
unsigned leaf_block;
|
||||
uint64_t leaf_off;
|
||||
unsigned alloc_block_size;
|
||||
unsigned alloc_first_block;
|
||||
unsigned embed_first_block;
|
||||
unsigned record_count;
|
||||
struct hfsplus_vol_header *hfsplus;
|
||||
struct hfsplus_bnode_descriptor *descr;
|
||||
struct hfsplus_bheader_record *bnode;
|
||||
struct hfsplus_catalog_key *key;
|
||||
unsigned label_len;
|
||||
struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
|
||||
struct hfs_mdb *hfs;
|
||||
const uint8_t *buf;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
hfs = (struct hfs_mdb *) buf;
|
||||
if (hfs->signature[0] != 'B' || hfs->signature[1] != 'D')
|
||||
goto checkplus;
|
||||
|
||||
/* it may be just a hfs wrapper for hfs+ */
|
||||
if (memcmp(hfs->embed_sig, "H+", 2) == 0) {
|
||||
alloc_block_size = be32_to_cpu(hfs->al_blk_size);
|
||||
dbg("alloc_block_size 0x%x", alloc_block_size);
|
||||
|
||||
alloc_first_block = be16_to_cpu(hfs->al_bl_st);
|
||||
dbg("alloc_first_block 0x%x", alloc_first_block);
|
||||
|
||||
embed_first_block = be16_to_cpu(hfs->embed_startblock);
|
||||
dbg("embed_first_block 0x%x", embed_first_block);
|
||||
|
||||
off += (alloc_first_block * 512) +
|
||||
(embed_first_block * alloc_block_size);
|
||||
dbg("hfs wrapped hfs+ found at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
goto checkplus;
|
||||
}
|
||||
|
||||
if (hfs->label_len > 0 && hfs->label_len < 28) {
|
||||
volume_id_set_label_raw(id, hfs->label, hfs->label_len);
|
||||
volume_id_set_label_string(id, hfs->label, hfs->label_len) ;
|
||||
}
|
||||
|
||||
volume_id_set_uuid(id, hfs->finder_info.id, UUID_HFS);
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "hfs";
|
||||
|
||||
return 0;
|
||||
|
||||
checkplus:
|
||||
hfsplus = (struct hfsplus_vol_header *) buf;
|
||||
if (hfs->signature[0] == 'H')
|
||||
if (hfs->signature[1] == '+' || hfs->signature[1] == 'X')
|
||||
goto hfsplus;
|
||||
return -1;
|
||||
|
||||
hfsplus:
|
||||
volume_id_set_uuid(id, hfsplus->finder_info.id, UUID_HFS);
|
||||
|
||||
blocksize = be32_to_cpu(hfsplus->blocksize);
|
||||
dbg("blocksize %u", blocksize);
|
||||
|
||||
memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
|
||||
cat_block = be32_to_cpu(extents[0].start_block);
|
||||
dbg("catalog start block 0x%x", cat_block);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000);
|
||||
if (buf == NULL)
|
||||
goto found;
|
||||
|
||||
bnode = (struct hfsplus_bheader_record *)
|
||||
&buf[sizeof(struct hfsplus_bnode_descriptor)];
|
||||
|
||||
leaf_node_head = be32_to_cpu(bnode->leaf_head);
|
||||
dbg("catalog leaf node 0x%x", leaf_node_head);
|
||||
|
||||
leaf_node_size = be16_to_cpu(bnode->node_size);
|
||||
dbg("leaf node size 0x%x", leaf_node_size);
|
||||
|
||||
leaf_node_count = be32_to_cpu(bnode->leaf_count);
|
||||
dbg("leaf node count 0x%x", leaf_node_count);
|
||||
if (leaf_node_count == 0)
|
||||
goto found;
|
||||
|
||||
leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
|
||||
|
||||
/* get physical location */
|
||||
for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
|
||||
ext_block_start = be32_to_cpu(extents[ext].start_block);
|
||||
ext_block_count = be32_to_cpu(extents[ext].block_count);
|
||||
dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
|
||||
|
||||
if (ext_block_count == 0)
|
||||
goto found;
|
||||
|
||||
/* this is our extent */
|
||||
if (leaf_block < ext_block_count)
|
||||
break;
|
||||
|
||||
leaf_block -= ext_block_count;
|
||||
}
|
||||
if (ext == HFSPLUS_EXTENT_COUNT)
|
||||
goto found;
|
||||
dbg("found block in extent %i", ext);
|
||||
|
||||
leaf_off = (ext_block_start + leaf_block) * blocksize;
|
||||
|
||||
buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size);
|
||||
if (buf == NULL)
|
||||
goto found;
|
||||
|
||||
descr = (struct hfsplus_bnode_descriptor *) buf;
|
||||
dbg("descriptor type 0x%x", descr->type);
|
||||
|
||||
record_count = be16_to_cpu(descr->num_recs);
|
||||
dbg("number of records %u", record_count);
|
||||
if (record_count == 0)
|
||||
goto found;
|
||||
|
||||
if (descr->type != HFS_NODE_LEAF)
|
||||
goto found;
|
||||
|
||||
key = (struct hfsplus_catalog_key *)
|
||||
&buf[sizeof(struct hfsplus_bnode_descriptor)];
|
||||
|
||||
dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
|
||||
if (key->parent_id != cpu_to_be32(HFSPLUS_POR_CNID))
|
||||
goto found;
|
||||
|
||||
label_len = be16_to_cpu(key->unicode_len) * 2;
|
||||
dbg("label unicode16 len %i", label_len);
|
||||
volume_id_set_label_raw(id, key->unicode, label_len);
|
||||
volume_id_set_label_unicode16(id, key->unicode, BE, label_len);
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "hfsplus";
|
||||
|
||||
return 0;
|
||||
}
|
86
util-linux/volume_id/highpoint.c
Normal file
86
util-linux/volume_id/highpoint.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct hpt37x_meta {
|
||||
uint8_t filler1[32];
|
||||
uint32_t magic;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct hpt45x_meta {
|
||||
uint32_t magic;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define HPT37X_CONFIG_OFF 0x1200
|
||||
#define HPT37X_MAGIC_OK 0x5a7816f0
|
||||
#define HPT37X_MAGIC_BAD 0x5a7816fd
|
||||
|
||||
#define HPT45X_MAGIC_OK 0x5a7816f3
|
||||
#define HPT45X_MAGIC_BAD 0x5a7816fd
|
||||
|
||||
|
||||
int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct hpt37x_meta *hpt;
|
||||
uint32_t magic;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
hpt = volume_id_get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200);
|
||||
if (hpt == NULL)
|
||||
return -1;
|
||||
|
||||
magic = hpt->magic;
|
||||
if (magic != cpu_to_le32(HPT37X_MAGIC_OK) && magic != cpu_to_le32(HPT37X_MAGIC_BAD))
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "highpoint_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct hpt45x_meta *hpt;
|
||||
uint64_t meta_off;
|
||||
uint32_t magic;
|
||||
|
||||
dbg("probing at offset 0x%llx, size 0x%llx",
|
||||
(unsigned long long) off, (unsigned long long) size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-11) * 0x200;
|
||||
hpt = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (hpt == NULL)
|
||||
return -1;
|
||||
|
||||
magic = hpt->magic;
|
||||
if (magic != cpu_to_le32(HPT45X_MAGIC_OK) && magic != cpu_to_le32(HPT45X_MAGIC_BAD))
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "highpoint_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
50
util-linux/volume_id/hpfs.c
Normal file
50
util-linux/volume_id/hpfs.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct hpfs_super
|
||||
{
|
||||
uint8_t magic[4];
|
||||
uint8_t version;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define HPFS_SUPERBLOCK_OFFSET 0x2000
|
||||
|
||||
int volume_id_probe_hpfs(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct hpfs_super *hs;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
hs = volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (hs == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(hs->magic, "\x49\xe8\x95\xf9", 4) == 0) {
|
||||
sprintf(id->type_version, "%u", hs->version);
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "hpfs";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
118
util-linux/volume_id/iso9660.c
Normal file
118
util-linux/volume_id/iso9660.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
#define ISO_SUPERBLOCK_OFFSET 0x8000
|
||||
#define ISO_SECTOR_SIZE 0x800
|
||||
#define ISO_VD_OFFSET (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
|
||||
#define ISO_VD_PRIMARY 0x1
|
||||
#define ISO_VD_SUPPLEMENTARY 0x2
|
||||
#define ISO_VD_END 0xff
|
||||
#define ISO_VD_MAX 16
|
||||
|
||||
struct iso_volume_descriptor {
|
||||
uint8_t vd_type;
|
||||
uint8_t vd_id[5];
|
||||
uint8_t vd_version;
|
||||
uint8_t flags;
|
||||
uint8_t system_id[32];
|
||||
uint8_t volume_id[32];
|
||||
uint8_t unused[8];
|
||||
uint8_t space_size[8];
|
||||
uint8_t escape_sequences[8];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct high_sierra_volume_descriptor {
|
||||
uint8_t foo[8];
|
||||
uint8_t type;
|
||||
uint8_t id[4];
|
||||
uint8_t version;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
int volume_id_probe_iso9660(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
uint8_t *buf;
|
||||
struct iso_volume_descriptor *is;
|
||||
struct high_sierra_volume_descriptor *hs;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
is = (struct iso_volume_descriptor *) buf;
|
||||
|
||||
if (memcmp(is->vd_id, "CD001", 5) == 0) {
|
||||
int vd_offset;
|
||||
int i;
|
||||
|
||||
dbg("read label from PVD");
|
||||
volume_id_set_label_raw(id, is->volume_id, 32);
|
||||
volume_id_set_label_string(id, is->volume_id, 32);
|
||||
|
||||
dbg("looking for SVDs");
|
||||
vd_offset = ISO_VD_OFFSET;
|
||||
for (i = 0; i < ISO_VD_MAX; i++) {
|
||||
uint8_t svd_label[64];
|
||||
|
||||
is = volume_id_get_buffer(id, off + vd_offset, 0x200);
|
||||
if (is == NULL || is->vd_type == ISO_VD_END)
|
||||
break;
|
||||
if (is->vd_type != ISO_VD_SUPPLEMENTARY)
|
||||
continue;
|
||||
|
||||
dbg("found SVD at offset 0x%llx", (unsigned long long) (off + vd_offset));
|
||||
if (memcmp(is->escape_sequences, "%/@", 3) == 0||
|
||||
memcmp(is->escape_sequences, "%/C", 3) == 0||
|
||||
memcmp(is->escape_sequences, "%/E", 3) == 0) {
|
||||
dbg("Joliet extension found");
|
||||
volume_id_set_unicode16((char *)svd_label, sizeof(svd_label), is->volume_id, BE, 32);
|
||||
if (memcmp(id->label, svd_label, 16) == 0) {
|
||||
dbg("SVD label is identical, use the possibly longer PVD one");
|
||||
break;
|
||||
}
|
||||
|
||||
volume_id_set_label_raw(id, is->volume_id, 32);
|
||||
volume_id_set_label_string(id, svd_label, 32);
|
||||
strcpy(id->type_version, "Joliet Extension");
|
||||
goto found;
|
||||
}
|
||||
vd_offset += ISO_SECTOR_SIZE;
|
||||
}
|
||||
goto found;
|
||||
}
|
||||
|
||||
hs = (struct high_sierra_volume_descriptor *) buf;
|
||||
|
||||
if (memcmp(hs->id, "CDROM", 5) == 0) {
|
||||
strcpy(id->type_version, "High Sierra");
|
||||
goto found;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "iso9660";
|
||||
|
||||
return 0;
|
||||
}
|
58
util-linux/volume_id/isw_raid.c
Normal file
58
util-linux/volume_id/isw_raid.c
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct isw_meta {
|
||||
uint8_t sig[32];
|
||||
uint32_t check_sum;
|
||||
uint32_t mpb_size;
|
||||
uint32_t family_num;
|
||||
uint32_t generation_num;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define ISW_SIGNATURE "Intel Raid ISM Cfg Sig. "
|
||||
|
||||
|
||||
int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint64_t meta_off;
|
||||
struct isw_meta *isw;
|
||||
|
||||
dbg("probing at offset 0x%llx, size 0x%llx",
|
||||
(unsigned long long) off, (unsigned long long) size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-2) * 0x200;
|
||||
isw = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (isw == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
memcpy(id->type_version, &isw->sig[sizeof(ISW_SIGNATURE)-1], 6);
|
||||
id->type = "isw_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
59
util-linux/volume_id/jfs.c
Normal file
59
util-linux/volume_id/jfs.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct jfs_super_block {
|
||||
uint8_t magic[4];
|
||||
uint32_t version;
|
||||
uint64_t size;
|
||||
uint32_t bsize;
|
||||
uint32_t dummy1;
|
||||
uint32_t pbsize;
|
||||
uint32_t dummy2[27];
|
||||
uint8_t uuid[16];
|
||||
uint8_t label[16];
|
||||
uint8_t loguuid[16];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define JFS_SUPERBLOCK_OFFSET 0x8000
|
||||
|
||||
int volume_id_probe_jfs(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct jfs_super_block *js;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
js = volume_id_get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (js == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(js->magic, "JFS1", 4) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_label_raw(id, js->label, 16);
|
||||
volume_id_set_label_string(id, js->label, 16);
|
||||
volume_id_set_uuid(id, js->uuid, UUID_DCE);
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "jfs";
|
||||
|
||||
return 0;
|
||||
}
|
79
util-linux/volume_id/linux_raid.c
Normal file
79
util-linux/volume_id/linux_raid.c
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct mdp_super_block {
|
||||
uint32_t md_magic;
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t patch_version;
|
||||
uint32_t gvalid_words;
|
||||
uint32_t set_uuid0;
|
||||
uint32_t ctime;
|
||||
uint32_t level;
|
||||
uint32_t size;
|
||||
uint32_t nr_disks;
|
||||
uint32_t raid_disks;
|
||||
uint32_t md_minor;
|
||||
uint32_t not_persistent;
|
||||
uint32_t set_uuid1;
|
||||
uint32_t set_uuid2;
|
||||
uint32_t set_uuid3;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define MD_RESERVED_BYTES 0x10000
|
||||
#define MD_MAGIC 0xa92b4efc
|
||||
|
||||
int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint64_t sboff;
|
||||
uint8_t uuid[16];
|
||||
struct mdp_super_block *mdp;
|
||||
|
||||
dbg("probing at offset 0x%llx, size 0x%llx",
|
||||
(unsigned long long) off, (unsigned long long) size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES;
|
||||
mdp = volume_id_get_buffer(id, off + sboff, 0x800);
|
||||
if (mdp == NULL)
|
||||
return -1;
|
||||
|
||||
if (mdp->md_magic != cpu_to_le32(MD_MAGIC))
|
||||
return -1;
|
||||
|
||||
memcpy(uuid, &mdp->set_uuid0, 4);
|
||||
memcpy(&uuid[4], &mdp->set_uuid1, 12);
|
||||
volume_id_set_uuid(id, uuid, UUID_DCE);
|
||||
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u.%u",
|
||||
le32_to_cpu(mdp->major_version),
|
||||
le32_to_cpu(mdp->minor_version),
|
||||
le32_to_cpu(mdp->patch_version));
|
||||
|
||||
dbg("found raid signature");
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "linux_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
73
util-linux/volume_id/linux_swap.c
Normal file
73
util-linux/volume_id/linux_swap.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct swap_header_v1_2 {
|
||||
uint8_t bootbits[1024];
|
||||
uint32_t version;
|
||||
uint32_t last_page;
|
||||
uint32_t nr_badpages;
|
||||
uint8_t uuid[16];
|
||||
uint8_t volume_name[16];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define LARGEST_PAGESIZE 0x4000
|
||||
|
||||
int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct swap_header_v1_2 *sw;
|
||||
const uint8_t *buf;
|
||||
unsigned page;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
/* the swap signature is at the end of the PAGE_SIZE */
|
||||
for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
|
||||
buf = volume_id_get_buffer(id, off + page-10, 10);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(buf, "SWAP-SPACE", 10) == 0) {
|
||||
id->type_version[0] = '1';
|
||||
id->type_version[1] = '\0';
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (memcmp(buf, "SWAPSPACE2", 10) == 0) {
|
||||
sw = volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2));
|
||||
if (sw == NULL)
|
||||
return -1;
|
||||
id->type_version[0] = '2';
|
||||
id->type_version[1] = '\0';
|
||||
volume_id_set_label_raw(id, sw->volume_name, 16);
|
||||
volume_id_set_label_string(id, sw->volume_name, 16);
|
||||
volume_id_set_uuid(id, sw->uuid, UUID_DCE);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_OTHER);
|
||||
id->type = "swap";
|
||||
|
||||
return 0;
|
||||
}
|
52
util-linux/volume_id/lsi_raid.c
Normal file
52
util-linux/volume_id/lsi_raid.c
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct lsi_meta {
|
||||
uint8_t sig[6];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define LSI_SIGNATURE "$XIDE$"
|
||||
|
||||
int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint64_t meta_off;
|
||||
struct lsi_meta *lsi;
|
||||
|
||||
dbg("probing at offset 0x%llx, size 0x%llx",
|
||||
(unsigned long long) off, (unsigned long long) size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-1) * 0x200;
|
||||
lsi = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (lsi == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "lsi_mega_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
76
util-linux/volume_id/luks.c
Normal file
76
util-linux/volume_id/luks.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 W. Michael Petullo <mike@flyn.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
#define SECTOR_SHIFT 9
|
||||
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
|
||||
|
||||
#define LUKS_CIPHERNAME_L 32
|
||||
#define LUKS_CIPHERMODE_L 32
|
||||
#define LUKS_HASHSPEC_L 32
|
||||
#define LUKS_DIGESTSIZE 20
|
||||
#define LUKS_SALTSIZE 32
|
||||
#define LUKS_NUMKEYS 8
|
||||
|
||||
static const uint8_t LUKS_MAGIC[] = { 'L','U','K','S', 0xba, 0xbe };
|
||||
#define LUKS_MAGIC_L 6
|
||||
#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/SECTOR_SIZE+1)
|
||||
#define UUID_STRING_L 40
|
||||
|
||||
struct luks_phdr {
|
||||
uint8_t magic[LUKS_MAGIC_L];
|
||||
uint16_t version;
|
||||
uint8_t cipherName[LUKS_CIPHERNAME_L];
|
||||
uint8_t cipherMode[LUKS_CIPHERMODE_L];
|
||||
uint8_t hashSpec[LUKS_HASHSPEC_L];
|
||||
uint32_t payloadOffset;
|
||||
uint32_t keyBytes;
|
||||
uint8_t mkDigest[LUKS_DIGESTSIZE];
|
||||
uint8_t mkDigestSalt[LUKS_SALTSIZE];
|
||||
uint32_t mkDigestIterations;
|
||||
uint8_t uuid[UUID_STRING_L];
|
||||
struct {
|
||||
uint32_t active;
|
||||
uint32_t passwordIterations;
|
||||
uint8_t passwordSalt[LUKS_SALTSIZE];
|
||||
uint32_t keyMaterialOffset;
|
||||
uint32_t stripes;
|
||||
} keyblock[LUKS_NUMKEYS];
|
||||
};
|
||||
|
||||
int volume_id_probe_luks(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct luks_phdr *header;
|
||||
|
||||
header = volume_id_get_buffer(id, off, LUKS_PHDR_SIZE);
|
||||
if (header == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(header->magic, LUKS_MAGIC, LUKS_MAGIC_L))
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_CRYPTO);
|
||||
volume_id_set_uuid(id, header->uuid, UUID_DCE_STRING);
|
||||
|
||||
id->type = "crypto_LUKS";
|
||||
|
||||
return 0;
|
||||
}
|
91
util-linux/volume_id/lvm.c
Normal file
91
util-linux/volume_id/lvm.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct lvm1_super_block {
|
||||
uint8_t id[2];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct lvm2_super_block {
|
||||
uint8_t id[8];
|
||||
uint64_t sector_xl;
|
||||
uint32_t crc_xl;
|
||||
uint32_t offset_xl;
|
||||
uint8_t type[8];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define LVM1_SB_OFF 0x400
|
||||
#define LVM1_MAGIC "HM"
|
||||
|
||||
int volume_id_probe_lvm1(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct lvm1_super_block *lvm;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + LVM1_SB_OFF, 0x800);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
lvm = (struct lvm1_super_block *) buf;
|
||||
|
||||
if (memcmp(lvm->id, LVM1_MAGIC, 2) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "LVM1_member";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LVM2_LABEL_ID "LABELONE"
|
||||
#define LVM2LABEL_SCAN_SECTORS 4
|
||||
|
||||
int volume_id_probe_lvm2(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
unsigned soff;
|
||||
struct lvm2_super_block *lvm;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
|
||||
lvm = (struct lvm2_super_block *) &buf[soff];
|
||||
|
||||
if (memcmp(lvm->id, LVM2_LABEL_ID, 8) == 0)
|
||||
goto found;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
found:
|
||||
memcpy(id->type_version, lvm->type, 8);
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "LVM2_member";
|
||||
|
||||
return 0;
|
||||
}
|
125
util-linux/volume_id/mac.c
Normal file
125
util-linux/volume_id/mac.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct mac_driver_desc {
|
||||
uint8_t signature[2];
|
||||
uint16_t block_size;
|
||||
uint32_t block_count;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct mac_partition {
|
||||
uint8_t signature[2];
|
||||
uint16_t res1;
|
||||
uint32_t map_count;
|
||||
uint32_t start_block;
|
||||
uint32_t block_count;
|
||||
uint8_t name[32];
|
||||
uint8_t type[32];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
int volume_id_probe_mac_partition_map(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct mac_driver_desc *driver;
|
||||
struct mac_partition *part;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
part = (struct mac_partition *) buf;
|
||||
if ((memcmp(part->signature, "PM", 2) == 0) &&
|
||||
(memcmp(part->type, "Apple_partition_map", 19) == 0)) {
|
||||
/* linux creates an own subdevice for the map
|
||||
* just return the type if the drive header is missing */
|
||||
volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
|
||||
id->type = "mac_partition_map";
|
||||
return 0;
|
||||
}
|
||||
|
||||
driver = (struct mac_driver_desc *) buf;
|
||||
if (memcmp(driver->signature, "ER", 2) == 0) {
|
||||
/* we are on a main device, like a CD
|
||||
* just try to probe the first partition from the map */
|
||||
unsigned bsize = be16_to_cpu(driver->block_size);
|
||||
int part_count;
|
||||
int i;
|
||||
|
||||
/* get first entry of partition table */
|
||||
buf = volume_id_get_buffer(id, off + bsize, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
part = (struct mac_partition *) buf;
|
||||
if (memcmp(part->signature, "PM", 2) != 0)
|
||||
return -1;
|
||||
|
||||
part_count = be32_to_cpu(part->map_count);
|
||||
dbg("expecting %d partition entries", part_count);
|
||||
|
||||
if (id->partitions != NULL)
|
||||
free(id->partitions);
|
||||
id->partitions =
|
||||
malloc(part_count * sizeof(struct volume_id_partition));
|
||||
if (id->partitions == NULL)
|
||||
return -1;
|
||||
memset(id->partitions, 0x00, sizeof(struct volume_id_partition));
|
||||
|
||||
id->partition_count = part_count;
|
||||
|
||||
for (i = 0; i < part_count; i++) {
|
||||
uint64_t poff;
|
||||
uint64_t plen;
|
||||
|
||||
buf = volume_id_get_buffer(id, off + ((i+1) * bsize), 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
part = (struct mac_partition *) buf;
|
||||
if (memcmp(part->signature, "PM", 2) != 0)
|
||||
return -1;
|
||||
|
||||
poff = be32_to_cpu(part->start_block) * bsize;
|
||||
plen = be32_to_cpu(part->block_count) * bsize;
|
||||
dbg("found '%s' partition entry at 0x%llx, len 0x%llx",
|
||||
part->type, (unsigned long long) poff, (unsigned long long) plen);
|
||||
|
||||
id->partitions[i].off = poff;
|
||||
id->partitions[i].len = plen;
|
||||
|
||||
if (memcmp(part->type, "Apple_Free", 10) == 0) {
|
||||
volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNUSED);
|
||||
} else if (memcmp(part->type, "Apple_partition_map", 19) == 0) {
|
||||
volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_PARTITIONTABLE);
|
||||
} else {
|
||||
volume_id_set_usage_part(&id->partitions[i], VOLUME_ID_UNPROBED);
|
||||
}
|
||||
}
|
||||
volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
|
||||
id->type = "mac_partition_map";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
76
util-linux/volume_id/minix.c
Normal file
76
util-linux/volume_id/minix.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct minix_super_block
|
||||
{
|
||||
uint16_t s_ninodes;
|
||||
uint16_t s_nzones;
|
||||
uint16_t s_imap_blocks;
|
||||
uint16_t s_zmap_blocks;
|
||||
uint16_t s_firstdatazone;
|
||||
uint16_t s_log_zone_size;
|
||||
uint32_t s_max_size;
|
||||
uint16_t s_magic;
|
||||
uint16_t s_state;
|
||||
uint32_t s_zones;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define MINIX_SUPERBLOCK_OFFSET 0x400
|
||||
|
||||
int volume_id_probe_minix(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct minix_super_block *ms;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
ms = volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (ms == NULL)
|
||||
return -1;
|
||||
|
||||
if (le16_to_cpu(ms->s_magic) == 0x137f) {
|
||||
id->type_version[0] = '1';
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(ms->s_magic) == 0x1387) {
|
||||
id->type_version[0] = '1';
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(ms->s_magic) == 0x2468) {
|
||||
id->type_version[0] = '2';
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (le16_to_cpu(ms->s_magic) == 0x2478) {
|
||||
id->type_version[0] = '2';
|
||||
goto found;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
found:
|
||||
id->type_version[1] = '\0';
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "minix";
|
||||
return 0;
|
||||
}
|
196
util-linux/volume_id/msdos.c
Normal file
196
util-linux/volume_id/msdos.c
Normal file
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct msdos_partition_entry {
|
||||
uint8_t boot_ind;
|
||||
uint8_t head;
|
||||
uint8_t sector;
|
||||
uint8_t cyl;
|
||||
uint8_t sys_ind;
|
||||
uint8_t end_head;
|
||||
uint8_t end_sector;
|
||||
uint8_t end_cyl;
|
||||
uint32_t start_sect;
|
||||
uint32_t nr_sects;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define MSDOS_MAGIC "\x55\xaa"
|
||||
#define MSDOS_PARTTABLE_OFFSET 0x1be
|
||||
#define MSDOS_SIG_OFF 0x1fe
|
||||
#define BSIZE 0x200
|
||||
#define DOS_EXTENDED_PARTITION 0x05
|
||||
#define LINUX_EXTENDED_PARTITION 0x85
|
||||
#define WIN98_EXTENDED_PARTITION 0x0f
|
||||
#define LINUX_RAID_PARTITION 0xfd
|
||||
#define is_extended(type) \
|
||||
(type == DOS_EXTENDED_PARTITION || \
|
||||
type == WIN98_EXTENDED_PARTITION || \
|
||||
type == LINUX_EXTENDED_PARTITION)
|
||||
#define is_raid(type) \
|
||||
(type == LINUX_RAID_PARTITION)
|
||||
|
||||
int volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
int i;
|
||||
uint64_t poff;
|
||||
uint64_t plen;
|
||||
uint64_t extended = 0;
|
||||
uint64_t current;
|
||||
uint64_t next;
|
||||
int limit;
|
||||
int empty = 1;
|
||||
struct msdos_partition_entry *part;
|
||||
struct volume_id_partition *p;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
|
||||
return -1;
|
||||
|
||||
/* check flags on all entries for a valid partition table */
|
||||
part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (part[i].boot_ind != 0 &&
|
||||
part[i].boot_ind != 0x80)
|
||||
return -1;
|
||||
|
||||
if (part[i].nr_sects != 0)
|
||||
empty = 0;
|
||||
}
|
||||
if (empty == 1)
|
||||
return -1;
|
||||
|
||||
if (id->partitions != NULL)
|
||||
free(id->partitions);
|
||||
id->partitions = malloc(VOLUME_ID_PARTITIONS_MAX *
|
||||
sizeof(struct volume_id_partition));
|
||||
if (id->partitions == NULL)
|
||||
return -1;
|
||||
memset(id->partitions, 0x00,
|
||||
VOLUME_ID_PARTITIONS_MAX * sizeof(struct volume_id_partition));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
|
||||
plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;
|
||||
|
||||
if (plen == 0)
|
||||
continue;
|
||||
|
||||
p = &id->partitions[i];
|
||||
|
||||
p->partition_type_raw = part[i].sys_ind;
|
||||
|
||||
if (is_extended(part[i].sys_ind)) {
|
||||
dbg("found extended partition at 0x%llx", (unsigned long long) poff);
|
||||
volume_id_set_usage_part(p, VOLUME_ID_PARTITIONTABLE);
|
||||
p->type = "msdos_extended_partition";
|
||||
if (extended == 0)
|
||||
extended = off + poff;
|
||||
} else {
|
||||
dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
|
||||
part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
|
||||
|
||||
if (is_raid(part[i].sys_ind))
|
||||
volume_id_set_usage_part(p, VOLUME_ID_RAID);
|
||||
else
|
||||
volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
|
||||
}
|
||||
|
||||
p->off = off + poff;
|
||||
p->len = plen;
|
||||
id->partition_count = i+1;
|
||||
}
|
||||
|
||||
next = extended;
|
||||
current = extended;
|
||||
limit = 50;
|
||||
|
||||
/* follow extended partition chain and add data partitions */
|
||||
while (next != 0) {
|
||||
if (limit-- == 0) {
|
||||
dbg("extended chain limit reached");
|
||||
break;
|
||||
}
|
||||
|
||||
buf = volume_id_get_buffer(id, current, 0x200);
|
||||
if (buf == NULL)
|
||||
break;
|
||||
|
||||
part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
|
||||
|
||||
if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
|
||||
break;
|
||||
|
||||
next = 0;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
poff = (uint64_t) le32_to_cpu(part[i].start_sect) * BSIZE;
|
||||
plen = (uint64_t) le32_to_cpu(part[i].nr_sects) * BSIZE;
|
||||
|
||||
if (plen == 0)
|
||||
continue;
|
||||
|
||||
if (is_extended(part[i].sys_ind)) {
|
||||
dbg("found extended partition at 0x%llx", (unsigned long long) poff);
|
||||
if (next == 0)
|
||||
next = extended + poff;
|
||||
} else {
|
||||
dbg("found 0x%x data partition at 0x%llx, len 0x%llx",
|
||||
part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen);
|
||||
|
||||
/* we always start at the 5th entry */
|
||||
while (id->partition_count < 4)
|
||||
volume_id_set_usage_part(&id->partitions[id->partition_count++], VOLUME_ID_UNUSED);
|
||||
|
||||
p = &id->partitions[id->partition_count];
|
||||
|
||||
if (is_raid(part[i].sys_ind))
|
||||
volume_id_set_usage_part(p, VOLUME_ID_RAID);
|
||||
else
|
||||
volume_id_set_usage_part(p, VOLUME_ID_UNPROBED);
|
||||
|
||||
p->off = current + poff;
|
||||
p->len = plen;
|
||||
id->partition_count++;
|
||||
|
||||
p->partition_type_raw = part[i].sys_ind;
|
||||
|
||||
if (id->partition_count >= VOLUME_ID_PARTITIONS_MAX) {
|
||||
dbg("too many partitions");
|
||||
next = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_PARTITIONTABLE);
|
||||
id->type = "msdos_partition_table";
|
||||
|
||||
return 0;
|
||||
}
|
193
util-linux/volume_id/ntfs.c
Normal file
193
util-linux/volume_id/ntfs.c
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct ntfs_super_block {
|
||||
uint8_t jump[3];
|
||||
uint8_t oem_id[8];
|
||||
uint16_t bytes_per_sector;
|
||||
uint8_t sectors_per_cluster;
|
||||
uint16_t reserved_sectors;
|
||||
uint8_t fats;
|
||||
uint16_t root_entries;
|
||||
uint16_t sectors;
|
||||
uint8_t media_type;
|
||||
uint16_t sectors_per_fat;
|
||||
uint16_t sectors_per_track;
|
||||
uint16_t heads;
|
||||
uint32_t hidden_sectors;
|
||||
uint32_t large_sectors;
|
||||
uint16_t unused[2];
|
||||
uint64_t number_of_sectors;
|
||||
uint64_t mft_cluster_location;
|
||||
uint64_t mft_mirror_cluster_location;
|
||||
int8_t cluster_per_mft_record;
|
||||
uint8_t reserved1[3];
|
||||
int8_t cluster_per_index_record;
|
||||
uint8_t reserved2[3];
|
||||
uint8_t volume_serial[8];
|
||||
uint16_t checksum;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct master_file_table_record {
|
||||
uint8_t magic[4];
|
||||
uint16_t usa_ofs;
|
||||
uint16_t usa_count;
|
||||
uint64_t lsn;
|
||||
uint16_t sequence_number;
|
||||
uint16_t link_count;
|
||||
uint16_t attrs_offset;
|
||||
uint16_t flags;
|
||||
uint32_t bytes_in_use;
|
||||
uint32_t bytes_allocated;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct file_attribute {
|
||||
uint32_t type;
|
||||
uint32_t len;
|
||||
uint8_t non_resident;
|
||||
uint8_t name_len;
|
||||
uint16_t name_offset;
|
||||
uint16_t flags;
|
||||
uint16_t instance;
|
||||
uint32_t value_len;
|
||||
uint16_t value_offset;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct volume_info {
|
||||
uint64_t reserved;
|
||||
uint8_t major_ver;
|
||||
uint8_t minor_ver;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define MFT_RECORD_VOLUME 3
|
||||
#define MFT_RECORD_ATTR_VOLUME_NAME 0x60
|
||||
#define MFT_RECORD_ATTR_VOLUME_INFO 0x70
|
||||
#define MFT_RECORD_ATTR_OBJECT_ID 0x40
|
||||
#define MFT_RECORD_ATTR_END 0xffffffffu
|
||||
|
||||
int volume_id_probe_ntfs(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
unsigned sector_size;
|
||||
unsigned cluster_size;
|
||||
uint64_t mft_cluster;
|
||||
uint64_t mft_off;
|
||||
unsigned mft_record_size;
|
||||
unsigned attr_type;
|
||||
unsigned attr_off;
|
||||
unsigned attr_len;
|
||||
unsigned val_off;
|
||||
unsigned val_len;
|
||||
struct master_file_table_record *mftr;
|
||||
struct ntfs_super_block *ns;
|
||||
const uint8_t *buf;
|
||||
const uint8_t *val;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
ns = volume_id_get_buffer(id, off, 0x200);
|
||||
if (ns == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(ns->oem_id, "NTFS", 4) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_uuid(id, ns->volume_serial, UUID_NTFS);
|
||||
|
||||
sector_size = le16_to_cpu(ns->bytes_per_sector);
|
||||
cluster_size = ns->sectors_per_cluster * sector_size;
|
||||
mft_cluster = le64_to_cpu(ns->mft_cluster_location);
|
||||
mft_off = mft_cluster * cluster_size;
|
||||
|
||||
if (ns->cluster_per_mft_record < 0)
|
||||
/* size = -log2(mft_record_size); normally 1024 Bytes */
|
||||
mft_record_size = 1 << -ns->cluster_per_mft_record;
|
||||
else
|
||||
mft_record_size = ns->cluster_per_mft_record * cluster_size;
|
||||
|
||||
dbg("sectorsize 0x%x", sector_size);
|
||||
dbg("clustersize 0x%x", cluster_size);
|
||||
dbg("mftcluster %llu", (unsigned long long) mft_cluster);
|
||||
dbg("mftoffset 0x%llx", (unsigned long long) mft_off);
|
||||
dbg("cluster per mft_record %i", ns->cluster_per_mft_record);
|
||||
dbg("mft record size %i", mft_record_size);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
|
||||
mft_record_size);
|
||||
if (buf == NULL)
|
||||
goto found;
|
||||
|
||||
mftr = (struct master_file_table_record*) buf;
|
||||
|
||||
dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
|
||||
if (memcmp(mftr->magic, "FILE", 4) != 0)
|
||||
goto found;
|
||||
|
||||
attr_off = le16_to_cpu(mftr->attrs_offset);
|
||||
dbg("file $Volume's attributes are at offset %i", attr_off);
|
||||
|
||||
while (1) {
|
||||
struct file_attribute *attr;
|
||||
|
||||
attr = (struct file_attribute*) &buf[attr_off];
|
||||
attr_type = le32_to_cpu(attr->type);
|
||||
attr_len = le16_to_cpu(attr->len);
|
||||
val_off = le16_to_cpu(attr->value_offset);
|
||||
val_len = le32_to_cpu(attr->value_len);
|
||||
attr_off += attr_len;
|
||||
|
||||
if (attr_len == 0)
|
||||
break;
|
||||
|
||||
if (attr_off >= mft_record_size)
|
||||
break;
|
||||
|
||||
if (attr_type == MFT_RECORD_ATTR_END)
|
||||
break;
|
||||
|
||||
dbg("found attribute type 0x%x, len %i, at offset %i",
|
||||
attr_type, attr_len, attr_off);
|
||||
|
||||
if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
|
||||
struct volume_info *info;
|
||||
dbg("found info, len %i", val_len);
|
||||
info = (struct volume_info*) (((uint8_t *) attr) + val_off);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1,
|
||||
"%u.%u", info->major_ver, info->minor_ver);
|
||||
}
|
||||
|
||||
if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
|
||||
dbg("found label, len %i", val_len);
|
||||
if (val_len > VOLUME_ID_LABEL_SIZE)
|
||||
val_len = VOLUME_ID_LABEL_SIZE;
|
||||
|
||||
val = ((uint8_t *) attr) + val_off;
|
||||
volume_id_set_label_raw(id, val, val_len);
|
||||
volume_id_set_label_unicode16(id, val, LE, val_len);
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "ntfs";
|
||||
|
||||
return 0;
|
||||
}
|
56
util-linux/volume_id/nvidia_raid.c
Normal file
56
util-linux/volume_id/nvidia_raid.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct nvidia_meta {
|
||||
uint8_t vendor[8];
|
||||
uint32_t size;
|
||||
uint32_t chksum;
|
||||
uint16_t version;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define NVIDIA_SIGNATURE "NVIDIA"
|
||||
|
||||
int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint64_t meta_off;
|
||||
struct nvidia_meta *nv;
|
||||
|
||||
dbg("probing at offset 0x%llx, size 0x%llx",
|
||||
(unsigned long long) off, (unsigned long long) size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-2) * 0x200;
|
||||
nv = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (nv == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u", le16_to_cpu(nv->version));
|
||||
id->type = "nvidia_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
105
util-linux/volume_id/ocfs2.c
Normal file
105
util-linux/volume_id/ocfs2.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) Andre Masella <andre@masella.no-ip.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
/* All these values are taken from ocfs2-tools's ocfs2_fs.h */
|
||||
#define OCFS2_VOL_UUID_LEN 16
|
||||
#define OCFS2_MAX_VOL_LABEL_LEN 64
|
||||
#define OCFS2_SUPERBLOCK_OFFSET 0x2000
|
||||
|
||||
|
||||
/* This is the superblock. The OCFS2 header files have structs in structs.
|
||||
This is one has been simplified since we only care about the superblock.
|
||||
*/
|
||||
|
||||
struct ocfs2_super_block {
|
||||
uint8_t i_signature[8]; /* Signature for validation */
|
||||
uint32_t i_generation; /* Generation number */
|
||||
int16_t i_suballoc_slot; /* Slot suballocator this inode belongs to */
|
||||
uint16_t i_suballoc_bit; /* Bit offset in suballocator block group */
|
||||
uint32_t i_reserved0;
|
||||
uint32_t i_clusters; /* Cluster count */
|
||||
uint32_t i_uid; /* Owner UID */
|
||||
uint32_t i_gid; /* Owning GID */
|
||||
uint64_t i_size; /* Size in bytes */
|
||||
uint16_t i_mode; /* File mode */
|
||||
uint16_t i_links_count; /* Links count */
|
||||
uint32_t i_flags; /* File flags */
|
||||
uint64_t i_atime; /* Access time */
|
||||
uint64_t i_ctime; /* Creation time */
|
||||
uint64_t i_mtime; /* Modification time */
|
||||
uint64_t i_dtime; /* Deletion time */
|
||||
uint64_t i_blkno; /* Offset on disk, in blocks */
|
||||
uint64_t i_last_eb_blk; /* Pointer to last extent block */
|
||||
uint32_t i_fs_generation; /* Generation per fs-instance */
|
||||
uint32_t i_atime_nsec;
|
||||
uint32_t i_ctime_nsec;
|
||||
uint32_t i_mtime_nsec;
|
||||
uint64_t i_reserved1[9];
|
||||
uint64_t i_pad1; /* Generic way to refer to this 64bit union */
|
||||
/* Normally there is a union of the different block types, but we only care about the superblock. */
|
||||
uint16_t s_major_rev_level;
|
||||
uint16_t s_minor_rev_level;
|
||||
uint16_t s_mnt_count;
|
||||
int16_t s_max_mnt_count;
|
||||
uint16_t s_state; /* File system state */
|
||||
uint16_t s_errors; /* Behaviour when detecting errors */
|
||||
uint32_t s_checkinterval; /* Max time between checks */
|
||||
uint64_t s_lastcheck; /* Time of last check */
|
||||
uint32_t s_creator_os; /* OS */
|
||||
uint32_t s_feature_compat; /* Compatible feature set */
|
||||
uint32_t s_feature_incompat; /* Incompatible feature set */
|
||||
uint32_t s_feature_ro_compat; /* Readonly-compatible feature set */
|
||||
uint64_t s_root_blkno; /* Offset, in blocks, of root directory dinode */
|
||||
uint64_t s_system_dir_blkno; /* Offset, in blocks, of system directory dinode */
|
||||
uint32_t s_blocksize_bits; /* Blocksize for this fs */
|
||||
uint32_t s_clustersize_bits; /* Clustersize for this fs */
|
||||
uint16_t s_max_slots; /* Max number of simultaneous mounts before tunefs required */
|
||||
uint16_t s_reserved1;
|
||||
uint32_t s_reserved2;
|
||||
uint64_t s_first_cluster_group; /* Block offset of 1st cluster group header */
|
||||
uint8_t s_label[OCFS2_MAX_VOL_LABEL_LEN]; /* Label for mounting, etc. */
|
||||
uint8_t s_uuid[OCFS2_VOL_UUID_LEN]; /* 128-bit uuid */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct ocfs2_super_block *os;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
os = volume_id_get_buffer(id, off + OCFS2_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (os == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(os->i_signature, "OCFSV2", 6) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
volume_id_set_label_raw(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ?
|
||||
OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE);
|
||||
volume_id_set_label_string(id, os->s_label, OCFS2_MAX_VOL_LABEL_LEN < VOLUME_ID_LABEL_SIZE ?
|
||||
OCFS2_MAX_VOL_LABEL_LEN : VOLUME_ID_LABEL_SIZE);
|
||||
volume_id_set_uuid(id, os->s_uuid, UUID_DCE);
|
||||
id->type = "ocfs2";
|
||||
return 0;
|
||||
}
|
63
util-linux/volume_id/promise_raid.c
Normal file
63
util-linux/volume_id/promise_raid.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct promise_meta {
|
||||
uint8_t sig[24];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define PDC_CONFIG_OFF 0x1200
|
||||
#define PDC_SIGNATURE "Promise Technology, Inc."
|
||||
|
||||
int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
static const unsigned short sectors[] = {
|
||||
63, 255, 256, 16, 399
|
||||
};
|
||||
|
||||
struct promise_meta *pdc;
|
||||
unsigned i;
|
||||
|
||||
dbg("probing at offset 0x%llx, size 0x%llx",
|
||||
(unsigned long long) off, (unsigned long long) size);
|
||||
|
||||
if (size < 0x40000)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sectors); i++) {
|
||||
uint64_t meta_off;
|
||||
|
||||
meta_off = ((size / 0x200) - sectors[i]) * 0x200;
|
||||
pdc = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (pdc == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(pdc->sig, PDC_SIGNATURE, sizeof(PDC_SIGNATURE)-1) == 0)
|
||||
goto found;
|
||||
}
|
||||
return -1;
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "promise_fasttrack_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
105
util-linux/volume_id/reiserfs.c
Normal file
105
util-linux/volume_id/reiserfs.c
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
* Copyright (C) 2005 Tobias Klauser <tklauser@access.unizh.ch>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct reiserfs_super_block {
|
||||
uint32_t blocks_count;
|
||||
uint32_t free_blocks;
|
||||
uint32_t root_block;
|
||||
uint32_t journal_block;
|
||||
uint32_t journal_dev;
|
||||
uint32_t orig_journal_size;
|
||||
uint32_t dummy2[5];
|
||||
uint16_t blocksize;
|
||||
uint16_t dummy3[3];
|
||||
uint8_t magic[12];
|
||||
uint32_t dummy4[5];
|
||||
uint8_t uuid[16];
|
||||
uint8_t label[16];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct reiser4_super_block {
|
||||
uint8_t magic[16];
|
||||
uint16_t dummy[2];
|
||||
uint8_t uuid[16];
|
||||
uint8_t label[16];
|
||||
uint64_t dummy2;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define REISERFS1_SUPERBLOCK_OFFSET 0x2000
|
||||
#define REISERFS_SUPERBLOCK_OFFSET 0x10000
|
||||
|
||||
int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct reiserfs_super_block *rs;
|
||||
struct reiser4_super_block *rs4;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
rs = volume_id_get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (rs == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(rs->magic, "ReIsErFs", 8) == 0) {
|
||||
strcpy(id->type_version, "3.5");
|
||||
goto found;
|
||||
}
|
||||
if (memcmp(rs->magic, "ReIsEr2Fs", 9) == 0) {
|
||||
strcpy(id->type_version, "3.6");
|
||||
goto found_label;
|
||||
}
|
||||
if (memcmp(rs->magic, "ReIsEr3Fs", 9) == 0) {
|
||||
strcpy(id->type_version, "JR");
|
||||
goto found_label;
|
||||
}
|
||||
|
||||
rs4 = (struct reiser4_super_block *) rs;
|
||||
if (memcmp(rs4->magic, "ReIsEr4", 7) == 0) {
|
||||
strcpy(id->type_version, "4");
|
||||
volume_id_set_label_raw(id, rs4->label, 16);
|
||||
volume_id_set_label_string(id, rs4->label, 16);
|
||||
volume_id_set_uuid(id, rs4->uuid, UUID_DCE);
|
||||
goto found;
|
||||
}
|
||||
|
||||
rs = volume_id_get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (rs == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(rs->magic, "ReIsErFs", 8) == 0) {
|
||||
strcpy(id->type_version, "3.5");
|
||||
goto found;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
found_label:
|
||||
volume_id_set_label_raw(id, rs->label, 16);
|
||||
volume_id_set_label_string(id, rs->label, 16);
|
||||
volume_id_set_uuid(id, rs->uuid, UUID_DCE);
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "reiserfs";
|
||||
|
||||
return 0;
|
||||
}
|
54
util-linux/volume_id/romfs.c
Normal file
54
util-linux/volume_id/romfs.c
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct romfs_super {
|
||||
uint8_t magic[8];
|
||||
uint32_t size;
|
||||
uint32_t checksum;
|
||||
uint8_t name[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
int volume_id_probe_romfs(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct romfs_super *rfs;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
rfs = volume_id_get_buffer(id, off, 0x200);
|
||||
if (rfs == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(rfs->magic, "-rom1fs-", 4) == 0) {
|
||||
size_t len = strlen((char *)rfs->name);
|
||||
|
||||
if (len) {
|
||||
volume_id_set_label_raw(id, rfs->name, len);
|
||||
volume_id_set_label_string(id, rfs->name, len);
|
||||
}
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "romfs";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
69
util-linux/volume_id/silicon_raid.c
Normal file
69
util-linux/volume_id/silicon_raid.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct silicon_meta {
|
||||
uint8_t unknown0[0x2E];
|
||||
uint8_t ascii_version[0x36 - 0x2E];
|
||||
uint8_t diskname[0x56 - 0x36];
|
||||
uint8_t unknown1[0x60 - 0x56];
|
||||
uint32_t magic;
|
||||
uint32_t unknown1a[0x6C - 0x64];
|
||||
uint32_t array_sectors_low;
|
||||
uint32_t array_sectors_high;
|
||||
uint8_t unknown2[0x78 - 0x74];
|
||||
uint32_t thisdisk_sectors;
|
||||
uint8_t unknown3[0x100 - 0x7C];
|
||||
uint8_t unknown4[0x104 - 0x100];
|
||||
uint16_t product_id;
|
||||
uint16_t vendor_id;
|
||||
uint16_t minor_ver;
|
||||
uint16_t major_ver;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SILICON_MAGIC 0x2F000000
|
||||
|
||||
int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint64_t meta_off;
|
||||
struct silicon_meta *sil;
|
||||
|
||||
dbg("probing at offset 0x%llx, size 0x%llx",
|
||||
(unsigned long long) off, (unsigned long long) size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-1) * 0x200;
|
||||
sil = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (sil == NULL)
|
||||
return -1;
|
||||
|
||||
if (sil->magic != cpu_to_le32(SILICON_MAGIC))
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u",
|
||||
le16_to_cpu(sil->major_ver), le16_to_cpu(sil->minor_ver));
|
||||
id->type = "silicon_medley_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
125
util-linux/volume_id/sysv.c
Normal file
125
util-linux/volume_id/sysv.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
#define SYSV_NICINOD 100
|
||||
#define SYSV_NICFREE 50
|
||||
|
||||
struct sysv_super
|
||||
{
|
||||
uint16_t s_isize;
|
||||
uint16_t s_pad0;
|
||||
uint32_t s_fsize;
|
||||
uint16_t s_nfree;
|
||||
uint16_t s_pad1;
|
||||
uint32_t s_free[SYSV_NICFREE];
|
||||
uint16_t s_ninode;
|
||||
uint16_t s_pad2;
|
||||
uint16_t s_inode[SYSV_NICINOD];
|
||||
uint8_t s_flock;
|
||||
uint8_t s_ilock;
|
||||
uint8_t s_fmod;
|
||||
uint8_t s_ronly;
|
||||
uint32_t s_time;
|
||||
uint16_t s_dinfo[4];
|
||||
uint32_t s_tfree;
|
||||
uint16_t s_tinode;
|
||||
uint16_t s_pad3;
|
||||
uint8_t s_fname[6];
|
||||
uint8_t s_fpack[6];
|
||||
uint32_t s_fill[12];
|
||||
uint32_t s_state;
|
||||
uint32_t s_magic;
|
||||
uint32_t s_type;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define XENIX_NICINOD 100
|
||||
#define XENIX_NICFREE 100
|
||||
|
||||
struct xenix_super {
|
||||
uint16_t s_isize;
|
||||
uint32_t s_fsize;
|
||||
uint16_t s_nfree;
|
||||
uint32_t s_free[XENIX_NICFREE];
|
||||
uint16_t s_ninode;
|
||||
uint16_t s_inode[XENIX_NICINOD];
|
||||
uint8_t s_flock;
|
||||
uint8_t s_ilock;
|
||||
uint8_t s_fmod;
|
||||
uint8_t s_ronly;
|
||||
uint32_t s_time;
|
||||
uint32_t s_tfree;
|
||||
uint16_t s_tinode;
|
||||
uint16_t s_dinfo[4];
|
||||
uint8_t s_fname[6];
|
||||
uint8_t s_fpack[6];
|
||||
uint8_t s_clean;
|
||||
uint8_t s_fill[371];
|
||||
uint32_t s_magic;
|
||||
uint32_t s_type;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define SYSV_SUPERBLOCK_BLOCK 0x01
|
||||
#define SYSV_MAGIC 0xfd187e20
|
||||
#define XENIX_SUPERBLOCK_BLOCK 0x18
|
||||
#define XENIX_MAGIC 0x2b5544
|
||||
#define SYSV_MAX_BLOCKSIZE 0x800
|
||||
|
||||
int volume_id_probe_sysv(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct sysv_super *vs;
|
||||
struct xenix_super *xs;
|
||||
unsigned boff;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
|
||||
vs = volume_id_get_buffer(id, off + (boff * SYSV_SUPERBLOCK_BLOCK), 0x200);
|
||||
if (vs == NULL)
|
||||
return -1;
|
||||
|
||||
if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) {
|
||||
volume_id_set_label_raw(id, vs->s_fname, 6);
|
||||
volume_id_set_label_string(id, vs->s_fname, 6);
|
||||
id->type = "sysv";
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
|
||||
xs = volume_id_get_buffer(id, off + (boff + XENIX_SUPERBLOCK_BLOCK), 0x200);
|
||||
if (xs == NULL)
|
||||
return -1;
|
||||
|
||||
if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) {
|
||||
volume_id_set_label_raw(id, xs->s_fname, 6);
|
||||
volume_id_set_label_string(id, xs->s_fname, 6);
|
||||
id->type = "xenix";
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
return 0;
|
||||
}
|
172
util-linux/volume_id/udf.c
Normal file
172
util-linux/volume_id/udf.c
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct volume_descriptor {
|
||||
struct descriptor_tag {
|
||||
uint16_t id;
|
||||
uint16_t version;
|
||||
uint8_t checksum;
|
||||
uint8_t reserved;
|
||||
uint16_t serial;
|
||||
uint16_t crc;
|
||||
uint16_t crc_len;
|
||||
uint32_t location;
|
||||
} __attribute__((__packed__)) tag;
|
||||
union {
|
||||
struct anchor_descriptor {
|
||||
uint32_t length;
|
||||
uint32_t location;
|
||||
} __attribute__((__packed__)) anchor;
|
||||
struct primary_descriptor {
|
||||
uint32_t seq_num;
|
||||
uint32_t desc_num;
|
||||
struct dstring {
|
||||
uint8_t clen;
|
||||
uint8_t c[31];
|
||||
} __attribute__((__packed__)) ident;
|
||||
} __attribute__((__packed__)) primary;
|
||||
} __attribute__((__packed__)) type;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct volume_structure_descriptor {
|
||||
uint8_t type;
|
||||
uint8_t id[5];
|
||||
uint8_t version;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define UDF_VSD_OFFSET 0x8000
|
||||
|
||||
int volume_id_probe_udf(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct volume_descriptor *vd;
|
||||
struct volume_structure_descriptor *vsd;
|
||||
unsigned bs;
|
||||
unsigned b;
|
||||
unsigned type;
|
||||
unsigned count;
|
||||
unsigned loc;
|
||||
unsigned clen;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
|
||||
if (vsd == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(vsd->id, "NSR02", 5) == 0)
|
||||
goto blocksize;
|
||||
if (memcmp(vsd->id, "NSR03", 5) == 0)
|
||||
goto blocksize;
|
||||
if (memcmp(vsd->id, "BEA01", 5) == 0)
|
||||
goto blocksize;
|
||||
if (memcmp(vsd->id, "BOOT2", 5) == 0)
|
||||
goto blocksize;
|
||||
if (memcmp(vsd->id, "CD001", 5) == 0)
|
||||
goto blocksize;
|
||||
if (memcmp(vsd->id, "CDW02", 5) == 0)
|
||||
goto blocksize;
|
||||
if (memcmp(vsd->id, "TEA03", 5) == 0)
|
||||
goto blocksize;
|
||||
return -1;
|
||||
|
||||
blocksize:
|
||||
/* search the next VSD to get the logical block size of the volume */
|
||||
for (bs = 0x800; bs < 0x8000; bs += 0x800) {
|
||||
vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
|
||||
if (vsd == NULL)
|
||||
return -1;
|
||||
dbg("test for blocksize: 0x%x", bs);
|
||||
if (vsd->id[0] != '\0')
|
||||
goto nsr;
|
||||
}
|
||||
return -1;
|
||||
|
||||
nsr:
|
||||
/* search the list of VSDs for a NSR descriptor */
|
||||
for (b = 0; b < 64; b++) {
|
||||
vsd = volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
|
||||
if (vsd == NULL)
|
||||
return -1;
|
||||
|
||||
dbg("vsd: %c%c%c%c%c",
|
||||
vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
|
||||
|
||||
if (vsd->id[0] == '\0')
|
||||
return -1;
|
||||
if (memcmp(vsd->id, "NSR02", 5) == 0)
|
||||
goto anchor;
|
||||
if (memcmp(vsd->id, "NSR03", 5) == 0)
|
||||
goto anchor;
|
||||
}
|
||||
return -1;
|
||||
|
||||
anchor:
|
||||
/* read anchor volume descriptor */
|
||||
vd = volume_id_get_buffer(id, off + (256 * bs), 0x200);
|
||||
if (vd == NULL)
|
||||
return -1;
|
||||
|
||||
type = le16_to_cpu(vd->tag.id);
|
||||
if (type != 2) /* TAG_ID_AVDP */
|
||||
goto found;
|
||||
|
||||
/* get desriptor list address and block count */
|
||||
count = le32_to_cpu(vd->type.anchor.length) / bs;
|
||||
loc = le32_to_cpu(vd->type.anchor.location);
|
||||
dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
|
||||
|
||||
/* pick the primary descriptor from the list */
|
||||
for (b = 0; b < count; b++) {
|
||||
vd = volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200);
|
||||
if (vd == NULL)
|
||||
return -1;
|
||||
|
||||
type = le16_to_cpu(vd->tag.id);
|
||||
dbg("descriptor type %i", type);
|
||||
|
||||
/* check validity */
|
||||
if (type == 0)
|
||||
goto found;
|
||||
if (le32_to_cpu(vd->tag.location) != loc + b)
|
||||
goto found;
|
||||
|
||||
if (type == 1) /* TAG_ID_PVD */
|
||||
goto pvd;
|
||||
}
|
||||
goto found;
|
||||
|
||||
pvd:
|
||||
volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32);
|
||||
|
||||
clen = vd->type.primary.ident.clen;
|
||||
dbg("label string charsize=%i bit", clen);
|
||||
if (clen == 8)
|
||||
volume_id_set_label_string(id, vd->type.primary.ident.c, 31);
|
||||
else if (clen == 16)
|
||||
volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE, 31);
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "udf";
|
||||
|
||||
return 0;
|
||||
}
|
206
util-linux/volume_id/ufs.c
Normal file
206
util-linux/volume_id/ufs.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct ufs_super_block {
|
||||
uint32_t fs_link;
|
||||
uint32_t fs_rlink;
|
||||
uint32_t fs_sblkno;
|
||||
uint32_t fs_cblkno;
|
||||
uint32_t fs_iblkno;
|
||||
uint32_t fs_dblkno;
|
||||
uint32_t fs_cgoffset;
|
||||
uint32_t fs_cgmask;
|
||||
uint32_t fs_time;
|
||||
uint32_t fs_size;
|
||||
uint32_t fs_dsize;
|
||||
uint32_t fs_ncg;
|
||||
uint32_t fs_bsize;
|
||||
uint32_t fs_fsize;
|
||||
uint32_t fs_frag;
|
||||
uint32_t fs_minfree;
|
||||
uint32_t fs_rotdelay;
|
||||
uint32_t fs_rps;
|
||||
uint32_t fs_bmask;
|
||||
uint32_t fs_fmask;
|
||||
uint32_t fs_bshift;
|
||||
uint32_t fs_fshift;
|
||||
uint32_t fs_maxcontig;
|
||||
uint32_t fs_maxbpg;
|
||||
uint32_t fs_fragshift;
|
||||
uint32_t fs_fsbtodb;
|
||||
uint32_t fs_sbsize;
|
||||
uint32_t fs_csmask;
|
||||
uint32_t fs_csshift;
|
||||
uint32_t fs_nindir;
|
||||
uint32_t fs_inopb;
|
||||
uint32_t fs_nspf;
|
||||
uint32_t fs_optim;
|
||||
uint32_t fs_npsect_state;
|
||||
uint32_t fs_interleave;
|
||||
uint32_t fs_trackskew;
|
||||
uint32_t fs_id[2];
|
||||
uint32_t fs_csaddr;
|
||||
uint32_t fs_cssize;
|
||||
uint32_t fs_cgsize;
|
||||
uint32_t fs_ntrak;
|
||||
uint32_t fs_nsect;
|
||||
uint32_t fs_spc;
|
||||
uint32_t fs_ncyl;
|
||||
uint32_t fs_cpg;
|
||||
uint32_t fs_ipg;
|
||||
uint32_t fs_fpg;
|
||||
struct ufs_csum {
|
||||
uint32_t cs_ndir;
|
||||
uint32_t cs_nbfree;
|
||||
uint32_t cs_nifree;
|
||||
uint32_t cs_nffree;
|
||||
} __attribute__((__packed__)) fs_cstotal;
|
||||
int8_t fs_fmod;
|
||||
int8_t fs_clean;
|
||||
int8_t fs_ronly;
|
||||
int8_t fs_flags;
|
||||
union {
|
||||
struct {
|
||||
int8_t fs_fsmnt[512];
|
||||
uint32_t fs_cgrotor;
|
||||
uint32_t fs_csp[31];
|
||||
uint32_t fs_maxcluster;
|
||||
uint32_t fs_cpc;
|
||||
uint16_t fs_opostbl[16][8];
|
||||
} __attribute__((__packed__)) fs_u1;
|
||||
struct {
|
||||
int8_t fs_fsmnt[468];
|
||||
uint8_t fs_volname[32];
|
||||
uint64_t fs_swuid;
|
||||
int32_t fs_pad;
|
||||
uint32_t fs_cgrotor;
|
||||
uint32_t fs_ocsp[28];
|
||||
uint32_t fs_contigdirs;
|
||||
uint32_t fs_csp;
|
||||
uint32_t fs_maxcluster;
|
||||
uint32_t fs_active;
|
||||
int32_t fs_old_cpc;
|
||||
int32_t fs_maxbsize;
|
||||
int64_t fs_sparecon64[17];
|
||||
int64_t fs_sblockloc;
|
||||
struct ufs2_csum_total {
|
||||
uint64_t cs_ndir;
|
||||
uint64_t cs_nbfree;
|
||||
uint64_t cs_nifree;
|
||||
uint64_t cs_nffree;
|
||||
uint64_t cs_numclusters;
|
||||
uint64_t cs_spare[3];
|
||||
} __attribute__((__packed__)) fs_cstotal;
|
||||
struct ufs_timeval {
|
||||
int32_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
} __attribute__((__packed__)) fs_time;
|
||||
int64_t fs_size;
|
||||
int64_t fs_dsize;
|
||||
uint64_t fs_csaddr;
|
||||
int64_t fs_pendingblocks;
|
||||
int32_t fs_pendinginodes;
|
||||
} __attribute__((__packed__)) fs_u2;
|
||||
} fs_u11;
|
||||
union {
|
||||
struct {
|
||||
int32_t fs_sparecon[53];
|
||||
int32_t fs_reclaim;
|
||||
int32_t fs_sparecon2[1];
|
||||
int32_t fs_state;
|
||||
uint32_t fs_qbmask[2];
|
||||
uint32_t fs_qfmask[2];
|
||||
} __attribute__((__packed__)) fs_sun;
|
||||
struct {
|
||||
int32_t fs_sparecon[53];
|
||||
int32_t fs_reclaim;
|
||||
int32_t fs_sparecon2[1];
|
||||
uint32_t fs_npsect;
|
||||
uint32_t fs_qbmask[2];
|
||||
uint32_t fs_qfmask[2];
|
||||
} __attribute__((__packed__)) fs_sunx86;
|
||||
struct {
|
||||
int32_t fs_sparecon[50];
|
||||
int32_t fs_contigsumsize;
|
||||
int32_t fs_maxsymlinklen;
|
||||
int32_t fs_inodefmt;
|
||||
uint32_t fs_maxfilesize[2];
|
||||
uint32_t fs_qbmask[2];
|
||||
uint32_t fs_qfmask[2];
|
||||
int32_t fs_state;
|
||||
} __attribute__((__packed__)) fs_44;
|
||||
} fs_u2;
|
||||
int32_t fs_postblformat;
|
||||
int32_t fs_nrpos;
|
||||
int32_t fs_postbloff;
|
||||
int32_t fs_rotbloff;
|
||||
uint32_t fs_magic;
|
||||
uint8_t fs_space[1];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define UFS_MAGIC 0x00011954
|
||||
#define UFS2_MAGIC 0x19540119
|
||||
#define UFS_MAGIC_FEA 0x00195612
|
||||
#define UFS_MAGIC_LFN 0x00095014
|
||||
|
||||
int volume_id_probe_ufs(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
static const short offsets[] = { 0, 8, 64, 256 };
|
||||
|
||||
uint32_t magic;
|
||||
int i;
|
||||
struct ufs_super_block *ufs;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(offsets); i++) {
|
||||
ufs = volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800);
|
||||
if (ufs == NULL)
|
||||
return -1;
|
||||
|
||||
dbg("offset 0x%x", offsets[i] * 0x400);
|
||||
magic = ufs->fs_magic;
|
||||
if ((magic == cpu_to_be32(UFS_MAGIC))
|
||||
|| (magic == cpu_to_be32(UFS2_MAGIC))
|
||||
|| (magic == cpu_to_be32(UFS_MAGIC_FEA))
|
||||
|| (magic == cpu_to_be32(UFS_MAGIC_LFN))
|
||||
) {
|
||||
dbg("magic 0x%08x(be)", magic);
|
||||
goto found;
|
||||
}
|
||||
if ((magic == cpu_to_le32(UFS_MAGIC))
|
||||
|| (magic == cpu_to_le32(UFS2_MAGIC))
|
||||
|| (magic == cpu_to_le32(UFS_MAGIC_FEA))
|
||||
|| (magic == cpu_to_le32(UFS_MAGIC_LFN))
|
||||
) {
|
||||
dbg("magic 0x%08x(le)", magic);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "ufs";
|
||||
|
||||
return 0;
|
||||
}
|
260
util-linux/volume_id/util.c
Normal file
260
util-linux/volume_id/util.c
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count)
|
||||
{
|
||||
unsigned i, j;
|
||||
uint16_t c;
|
||||
|
||||
j = 0;
|
||||
for (i = 0; i + 2 <= count; i += 2) {
|
||||
if (endianess == LE)
|
||||
c = (buf[i+1] << 8) | buf[i];
|
||||
else
|
||||
c = (buf[i] << 8) | buf[i+1];
|
||||
if (c == 0) {
|
||||
str[j] = '\0';
|
||||
break;
|
||||
} else if (c < 0x80) {
|
||||
if (j+1 >= len)
|
||||
break;
|
||||
str[j++] = (uint8_t) c;
|
||||
} else if (c < 0x800) {
|
||||
if (j+2 >= len)
|
||||
break;
|
||||
str[j++] = (uint8_t) (0xc0 | (c >> 6));
|
||||
str[j++] = (uint8_t) (0x80 | (c & 0x3f));
|
||||
} else {
|
||||
if (j+3 >= len)
|
||||
break;
|
||||
str[j++] = (uint8_t) (0xe0 | (c >> 12));
|
||||
str[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
|
||||
str[j++] = (uint8_t) (0x80 | (c & 0x3f));
|
||||
}
|
||||
}
|
||||
str[j] = '\0';
|
||||
}
|
||||
|
||||
static const char *usage_to_string(enum volume_id_usage usage_id)
|
||||
{
|
||||
switch (usage_id) {
|
||||
case VOLUME_ID_FILESYSTEM:
|
||||
return "filesystem";
|
||||
case VOLUME_ID_PARTITIONTABLE:
|
||||
return "partitiontable";
|
||||
case VOLUME_ID_OTHER:
|
||||
return "other";
|
||||
case VOLUME_ID_RAID:
|
||||
return "raid";
|
||||
case VOLUME_ID_DISKLABEL:
|
||||
return "disklabel";
|
||||
case VOLUME_ID_CRYPTO:
|
||||
return "crypto";
|
||||
case VOLUME_ID_UNPROBED:
|
||||
return "unprobed";
|
||||
case VOLUME_ID_UNUSED:
|
||||
return "unused";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id)
|
||||
{
|
||||
part->usage_id = usage_id;
|
||||
part->usage = usage_to_string(usage_id);
|
||||
}
|
||||
|
||||
void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id)
|
||||
{
|
||||
id->usage_id = usage_id;
|
||||
id->usage = usage_to_string(usage_id);
|
||||
}
|
||||
|
||||
void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count)
|
||||
{
|
||||
memcpy(id->label_raw, buf, count);
|
||||
id->label_raw_len = count;
|
||||
}
|
||||
|
||||
#ifdef NOT_NEEDED
|
||||
static size_t strnlen(const char *s, size_t maxlen)
|
||||
{
|
||||
size_t i;
|
||||
if (!maxlen) return 0;
|
||||
if (!s) return 0;
|
||||
for (i = 0; *s && i < maxlen; ++s) ++i;
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
memcpy(id->label, buf, count);
|
||||
|
||||
/* remove trailing whitespace */
|
||||
i = strnlen(id->label, count);
|
||||
while (i--) {
|
||||
if (!isspace(id->label[i]))
|
||||
break;
|
||||
}
|
||||
id->label[i+1] = '\0';
|
||||
}
|
||||
|
||||
void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count)
|
||||
{
|
||||
volume_id_set_unicode16(id->label, sizeof(id->label), buf, endianess, count);
|
||||
}
|
||||
|
||||
void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, enum uuid_format format)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned count = 0;
|
||||
|
||||
switch(format) {
|
||||
case UUID_DOS:
|
||||
count = 4;
|
||||
break;
|
||||
case UUID_NTFS:
|
||||
case UUID_HFS:
|
||||
count = 8;
|
||||
break;
|
||||
case UUID_DCE:
|
||||
count = 16;
|
||||
break;
|
||||
case UUID_DCE_STRING:
|
||||
count = 36;
|
||||
break;
|
||||
}
|
||||
memcpy(id->uuid_raw, buf, count);
|
||||
id->uuid_raw_len = count;
|
||||
|
||||
/* if set, create string in the same format, the native platform uses */
|
||||
for (i = 0; i < count; i++)
|
||||
if (buf[i] != 0)
|
||||
goto set;
|
||||
return;
|
||||
|
||||
set:
|
||||
switch(format) {
|
||||
case UUID_DOS:
|
||||
sprintf(id->uuid, "%02X%02X-%02X%02X",
|
||||
buf[3], buf[2], buf[1], buf[0]);
|
||||
break;
|
||||
case UUID_NTFS:
|
||||
sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
buf[7], buf[6], buf[5], buf[4],
|
||||
buf[3], buf[2], buf[1], buf[0]);
|
||||
break;
|
||||
case UUID_HFS:
|
||||
sprintf(id->uuid,"%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
buf[0], buf[1], buf[2], buf[3],
|
||||
buf[4], buf[5], buf[6], buf[7]);
|
||||
break;
|
||||
case UUID_DCE:
|
||||
sprintf(id->uuid,
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
buf[0], buf[1], buf[2], buf[3],
|
||||
buf[4], buf[5],
|
||||
buf[6], buf[7],
|
||||
buf[8], buf[9],
|
||||
buf[10], buf[11], buf[12], buf[13], buf[14],buf[15]);
|
||||
break;
|
||||
case UUID_DCE_STRING:
|
||||
memcpy(id->uuid, buf, count);
|
||||
id->uuid[count] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
|
||||
{
|
||||
ssize_t buf_len;
|
||||
|
||||
dbg("get buffer off 0x%llx(%llu), len 0x%zx", (unsigned long long) off, (unsigned long long) off, len);
|
||||
/* check if requested area fits in superblock buffer */
|
||||
if (off + len <= SB_BUFFER_SIZE) {
|
||||
if (id->sbbuf == NULL) {
|
||||
id->sbbuf = xmalloc(SB_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/* check if we need to read */
|
||||
if ((off + len) > id->sbbuf_len) {
|
||||
dbg("read sbbuf len:0x%llx", (unsigned long long) (off + len));
|
||||
xlseek(id->fd, 0, SEEK_SET);
|
||||
buf_len = full_read(id->fd, id->sbbuf, off + len);
|
||||
if (buf_len < 0) {
|
||||
dbg("read failed (%s)", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
dbg("got 0x%zx (%zi) bytes", buf_len, buf_len);
|
||||
id->sbbuf_len = buf_len;
|
||||
if (buf_len < off + len) {
|
||||
dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return &(id->sbbuf[off]);
|
||||
}
|
||||
|
||||
if (len > SEEK_BUFFER_SIZE) {
|
||||
dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get seek buffer */
|
||||
if (id->seekbuf == NULL) {
|
||||
id->seekbuf = xmalloc(SEEK_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
/* check if we need to read */
|
||||
if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
|
||||
dbg("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len);
|
||||
xlseek(id->fd, off, SEEK_SET);
|
||||
buf_len = full_read(id->fd, id->seekbuf, len);
|
||||
if (buf_len < 0) {
|
||||
dbg("read failed (%s)", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
dbg("got 0x%zx (%zi) bytes", buf_len, buf_len);
|
||||
id->seekbuf_off = off;
|
||||
id->seekbuf_len = buf_len;
|
||||
if (buf_len < len) {
|
||||
dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return &(id->seekbuf[off - id->seekbuf_off]);
|
||||
}
|
||||
|
||||
void volume_id_free_buffer(struct volume_id *id)
|
||||
{
|
||||
free(id->sbbuf);
|
||||
id->sbbuf = NULL;
|
||||
id->sbbuf_len = 0;
|
||||
free(id->seekbuf);
|
||||
id->seekbuf = NULL;
|
||||
id->seekbuf_len = 0;
|
||||
}
|
68
util-linux/volume_id/via_raid.c
Normal file
68
util-linux/volume_id/via_raid.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct via_meta {
|
||||
uint16_t signature;
|
||||
uint8_t version_number;
|
||||
struct via_array {
|
||||
uint16_t disk_bits;
|
||||
uint8_t disk_array_ex;
|
||||
uint32_t capacity_low;
|
||||
uint32_t capacity_high;
|
||||
uint32_t serial_checksum;
|
||||
} __attribute((packed)) array;
|
||||
uint32_t serial_checksum[8];
|
||||
uint8_t checksum;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define VIA_SIGNATURE 0xAA55
|
||||
|
||||
int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint64_t meta_off;
|
||||
struct via_meta *via;
|
||||
|
||||
dbg("probing at offset 0x%llx, size 0x%llx",
|
||||
(unsigned long long) off, (unsigned long long) size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-1) * 0x200;
|
||||
|
||||
via = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (via == NULL)
|
||||
return -1;
|
||||
|
||||
if (via->signature != cpu_to_le16(VIA_SIGNATURE))
|
||||
return -1;
|
||||
|
||||
if (via->version_number > 1)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type_version[0] = '0' + via->version_number;
|
||||
id->type_version[1] = '\0';
|
||||
id->type = "via_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
214
util-linux/volume_id/volume_id.c
Normal file
214
util-linux/volume_id/volume_id.c
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
typedef int (*raid_probe_fptr)(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
typedef int (*probe_fptr)(struct volume_id *id, uint64_t off);
|
||||
|
||||
static const raid_probe_fptr raid1[] = {
|
||||
#if ENABLE_FEATURE_VOLUMEID_LINUXRAID
|
||||
volume_id_probe_linux_raid,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_ISWRAID
|
||||
volume_id_probe_intel_software_raid,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_LSIRAID
|
||||
volume_id_probe_lsi_mega_raid,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_VIARAID
|
||||
volume_id_probe_via_raid,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_SILICONRAID
|
||||
volume_id_probe_silicon_medley_raid,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_NVIDIARAID
|
||||
volume_id_probe_nvidia_raid,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_PROMISERAID
|
||||
volume_id_probe_promise_fasttrack_raid,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID
|
||||
volume_id_probe_highpoint_45x_raid,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const probe_fptr raid2[] = {
|
||||
#if ENABLE_FEATURE_VOLUMEID_LVM
|
||||
volume_id_probe_lvm1,
|
||||
volume_id_probe_lvm2,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_HIGHPOINTRAID
|
||||
volume_id_probe_highpoint_37x_raid,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_LUKS
|
||||
volume_id_probe_luks,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* signature in the first block, only small buffer needed */
|
||||
static const probe_fptr fs1[] = {
|
||||
#if ENABLE_FEATURE_VOLUMEID_FAT
|
||||
volume_id_probe_vfat,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_MAC
|
||||
volume_id_probe_mac_partition_map,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_XFS
|
||||
volume_id_probe_xfs,
|
||||
#endif
|
||||
};
|
||||
|
||||
/* fill buffer with maximum */
|
||||
static const probe_fptr fs2[] = {
|
||||
#if ENABLE_FEATURE_VOLUMEID_LINUXSWAP
|
||||
volume_id_probe_linux_swap,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_EXT
|
||||
volume_id_probe_ext,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_REISERFS
|
||||
volume_id_probe_reiserfs,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_JFS
|
||||
volume_id_probe_jfs,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_UDF
|
||||
volume_id_probe_udf,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_ISO9660
|
||||
volume_id_probe_iso9660,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_HFS
|
||||
volume_id_probe_hfs_hfsplus,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_UFS
|
||||
volume_id_probe_ufs,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_NTFS
|
||||
volume_id_probe_ntfs,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_CRAMFS
|
||||
volume_id_probe_cramfs,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_ROMFS
|
||||
volume_id_probe_romfs,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_HPFS
|
||||
volume_id_probe_hpfs,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_SYSV
|
||||
volume_id_probe_sysv,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_MINIX
|
||||
volume_id_probe_minix,
|
||||
#endif
|
||||
#if ENABLE_FEATURE_VOLUMEID_OCFS2
|
||||
volume_id_probe_ocfs2,
|
||||
#endif
|
||||
};
|
||||
|
||||
int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (id == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* probe for raid first, cause fs probes may be successful on raid members */
|
||||
if (size) {
|
||||
for (i = 0; i < ARRAY_SIZE(raid1); i++)
|
||||
if (raid1[i](id, off, size) == 0)
|
||||
goto ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(raid2); i++)
|
||||
if (raid2[i](id, off) == 0)
|
||||
goto ret;
|
||||
|
||||
/* signature in the first block, only small buffer needed */
|
||||
for (i = 0; i < ARRAY_SIZE(fs1); i++)
|
||||
if (fs1[i](id, off) == 0)
|
||||
goto ret;
|
||||
|
||||
/* fill buffer with maximum */
|
||||
volume_id_get_buffer(id, 0, SB_BUFFER_SIZE);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fs2); i++)
|
||||
if (fs2[i](id, off) == 0)
|
||||
goto ret;
|
||||
return -1;
|
||||
|
||||
ret:
|
||||
/* If the filestystem in recognized, we free the allocated buffers,
|
||||
otherwise they will stay in place for the possible next probe call */
|
||||
volume_id_free_buffer(id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* open volume by device node */
|
||||
struct volume_id *volume_id_open_node(const char *path)
|
||||
{
|
||||
struct volume_id *id;
|
||||
int fd;
|
||||
|
||||
fd = xopen(path, O_RDONLY);
|
||||
id = xzalloc(sizeof(struct volume_id));
|
||||
id->fd = fd;
|
||||
///* close fd on device close */
|
||||
//id->fd_close = 1;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
#ifdef UNUSED
|
||||
/* open volume by major/minor */
|
||||
struct volume_id *volume_id_open_dev_t(dev_t devt)
|
||||
{
|
||||
struct volume_id *id;
|
||||
char *tmp_node[VOLUME_ID_PATH_MAX];
|
||||
|
||||
tmp_node = xasprintf("/dev/.volume_id-%u-%u-%u",
|
||||
(unsigned)getpid(), (unsigned)major(devt), (unsigned)minor(devt));
|
||||
|
||||
/* create temporary node to open block device */
|
||||
unlink(tmp_node);
|
||||
if (mknod(tmp_node, (S_IFBLK | 0600), devt) != 0)
|
||||
bb_perror_msg_and_die("cannot mknod(%s)", tmp_node);
|
||||
|
||||
id = volume_id_open_node(tmp_node);
|
||||
unlink(tmp_node);
|
||||
free(tmp_node);
|
||||
return id;
|
||||
}
|
||||
#endif
|
||||
|
||||
void free_volume_id(struct volume_id *id)
|
||||
{
|
||||
if (id == NULL)
|
||||
return;
|
||||
|
||||
//if (id->fd_close != 0) - always true
|
||||
close(id->fd);
|
||||
volume_id_free_buffer(id);
|
||||
free(id->partitions);
|
||||
free(id);
|
||||
}
|
220
util-linux/volume_id/volume_id_internal.h
Normal file
220
util-linux/volume_id/volume_id_internal.h
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "libbb.h"
|
||||
#include "volume_id.h"
|
||||
|
||||
|
||||
#define dbg(...) ((void)0)
|
||||
|
||||
|
||||
/* volume_id.h */
|
||||
|
||||
#define VOLUME_ID_VERSION 48
|
||||
|
||||
#define VOLUME_ID_LABEL_SIZE 64
|
||||
#define VOLUME_ID_UUID_SIZE 36
|
||||
#define VOLUME_ID_FORMAT_SIZE 32
|
||||
#define VOLUME_ID_PARTITIONS_MAX 256
|
||||
|
||||
enum volume_id_usage {
|
||||
VOLUME_ID_UNUSED,
|
||||
VOLUME_ID_UNPROBED,
|
||||
VOLUME_ID_OTHER,
|
||||
VOLUME_ID_FILESYSTEM,
|
||||
VOLUME_ID_PARTITIONTABLE,
|
||||
VOLUME_ID_RAID,
|
||||
VOLUME_ID_DISKLABEL,
|
||||
VOLUME_ID_CRYPTO,
|
||||
};
|
||||
|
||||
struct volume_id_partition {
|
||||
enum volume_id_usage usage_id;
|
||||
const char *usage;
|
||||
const char *type;
|
||||
uint64_t off;
|
||||
uint64_t len;
|
||||
uint8_t partition_type_raw;
|
||||
};
|
||||
|
||||
struct volume_id {
|
||||
uint8_t label_raw[VOLUME_ID_LABEL_SIZE];
|
||||
size_t label_raw_len;
|
||||
char label[VOLUME_ID_LABEL_SIZE+1];
|
||||
uint8_t uuid_raw[VOLUME_ID_UUID_SIZE];
|
||||
size_t uuid_raw_len;
|
||||
char uuid[VOLUME_ID_UUID_SIZE+1];
|
||||
enum volume_id_usage usage_id;
|
||||
const char *usage;
|
||||
const char *type;
|
||||
char type_version[VOLUME_ID_FORMAT_SIZE];
|
||||
|
||||
struct volume_id_partition *partitions;
|
||||
size_t partition_count;
|
||||
|
||||
int fd;
|
||||
uint8_t *sbbuf;
|
||||
uint8_t *seekbuf;
|
||||
size_t sbbuf_len;
|
||||
uint64_t seekbuf_off;
|
||||
size_t seekbuf_len;
|
||||
// int fd_close:1;
|
||||
};
|
||||
|
||||
struct volume_id *volume_id_open_node(const char *path);
|
||||
int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
void free_volume_id(struct volume_id *id);
|
||||
|
||||
/* util.h */
|
||||
|
||||
/* size of superblock buffer, reiserfs block is at 64k */
|
||||
#define SB_BUFFER_SIZE 0x11000
|
||||
/* size of seek buffer, FAT cluster is 32k max */
|
||||
#define SEEK_BUFFER_SIZE 0x10000
|
||||
|
||||
#define bswap16(x) (uint16_t) ( \
|
||||
(((uint16_t)(x) & 0x00ffu) << 8) | \
|
||||
(((uint16_t)(x) & 0xff00u) >> 8))
|
||||
|
||||
#define bswap32(x) (uint32_t) ( \
|
||||
(((uint32_t)(x) & 0xff000000u) >> 24) | \
|
||||
(((uint32_t)(x) & 0x00ff0000u) >> 8) | \
|
||||
(((uint32_t)(x) & 0x0000ff00u) << 8) | \
|
||||
(((uint32_t)(x) & 0x000000ffu) << 24))
|
||||
|
||||
#define bswap64(x) (uint64_t) ( \
|
||||
(((uint64_t)(x) & 0xff00000000000000ull) >> 56) | \
|
||||
(((uint64_t)(x) & 0x00ff000000000000ull) >> 40) | \
|
||||
(((uint64_t)(x) & 0x0000ff0000000000ull) >> 24) | \
|
||||
(((uint64_t)(x) & 0x000000ff00000000ull) >> 8) | \
|
||||
(((uint64_t)(x) & 0x00000000ff000000ull) << 8) | \
|
||||
(((uint64_t)(x) & 0x0000000000ff0000ull) << 24) | \
|
||||
(((uint64_t)(x) & 0x000000000000ff00ull) << 40) | \
|
||||
(((uint64_t)(x) & 0x00000000000000ffull) << 56))
|
||||
|
||||
#if BB_LITTLE_ENDIAN
|
||||
#define le16_to_cpu(x) (x)
|
||||
#define le32_to_cpu(x) (x)
|
||||
#define le64_to_cpu(x) (x)
|
||||
#define be16_to_cpu(x) bswap16(x)
|
||||
#define be32_to_cpu(x) bswap32(x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define cpu_to_be32(x) bswap32(x)
|
||||
#else
|
||||
#define le16_to_cpu(x) bswap16(x)
|
||||
#define le32_to_cpu(x) bswap32(x)
|
||||
#define le64_to_cpu(x) bswap64(x)
|
||||
#define be16_to_cpu(x) (x)
|
||||
#define be32_to_cpu(x) (x)
|
||||
#define cpu_to_le16(x) bswap16(x)
|
||||
#define cpu_to_le32(x) bswap32(x)
|
||||
#define cpu_to_be32(x) (x)
|
||||
#endif
|
||||
|
||||
enum uuid_format {
|
||||
UUID_DCE_STRING,
|
||||
UUID_DCE,
|
||||
UUID_DOS,
|
||||
UUID_NTFS,
|
||||
UUID_HFS,
|
||||
};
|
||||
|
||||
enum endian {
|
||||
LE = 0,
|
||||
BE = 1
|
||||
};
|
||||
|
||||
void volume_id_set_unicode16(char *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count);
|
||||
void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id);
|
||||
void volume_id_set_usage_part(struct volume_id_partition *part, enum volume_id_usage usage_id);
|
||||
void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count);
|
||||
void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count);
|
||||
void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count);
|
||||
void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, enum uuid_format format);
|
||||
void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len);
|
||||
void volume_id_free_buffer(struct volume_id *id);
|
||||
|
||||
|
||||
/* Probe routines */
|
||||
|
||||
/* RAID */
|
||||
|
||||
int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off);
|
||||
int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
int volume_id_probe_lvm1(struct volume_id *id, uint64_t off);
|
||||
int volume_id_probe_lvm2(struct volume_id *id, uint64_t off);
|
||||
|
||||
/* FS */
|
||||
|
||||
int volume_id_probe_cramfs(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_ext(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_vfat(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_hpfs(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_iso9660(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_jfs(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_luks(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_mac_partition_map(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_minix(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_msdos_part_table(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_ntfs(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_romfs(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_sysv(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_udf(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_ufs(struct volume_id *id, uint64_t off);
|
||||
|
||||
int volume_id_probe_xfs(struct volume_id *id, uint64_t off);
|
59
util-linux/volume_id/xfs.c
Normal file
59
util-linux/volume_id/xfs.c
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "volume_id_internal.h"
|
||||
|
||||
struct xfs_super_block {
|
||||
uint8_t magic[4];
|
||||
uint32_t blocksize;
|
||||
uint64_t dblocks;
|
||||
uint64_t rblocks;
|
||||
uint32_t dummy1[2];
|
||||
uint8_t uuid[16];
|
||||
uint32_t dummy2[15];
|
||||
uint8_t fname[12];
|
||||
uint32_t dummy3[2];
|
||||
uint64_t icount;
|
||||
uint64_t ifree;
|
||||
uint64_t fdblocks;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
int volume_id_probe_xfs(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
struct xfs_super_block *xs;
|
||||
|
||||
dbg("probing at offset 0x%llx", (unsigned long long) off);
|
||||
|
||||
xs = volume_id_get_buffer(id, off, 0x200);
|
||||
if (xs == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(xs->magic, "XFSB", 4) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_label_raw(id, xs->fname, 12);
|
||||
volume_id_set_label_string(id, xs->fname, 12);
|
||||
volume_id_set_uuid(id, xs->uuid, UUID_DCE);
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "xfs";
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user