mirror of
https://github.com/systemd/systemd.git
synced 2025-01-11 09:18:07 +03:00
delete libvolume_id
This commit is contained in:
parent
f07996885d
commit
3de63a356f
9
NEWS
9
NEWS
@ -2,10 +2,11 @@ udev 142
|
||||
========
|
||||
Bugfixes.
|
||||
|
||||
The program vol_id is removed from the repository and blkid from the
|
||||
latest util-linux-ng package replaces it. Persisten disk links for
|
||||
label and uuid depend on the util-linux-ng version of blkid now. Older
|
||||
versions can not be used with udev.
|
||||
The program vol_id and the library libvolume_id is removed from the
|
||||
repository. Libvolume_id is merged with libblkid from the util-linux-ng
|
||||
package. Persistent disk links for label and uuid depend on the
|
||||
util-linux-ng version (2.15) of blkid now. Older versions of blkid
|
||||
can not be used with udev.
|
||||
|
||||
Libudev allows to subscribe to udev events. To prevent unwanted messages
|
||||
to be delivered, and waking up the subscribing process, a filter can be
|
||||
|
11
configure.ac
11
configure.ac
@ -21,14 +21,6 @@ AC_SUBST(LIBUDEV_LT_CURRENT)
|
||||
AC_SUBST(LIBUDEV_LT_REVISION)
|
||||
AC_SUBST(LIBUDEV_LT_AGE)
|
||||
|
||||
dnl /* libvolume_id version */
|
||||
VOLID_LT_CURRENT=2
|
||||
VOLID_LT_REVISION=0
|
||||
VOLID_LT_AGE=1
|
||||
AC_SUBST(VOLID_LT_CURRENT)
|
||||
AC_SUBST(VOLID_LT_REVISION)
|
||||
AC_SUBST(VOLID_LT_AGE)
|
||||
|
||||
AC_PATH_PROG([XSLTPROC], [xsltproc])
|
||||
|
||||
AC_CHECK_LIB(c, inotify_init,
|
||||
@ -97,9 +89,6 @@ AC_CONFIG_FILES([
|
||||
extras/rule_generator/Makefile
|
||||
extras/scsi_id/Makefile
|
||||
extras/usb_id/Makefile
|
||||
extras/volume_id/Makefile
|
||||
extras/volume_id/lib/Makefile
|
||||
extras/volume_id/lib/libvolume_id.pc
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
|
@ -11,5 +11,4 @@ SUBDIRS = \
|
||||
fstab_import \
|
||||
rule_generator \
|
||||
scsi_id \
|
||||
usb_id \
|
||||
volume_id
|
||||
usb_id
|
||||
|
3
extras/volume_id/.gitignore
vendored
3
extras/volume_id/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
vol_id
|
||||
*.8
|
||||
|
@ -1,4 +0,0 @@
|
||||
include $(top_srcdir)/Makefile.am.inc
|
||||
|
||||
SUBDIRS = \
|
||||
lib
|
2
extras/volume_id/lib/.gitignore
vendored
2
extras/volume_id/lib/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
libvolume_id.pc
|
||||
libvolume_id.so*
|
@ -1,74 +0,0 @@
|
||||
include $(top_srcdir)/Makefile.am.inc
|
||||
|
||||
rootlibdir = $(exec_prefix)/$(libdir_name)
|
||||
rootlib_LTLIBRARIES = \
|
||||
libvolume_id.la
|
||||
|
||||
include_HEADERS =\
|
||||
libvolume_id.h
|
||||
|
||||
libvolume_id_la_SOURCES =\
|
||||
libvolume_id-private.h \
|
||||
volume_id.c \
|
||||
util.c \
|
||||
md5.h \
|
||||
md5.c \
|
||||
ext.c \
|
||||
fat.c \
|
||||
hfs.c \
|
||||
highpoint.c \
|
||||
isw_raid.c \
|
||||
lsi_raid.c \
|
||||
via_raid.c \
|
||||
silicon_raid.c \
|
||||
nvidia_raid.c \
|
||||
promise_raid.c \
|
||||
adaptec_raid.c \
|
||||
jmicron_raid.c \
|
||||
ddf_raid.c \
|
||||
iso9660.c \
|
||||
jfs.c \
|
||||
linux_raid.c \
|
||||
linux_swap.c \
|
||||
lvm.c \
|
||||
ntfs.c \
|
||||
reiserfs.c \
|
||||
udf.c \
|
||||
ufs.c \
|
||||
xfs.c \
|
||||
cramfs.c \
|
||||
hpfs.c \
|
||||
romfs.c \
|
||||
sysv.c \
|
||||
minix.c \
|
||||
gfs.c \
|
||||
luks.c \
|
||||
ocfs.c \
|
||||
vxfs.c \
|
||||
squashfs.c \
|
||||
netware.c \
|
||||
oracleasm.c \
|
||||
btrfs.c
|
||||
|
||||
libvolume_id_la_LDFLAGS = \
|
||||
-version-info $(VOLID_LT_CURRENT):$(VOLID_LT_REVISION):$(VOLID_LT_AGE) \
|
||||
-export-symbols $(top_srcdir)/extras/volume_id/lib/exported_symbols
|
||||
|
||||
# move devel files to $(prefix)$(libdir_name) if needed
|
||||
install-data-hook:
|
||||
rm $(DESTDIR)$(rootlibdir)/libvolume_id.la
|
||||
if test "$(prefix)" != "$(exec_prefix)"; then \
|
||||
mkdir -p $(DESTDIR)$(prefix)/$(libdir_name); \
|
||||
mv $(DESTDIR)$(rootlibdir)/libvolume_id.a $(DESTDIR)$(prefix)/$(libdir_name)/; \
|
||||
so_img_name=$$(readlink $(DESTDIR)$(rootlibdir)/libvolume_id.so); \
|
||||
rm $(DESTDIR)$(rootlibdir)/libvolume_id.so; \
|
||||
so_img_rel_target_prefix=$$(echo $(prefix)/$(libdir_name) | sed 's,\(^/\|\)[^/][^/]*,..,g'); \
|
||||
ln -sf $$so_img_rel_target_prefix$(exec_prefix)/$(libdir_name)/$$so_img_name \
|
||||
$(DESTDIR)$(prefix)/$(libdir_name)/libvolume_id.so; \
|
||||
fi
|
||||
|
||||
EXTRA_DIST = \
|
||||
exported_symbols
|
||||
|
||||
pkgconfigdir = $(prefix)/$(libdir_name)/pkgconfig
|
||||
pkgconfig_DATA = libvolume_id.pc
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct adaptec_meta {
|
||||
uint32_t b0idcode;
|
||||
uint8_t lunsave[8];
|
||||
uint16_t sdtype;
|
||||
uint16_t ssavecyl;
|
||||
uint8_t ssavehed;
|
||||
uint8_t ssavesec;
|
||||
uint8_t sb0flags;
|
||||
uint8_t jbodEnable;
|
||||
uint8_t lundsave;
|
||||
uint8_t svpdirty;
|
||||
uint16_t biosInfo;
|
||||
uint16_t svwbskip;
|
||||
uint16_t svwbcln;
|
||||
uint16_t svwbmax;
|
||||
uint16_t res3;
|
||||
uint16_t svwbmin;
|
||||
uint16_t res4;
|
||||
uint16_t svrcacth;
|
||||
uint16_t svwcacth;
|
||||
uint16_t svwbdly;
|
||||
uint8_t svsdtime;
|
||||
uint8_t res5;
|
||||
uint16_t firmval;
|
||||
uint16_t firmbln;
|
||||
uint32_t firmblk;
|
||||
uint32_t fstrsvrb;
|
||||
uint16_t svBlockStorageTid;
|
||||
uint16_t svtid;
|
||||
uint8_t svseccfl;
|
||||
uint8_t res6;
|
||||
uint8_t svhbanum;
|
||||
uint8_t resver;
|
||||
uint32_t drivemagic;
|
||||
uint8_t reserved[20];
|
||||
uint8_t testnum;
|
||||
uint8_t testflags;
|
||||
uint16_t maxErrorCount;
|
||||
uint32_t count;
|
||||
uint32_t startTime;
|
||||
uint32_t interval;
|
||||
uint8_t tstxt0;
|
||||
uint8_t tstxt1;
|
||||
uint8_t serNum[32];
|
||||
uint8_t res8[102];
|
||||
uint32_t fwTestMagic;
|
||||
uint32_t fwTestSeqNum;
|
||||
uint8_t fwTestRes[8];
|
||||
uint8_t smagic[4];
|
||||
uint32_t raidtbl;
|
||||
uint16_t raidline;
|
||||
uint8_t res9[0xF6];
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_adaptec_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
uint64_t meta_off;
|
||||
struct adaptec_meta *ad;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-1) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
ad = (struct adaptec_meta *) buf;
|
||||
if (memcmp(ad->smagic, "DPTM", 4) != 0)
|
||||
return -1;
|
||||
|
||||
if (ad->b0idcode != be32_to_cpu(0x37FC4D1E))
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u", ad->resver);
|
||||
id->type = "adaptec_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <byteswap.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct btrfs_super_block {
|
||||
uint8_t csum[32];
|
||||
uint8_t fsid[16];
|
||||
uint64_t bytenr;
|
||||
uint64_t flags;
|
||||
uint8_t magic[8];
|
||||
uint64_t generation;
|
||||
uint64_t root;
|
||||
uint64_t chunk_root;
|
||||
uint64_t log_root;
|
||||
uint64_t log_root_transid;
|
||||
uint64_t total_bytes;
|
||||
uint64_t bytes_used;
|
||||
uint64_t root_dir_objectid;
|
||||
uint64_t num_devices;
|
||||
uint32_t sectorsize;
|
||||
uint32_t nodesize;
|
||||
uint32_t leafsize;
|
||||
uint32_t stripesize;
|
||||
uint32_t sys_chunk_array_size;
|
||||
uint64_t chunk_root_generation;
|
||||
uint64_t compat_flags;
|
||||
uint64_t compat_ro_flags;
|
||||
uint64_t incompat_flags;
|
||||
uint16_t csum_type;
|
||||
uint8_t root_level;
|
||||
uint8_t chunk_root_level;
|
||||
uint8_t log_root_level;
|
||||
struct btrfs_dev_item {
|
||||
uint64_t devid;
|
||||
uint64_t total_bytes;
|
||||
uint64_t bytes_used;
|
||||
uint32_t io_align;
|
||||
uint32_t io_width;
|
||||
uint32_t sector_size;
|
||||
uint64_t type;
|
||||
uint64_t generation;
|
||||
uint64_t start_offset;
|
||||
uint32_t dev_group;
|
||||
uint8_t seek_speed;
|
||||
uint8_t bandwidth;
|
||||
uint8_t uuid[16];
|
||||
uint8_t fsid[16];
|
||||
} PACKED dev_item;
|
||||
uint8_t label[256];
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_btrfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct btrfs_super_block *bfs;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + 0x10000, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
bfs = (struct btrfs_super_block *)buf;
|
||||
if (memcmp(bfs->magic, "_BHRfS_M", 8) != 0)
|
||||
return -1;
|
||||
volume_id_set_uuid(id, bfs->fsid, 0, UUID_DCE);
|
||||
volume_id_set_uuid_sub(id, bfs->dev_item.uuid, 0, UUID_DCE);
|
||||
volume_id_set_label_raw(id, bfs->label, 256);
|
||||
volume_id_set_label_string(id, bfs->label, 256);
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "btrfs";
|
||||
return 0;
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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;
|
||||
} PACKED info;
|
||||
uint8_t name[16];
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_cramfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct cramfs_super *cs;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
cs = (struct cramfs_super *) volume_id_get_buffer(id, off, 0x200);
|
||||
if (cs == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(cs->magic, "\x45\x3d\xcd\x28", 4) == 0 || memcmp(cs->magic, "\x28\xcd\x3d\x45", 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;
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <byteswap.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
/* http://www.snia.org/standards/home */
|
||||
|
||||
#define DDF_GUID_LENGTH 24
|
||||
#define DDF_REV_LENGTH 8
|
||||
|
||||
struct ddf_header {
|
||||
uint8_t signature[4];
|
||||
uint32_t crc;
|
||||
uint8_t guid[DDF_GUID_LENGTH];
|
||||
uint8_t ddf_rev[DDF_REV_LENGTH];
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_ddf_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint64_t ddf_off;
|
||||
const uint8_t *buf;
|
||||
struct ddf_header *ddf;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
if (size < 0x30000)
|
||||
return -1;
|
||||
|
||||
/* header at last sector */
|
||||
ddf_off = ((size / 0x200)-1) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + ddf_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
ddf = (struct ddf_header *) buf;
|
||||
if (memcmp(ddf->signature, "\x11\xde\x11\xde", 4) == 0) {
|
||||
info("header (little endian) found at %" PRIu64 "\n", (off + ddf_off));
|
||||
goto found;
|
||||
}
|
||||
if (memcmp(ddf->signature, "\xde\x11\xde\x11", 4) == 0) {
|
||||
info("header (big endian) found at %" PRIu64 "\n", (off + ddf_off));
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* adaptec non-standard header location */
|
||||
ddf_off = ((size / 0x200)-257) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + ddf_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
ddf = (struct ddf_header *) buf;
|
||||
if (memcmp(ddf->signature, "\x11\xde\x11\xde", 4) == 0) {
|
||||
info("header adaptec (little endian) found at %" PRIu64 "\n", (off + ddf_off));
|
||||
goto found;
|
||||
}
|
||||
if (memcmp(ddf->signature, "\xde\x11\xde\x11", 4) == 0) {
|
||||
info("header adaptec (big endian) found at %" PRIu64 "\n", (off + ddf_off));
|
||||
goto found;
|
||||
}
|
||||
|
||||
return -1;
|
||||
found:
|
||||
volume_id_set_uuid(id, ddf->guid, DDF_GUID_LENGTH, UUID_STRING);
|
||||
snprintf(id->type_version, DDF_REV_LENGTH + 1, "%s", ddf->ddf_rev);
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "ddf_raid_member";
|
||||
return 0;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
volume_id_log_fn
|
||||
volume_id_get_label
|
||||
volume_id_get_label_raw
|
||||
volume_id_get_uuid
|
||||
volume_id_get_uuid_raw
|
||||
volume_id_get_uuid_sub
|
||||
volume_id_get_usage
|
||||
volume_id_get_type
|
||||
volume_id_get_type_version
|
||||
volume_id_open_fd
|
||||
volume_id_close
|
||||
volume_id_probe_all
|
||||
volume_id_probe_filesystem
|
||||
volume_id_probe_raid
|
||||
volume_id_all_probers
|
||||
volume_id_get_prober_by_type
|
||||
volume_id_encode_string
|
@ -1,203 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
|
||||
* Copyright (C) 2008 Theodore Ts'o <tytso@mit.edu>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct ext2_super_block {
|
||||
uint32_t s_inodes_count;
|
||||
uint32_t s_blocks_count;
|
||||
uint32_t s_r_blocks_count;
|
||||
uint32_t s_free_blocks_count;
|
||||
uint32_t s_free_inodes_count;
|
||||
uint32_t s_first_data_block;
|
||||
uint32_t s_log_block_size;
|
||||
uint32_t s_log_frag_size;
|
||||
uint32_t s_blocks_per_group;
|
||||
uint32_t s_frags_per_group;
|
||||
uint32_t s_inodes_per_group;
|
||||
uint32_t s_mtime;
|
||||
uint32_t s_wtime;
|
||||
uint16_t s_mnt_count;
|
||||
uint16_t s_max_mnt_count;
|
||||
uint16_t s_magic;
|
||||
uint16_t s_state;
|
||||
uint16_t s_errors;
|
||||
uint16_t s_minor_rev_level;
|
||||
uint32_t s_lastcheck;
|
||||
uint32_t s_checkinterval;
|
||||
uint32_t s_creator_os;
|
||||
uint32_t s_rev_level;
|
||||
uint16_t s_def_resuid;
|
||||
uint16_t s_def_resgid;
|
||||
uint32_t s_first_ino;
|
||||
uint16_t s_inode_size;
|
||||
uint16_t s_block_group_nr;
|
||||
uint32_t s_feature_compat;
|
||||
uint32_t s_feature_incompat;
|
||||
uint32_t s_feature_ro_compat;
|
||||
uint8_t s_uuid[16];
|
||||
uint8_t s_volume_name[16];
|
||||
uint8_t s_last_mounted[64];
|
||||
uint32_t s_algorithm_usage_bitmap;
|
||||
uint8_t s_prealloc_blocks;
|
||||
uint8_t s_prealloc_dir_blocks;
|
||||
uint16_t s_reserved_gdt_blocks;
|
||||
uint8_t s_journal_uuid[16];
|
||||
uint32_t s_journal_inum;
|
||||
uint32_t s_journal_dev;
|
||||
uint32_t s_last_orphan;
|
||||
uint32_t s_hash_seed[4];
|
||||
uint8_t s_def_hash_version;
|
||||
uint8_t s_jnl_backup_type;
|
||||
uint16_t s_reserved_word_pad;
|
||||
uint32_t s_default_mount_opts;
|
||||
uint32_t s_first_meta_bg;
|
||||
uint32_t s_mkfs_time;
|
||||
uint32_t s_jnl_blocks[17];
|
||||
uint32_t s_blocks_count_hi;
|
||||
uint32_t s_r_blocks_count_hi;
|
||||
uint32_t s_free_blocks_hi;
|
||||
uint16_t s_min_extra_isize;
|
||||
uint16_t s_want_extra_isize;
|
||||
uint32_t s_flags;
|
||||
} PACKED;
|
||||
|
||||
#define EXT_SUPER_MAGIC 0xEF53
|
||||
#define EXT2_FLAGS_TEST_FILESYS 0x0004
|
||||
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
|
||||
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
|
||||
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
|
||||
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
|
||||
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
|
||||
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
|
||||
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
|
||||
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
|
||||
|
||||
|
||||
#define EXT2_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
|
||||
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
|
||||
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
|
||||
#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT2_FEATURE_RO_COMPAT_SUPP
|
||||
|
||||
#define EXT2_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
|
||||
EXT2_FEATURE_INCOMPAT_META_BG)
|
||||
#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED ~EXT2_FEATURE_INCOMPAT_SUPP
|
||||
|
||||
#define EXT3_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
|
||||
EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
|
||||
EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
|
||||
#define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP
|
||||
|
||||
#define EXT3_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE| \
|
||||
EXT3_FEATURE_INCOMPAT_RECOVER| \
|
||||
EXT2_FEATURE_INCOMPAT_META_BG)
|
||||
#define EXT3_FEATURE_INCOMPAT_UNSUPPORTED ~EXT3_FEATURE_INCOMPAT_SUPP
|
||||
|
||||
#define EXT_SUPERBLOCK_OFFSET 0x400
|
||||
#define EXT3_MIN_BLOCK_SIZE 0x400
|
||||
#define EXT3_MAX_BLOCK_SIZE 0x1000
|
||||
|
||||
int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct ext2_super_block *es;
|
||||
size_t bsize;
|
||||
uint32_t feature_compat;
|
||||
uint32_t feature_ro_compat;
|
||||
uint32_t feature_incompat;
|
||||
uint32_t flags;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
es = (struct ext2_super_block *) volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (es == NULL)
|
||||
return -1;
|
||||
|
||||
if (es->s_magic != cpu_to_le16(EXT_SUPER_MAGIC))
|
||||
return -1;
|
||||
|
||||
bsize = 0x400 << le32_to_cpu(es->s_log_block_size);
|
||||
dbg("ext blocksize 0x%zx\n", bsize);
|
||||
if (bsize < EXT3_MIN_BLOCK_SIZE || bsize > EXT3_MAX_BLOCK_SIZE) {
|
||||
dbg("invalid ext blocksize\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
feature_compat = le32_to_cpu(es->s_feature_compat);
|
||||
feature_ro_compat = le32_to_cpu(es->s_feature_ro_compat);
|
||||
feature_incompat = le32_to_cpu(es->s_feature_incompat);
|
||||
flags = le32_to_cpu(es->s_flags);
|
||||
|
||||
/* external journal device is jbd */
|
||||
if ((feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) != 0) {
|
||||
volume_id_set_usage(id, VOLUME_ID_OTHER);
|
||||
id->type = "jbd";
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* has journal */
|
||||
if ((feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) {
|
||||
/* "use on development code" is ext4dev */
|
||||
if ((flags & EXT2_FLAGS_TEST_FILESYS) != 0) {
|
||||
id->type = "ext4dev";
|
||||
goto found;
|
||||
}
|
||||
|
||||
/* incompatible ext3 features is ext4 */
|
||||
if ((feature_ro_compat & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) != 0 ||
|
||||
(feature_incompat & EXT3_FEATURE_INCOMPAT_UNSUPPORTED) != 0) {
|
||||
id->type = "ext4";
|
||||
goto found;
|
||||
}
|
||||
|
||||
id->type = "ext3";
|
||||
goto found;
|
||||
} else {
|
||||
/* no incompatible ext2 feature is ext2 */
|
||||
if ((feature_ro_compat & EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) == 0 &&
|
||||
(feature_incompat & EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0) {
|
||||
id->type = "ext2";
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
found:
|
||||
volume_id_set_label_raw(id, es->s_volume_name, 16);
|
||||
volume_id_set_label_string(id, es->s_volume_name, 16);
|
||||
volume_id_set_uuid(id, es->s_uuid, 0, UUID_DCE);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u",
|
||||
le32_to_cpu(es->s_rev_level), le16_to_cpu(es->s_minor_rev_level));
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
return 0;
|
||||
}
|
@ -1,509 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004-2007 Kay Sievers <kay.sievers@vrfy.org>
|
||||
* Copyright (C) 2007 Ryan Lortie <desrt@desrt.ca>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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
|
||||
|
||||
#define VFAT_LFN_SEQ_MASK 0x3f
|
||||
#define VFAT_LFN_SEQ_LAST 0x40
|
||||
#define VFAT_LFN_SEQ_MAX 20
|
||||
#define VFAT_LFN_CHARS_PER_ENTRY (5 + 6 + 2)
|
||||
#define VFAT_LOWERCASE_NAME 0x10
|
||||
#define VFAT_LOWERCASE_EXT 0x08
|
||||
|
||||
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];
|
||||
} PACKED fat;
|
||||
struct fat32_super_block {
|
||||
uint32_t fat32_length;
|
||||
uint16_t flags;
|
||||
uint8_t version[2];
|
||||
uint32_t root_cluster;
|
||||
uint16_t fsinfo_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];
|
||||
} PACKED fat32;
|
||||
} PACKED type;
|
||||
} PACKED;
|
||||
|
||||
struct fat32_fsinfo {
|
||||
uint8_t signature1[4];
|
||||
uint32_t reserved1[120];
|
||||
uint8_t signature2[4];
|
||||
uint32_t free_clusters;
|
||||
uint32_t next_cluster;
|
||||
uint32_t reserved2[4];
|
||||
} PACKED;
|
||||
|
||||
struct vfat_dir_entry {
|
||||
uint8_t name[11];
|
||||
uint8_t attr;
|
||||
uint8_t lowercase;
|
||||
uint8_t fine_time_creat;
|
||||
uint16_t time_creat;
|
||||
uint16_t date_creat;
|
||||
uint16_t date_acc;
|
||||
uint16_t cluster_high;
|
||||
uint16_t time_write;
|
||||
uint16_t date_write;
|
||||
uint16_t cluster_low;
|
||||
uint32_t size;
|
||||
} PACKED;
|
||||
|
||||
|
||||
struct vfat_lfn_entry {
|
||||
uint8_t seq;
|
||||
uint16_t name0[5];
|
||||
uint8_t attr;
|
||||
uint8_t reserved;
|
||||
uint8_t cksum;
|
||||
uint16_t name1[6];
|
||||
uint16_t cluster;
|
||||
uint16_t name2[2];
|
||||
} PACKED;
|
||||
|
||||
static uint8_t fat_lfn_checksum(const uint8_t name[11])
|
||||
{
|
||||
uint8_t cksum = 0;
|
||||
int i;
|
||||
|
||||
/* http://en.wikipedia.org/wiki/File_Allocation_Table */
|
||||
for (i = 0; i < 11; i++)
|
||||
cksum = ((cksum & 1) ? 0x80 : 0) + (cksum >> 1) + name[i];
|
||||
|
||||
return cksum;
|
||||
}
|
||||
|
||||
static size_t fat_read_lfn(uint8_t *filename, size_t fnsize,
|
||||
struct vfat_dir_entry *dir,
|
||||
struct vfat_dir_entry *entry)
|
||||
{
|
||||
uint8_t buffer[VFAT_LFN_SEQ_MAX * VFAT_LFN_CHARS_PER_ENTRY * 2];
|
||||
uint8_t expected_seq = 1;
|
||||
uint8_t cksum;
|
||||
size_t len = 0;
|
||||
size_t fnlen = 0;
|
||||
|
||||
cksum = fat_lfn_checksum(entry->name);
|
||||
|
||||
while (--entry >= dir) {
|
||||
struct vfat_lfn_entry *lfn = (struct vfat_lfn_entry *) entry;
|
||||
|
||||
if (expected_seq > VFAT_LFN_SEQ_MAX)
|
||||
break;
|
||||
|
||||
if ((lfn->attr & FAT_ATTR_MASK) != FAT_ATTR_LONG_NAME)
|
||||
break;
|
||||
|
||||
if (lfn->cksum != cksum)
|
||||
break;
|
||||
|
||||
if ((lfn->seq & VFAT_LFN_SEQ_MASK) != expected_seq++)
|
||||
break;
|
||||
|
||||
if (lfn->cluster != 0)
|
||||
break;
|
||||
|
||||
/* extra paranoia -- should never happen */
|
||||
if (len + sizeof(lfn->name0) + sizeof(lfn->name1) +
|
||||
sizeof(lfn->name2) > sizeof(buffer))
|
||||
break;
|
||||
|
||||
memcpy (&buffer[len], lfn->name0, sizeof(lfn->name0));
|
||||
len += sizeof(lfn->name0);
|
||||
memcpy (&buffer[len], lfn->name1, sizeof(lfn->name1));
|
||||
len += sizeof(lfn->name1);
|
||||
memcpy (&buffer[len], lfn->name2, sizeof(lfn->name2));
|
||||
len += sizeof(lfn->name2);
|
||||
|
||||
if (lfn->seq & VFAT_LFN_SEQ_LAST) {
|
||||
fnlen = volume_id_set_unicode16(filename, fnsize, buffer, LE, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fnlen;
|
||||
}
|
||||
|
||||
static size_t fat_read_filename(uint8_t *filename, size_t fnsize,
|
||||
struct vfat_dir_entry *dir, struct vfat_dir_entry *entry)
|
||||
{
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
/* check if maybe we have LFN entries */
|
||||
len = fat_read_lfn(filename, fnsize, dir, entry);
|
||||
if (len > 0)
|
||||
goto out;
|
||||
|
||||
/* else, read the normal 8.3 name */
|
||||
for (i = 0; i < 11; i++) {
|
||||
if (entry->lowercase & ((i < 8) ? VFAT_LOWERCASE_NAME : VFAT_LOWERCASE_EXT))
|
||||
filename[i] = tolower(entry->name[i]);
|
||||
else
|
||||
filename[i] = entry->name[i];
|
||||
}
|
||||
len = 11;
|
||||
|
||||
out:
|
||||
filename[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
/* fills filename, returns string length */
|
||||
static size_t get_fat_attr_volume_id(uint8_t *filename, size_t fnsize,
|
||||
struct vfat_dir_entry *dir, unsigned int count)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
/* end marker */
|
||||
if (dir[i].name[0] == 0x00) {
|
||||
dbg("end of dir\n");
|
||||
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\n");
|
||||
return fat_read_filename(filename, fnsize, dir, &dir[i]);
|
||||
}
|
||||
|
||||
dbg("skip dir entry\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int volume_id_probe_vfat(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint8_t filename[255 * 3];
|
||||
struct vfat_super_block *vs;
|
||||
struct vfat_dir_entry *dir;
|
||||
struct fat32_fsinfo *fsinfo;
|
||||
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;
|
||||
uint16_t fat_length;
|
||||
uint32_t fat32_length;
|
||||
uint64_t root_start;
|
||||
uint32_t start_data_sect;
|
||||
uint16_t root_dir_entries;
|
||||
uint16_t fsinfo_sect;
|
||||
uint8_t *buf;
|
||||
uint32_t buf_size;
|
||||
uint32_t next;
|
||||
int maxloop;
|
||||
size_t fnlen;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off, 0x400);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
vs = (struct vfat_super_block *) buf;
|
||||
if (memcmp(vs->sysid, "NTFS", 4) == 0)
|
||||
return -1;
|
||||
|
||||
/* believe only that's fat, don't trust the version */
|
||||
if (memcmp(vs->type.fat32.magic, "MSWIN", 5) == 0)
|
||||
goto magic;
|
||||
|
||||
if (memcmp(vs->type.fat32.magic, "FAT32 ", 8) == 0)
|
||||
goto magic;
|
||||
|
||||
if (memcmp(vs->type.fat.magic, "FAT16 ", 8) == 0)
|
||||
goto magic;
|
||||
|
||||
if (memcmp(vs->type.fat.magic, "MSDOS", 5) == 0)
|
||||
goto magic;
|
||||
|
||||
if (memcmp(vs->type.fat.magic, "FAT12 ", 8) == 0)
|
||||
goto magic;
|
||||
|
||||
/* check signature */
|
||||
if (buf[510] != 0x55 || buf[511] != 0xaa)
|
||||
return -1;
|
||||
|
||||
/* some old floppies don't have a magic, expect the boot jump address to match */
|
||||
if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
|
||||
vs->boot_jump[0] != 0xe9)
|
||||
return -1;
|
||||
|
||||
magic:
|
||||
info("magic found\n");
|
||||
/* reserverd sector count */
|
||||
if (!vs->reserved)
|
||||
return -1;
|
||||
|
||||
/* fat count */
|
||||
if (!vs->fats)
|
||||
return -1;
|
||||
|
||||
/* media check */
|
||||
if (vs->media < 0xf8 && vs->media != 0xf0)
|
||||
return -1;
|
||||
|
||||
/* cluster size check */
|
||||
if (vs->sectors_per_cluster == 0 ||
|
||||
(vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
|
||||
return -1;
|
||||
|
||||
/* sector size check */
|
||||
sector_size = le16_to_cpu(vs->sector_size);
|
||||
if (sector_size == 0 || ((sector_size & (sector_size-1)) != 0))
|
||||
return -1;
|
||||
|
||||
info("checks passed\n");
|
||||
dbg("sector_size 0x%x\n", sector_size);
|
||||
dbg("sectors_per_cluster 0x%x\n", vs->sectors_per_cluster);
|
||||
|
||||
dir_entries = le16_to_cpu(vs->dir_entries);
|
||||
reserved = le16_to_cpu(vs->reserved);
|
||||
dbg("reserved 0x%x\n", 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\n", sect_count);
|
||||
|
||||
fat_length = le16_to_cpu(vs->fat_length);
|
||||
info("fat_length 0x%x\n", fat_length);
|
||||
fat32_length = le32_to_cpu(vs->type.fat32.fat32_length);
|
||||
info("fat32_length 0x%x\n", fat32_length);
|
||||
|
||||
if (fat_length)
|
||||
fat_size = fat_length * vs->fats;
|
||||
else if (fat32_length)
|
||||
fat_size = fat32_length * vs->fats;
|
||||
else
|
||||
return -1;
|
||||
info("fat_size 0x%x\n", fat_size);
|
||||
|
||||
dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
|
||||
(sector_size-1)) / sector_size;
|
||||
info("dir_size 0x%x\n", dir_size);
|
||||
|
||||
cluster_count = sect_count - (reserved + fat_size + dir_size);
|
||||
cluster_count /= vs->sectors_per_cluster;
|
||||
info("cluster_count 0x%x\n", cluster_count);
|
||||
|
||||
/* must be FAT32 */
|
||||
if (!fat_length && fat32_length)
|
||||
goto fat32;
|
||||
|
||||
/* cluster_count tells us the format */
|
||||
if (cluster_count < FAT12_MAX)
|
||||
strcpy(id->type_version, "FAT12");
|
||||
else if (cluster_count < FAT16_MAX)
|
||||
strcpy(id->type_version, "FAT16");
|
||||
else
|
||||
goto fat32;
|
||||
|
||||
/* the label may be an attribute in the root directory */
|
||||
root_start = (reserved + fat_size) * sector_size;
|
||||
dbg("root dir start 0x%" PRIx64 "\n", root_start);
|
||||
root_dir_entries = le16_to_cpu(vs->dir_entries);
|
||||
dbg("expected entries 0x%x\n", 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;
|
||||
|
||||
fnlen = get_fat_attr_volume_id(filename, sizeof(filename), dir, root_dir_entries);
|
||||
|
||||
vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
|
||||
if (vs == NULL)
|
||||
return -1;
|
||||
|
||||
if (fnlen > 0 && memcmp(filename, "NO NAME ", 11) != 0) {
|
||||
volume_id_set_label_raw(id, filename, fnlen);
|
||||
volume_id_set_label_string(id, filename, fnlen);
|
||||
} 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, 0, UUID_DOS);
|
||||
goto found;
|
||||
|
||||
fat32:
|
||||
info("looking for FAT32\n");
|
||||
/*
|
||||
* FAT32 should have a valid signature in the fsinfo block,
|
||||
* but also allow all bytes set to '\0', because some volumes
|
||||
* do not set the signature at all.
|
||||
*/
|
||||
fsinfo_sect = le16_to_cpu(vs->type.fat32.fsinfo_sector);
|
||||
buf = volume_id_get_buffer(id, off + (fsinfo_sect * sector_size), 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
fsinfo = (struct fat32_fsinfo *) buf;
|
||||
info("signature1: 0x%02x%02x%02x%02x\n",
|
||||
fsinfo->signature1[0], fsinfo->signature1[1],
|
||||
fsinfo->signature1[2], fsinfo->signature1[3]);
|
||||
info("signature2: 0x%02x%02x%02x%02x\n",
|
||||
fsinfo->signature2[0], fsinfo->signature2[1],
|
||||
fsinfo->signature2[2], fsinfo->signature2[3]);
|
||||
if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 &&
|
||||
memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0)
|
||||
return -1;
|
||||
if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 &&
|
||||
memcmp(fsinfo->signature2, "\x00\x00\x00\x00", 4) != 0)
|
||||
return -1 ;
|
||||
info("FAT32 signatures ok\n");
|
||||
|
||||
vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
|
||||
if (vs == NULL)
|
||||
return -1;
|
||||
|
||||
strcpy(id->type_version, "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\n", 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\n", next);
|
||||
next_sect_off = (next - 2) * vs->sectors_per_cluster;
|
||||
next_off = (start_data_sect + next_sect_off) * sector_size;
|
||||
dbg("cluster offset 0x%" PRIx64 "\n", 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\n", count);
|
||||
|
||||
fnlen = get_fat_attr_volume_id(filename, sizeof(filename), dir, count);
|
||||
if (fnlen > 0)
|
||||
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 < 2 || next >= 0x0ffffff0)
|
||||
break;
|
||||
}
|
||||
if (maxloop == 0)
|
||||
dbg("reached maximum follow count of root cluster chain, give up\n");
|
||||
|
||||
vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
|
||||
if (vs == NULL)
|
||||
return -1;
|
||||
|
||||
if (fnlen > 0 && memcmp(filename, "NO NAME ", 11) != 0) {
|
||||
volume_id_set_label_raw(id, filename, fnlen);
|
||||
volume_id_set_label_string(id, filename, fnlen);
|
||||
} 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, 0, UUID_DOS);
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "vfat";
|
||||
/* we think this is fat, but we make sure no other signatures are found */
|
||||
id->force_unique_result = 1;
|
||||
return 0;
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2006 Red Hat, Inc. <redhat.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
/* Common gfs/gfs2 constants: */
|
||||
#define GFS_MAGIC 0x01161970
|
||||
#define GFS_DEFAULT_BSIZE 4096
|
||||
#define GFS_SUPERBLOCK_OFFSET (0x10 * GFS_DEFAULT_BSIZE)
|
||||
#define GFS_METATYPE_SB 1
|
||||
#define GFS_FORMAT_SB 100
|
||||
#define GFS_LOCKNAME_LEN 64
|
||||
|
||||
/* gfs1 constants: */
|
||||
#define GFS_FORMAT_FS 1309
|
||||
#define GFS_FORMAT_MULTI 1401
|
||||
/* gfs2 constants: */
|
||||
#define GFS2_FORMAT_FS 1801
|
||||
#define GFS2_FORMAT_MULTI 1900
|
||||
|
||||
struct gfs2_meta_header {
|
||||
uint32_t mh_magic;
|
||||
uint32_t mh_type;
|
||||
uint64_t __pad0; /* Was generation number in gfs1 */
|
||||
uint32_t mh_format;
|
||||
uint32_t __pad1; /* Was incarnation number in gfs1 */
|
||||
};
|
||||
|
||||
struct gfs2_inum {
|
||||
uint64_t no_formal_ino;
|
||||
uint64_t no_addr;
|
||||
};
|
||||
|
||||
struct gfs2_sb {
|
||||
struct gfs2_meta_header sb_header;
|
||||
|
||||
uint32_t sb_fs_format;
|
||||
uint32_t sb_multihost_format;
|
||||
uint32_t __pad0; /* Was superblock flags in gfs1 */
|
||||
|
||||
uint32_t sb_bsize;
|
||||
uint32_t sb_bsize_shift;
|
||||
uint32_t __pad1; /* Was journal segment size in gfs1 */
|
||||
|
||||
struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */
|
||||
struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */
|
||||
struct gfs2_inum sb_root_dir;
|
||||
|
||||
char sb_lockproto[GFS_LOCKNAME_LEN];
|
||||
char sb_locktable[GFS_LOCKNAME_LEN];
|
||||
|
||||
struct gfs2_inum __pad3; /* Was quota inode in gfs1 */
|
||||
struct gfs2_inum __pad4; /* Was licence inode in gfs1 */
|
||||
uint8_t sb_uuid[16]; /* The UUID maybe 0 for backwards compat */
|
||||
} PACKED;
|
||||
|
||||
static int uuid_non_zero(const uint8_t *p)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 16; i++) {
|
||||
if (p[i] != 0)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int volume_id_probe_gfs_generic(struct volume_id *id, uint64_t off, int vers)
|
||||
{
|
||||
struct gfs2_sb *sbd;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
sbd = (struct gfs2_sb *)
|
||||
volume_id_get_buffer(id, off + GFS_SUPERBLOCK_OFFSET, sizeof(struct gfs2_sb));
|
||||
if (sbd == NULL)
|
||||
return -1;
|
||||
|
||||
if (be32_to_cpu(sbd->sb_header.mh_magic) == GFS_MAGIC &&
|
||||
be32_to_cpu(sbd->sb_header.mh_type) == GFS_METATYPE_SB) {
|
||||
if (vers == 1) {
|
||||
if (be32_to_cpu(sbd->sb_fs_format) != GFS_FORMAT_FS ||
|
||||
be32_to_cpu(sbd->sb_multihost_format) != GFS_FORMAT_MULTI)
|
||||
return -1; /* not gfs1 */
|
||||
id->type = "gfs";
|
||||
}
|
||||
else if (vers == 2) {
|
||||
if (be32_to_cpu(sbd->sb_fs_format) != GFS2_FORMAT_FS ||
|
||||
be32_to_cpu(sbd->sb_multihost_format) != GFS2_FORMAT_MULTI)
|
||||
return -1; /* not gfs2 */
|
||||
id->type = "gfs2";
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
if (strlen(sbd->sb_locktable)) {
|
||||
uint8_t *label = (uint8_t *) sbd->sb_locktable;
|
||||
|
||||
volume_id_set_label_raw(id, label, GFS_LOCKNAME_LEN);
|
||||
volume_id_set_label_string(id, label, GFS_LOCKNAME_LEN);
|
||||
}
|
||||
if (vers == 2 && uuid_non_zero(sbd->sb_uuid))
|
||||
volume_id_set_uuid(id, sbd->sb_uuid, 0, UUID_DCE);
|
||||
strcpy(id->type_version, "1");
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int volume_id_probe_gfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
return volume_id_probe_gfs_generic(id, off, 1);
|
||||
}
|
||||
|
||||
int volume_id_probe_gfs2(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
return volume_id_probe_gfs_generic(id, off, 2);
|
||||
}
|
@ -1,325 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
#include "md5.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];
|
||||
} PACKED;
|
||||
|
||||
static 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;
|
||||
} PACKED *hfs;
|
||||
|
||||
struct hfsplus_bnode_descriptor {
|
||||
uint32_t next;
|
||||
uint32_t prev;
|
||||
uint8_t type;
|
||||
uint8_t height;
|
||||
uint16_t num_recs;
|
||||
uint16_t reserved;
|
||||
} 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;
|
||||
} PACKED;
|
||||
|
||||
struct hfsplus_catalog_key {
|
||||
uint16_t key_len;
|
||||
uint32_t parent_id;
|
||||
uint16_t unicode_len;
|
||||
uint8_t unicode[255 * 2];
|
||||
} PACKED;
|
||||
|
||||
struct hfsplus_extent {
|
||||
uint32_t start_block;
|
||||
uint32_t block_count;
|
||||
} 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];
|
||||
} PACKED;
|
||||
|
||||
static 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;
|
||||
} PACKED *hfsplus;
|
||||
|
||||
#define HFS_SUPERBLOCK_OFFSET 0x400
|
||||
#define HFS_NODE_LEAF 0xff
|
||||
#define HFSPLUS_POR_CNID 1
|
||||
|
||||
static void hfsid_set_uuid(struct volume_id *id, const uint8_t *hfs_id)
|
||||
{
|
||||
struct md5_ctx md5c;
|
||||
static const uint8_t hash_init[16] = {
|
||||
0xb3, 0xe2, 0x0f, 0x39, 0xf2, 0x92, 0x11, 0xd6,
|
||||
0x97, 0xa4, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
|
||||
};
|
||||
uint8_t uuid[16];
|
||||
|
||||
if (*((uint64_t *)hfs_id) == 0)
|
||||
return;
|
||||
|
||||
md5_init(&md5c);
|
||||
md5_update(&md5c, hash_init, 16);
|
||||
md5_update(&md5c, hfs_id, 8);
|
||||
md5_final(&md5c, uuid);
|
||||
|
||||
uuid[6] = 0x30 | (uuid[6] & 0x0f);
|
||||
uuid[8] = 0x80 | (uuid[8] & 0x3f);
|
||||
volume_id_set_uuid(id, uuid, 0, UUID_DCE);
|
||||
}
|
||||
|
||||
int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
unsigned int blocksize;
|
||||
unsigned int cat_block;
|
||||
unsigned int ext_block_start;
|
||||
unsigned int ext_block_count;
|
||||
int ext;
|
||||
unsigned int leaf_node_head;
|
||||
unsigned int leaf_node_count;
|
||||
unsigned int leaf_node_size;
|
||||
unsigned int leaf_block;
|
||||
uint64_t leaf_off;
|
||||
unsigned int alloc_block_size;
|
||||
unsigned int alloc_first_block;
|
||||
unsigned int embed_first_block;
|
||||
unsigned int record_count;
|
||||
struct hfsplus_bnode_descriptor *descr;
|
||||
struct hfsplus_bheader_record *bnode;
|
||||
struct hfsplus_catalog_key *key;
|
||||
unsigned int label_len;
|
||||
struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
|
||||
const uint8_t *buf;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
hfs = (struct hfs_mdb *) buf;
|
||||
if (memcmp(hfs->signature, "BD", 2) != 0)
|
||||
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\n", alloc_block_size);
|
||||
|
||||
alloc_first_block = be16_to_cpu(hfs->al_bl_st);
|
||||
dbg("alloc_first_block 0x%x\n", alloc_first_block);
|
||||
|
||||
embed_first_block = be16_to_cpu(hfs->embed_startblock);
|
||||
dbg("embed_first_block 0x%x\n", embed_first_block);
|
||||
|
||||
off += (alloc_first_block * 512) +
|
||||
(embed_first_block * alloc_block_size);
|
||||
dbg("hfs wrapped hfs+ found at offset 0x%" PRIx64 "\n", 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) ;
|
||||
}
|
||||
|
||||
hfsid_set_uuid(id, hfs->finder_info.id);
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "hfs";
|
||||
|
||||
return 0;
|
||||
|
||||
checkplus:
|
||||
hfsplus = (struct hfsplus_vol_header *) buf;
|
||||
if (memcmp(hfsplus->signature, "H+", 2) == 0)
|
||||
goto hfsplus;
|
||||
if (memcmp(hfsplus->signature, "HX", 2) == 0)
|
||||
goto hfsplus;
|
||||
return -1;
|
||||
|
||||
hfsplus:
|
||||
hfsid_set_uuid(id, hfsplus->finder_info.id);
|
||||
|
||||
blocksize = be32_to_cpu(hfsplus->blocksize);
|
||||
dbg("blocksize %u\n", blocksize);
|
||||
|
||||
memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
|
||||
cat_block = be32_to_cpu(extents[0].start_block);
|
||||
dbg("catalog start block 0x%x\n", 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\n", leaf_node_head);
|
||||
|
||||
leaf_node_size = be16_to_cpu(bnode->node_size);
|
||||
dbg("leaf node size 0x%x\n", leaf_node_size);
|
||||
|
||||
leaf_node_count = be32_to_cpu(bnode->leaf_count);
|
||||
dbg("leaf node count 0x%x\n", 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\n", 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\n", 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\n", descr->type);
|
||||
|
||||
record_count = be16_to_cpu(descr->num_recs);
|
||||
dbg("number of records %u\n", 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\n", be32_to_cpu(key->parent_id));
|
||||
if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
|
||||
goto found;
|
||||
|
||||
label_len = be16_to_cpu(key->unicode_len) * 2;
|
||||
dbg("label unicode16 len %i\n", 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;
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct hpt37x_meta {
|
||||
uint8_t filler1[32];
|
||||
uint32_t magic;
|
||||
} PACKED;
|
||||
|
||||
struct hpt45x_meta {
|
||||
uint32_t magic;
|
||||
} 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, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct hpt37x_meta *hpt;
|
||||
uint32_t magic;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
hpt = (struct hpt37x_meta *) buf;
|
||||
magic = le32_to_cpu(hpt->magic);
|
||||
if (magic != HPT37X_MAGIC_OK && magic != 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)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct hpt45x_meta *hpt;
|
||||
uint64_t meta_off;
|
||||
uint32_t magic;
|
||||
|
||||
dbg("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-11) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
hpt = (struct hpt45x_meta *) buf;
|
||||
magic = le32_to_cpu(hpt->magic);
|
||||
if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "highpoint_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct hpfs_boot_block
|
||||
{
|
||||
uint8_t jmp[3];
|
||||
uint8_t oem_id[8];
|
||||
uint8_t bytes_per_sector[2];
|
||||
uint8_t sectors_per_cluster;
|
||||
uint8_t n_reserved_sectors[2];
|
||||
uint8_t n_fats;
|
||||
uint8_t n_rootdir_entries[2];
|
||||
uint8_t n_sectors_s[2];
|
||||
uint8_t media_byte;
|
||||
uint16_t sectors_per_fat;
|
||||
uint16_t sectors_per_track;
|
||||
uint16_t heads_per_cyl;
|
||||
uint32_t n_hidden_sectors;
|
||||
uint32_t n_sectors_l;
|
||||
uint8_t drive_number;
|
||||
uint8_t mbz;
|
||||
uint8_t sig_28h;
|
||||
uint8_t vol_serno[4];
|
||||
uint8_t vol_label[11];
|
||||
uint8_t sig_hpfs[8];
|
||||
uint8_t pad[448];
|
||||
uint8_t magic[2];
|
||||
} PACKED;
|
||||
|
||||
struct hpfs_super
|
||||
{
|
||||
uint8_t magic[4];
|
||||
uint8_t magic1[4];
|
||||
uint8_t version;
|
||||
} PACKED;
|
||||
|
||||
|
||||
struct hpfs_spare_super
|
||||
{
|
||||
uint8_t magic[4];
|
||||
uint8_t magic1[4];
|
||||
} PACKED;
|
||||
|
||||
#define HPFS_SUPERBLOCK_OFFSET 0x2000
|
||||
#define HPFS_SUPERBLOCK_SPARE_OFFSET 0x2200
|
||||
|
||||
int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct hpfs_super *hs;
|
||||
struct hpfs_spare_super *hss;
|
||||
struct hpfs_boot_block *hbb;
|
||||
uint8_t version;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
hs = (struct hpfs_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x400);
|
||||
if (hs == NULL)
|
||||
return -1;
|
||||
if (memcmp(hs->magic, "\x49\xe8\x95\xf9", 4) != 0)
|
||||
return -1;
|
||||
|
||||
hss = (struct hpfs_spare_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_SPARE_OFFSET, 0x200);
|
||||
if (hss == NULL)
|
||||
return -1;
|
||||
if (memcmp(hss->magic, "\x49\x18\x91\xf9", 4) != 0)
|
||||
return -1;
|
||||
|
||||
version = hs->version;
|
||||
|
||||
/* if boot block looks valid, read label and uuid from there */
|
||||
hbb = (struct hpfs_boot_block *) volume_id_get_buffer(id, off, 0x200);
|
||||
if (hbb == NULL)
|
||||
return -1;
|
||||
if (memcmp(hbb->magic, "\x55\xaa", 2) == 0 &&
|
||||
memcmp(hbb->sig_hpfs, "HPFS", 4) == 0 &&
|
||||
hbb->sig_28h == 0x28) {
|
||||
volume_id_set_label_raw(id, hbb->vol_label, 11);
|
||||
volume_id_set_label_string(id, hbb->vol_label, 11);
|
||||
volume_id_set_uuid(id, hbb->vol_serno, 0, UUID_DOS);
|
||||
}
|
||||
sprintf(id->type_version, "%u", version);
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "hpfs";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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 type;
|
||||
uint8_t id[5];
|
||||
uint8_t 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];
|
||||
} PACKED;
|
||||
|
||||
struct high_sierra_volume_descriptor {
|
||||
uint8_t foo[8];
|
||||
uint8_t type;
|
||||
uint8_t id[5];
|
||||
uint8_t version;
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint8_t *buf;
|
||||
struct iso_volume_descriptor *is;
|
||||
struct high_sierra_volume_descriptor *hs;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", 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->id, "CD001", 5) == 0) {
|
||||
int vd_offset;
|
||||
int i;
|
||||
|
||||
dbg("read label from PVD\n");
|
||||
volume_id_set_label_raw(id, is->volume_id, 32);
|
||||
volume_id_set_label_string(id, is->volume_id, 32);
|
||||
|
||||
dbg("looking for SVDs\n");
|
||||
vd_offset = ISO_VD_OFFSET;
|
||||
for (i = 0; i < ISO_VD_MAX; i++) {
|
||||
uint8_t svd_label[64];
|
||||
|
||||
is = (struct iso_volume_descriptor *) volume_id_get_buffer(id, off + vd_offset, 0x200);
|
||||
if (is == NULL || is->type == ISO_VD_END)
|
||||
break;
|
||||
if (is->type != ISO_VD_SUPPLEMENTARY)
|
||||
continue;
|
||||
|
||||
dbg("found SVD at offset 0x%" PRIx64 "\n", (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\n");
|
||||
volume_id_set_unicode16(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\n");
|
||||
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;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct isw_meta {
|
||||
uint8_t sig[32];
|
||||
uint32_t check_sum;
|
||||
uint32_t mpb_size;
|
||||
uint32_t family_num;
|
||||
uint32_t generation_num;
|
||||
} 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)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
uint64_t meta_off;
|
||||
struct isw_meta *isw;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-2) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
isw = (struct isw_meta *) buf;
|
||||
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;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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];
|
||||
} PACKED;
|
||||
|
||||
#define JFS_SUPERBLOCK_OFFSET 0x8000
|
||||
|
||||
int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct jfs_super_block *js;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
js = (struct jfs_super_block *) 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, 0, UUID_DCE);
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "jfs";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct jmicron_meta {
|
||||
int8_t signature[2];
|
||||
uint8_t minor_version;
|
||||
uint8_t major_version;
|
||||
uint16_t checksum;
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_jmicron_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
uint64_t meta_off;
|
||||
struct jmicron_meta *jm;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-1) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
jm = (struct jmicron_meta *) buf;
|
||||
if (memcmp(jm->signature, "JM", 2) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u", jm->major_version, jm->minor_version);
|
||||
id->type = "jmicron_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,187 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads volume label and uuid
|
||||
*
|
||||
* Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _LIBVOLUME_ID_PRIVATE_H_
|
||||
#define _LIBVOLUME_ID_PRIVATE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <endian.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <byteswap.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
|
||||
#define ALLOWED_CHARS "#+-.:=@_"
|
||||
|
||||
#ifndef PACKED
|
||||
#define PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
static inline void __attribute__ ((format(printf, 1, 2)))
|
||||
log_null(const char *format, ...) {}
|
||||
|
||||
#define err(format, arg...) volume_id_log_fn(LOG_ERR, __FILE__, __LINE__, format, ##arg)
|
||||
#define info(format, arg...) volume_id_log_fn(LOG_INFO, __FILE__, __LINE__, format, ##arg)
|
||||
#ifdef DEBUG
|
||||
#define dbg(format, arg...) volume_id_log_fn(LOG_DEBUG, __FILE__, __LINE__, format, ##arg)
|
||||
#else
|
||||
#define dbg(format, arg...) log_null(format, ##arg)
|
||||
#endif
|
||||
|
||||
#if (__BYTE_ORDER == __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) bswap_16(x)
|
||||
#define be32_to_cpu(x) bswap_32(x)
|
||||
#define cpu_to_le16(x) (x)
|
||||
#define cpu_to_le32(x) (x)
|
||||
#define cpu_to_be32(x) bswap_32(x)
|
||||
#elif (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
#define le16_to_cpu(x) bswap_16(x)
|
||||
#define le32_to_cpu(x) bswap_32(x)
|
||||
#define le64_to_cpu(x) bswap_64(x)
|
||||
#define be16_to_cpu(x) (x)
|
||||
#define be32_to_cpu(x) (x)
|
||||
#define cpu_to_le16(x) bswap_16(x)
|
||||
#define cpu_to_le32(x) bswap_32(x)
|
||||
#define cpu_to_be32(x) (x)
|
||||
#endif /* __BYTE_ORDER */
|
||||
|
||||
enum uuid_format {
|
||||
UUID_STRING,
|
||||
UUID_HEX_STRING,
|
||||
UUID_DCE,
|
||||
UUID_DOS,
|
||||
UUID_64BIT_LE,
|
||||
UUID_MD,
|
||||
UUID_LVM,
|
||||
};
|
||||
|
||||
enum endian {
|
||||
LE = 0,
|
||||
BE = 1
|
||||
};
|
||||
|
||||
#define VOLUME_ID_LABEL_SIZE 64
|
||||
#define VOLUME_ID_UUID_SIZE 36
|
||||
#define VOLUME_ID_FORMAT_SIZE 32
|
||||
#define VOLUME_ID_PATH_MAX 256
|
||||
#define VOLUME_ID_PARTITIONS_MAX 256
|
||||
|
||||
/* 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
|
||||
|
||||
enum volume_id_usage {
|
||||
VOLUME_ID_UNUSED,
|
||||
VOLUME_ID_OTHER,
|
||||
VOLUME_ID_FILESYSTEM,
|
||||
VOLUME_ID_RAID,
|
||||
VOLUME_ID_CRYPTO,
|
||||
};
|
||||
|
||||
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];
|
||||
uint8_t uuid_sub_raw[VOLUME_ID_UUID_SIZE];
|
||||
size_t uuid_sub_raw_len;
|
||||
char uuid_sub[VOLUME_ID_UUID_SIZE+1];
|
||||
enum volume_id_usage usage_id;
|
||||
char *usage;
|
||||
char *type;
|
||||
char type_version[VOLUME_ID_FORMAT_SIZE];
|
||||
|
||||
int fd;
|
||||
uint8_t *sbbuf;
|
||||
size_t sbbuf_len;
|
||||
uint8_t *seekbuf;
|
||||
uint64_t seekbuf_off;
|
||||
size_t seekbuf_len;
|
||||
int force_unique_result;
|
||||
};
|
||||
|
||||
/* utils */
|
||||
extern int volume_id_utf8_encoded_valid_unichar(const char *str);
|
||||
extern size_t volume_id_set_unicode16(uint8_t *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count);
|
||||
extern void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id);
|
||||
extern void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count);
|
||||
extern void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count);
|
||||
extern void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count);
|
||||
extern void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format);
|
||||
extern void volume_id_set_uuid_sub(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format);
|
||||
extern uint8_t *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len);
|
||||
extern void volume_id_free_buffer(struct volume_id *id);
|
||||
|
||||
/* filesystems */
|
||||
extern int volume_id_probe_cramfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_vfat(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_ntfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_romfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_udf(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_vxfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_xfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_gfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_gfs2(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_btrfs(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
/* special formats */
|
||||
extern int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_luks(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
/* raid */
|
||||
extern int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_lvm2(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_ddf_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_oracleasm(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
/* bios raid */
|
||||
extern int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_adaptec_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_jmicron_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
|
||||
#endif
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads volume label and uuid
|
||||
*
|
||||
* Copyright (C) 2005-2008 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _LIBVOLUME_ID_H_
|
||||
#define _LIBVOLUME_ID_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct volume_id;
|
||||
typedef void (*volume_id_log_fn_t)(int priority, const char *file, int line, const char *format, ...)
|
||||
__attribute__ ((format(printf, 4, 5)));
|
||||
extern volume_id_log_fn_t volume_id_log_fn;
|
||||
|
||||
typedef int (*volume_id_probe_fn_t)(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
typedef int (*all_probers_fn_t)(volume_id_probe_fn_t probe_fn,
|
||||
struct volume_id *id, uint64_t off, uint64_t size,
|
||||
void *data);
|
||||
|
||||
extern struct volume_id *volume_id_open_fd(int fd);
|
||||
extern void volume_id_close(struct volume_id *id);
|
||||
extern int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size);
|
||||
extern const volume_id_probe_fn_t *volume_id_get_prober_by_type(const char *type);
|
||||
extern void volume_id_all_probers(all_probers_fn_t all_probers_fn,
|
||||
struct volume_id *id, uint64_t off, uint64_t size,
|
||||
void *data);
|
||||
extern int volume_id_get_label(struct volume_id *id, const char **label);
|
||||
extern int volume_id_get_label_raw(struct volume_id *id, const uint8_t **label, size_t *len);
|
||||
extern int volume_id_get_uuid(struct volume_id *id, const char **uuid);
|
||||
extern int volume_id_get_uuid_sub(struct volume_id *id, const char **uuid);
|
||||
extern int volume_id_get_uuid_raw(struct volume_id *id, const uint8_t **uuid, size_t *len);
|
||||
extern int volume_id_get_usage(struct volume_id *id, const char **usage);
|
||||
extern int volume_id_get_type(struct volume_id *id, const char **type);
|
||||
extern int volume_id_get_type_version(struct volume_id *id, const char **type_version);
|
||||
extern int volume_id_encode_string(const char *str, char *str_enc, size_t len);
|
||||
|
||||
#endif
|
@ -1,10 +0,0 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@prefix@
|
||||
libdir=@prefix@/@libdir_name@
|
||||
includedir=@prefix@/include
|
||||
|
||||
Name: libvolume_id
|
||||
Description: Library for reading metadata, label, uuid from various filesystems
|
||||
Version: @VERSION@
|
||||
Libs: -L${libdir} -lvolume_id
|
||||
Cflags: -I${includedir}
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <byteswap.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct mdp0_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;
|
||||
} PACKED;
|
||||
|
||||
struct mdp1_super_block {
|
||||
uint32_t magic;
|
||||
uint32_t major_version;
|
||||
uint32_t feature_map;
|
||||
uint32_t pad0;
|
||||
uint8_t set_uuid[16];
|
||||
uint8_t set_name[32];
|
||||
} PACKED;
|
||||
|
||||
#define MD_RESERVED_BYTES 0x10000
|
||||
#define MD_SB_MAGIC 0xa92b4efc
|
||||
|
||||
static int volume_id_probe_linux_raid0(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct mdp0_super_block *mdp0;
|
||||
union {
|
||||
uint32_t ints[4];
|
||||
uint8_t bytes[16];
|
||||
} uuid;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
buf = volume_id_get_buffer(id, off, 0x800);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
mdp0 = (struct mdp0_super_block *) buf;
|
||||
|
||||
if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
|
||||
uuid.ints[0] = bswap_32(mdp0->set_uuid0);
|
||||
if (le32_to_cpu(mdp0->minor_version >= 90)) {
|
||||
uuid.ints[1] = bswap_32(mdp0->set_uuid1);
|
||||
uuid.ints[2] = bswap_32(mdp0->set_uuid2);
|
||||
uuid.ints[3] = bswap_32(mdp0->set_uuid3);
|
||||
} else {
|
||||
uuid.ints[1] = 0;
|
||||
uuid.ints[2] = 0;
|
||||
uuid.ints[3] = 0;
|
||||
}
|
||||
volume_id_set_uuid(id, uuid.bytes, 0, UUID_MD);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u.%u",
|
||||
le32_to_cpu(mdp0->major_version),
|
||||
le32_to_cpu(mdp0->minor_version),
|
||||
le32_to_cpu(mdp0->patch_version));
|
||||
} else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
|
||||
uuid.ints[0] = mdp0->set_uuid0;
|
||||
if (be32_to_cpu(mdp0->minor_version >= 90)) {
|
||||
uuid.ints[1] = mdp0->set_uuid1;
|
||||
uuid.ints[2] = mdp0->set_uuid2;
|
||||
uuid.ints[3] = mdp0->set_uuid3;
|
||||
} else {
|
||||
uuid.ints[1] = 0;
|
||||
uuid.ints[2] = 0;
|
||||
uuid.ints[3] = 0;
|
||||
}
|
||||
volume_id_set_uuid(id, uuid.bytes, 0, UUID_MD);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%u.%u",
|
||||
be32_to_cpu(mdp0->major_version),
|
||||
be32_to_cpu(mdp0->minor_version),
|
||||
be32_to_cpu(mdp0->patch_version));
|
||||
} else
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "linux_raid_member";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int volume_id_probe_linux_raid1(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct mdp1_super_block *mdp1;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
buf = volume_id_get_buffer(id, off, 0x800);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
mdp1 = (struct mdp1_super_block *) buf;
|
||||
|
||||
if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC)
|
||||
return -1;
|
||||
|
||||
if (le32_to_cpu(mdp1->major_version) != 1)
|
||||
return -1;
|
||||
|
||||
volume_id_set_uuid(id, mdp1->set_uuid, 0, UUID_MD);
|
||||
volume_id_set_label_raw(id, mdp1->set_name, 32);
|
||||
volume_id_set_label_string(id, mdp1->set_name, 32);
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
id->type = "linux_raid_member";
|
||||
return 0;
|
||||
}
|
||||
|
||||
int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint64_t sboff;
|
||||
|
||||
if (size > MD_RESERVED_BYTES) {
|
||||
/* version 0 at the end of the device */
|
||||
sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES;
|
||||
if (volume_id_probe_linux_raid0(id, off + sboff, size) == 0)
|
||||
return 0;
|
||||
|
||||
/* version 1.0 at the end of the device */
|
||||
sboff = (size & ~(0x1000 - 1)) - 0x2000;
|
||||
if (volume_id_probe_linux_raid1(id, off + sboff, size) == 0) {
|
||||
strcpy(id->type_version, "1.0");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* version 1.1 at the start of the device */
|
||||
if (volume_id_probe_linux_raid1(id, off, size) == 0) {
|
||||
strcpy(id->type_version, "1.1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* version 1.2 at 4k offset from the start */
|
||||
if (volume_id_probe_linux_raid1(id, off + 0x1000, size) == 0) {
|
||||
strcpy(id->type_version, "1.2");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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];
|
||||
} PACKED;
|
||||
|
||||
#define LARGEST_PAGESIZE 0x10000
|
||||
|
||||
int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
unsigned int page;
|
||||
struct swap_header_v1_2 *sw;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
/* eek, 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 = "swap";
|
||||
strcpy(id->type_version, "1");
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (memcmp(buf, "SWAPSPACE2", 10) == 0) {
|
||||
id->type = "swap";
|
||||
strcpy(id->type_version, "2");
|
||||
goto found_label;
|
||||
}
|
||||
|
||||
if (memcmp(buf, "S1SUSPEND", 9) == 0) {
|
||||
id->type = "suspend";
|
||||
strcpy(id->type_version, "s1suspend");
|
||||
goto found_label;
|
||||
}
|
||||
|
||||
if (memcmp(buf, "ULSUSPEND", 9) == 0) {
|
||||
id->type = "suspend";
|
||||
strcpy(id->type_version, "ulsuspend");
|
||||
goto found_label;
|
||||
}
|
||||
|
||||
if (memcmp(buf, "\xed\xc3\x02\xe9\x98\x56\xe5\x0c", 8) == 0) {
|
||||
id->type = "suspend";
|
||||
strcpy(id->type_version, "tuxonice");
|
||||
goto found_label;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
found_label:
|
||||
sw = (struct swap_header_v1_2 *) volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2));
|
||||
if (sw != NULL) {
|
||||
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, 0, UUID_DCE);
|
||||
}
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_OTHER);
|
||||
/* we think this is swap, but we make sure no other signatures are found */
|
||||
id->force_unique_result = 1;
|
||||
return 0;
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct lsi_meta {
|
||||
uint8_t sig[6];
|
||||
} PACKED;
|
||||
|
||||
#define LSI_SIGNATURE "$XIDE$"
|
||||
|
||||
int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
uint64_t meta_off;
|
||||
struct lsi_meta *lsi;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-1) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
lsi = (struct lsi_meta *) buf;
|
||||
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;
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 W. Michael Petullo <mike@flyn.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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
|
||||
|
||||
#define LUKS_MAGIC_L 6
|
||||
#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/SECTOR_SIZE+1)
|
||||
#define UUID_STRING_L 40
|
||||
static const uint8_t LUKS_MAGIC[] = {'L','U','K','S', 0xba, 0xbe};
|
||||
|
||||
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, uint64_t size)
|
||||
{
|
||||
struct luks_phdr *header;
|
||||
|
||||
header = (struct luks_phdr*) 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, 36, UUID_HEX_STRING);
|
||||
snprintf(id->type_version, sizeof(header->version), "%u", le16_to_cpu(header->version));
|
||||
id->type = "crypto_LUKS";
|
||||
return 0;
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct lvm1_super_block {
|
||||
uint8_t id[2];
|
||||
} 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];
|
||||
} PACKED;
|
||||
|
||||
struct lvm2_pv_header {
|
||||
uint8_t id[32];
|
||||
uint64_t devsize_xl;
|
||||
} PACKED;
|
||||
|
||||
#define LVM1_SB_OFF 0x400
|
||||
#define LVM1_MAGIC "HM"
|
||||
|
||||
int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct lvm1_super_block *lvm;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", 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, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
unsigned int soff;
|
||||
struct lvm2_super_block *lvm;
|
||||
struct lvm2_pv_header *pvhdr;
|
||||
|
||||
dbg("probing at offset 0x%" PRIx64 "\n", 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:
|
||||
dbg("found at offset 0x%x (pv hdr offset 0x%x)\n",
|
||||
soff, cpu_to_le32(lvm->offset_xl));
|
||||
soff += cpu_to_le32(lvm->offset_xl);
|
||||
pvhdr = (struct lvm2_pv_header *) &buf[soff];
|
||||
memcpy(id->type_version, lvm->type, 8);
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
volume_id_set_uuid(id, pvhdr->id, 0, UUID_LVM);
|
||||
id->type = "LVM2_member";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* MD5 Message Digest Algorithm (RFC1321).
|
||||
*
|
||||
* Derived from cryptoapi implementation, originally based on the
|
||||
* public domain implementation written by Colin Plumb in 1993.
|
||||
*
|
||||
* Copyright (c) Cryptoapi developers.
|
||||
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <endian.h>
|
||||
#include <byteswap.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
#if !defined __BYTE_ORDER || !(__BYTE_ORDER == __LITTLE_ENDIAN) && !(__BYTE_ORDER == __BIG_ENDIAN)
|
||||
#error missing __BYTE_ORDER
|
||||
#endif
|
||||
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
#define MD5STEP(f, w, x, y, z, in, s) \
|
||||
(w += f(x, y, z) + in, w = (w<<s | w>>(32-s)) + x)
|
||||
|
||||
static void md5_transform(uint32_t *hash, uint32_t const *in)
|
||||
{
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
a = hash[0];
|
||||
b = hash[1];
|
||||
c = hash[2];
|
||||
d = hash[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
hash[0] += a;
|
||||
hash[1] += b;
|
||||
hash[2] += c;
|
||||
hash[3] += d;
|
||||
}
|
||||
|
||||
static inline void swab32_array(uint32_t *buf, unsigned int words)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < words; i++)
|
||||
buf[i] = bswap_32(buf[i]);
|
||||
}
|
||||
|
||||
static inline void le32_to_cpu_array(uint32_t *buf, unsigned int words)
|
||||
{
|
||||
#if (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
swab32_array(buf, words);
|
||||
#endif
|
||||
}
|
||||
static inline void cpu_to_le32_array(uint32_t *buf, unsigned int words)
|
||||
{
|
||||
#if (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
swab32_array(buf, words);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void md5_transform_helper(struct md5_ctx *ctx)
|
||||
{
|
||||
le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(uint32_t));
|
||||
md5_transform(ctx->hash, ctx->block);
|
||||
}
|
||||
|
||||
void md5_init(struct md5_ctx *mctx)
|
||||
{
|
||||
mctx->hash[0] = 0x67452301;
|
||||
mctx->hash[1] = 0xefcdab89;
|
||||
mctx->hash[2] = 0x98badcfe;
|
||||
mctx->hash[3] = 0x10325476;
|
||||
mctx->byte_count = 0;
|
||||
}
|
||||
|
||||
void md5_update(struct md5_ctx *mctx, const uint8_t *data, unsigned int len)
|
||||
{
|
||||
const uint32_t avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
|
||||
|
||||
mctx->byte_count += len;
|
||||
|
||||
if (avail > len) {
|
||||
memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
|
||||
data, len);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, avail);
|
||||
|
||||
md5_transform_helper(mctx);
|
||||
data += avail;
|
||||
len -= avail;
|
||||
|
||||
while (len >= sizeof(mctx->block)) {
|
||||
memcpy(mctx->block, data, sizeof(mctx->block));
|
||||
md5_transform_helper(mctx);
|
||||
data += sizeof(mctx->block);
|
||||
len -= sizeof(mctx->block);
|
||||
}
|
||||
|
||||
memcpy(mctx->block, data, len);
|
||||
}
|
||||
|
||||
void md5_final(struct md5_ctx *mctx, uint8_t *out)
|
||||
{
|
||||
const unsigned int offset = mctx->byte_count & 0x3f;
|
||||
char *p = (char *)mctx->block + offset;
|
||||
int padding = 56 - (offset + 1);
|
||||
|
||||
*p++ = 0x80;
|
||||
if (padding < 0) {
|
||||
memset(p, 0x00, padding + sizeof (uint64_t));
|
||||
md5_transform_helper(mctx);
|
||||
p = (char *)mctx->block;
|
||||
padding = 56;
|
||||
}
|
||||
|
||||
memset(p, 0, padding);
|
||||
mctx->block[14] = mctx->byte_count << 3;
|
||||
mctx->block[15] = mctx->byte_count >> 29;
|
||||
le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
|
||||
sizeof(uint64_t)) / sizeof(uint32_t));
|
||||
md5_transform(mctx->hash, mctx->block);
|
||||
cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(uint32_t));
|
||||
memcpy(out, mctx->hash, sizeof(mctx->hash));
|
||||
memset(mctx, 0, sizeof(*mctx));
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* MD5 Message Digest Algorithm (RFC1321).
|
||||
*
|
||||
* Derived from cryptoapi implementation, originally based on the
|
||||
* public domain implementation written by Colin Plumb in 1993.
|
||||
*
|
||||
* Copyright (c) Cryptoapi developers.
|
||||
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#define MD5_DIGEST_SIZE 16
|
||||
#define MD5_HMAC_BLOCK_SIZE 64
|
||||
#define MD5_BLOCK_WORDS 16
|
||||
#define MD5_HASH_WORDS 4
|
||||
|
||||
struct md5_ctx {
|
||||
uint32_t hash[MD5_HASH_WORDS];
|
||||
uint32_t block[MD5_BLOCK_WORDS];
|
||||
uint64_t byte_count;
|
||||
};
|
||||
|
||||
extern void md5_init(struct md5_ctx *mctx);
|
||||
extern void md5_update(struct md5_ctx *mctx, const uint8_t *data, unsigned int len);
|
||||
extern void md5_final(struct md5_ctx *mctx, uint8_t *out);
|
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
#define MINIX_SUPERBLOCK_OFFSET 0x400
|
||||
|
||||
#define MINIX_SUPER_MAGIC 0x137F
|
||||
#define MINIX_SUPER_MAGIC2 0x138F
|
||||
#define MINIX2_SUPER_MAGIC 0x2468
|
||||
#define MINIX2_SUPER_MAGIC2 0x2478
|
||||
#define MINIX3_SUPER_MAGIC 0x4d5a
|
||||
|
||||
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;
|
||||
} PACKED;
|
||||
|
||||
struct minix3_super_block {
|
||||
uint32_t s_ninodes;
|
||||
uint16_t s_pad0;
|
||||
uint16_t s_imap_blocks;
|
||||
uint16_t s_zmap_blocks;
|
||||
uint16_t s_firstdatazone;
|
||||
uint16_t s_log_zone_size;
|
||||
uint16_t s_pad1;
|
||||
uint32_t s_max_size;
|
||||
uint32_t s_zones;
|
||||
uint16_t s_magic;
|
||||
uint16_t s_pad2;
|
||||
uint16_t s_blocksize;
|
||||
uint8_t s_disk_version;
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
uint8_t *buf;
|
||||
struct minix_super_block *ms;
|
||||
struct minix3_super_block *m3s;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
ms = (struct minix_super_block *) buf;
|
||||
|
||||
if (ms->s_magic == MINIX_SUPER_MAGIC ||
|
||||
ms->s_magic == bswap_16(MINIX_SUPER_MAGIC)) {
|
||||
strcpy(id->type_version, "1");
|
||||
goto found;
|
||||
}
|
||||
if (ms->s_magic == MINIX_SUPER_MAGIC2 ||
|
||||
ms->s_magic == bswap_16(MINIX_SUPER_MAGIC2)) {
|
||||
strcpy(id->type_version, "1");
|
||||
goto found;
|
||||
}
|
||||
if (ms->s_magic == MINIX2_SUPER_MAGIC ||
|
||||
ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC)) {
|
||||
strcpy(id->type_version, "2");
|
||||
goto found;
|
||||
}
|
||||
if (ms->s_magic == MINIX2_SUPER_MAGIC2 ||
|
||||
ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC2)) {
|
||||
strcpy(id->type_version, "2");
|
||||
goto found;
|
||||
}
|
||||
|
||||
m3s = (struct minix3_super_block *) buf;
|
||||
if (m3s->s_magic == MINIX3_SUPER_MAGIC ||
|
||||
m3s->s_magic == bswap_16(MINIX3_SUPER_MAGIC)) {
|
||||
strcpy(id->type_version, "3");
|
||||
goto found;
|
||||
}
|
||||
goto exit;
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "minix";
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
return -1;
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
#define NW_SUPERBLOCK_OFFSET 0x1000
|
||||
|
||||
struct netware_super_block {
|
||||
uint8_t SBH_Signature[4];
|
||||
uint16_t SBH_VersionMajor;
|
||||
uint16_t SBH_VersionMinor;
|
||||
uint16_t SBH_VersionMediaMajor;
|
||||
uint16_t SBH_VersionMediaMinor;
|
||||
uint32_t SBH_ItemsMoved;
|
||||
uint8_t SBH_InternalID[16];
|
||||
uint32_t SBH_PackedSize;
|
||||
uint32_t SBH_Checksum;
|
||||
uint32_t supersyncid;
|
||||
int64_t superlocation[4];
|
||||
uint32_t physSizeUsed;
|
||||
uint32_t sizeUsed;
|
||||
uint32_t superTimeStamp;
|
||||
uint32_t reserved0[1];
|
||||
int64_t SBH_LoggedPoolDataBlk;
|
||||
int64_t SBH_PoolDataBlk;
|
||||
uint8_t SBH_OldInternalID[16];
|
||||
uint32_t SBH_PoolToLVStartUTC;
|
||||
uint32_t SBH_PoolToLVEndUTC;
|
||||
uint16_t SBH_VersionMediaMajorCreate;
|
||||
uint16_t SBH_VersionMediaMinorCreate;
|
||||
uint32_t SBH_BlocksMoved;
|
||||
uint32_t SBH_TempBTSpBlk;
|
||||
uint32_t SBH_TempFTSpBlk;
|
||||
uint32_t SBH_TempFTSpBlk1;
|
||||
uint32_t SBH_TempFTSpBlk2;
|
||||
uint32_t nssMagicNumber;
|
||||
uint32_t poolClassID;
|
||||
uint32_t poolID;
|
||||
uint32_t createTime;
|
||||
int64_t SBH_LoggedVolumeDataBlk;
|
||||
int64_t SBH_VolumeDataBlk;
|
||||
int64_t SBH_SystemBeastBlkNum;
|
||||
uint64_t totalblocks;
|
||||
uint16_t SBH_Name[64];
|
||||
uint8_t SBH_VolumeID[16];
|
||||
uint8_t SBH_PoolID[16];
|
||||
uint8_t SBH_PoolInternalID[16];
|
||||
uint64_t SBH_Lsn;
|
||||
uint32_t SBH_SS_Enabled;
|
||||
uint32_t SBH_SS_CreateTime;
|
||||
uint8_t SBH_SS_OriginalPoolID[16];
|
||||
uint8_t SBH_SS_OriginalVolumeID[16];
|
||||
uint8_t SBH_SS_Guid[16];
|
||||
uint16_t SBH_SS_OriginalName[64];
|
||||
uint32_t reserved2[64-(2+46)];
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct netware_super_block *nw;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
nw = (struct netware_super_block *) volume_id_get_buffer(id, off + NW_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (nw == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(nw->SBH_Signature, "SPB5", 4) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_uuid(id, nw->SBH_PoolID, 0, UUID_DCE);
|
||||
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u.%02u",
|
||||
le16_to_cpu(nw->SBH_VersionMediaMajor), le16_to_cpu(nw->SBH_VersionMediaMinor));
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "nss";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
static 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;
|
||||
} PACKED *ns;
|
||||
|
||||
static 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;
|
||||
} PACKED *mftr;
|
||||
|
||||
static 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;
|
||||
} PACKED *attr;
|
||||
|
||||
static struct volume_info {
|
||||
uint64_t reserved;
|
||||
uint8_t major_ver;
|
||||
uint8_t minor_ver;
|
||||
} PACKED *info;
|
||||
|
||||
#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, uint64_t size)
|
||||
{
|
||||
uint8_t volume_serial[8];
|
||||
unsigned int sector_size;
|
||||
unsigned int cluster_size;
|
||||
uint64_t mft_cluster;
|
||||
uint64_t mft_off;
|
||||
unsigned int mft_record_size;
|
||||
unsigned int attr_type;
|
||||
unsigned int attr_off;
|
||||
unsigned int attr_len;
|
||||
unsigned int val_off;
|
||||
unsigned int val_len;
|
||||
const uint8_t *buf;
|
||||
const uint8_t *val;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
ns = (struct ntfs_super_block *) volume_id_get_buffer(id, off, 0x200);
|
||||
if (ns == NULL)
|
||||
return -1;
|
||||
|
||||
if (memcmp(ns->oem_id, "NTFS", 4) != 0)
|
||||
return -1;
|
||||
|
||||
memcpy(volume_serial, ns->volume_serial, sizeof(volume_serial));
|
||||
|
||||
sector_size = le16_to_cpu(ns->bytes_per_sector);
|
||||
if (sector_size < 0x200)
|
||||
return -1;
|
||||
|
||||
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\n", sector_size);
|
||||
dbg("clustersize 0x%x\n", cluster_size);
|
||||
dbg("mftcluster %" PRIu64 "\n", mft_cluster);
|
||||
dbg("mftoffset 0x%" PRIx64 "\n", mft_off);
|
||||
dbg("cluster per mft_record %i\n", ns->cluster_per_mft_record);
|
||||
dbg("mft record size %i\n", mft_record_size);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
|
||||
mft_record_size);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
mftr = (struct master_file_table_record*) buf;
|
||||
dbg("mftr->magic '%c%c%c%c'\n", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
|
||||
if (memcmp(mftr->magic, "FILE", 4) != 0)
|
||||
return -1;
|
||||
|
||||
attr_off = le16_to_cpu(mftr->attrs_offset);
|
||||
dbg("file $Volume's attributes are at offset %i\n", attr_off);
|
||||
|
||||
while (1) {
|
||||
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\n",
|
||||
attr_type, attr_len, attr_off);
|
||||
|
||||
if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
|
||||
dbg("found info, len %i\n", 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\n", 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);
|
||||
}
|
||||
}
|
||||
|
||||
volume_id_set_uuid(id, volume_serial, 0, UUID_64BIT_LE);
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "ntfs";
|
||||
/* we think this is ntfs, but we make sure no other signatures are found */
|
||||
id->force_unique_result = 1;
|
||||
return 0;
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct nvidia_meta {
|
||||
uint8_t vendor[8];
|
||||
uint32_t size;
|
||||
uint32_t chksum;
|
||||
uint16_t version;
|
||||
} PACKED;
|
||||
|
||||
#define NVIDIA_SIGNATURE "NVIDIA"
|
||||
|
||||
int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
uint64_t meta_off;
|
||||
struct nvidia_meta *nv;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-2) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
nv = (struct nvidia_meta *) buf;
|
||||
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;
|
||||
}
|
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Andre Masella <andre@masella.no-ip.org>
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct ocfs1_super_block_header {
|
||||
uint32_t minor_version;
|
||||
uint32_t major_version;
|
||||
uint8_t signature[128];
|
||||
uint8_t mount_point[128];
|
||||
uint64_t serial_num;
|
||||
uint64_t device_size;
|
||||
uint64_t start_off;
|
||||
uint64_t bitmap_off;
|
||||
uint64_t publ_off;
|
||||
uint64_t vote_off;
|
||||
uint64_t root_bitmap_off;
|
||||
uint64_t data_start_off;
|
||||
uint64_t root_bitmap_size;
|
||||
uint64_t root_off;
|
||||
uint64_t root_size;
|
||||
uint64_t cluster_size;
|
||||
uint64_t num_nodes;
|
||||
uint64_t num_clusters;
|
||||
uint64_t dir_node_size;
|
||||
uint64_t file_node_size;
|
||||
uint64_t internal_off;
|
||||
uint64_t node_cfg_off;
|
||||
uint64_t node_cfg_size;
|
||||
uint64_t new_cfg_off;
|
||||
uint32_t prot_bits;
|
||||
int32_t excl_mount;
|
||||
} PACKED;
|
||||
|
||||
struct ocfs1_super_block_label {
|
||||
struct ocfs1_disk_lock {
|
||||
uint32_t curr_master;
|
||||
uint8_t file_lock;
|
||||
uint8_t compat_pad[3];
|
||||
uint64_t last_write_time;
|
||||
uint64_t last_read_time;
|
||||
uint32_t writer_node_num;
|
||||
uint32_t reader_node_num;
|
||||
uint64_t oin_node_map;
|
||||
uint64_t dlock_seq_num;
|
||||
} PACKED disk_lock;
|
||||
uint8_t label[64];
|
||||
uint16_t label_len;
|
||||
uint8_t vol_id[16];
|
||||
uint16_t vol_id_len;
|
||||
uint8_t cluster_name[64];
|
||||
uint16_t cluster_name_len;
|
||||
} PACKED;
|
||||
|
||||
struct ocfs2_super_block {
|
||||
uint8_t i_signature[8];
|
||||
uint32_t i_generation;
|
||||
int16_t i_suballoc_slot;
|
||||
uint16_t i_suballoc_bit;
|
||||
uint32_t i_reserved0;
|
||||
uint32_t i_clusters;
|
||||
uint32_t i_uid;
|
||||
uint32_t i_gid;
|
||||
uint64_t i_size;
|
||||
uint16_t i_mode;
|
||||
uint16_t i_links_count;
|
||||
uint32_t i_flags;
|
||||
uint64_t i_atime;
|
||||
uint64_t i_ctime;
|
||||
uint64_t i_mtime;
|
||||
uint64_t i_dtime;
|
||||
uint64_t i_blkno;
|
||||
uint64_t i_last_eb_blk;
|
||||
uint32_t i_fs_generation;
|
||||
uint32_t i_atime_nsec;
|
||||
uint32_t i_ctime_nsec;
|
||||
uint32_t i_mtime_nsec;
|
||||
uint64_t i_reserved1[9];
|
||||
uint64_t i_pad1;
|
||||
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;
|
||||
uint16_t s_errors;
|
||||
uint32_t s_checkinterval;
|
||||
uint64_t s_lastcheck;
|
||||
uint32_t s_creator_os;
|
||||
uint32_t s_feature_compat;
|
||||
uint32_t s_feature_incompat;
|
||||
uint32_t s_feature_ro_compat;
|
||||
uint64_t s_root_blkno;
|
||||
uint64_t s_system_dir_blkno;
|
||||
uint32_t s_blocksize_bits;
|
||||
uint32_t s_clustersize_bits;
|
||||
uint16_t s_max_slots;
|
||||
uint16_t s_reserved1;
|
||||
uint32_t s_reserved2;
|
||||
uint64_t s_first_cluster_group;
|
||||
uint8_t s_label[64];
|
||||
uint8_t s_uuid[16];
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct ocfs1_super_block_header *osh;
|
||||
struct ocfs1_super_block_label *osl;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
osh = (struct ocfs1_super_block_header *) buf;
|
||||
if (memcmp(osh->signature, "OracleCFS", 9) != 0)
|
||||
return -1;
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1,
|
||||
"%u.%u", osh->major_version, osh->minor_version);
|
||||
|
||||
dbg("found OracleCFS signature, now reading label\n");
|
||||
buf = volume_id_get_buffer(id, off + 0x200, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
osl = (struct ocfs1_super_block_label *) buf;
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
if (osl->label_len <= 64) {
|
||||
volume_id_set_label_raw(id, osl->label, 64);
|
||||
volume_id_set_label_string(id, osl->label, 64);
|
||||
}
|
||||
if (osl->vol_id_len == 16)
|
||||
volume_id_set_uuid(id, osl->vol_id, 0, UUID_DCE);
|
||||
id->type = "ocfs";
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define OCFS2_MAX_BLOCKSIZE 0x1000
|
||||
#define OCFS2_SUPER_BLOCK_BLKNO 2
|
||||
|
||||
int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct ocfs2_super_block *os;
|
||||
size_t blksize;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
for (blksize = 0x200; blksize <= OCFS2_MAX_BLOCKSIZE; blksize <<= 1) {
|
||||
buf = volume_id_get_buffer(id, off + OCFS2_SUPER_BLOCK_BLKNO * blksize, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
os = (struct ocfs2_super_block *) buf;
|
||||
if (memcmp(os->i_signature, "OCFSV2", 6) != 0)
|
||||
continue;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
volume_id_set_label_raw(id, os->s_label, 64);
|
||||
volume_id_set_label_string(id, os->s_label, 64);
|
||||
volume_id_set_uuid(id, os->s_uuid, 0, UUID_DCE);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1,
|
||||
"%u.%u", os->s_major_rev_level, os->s_minor_rev_level);
|
||||
id->type = "ocfs2";
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct oracleasm_super_block {
|
||||
uint8_t tag[8];
|
||||
uint8_t id[24];
|
||||
} PACKED;
|
||||
|
||||
#define ASM_SB_OFF 0x20
|
||||
#define ASM_MAGIC "ORCLDISK"
|
||||
|
||||
/*
|
||||
* Detect Oracle Automatic Storage Management (ASM).
|
||||
* It can do mirroring, but don't consider it RAID in the sense
|
||||
* that an ext3 filesystem could live inside. Thus, mark it 'other'.
|
||||
* There also is a magic word 'ORCLCLRD'; like blkid(8), we ignore that.
|
||||
*/
|
||||
int volume_id_probe_oracleasm(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct oracleasm_super_block *oracleasm;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + ASM_SB_OFF, 0x800);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
oracleasm = (struct oracleasm_super_block *) buf;
|
||||
|
||||
if (memcmp(oracleasm->tag, ASM_MAGIC, 8) != 0)
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_OTHER);
|
||||
volume_id_set_label_raw(id, oracleasm->id, 24);
|
||||
volume_id_set_label_string(id, oracleasm->id, 24);
|
||||
id->type = "oracleasm";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct promise_meta {
|
||||
uint8_t sig[24];
|
||||
} 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)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
struct promise_meta *pdc;
|
||||
unsigned int i;
|
||||
static unsigned int sectors[] = {
|
||||
63, 255, 256, 16, 399, 0
|
||||
};
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x40000)
|
||||
return -1;
|
||||
|
||||
for (i = 0; sectors[i] != 0; i++) {
|
||||
uint64_t meta_off;
|
||||
|
||||
meta_off = ((size / 0x200) - sectors[i]) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
pdc = (struct promise_meta *) buf;
|
||||
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;
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* 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 program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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];
|
||||
} PACKED;
|
||||
|
||||
struct reiser4_super_block {
|
||||
uint8_t magic[16];
|
||||
uint16_t dummy[2];
|
||||
uint8_t uuid[16];
|
||||
uint8_t label[16];
|
||||
uint64_t dummy2;
|
||||
} PACKED;
|
||||
|
||||
#define REISERFS1_SUPERBLOCK_OFFSET 0x2000
|
||||
#define REISERFS_SUPERBLOCK_OFFSET 0x10000
|
||||
|
||||
int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct reiserfs_super_block *rs;
|
||||
struct reiser4_super_block *rs4;
|
||||
uint8_t *buf;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
buf = volume_id_get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
rs = (struct reiserfs_super_block *) buf;
|
||||
if (memcmp(rs->magic, "ReIsErFs", 8) == 0) {
|
||||
strcpy(id->type_version, "3.5");
|
||||
id->type = "reiserfs";
|
||||
goto found;
|
||||
}
|
||||
if (memcmp(rs->magic, "ReIsEr2Fs", 9) == 0) {
|
||||
strcpy(id->type_version, "3.6");
|
||||
id->type = "reiserfs";
|
||||
goto found_label;
|
||||
}
|
||||
if (memcmp(rs->magic, "ReIsEr3Fs", 9) == 0) {
|
||||
strcpy(id->type_version, "JR");
|
||||
id->type = "reiserfs";
|
||||
goto found_label;
|
||||
}
|
||||
|
||||
rs4 = (struct reiser4_super_block *) buf;
|
||||
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, 0, UUID_DCE);
|
||||
id->type = "reiser4";
|
||||
goto found;
|
||||
}
|
||||
|
||||
buf = volume_id_get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
rs = (struct reiserfs_super_block *) buf;
|
||||
if (memcmp(rs->magic, "ReIsErFs", 8) == 0) {
|
||||
strcpy(id->type_version, "3.5");
|
||||
id->type = "reiserfs";
|
||||
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, 0, UUID_DCE);
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct romfs_super {
|
||||
uint8_t magic[8];
|
||||
uint32_t size;
|
||||
uint32_t checksum;
|
||||
uint8_t name[0];
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_romfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct romfs_super *rfs;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
rfs = (struct romfs_super *) 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;
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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;
|
||||
} PACKED;
|
||||
|
||||
#define SILICON_MAGIC 0x2F000000
|
||||
|
||||
int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
uint64_t meta_off;
|
||||
struct silicon_meta *sil;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-1) * 0x200;
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
sil = (struct silicon_meta *) buf;
|
||||
if (le32_to_cpu(sil->magic) != 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;
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
#define SQUASHFS_MAGIC 0x73717368
|
||||
#define SQUASHFS_MAGIC_LZMA 0x71736873
|
||||
|
||||
struct squashfs_super {
|
||||
uint32_t s_magic;
|
||||
uint32_t inodes;
|
||||
uint32_t bytes_used_2;
|
||||
uint32_t uid_start_2;
|
||||
uint32_t guid_start_2;
|
||||
uint32_t inode_table_start_2;
|
||||
uint32_t directory_table_start_2;
|
||||
uint16_t s_major;
|
||||
uint16_t s_minor;
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct squashfs_super *sqs;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
sqs = (struct squashfs_super *) volume_id_get_buffer(id, off, 0x200);
|
||||
if (sqs == NULL)
|
||||
return -1;
|
||||
|
||||
if (sqs->s_magic == SQUASHFS_MAGIC || sqs->s_magic == SQUASHFS_MAGIC_LZMA) {
|
||||
snprintf(id->type_version, sizeof(id->type_version), "%u.%u",
|
||||
sqs->s_major, sqs->s_minor);
|
||||
goto found;
|
||||
}
|
||||
if (sqs->s_magic == bswap_32(SQUASHFS_MAGIC) || sqs->s_magic == bswap_32(SQUASHFS_MAGIC_LZMA)) {
|
||||
snprintf(id->type_version, sizeof(id->type_version), "%u.%u",
|
||||
bswap_16(sqs->s_major), bswap_16(sqs->s_minor));
|
||||
goto found;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "squashfs";
|
||||
return 0;
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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;
|
||||
} 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;
|
||||
} 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, uint64_t size)
|
||||
{
|
||||
struct sysv_super *vs;
|
||||
struct xenix_super *xs;
|
||||
unsigned int boff;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
|
||||
vs = (struct sysv_super *)
|
||||
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 = (struct xenix_super *)
|
||||
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;
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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;
|
||||
} PACKED tag;
|
||||
union {
|
||||
struct anchor_descriptor {
|
||||
uint32_t length;
|
||||
uint32_t location;
|
||||
} PACKED anchor;
|
||||
struct primary_descriptor {
|
||||
uint32_t seq_num;
|
||||
uint32_t desc_num;
|
||||
struct dstring {
|
||||
uint8_t clen;
|
||||
uint8_t c[31];
|
||||
} PACKED ident;
|
||||
} PACKED primary;
|
||||
} PACKED type;
|
||||
} PACKED;
|
||||
|
||||
struct volume_structure_descriptor {
|
||||
uint8_t type;
|
||||
uint8_t id[5];
|
||||
uint8_t version;
|
||||
} PACKED;
|
||||
|
||||
#define UDF_VSD_OFFSET 0x8000
|
||||
|
||||
int volume_id_probe_udf(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct volume_descriptor *vd;
|
||||
struct volume_structure_descriptor *vsd;
|
||||
unsigned int bs;
|
||||
unsigned int b;
|
||||
unsigned int type;
|
||||
unsigned int count;
|
||||
unsigned int loc;
|
||||
unsigned int clen;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
vsd = (struct volume_structure_descriptor *) 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 = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
|
||||
if (vsd == NULL)
|
||||
return -1;
|
||||
dbg("test for blocksize: 0x%x\n", 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 = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
|
||||
if (vsd == NULL)
|
||||
return -1;
|
||||
|
||||
dbg("vsd: %c%c%c%c%c\n",
|
||||
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 = (struct volume_descriptor *) 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\n", count, loc);
|
||||
|
||||
/* pick the primary descriptor from the list */
|
||||
for (b = 0; b < count; b++) {
|
||||
vd = (struct volume_descriptor *) 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\n", 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\n", 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;
|
||||
}
|
@ -1,227 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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;
|
||||
} 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];
|
||||
} 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];
|
||||
} PACKED fs_cstotal;
|
||||
struct ufs_timeval {
|
||||
int32_t tv_sec;
|
||||
int32_t tv_usec;
|
||||
} PACKED fs_time;
|
||||
int64_t fs_size;
|
||||
int64_t fs_dsize;
|
||||
uint64_t fs_csaddr;
|
||||
int64_t fs_pendingblocks;
|
||||
int32_t fs_pendinginodes;
|
||||
} 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];
|
||||
} 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];
|
||||
} 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;
|
||||
} 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];
|
||||
} 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, uint64_t size)
|
||||
{
|
||||
uint32_t magic;
|
||||
int i;
|
||||
struct ufs_super_block *ufs;
|
||||
int offsets[] = {0, 8, 64, 256, -1};
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
for (i = 0; offsets[i] >= 0; i++) {
|
||||
ufs = (struct ufs_super_block *) volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800);
|
||||
if (ufs == NULL)
|
||||
return -1;
|
||||
|
||||
dbg("offset 0x%x\n", offsets[i] * 0x400);
|
||||
magic = be32_to_cpu(ufs->fs_magic);
|
||||
if ((magic == UFS_MAGIC) ||
|
||||
(magic == UFS2_MAGIC) ||
|
||||
(magic == UFS_MAGIC_FEA) ||
|
||||
(magic == UFS_MAGIC_LFN)) {
|
||||
dbg("magic 0x%08x(be)\n", magic);
|
||||
goto found;
|
||||
}
|
||||
magic = le32_to_cpu(ufs->fs_magic);
|
||||
if ((magic == UFS_MAGIC) ||
|
||||
(magic == UFS2_MAGIC) ||
|
||||
(magic == UFS_MAGIC_FEA) ||
|
||||
(magic == UFS_MAGIC_LFN)) {
|
||||
dbg("magic 0x%08x(le)\n", magic);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
found:
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "ufs";
|
||||
switch (magic) {
|
||||
case UFS_MAGIC:
|
||||
strcpy(id->type_version, "1");
|
||||
break;
|
||||
case UFS2_MAGIC:
|
||||
strcpy(id->type_version, "2");
|
||||
volume_id_set_label_raw(id, ufs->fs_u11.fs_u2.fs_volname, 32);
|
||||
volume_id_set_label_string(id, ufs->fs_u11.fs_u2.fs_volname, 32);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,449 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
/* count of characters used to encode one unicode char */
|
||||
static int utf8_encoded_expected_len(const char *str)
|
||||
{
|
||||
unsigned char c = (unsigned char)str[0];
|
||||
|
||||
if (c < 0x80)
|
||||
return 1;
|
||||
if ((c & 0xe0) == 0xc0)
|
||||
return 2;
|
||||
if ((c & 0xf0) == 0xe0)
|
||||
return 3;
|
||||
if ((c & 0xf8) == 0xf0)
|
||||
return 4;
|
||||
if ((c & 0xfc) == 0xf8)
|
||||
return 5;
|
||||
if ((c & 0xfe) == 0xfc)
|
||||
return 6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* decode one unicode char */
|
||||
static int utf8_encoded_to_unichar(const char *str)
|
||||
{
|
||||
int unichar;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
len = utf8_encoded_expected_len(str);
|
||||
switch (len) {
|
||||
case 1:
|
||||
return (int)str[0];
|
||||
case 2:
|
||||
unichar = str[0] & 0x1f;
|
||||
break;
|
||||
case 3:
|
||||
unichar = (int)str[0] & 0x0f;
|
||||
break;
|
||||
case 4:
|
||||
unichar = (int)str[0] & 0x07;
|
||||
break;
|
||||
case 5:
|
||||
unichar = (int)str[0] & 0x03;
|
||||
break;
|
||||
case 6:
|
||||
unichar = (int)str[0] & 0x01;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 1; i < len; i++) {
|
||||
if (((int)str[i] & 0xc0) != 0x80)
|
||||
return -1;
|
||||
unichar <<= 6;
|
||||
unichar |= (int)str[i] & 0x3f;
|
||||
}
|
||||
|
||||
return unichar;
|
||||
}
|
||||
|
||||
/* expected size used to encode one unicode char */
|
||||
static int utf8_unichar_to_encoded_len(int unichar)
|
||||
{
|
||||
if (unichar < 0x80)
|
||||
return 1;
|
||||
if (unichar < 0x800)
|
||||
return 2;
|
||||
if (unichar < 0x10000)
|
||||
return 3;
|
||||
if (unichar < 0x200000)
|
||||
return 4;
|
||||
if (unichar < 0x4000000)
|
||||
return 5;
|
||||
return 6;
|
||||
}
|
||||
|
||||
/* check if unicode char has a valid numeric range */
|
||||
static int utf8_unichar_valid_range(int unichar)
|
||||
{
|
||||
if (unichar > 0x10ffff)
|
||||
return 0;
|
||||
if ((unichar & 0xfffff800) == 0xd800)
|
||||
return 0;
|
||||
if ((unichar > 0xfdcf) && (unichar < 0xfdf0))
|
||||
return 0;
|
||||
if ((unichar & 0xffff) == 0xffff)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* validate one encoded unicode char and return its length */
|
||||
int volume_id_utf8_encoded_valid_unichar(const char *str)
|
||||
{
|
||||
int len;
|
||||
int unichar;
|
||||
int i;
|
||||
|
||||
len = utf8_encoded_expected_len(str);
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
/* ascii is valid */
|
||||
if (len == 1)
|
||||
return 1;
|
||||
|
||||
/* check if expected encoded chars are available */
|
||||
for (i = 0; i < len; i++)
|
||||
if ((str[i] & 0x80) != 0x80)
|
||||
return -1;
|
||||
|
||||
unichar = utf8_encoded_to_unichar(str);
|
||||
|
||||
/* check if encoded length matches encoded value */
|
||||
if (utf8_unichar_to_encoded_len(unichar) != len)
|
||||
return -1;
|
||||
|
||||
/* check if value has valid range */
|
||||
if (!utf8_unichar_valid_range(unichar))
|
||||
return -1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t volume_id_set_unicode16(uint8_t *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count)
|
||||
{
|
||||
size_t 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';
|
||||
return j;
|
||||
}
|
||||
|
||||
static char *usage_to_string(enum volume_id_usage usage_id)
|
||||
{
|
||||
switch (usage_id) {
|
||||
case VOLUME_ID_FILESYSTEM:
|
||||
return "filesystem";
|
||||
case VOLUME_ID_OTHER:
|
||||
return "other";
|
||||
case VOLUME_ID_RAID:
|
||||
return "raid";
|
||||
case VOLUME_ID_CRYPTO:
|
||||
return "crypto";
|
||||
case VOLUME_ID_UNUSED:
|
||||
return "unused";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (count > sizeof(id->label_raw))
|
||||
count = sizeof(id->label_raw);
|
||||
|
||||
memcpy(id->label_raw, buf, count);
|
||||
id->label_raw_len = count;
|
||||
}
|
||||
|
||||
void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (count >= sizeof(id->label))
|
||||
count = sizeof(id->label)-1;
|
||||
|
||||
memcpy(id->label, buf, count);
|
||||
id->label[count] = '\0';
|
||||
|
||||
/* 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)
|
||||
{
|
||||
if (count >= sizeof(id->label))
|
||||
count = sizeof(id->label)-1;
|
||||
|
||||
volume_id_set_unicode16((uint8_t *)id->label, sizeof(id->label), buf, endianess, count);
|
||||
}
|
||||
|
||||
static void set_uuid(const uint8_t *buf, size_t len, enum uuid_format format,
|
||||
char *uuid, uint8_t *uuid_raw, size_t *uuid_raw_len)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int count = 0;
|
||||
|
||||
switch(format) {
|
||||
case UUID_STRING:
|
||||
count = len;
|
||||
break;
|
||||
case UUID_HEX_STRING:
|
||||
count = len;
|
||||
break;
|
||||
case UUID_DOS:
|
||||
count = 4;
|
||||
break;
|
||||
case UUID_64BIT_LE:
|
||||
count = 8;
|
||||
break;
|
||||
case UUID_DCE:
|
||||
count = 16;
|
||||
break;
|
||||
case UUID_MD:
|
||||
count = 35;
|
||||
break;
|
||||
case UUID_LVM:
|
||||
count = 32;
|
||||
break;
|
||||
}
|
||||
memcpy(uuid_raw, buf, count);
|
||||
*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(uuid, "%02X%02X-%02X%02X",
|
||||
buf[3], buf[2], buf[1], buf[0]);
|
||||
break;
|
||||
case UUID_64BIT_LE:
|
||||
sprintf(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_DCE:
|
||||
sprintf(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_HEX_STRING:
|
||||
/* translate A..F to a..f */
|
||||
memcpy(uuid, buf, count);
|
||||
for (i = 0; i < count; i++)
|
||||
if (uuid[i] >= 'A' && uuid[i] <= 'F')
|
||||
uuid[i] = (uuid[i] - 'A') + 'a';
|
||||
uuid[count] = '\0';
|
||||
break;
|
||||
case UUID_STRING:
|
||||
memcpy(uuid, buf, count);
|
||||
uuid[count] = '\0';
|
||||
break;
|
||||
case UUID_MD:
|
||||
sprintf(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_LVM:
|
||||
sprintf(uuid,
|
||||
"%c%c%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c-%c%c%c%c%c%c",
|
||||
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], buf[16], buf[17],
|
||||
buf[18], buf[19], buf[20], buf[21],
|
||||
buf[22], buf[23], buf[24], buf[25],
|
||||
buf[26], buf[27], buf[28], buf[29], buf[30], buf[31]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format)
|
||||
{
|
||||
if (len > sizeof(id->uuid_raw))
|
||||
len = sizeof(id->uuid_raw);
|
||||
|
||||
set_uuid(buf, len, format, id->uuid, id->uuid_raw, &id->uuid_raw_len);
|
||||
}
|
||||
|
||||
void volume_id_set_uuid_sub(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format)
|
||||
{
|
||||
if (len > sizeof(id->uuid_sub_raw))
|
||||
len = sizeof(id->uuid_sub_raw);
|
||||
|
||||
set_uuid(buf, len, format, id->uuid_sub, id->uuid_sub_raw, &id->uuid_sub_raw_len);
|
||||
}
|
||||
|
||||
uint8_t *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
|
||||
{
|
||||
ssize_t buf_len;
|
||||
|
||||
info("get buffer off 0x%" PRIx64 "(%" PRIu64 "), len 0x%zx\n", off, off, len);
|
||||
/* check if requested area fits in superblock buffer */
|
||||
if (off + len <= SB_BUFFER_SIZE) {
|
||||
if (id->sbbuf == NULL) {
|
||||
id->sbbuf = malloc(SB_BUFFER_SIZE);
|
||||
if (id->sbbuf == NULL) {
|
||||
dbg("error malloc\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if we need to read */
|
||||
if ((off + len) > id->sbbuf_len) {
|
||||
info("read sbbuf len:0x%" PRIx64 "\n", (off + len));
|
||||
if (lseek(id->fd, 0, SEEK_SET) < 0) {
|
||||
dbg("lseek failed (%s)\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
buf_len = read(id->fd, id->sbbuf, off + len);
|
||||
if (buf_len < 0) {
|
||||
dbg("read failed (%s)\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
dbg("got 0x%zx (%zi) bytes\n", buf_len, buf_len);
|
||||
id->sbbuf_len = buf_len;
|
||||
if ((size_t)buf_len < off + len) {
|
||||
dbg("requested 0x%zx bytes, got only 0x%zx bytes\n", len, buf_len);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return &(id->sbbuf[off]);
|
||||
} else {
|
||||
if (len > SEEK_BUFFER_SIZE) {
|
||||
dbg("seek buffer too small %d\n", SEEK_BUFFER_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get seek buffer */
|
||||
if (id->seekbuf == NULL) {
|
||||
id->seekbuf = malloc(SEEK_BUFFER_SIZE);
|
||||
if (id->seekbuf == NULL) {
|
||||
dbg("error malloc\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if we need to read */
|
||||
if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
|
||||
info("read seekbuf off:0x%" PRIx64 " len:0x%zx\n", off, len);
|
||||
if (lseek(id->fd, off, SEEK_SET) < 0) {
|
||||
dbg("lseek failed (%s)\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
buf_len = read(id->fd, id->seekbuf, len);
|
||||
if (buf_len < 0) {
|
||||
dbg("read failed (%s)\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
dbg("got 0x%zx (%zi) bytes\n", buf_len, buf_len);
|
||||
id->seekbuf_off = off;
|
||||
id->seekbuf_len = buf_len;
|
||||
if ((size_t)buf_len < len) {
|
||||
dbg("requested 0x%zx bytes, got only 0x%zx bytes\n", len, buf_len);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return &(id->seekbuf[off - id->seekbuf_off]);
|
||||
}
|
||||
}
|
||||
|
||||
void volume_id_free_buffer(struct volume_id *id)
|
||||
{
|
||||
if (id->sbbuf != NULL) {
|
||||
free(id->sbbuf);
|
||||
id->sbbuf = NULL;
|
||||
id->sbbuf_len = 0;
|
||||
}
|
||||
if (id->seekbuf != NULL) {
|
||||
free(id->seekbuf);
|
||||
id->seekbuf = NULL;
|
||||
id->seekbuf_len = 0;
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* Based on information taken from dmraid:
|
||||
* Copyright (C) 2004-2006 Heinz Mauelshagen, Red Hat GmbH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
struct via_meta {
|
||||
uint16_t signature;
|
||||
uint8_t version_number;
|
||||
struct via_array {
|
||||
uint16_t disk_bit_mask;
|
||||
uint8_t disk_array_ex;
|
||||
uint32_t capacity_low;
|
||||
uint32_t capacity_high;
|
||||
uint32_t serial_checksum;
|
||||
} PACKED array;
|
||||
uint32_t serial_checksum[8];
|
||||
uint8_t checksum;
|
||||
} PACKED;
|
||||
|
||||
#define VIA_SIGNATURE 0xAA55
|
||||
|
||||
/* 8 bit checksum on first 50 bytes of metadata. */
|
||||
static uint8_t meta_checksum(struct via_meta *via)
|
||||
{
|
||||
uint8_t i = 50, sum = 0;
|
||||
|
||||
while (i--)
|
||||
sum += ((uint8_t*) via)[i];
|
||||
|
||||
return sum == via->checksum;
|
||||
}
|
||||
|
||||
|
||||
int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
const uint8_t *buf;
|
||||
uint64_t meta_off;
|
||||
struct via_meta *via;
|
||||
|
||||
dbg("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
if (size < 0x10000)
|
||||
return -1;
|
||||
|
||||
meta_off = ((size / 0x200)-1) * 0x200;
|
||||
|
||||
buf = volume_id_get_buffer(id, off + meta_off, 0x200);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
via = (struct via_meta *) buf;
|
||||
if (le16_to_cpu(via->signature) != VIA_SIGNATURE)
|
||||
return -1;
|
||||
|
||||
if (via->version_number > 2)
|
||||
return -1;
|
||||
|
||||
if (!meta_checksum(via))
|
||||
return -1;
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_RAID);
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u", via->version_number);
|
||||
id->type = "via_raid_member";
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,592 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads volume label and uuid
|
||||
*
|
||||
* Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
struct prober {
|
||||
volume_id_probe_fn_t prober;
|
||||
const char *name[4];
|
||||
};
|
||||
|
||||
static const struct prober prober_raid[] = {
|
||||
{ volume_id_probe_linux_raid, { "linux_raid", } },
|
||||
{ volume_id_probe_ddf_raid, { "ddf_raid", } },
|
||||
{ volume_id_probe_intel_software_raid, { "isw_raid", } },
|
||||
{ volume_id_probe_lsi_mega_raid, { "lsi_mega_raid", } },
|
||||
{ volume_id_probe_via_raid, { "via_raid", } },
|
||||
{ volume_id_probe_silicon_medley_raid, { "silicon_medley_raid", } },
|
||||
{ volume_id_probe_nvidia_raid, { "nvidia_raid", } },
|
||||
{ volume_id_probe_promise_fasttrack_raid, { "promise_fasttrack_raid", } },
|
||||
{ volume_id_probe_highpoint_45x_raid, { "highpoint_raid", } },
|
||||
{ volume_id_probe_adaptec_raid, { "adaptec_raid", } },
|
||||
{ volume_id_probe_jmicron_raid, { "jmicron_raid", } },
|
||||
{ volume_id_probe_lvm1, { "lvm1", } },
|
||||
{ volume_id_probe_lvm2, { "lvm2", } },
|
||||
{ volume_id_probe_highpoint_37x_raid, { "highpoint_raid", } },
|
||||
};
|
||||
|
||||
static const struct prober prober_filesystem[] = {
|
||||
{ volume_id_probe_vfat, { "vfat", } },
|
||||
{ volume_id_probe_linux_swap, { "swap", } },
|
||||
{ volume_id_probe_luks, { "luks", } },
|
||||
{ volume_id_probe_xfs, { "xfs", } },
|
||||
{ volume_id_probe_ext, { "ext2", "ext3", "jbd", } },
|
||||
{ volume_id_probe_reiserfs, { "reiserfs", "reiser4", } },
|
||||
{ volume_id_probe_jfs, { "jfs", } },
|
||||
{ volume_id_probe_udf, { "udf", } },
|
||||
{ volume_id_probe_iso9660, { "iso9660", } },
|
||||
{ volume_id_probe_hfs_hfsplus, { "hfs", "hfsplus", } },
|
||||
{ volume_id_probe_ufs, { "ufs", } },
|
||||
{ volume_id_probe_ntfs, { "ntfs", } },
|
||||
{ volume_id_probe_cramfs, { "cramfs", } },
|
||||
{ volume_id_probe_romfs, { "romfs", } },
|
||||
{ volume_id_probe_hpfs, { "hpfs", } },
|
||||
{ volume_id_probe_sysv, { "sysv", "xenix", } },
|
||||
{ volume_id_probe_minix, { "minix", } },
|
||||
{ volume_id_probe_gfs, { "gfs", } },
|
||||
{ volume_id_probe_gfs2, { "gfs2", } },
|
||||
{ volume_id_probe_ocfs1, { "ocfs1", } },
|
||||
{ volume_id_probe_ocfs2, { "ocfs2", } },
|
||||
{ volume_id_probe_vxfs, { "vxfs", } },
|
||||
{ volume_id_probe_squashfs, { "squashfs", } },
|
||||
{ volume_id_probe_netware, { "netware", } },
|
||||
{ volume_id_probe_oracleasm, { "oracleasm", } },
|
||||
{ volume_id_probe_btrfs, { "btrfs", } },
|
||||
};
|
||||
|
||||
/* the user can overwrite this log function */
|
||||
static void default_log(int priority, const char *file, int line, const char *format, ...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
volume_id_log_fn_t volume_id_log_fn = default_log;
|
||||
|
||||
/**
|
||||
* volume_id_get_prober_by_type:
|
||||
* @type: Type string.
|
||||
*
|
||||
* Lookup the probing function for a specific type.
|
||||
*
|
||||
* Returns: The probing function for the given type, #NULL otherwise.
|
||||
**/
|
||||
const volume_id_probe_fn_t *volume_id_get_prober_by_type(const char *type)
|
||||
{
|
||||
unsigned int p, n;
|
||||
|
||||
if (type == NULL)
|
||||
return NULL;
|
||||
|
||||
for (p = 0; p < ARRAY_SIZE(prober_raid); p++)
|
||||
for (n = 0; prober_raid[p].name[n] != NULL; n++)
|
||||
if (strcmp(type, prober_raid[p].name[n]) == 0)
|
||||
return &prober_raid[p].prober;
|
||||
for (p = 0; p < ARRAY_SIZE(prober_filesystem); p++)
|
||||
for (n = 0; prober_filesystem[p].name[n] != NULL; n++)
|
||||
if (strcmp(type, prober_filesystem[p].name[n]) == 0)
|
||||
return &prober_filesystem[p].prober;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_get_label:
|
||||
* @id: Probing context.
|
||||
* @label: Label string. Must not be freed by the caller.
|
||||
*
|
||||
* Get the label string after a successful probe. Unicode
|
||||
* is translated to UTF-8.
|
||||
*
|
||||
* Returns: 1 if the value was set, 0 otherwise.
|
||||
**/
|
||||
int volume_id_get_label(struct volume_id *id, const char **label)
|
||||
{
|
||||
if (id == NULL)
|
||||
return 0;
|
||||
if (label == NULL)
|
||||
return 0;
|
||||
if (id->usage_id == VOLUME_ID_UNUSED)
|
||||
return 0;
|
||||
|
||||
*label = id->label;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_get_label_raw:
|
||||
* @id: Probing context.
|
||||
* @label: Label byte array. Must not be freed by the caller.
|
||||
* @len: Length of raw label byte array.
|
||||
*
|
||||
* Get the raw label byte array after a successful probe. It may
|
||||
* contain undecoded multibyte character streams.
|
||||
*
|
||||
* Returns: 1 if the value was set, 0 otherwise.
|
||||
**/
|
||||
int volume_id_get_label_raw(struct volume_id *id, const uint8_t **label, size_t *len)
|
||||
{
|
||||
if (id == NULL)
|
||||
return 0;
|
||||
if (label == NULL)
|
||||
return 0;
|
||||
if (len == NULL)
|
||||
return 0;
|
||||
if (id->usage_id == VOLUME_ID_UNUSED)
|
||||
return 0;
|
||||
|
||||
*label = id->label_raw;
|
||||
*len = id->label_raw_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_get_uuid:
|
||||
* @id: Probing context.
|
||||
* @uuid: UUID string. Must not be freed by the caller.
|
||||
*
|
||||
* Get the raw UUID string after a successful probe.
|
||||
*
|
||||
* Returns: 1 if the value was set, 0 otherwise.
|
||||
**/
|
||||
int volume_id_get_uuid(struct volume_id *id, const char **uuid)
|
||||
{
|
||||
if (id == NULL)
|
||||
return 0;
|
||||
if (uuid == NULL)
|
||||
return 0;
|
||||
if (id->usage_id == VOLUME_ID_UNUSED)
|
||||
return 0;
|
||||
|
||||
*uuid = id->uuid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_get_uuid_raw:
|
||||
* @id: Probing context.
|
||||
* @uuid: UUID byte array. Must not be freed by the caller.
|
||||
* @len: Length of raw UUID byte array.
|
||||
*
|
||||
* Get the raw UUID byte array after a successful probe. It may
|
||||
* contain unconverted endianes values.
|
||||
*
|
||||
* Returns: 1 if the value was set, 0 otherwise.
|
||||
**/
|
||||
int volume_id_get_uuid_raw(struct volume_id *id, const uint8_t **uuid, size_t *len)
|
||||
{
|
||||
if (id == NULL)
|
||||
return 0;
|
||||
if (uuid == NULL)
|
||||
return 0;
|
||||
if (len == NULL)
|
||||
return 0;
|
||||
if (id->usage_id == VOLUME_ID_UNUSED)
|
||||
return 0;
|
||||
|
||||
*uuid = id->uuid_raw;
|
||||
*len = id->uuid_raw_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int volume_id_get_uuid_sub(struct volume_id *id, const char **uuid)
|
||||
{
|
||||
if (id == NULL)
|
||||
return 0;
|
||||
if (uuid == NULL)
|
||||
return 0;
|
||||
if (id->usage_id == VOLUME_ID_UNUSED)
|
||||
return 0;
|
||||
|
||||
*uuid = id->uuid_sub;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_get_usage:
|
||||
* @id: Probing context.
|
||||
* @usage: Usage string. Must not be freed by the caller.
|
||||
*
|
||||
* Get the usage string after a successful probe.
|
||||
*
|
||||
* Returns: 1 if the value was set, 0 otherwise.
|
||||
**/
|
||||
int volume_id_get_usage(struct volume_id *id, const char **usage)
|
||||
{
|
||||
if (id == NULL)
|
||||
return 0;
|
||||
if (usage == NULL)
|
||||
return 0;
|
||||
if (id->usage_id == VOLUME_ID_UNUSED)
|
||||
return 0;
|
||||
|
||||
*usage = id->usage;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_get_type:
|
||||
* @id: Probing context
|
||||
* @type: Type string. Must not be freed by the caller.
|
||||
*
|
||||
* Get the type string after a successful probe.
|
||||
*
|
||||
* Returns: 1 if the value was set, 0 otherwise.
|
||||
**/
|
||||
int volume_id_get_type(struct volume_id *id, const char **type)
|
||||
{
|
||||
if (id == NULL)
|
||||
return 0;
|
||||
if (type == NULL)
|
||||
return 0;
|
||||
if (id->usage_id == VOLUME_ID_UNUSED)
|
||||
return 0;
|
||||
|
||||
*type = id->type;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_get_type_version:
|
||||
* @id: Probing context.
|
||||
* @type_version: Type version string. Must not be freed by the caller.
|
||||
*
|
||||
* Get the Type version string after a successful probe.
|
||||
*
|
||||
* Returns: 1 if the value was set, 0 otherwise.
|
||||
**/
|
||||
int volume_id_get_type_version(struct volume_id *id, const char **type_version)
|
||||
{
|
||||
if (id == NULL)
|
||||
return 0;
|
||||
if (type_version == NULL)
|
||||
return 0;
|
||||
if (id->usage_id == VOLUME_ID_UNUSED)
|
||||
return 0;
|
||||
|
||||
*type_version = id->type_version;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int needs_encoding(const char c)
|
||||
{
|
||||
if ((c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
strchr(ALLOWED_CHARS, c))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_encode_string:
|
||||
* @str: Input string to be encoded.
|
||||
* @str_enc: Target string to store the encoded input.
|
||||
* @len: Location to store the encoded string. The target string,
|
||||
* which may be four times as long as the input string.
|
||||
*
|
||||
* Encode all potentially unsafe characters of a string to the
|
||||
* corresponding hex value prefixed by '\x'.
|
||||
*
|
||||
* Returns: 1 if the entire string was copied, 0 otherwise.
|
||||
**/
|
||||
int volume_id_encode_string(const char *str, char *str_enc, size_t len)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
if (str == NULL || str_enc == NULL || len == 0)
|
||||
return 0;
|
||||
|
||||
str_enc[0] = '\0';
|
||||
for (i = 0, j = 0; str[i] != '\0'; i++) {
|
||||
int seqlen;
|
||||
|
||||
seqlen = volume_id_utf8_encoded_valid_unichar(&str[i]);
|
||||
if (seqlen > 1) {
|
||||
memcpy(&str_enc[j], &str[i], seqlen);
|
||||
j += seqlen;
|
||||
i += (seqlen-1);
|
||||
} else if (str[i] == '\\' || needs_encoding(str[i])) {
|
||||
sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
|
||||
j += 4;
|
||||
} else {
|
||||
str_enc[j] = str[i];
|
||||
j++;
|
||||
}
|
||||
if (j+3 >= len)
|
||||
goto err;
|
||||
}
|
||||
str_enc[j] = '\0';
|
||||
return 1;
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* run only once into a timeout for unreadable devices */
|
||||
static int device_is_readable(struct volume_id *id, uint64_t off)
|
||||
{
|
||||
if (volume_id_get_buffer(id, off, 0x200) != NULL)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_probe_raid:
|
||||
* @id: Probing context.
|
||||
* @off: Probing offset relative to the start of the device.
|
||||
* @size: Total size of the device.
|
||||
*
|
||||
* Probe device for all known raid signatures.
|
||||
*
|
||||
* Returns: 0 on successful probe, otherwise negative value.
|
||||
**/
|
||||
int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (id == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (!device_is_readable(id, off))
|
||||
return -1;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(prober_raid); i++) {
|
||||
if (prober_raid[i].prober(id, off, size) == 0) {
|
||||
info("signature '%s' detected\n", id->type);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
||||
found:
|
||||
/* If recognized, we free the allocated buffers */
|
||||
volume_id_free_buffer(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void volume_id_reset_result(struct volume_id *id)
|
||||
{
|
||||
id->label_raw_len = 0;
|
||||
id->label[0] = '\0';
|
||||
id->uuid_raw_len = 0;
|
||||
id->uuid[0] = '\0';
|
||||
id->usage_id = VOLUME_ID_UNUSED;
|
||||
id->usage = NULL;
|
||||
id->type = NULL;
|
||||
id->type_version[0] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_probe_filesystem:
|
||||
* @id: Probing context.
|
||||
* @off: Probing offset relative to the start of the device.
|
||||
* @size: Total size of the device.
|
||||
*
|
||||
* Probe device for all known filesystem signatures.
|
||||
*
|
||||
* Returns: 0 on successful probe, otherwise negative value.
|
||||
**/
|
||||
int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (id == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (!device_is_readable(id, off))
|
||||
return -1;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size);
|
||||
|
||||
/*
|
||||
* We probe for all known filesystems to find conflicting signatures. If
|
||||
* we find multiple matching signatures and one of the detected filesystem
|
||||
* types claims that it can not co-exist with any other filesystem type,
|
||||
* we do not return a probing result.
|
||||
*
|
||||
* We can not afford to mount a volume with the wrong filesystem code and
|
||||
* possibly corrupt it. Linux sytems have the problem of dozens of possible
|
||||
* filesystem types, and volumes with left-over signatures from former
|
||||
* filesystem types. Invalid signatures need to be removed from the volume
|
||||
* to make the filesystem detection successful.
|
||||
*
|
||||
* We do not want to read that many bytes from probed floppies, skip volumes
|
||||
* smaller than a usual floppy disk.
|
||||
*/
|
||||
if (size > 1440 * 1024) {
|
||||
int found = 0;
|
||||
int force_unique_result = 0;
|
||||
int first_match = -1;
|
||||
|
||||
volume_id_reset_result(id);
|
||||
for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) {
|
||||
int match;
|
||||
|
||||
match = (prober_filesystem[i].prober(id, off, size) == 0);
|
||||
if (match) {
|
||||
info("signature '%s' %i detected\n", id->type, i);
|
||||
if (id->force_unique_result)
|
||||
force_unique_result = 1;
|
||||
if (found > 0 && force_unique_result) {
|
||||
info("conflicting signatures found, skip results\n");
|
||||
return -1;
|
||||
}
|
||||
found++;
|
||||
if (first_match < 0)
|
||||
first_match = i;
|
||||
}
|
||||
}
|
||||
if (found < 1)
|
||||
return -1;
|
||||
if (found == 1)
|
||||
goto found;
|
||||
if (found > 1) {
|
||||
volume_id_reset_result(id);
|
||||
info("re-read first match metadata %i\n", first_match);
|
||||
if (prober_filesystem[first_match].prober(id, off, size) == 0)
|
||||
goto found;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the first match */
|
||||
volume_id_reset_result(id);
|
||||
for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) {
|
||||
if (prober_filesystem[i].prober(id, off, size) == 0) {
|
||||
info("signature '%s' detected\n", id->type);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
found:
|
||||
/* If recognized, we free the allocated buffers */
|
||||
volume_id_free_buffer(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_probe_all:
|
||||
* @id: Probing context.
|
||||
* @off: Probing offset relative to the start of the device.
|
||||
* @size: Total size of the device.
|
||||
*
|
||||
* Probe device for all known raid and filesystem signatures.
|
||||
*
|
||||
* Returns: 0 on successful probe, otherwise negative value.
|
||||
**/
|
||||
int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
if (id == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (!device_is_readable(id, off))
|
||||
return -1;
|
||||
|
||||
/* probe for raid first, because fs probes may be successful on raid members */
|
||||
if (volume_id_probe_raid(id, off, size) == 0)
|
||||
return 0;
|
||||
|
||||
if (volume_id_probe_filesystem(id, off, size) == 0)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_probe_raid:
|
||||
* @all_probers_fn: prober function to called for all known probing routines.
|
||||
* @id: Context passed to prober function.
|
||||
* @off: Offset value passed to prober function.
|
||||
* @size: Size value passed to prober function.
|
||||
* @data: Arbitrary data passed to the prober function.
|
||||
*
|
||||
* Run a custom function for all known probing routines.
|
||||
**/
|
||||
void volume_id_all_probers(all_probers_fn_t all_probers_fn,
|
||||
struct volume_id *id, uint64_t off, uint64_t size,
|
||||
void *data)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (all_probers_fn == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(prober_raid); i++)
|
||||
if (all_probers_fn(prober_raid[i].prober, id, off, size, data) != 0)
|
||||
goto out;
|
||||
for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++)
|
||||
if (all_probers_fn(prober_filesystem[i].prober, id, off, size, data) != 0)
|
||||
goto out;
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_open_fd:
|
||||
* @id: Probing context.
|
||||
* @fd: Open file descriptor of device to read from.
|
||||
*
|
||||
* Create the context for probing.
|
||||
*
|
||||
* Returns: Probing context, or #NULL on failure.
|
||||
**/
|
||||
struct volume_id *volume_id_open_fd(int fd)
|
||||
{
|
||||
struct volume_id *id;
|
||||
|
||||
id = calloc(1, sizeof(struct volume_id));
|
||||
if (id == NULL)
|
||||
return NULL;
|
||||
|
||||
id->fd = fd;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* volume_id_close:
|
||||
* @id: Probing context.
|
||||
*
|
||||
* Release probing context and free all associated data.
|
||||
*/
|
||||
void volume_id_close(struct volume_id *id)
|
||||
{
|
||||
if (id == NULL)
|
||||
return;
|
||||
|
||||
volume_id_free_buffer(id);
|
||||
|
||||
free(id);
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.h"
|
||||
|
||||
#define VXFS_SUPER_MAGIC 0xa501FCF5
|
||||
|
||||
struct vxfs_super {
|
||||
uint32_t vs_magic;
|
||||
int32_t vs_version;
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_vxfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct vxfs_super *vxs;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
vxs = (struct vxfs_super *) volume_id_get_buffer(id, off + 0x200, 0x200);
|
||||
if (vxs == NULL)
|
||||
return -1;
|
||||
|
||||
if (vxs->vs_magic == cpu_to_le32(VXFS_SUPER_MAGIC)) {
|
||||
snprintf(id->type_version, sizeof(id->type_version)-1, "%u", (unsigned int) vxs->vs_version);
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "vxfs";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* volume_id - reads filesystem label and uuid
|
||||
*
|
||||
* Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "libvolume_id.h"
|
||||
#include "libvolume_id-private.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;
|
||||
} PACKED;
|
||||
|
||||
int volume_id_probe_xfs(struct volume_id *id, uint64_t off, uint64_t size)
|
||||
{
|
||||
struct xfs_super_block *xs;
|
||||
|
||||
info("probing at offset 0x%" PRIx64 "\n", off);
|
||||
|
||||
xs = (struct xfs_super_block *) 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, 0, UUID_DCE);
|
||||
|
||||
volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
|
||||
id->type = "xfs";
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user