support for mount by label (not yet tested)

Also adds findfs applet. Closes bug 1143.
This commit is contained in:
Denis Vlasenko 2008-02-18 21:08:49 +00:00
parent 27dd495b98
commit de7684a309
43 changed files with 4632 additions and 20 deletions

View File

@ -452,6 +452,7 @@ libs-y := \
shell/ \
sysklogd/ \
util-linux/ \
util-linux/volume_id/ \
endif # KBUILD_EXTMOD

View File

@ -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 */

View File

@ -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
View 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);

View File

@ -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

View File

@ -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

View File

@ -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
View 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;
}

View File

@ -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);

View 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

View 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;
}

View 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
View 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;
}

View 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
View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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
View 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;
}

View 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;
}

View 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
View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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
View 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
View 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
View 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
View 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;
}

View 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;
}

View 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);
}

View 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);

View 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;
}