libblkid: add superblocks chain
Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
parent
5657c25a51
commit
0e89abac8b
|
@ -5,6 +5,7 @@ AM_CPPFLAGS += -I$(ul_libblkid_srcdir)
|
|||
noinst_LTLIBRARIES = libblkid_superblocks.la
|
||||
libblkid_superblocks_la_SOURCES = \
|
||||
superblocks.h \
|
||||
superblocks.c \
|
||||
cramfs.c \
|
||||
swap.c \
|
||||
adaptec_raid.c \
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
/*
|
||||
* superblocks.c - reads information from filesystem and raid superblocks
|
||||
*
|
||||
* Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
|
||||
*
|
||||
* This file may be redistributed under the terms of the
|
||||
* GNU Lesser General Public License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "blkdev.h"
|
||||
#include "blkidP.h"
|
||||
|
||||
#include "superblocks.h"
|
||||
|
||||
/**
|
||||
* SECTION:superblocks
|
||||
* @title: Superblocks probing
|
||||
* @short_description: filesystems and raids superblocks probing.
|
||||
*
|
||||
* The library API has been originaly designed for superblocks probing only.
|
||||
* This is reason why some *deprecated* superblock specific functions don't use
|
||||
* '_superblocks_' namespace in the function name. Please, don't use these
|
||||
* functions in new code.
|
||||
*
|
||||
* The 'superblocks' probers support NAME=value (tags) interface only. The
|
||||
* superblocks probing is enabled by default (and controled by
|
||||
* blkid_probe_enable_superblocks()).
|
||||
*
|
||||
* Currently supported tags:
|
||||
*
|
||||
* @TYPE: filesystem type
|
||||
*
|
||||
* @SEC_TYPE: secondary filesystem type
|
||||
*
|
||||
* @LABEL: filesystem label
|
||||
*
|
||||
* @LABEL_RAW: raw label from FS superblock
|
||||
*
|
||||
* @UUID: filesystem UUID (lower case)
|
||||
*
|
||||
* @UUID_RAW: raw UUID from FS superblock
|
||||
*
|
||||
* @EXT_JOURNAL: external journal UUID
|
||||
*
|
||||
* @USAGE: usage string: "raid", "filesystem", ...
|
||||
*
|
||||
* @VERSION: filesystem version
|
||||
*
|
||||
* @MOUNT: cluster mount name (?) -- ocfs only
|
||||
*
|
||||
* @SBMAGIC: super block magic string [not-implemented yet]
|
||||
*
|
||||
* @SBOFFSET: offset of superblock [not-implemented yet]
|
||||
*
|
||||
* @FSSIZE: size of filessystem [not-implemented yet]
|
||||
*/
|
||||
|
||||
static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn);
|
||||
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn);
|
||||
|
||||
static int blkid_probe_set_usage(blkid_probe pr, int usage);
|
||||
|
||||
|
||||
/*
|
||||
* Superblocks chains probing functions
|
||||
*/
|
||||
static const struct blkid_idinfo *idinfos[] =
|
||||
{
|
||||
/* RAIDs */
|
||||
&linuxraid_idinfo,
|
||||
&ddfraid_idinfo,
|
||||
&iswraid_idinfo,
|
||||
&lsiraid_idinfo,
|
||||
&viaraid_idinfo,
|
||||
&silraid_idinfo,
|
||||
&nvraid_idinfo,
|
||||
&pdcraid_idinfo,
|
||||
&highpoint45x_idinfo,
|
||||
&highpoint37x_idinfo,
|
||||
&adraid_idinfo,
|
||||
&jmraid_idinfo,
|
||||
&lvm2_idinfo,
|
||||
&lvm1_idinfo,
|
||||
&snapcow_idinfo,
|
||||
&luks_idinfo,
|
||||
|
||||
/* Filesystems */
|
||||
&vfat_idinfo,
|
||||
&swsuspend_idinfo,
|
||||
&swap_idinfo,
|
||||
&xfs_idinfo,
|
||||
&ext4dev_idinfo,
|
||||
&ext4_idinfo,
|
||||
&ext3_idinfo,
|
||||
&ext2_idinfo,
|
||||
&jbd_idinfo,
|
||||
&reiser_idinfo,
|
||||
&reiser4_idinfo,
|
||||
&jfs_idinfo,
|
||||
&udf_idinfo,
|
||||
&iso9660_idinfo,
|
||||
&zfs_idinfo,
|
||||
&hfsplus_idinfo,
|
||||
&hfs_idinfo,
|
||||
&ufs_idinfo,
|
||||
&hpfs_idinfo,
|
||||
&sysv_idinfo,
|
||||
&xenix_idinfo,
|
||||
&ntfs_idinfo,
|
||||
&cramfs_idinfo,
|
||||
&romfs_idinfo,
|
||||
&minix_idinfo,
|
||||
&gfs_idinfo,
|
||||
&gfs2_idinfo,
|
||||
&ocfs_idinfo,
|
||||
&ocfs2_idinfo,
|
||||
&oracleasm_idinfo,
|
||||
&vxfs_idinfo,
|
||||
&squashfs_idinfo,
|
||||
&netware_idinfo,
|
||||
&btrfs_idinfo
|
||||
};
|
||||
|
||||
/*
|
||||
* Driver definition
|
||||
*/
|
||||
const struct blkid_chaindrv superblocks_drv = {
|
||||
.id = BLKID_CHAIN_SUBLKS,
|
||||
.name = "superblocks",
|
||||
.dflt_enabled = TRUE,
|
||||
.dflt_flags = BLKID_SUBLKS_DEFAULT,
|
||||
.idinfos = idinfos,
|
||||
.nidinfos = ARRAY_SIZE(idinfos),
|
||||
.has_fltr = TRUE,
|
||||
.probe = superblocks_probe,
|
||||
.safeprobe = superblocks_safeprobe
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The blkid_do_probe() backend.
|
||||
*/
|
||||
static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (!pr || chn->idx < -1)
|
||||
return -1;
|
||||
if (chn->idx < -1)
|
||||
return -1;
|
||||
blkid_probe_chain_reset_vals(pr, chn);
|
||||
|
||||
DBG(DEBUG_LOWPROBE,
|
||||
printf("--> starting probing loop [SUBLKS idx=%d]\n",
|
||||
chn->idx));
|
||||
|
||||
i = chn->idx + 1;
|
||||
|
||||
for ( ; i < ARRAY_SIZE(idinfos); i++) {
|
||||
const struct blkid_idinfo *id;
|
||||
const struct blkid_idmag *mag;
|
||||
int hasmag = 0;
|
||||
|
||||
chn->idx = i;
|
||||
|
||||
if (chn->fltr && blkid_bmp_get_item(chn->fltr, i))
|
||||
continue;
|
||||
|
||||
id = idinfos[i];
|
||||
mag = id->magics ? &id->magics[0] : NULL;
|
||||
|
||||
/* try to detect by magic string */
|
||||
while(mag && mag->magic) {
|
||||
blkid_loff_t off;
|
||||
unsigned char *buf;
|
||||
|
||||
off = mag->kboff + ((blkid_loff_t) mag->sboff >> 10);
|
||||
buf = blkid_probe_get_buffer(pr, off << 10, 1024);
|
||||
|
||||
if (buf && !memcmp(mag->magic,
|
||||
buf + (mag->sboff & 0x3ff), mag->len)) {
|
||||
DBG(DEBUG_LOWPROBE, printf(
|
||||
"%s: magic sboff=%u, kboff=%ld\n",
|
||||
id->name, mag->sboff, mag->kboff));
|
||||
hasmag = 1;
|
||||
break;
|
||||
}
|
||||
mag++;
|
||||
}
|
||||
|
||||
if (hasmag == 0 && id->magics && id->magics[0].magic)
|
||||
/* magic string(s) defined, but not found */
|
||||
continue;
|
||||
|
||||
/* final check by probing function */
|
||||
if (id->probefunc) {
|
||||
DBG(DEBUG_LOWPROBE, printf(
|
||||
"%s: call probefunc()\n", id->name));
|
||||
if (id->probefunc(pr, mag) != 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* all cheks passed */
|
||||
if (chn->flags & BLKID_SUBLKS_TYPE)
|
||||
blkid_probe_set_value(pr, "TYPE",
|
||||
(unsigned char *) id->name,
|
||||
strlen(id->name) + 1);
|
||||
if (chn->flags & BLKID_SUBLKS_USAGE)
|
||||
blkid_probe_set_usage(pr, id->usage);
|
||||
|
||||
DBG(DEBUG_LOWPROBE,
|
||||
printf("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]\n",
|
||||
id->name, chn->idx));
|
||||
return 0;
|
||||
}
|
||||
DBG(DEBUG_LOWPROBE,
|
||||
printf("<-- leaving probing loop (failed) [SUBLKS idx=%d]\n",
|
||||
chn->idx));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the same function as blkid_do_probe(), but returns only one result
|
||||
* (cannot be used in while()) and checks for ambivalen results (more
|
||||
* filesystems on the device) -- in such case returns -2.
|
||||
*
|
||||
* The function does not check for filesystems when a RAID signature is
|
||||
* detected. The function also does not check for collision between RAIDs. The
|
||||
* first detected RAID is returned.
|
||||
*/
|
||||
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
|
||||
{
|
||||
struct blkid_prval vals[BLKID_NVALS_SUBLKS];
|
||||
int nvals = BLKID_NVALS_SUBLKS;
|
||||
int idx = -1;
|
||||
int count = 0;
|
||||
int intol = 0;
|
||||
int rc;
|
||||
|
||||
while ((rc = superblocks_probe(pr, chn)) == 0) {
|
||||
if (!count) {
|
||||
/* save the first result */
|
||||
nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
|
||||
idx = chn->idx;
|
||||
}
|
||||
count++;
|
||||
|
||||
if (idinfos[chn->idx]->usage & BLKID_USAGE_RAID)
|
||||
break;
|
||||
if (!(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT))
|
||||
intol++;
|
||||
}
|
||||
if (rc < 0)
|
||||
return rc; /* error */
|
||||
if (count > 1 && intol) {
|
||||
DBG(DEBUG_LOWPROBE,
|
||||
printf("ERROR: superblocks chain: "
|
||||
"ambivalent result detected (%d filesystems)!\n",
|
||||
count));
|
||||
return -2; /* error, ambivalent result (more FS) */
|
||||
}
|
||||
if (!count)
|
||||
return 1; /* nothing detected */
|
||||
|
||||
/* restore the first result */
|
||||
blkid_probe_chain_reset_vals(pr, chn);
|
||||
blkid_probe_append_vals(pr, vals, nvals);
|
||||
chn->idx = idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int blkid_probe_set_usage(blkid_probe pr, int usage)
|
||||
{
|
||||
char *u = NULL;
|
||||
|
||||
if (usage & BLKID_USAGE_FILESYSTEM)
|
||||
u = "filesystem";
|
||||
else if (usage & BLKID_USAGE_RAID)
|
||||
u = "raid";
|
||||
else if (usage & BLKID_USAGE_CRYPTO)
|
||||
u = "crypto";
|
||||
else if (usage & BLKID_USAGE_OTHER)
|
||||
u = "other";
|
||||
else
|
||||
u = "unknown";
|
||||
|
||||
return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1);
|
||||
}
|
Loading…
Reference in New Issue