Update blkid to 2.25.0
Break libblkid into 4 libraries: libblkid, libuuid, libutil-linux and libfdisk.

This should help in later patch updates.

Change-Id: I680d9a7feb031e5c29a603e9c58aff4b65826262
diff --git a/libblkid/src/superblocks/adaptec_raid.c b/libblkid/src/superblocks/adaptec_raid.c
new file mode 100644
index 0000000..65fd5b8
--- /dev/null
+++ b/libblkid/src/superblocks/adaptec_raid.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct adaptec_metadata {
+
+	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];
+	uint32_t	smagic;
+	uint32_t	raidtbl;
+	uint16_t	raidline;
+	uint8_t		res9[0xF6];
+} __attribute__((packed));
+
+#define AD_SIGNATURE	0x4450544D	/* "DPTM" */
+#define AD_MAGIC	0x37FC4D1E
+
+static int probe_adraid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	uint64_t off;
+	struct adaptec_metadata *ad;
+
+	if (pr->size < 0x10000)
+		return BLKID_PROBE_NONE;
+
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return BLKID_PROBE_NONE;
+
+	off = ((pr->size / 0x200)-1) * 0x200;
+	ad = (struct adaptec_metadata *)
+			blkid_probe_get_buffer(pr,
+					off,
+					sizeof(struct adaptec_metadata));
+	if (!ad)
+		return errno ? -errno : BLKID_PROBE_NONE;;
+
+	if (ad->smagic != be32_to_cpu(AD_SIGNATURE))
+		return BLKID_PROBE_NONE;
+	if (ad->b0idcode != be32_to_cpu(AD_MAGIC))
+		return BLKID_PROBE_NONE;
+	if (blkid_probe_sprintf_version(pr, "%u", ad->resver) != 0)
+		return BLKID_PROBE_NONE;
+	if (blkid_probe_set_magic(pr, off, sizeof(ad->b0idcode),
+				(unsigned char *) &ad->b0idcode))
+		return BLKID_PROBE_NONE;
+
+	return BLKID_PROBE_OK;
+}
+
+const struct blkid_idinfo adraid_idinfo = {
+	.name		= "adaptec_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_adraid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c
new file mode 100644
index 0000000..b3e397b
--- /dev/null
+++ b/libblkid/src/superblocks/bcache.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2013 Rolf Fokkens <rolf@fokkens.nl>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ * Based on code fragments from bcache-tools by Kent Overstreet:
+ * http://evilpiepirate.org/git/bcache-tools.git
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "superblocks.h"
+#include "crc64.h"
+
+#define SB_LABEL_SIZE      32
+#define SB_JOURNAL_BUCKETS 256U
+
+#define node(i, j)         ((i)->d + (j))
+#define end(i)             node(i, (i)->keys)
+
+static const char bcache_magic[] = {
+	0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
+	0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81
+};
+
+struct bcache_super_block {
+	uint64_t		csum;
+	uint64_t		offset;	/* sector where this sb was written */
+	uint64_t		version;
+
+	uint8_t			magic[16];
+
+	uint8_t			uuid[16];
+	union {
+		uint8_t		set_uuid[16];
+		uint64_t	set_magic;
+	};
+	uint8_t			label[SB_LABEL_SIZE];
+
+	uint64_t		flags;
+	uint64_t		seq;
+	uint64_t		pad[8];
+
+	union {
+	struct {
+		/* Cache devices */
+		uint64_t	nbuckets;	/* device size */
+
+		uint16_t	block_size;	/* sectors */
+		uint16_t	bucket_size;	/* sectors */
+
+		uint16_t	nr_in_set;
+		uint16_t	nr_this_dev;
+	};
+	struct {
+		/* Backing devices */
+		uint64_t	data_offset;
+
+		/*
+		 * block_size from the cache device section is still used by
+		 * backing devices, so don't add anything here until we fix
+		 * things to not need it for backing devices anymore
+		 */
+	};
+	};
+
+	uint32_t		last_mount;	/* time_t */
+
+	uint16_t		first_bucket;
+	union {
+		uint16_t	njournal_buckets;
+		uint16_t	keys;
+	};
+	uint64_t		d[SB_JOURNAL_BUCKETS];	/* journal buckets */
+};
+
+/* magic string */
+#define BCACHE_SB_MAGIC     bcache_magic
+/* magic string len */
+#define BCACHE_SB_MAGIC_LEN sizeof (bcache_magic)
+/* super block offset */
+#define BCACHE_SB_OFF       0x1000
+/* supper block offset in kB */
+#define BCACHE_SB_KBOFF     (BCACHE_SB_OFF >> 10)
+/* magic string offset within super block */
+#define BCACHE_SB_MAGIC_OFF offsetof (struct bcache_super_block, magic)
+
+static uint64_t bcache_crc64(struct bcache_super_block *bcs)
+{
+	unsigned char *data = (unsigned char *) bcs;
+	size_t sz;
+
+	data += 8;		/* skip csum field */
+	sz = (unsigned char *) end(bcs) - data;
+
+	return crc64(0xFFFFFFFFFFFFFFFFULL, data, sz) ^ 0xFFFFFFFFFFFFFFFFULL;
+}
+
+static int probe_bcache (blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct bcache_super_block *bcs;
+
+	bcs = blkid_probe_get_sb(pr, mag, struct bcache_super_block);
+	if (!bcs)
+		return errno ? -errno : BLKID_PROBE_NONE;
+
+	if (le64_to_cpu(bcs->offset) != BCACHE_SB_OFF / 512)
+		return BLKID_PROBE_NONE;
+	if (!blkid_probe_verify_csum(pr, bcache_crc64(bcs), le64_to_cpu(bcs->csum)))
+		return BLKID_PROBE_NONE;
+
+	if (blkid_probe_set_uuid(pr, bcs->uuid) < 0)
+		return BLKID_PROBE_NONE;
+
+	return BLKID_PROBE_OK;
+};
+
+const struct blkid_idinfo bcache_idinfo =
+{
+	.name		= "bcache",
+	.usage		= BLKID_USAGE_OTHER,
+	.probefunc	= probe_bcache,
+	.minsz		= 8192,
+	.magics		=
+	{
+		{ .magic = BCACHE_SB_MAGIC
+		, .len   = BCACHE_SB_MAGIC_LEN
+		, .kboff = BCACHE_SB_KBOFF
+		, .sboff = BCACHE_SB_MAGIC_OFF
+		} ,
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/befs.c b/libblkid/src/superblocks/befs.c
new file mode 100644
index 0000000..e4453bc
--- /dev/null
+++ b/libblkid/src/superblocks/befs.c
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2010 Jeroen Oortwijn <oortwijn@gmail.com>
+ *
+ * Partly based on the Haiku BFS driver by
+ *     Axel Dörfler <axeld@pinc-software.de>
+ *
+ * Also inspired by the Linux BeFS driver by
+ *     Will Dyson <will_dyson@pobox.com>, et al.
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "superblocks.h"
+
+#define B_OS_NAME_LENGTH	0x20
+#define SUPER_BLOCK_MAGIC1	0x42465331	/* BFS1 */
+#define SUPER_BLOCK_MAGIC2	0xdd121031
+#define SUPER_BLOCK_MAGIC3	0x15b6830e
+#define SUPER_BLOCK_FS_ENDIAN	0x42494745	/* BIGE */
+#define INODE_MAGIC1		0x3bbe0ad9
+#define BPLUSTREE_MAGIC		0x69f6c2e8
+#define BPLUSTREE_NULL		-1LL
+#define NUM_DIRECT_BLOCKS	12
+#define B_UINT64_TYPE		0x554c4c47	/* ULLG */
+#define KEY_NAME		"be:volume_id"
+#define KEY_SIZE		8
+
+#define FS16_TO_CPU(value, fs_is_le) (fs_is_le ? le16_to_cpu(value) \
+							: be16_to_cpu(value))
+#define FS32_TO_CPU(value, fs_is_le) (fs_is_le ? le32_to_cpu(value) \
+							: be32_to_cpu(value))
+#define FS64_TO_CPU(value, fs_is_le) (fs_is_le ? le64_to_cpu(value) \
+							: be64_to_cpu(value))
+
+typedef struct block_run {
+	int32_t		allocation_group;
+	uint16_t	start;
+	uint16_t	len;
+} __attribute__((packed)) block_run, inode_addr;
+
+struct befs_super_block {
+	char		name[B_OS_NAME_LENGTH];
+	int32_t		magic1;
+	int32_t		fs_byte_order;
+	uint32_t	block_size;
+	uint32_t	block_shift;
+	int64_t		num_blocks;
+	int64_t		used_blocks;
+	int32_t		inode_size;
+	int32_t		magic2;
+	int32_t		blocks_per_ag;
+	int32_t		ag_shift;
+	int32_t		num_ags;
+	int32_t		flags;
+	block_run	log_blocks;
+	int64_t		log_start;
+	int64_t		log_end;
+	int32_t		magic3;
+	inode_addr	root_dir;
+	inode_addr	indices;
+	int32_t		pad[8];
+} __attribute__((packed));
+
+typedef struct data_stream {
+	block_run	direct[NUM_DIRECT_BLOCKS];
+	int64_t		max_direct_range;
+	block_run	indirect;
+	int64_t		max_indirect_range;
+	block_run	double_indirect;
+	int64_t		max_double_indirect_range;
+	int64_t		size;
+} __attribute__((packed)) data_stream;
+
+struct befs_inode {
+	int32_t		magic1;
+	inode_addr	inode_num;
+	int32_t		uid;
+	int32_t		gid;
+	int32_t		mode;
+	int32_t		flags;
+	int64_t		create_time;
+	int64_t		last_modified_time;
+	inode_addr	parent;
+	inode_addr	attributes;
+	uint32_t	type;
+	int32_t		inode_size;
+	uint32_t	etc;
+	data_stream	data;
+	int32_t		pad[4];
+	int32_t		small_data[0];
+} __attribute__((packed));
+
+struct small_data {
+	uint32_t	type;
+	uint16_t	name_size;
+	uint16_t	data_size;
+	char		name[0];
+} __attribute__((packed));
+
+struct bplustree_header {
+	uint32_t	magic;
+	uint32_t	node_size;
+	uint32_t	max_number_of_levels;
+	uint32_t	data_type;
+	int64_t		root_node_pointer;
+	int64_t		free_node_pointer;
+	int64_t		maximum_size;
+} __attribute__((packed));
+
+struct bplustree_node {
+	int64_t		left_link;
+	int64_t		right_link;
+	int64_t		overflow_link;
+	uint16_t	all_key_count;
+	uint16_t	all_key_length;
+	char		name[0];
+} __attribute__((packed));
+
+static unsigned char *get_block_run(blkid_probe pr, const struct befs_super_block *bs,
+					const struct block_run *br, int fs_le)
+{
+	return blkid_probe_get_buffer(pr,
+			((blkid_loff_t) FS32_TO_CPU(br->allocation_group, fs_le)
+					<< FS32_TO_CPU(bs->ag_shift, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le))
+				+ ((blkid_loff_t) FS16_TO_CPU(br->start, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le)),
+			(blkid_loff_t) FS16_TO_CPU(br->len, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le));
+}
+
+static unsigned char *get_custom_block_run(blkid_probe pr,
+				const struct befs_super_block *bs,
+				const struct block_run *br,
+				int64_t offset, uint32_t length, int fs_le)
+{
+	if (offset + length > (int64_t) FS16_TO_CPU(br->len, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le))
+		return NULL;
+
+	return blkid_probe_get_buffer(pr,
+			((blkid_loff_t) FS32_TO_CPU(br->allocation_group, fs_le)
+					<< FS32_TO_CPU(bs->ag_shift, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le))
+				+ ((blkid_loff_t) FS16_TO_CPU(br->start, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le))
+				+ offset,
+			length);
+}
+
+static unsigned char *get_tree_node(blkid_probe pr, const struct befs_super_block *bs,
+				const struct data_stream *ds,
+				int64_t start, uint32_t length, int fs_le)
+{
+	if (start < (int64_t) FS64_TO_CPU(ds->max_direct_range, fs_le)) {
+		int64_t br_len;
+		size_t i;
+
+		for (i = 0; i < NUM_DIRECT_BLOCKS; i++) {
+			br_len = (int64_t) FS16_TO_CPU(ds->direct[i].len, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le);
+			if (start < br_len)
+				return get_custom_block_run(pr, bs,
+							&ds->direct[i],
+							start, length, fs_le);
+			else
+				start -= br_len;
+		}
+	} else if (start < (int64_t) FS64_TO_CPU(ds->max_indirect_range, fs_le)) {
+		struct block_run *br;
+		int64_t max_br, br_len, i;
+
+		start -= FS64_TO_CPU(ds->max_direct_range, fs_le);
+		max_br = ((int64_t) FS16_TO_CPU(ds->indirect.len, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le))
+				/ sizeof(struct block_run);
+
+		br = (struct block_run *) get_block_run(pr, bs, &ds->indirect,
+									fs_le);
+		if (!br)
+			return NULL;
+
+		for (i = 0; i < max_br; i++) {
+			br_len = (int64_t) FS16_TO_CPU(br[i].len, fs_le)
+					<< FS32_TO_CPU(bs->block_shift, fs_le);
+			if (start < br_len)
+				return get_custom_block_run(pr, bs, &br[i],
+							start, length, fs_le);
+			else
+				start -= br_len;
+		}
+	} else if (start < (int64_t) FS64_TO_CPU(ds->max_double_indirect_range, fs_le)) {
+		struct block_run *br;
+		int64_t di_br_size, br_per_di_br, di_index, i_index;
+
+		start -= (int64_t) FS64_TO_CPU(ds->max_indirect_range, fs_le);
+
+		di_br_size = (int64_t) FS16_TO_CPU(ds->double_indirect.len,
+				fs_le) << FS32_TO_CPU(bs->block_shift, fs_le);
+		if (di_br_size == 0)
+			return NULL;
+
+		br_per_di_br = di_br_size / sizeof(struct block_run);
+		if (br_per_di_br == 0)
+			return NULL;
+
+		di_index = start / (br_per_di_br * di_br_size);
+		i_index = (start % (br_per_di_br * di_br_size)) / di_br_size;
+		start = (start % (br_per_di_br * di_br_size)) % di_br_size;
+
+		br = (struct block_run *) get_block_run(pr, bs,
+						&ds->double_indirect, fs_le);
+		if (!br)
+			return NULL;
+
+		br = (struct block_run *) get_block_run(pr, bs, &br[di_index],
+									fs_le);
+		if (!br)
+			return NULL;
+
+		return get_custom_block_run(pr, bs, &br[i_index], start, length,
+									fs_le);
+	}
+	return NULL;
+}
+
+static int32_t compare_keys(const char keys1[], uint16_t keylengths1[], int32_t index,
+			const char *key2, uint16_t keylength2, int fs_le)
+{
+	const char *key1;
+	uint16_t keylength1;
+	int32_t result;
+
+	key1 = &keys1[index == 0 ? 0 : FS16_TO_CPU(keylengths1[index - 1],
+									fs_le)];
+	keylength1 = FS16_TO_CPU(keylengths1[index], fs_le)
+			- (index == 0 ? 0 : FS16_TO_CPU(keylengths1[index - 1],
+									fs_le));
+
+	result = strncmp(key1, key2, min(keylength1, keylength2));
+
+	if (result == 0)
+		return keylength1 - keylength2;
+
+	return result;
+}
+
+static int64_t get_key_value(blkid_probe pr, const struct befs_super_block *bs,
+			const struct befs_inode *bi, const char *key, int fs_le)
+{
+	struct bplustree_header *bh;
+	struct bplustree_node *bn;
+	uint16_t *keylengths;
+	int64_t *values;
+	int64_t node_pointer;
+	int32_t first, last, mid, cmp;
+
+	errno = 0;
+	bh = (struct bplustree_header *) get_tree_node(pr, bs, &bi->data, 0,
+					sizeof(struct bplustree_header), fs_le);
+	if (!bh)
+		return errno ? -errno : -ENOENT;
+
+	if ((int32_t) FS32_TO_CPU(bh->magic, fs_le) != BPLUSTREE_MAGIC)
+		return -ENOENT;
+
+	node_pointer = FS64_TO_CPU(bh->root_node_pointer, fs_le);
+
+	do {
+		errno = 0;
+		bn = (struct bplustree_node *) get_tree_node(pr, bs, &bi->data,
+			node_pointer, FS32_TO_CPU(bh->node_size, fs_le), fs_le);
+		if (!bn)
+			return errno ? -errno : -ENOENT;
+
+		keylengths = (uint16_t *) ((uint8_t *) bn
+				+ ((sizeof(struct bplustree_node)
+					+ FS16_TO_CPU(bn->all_key_length, fs_le)
+					+ sizeof(int64_t) - 1)
+						& ~(sizeof(int64_t) - 1)));
+		values = (int64_t *) ((uint8_t *) keylengths
+					+ FS16_TO_CPU(bn->all_key_count, fs_le)
+						* sizeof(uint16_t));
+		first = 0;
+		mid = 0;
+		last = FS16_TO_CPU(bn->all_key_count, fs_le) - 1;
+
+		cmp = compare_keys(bn->name, keylengths, last, key, strlen(key),
+									fs_le);
+		if (cmp == 0) {
+			if ((int64_t) FS64_TO_CPU(bn->overflow_link, fs_le)
+							== BPLUSTREE_NULL)
+				return FS64_TO_CPU(values[last], fs_le);
+			else
+				node_pointer = FS64_TO_CPU(values[last], fs_le);
+		} else if (cmp < 0)
+			node_pointer = FS64_TO_CPU(bn->overflow_link, fs_le);
+		else {
+			while (first <= last) {
+				mid = (first + last) / 2;
+
+				cmp = compare_keys(bn->name, keylengths, mid,
+						key, strlen(key), fs_le);
+				if (cmp == 0) {
+					if ((int64_t) FS64_TO_CPU(bn->overflow_link,
+						fs_le) == BPLUSTREE_NULL)
+						return FS64_TO_CPU(values[mid],
+									fs_le);
+					else
+						break;
+				} else if (cmp < 0)
+					first = mid + 1;
+				else
+					last = mid - 1;
+			}
+			if (cmp < 0)
+				node_pointer = FS64_TO_CPU(values[mid + 1],
+									fs_le);
+			else
+				node_pointer = FS64_TO_CPU(values[mid], fs_le);
+		}
+	} while ((int64_t) FS64_TO_CPU(bn->overflow_link, fs_le)
+						!= BPLUSTREE_NULL);
+	return 0;
+}
+
+static int get_uuid(blkid_probe pr, const struct befs_super_block *bs,
+					uint64_t * const uuid, int fs_le)
+{
+	struct befs_inode *bi;
+	struct small_data *sd;
+
+	bi = (struct befs_inode *) get_block_run(pr, bs, &bs->root_dir, fs_le);
+	if (!bi)
+		return errno ? -errno : BLKID_PROBE_NONE;
+
+	if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
+		return BLKID_PROBE_NONE;
+
+	sd = (struct small_data *) bi->small_data;
+
+	do {
+		if (FS32_TO_CPU(sd->type, fs_le) == B_UINT64_TYPE
+			&& FS16_TO_CPU(sd->name_size, fs_le) == strlen(KEY_NAME)
+			&& FS16_TO_CPU(sd->data_size, fs_le) == KEY_SIZE
+			&& strcmp(sd->name, KEY_NAME) == 0) {
+
+			memcpy(uuid,
+			       sd->name + FS16_TO_CPU(sd->name_size, fs_le) + 3,
+			       sizeof(uint64_t));
+
+			break;
+		} else if (FS32_TO_CPU(sd->type, fs_le) == 0
+				&& FS16_TO_CPU(sd->name_size, fs_le) == 0
+				&& FS16_TO_CPU(sd->data_size, fs_le) == 0)
+			break;
+
+		sd = (struct small_data *) ((uint8_t *) sd
+				+ sizeof(struct small_data)
+				+ FS16_TO_CPU(sd->name_size, fs_le) + 3
+				+ FS16_TO_CPU(sd->data_size, fs_le) + 1);
+
+	} while ((intptr_t) sd < (intptr_t) bi
+				+ (int32_t) FS32_TO_CPU(bi->inode_size, fs_le)
+				- (int32_t) sizeof(struct small_data));
+	if (*uuid == 0
+		&& (FS32_TO_CPU(bi->attributes.allocation_group, fs_le) != 0
+			|| FS16_TO_CPU(bi->attributes.start, fs_le) != 0
+			|| FS16_TO_CPU(bi->attributes.len, fs_le) != 0)) {
+		int64_t value;
+
+		bi = (struct befs_inode *) get_block_run(pr, bs,
+							&bi->attributes, fs_le);
+		if (!bi)
+			return errno ? -errno : BLKID_PROBE_NONE;
+
+		if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
+			return BLKID_PROBE_NONE;
+
+		value = get_key_value(pr, bs, bi, KEY_NAME, fs_le);
+		if (value < 0)
+			return value == -ENOENT ? BLKID_PROBE_NONE : value;
+
+		else if (value > 0) {
+			bi = (struct befs_inode *) blkid_probe_get_buffer(pr,
+				value << FS32_TO_CPU(bs->block_shift, fs_le),
+				FS32_TO_CPU(bs->block_size, fs_le));
+			if (!bi)
+				return errno ? -errno : BLKID_PROBE_NONE;
+
+			if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
+				return 1;
+
+			if (FS32_TO_CPU(bi->type, fs_le) == B_UINT64_TYPE
+				&& FS64_TO_CPU(bi->data.size, fs_le) == KEY_SIZE
+				&& FS16_TO_CPU(bi->data.direct[0].len, fs_le)
+									== 1) {
+				uint64_t *attr_data;
+
+				attr_data = (uint64_t *) get_block_run(pr, bs,
+						&bi->data.direct[0], fs_le);
+				if (!attr_data)
+					return errno ? -errno : BLKID_PROBE_NONE;
+
+				*uuid = *attr_data;
+			}
+		}
+	}
+	return 0;
+}
+
+static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct befs_super_block *bs;
+	const char *version = NULL;
+	uint64_t volume_id = 0;
+	int fs_le, ret;
+
+	bs = (struct befs_super_block *) blkid_probe_get_buffer(pr,
+					mag->sboff - B_OS_NAME_LENGTH,
+					sizeof(struct befs_super_block));
+	if (!bs)
+		return errno ? -errno : BLKID_PROBE_NONE;
+
+	if (le32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1
+		&& le32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2
+		&& le32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3
+		&& le32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) {
+		fs_le = 1;
+		version = "little-endian";
+	} else if (be32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1
+		&& be32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2
+		&& be32_to_cpu(bs->magic3) == SUPER_BLOCK_MAGIC3
+		&& be32_to_cpu(bs->fs_byte_order) == SUPER_BLOCK_FS_ENDIAN) {
+		fs_le = 0;
+		version = "big-endian";
+	} else
+		return BLKID_PROBE_NONE;
+
+	ret = get_uuid(pr, bs, &volume_id, fs_le);
+
+	if (ret != 0)
+		return ret;
+
+	/*
+	 * all checks pass, set LABEL, VERSION and UUID
+	 */
+	if (strlen(bs->name))
+		blkid_probe_set_label(pr, (unsigned char *) bs->name,
+							sizeof(bs->name));
+	if (version)
+		blkid_probe_set_version(pr, version);
+
+	if (volume_id)
+		blkid_probe_sprintf_uuid(pr, (unsigned char *) &volume_id,
+					sizeof(volume_id), "%016" PRIx64,
+					FS64_TO_CPU(volume_id, fs_le));
+	return BLKID_PROBE_OK;
+}
+
+const struct blkid_idinfo befs_idinfo =
+{
+	.name		= "befs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_befs,
+	.minsz		= 1024 * 1440,
+	.magics		= {
+		{ .magic = "BFS1", .len = 4, .sboff = B_OS_NAME_LENGTH },
+		{ .magic = "1SFB", .len = 4, .sboff = B_OS_NAME_LENGTH },
+		{ .magic = "BFS1", .len = 4, .sboff = 0x200 +
+							B_OS_NAME_LENGTH },
+		{ .magic = "1SFB", .len = 4, .sboff = 0x200 +
+							B_OS_NAME_LENGTH },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/bfs.c b/libblkid/src/superblocks/bfs.c
new file mode 100644
index 0000000..8a34c58
--- /dev/null
+++ b/libblkid/src/superblocks/bfs.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2009 Red Hat, Inc.
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include "superblocks.h"
+
+/*
+ * BFS actually has two different labels in the superblock, each
+ * of them only 6 bytes long.  Until we find out what their use
+ * we just ignore them.
+ */
+const struct blkid_idinfo bfs_idinfo =
+{
+	.name		= "bfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.magics		= {
+		{ .magic = "\xce\xfa\xad\x1b", .len = 4 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/btrfs.c b/libblkid/src/superblocks/btrfs.c
new file mode 100644
index 0000000..7ce3dff
--- /dev/null
+++ b/libblkid/src/superblocks/btrfs.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.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];
+	} __attribute__ ((__packed__)) dev_item;
+	uint8_t label[256];
+} __attribute__ ((__packed__));
+
+static int probe_btrfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct btrfs_super_block *bfs;
+
+	bfs = blkid_probe_get_sb(pr, mag, struct btrfs_super_block);
+	if (!bfs)
+		return errno ? -errno : 1;
+
+	if (*bfs->label)
+		blkid_probe_set_label(pr,
+				(unsigned char *) bfs->label,
+				sizeof(bfs->label));
+
+	blkid_probe_set_uuid(pr, bfs->fsid);
+	blkid_probe_set_uuid_as(pr, bfs->dev_item.uuid, "UUID_SUB");
+
+	return 0;
+}
+
+const struct blkid_idinfo btrfs_idinfo =
+{
+	.name		= "btrfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_btrfs,
+	.minsz		= 1024 * 1024,
+	.magics		=
+	{
+	  { .magic = "_BHRfS_M", .len = 8, .sboff = 0x40, .kboff = 64 },
+	  { NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/cramfs.c b/libblkid/src/superblocks/cramfs.c
new file mode 100644
index 0000000..6d01b0b
--- /dev/null
+++ b/libblkid/src/superblocks/cramfs.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct cramfs_super
+{
+	uint8_t		magic[4];
+	uint32_t	size;
+	uint32_t	flags;
+	uint32_t	future;
+	uint8_t		signature[16];
+	struct cramfs_info
+	{
+		uint32_t	crc;
+		uint32_t	edition;
+		uint32_t	blocks;
+		uint32_t	files;
+	} __attribute__((packed)) info;
+	uint8_t		name[16];
+} __attribute__((packed));
+
+static int probe_cramfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct cramfs_super *cs;
+
+	cs = blkid_probe_get_sb(pr, mag, struct cramfs_super);
+	if (!cs)
+		return errno ? -errno : 1;
+
+	blkid_probe_set_label(pr, cs->name, sizeof(cs->name));
+	return 0;
+}
+
+const struct blkid_idinfo cramfs_idinfo =
+{
+	.name		= "cramfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_cramfs,
+	.magics		=
+	{
+		{ "\x45\x3d\xcd\x28", 4, 0, 0 },
+		{ "\x28\xcd\x3d\x45", 4, 0, 0 },
+		{ NULL }
+	}
+};
+
+
diff --git a/libblkid/src/superblocks/ddf_raid.c b/libblkid/src/superblocks/ddf_raid.c
new file mode 100644
index 0000000..fc2c39d
--- /dev/null
+++ b/libblkid/src/superblocks/ddf_raid.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+/* http://www.snia.org/standards/home */
+#define DDF_GUID_LENGTH			24
+#define DDF_REV_LENGTH			8
+#define DDF_MAGIC			0xDE11DE11
+
+
+struct ddf_header {
+	uint32_t	signature;
+	uint32_t	crc;
+	uint8_t		guid[DDF_GUID_LENGTH];
+	char		ddf_rev[8];	/* 01.02.00 */
+	uint32_t	seq;		/* starts at '1' */
+	uint32_t	timestamp;
+	uint8_t		openflag;
+	uint8_t		foreignflag;
+	uint8_t		enforcegroups;
+	uint8_t		pad0;		/* 0xff */
+	uint8_t		pad1[12];	/* 12 * 0xff */
+	/* 64 bytes so far */
+	uint8_t		header_ext[32];	/* reserved: fill with 0xff */
+	uint64_t	primary_lba;
+	uint64_t	secondary_lba;
+	uint8_t		type;
+	uint8_t		pad2[3];	/* 0xff */
+	uint32_t	workspace_len;	/* sectors for vendor space -
+					 * at least 32768(sectors) */
+	uint64_t	workspace_lba;
+	uint16_t	max_pd_entries;	/* one of 15, 63, 255, 1023, 4095 */
+	uint16_t	max_vd_entries; /* 2^(4,6,8,10,12)-1 : i.e. as above */
+	uint16_t	max_partitions; /* i.e. max num of configuration
+					   record entries per disk */
+	uint16_t	config_record_len; /* 1 +ROUNDUP(max_primary_element_entries
+				           *12/512) */
+	uint16_t	max_primary_element_entries; /* 16, 64, 256, 1024, or 4096 */
+	uint8_t		pad3[54];	/* 0xff */
+	/* 192 bytes so far */
+	uint32_t	controller_section_offset;
+	uint32_t	controller_section_length;
+	uint32_t	phys_section_offset;
+	uint32_t	phys_section_length;
+	uint32_t	virt_section_offset;
+	uint32_t	virt_section_length;
+	uint32_t	config_section_offset;
+	uint32_t	config_section_length;
+	uint32_t	data_section_offset;
+	uint32_t	data_section_length;
+	uint32_t	bbm_section_offset;
+	uint32_t	bbm_section_length;
+	uint32_t	diag_space_offset;
+	uint32_t	diag_space_length;
+	uint32_t	vendor_offset;
+	uint32_t	vendor_length;
+	/* 256 bytes so far */
+	uint8_t		pad4[256];	/* 0xff */
+} __attribute__((packed));
+
+static int probe_ddf(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	int hdrs[] = { 1, 257 };
+	size_t i;
+	struct ddf_header *ddf = NULL;
+	char version[DDF_REV_LENGTH + 1];
+	uint64_t off, lba;
+
+	if (pr->size < 0x30000)
+		return 1;
+
+	for (i = 0; i < ARRAY_SIZE(hdrs); i++) {
+		off = ((pr->size / 0x200) - hdrs[i]) * 0x200;
+
+		ddf = (struct ddf_header *) blkid_probe_get_buffer(pr,
+					off,
+					sizeof(struct ddf_header));
+		if (!ddf)
+			return errno ? -errno : 1;
+		if (ddf->signature == cpu_to_be32(DDF_MAGIC) ||
+		    ddf->signature == cpu_to_le32(DDF_MAGIC))
+			break;
+		ddf = NULL;
+	}
+
+	if (!ddf)
+		return 1;
+
+	lba = ddf->signature == cpu_to_be32(DDF_MAGIC) ?
+			be64_to_cpu(ddf->primary_lba) :
+			le64_to_cpu(ddf->primary_lba);
+
+	if (lba > 0) {
+		/* check primary header */
+		unsigned char *buf;
+
+		buf = blkid_probe_get_buffer(pr,
+					lba << 9, sizeof(ddf->signature));
+		if (!buf)
+			return errno ? -errno : 1;
+
+		if (memcmp(buf, &ddf->signature, 4) != 0)
+			return 1;
+	}
+
+	blkid_probe_strncpy_uuid(pr, ddf->guid, sizeof(ddf->guid));
+
+	memcpy(version, ddf->ddf_rev, sizeof(ddf->ddf_rev));
+	*(version + sizeof(ddf->ddf_rev)) = '\0';
+
+	if (blkid_probe_set_version(pr, version) != 0)
+		return 1;
+	if (blkid_probe_set_magic(pr, off,
+			sizeof(ddf->signature),
+			(unsigned char *) &ddf->signature))
+		return 1;
+	return 0;
+}
+
+const struct blkid_idinfo ddfraid_idinfo = {
+	.name		= "ddf_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_ddf,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/drbd.c b/libblkid/src/superblocks/drbd.c
new file mode 100644
index 0000000..e88e9f3
--- /dev/null
+++ b/libblkid/src/superblocks/drbd.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2009 by Bastian Friedrich <bastian.friedrich@collax.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ *
+ * defines, structs taken from drbd source; file names represent drbd source
+ * files.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <stddef.h>
+
+#include "superblocks.h"
+
+/*
+ * drbd/linux/drbd.h
+ */
+#define DRBD_MAGIC 0x83740267
+
+/*
+ * user/drbdmeta.c
+ * We only support v08 for now
+ */
+#define DRBD_MD_MAGIC_08         (DRBD_MAGIC+4)
+#define DRBD_MD_MAGIC_84_UNCLEAN (DRBD_MAGIC+5)
+
+/*
+ * drbd/linux/drbd.h
+ */
+enum drbd_uuid_index {
+	UI_CURRENT,
+	UI_BITMAP,
+	UI_HISTORY_START,
+	UI_HISTORY_END,
+	UI_SIZE,		/* nl-packet: number of dirty bits */
+	UI_FLAGS,		/* nl-packet: flags */
+	UI_EXTENDED_SIZE	/* Everything. */
+};
+
+/*
+ * user/drbdmeta.c
+ * Minor modifications wrt. types
+ */
+struct md_on_disk_08 {
+	uint64_t la_sect;         /* last agreed size. */
+	uint64_t uuid[UI_SIZE];   /* UUIDs */
+	uint64_t device_uuid;
+	uint64_t reserved_u64_1;
+	uint32_t flags;
+	uint32_t magic;
+	uint32_t md_size_sect;
+	int32_t  al_offset;       /* signed sector offset to this block */
+	uint32_t al_nr_extents;   /* important for restoring the AL */
+	int32_t  bm_offset;       /* signed sector offset to the bitmap, from here */
+	uint32_t bm_bytes_per_bit;
+	uint32_t reserved_u32[4];
+
+	char reserved[8 * 512 - (8*(UI_SIZE+3)+4*11)];
+};
+
+
+static int probe_drbd(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct md_on_disk_08 *md;
+	off_t off;
+
+	off = pr->size - sizeof(*md);
+
+	/* Small devices cannot be drbd (?) */
+	if (pr->size < 0x10000)
+		return 1;
+
+	md = (struct md_on_disk_08 *)
+			blkid_probe_get_buffer(pr,
+					off,
+					sizeof(struct md_on_disk_08));
+	if (!md)
+		return errno ? -errno : 1;
+
+	if (be32_to_cpu(md->magic) != DRBD_MD_MAGIC_08 &&
+			be32_to_cpu(md->magic) != DRBD_MD_MAGIC_84_UNCLEAN)
+		return 1;
+
+	/*
+	 * DRBD does not have "real" uuids; the following resembles DRBD's
+	 * notion of uuids (64 bit, see struct above)
+	 */
+	blkid_probe_sprintf_uuid(pr,
+		(unsigned char *) &md->device_uuid, sizeof(md->device_uuid),
+		"%" PRIx64, be64_to_cpu(md->device_uuid));
+
+	blkid_probe_set_version(pr, "v08");
+
+	if (blkid_probe_set_magic(pr,
+				off + offsetof(struct md_on_disk_08, magic),
+				sizeof(md->magic),
+				(unsigned char *) &md->magic))
+		return 1;
+
+	return 0;
+}
+
+const struct blkid_idinfo drbd_idinfo =
+{
+	.name		= "drbd",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_drbd,
+	.magics		= BLKID_NONE_MAGIC
+};
+
diff --git a/libblkid/src/superblocks/drbdproxy_datalog.c b/libblkid/src/superblocks/drbdproxy_datalog.c
new file mode 100644
index 0000000..af59722
--- /dev/null
+++ b/libblkid/src/superblocks/drbdproxy_datalog.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 by Philipp Marek <philipp.marek@linbit.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <stddef.h>
+
+#include "superblocks.h"
+
+
+struct log_header_t {
+	uint64_t magic;
+	uint64_t version;
+
+	unsigned char uuid[16];
+
+	uint64_t flags;
+} __attribute__((packed));
+
+
+static int probe_drbdproxy_datalog(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct log_header_t *lh;
+
+	lh = (struct log_header_t *) blkid_probe_get_buffer(pr, 0, sizeof(*lh));
+	if (!lh)
+		return errno ? -errno : 1;
+
+	blkid_probe_set_uuid(pr, lh->uuid);
+	blkid_probe_sprintf_version(pr, "v%jd", le64_to_cpu(lh->version));
+
+	return 0;
+}
+
+const struct blkid_idinfo drbdproxy_datalog_idinfo =
+{
+	.name		= "drbdproxy_datalog",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_drbdproxy_datalog,
+	.minsz		= 16*1024,
+	.magics		=
+	{
+		{ .magic = "DRBDdlh*", .len = 8, .sboff = 0, .kboff = 0 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/exfat.c b/libblkid/src/superblocks/exfat.c
new file mode 100644
index 0000000..b526560
--- /dev/null
+++ b/libblkid/src/superblocks/exfat.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2010 Andrew Nayenko <resver@gmail.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include "superblocks.h"
+
+struct exfat_super_block {
+	uint8_t jump[3];
+	uint8_t oem_name[8];
+	uint8_t	__unused1[53];
+	uint64_t block_start;
+	uint64_t block_count;
+	uint32_t fat_block_start;
+	uint32_t fat_block_count;
+	uint32_t cluster_block_start;
+	uint32_t cluster_count;
+	uint32_t rootdir_cluster;
+	uint8_t volume_serial[4];
+	struct {
+		uint8_t minor;
+		uint8_t major;
+	} version;
+	uint16_t volume_state;
+	uint8_t block_bits;
+	uint8_t bpc_bits;
+	uint8_t fat_count;
+	uint8_t drive_no;
+	uint8_t allocated_percent;
+} __attribute__((__packed__));
+
+struct exfat_entry_label {
+	uint8_t type;
+	uint8_t length;
+	uint8_t name[30];
+} __attribute__((__packed__));
+
+#define BLOCK_SIZE(sb) (1 << (sb)->block_bits)
+#define CLUSTER_SIZE(sb) (BLOCK_SIZE(sb) << (sb)->bpc_bits)
+#define EXFAT_FIRST_DATA_CLUSTER 2
+#define EXFAT_LAST_DATA_CLUSTER 0xffffff6
+#define EXFAT_ENTRY_SIZE 32
+
+#define EXFAT_ENTRY_EOD		0x00
+#define EXFAT_ENTRY_LABEL	0x83
+
+static blkid_loff_t block_to_offset(const struct exfat_super_block *sb,
+		blkid_loff_t block)
+{
+	return (blkid_loff_t) block << sb->block_bits;
+}
+
+static blkid_loff_t cluster_to_block(const struct exfat_super_block *sb,
+		uint32_t cluster)
+{
+	return le32_to_cpu(sb->cluster_block_start) +
+			((blkid_loff_t) (cluster - EXFAT_FIRST_DATA_CLUSTER)
+					<< sb->bpc_bits);
+}
+
+static blkid_loff_t cluster_to_offset(const struct exfat_super_block *sb,
+		uint32_t cluster)
+{
+	return block_to_offset(sb, cluster_to_block(sb, cluster));
+}
+
+static uint32_t next_cluster(blkid_probe pr,
+		const struct exfat_super_block *sb, uint32_t cluster)
+{
+	uint32_t *next;
+	blkid_loff_t fat_offset;
+
+	fat_offset = block_to_offset(sb, le32_to_cpu(sb->fat_block_start))
+		+ (blkid_loff_t) cluster * sizeof(cluster);
+	next = (uint32_t *) blkid_probe_get_buffer(pr, fat_offset,
+			sizeof(uint32_t));
+	if (!next)
+		return 0;
+	return le32_to_cpu(*next);
+}
+
+static struct exfat_entry_label *find_label(blkid_probe pr,
+		const struct exfat_super_block *sb)
+{
+	uint32_t cluster = le32_to_cpu(sb->rootdir_cluster);
+	blkid_loff_t offset = cluster_to_offset(sb, cluster);
+	uint8_t *entry;
+
+	for (;;) {
+		entry = (uint8_t *) blkid_probe_get_buffer(pr, offset,
+				EXFAT_ENTRY_SIZE);
+		if (!entry)
+			return NULL;
+		if (entry[0] == EXFAT_ENTRY_EOD)
+			return NULL;
+		if (entry[0] == EXFAT_ENTRY_LABEL)
+			return (struct exfat_entry_label *) entry;
+		offset += EXFAT_ENTRY_SIZE;
+		if (offset % CLUSTER_SIZE(sb) == 0) {
+			cluster = next_cluster(pr, sb, cluster);
+			if (cluster < EXFAT_FIRST_DATA_CLUSTER)
+				return NULL;
+			if (cluster > EXFAT_LAST_DATA_CLUSTER)
+				return NULL;
+			offset = cluster_to_offset(sb, cluster);
+		}
+	}
+}
+
+static int probe_exfat(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct exfat_super_block *sb;
+	struct exfat_entry_label *label;
+
+	sb = blkid_probe_get_sb(pr, mag, struct exfat_super_block);
+	if (!sb)
+		return errno ? -errno : BLKID_PROBE_NONE;
+
+	label = find_label(pr, sb);
+	if (label)
+		blkid_probe_set_utf8label(pr, label->name,
+				min(label->length * 2, 30), BLKID_ENC_UTF16LE);
+	else if (errno)
+		return -errno;
+
+	blkid_probe_sprintf_uuid(pr, sb->volume_serial, 4,
+			"%02hhX%02hhX-%02hhX%02hhX",
+			sb->volume_serial[3], sb->volume_serial[2],
+			sb->volume_serial[1], sb->volume_serial[0]);
+
+	blkid_probe_sprintf_version(pr, "%u.%u",
+			sb->version.major, sb->version.minor);
+
+	return BLKID_PROBE_OK;
+}
+
+const struct blkid_idinfo exfat_idinfo =
+{
+	.name		= "exfat",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_exfat,
+	.magics		=
+	{
+		{ .magic = "EXFAT   ", .len = 8, .sboff = 3 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/ext.c b/libblkid/src/superblocks/ext.c
new file mode 100644
index 0000000..5b1d179
--- /dev/null
+++ b/libblkid/src/superblocks/ext.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 1999, 2001 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+#ifdef __linux__
+#include <sys/utsname.h>
+#endif
+#include <time.h>
+
+#include "superblocks.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_dummy3[7];
+	unsigned char		s_magic[2];
+	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;
+	unsigned char		s_uuid[16];
+	char			s_volume_name[16];
+	char			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;
+	uint16_t		s_raid_stride;
+	uint16_t		s_mmp_interval;
+	uint64_t		s_mmp_block;
+	uint32_t		s_raid_stripe_width;
+	uint32_t		s_reserved[163];
+} __attribute__((packed));
+
+/* magic string */
+#define EXT_SB_MAGIC				"\123\357"
+/* supper block offset */
+#define EXT_SB_OFF				0x400
+/* supper block offset in kB */
+#define EXT_SB_KBOFF				(EXT_SB_OFF >> 10)
+/* magic string offset within super block */
+#define EXT_MAG_OFF				0x38
+
+
+
+/* for s_flags */
+#define EXT2_FLAGS_TEST_FILESYS		0x0004
+
+/* for s_feature_compat */
+#define EXT3_FEATURE_COMPAT_HAS_JOURNAL		0x0004
+
+/* for s_feature_ro_compat */
+#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 EXT4_FEATURE_RO_COMPAT_HUGE_FILE	0x0008
+#define EXT4_FEATURE_RO_COMPAT_GDT_CSUM		0x0010
+#define EXT4_FEATURE_RO_COMPAT_DIR_NLINK	0x0020
+#define EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE	0x0040
+
+/* for s_feature_incompat */
+#define EXT2_FEATURE_INCOMPAT_FILETYPE		0x0002
+#define EXT3_FEATURE_INCOMPAT_RECOVER		0x0004
+#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008
+#define EXT2_FEATURE_INCOMPAT_META_BG		0x0010
+#define EXT4_FEATURE_INCOMPAT_EXTENTS		0x0040 /* extents support */
+#define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
+#define EXT4_FEATURE_INCOMPAT_MMP		0x0100
+#define EXT4_FEATURE_INCOMPAT_FLEX_BG		0x0200
+
+#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_INCOMPAT_SUPP	(EXT2_FEATURE_INCOMPAT_FILETYPE| \
+					 EXT2_FEATURE_INCOMPAT_META_BG)
+#define EXT2_FEATURE_INCOMPAT_UNSUPPORTED	~EXT2_FEATURE_INCOMPAT_SUPP
+#define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED	~EXT2_FEATURE_RO_COMPAT_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_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 EXT3_FEATURE_RO_COMPAT_UNSUPPORTED	~EXT3_FEATURE_RO_COMPAT_SUPP
+
+/*
+ * Starting in 2.6.29, ext4 can be used to support filesystems
+ * without a journal.
+ */
+#define EXT4_SUPPORTS_EXT2 KERNEL_VERSION(2, 6, 29)
+
+/*
+ * reads superblock and returns:
+ *	fc = feature_compat
+ *	fi = feature_incompat
+ *	frc = feature_ro_compat
+ */
+static struct ext2_super_block *ext_get_super(
+		blkid_probe pr, uint32_t *fc, uint32_t *fi, uint32_t *frc)
+{
+	struct ext2_super_block *es;
+
+	es = (struct ext2_super_block *)
+			blkid_probe_get_buffer(pr, EXT_SB_OFF, 0x200);
+	if (!es)
+		return NULL;
+	if (fc)
+		*fc = le32_to_cpu(es->s_feature_compat);
+	if (fi)
+		*fi = le32_to_cpu(es->s_feature_incompat);
+	if (frc)
+		*frc = le32_to_cpu(es->s_feature_ro_compat);
+
+	return es;
+}
+
+static void ext_get_info(blkid_probe pr, int ver, struct ext2_super_block *es)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+
+	DBG(PROBE, ul_debug("ext2_sb.compat = %08X:%08X:%08X",
+		   le32_to_cpu(es->s_feature_compat),
+		   le32_to_cpu(es->s_feature_incompat),
+		   le32_to_cpu(es->s_feature_ro_compat)));
+
+	if (strlen(es->s_volume_name))
+		blkid_probe_set_label(pr, (unsigned char *) es->s_volume_name,
+					sizeof(es->s_volume_name));
+	blkid_probe_set_uuid(pr, es->s_uuid);
+
+	if (le32_to_cpu(es->s_feature_compat) & EXT3_FEATURE_COMPAT_HAS_JOURNAL)
+		blkid_probe_set_uuid_as(pr, es->s_journal_uuid, "EXT_JOURNAL");
+
+	if (ver != 2 && (chn->flags & BLKID_SUBLKS_SECTYPE) &&
+	    ((le32_to_cpu(es->s_feature_incompat) & EXT2_FEATURE_INCOMPAT_UNSUPPORTED) == 0))
+		blkid_probe_set_value(pr, "SEC_TYPE",
+				(unsigned char *) "ext2",
+				sizeof("ext2"));
+
+	blkid_probe_sprintf_version(pr, "%u.%u",
+		le32_to_cpu(es->s_rev_level),
+		le16_to_cpu(es->s_minor_rev_level));
+}
+
+
+static int probe_jbd(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct ext2_super_block *es;
+	uint32_t fi;
+
+	es = ext_get_super(pr, NULL, &fi, NULL);
+	if (!es)
+		return errno ? -errno : 1;
+	if (!(fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
+		return 1;
+
+	ext_get_info(pr, 2, es);
+	blkid_probe_set_uuid_as(pr, es->s_uuid, "LOGUUID");
+
+	return 0;
+}
+
+static int probe_ext2(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct ext2_super_block *es;
+	uint32_t fc, frc, fi;
+
+	es = ext_get_super(pr, &fc, &fi, &frc);
+	if (!es)
+		return errno ? -errno : 1;
+
+	/* Distinguish between ext3 and ext2 */
+	if (fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL)
+		return 1;
+
+	/* Any features which ext2 doesn't understand */
+	if ((frc & EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) ||
+	    (fi  & EXT2_FEATURE_INCOMPAT_UNSUPPORTED))
+		return 1;
+
+	ext_get_info(pr, 2, es);
+	return 0;
+}
+
+static int probe_ext3(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct ext2_super_block *es;
+	uint32_t fc, frc, fi;
+
+	es = ext_get_super(pr, &fc, &fi, &frc);
+	if (!es)
+		return errno ? -errno : 1;
+
+	/* ext3 requires journal */
+	if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
+		return 1;
+
+	/* Any features which ext3 doesn't understand */
+	if ((frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) ||
+	    (fi  & EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
+		return 1;
+
+	ext_get_info(pr, 3, es);
+	return 0;
+}
+
+
+static int probe_ext4dev(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct ext2_super_block *es;
+	uint32_t fc, frc, fi;
+
+	es = ext_get_super(pr, &fc, &fi, &frc);
+	if (!es)
+		return errno ? -errno : 1;
+
+	/* Distinguish from jbd */
+	if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+		return 1;
+
+	if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS))
+		return 1;
+
+	ext_get_info(pr, 4, es);
+	return 0;
+}
+
+static int probe_ext4(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct ext2_super_block *es;
+	uint32_t fc, frc, fi;
+
+	es = ext_get_super(pr, &fc, &fi, &frc);
+	if (!es)
+		return errno ? -errno : 1;
+
+	/* Distinguish from jbd */
+	if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)
+		return 1;
+
+	/* Ext4 has at least one feature which ext3 doesn't understand */
+	if (!(frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) &&
+	    !(fi  & EXT3_FEATURE_INCOMPAT_UNSUPPORTED))
+		return 1;
+
+	/*
+	 * If the filesystem is a OK for use by in-development
+	 * filesystem code, and ext4dev is supported or ext4 is not
+	 * supported, then don't call ourselves ext4, so we can redo
+	 * the detection and mark the filesystem as ext4dev.
+	 *
+	 * If the filesystem is marked as in use by production
+	 * filesystem, then it can only be used by ext4 and NOT by
+	 * ext4dev.
+	 */
+	if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)
+		return 1;
+
+	ext_get_info(pr, 4, es);
+	return 0;
+}
+
+#define BLKID_EXT_MAGICS \
+	{ \
+		{	 \
+			.magic = EXT_SB_MAGIC, \
+			.len = sizeof(EXT_SB_MAGIC) - 1, \
+			.kboff = EXT_SB_KBOFF, \
+			.sboff = EXT_MAG_OFF \
+		}, \
+		{ NULL } \
+	}
+
+const struct blkid_idinfo jbd_idinfo =
+{
+	.name		= "jbd",
+	.usage		= BLKID_USAGE_OTHER,
+	.probefunc	= probe_jbd,
+	.magics		= BLKID_EXT_MAGICS
+};
+
+const struct blkid_idinfo ext2_idinfo =
+{
+	.name		= "ext2",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ext2,
+	.magics		= BLKID_EXT_MAGICS
+};
+
+const struct blkid_idinfo ext3_idinfo =
+{
+	.name		= "ext3",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ext3,
+	.magics		= BLKID_EXT_MAGICS
+};
+
+const struct blkid_idinfo ext4_idinfo =
+{
+	.name		= "ext4",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ext4,
+	.magics		= BLKID_EXT_MAGICS
+};
+
+const struct blkid_idinfo ext4dev_idinfo =
+{
+	.name		= "ext4dev",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ext4dev,
+	.magics		= BLKID_EXT_MAGICS
+};
+
diff --git a/libblkid/src/superblocks/f2fs.c b/libblkid/src/superblocks/f2fs.c
new file mode 100644
index 0000000..2bf0f5e
--- /dev/null
+++ b/libblkid/src/superblocks/f2fs.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013 Alejandro Martinez Ruiz <alex@nowcomputing.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "superblocks.h"
+
+#define F2FS_MAGIC		"\x10\x20\xF5\xF2"
+#define F2FS_MAGIC_OFF		0
+#define F2FS_UUID_SIZE		16
+#define F2FS_LABEL_SIZE		512
+#define F2FS_SB1_OFF		0x400
+#define F2FS_SB1_KBOFF		(F2FS_SB1_OFF >> 10)
+#define F2FS_SB2_OFF		0x1400
+#define F2FS_SB2_KBOFF		(F2FS_SB2_OFF >> 10)
+
+struct f2fs_super_block {					/* According to version 1.1 */
+/* 0x00 */	uint32_t	magic;				/* Magic Number */
+/* 0x04 */	uint16_t	major_ver;			/* Major Version */
+/* 0x06 */	uint16_t	minor_ver;			/* Minor Version */
+/* 0x08 */	uint32_t	log_sectorsize;			/* log2 sector size in bytes */
+/* 0x0C */	uint32_t	log_sectors_per_block;		/* log2 # of sectors per block */
+/* 0x10 */	uint32_t	log_blocksize;			/* log2 block size in bytes */
+/* 0x14 */	uint32_t	log_blocks_per_seg;		/* log2 # of blocks per segment */
+/* 0x18 */	uint32_t	segs_per_sec;			/* # of segments per section */
+/* 0x1C */	uint32_t	secs_per_zone;			/* # of sections per zone */
+/* 0x20 */	uint32_t	checksum_offset;		/* checksum offset inside super block */
+/* 0x24 */	uint64_t	block_count;			/* total # of user blocks */
+/* 0x2C */	uint32_t	section_count;			/* total # of sections */
+/* 0x30 */	uint32_t	segment_count;			/* total # of segments */
+/* 0x34 */	uint32_t	segment_count_ckpt;		/* # of segments for checkpoint */
+/* 0x38 */	uint32_t	segment_count_sit;		/* # of segments for SIT */
+/* 0x3C */	uint32_t	segment_count_nat;		/* # of segments for NAT */
+/* 0x40 */	uint32_t	segment_count_ssa;		/* # of segments for SSA */
+/* 0x44 */	uint32_t	segment_count_main;		/* # of segments for main area */
+/* 0x48 */	uint32_t	segment0_blkaddr;		/* start block address of segment 0 */
+/* 0x4C */	uint32_t	cp_blkaddr;			/* start block address of checkpoint */
+/* 0x50 */	uint32_t	sit_blkaddr;			/* start block address of SIT */
+/* 0x54 */	uint32_t	nat_blkaddr;			/* start block address of NAT */
+/* 0x58 */	uint32_t	ssa_blkaddr;			/* start block address of SSA */
+/* 0x5C */	uint32_t	main_blkaddr;			/* start block address of main area */
+/* 0x60 */	uint32_t	root_ino;			/* root inode number */
+/* 0x64 */	uint32_t	node_ino;			/* node inode number */
+/* 0x68 */	uint32_t	meta_ino;			/* meta inode number */
+/* 0x6C */	uint8_t		uuid[F2FS_UUID_SIZE];		/* 128-bit uuid for volume */
+/* 0x7C */	uint16_t	volume_name[F2FS_LABEL_SIZE];	/* volume name */
+#if 0
+/* 0x47C */	uint32_t	extension_count;		/* # of extensions below */
+/* 0x480 */	uint8_t		extension_list[64][8];		/* extension array */
+#endif
+} __attribute__((packed));
+
+static int probe_f2fs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct f2fs_super_block *sb;
+	uint16_t major, minor;
+
+	sb = blkid_probe_get_sb(pr, mag, struct f2fs_super_block);
+	if (!sb)
+		return errno ? -errno : 1;
+
+	major = le16_to_cpu(sb->major_ver);
+	minor = le16_to_cpu(sb->minor_ver);
+
+	/* For version 1.0 we cannot know the correct sb structure */
+	if (major == 1 && minor == 0)
+		return 0;
+
+	if (*((unsigned char *) sb->volume_name))
+		blkid_probe_set_utf8label(pr, (unsigned char *) sb->volume_name,
+						sizeof(sb->volume_name),
+						BLKID_ENC_UTF16LE);
+
+	blkid_probe_set_uuid(pr, sb->uuid);
+	blkid_probe_sprintf_version(pr, "%u.%u", major, minor);
+	return 0;
+}
+
+const struct blkid_idinfo f2fs_idinfo =
+{
+	.name           = "f2fs",
+	.usage          = BLKID_USAGE_FILESYSTEM,
+	.probefunc      = probe_f2fs,
+	.magics         =
+        {
+		{
+			.magic = F2FS_MAGIC,
+			.len = 4,
+			.kboff = F2FS_SB1_KBOFF,
+			.sboff = F2FS_MAGIC_OFF
+		},
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/gfs.c b/libblkid/src/superblocks/gfs.c
new file mode 100644
index 0000000..1b26558
--- /dev/null
+++ b/libblkid/src/superblocks/gfs.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+/* Common gfs/gfs2 constants: */
+#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 */
+} __attribute__((packed));
+
+static int probe_gfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct gfs2_sb *sbd;
+
+	sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb);
+	if (!sbd)
+		return errno ? -errno : 1;
+
+	if (be32_to_cpu(sbd->sb_fs_format) == GFS_FORMAT_FS &&
+	    be32_to_cpu(sbd->sb_multihost_format) == GFS_FORMAT_MULTI)
+	{
+		if (*sbd->sb_locktable)
+			blkid_probe_set_label(pr,
+				(unsigned char *) sbd->sb_locktable,
+				sizeof(sbd->sb_locktable));
+
+		blkid_probe_set_uuid(pr, sbd->sb_uuid);
+		return 0;
+	}
+
+	return 1;
+}
+
+static int probe_gfs2(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct gfs2_sb *sbd;
+
+	sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb);
+	if (!sbd)
+		return errno ? -errno : 1;
+
+	if (be32_to_cpu(sbd->sb_fs_format) == GFS2_FORMAT_FS &&
+	    be32_to_cpu(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI)
+	{
+		if (*sbd->sb_locktable)
+			blkid_probe_set_label(pr,
+				(unsigned char *) sbd->sb_locktable,
+				sizeof(sbd->sb_locktable));
+		blkid_probe_set_uuid(pr, sbd->sb_uuid);
+		blkid_probe_set_version(pr, "1");
+		return 0;
+	}
+	return 1;
+}
+
+const struct blkid_idinfo gfs_idinfo =
+{
+	.name		= "gfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_gfs,
+	.minsz		= 32 * 1024 * 1024,	/* minimal size of GFS journal */
+	.magics		=
+	{
+		{ .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo gfs2_idinfo =
+{
+	.name		= "gfs2",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_gfs2,
+	.minsz		= 32 * 1024 * 1024,	/* minimal size of GFS journal */
+	.magics		=
+	{
+		{ .magic = "\x01\x16\x19\x70", .len = 4, .kboff = 64 },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/hfs.c b/libblkid/src/superblocks/hfs.c
new file mode 100644
index 0000000..fe57241
--- /dev/null
+++ b/libblkid/src/superblocks/hfs.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "superblocks.h"
+#include "md5.h"
+
+/* HFS / HFS+ */
+struct hfs_finder_info {
+        uint32_t        boot_folder;
+        uint32_t        start_app;
+        uint32_t        open_folder;
+        uint32_t        os9_folder;
+        uint32_t        reserved;
+        uint32_t        osx_folder;
+        uint8_t         id[8];
+} __attribute__((packed));
+
+struct hfs_mdb {
+        uint8_t         signature[2];
+        uint32_t        cr_date;
+        uint32_t        ls_Mod;
+        uint16_t        atrb;
+        uint16_t        nm_fls;
+        uint16_t        vbm_st;
+        uint16_t        alloc_ptr;
+        uint16_t        nm_al_blks;
+        uint32_t        al_blk_size;
+        uint32_t        clp_size;
+        uint16_t        al_bl_st;
+        uint32_t        nxt_cnid;
+        uint16_t        free_bks;
+        uint8_t         label_len;
+        uint8_t         label[27];
+        uint32_t        vol_bkup;
+        uint16_t        vol_seq_num;
+        uint32_t        wr_cnt;
+        uint32_t        xt_clump_size;
+        uint32_t        ct_clump_size;
+        uint16_t        num_root_dirs;
+        uint32_t        file_count;
+        uint32_t        dir_count;
+        struct hfs_finder_info finder_info;
+        uint8_t         embed_sig[2];
+        uint16_t        embed_startblock;
+        uint16_t        embed_blockcount;
+} __attribute__((packed));
+
+
+#define HFS_NODE_LEAF			0xff
+#define HFSPLUS_POR_CNID		1
+
+struct hfsplus_bnode_descriptor {
+	uint32_t		next;
+	uint32_t		prev;
+	uint8_t		type;
+	uint8_t		height;
+	uint16_t		num_recs;
+	uint16_t		reserved;
+} __attribute__((packed));
+
+struct hfsplus_bheader_record {
+	uint16_t		depth;
+	uint32_t		root;
+	uint32_t		leaf_count;
+	uint32_t		leaf_head;
+	uint32_t		leaf_tail;
+	uint16_t		node_size;
+} __attribute__((packed));
+
+struct hfsplus_catalog_key {
+	uint16_t	key_len;
+	uint32_t	parent_id;
+	uint16_t	unicode_len;
+	uint8_t		unicode[255 * 2];
+} __attribute__((packed));
+
+struct hfsplus_extent {
+	uint32_t		start_block;
+	uint32_t		block_count;
+} __attribute__((packed));
+
+#define HFSPLUS_EXTENT_COUNT		8
+struct hfsplus_fork {
+	uint64_t		total_size;
+	uint32_t		clump_size;
+	uint32_t		total_blocks;
+	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
+} __attribute__((packed));
+
+struct hfsplus_vol_header {
+	uint8_t		signature[2];
+	uint16_t		version;
+	uint32_t		attributes;
+	uint32_t		last_mount_vers;
+	uint32_t		reserved;
+	uint32_t		create_date;
+	uint32_t		modify_date;
+	uint32_t		backup_date;
+	uint32_t		checked_date;
+	uint32_t		file_count;
+	uint32_t		folder_count;
+	uint32_t		blocksize;
+	uint32_t		total_blocks;
+	uint32_t		free_blocks;
+	uint32_t		next_alloc;
+	uint32_t		rsrc_clump_sz;
+	uint32_t		data_clump_sz;
+	uint32_t		next_cnid;
+	uint32_t		write_count;
+	uint64_t		encodings_bmp;
+	struct hfs_finder_info finder_info;
+	struct hfsplus_fork alloc_file;
+	struct hfsplus_fork ext_file;
+	struct hfsplus_fork cat_file;
+	struct hfsplus_fork attr_file;
+	struct hfsplus_fork start_file;
+}  __attribute__((packed));
+
+#define HFSPLUS_SECTOR_SIZE        512
+
+static int hfs_set_uuid(blkid_probe pr, unsigned char const *hfs_info, size_t len)
+{
+	static unsigned char const hash_init[MD5LENGTH] = {
+		0xb3, 0xe2, 0x0f, 0x39, 0xf2, 0x92, 0x11, 0xd6,
+		0x97, 0xa4, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
+	};
+	unsigned char uuid[MD5LENGTH];
+	struct MD5Context md5c;
+
+	if (memcmp(hfs_info, "\0\0\0\0\0\0\0\0", len) == 0)
+		return -1;
+	MD5Init(&md5c);
+	MD5Update(&md5c, hash_init, MD5LENGTH);
+	MD5Update(&md5c, hfs_info, len);
+	MD5Final(uuid, &md5c);
+	uuid[6] = 0x30 | (uuid[6] & 0x0f);
+	uuid[8] = 0x80 | (uuid[8] & 0x3f);
+	return blkid_probe_set_uuid(pr, uuid);
+}
+
+static int probe_hfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct hfs_mdb	*hfs;
+
+	hfs = blkid_probe_get_sb(pr, mag, struct hfs_mdb);
+	if (!hfs)
+		return errno ? -errno : 1;
+
+	if ((memcmp(hfs->embed_sig, "H+", 2) == 0) ||
+	    (memcmp(hfs->embed_sig, "HX", 2) == 0))
+		return 1;	/* Not hfs, but an embedded HFS+ */
+
+	hfs_set_uuid(pr, hfs->finder_info.id, sizeof(hfs->finder_info.id));
+
+	blkid_probe_set_label(pr, hfs->label, hfs->label_len);
+	return 0;
+}
+
+static int probe_hfsplus(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
+	struct hfsplus_bnode_descriptor *descr;
+	struct hfsplus_bheader_record *bnode;
+	struct hfsplus_catalog_key *key;
+	struct hfsplus_vol_header *hfsplus;
+	struct hfs_mdb *sbd;
+	unsigned int alloc_block_size;
+	unsigned int alloc_first_block;
+	unsigned int embed_first_block;
+	unsigned int off = 0;
+	unsigned int blocksize;
+	unsigned int cat_block;
+	unsigned int ext_block_start;
+	unsigned int ext_block_count;
+	unsigned int record_count;
+	unsigned int leaf_node_head;
+	unsigned int leaf_node_count;
+	unsigned int leaf_node_size;
+	unsigned int leaf_block;
+	int ext;
+	uint64_t leaf_off;
+	unsigned char *buf;
+
+	sbd = blkid_probe_get_sb(pr, mag, struct hfs_mdb);
+	if (!sbd)
+		return errno ? -errno : 1;
+
+	/* Check for a HFS+ volume embedded in a HFS volume */
+	if (memcmp(sbd->signature, "BD", 2) == 0) {
+		if ((memcmp(sbd->embed_sig, "H+", 2) != 0) &&
+		    (memcmp(sbd->embed_sig, "HX", 2) != 0))
+			/* This must be an HFS volume, so fail */
+			return 1;
+
+		alloc_block_size = be32_to_cpu(sbd->al_blk_size);
+		alloc_first_block = be16_to_cpu(sbd->al_bl_st);
+		embed_first_block = be16_to_cpu(sbd->embed_startblock);
+		off = (alloc_first_block * 512) +
+			(embed_first_block * alloc_block_size);
+
+		buf = blkid_probe_get_buffer(pr,
+				off + (mag->kboff * 1024),
+				sizeof(struct hfsplus_vol_header));
+		hfsplus = (struct hfsplus_vol_header *) buf;
+
+	} else
+		hfsplus = blkid_probe_get_sb(pr, mag,
+				struct hfsplus_vol_header);
+
+	if (!hfsplus)
+		return errno ? -errno : 1;
+
+	if ((memcmp(hfsplus->signature, "H+", 2) != 0) &&
+	    (memcmp(hfsplus->signature, "HX", 2) != 0))
+		return 1;
+
+	hfs_set_uuid(pr, hfsplus->finder_info.id, sizeof(hfsplus->finder_info.id));
+
+	blocksize = be32_to_cpu(hfsplus->blocksize);
+	if (blocksize < HFSPLUS_SECTOR_SIZE)
+		return 1;
+
+	memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
+	cat_block = be32_to_cpu(extents[0].start_block);
+
+	buf = blkid_probe_get_buffer(pr,
+			off + ((blkid_loff_t) cat_block * blocksize), 0x2000);
+	if (!buf)
+		return errno ? -errno : 0;
+
+	bnode = (struct hfsplus_bheader_record *)
+		&buf[sizeof(struct hfsplus_bnode_descriptor)];
+
+	leaf_node_head = be32_to_cpu(bnode->leaf_head);
+	leaf_node_size = be16_to_cpu(bnode->node_size);
+	leaf_node_count = be32_to_cpu(bnode->leaf_count);
+	if (leaf_node_count == 0)
+		return 0;
+
+	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);
+		if (ext_block_count == 0)
+			return 0;
+
+		/* this is our extent */
+		if (leaf_block < ext_block_count)
+			break;
+
+		leaf_block -= ext_block_count;
+	}
+	if (ext == HFSPLUS_EXTENT_COUNT)
+		return 0;
+
+	leaf_off = (ext_block_start + leaf_block) * blocksize;
+
+	buf = blkid_probe_get_buffer(pr,
+				(blkid_loff_t) off + leaf_off,
+				leaf_node_size);
+	if (!buf)
+		return errno ? -errno : 0;
+
+	descr = (struct hfsplus_bnode_descriptor *) buf;
+	record_count = be16_to_cpu(descr->num_recs);
+	if (record_count == 0)
+		return 0;
+
+	if (descr->type != HFS_NODE_LEAF)
+		return 0;
+
+	key = (struct hfsplus_catalog_key *)
+		&buf[sizeof(struct hfsplus_bnode_descriptor)];
+
+	if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
+		return 0;
+
+	blkid_probe_set_utf8label(pr, key->unicode,
+			be16_to_cpu(key->unicode_len) * 2,
+			BLKID_ENC_UTF16BE);
+	return 0;
+}
+
+const struct blkid_idinfo hfs_idinfo =
+{
+	.name		= "hfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_hfs,
+	.flags		= BLKID_IDINFO_TOLERANT,
+	.magics		=
+	{
+		{ .magic = "BD", .len = 2, .kboff = 1 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo hfsplus_idinfo =
+{
+	.name		= "hfsplus",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_hfsplus,
+	.magics		=
+	{
+		{ .magic = "BD", .len = 2, .kboff = 1 },
+		{ .magic = "H+", .len = 2, .kboff = 1 },
+		{ .magic = "HX", .len = 2, .kboff = 1 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/highpoint_raid.c b/libblkid/src/superblocks/highpoint_raid.c
new file mode 100644
index 0000000..ad3b538
--- /dev/null
+++ b/libblkid/src/superblocks/highpoint_raid.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct hpt45x_metadata {
+	uint32_t	magic;
+};
+
+#define HPT45X_MAGIC_OK			0x5a7816f3
+#define HPT45X_MAGIC_BAD		0x5a7816fd
+
+static int probe_highpoint45x(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct hpt45x_metadata *hpt;
+	uint64_t off;
+	uint32_t magic;
+
+	if (pr->size < 0x10000)
+		return 1;
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+
+	off = ((pr->size / 0x200) - 11) * 0x200;
+	hpt = (struct hpt45x_metadata *)
+			blkid_probe_get_buffer(pr,
+					off,
+					sizeof(struct hpt45x_metadata));
+	if (!hpt)
+		return errno ? -errno : 1;
+	magic = le32_to_cpu(hpt->magic);
+	if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD)
+		return 1;
+	if (blkid_probe_set_magic(pr, off, sizeof(hpt->magic),
+				(unsigned char *) &hpt->magic))
+		return 1;
+	return 0;
+}
+
+static int probe_highpoint37x(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+	return 0;
+}
+
+
+const struct blkid_idinfo highpoint45x_idinfo = {
+	.name		= "hpt45x_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_highpoint45x,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+const struct blkid_idinfo highpoint37x_idinfo = {
+	.name		= "hpt37x_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_highpoint37x,
+	.magics		= {
+		/*
+		 * Superblok offset:                      4608 bytes  (9 sectors)
+		 * Magic string offset within superblock:   32 bytes
+		 *
+		 * kboff = (4608 + 32) / 1024
+		 * sboff = (4608 + 32) % kboff
+		 */
+		{ .magic = "\xf0\x16\x78\x5a", .len = 4, .kboff = 4, .sboff = 544 },
+		{ .magic = "\xfd\x16\x78\x5a", .len = 4, .kboff = 4, .sboff = 544 },
+		{ NULL }
+	}
+};
+
+
diff --git a/libblkid/src/superblocks/hpfs.c b/libblkid/src/superblocks/hpfs.c
new file mode 100644
index 0000000..0565d37
--- /dev/null
+++ b/libblkid/src/superblocks/hpfs.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.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];
+} __attribute__((packed));
+
+struct hpfs_super_block
+{
+	uint8_t		magic[4];
+	uint8_t		magic1[4];
+	uint8_t		version;
+} __attribute__((packed));
+
+struct hpfs_spare_super
+{
+	uint8_t		magic[4];
+	uint8_t		magic1[4];
+} __attribute__((packed));
+
+
+#define HPFS_SB_OFFSET			0x2000
+#define HPFS_SBSPARE_OFFSET		0x2200
+
+static int probe_hpfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct hpfs_super_block *hs;
+	struct hpfs_spare_super *hss;
+	struct hpfs_boot_block *hbb;
+	uint8_t version;
+
+	/* super block */
+	hs = blkid_probe_get_sb(pr, mag, struct hpfs_super_block);
+	if (!hs)
+		return errno ? -errno : 1;
+	version = hs->version;
+
+	/* spare super block */
+	hss = (struct hpfs_spare_super *)
+			blkid_probe_get_buffer(pr,
+				HPFS_SBSPARE_OFFSET,
+				sizeof(struct hpfs_spare_super));
+	if (!hss)
+		return errno ? -errno : 1;
+	if (memcmp(hss->magic, "\x49\x18\x91\xf9", 4) != 0)
+		return 1;
+
+	/* boot block (with UUID and LABEL) */
+	hbb = (struct hpfs_boot_block *)
+			blkid_probe_get_buffer(pr,
+				0,
+				sizeof(struct hpfs_boot_block));
+	if (!hbb)
+		return errno ? -errno : 1;
+	if (memcmp(hbb->magic, "\x55\xaa", 2) == 0 &&
+	    memcmp(hbb->sig_hpfs, "HPFS", 4) == 0 &&
+	    hbb->sig_28h == 0x28) {
+		blkid_probe_set_label(pr, hbb->vol_label, sizeof(hbb->vol_label));
+		blkid_probe_sprintf_uuid(pr,
+				hbb->vol_serno, sizeof(hbb->vol_serno),
+				"%02X%02X-%02X%02X",
+				hbb->vol_serno[3], hbb->vol_serno[2],
+				hbb->vol_serno[1], hbb->vol_serno[0]);
+	}
+	blkid_probe_sprintf_version(pr, "%u", version);
+
+	return 0;
+}
+
+const struct blkid_idinfo hpfs_idinfo =
+{
+	.name		= "hpfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_hpfs,
+	.magics		=
+	{
+		{
+		  .magic = "\x49\xe8\x95\xf9",
+		  .len = 4,
+		  .kboff = (HPFS_SB_OFFSET >> 10)
+		},
+		{ NULL }
+	}
+};
+
+
diff --git a/libblkid/src/superblocks/iso9660.c b/libblkid/src/superblocks/iso9660.c
new file mode 100644
index 0000000..d099467
--- /dev/null
+++ b/libblkid/src/superblocks/iso9660.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired also by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <ctype.h>
+
+#include "superblocks.h"
+
+struct iso9660_date {
+	unsigned char year[4];
+	unsigned char month[2];
+	unsigned char day[2];
+	unsigned char hour[2];
+	unsigned char minute[2];
+	unsigned char second[2];
+	unsigned char hundredth[2];
+	unsigned char offset;
+} __attribute__ ((packed));
+
+/* PVD - Primary volume descriptor */
+struct iso_volume_descriptor {
+	unsigned char	vd_type;
+	unsigned char	vd_id[5];
+	unsigned char	vd_version;
+	unsigned char	flags;
+	unsigned char	system_id[32];
+	unsigned char	volume_id[32];
+	unsigned char	unused[8];
+	unsigned char	space_size[8];
+	unsigned char	escape_sequences[8];
+	unsigned char  unused1[222];
+	unsigned char  publisher_id[128];
+	unsigned char  unused2[128];
+	unsigned char  application_id[128];
+	unsigned char  unused3[111];
+	struct iso9660_date created;
+	struct iso9660_date modified;
+} __attribute__((packed));
+
+/* Boot Record */
+struct boot_record {
+	unsigned char	vd_type;
+	unsigned char	vd_id[5];
+	unsigned char	vd_version;
+	unsigned char	boot_system_id[32];
+	unsigned char	boot_id[32];
+	unsigned char	unused[1];
+} __attribute__((packed));
+
+#define ISO_SUPERBLOCK_OFFSET		0x8000
+#define ISO_SECTOR_SIZE			0x800
+#define ISO_VD_OFFSET			(ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
+#define ISO_VD_BOOT_RECORD		0x0
+#define ISO_VD_SUPPLEMENTARY		0x2
+#define ISO_VD_END			0xff
+#define ISO_VD_MAX			16
+
+struct high_sierra_volume_descriptor {
+	unsigned char	foo[8];
+	unsigned char	type;
+	unsigned char	id[5];
+	unsigned char	version;
+	unsigned char	unused1;
+	unsigned char	system_id[32];
+	unsigned char   volume_id[32];
+} __attribute__((packed));
+
+/* returns 1 if the begin of @ascii is equal to @utf16 string.
+ */
+static int ascii_eq_utf16be(unsigned char *ascii,
+			unsigned char *utf16, size_t len)
+{
+	size_t a, u;
+
+	for (a = 0, u = 0; u < len; a++, u += 2) {
+		if (utf16[u] != 0x0 || ascii[a] != utf16[u + 1])
+			return 0;
+	}
+	return 1;
+}
+
+/* old High Sierra format */
+static int probe_iso9660_hsfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct high_sierra_volume_descriptor *iso;
+
+	iso = blkid_probe_get_sb(pr, mag, struct high_sierra_volume_descriptor);
+	if (!iso)
+		return errno ? -errno : 1;
+
+	blkid_probe_set_version(pr, "High Sierra");
+	blkid_probe_set_label(pr, iso->volume_id, sizeof(iso->volume_id));
+	return 0;
+}
+
+static int probe_iso9660_set_uuid (blkid_probe pr, const struct iso9660_date *date)
+{
+	unsigned char buffer[16];
+	unsigned int i, zeros = 0;
+
+	buffer[0] = date->year[0];
+	buffer[1] = date->year[1];
+	buffer[2] = date->year[2];
+	buffer[3] = date->year[3];
+	buffer[4] = date->month[0];
+	buffer[5] = date->month[1];
+	buffer[6] = date->day[0];
+	buffer[7] = date->day[1];
+	buffer[8] = date->hour[0];
+	buffer[9] = date->hour[1];
+	buffer[10] = date->minute[0];
+	buffer[11] = date->minute[1];
+	buffer[12] = date->second[0];
+	buffer[13] = date->second[1];
+	buffer[14] = date->hundredth[0];
+	buffer[15] = date->hundredth[1];
+
+	/* count the number of zeros ('0') in the date buffer */
+	for (i = 0, zeros = 0; i < sizeof(buffer); i++)
+		if (buffer[i] == '0')
+			zeros++;
+
+	/* due to the iso9660 standard if all date fields are '0' and offset is 0, the date is unset */
+	if (zeros == sizeof(buffer) && date->offset == 0)
+		return 0;
+
+	/* generate an UUID using this date and return success */
+	blkid_probe_sprintf_uuid (pr, buffer, sizeof(buffer),
+		"%c%c%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c",
+		buffer[0], buffer[1], buffer[2], buffer[3],
+		buffer[4], buffer[5],
+		buffer[6], buffer[7],
+		buffer[8], buffer[9],
+		buffer[10], buffer[11],
+		buffer[12], buffer[13],
+		buffer[14], buffer[15]);
+
+	return 1;
+}
+
+static int is_str_empty(const unsigned char *str, size_t len)
+{
+	size_t i;
+
+	if (!str || !*str)
+		return 1;
+
+	for (i = 0; i < len; i++)
+		if (!isspace(str[i]))
+			return 0;
+	return 1;
+}
+
+/* iso9660 [+ Microsoft Joliet Extension] */
+int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct iso_volume_descriptor *iso;
+	unsigned char label[32];
+	int i;
+	int off;
+
+	if (strcmp(mag->magic, "CDROM") == 0)
+		return probe_iso9660_hsfs(pr, mag);
+
+	iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor);
+	if (!iso)
+		return errno ? -errno : 1;
+
+	memcpy(label, iso->volume_id, sizeof(label));
+
+	if (!is_str_empty(iso->system_id, sizeof(iso->system_id)))
+		blkid_probe_set_id_label(pr, "SYSTEM_ID",
+				iso->system_id, sizeof(iso->system_id));
+
+	if (!is_str_empty(iso->publisher_id, sizeof(iso->publisher_id)))
+		blkid_probe_set_id_label(pr, "PUBLISHER_ID",
+				iso->publisher_id, sizeof(iso->publisher_id));
+
+	if (!is_str_empty(iso->application_id, sizeof(iso->application_id)))
+		blkid_probe_set_id_label(pr, "APPLICATION_ID",
+				iso->application_id, sizeof(iso->application_id));
+
+	/* create an UUID using the modified/created date */
+	if (! probe_iso9660_set_uuid(pr, &iso->modified))
+		probe_iso9660_set_uuid(pr, &iso->created);
+
+	/* Joliet Extension and Boot Record */
+	off = ISO_VD_OFFSET;
+	for (i = 0; i < ISO_VD_MAX; i++) {
+		struct boot_record *boot= (struct boot_record *)
+			blkid_probe_get_buffer(pr,
+					off,
+					max(sizeof(struct boot_record),
+					    sizeof(struct iso_volume_descriptor)));
+
+		if (boot == NULL || boot->vd_type == ISO_VD_END)
+			break;
+
+		if (boot->vd_type == ISO_VD_BOOT_RECORD) {
+			if (!is_str_empty(boot->boot_system_id,
+					  sizeof(boot->boot_system_id)))
+				blkid_probe_set_id_label(pr, "BOOT_SYSTEM_ID",
+							boot->boot_system_id,
+							sizeof(boot->boot_system_id));
+			off += ISO_SECTOR_SIZE;
+			continue;
+		}
+
+		/* Not a Boot record, lets see if its supplemntary volume descriptor */
+		iso = (struct iso_volume_descriptor *) boot;
+
+		if (iso->vd_type != ISO_VD_SUPPLEMENTARY) {
+			off += ISO_SECTOR_SIZE;
+			continue;
+		}
+
+		if (memcmp(iso->escape_sequences, "%/@", 3) == 0 ||
+		    memcmp(iso->escape_sequences, "%/C", 3) == 0 ||
+		    memcmp(iso->escape_sequences, "%/E", 3) == 0) {
+
+			blkid_probe_set_version(pr, "Joliet Extension");
+
+			/* Is the Joliet (UTF16BE) label equal to the label in
+			 * the PVD? If yes, use PVD label.  The Jolied version
+			 * of the label could be trimed (because UTF16..).
+			 */
+			if (ascii_eq_utf16be(label, iso->volume_id, 32))
+				break;
+
+			blkid_probe_set_utf8label(pr,
+					iso->volume_id,
+					sizeof(iso->volume_id),
+					BLKID_ENC_UTF16BE);
+			goto has_label;
+		}
+		off += ISO_SECTOR_SIZE;
+	}
+
+	/* Joliet not found, let use standard iso label */
+	blkid_probe_set_label(pr, label, sizeof(label));
+
+has_label:
+	return 0;
+}
+
+const struct blkid_idinfo iso9660_idinfo =
+{
+	.name		= "iso9660",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_iso9660,
+	.flags		= BLKID_IDINFO_TOLERANT,
+	.magics		=
+	{
+		{ .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 },
+		{ .magic = "CDROM", .len = 5, .kboff = 32, .sboff = 9 },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/iso9660.h b/libblkid/src/superblocks/iso9660.h
new file mode 100644
index 0000000..a8d729d
--- /dev/null
+++ b/libblkid/src/superblocks/iso9660.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2013 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef _BLKID_ISO9660_H
+#define _BLKID_ISO9660_H
+
+#include "blkidP.h"
+
+extern int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag);
+
+#endif /* _BLKID_ISO9660_H */
diff --git a/libblkid/src/superblocks/isw_raid.c b/libblkid/src/superblocks/isw_raid.c
new file mode 100644
index 0000000..065c2b2
--- /dev/null
+++ b/libblkid/src/superblocks/isw_raid.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct isw_metadata {
+	uint8_t		sig[32];
+	uint32_t	check_sum;
+	uint32_t	mpb_size;
+	uint32_t	family_num;
+	uint32_t	generation_num;
+};
+
+#define ISW_SIGNATURE		"Intel Raid ISM Cfg Sig. "
+
+
+static int probe_iswraid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	uint64_t off;
+	struct isw_metadata *isw;
+
+	if (pr->size < 0x10000)
+		return 1;
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+
+	off = ((pr->size / 0x200) - 2) * 0x200;
+	isw = (struct isw_metadata *)
+			blkid_probe_get_buffer(pr,
+					off,
+					sizeof(struct isw_metadata));
+	if (!isw)
+		return errno ? -errno : 1;
+
+	if (memcmp(isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0)
+		return 1;
+	if (blkid_probe_sprintf_version(pr, "%6s",
+			&isw->sig[sizeof(ISW_SIGNATURE)-1]) != 0)
+		return 1;
+	if (blkid_probe_set_magic(pr, off, sizeof(isw->sig),
+				(unsigned char *) isw->sig))
+		return 1;
+	return 0;
+}
+
+const struct blkid_idinfo iswraid_idinfo = {
+	.name		= "isw_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_iswraid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/jfs.c b/libblkid/src/superblocks/jfs.c
new file mode 100644
index 0000000..ac684d8
--- /dev/null
+++ b/libblkid/src/superblocks/jfs.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct jfs_super_block {
+	unsigned char	js_magic[4];
+	uint32_t	js_version;
+	uint64_t	js_size;
+	uint32_t	js_bsize;	/* 4: aggregate block size in bytes */
+	uint16_t	js_l2bsize;	/* 2: log2 of s_bsize */
+	uint16_t	js_l2bfactor;	/* 2: log2(s_bsize/hardware block size) */
+	uint32_t	js_pbsize;	/* 4: hardware/LVM block size in bytes */
+	uint16_t	js_l2pbsize;	/* 2: log2 of s_pbsize */
+	uint16_t	js_pad;		/* 2: padding necessary for alignment */
+	uint32_t	js_dummy2[26];
+	unsigned char	js_uuid[16];
+	unsigned char	js_label[16];
+	unsigned char	js_loguuid[16];
+};
+
+static int probe_jfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct jfs_super_block *js;
+
+	js = blkid_probe_get_sb(pr, mag, struct jfs_super_block);
+	if (!js)
+		return errno ? -errno : 1;
+	if (le32_to_cpu(js->js_bsize) != (1U << le16_to_cpu(js->js_l2bsize)))
+		return 1;
+	if (le32_to_cpu(js->js_pbsize) != (1U << le16_to_cpu(js->js_l2pbsize)))
+		return 1;
+	if ((le16_to_cpu(js->js_l2bsize) - le16_to_cpu(js->js_l2pbsize)) !=
+	    le16_to_cpu(js->js_l2bfactor))
+		return 1;
+
+	if (strlen((char *) js->js_label))
+		blkid_probe_set_label(pr, js->js_label, sizeof(js->js_label));
+	blkid_probe_set_uuid(pr, js->js_uuid);
+	return 0;
+}
+
+
+const struct blkid_idinfo jfs_idinfo =
+{
+	.name		= "jfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_jfs,
+	.minsz		= 16 * 1024 * 1024,
+	.magics		=
+	{
+		{ .magic = "JFS1", .len = 4, .kboff = 32 },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/jmicron_raid.c b/libblkid/src/superblocks/jmicron_raid.c
new file mode 100644
index 0000000..ca79867
--- /dev/null
+++ b/libblkid/src/superblocks/jmicron_raid.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct jm_metadata {
+	int8_t		signature[2];
+	uint8_t		minor_version;
+	uint8_t		major_version;
+	uint16_t	checksum;
+};
+
+#define JM_SIGNATURE		"JM"
+
+static int probe_jmraid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	uint64_t off;
+	struct jm_metadata *jm;
+
+	if (pr->size < 0x10000)
+		return 1;
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+
+	off = ((pr->size / 0x200) - 1) * 0x200;
+	jm = (struct jm_metadata *)
+		blkid_probe_get_buffer(pr,
+				off,
+				sizeof(struct jm_metadata));
+	if (!jm)
+		return errno ? -errno : 1;
+
+	if (memcmp(jm->signature, JM_SIGNATURE, sizeof(JM_SIGNATURE) - 1) != 0)
+		return 1;
+	if (blkid_probe_sprintf_version(pr, "%u.%u",
+				jm->major_version, jm->minor_version) != 0)
+		return 1;
+	if (blkid_probe_set_magic(pr, off, sizeof(jm->signature),
+				(unsigned char *) jm->signature))
+		return 1;
+	return 0;
+}
+
+const struct blkid_idinfo jmraid_idinfo = {
+	.name		= "jmicron_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_jmraid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/linux_raid.c b/libblkid/src/superblocks/linux_raid.c
new file mode 100644
index 0000000..cf29141
--- /dev/null
+++ b/libblkid/src/superblocks/linux_raid.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.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;
+};
+
+/*
+ * Version-1, little-endian.
+ */
+struct mdp1_super_block {
+	/* constant array information - 128 bytes */
+	uint32_t	magic;		/* MD_SB_MAGIC: 0xa92b4efc - little endian */
+	uint32_t	major_version;	/* 1 */
+	uint32_t	feature_map;	/* 0 for now */
+	uint32_t	pad0;		/* always set to 0 when writing */
+
+	uint8_t		set_uuid[16];	/* user-space generated. */
+	unsigned char	set_name[32];	/* set and interpreted by user-space */
+
+	uint64_t	ctime;		/* lo 40 bits are seconds, top 24 are microseconds or 0*/
+	uint32_t	level;		/* -4 (multipath), -1 (linear), 0,1,4,5 */
+	uint32_t	layout;		/* only for raid5 currently */
+	uint64_t	size;		/* used size of component devices, in 512byte sectors */
+
+	uint32_t	chunksize;	/* in 512byte sectors */
+	uint32_t	raid_disks;
+	uint32_t	bitmap_offset;	/* sectors after start of superblock that bitmap starts
+					 * NOTE: signed, so bitmap can be before superblock
+					 * only meaningful of feature_map[0] is set.
+					 */
+
+	/* These are only valid with feature bit '4' */
+	uint32_t	new_level;	/* new level we are reshaping to		*/
+	uint64_t	reshape_position;	/* next address in array-space for reshape */
+	uint32_t	delta_disks;	/* change in number of raid_disks		*/
+	uint32_t	new_layout;	/* new layout					*/
+	uint32_t	new_chunk;	/* new chunk size (bytes)			*/
+	uint8_t		pad1[128-124];	/* set to 0 when written */
+
+	/* constant this-device information - 64 bytes */
+	uint64_t	data_offset;	/* sector start of data, often 0 */
+	uint64_t	data_size;	/* sectors in this device that can be used for data */
+	uint64_t	super_offset;	/* sector start of this superblock */
+	uint64_t	recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
+	uint32_t	dev_number;	/* permanent identifier of this  device - not role in raid */
+	uint32_t	cnt_corrected_read; /* number of read errors that were corrected by re-writing */
+	uint8_t		device_uuid[16]; /* user-space setable, ignored by kernel */
+        uint8_t		devflags;        /* per-device flags.  Only one defined...*/
+	uint8_t		pad2[64-57];	/* set to 0 when writing */
+
+	/* array state information - 64 bytes */
+	uint64_t	utime;		/* 40 bits second, 24 btes microseconds */
+	uint64_t	events;		/* incremented when superblock updated */
+	uint64_t	resync_offset;	/* data before this offset (from data_offset) known to be in sync */
+	uint32_t	sb_csum;	/* checksum up to dev_roles[max_dev] */
+	uint32_t	max_dev;	/* size of dev_roles[] array to consider */
+	uint8_t		pad3[64-32];	/* set to 0 when writing */
+
+	/* device state information. Indexed by dev_number.
+	 * 2 bytes per device
+	 * Note there are no per-device state flags. State information is rolled
+	 * into the 'roles' value.  If a device is spare or faulty, then it doesn't
+	 * have a meaningful role.
+	 */
+	uint16_t	dev_roles[0];	/* role in array, or 0xffff for a spare, or 0xfffe for faulty */
+};
+
+
+#define MD_RESERVED_BYTES		0x10000
+#define MD_SB_MAGIC			0xa92b4efc
+
+static int probe_raid0(blkid_probe pr, blkid_loff_t off)
+{
+	struct mdp0_super_block *mdp0;
+	union {
+		uint32_t ints[4];
+		uint8_t bytes[16];
+	} uuid;
+	uint32_t ma, mi, pa;
+	uint64_t size;
+
+	if (pr->size < MD_RESERVED_BYTES)
+		return 1;
+	mdp0 = (struct mdp0_super_block *)
+			blkid_probe_get_buffer(pr,
+				off,
+				sizeof(struct mdp0_super_block));
+	if (!mdp0)
+		return errno ? -errno : 1;
+
+	memset(uuid.ints, 0, sizeof(uuid.ints));
+
+	if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
+		uuid.ints[0] = swab32(mdp0->set_uuid0);
+		if (le32_to_cpu(mdp0->minor_version) >= 90) {
+			uuid.ints[1] = swab32(mdp0->set_uuid1);
+			uuid.ints[2] = swab32(mdp0->set_uuid2);
+			uuid.ints[3] = swab32(mdp0->set_uuid3);
+		}
+		ma = le32_to_cpu(mdp0->major_version);
+		mi = le32_to_cpu(mdp0->minor_version);
+		pa = le32_to_cpu(mdp0->patch_version);
+		size = le32_to_cpu(mdp0->size);
+
+	} 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;
+		}
+		ma = be32_to_cpu(mdp0->major_version);
+		mi = be32_to_cpu(mdp0->minor_version);
+		pa = be32_to_cpu(mdp0->patch_version);
+		size = be32_to_cpu(mdp0->size);
+	} else
+		return 1;
+
+	size <<= 10;	/* convert KiB to bytes */
+
+	if (pr->size < 0 || (uint64_t) pr->size < size + MD_RESERVED_BYTES)
+		/* device is too small */
+		return 1;
+
+	if (off < 0 || (uint64_t) off < size)
+		/* no space before superblock */
+		return 1;
+
+	/*
+	 * Check for collisions between RAID and partition table
+	 *
+	 * For example the superblock is at the end of the last partition, it's
+	 * the same position as at the end of the disk...
+	 */
+	if ((S_ISREG(pr->mode) || blkid_probe_is_wholedisk(pr)) &&
+	    blkid_probe_is_covered_by_pt(pr,
+			off - size,				/* min. start  */
+			size + MD_RESERVED_BYTES)) {		/* min. length */
+
+		/* ignore this superblock, it's within any partition and
+		 * we are working with whole-disk now */
+		return 1;
+	}
+
+	if (blkid_probe_sprintf_version(pr, "%u.%u.%u", ma, mi, pa) != 0)
+		return 1;
+	if (blkid_probe_set_uuid(pr, (unsigned char *) uuid.bytes) != 0)
+		return 1;
+	if (blkid_probe_set_magic(pr, off, sizeof(mdp0->md_magic),
+				(unsigned char *) &mdp0->md_magic))
+		return 1;
+	return 0;
+}
+
+static int probe_raid1(blkid_probe pr, off_t off)
+{
+	struct mdp1_super_block *mdp1;
+
+	mdp1 = (struct mdp1_super_block *)
+			blkid_probe_get_buffer(pr,
+				off,
+				sizeof(struct mdp1_super_block));
+	if (!mdp1)
+		return errno ? -errno : 1;
+	if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC)
+		return 1;
+	if (le32_to_cpu(mdp1->major_version) != 1U)
+		return 1;
+	if (le64_to_cpu(mdp1->super_offset) != (uint64_t) off >> 9)
+		return 1;
+	if (blkid_probe_set_uuid(pr, (unsigned char *) mdp1->set_uuid) != 0)
+		return 1;
+	if (blkid_probe_set_uuid_as(pr,
+			(unsigned char *) mdp1->device_uuid, "UUID_SUB") != 0)
+		return 1;
+	if (blkid_probe_set_label(pr, mdp1->set_name,
+				sizeof(mdp1->set_name)) != 0)
+		return 1;
+	if (blkid_probe_set_magic(pr, off, sizeof(mdp1->magic),
+				(unsigned char *) &mdp1->magic))
+		return 1;
+	return 0;
+}
+
+int probe_raid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	const char *ver = NULL;
+	int ret = BLKID_PROBE_NONE;
+
+	if (pr->size > MD_RESERVED_BYTES) {
+		/* version 0 at the end of the device */
+		uint64_t sboff = (pr->size & ~(MD_RESERVED_BYTES - 1))
+			- MD_RESERVED_BYTES;
+		ret = probe_raid0(pr, sboff);
+		if (ret < 1)
+			return ret;	/* error */
+
+		/* version 1.0 at the end of the device */
+		sboff = (pr->size & ~(0x1000 - 1)) - 0x2000;
+		ret = probe_raid1(pr, sboff);
+		if (ret < 0)
+			return ret;	/* error */
+		if (ret == 0)
+			ver = "1.0";
+	}
+
+	if (!ver) {
+		/* version 1.1 at the start of the device */
+		ret = probe_raid1(pr, 0);
+		if (ret == 0)
+			ver = "1.1";
+
+		/* version 1.2 at 4k offset from the start */
+		else if (ret == BLKID_PROBE_NONE) {
+			ret = probe_raid1(pr, 0x1000);
+			if (ret == 0)
+				ver = "1.2";
+		}
+	}
+
+	if (ver) {
+		blkid_probe_set_version(pr, ver);
+		return BLKID_PROBE_OK;
+	}
+	return ret;
+}
+
+
+const struct blkid_idinfo linuxraid_idinfo = {
+	.name		= "linux_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_raid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/lsi_raid.c b/libblkid/src/superblocks/lsi_raid.c
new file mode 100644
index 0000000..697b0fe
--- /dev/null
+++ b/libblkid/src/superblocks/lsi_raid.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct lsi_metadata {
+	uint8_t		sig[6];
+};
+
+
+#define LSI_SIGNATURE		"$XIDE$"
+
+static int probe_lsiraid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	uint64_t off;
+	struct lsi_metadata *lsi;
+
+	if (pr->size < 0x10000)
+		return 1;
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+
+	off = ((pr->size / 0x200) - 1) * 0x200;
+	lsi = (struct lsi_metadata *)
+		blkid_probe_get_buffer(pr,
+				off,
+				sizeof(struct lsi_metadata));
+	if (!lsi)
+		return errno ? -errno : 1;
+
+	if (memcmp(lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0)
+		return 1;
+	if (blkid_probe_set_magic(pr, off, sizeof(lsi->sig),
+				(unsigned char *) lsi->sig))
+		return 1;
+	return 0;
+}
+
+const struct blkid_idinfo lsiraid_idinfo = {
+	.name		= "lsi_mega_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_lsiraid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/luks.c b/libblkid/src/superblocks/luks.c
new file mode 100644
index 0000000..00696f2
--- /dev/null
+++ b/libblkid/src/superblocks/luks.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+#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_MAGIC_L			6
+#define UUID_STRING_L			40
+
+struct luks_phdr {
+	uint8_t		magic[LUKS_MAGIC_L];
+	uint16_t	version;
+	uint8_t		cipherName[LUKS_CIPHERNAME_L];
+	uint8_t		cipherMode[LUKS_CIPHERMODE_L];
+	uint8_t		hashSpec[LUKS_HASHSPEC_L];
+	uint32_t	payloadOffset;
+	uint32_t	keyBytes;
+	uint8_t		mkDigest[LUKS_DIGESTSIZE];
+	uint8_t		mkDigestSalt[LUKS_SALTSIZE];
+	uint32_t	mkDigestIterations;
+	uint8_t		uuid[UUID_STRING_L];
+} __attribute__((packed));
+
+static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct luks_phdr *header;
+
+	header = blkid_probe_get_sb(pr, mag, struct luks_phdr);
+	if (header == NULL)
+		return errno ? -errno : 1;
+
+	blkid_probe_strncpy_uuid(pr, (unsigned char *) header->uuid,
+			sizeof(header->uuid));
+	blkid_probe_sprintf_version(pr, "%u", be16_to_cpu(header->version));
+	return 0;
+}
+
+const struct blkid_idinfo luks_idinfo =
+{
+	.name		= "crypto_LUKS",
+	.usage		= BLKID_USAGE_CRYPTO,
+	.probefunc	= probe_luks,
+	.magics		=
+	{
+		{ .magic = "LUKS\xba\xbe", .len = 6 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/lvm.c b/libblkid/src/superblocks/lvm.c
new file mode 100644
index 0000000..3c6df74
--- /dev/null
+++ b/libblkid/src/superblocks/lvm.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ * Copyright (C) 2012 Milan Broz <mbroz@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+#define LVM1_ID_LEN 128
+#define LVM2_ID_LEN 32
+
+struct lvm2_pv_label_header {
+	/* label_header */
+	uint8_t		id[8];		/* LABELONE */
+	uint64_t	sector_xl;	/* Sector number of this label */
+	uint32_t	crc_xl;		/* From next field to end of sector */
+	uint32_t	offset_xl;	/* Offset from start of struct to contents */
+	uint8_t		type[8];	/* LVM2 001 */
+	/* pv_header */
+	uint8_t		pv_uuid[LVM2_ID_LEN];
+} __attribute__ ((packed));
+
+struct lvm1_pv_label_header {
+	uint8_t id[2];			/* HM */
+	uint16_t version;		/* version 1 or 2 */
+	uint32_t _notused[10];		/* lvm1 internals */
+	uint8_t pv_uuid[LVM1_ID_LEN];
+} __attribute__ ((packed));
+
+#define LVM2_LABEL_SIZE 512
+static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
+{
+	static const unsigned int crctab[] = {
+		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+	};
+	unsigned int i, crc = 0xf597a6cf;
+	const uint8_t *data = (const uint8_t *) buf;
+
+	for (i = 0; i < size; i++) {
+		crc ^= *data++;
+		crc = (crc >> 4) ^ crctab[crc & 0xf];
+		crc = (crc >> 4) ^ crctab[crc & 0xf];
+	}
+	return crc;
+}
+
+/* Length of real UUID is always LVM2_ID_LEN */
+static void format_lvm_uuid(char *dst_uuid, char *src_uuid)
+{
+	unsigned int i, b;
+
+	for (i = 0, b = 1; i < LVM2_ID_LEN; i++, b <<= 1) {
+		if (b & 0x4444440)
+			*dst_uuid++ = '-';
+		*dst_uuid++ = *src_uuid++;
+	}
+	*dst_uuid = '\0';
+}
+
+static int probe_lvm2(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	int sector = mag->kboff << 1;
+	struct lvm2_pv_label_header *label;
+	char uuid[LVM2_ID_LEN + 7];
+	unsigned char *buf;
+
+	buf = blkid_probe_get_buffer(pr,
+			mag->kboff << 10,
+			512 + sizeof(struct lvm2_pv_label_header));
+	if (!buf)
+		return errno ? -errno : 1;
+
+	/* buf is at 0k or 1k offset; find label inside */
+	if (memcmp(buf, "LABELONE", 8) == 0) {
+		label = (struct lvm2_pv_label_header *) buf;
+	} else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
+		label = (struct lvm2_pv_label_header *)(buf + 512);
+		sector++;
+	} else {
+		return 1;
+	}
+
+	if (le64_to_cpu(label->sector_xl) != (unsigned) sector)
+		return 1;
+
+	if (!blkid_probe_verify_csum(
+		pr, lvm2_calc_crc(
+			&label->offset_xl, LVM2_LABEL_SIZE -
+			((char *) &label->offset_xl - (char *) label)),
+			le32_to_cpu(label->crc_xl)))
+		return 1;
+
+	format_lvm_uuid(uuid, (char *) label->pv_uuid);
+	blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
+			"%s", uuid);
+
+	/* the mag->magic is the same string as label->type,
+	 * but zero terminated */
+	blkid_probe_set_version(pr, mag->magic);
+
+	/* LVM (pvcreate) wipes begin of the device -- let's remember this
+	 * to resolve conflicts bettween LVM and partition tables, ...
+	 */
+	blkid_probe_set_wiper(pr, 0, 8 * 1024);
+
+	return 0;
+}
+
+static int probe_lvm1(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct lvm1_pv_label_header *label;
+	char uuid[LVM2_ID_LEN + 7];
+	unsigned int version;
+
+	label = blkid_probe_get_sb(pr, mag, struct lvm1_pv_label_header);
+	if (!label)
+		return errno ? -errno : 1;
+
+	version = le16_to_cpu(label->version);
+	if (version != 1 && version != 2)
+		return 1;
+
+	format_lvm_uuid(uuid, (char *) label->pv_uuid);
+	blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
+			"%s", uuid);
+
+	return 0;
+}
+
+struct verity_sb {
+	uint8_t  signature[8];	/* "verity\0\0" */
+	uint32_t version;	/* superblock version */
+	uint32_t hash_type;	/* 0 - Chrome OS, 1 - normal */
+	uint8_t  uuid[16];	/* UUID of hash device */
+	uint8_t  algorithm[32];/* hash algorithm name */
+	uint32_t data_block_size; /* data block in bytes */
+	uint32_t hash_block_size; /* hash block in bytes */
+	uint64_t data_blocks;	/* number of data blocks */
+	uint16_t salt_size;	/* salt size */
+	uint8_t  _pad1[6];
+	uint8_t  salt[256];	/* salt */
+	uint8_t  _pad2[168];
+} __attribute__((packed));
+
+static int probe_verity(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct verity_sb *sb;
+	unsigned int version;
+
+	sb = blkid_probe_get_sb(pr, mag, struct verity_sb);
+	if (sb == NULL)
+		return errno ? -errno : 1;
+
+	version = le32_to_cpu(sb->version);
+	if (version != 1)
+		return 1;
+
+	blkid_probe_set_uuid(pr, sb->uuid);
+	blkid_probe_sprintf_version(pr, "%u", version);
+	return 0;
+}
+
+/* NOTE: the original libblkid uses "lvm2pv" as a name */
+const struct blkid_idinfo lvm2_idinfo =
+{
+	.name		= "LVM2_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_lvm2,
+	.magics		=
+	{
+		{ .magic = "LVM2 001", .len = 8, .sboff = 0x218 },
+		{ .magic = "LVM2 001", .len = 8, .sboff = 0x018 },
+		{ .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x018 },
+		{ .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x218 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo lvm1_idinfo =
+{
+	.name		= "LVM1_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_lvm1,
+	.magics		=
+	{
+		{ .magic = "HM", .len = 2 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo snapcow_idinfo =
+{
+	.name		= "DM_snapshot_cow",
+	.usage		= BLKID_USAGE_OTHER,
+	.magics		=
+	{
+		{ .magic = "SnAp", .len = 4 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo verity_hash_idinfo =
+{
+	.name		= "DM_verity_hash",
+	.usage		= BLKID_USAGE_CRYPTO,
+	.probefunc	= probe_verity,
+	.magics		=
+	{
+		{ .magic = "verity\0\0", .len = 8 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/minix.c b/libblkid/src/superblocks/minix.c
new file mode 100644
index 0000000..9ea49fe
--- /dev/null
+++ b/libblkid/src/superblocks/minix.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008-2013 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <string.h>
+#include "superblocks.h"
+#include "minix.h"
+
+#define minix_swab16(doit, num)	((uint16_t) (doit ? swab16(num) : num))
+#define minix_swab32(doit, num)	((uint32_t) (doit ? swab32(num) : num))
+
+static int get_minix_version(const unsigned char *data, int *other_endian)
+{
+	struct minix_super_block *sb = (struct minix_super_block *) data;
+	struct minix3_super_block *sb3 = (struct minix3_super_block *) data;
+	int version = 0;
+
+	*other_endian = 0;
+
+	switch (sb->s_magic) {
+	case MINIX_SUPER_MAGIC:
+	case MINIX_SUPER_MAGIC2:
+		version = 1;
+		break;
+	case MINIX2_SUPER_MAGIC:
+	case MINIX2_SUPER_MAGIC2:
+		version = 2;
+		break;
+	default:
+		if (sb3->s_magic == MINIX3_SUPER_MAGIC)
+			version = 3;
+		break;
+	}
+
+	if (!version) {
+		*other_endian = 1;
+
+		switch (swab16(sb->s_magic)) {
+		case MINIX_SUPER_MAGIC:
+		case MINIX_SUPER_MAGIC2:
+			version = 1;
+			break;
+		case MINIX2_SUPER_MAGIC:
+		case MINIX2_SUPER_MAGIC2:
+			version = 2;
+			break;
+		default:
+			if (sb3->s_magic == MINIX3_SUPER_MAGIC)
+				version = 3;
+			break;
+		}
+	}
+	if (!version)
+		return -1;
+
+	DBG(LOWPROBE, ul_debug("minix version %d detected [%s]", version,
+#if defined(WORDS_BIGENDIAN)
+	*other_endian ? "LE" : "BE"
+#else
+	*other_endian ? "BE" : "LE"
+#endif
+	));
+	return version;
+}
+
+static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	unsigned char *ext;
+	const unsigned char *data;
+	int version = 0, swabme = 0;
+
+	data = blkid_probe_get_buffer(pr, 1024,
+			max(sizeof(struct minix_super_block),
+			    sizeof(struct minix3_super_block)));
+	if (!data)
+		return errno ? -errno : 1;
+	version = get_minix_version(data, &swabme);
+	if (version < 1)
+		return 1;
+
+	if (version <= 2) {
+		struct minix_super_block *sb = (struct minix_super_block *) data;
+		int zones, ninodes, imaps, zmaps, firstz;
+
+		if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
+			return 1;
+
+		zones = version == 2 ? minix_swab32(swabme, sb->s_zones) :
+				       minix_swab16(swabme, sb->s_nzones);
+		ninodes = minix_swab16(swabme, sb->s_ninodes);
+		imaps   = minix_swab16(swabme, sb->s_imap_blocks);
+		zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
+		firstz  = minix_swab16(swabme, sb->s_firstdatazone);
+
+		/* sanity checks to be sure that the FS is really minix */
+		if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1)
+			return 1;
+		if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1)
+			return 1;
+
+	} else if (version == 3) {
+		struct minix3_super_block *sb = (struct minix3_super_block *) data;
+
+		if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
+			return 1;
+	}
+
+	/* unfortunately, some parts of ext3 is sometimes possible to
+	 * interpreted as minix superblock. So check for extN magic
+	 * string. (For extN magic string and offsets see ext.c.)
+	 */
+	ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2);
+	if (!ext)
+		return errno ? -errno : 1;
+	else if (memcmp(ext, "\123\357", 2) == 0)
+		return 1;
+
+	blkid_probe_sprintf_version(pr, "%d", version);
+	return 0;
+}
+
+const struct blkid_idinfo minix_idinfo =
+{
+	.name		= "minix",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_minix,
+	.magics		=
+	{
+		/* version 1 - LE */
+		{ .magic = "\177\023", .len = 2, .kboff = 1, .sboff = 0x10 },
+		{ .magic = "\217\023", .len = 2, .kboff = 1, .sboff = 0x10 },
+
+		/* version 1 - BE */
+		{ .magic = "\023\177", .len = 2, .kboff = 1, .sboff = 0x10 },
+		{ .magic = "\023\217", .len = 2, .kboff = 1, .sboff = 0x10 },
+
+		/* version 2 - LE */
+		{ .magic = "\150\044", .len = 2, .kboff = 1, .sboff = 0x10 },
+		{ .magic = "\170\044", .len = 2, .kboff = 1, .sboff = 0x10 },
+
+		/* version 2 - BE */
+		{ .magic = "\044\150", .len = 2, .kboff = 1, .sboff = 0x10 },
+		{ .magic = "\044\170", .len = 2, .kboff = 1, .sboff = 0x10 },
+
+		/* version 3 - LE */
+		{ .magic = "\132\115", .len = 2, .kboff = 1, .sboff = 0x18 },
+
+		/* version 3 - BE */
+		{ .magic = "\115\132", .len = 2, .kboff = 1, .sboff = 0x18 },
+
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/netware.c b/libblkid/src/superblocks/netware.c
new file mode 100644
index 0000000..af81cf5
--- /dev/null
+++ b/libblkid/src/superblocks/netware.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+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)];
+} __attribute__((__packed__));
+
+static int probe_netware(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct netware_super_block *nw;
+
+	nw = blkid_probe_get_sb(pr, mag, struct netware_super_block);
+	if (!nw)
+		return errno ? -errno : 1;
+
+	blkid_probe_set_uuid(pr, nw->SBH_PoolID);
+
+	blkid_probe_sprintf_version(pr, "%u.%02u",
+		 le16_to_cpu(nw->SBH_VersionMediaMajor),
+		 le16_to_cpu(nw->SBH_VersionMediaMinor));
+
+	return 0;
+}
+
+const struct blkid_idinfo netware_idinfo =
+{
+	.name		= "nss",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_netware,
+	.magics		=
+	{
+		{ .magic = "SPB5", .len = 4, .kboff = 4 },
+		{ NULL }
+	}
+};
+
+
diff --git a/libblkid/src/superblocks/nilfs.c b/libblkid/src/superblocks/nilfs.c
new file mode 100644
index 0000000..3f03901
--- /dev/null
+++ b/libblkid/src/superblocks/nilfs.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2010 by Jiro SEKIBA <jir@unicus.jp>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License
+ */
+#include <stddef.h>
+#include <string.h>
+
+#include "superblocks.h"
+#include "crc32.h"
+
+struct nilfs_super_block {
+	uint32_t	s_rev_level;
+	uint16_t	s_minor_rev_level;
+	uint16_t	s_magic;
+
+	uint16_t	s_bytes;
+
+	uint16_t	s_flags;
+	uint32_t	s_crc_seed;
+	uint32_t	s_sum;
+
+	uint32_t	s_log_block_size;
+
+	uint64_t	s_nsegments;
+	uint64_t	s_dev_size;
+	uint64_t	s_first_data_block;
+	uint32_t	s_blocks_per_segment;
+	uint32_t	s_r_segments_percentage;
+
+	uint64_t	s_last_cno;
+	uint64_t	s_last_pseg;
+	uint64_t	s_last_seq;
+	uint64_t	s_free_blocks_count;
+
+	uint64_t	s_ctime;
+
+	uint64_t	s_mtime;
+	uint64_t	s_wtime;
+	uint16_t	s_mnt_count;
+	uint16_t	s_max_mnt_count;
+	uint16_t	s_state;
+	uint16_t	s_errors;
+	uint64_t	s_lastcheck;
+
+	uint32_t	s_checkinterval;
+	uint32_t	s_creator_os;
+	uint16_t	s_def_resuid;
+	uint16_t	s_def_resgid;
+	uint32_t	s_first_ino;
+
+	uint16_t	s_inode_size;
+	uint16_t	s_dat_entry_size;
+	uint16_t	s_checkpoint_size;
+	uint16_t	s_segment_usage_size;
+
+	uint8_t		s_uuid[16];
+	char		s_volume_name[80];
+
+	uint32_t	s_c_interval;
+	uint32_t	s_c_block_max;
+	uint32_t	s_reserved[192];
+};
+
+#define NILFS_SB_MAGIC		0x3434
+#define NILFS_SB_OFFSET		0x400
+
+static int nilfs_valid_sb(blkid_probe pr, struct nilfs_super_block *sb)
+{
+	static unsigned char sum[4];
+	const int sumoff = offsetof(struct nilfs_super_block, s_sum);
+	size_t bytes;
+	uint32_t crc;
+
+	if (!sb || le16_to_cpu(sb->s_magic) != NILFS_SB_MAGIC)
+		return 0;
+
+	bytes = le16_to_cpu(sb->s_bytes);
+	crc = crc32(le32_to_cpu(sb->s_crc_seed), (unsigned char *)sb, sumoff);
+	crc = crc32(crc, sum, 4);
+	crc = crc32(crc, (unsigned char *)sb + sumoff + 4, bytes - sumoff - 4);
+
+	return blkid_probe_verify_csum(pr, crc, le32_to_cpu(sb->s_sum));
+}
+
+static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct nilfs_super_block *sb, *sbp, *sbb;
+	int valid[2], swp = 0;
+
+	/* primary */
+	sbp = (struct nilfs_super_block *) blkid_probe_get_buffer(
+			pr, NILFS_SB_OFFSET, sizeof(struct nilfs_super_block));
+	if (!sbp)
+		return errno ? -errno : 1;
+	/* backup */
+	sbb = (struct nilfs_super_block *) blkid_probe_get_buffer(
+			pr, ((pr->size / 0x200) - 8) * 0x200, sizeof(struct nilfs_super_block));
+	if (!sbb)
+		return errno ? -errno : 1;
+
+	/*
+	 * Compare two super blocks and set 1 in swp if the secondary
+	 * super block is valid and newer.  Otherwise, set 0 in swp.
+	 */
+	valid[0] = nilfs_valid_sb(pr, sbp);
+	valid[1] = nilfs_valid_sb(pr, sbb);
+	if (!valid[0] && !valid[1])
+		return 1;
+
+	swp = valid[1] && (!valid[0] ||
+			   le64_to_cpu(sbp->s_last_cno) >
+			   le64_to_cpu(sbb->s_last_cno));
+	sb = swp ? sbb : sbp;
+
+	DBG(LOWPROBE, ul_debug("nilfs2: primary=%d, backup=%d, swap=%d",
+				valid[0], valid[1], swp));
+
+	if (strlen(sb->s_volume_name))
+		blkid_probe_set_label(pr, (unsigned char *) sb->s_volume_name,
+				      sizeof(sb->s_volume_name));
+
+	blkid_probe_set_uuid(pr, sb->s_uuid);
+	blkid_probe_sprintf_version(pr, "%u", le32_to_cpu(sb->s_rev_level));
+
+	return 0;
+}
+
+const struct blkid_idinfo nilfs2_idinfo =
+{
+	.name		= "nilfs2",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_nilfs2,
+	/* default min.size is 128MiB, but 1MiB for "mkfs.nilfs2 -b 1024 -B 16" */
+	.minsz		= (1024 * 1024),
+	.magics		= BLKID_NONE_MAGIC
+};
diff --git a/libblkid/src/superblocks/ntfs.c b/libblkid/src/superblocks/ntfs.c
new file mode 100644
index 0000000..8ff9ccd
--- /dev/null
+++ b/libblkid/src/superblocks/ntfs.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "superblocks.h"
+
+struct ntfs_bios_parameters {
+	uint16_t	sector_size;	/* Size of a sector in bytes. */
+	uint8_t		sectors_per_cluster;	/* Size of a cluster in sectors. */
+	uint16_t	reserved_sectors;	/* zero */
+	uint8_t		fats;			/* zero */
+	uint16_t	root_entries;		/* zero */
+	uint16_t	sectors;		/* zero */
+	uint8_t		media_type;		/* 0xf8 = hard disk */
+	uint16_t	sectors_per_fat;	/* zero */
+	uint16_t	sectors_per_track;	/* irrelevant */
+	uint16_t	heads;			/* irrelevant */
+	uint32_t	hidden_sectors;		/* zero */
+	uint32_t	large_sectors;		/* zero */
+} __attribute__ ((__packed__));
+
+struct ntfs_super_block {
+	uint8_t		jump[3];
+	uint8_t		oem_id[8];	/* magic string */
+
+	struct ntfs_bios_parameters	bpb;
+
+	uint16_t	unused[2];
+	uint64_t	number_of_sectors;
+	uint64_t	mft_cluster_location;
+	uint64_t	mft_mirror_cluster_location;
+	int8_t		clusters_per_mft_record;
+	uint8_t		reserved1[3];
+	int8_t		cluster_per_index_record;
+	uint8_t		reserved2[3];
+	uint64_t	volume_serial;
+	uint32_t	checksum;
+} __attribute__((packed));
+
+struct master_file_table_record {
+	uint32_t	magic;
+	uint16_t	usa_ofs;
+	uint16_t	usa_count;
+	uint64_t	lsn;
+	uint16_t	sequence_number;
+	uint16_t	link_count;
+	uint16_t	attrs_offset;
+	uint16_t	flags;
+	uint32_t	bytes_in_use;
+	uint32_t	bytes_allocated;
+} __attribute__((__packed__));
+
+struct file_attribute {
+	uint32_t	type;
+	uint32_t	len;
+	uint8_t		non_resident;
+	uint8_t		name_len;
+	uint16_t	name_offset;
+	uint16_t	flags;
+	uint16_t	instance;
+	uint32_t	value_len;
+	uint16_t	value_offset;
+} __attribute__((__packed__));
+
+#define MFT_RECORD_VOLUME	3
+#define NTFS_MAX_CLUSTER_SIZE	(64 * 1024)
+
+enum {
+	MFT_RECORD_ATTR_VOLUME_NAME		= 0x60,
+	MFT_RECORD_ATTR_END			= 0xffffffff
+};
+
+static int probe_ntfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct ntfs_super_block *ns;
+	struct master_file_table_record *mft;
+
+	uint32_t sectors_per_cluster, mft_record_size, attr_off;
+	uint16_t sector_size;
+	uint64_t nr_clusters, off;
+	unsigned char *buf_mft;
+
+	ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block);
+	if (!ns)
+		return errno ? -errno : 1;
+
+	/*
+	 * Check bios parameters block
+	 */
+	sector_size = le16_to_cpu(ns->bpb.sector_size);
+	sectors_per_cluster = ns->bpb.sectors_per_cluster;
+
+	if (sector_size < 256 || sector_size > 4096)
+		return 1;
+
+	switch (sectors_per_cluster) {
+	case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
+		break;
+	default:
+		return 1;
+	}
+
+	if ((uint16_t) le16_to_cpu(ns->bpb.sector_size) *
+			ns->bpb.sectors_per_cluster > NTFS_MAX_CLUSTER_SIZE)
+		return 1;
+
+	/* Unused fields must be zero */
+	if (le16_to_cpu(ns->bpb.reserved_sectors)
+	    || le16_to_cpu(ns->bpb.root_entries)
+	    || le16_to_cpu(ns->bpb.sectors)
+	    || le16_to_cpu(ns->bpb.sectors_per_fat)
+	    || le32_to_cpu(ns->bpb.large_sectors)
+	    || ns->bpb.fats)
+		return 1;
+
+	if ((uint8_t) ns->clusters_per_mft_record < 0xe1
+	    || (uint8_t) ns->clusters_per_mft_record > 0xf7) {
+
+		switch (ns->clusters_per_mft_record) {
+		case 1: case 2: case 4: case 8: case 16: case 32: case 64:
+			break;
+		default:
+			return 1;
+		}
+	}
+
+	if (ns->clusters_per_mft_record > 0)
+		mft_record_size = ns->clusters_per_mft_record *
+				  sectors_per_cluster * sector_size;
+	else
+		mft_record_size = 1 << (0 - ns->clusters_per_mft_record);
+
+	nr_clusters = le64_to_cpu(ns->number_of_sectors) / sectors_per_cluster;
+
+	if ((le64_to_cpu(ns->mft_cluster_location) > nr_clusters) ||
+	    (le64_to_cpu(ns->mft_mirror_cluster_location) > nr_clusters))
+		return 1;
+
+
+	off = le64_to_cpu(ns->mft_cluster_location) * sector_size *
+		sectors_per_cluster;
+
+	DBG(LOWPROBE, ul_debug("NTFS: sector_size=%d, mft_record_size=%d, "
+			"sectors_per_cluster=%d, nr_clusters=%ju "
+			"cluster_offset=%jd",
+			(int) sector_size, mft_record_size,
+			sectors_per_cluster, nr_clusters,
+			off));
+
+	buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
+	if (!buf_mft)
+		return errno ? -errno : 1;
+
+	if (memcmp(buf_mft, "FILE", 4))
+		return 1;
+
+	off += MFT_RECORD_VOLUME * mft_record_size;
+
+	buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size);
+	if (!buf_mft)
+		return errno ? -errno : 1;
+
+	if (memcmp(buf_mft, "FILE", 4))
+		return 1;
+
+	mft = (struct master_file_table_record *) buf_mft;
+	attr_off = le16_to_cpu(mft->attrs_offset);
+
+	while (attr_off < mft_record_size &&
+	       attr_off <= le32_to_cpu(mft->bytes_allocated)) {
+
+		uint32_t attr_len;
+		struct file_attribute *attr;
+
+		attr = (struct file_attribute *) (buf_mft + attr_off);
+		attr_len = le32_to_cpu(attr->len);
+		if (!attr_len)
+			break;
+
+		if (le32_to_cpu(attr->type) == MFT_RECORD_ATTR_END)
+			break;
+		if (le32_to_cpu(attr->type) == MFT_RECORD_ATTR_VOLUME_NAME) {
+			unsigned int val_off = le16_to_cpu(attr->value_offset);
+			unsigned int val_len = le32_to_cpu(attr->value_len);
+			unsigned char *val = ((uint8_t *) attr) + val_off;
+
+			blkid_probe_set_utf8label(pr, val, val_len, BLKID_ENC_UTF16LE);
+			break;
+		}
+
+		if (UINT_MAX - attr_len < attr_off)
+			break;
+		attr_off += attr_len;
+	}
+
+	blkid_probe_sprintf_uuid(pr,
+			(unsigned char *) &ns->volume_serial,
+			sizeof(ns->volume_serial),
+			"%016" PRIX64, le64_to_cpu(ns->volume_serial));
+	return 0;
+}
+
+
+const struct blkid_idinfo ntfs_idinfo =
+{
+	.name		= "ntfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ntfs,
+	.magics		=
+	{
+		{ .magic = "NTFS    ", .len = 8, .sboff = 3 },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/nvidia_raid.c b/libblkid/src/superblocks/nvidia_raid.c
new file mode 100644
index 0000000..5db8ec2
--- /dev/null
+++ b/libblkid/src/superblocks/nvidia_raid.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct nv_metadata {
+	uint8_t		vendor[8];
+	uint32_t	size;
+	uint32_t	chksum;
+	uint16_t	version;
+} __attribute__((packed));
+
+#define NVIDIA_SIGNATURE		"NVIDIA"
+
+static int probe_nvraid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	uint64_t off;
+	struct nv_metadata *nv;
+
+	if (pr->size < 0x10000)
+		return 1;
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+
+	off = ((pr->size / 0x200) - 2) * 0x200;
+	nv = (struct nv_metadata *)
+		blkid_probe_get_buffer(pr,
+				off,
+				sizeof(struct nv_metadata));
+	if (!nv)
+		return errno ? -errno : 1;
+
+	if (memcmp(nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0)
+		return 1;
+	if (blkid_probe_sprintf_version(pr, "%u", le16_to_cpu(nv->version)) != 0)
+		return 1;
+	if (blkid_probe_set_magic(pr, off, sizeof(nv->vendor),
+				(unsigned char *) nv->vendor))
+		return 1;
+	return 0;
+}
+
+const struct blkid_idinfo nvraid_idinfo = {
+	.name		= "nvidia_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_nvraid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/ocfs.c b/libblkid/src/superblocks/ocfs.c
new file mode 100644
index 0000000..3fe199d
--- /dev/null
+++ b/libblkid/src/superblocks/ocfs.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 1999, 2001 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct ocfs_volume_header {
+	unsigned char	minor_version[4];
+	unsigned char	major_version[4];
+	unsigned char	signature[128];
+	char		mount[128];
+	unsigned char   mount_len[2];
+} __attribute__((packed));
+
+struct ocfs_volume_label {
+	unsigned char	disk_lock[48];
+	char		label[64];
+	unsigned char	label_len[2];
+	unsigned char   vol_id[16];
+	unsigned char   vol_id_len[2];
+} __attribute__((packed));
+
+#define ocfsmajor(o) ( (uint32_t) o.major_version[0] \
+                   + (((uint32_t) o.major_version[1]) << 8) \
+                   + (((uint32_t) o.major_version[2]) << 16) \
+                   + (((uint32_t) o.major_version[3]) << 24))
+
+#define ocfsminor(o) ( (uint32_t) o.minor_version[0] \
+                   + (((uint32_t) o.minor_version[1]) << 8) \
+                   + (((uint32_t) o.minor_version[2]) << 16) \
+                   + (((uint32_t) o.minor_version[3]) << 24))
+
+#define ocfslabellen(o)	((uint32_t)o.label_len[0] + (((uint32_t) o.label_len[1]) << 8))
+#define ocfsmountlen(o)	((uint32_t)o.mount_len[0] + (((uint32_t) o.mount_len[1]) << 8))
+
+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];
+} __attribute__((packed));
+
+struct oracle_asm_disk_label {
+	char dummy[32];
+	char dl_tag[8];
+	char dl_id[24];
+} __attribute__((packed));
+
+static int probe_ocfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	unsigned char *buf;
+	struct ocfs_volume_header ovh;
+	struct ocfs_volume_label ovl;
+	uint32_t maj, min;
+
+	/* header */
+	buf = blkid_probe_get_buffer(pr, mag->kboff << 10,
+			sizeof(struct ocfs_volume_header));
+	if (!buf)
+		return errno ? -errno : 1;
+	memcpy(&ovh, buf, sizeof(ovh));
+
+	/* label */
+	buf = blkid_probe_get_buffer(pr, (mag->kboff << 10) + 512,
+			sizeof(struct ocfs_volume_label));
+	if (!buf)
+		return errno ? -errno : 1;
+	memcpy(&ovl, buf, sizeof(ovl));
+
+	maj = ocfsmajor(ovh);
+	min = ocfsminor(ovh);
+
+	if (maj == 1)
+		blkid_probe_set_value(pr, "SEC_TYPE",
+				(unsigned char *) "ocfs1", sizeof("ocfs1"));
+	else if (maj >= 9)
+		blkid_probe_set_value(pr, "SEC_TYPE",
+				(unsigned char *) "ntocfs", sizeof("ntocfs"));
+
+	blkid_probe_set_label(pr, (unsigned char *) ovl.label,
+				ocfslabellen(ovl));
+	blkid_probe_set_value(pr, "MOUNT", (unsigned char *) ovh.mount,
+				ocfsmountlen(ovh));
+	blkid_probe_set_uuid(pr, ovl.vol_id);
+	blkid_probe_sprintf_version(pr, "%u.%u", maj, min);
+	return 0;
+}
+
+static int probe_ocfs2(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct ocfs2_super_block *osb;
+
+	osb = blkid_probe_get_sb(pr, mag, struct ocfs2_super_block);
+	if (!osb)
+		return errno ? -errno : 1;
+
+	blkid_probe_set_label(pr, (unsigned char *) osb->s_label, sizeof(osb->s_label));
+	blkid_probe_set_uuid(pr, osb->s_uuid);
+
+	blkid_probe_sprintf_version(pr, "%u.%u",
+		le16_to_cpu(osb->s_major_rev_level),
+		le16_to_cpu(osb->s_minor_rev_level));
+
+	return 0;
+}
+
+static int probe_oracleasm(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct oracle_asm_disk_label *dl;
+
+	dl = blkid_probe_get_sb(pr, mag, struct oracle_asm_disk_label);
+	if (!dl)
+		return errno ? -errno : 1;
+
+	blkid_probe_set_label(pr, (unsigned char *) dl->dl_id, sizeof(dl->dl_id));
+	return 0;
+}
+
+
+const struct blkid_idinfo ocfs_idinfo =
+{
+	.name		= "ocfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ocfs,
+	.minsz		= 14000 * 1024,
+	.magics		=
+	{
+		{ .magic = "OracleCFS", .len = 9, .kboff = 8 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo ocfs2_idinfo =
+{
+	.name		= "ocfs2",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ocfs2,
+	.minsz		= 14000 * 1024,
+	.magics		=
+	{
+		{ .magic = "OCFSV2", .len = 6, .kboff = 1 },
+		{ .magic = "OCFSV2", .len = 6, .kboff = 2 },
+		{ .magic = "OCFSV2", .len = 6, .kboff = 4 },
+		{ .magic = "OCFSV2", .len = 6, .kboff = 8 },
+		{ NULL }
+	}
+};
+
+/* Oracle ASM (Automatic Storage Management) */
+const struct blkid_idinfo oracleasm_idinfo =
+{
+	.name		= "oracleasm",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_oracleasm,
+	.magics		=
+	{
+		{ .magic = "ORCLDISK", .len = 8, .sboff = 32 },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/promise_raid.c b/libblkid/src/superblocks/promise_raid.c
new file mode 100644
index 0000000..678460a
--- /dev/null
+++ b/libblkid/src/superblocks/promise_raid.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct promise_metadata {
+	uint8_t	sig[24];
+};
+
+#define PDC_CONFIG_OFF		0x1200
+#define PDC_SIGNATURE		"Promise Technology, Inc."
+
+static int probe_pdcraid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	unsigned int i;
+	static unsigned int sectors[] = {
+	  63, 255, 256, 16, 399, 591, 675, 735, 911, 974, 991, 951, 3087, 0
+	};
+
+	if (pr->size < 0x40000)
+		return 1;
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+
+	for (i = 0; sectors[i] != 0; i++) {
+		uint64_t off;
+		struct promise_metadata *pdc;
+
+		off = ((pr->size / 0x200) - sectors[i]) * 0x200;
+		pdc = (struct promise_metadata *)
+				blkid_probe_get_buffer(pr,
+					off,
+					sizeof(struct promise_metadata));
+		if (!pdc)
+			return errno ? -errno : 1;
+
+		if (memcmp(pdc->sig, PDC_SIGNATURE,
+				sizeof(PDC_SIGNATURE) - 1) == 0) {
+
+			if (blkid_probe_set_magic(pr, off, sizeof(pdc->sig),
+						(unsigned char *) pdc->sig))
+				return 1;
+			return 0;
+		}
+	}
+	return 1;
+}
+
+const struct blkid_idinfo pdcraid_idinfo = {
+	.name		= "promise_fasttrack_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_pdcraid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/refs.c b/libblkid/src/superblocks/refs.c
new file mode 100644
index 0000000..ea81f20
--- /dev/null
+++ b/libblkid/src/superblocks/refs.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2013 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "superblocks.h"
+
+
+const struct blkid_idinfo refs_idinfo =
+{
+	.name		= "ReFS",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.magics		=
+	{
+		{ .magic = "\000\000\000ReFS\000", .len = 8 },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/reiserfs.c b/libblkid/src/superblocks/reiserfs.c
new file mode 100644
index 0000000..edbaaa9
--- /dev/null
+++ b/libblkid/src/superblocks/reiserfs.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 1999, 2001 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct reiserfs_super_block {
+	uint32_t	rs_blocks_count;
+	uint32_t	rs_free_blocks;
+	uint32_t	rs_root_block;
+	uint32_t	rs_journal_block;
+	uint32_t	rs_journal_dev;
+	uint32_t	rs_orig_journal_size;
+	uint32_t	rs_dummy2[5];
+	uint16_t	rs_blocksize;
+	uint16_t	rs_dummy3[3];
+	unsigned char	rs_magic[12];
+	uint32_t	rs_dummy4[5];
+	unsigned char	rs_uuid[16];
+	char		rs_label[16];
+} __attribute__((packed));
+
+struct reiser4_super_block {
+	unsigned char	rs4_magic[16];
+	uint16_t	rs4_dummy[2];
+	unsigned char	rs4_uuid[16];
+	unsigned char	rs4_label[16];
+	uint64_t	rs4_dummy2;
+} __attribute__((packed));
+
+static int probe_reiser(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct reiserfs_super_block *rs;
+	unsigned int blocksize;
+
+	rs = blkid_probe_get_sb(pr, mag, struct reiserfs_super_block);
+	if (!rs)
+		return errno ? -errno : 1;
+
+	blocksize = le16_to_cpu(rs->rs_blocksize);
+
+	/* The blocksize must be at least 512B */
+	if ((blocksize >> 9) == 0)
+		return 1;
+
+	/* If the superblock is inside the journal, we have the wrong one */
+	if (mag->kboff / (blocksize >> 9) > le32_to_cpu(rs->rs_journal_block) / 2)
+		return 1;
+
+	/* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */
+	if (mag->magic[6] == '2' || mag->magic[6] == '3') {
+		if (*rs->rs_label)
+			blkid_probe_set_label(pr,
+					(unsigned char *) rs->rs_label,
+					sizeof(rs->rs_label));
+		blkid_probe_set_uuid(pr, rs->rs_uuid);
+	}
+
+	if (mag->magic[6] == '3')
+		blkid_probe_set_version(pr, "JR");
+	else if (mag->magic[6] == '2')
+		blkid_probe_set_version(pr, "3.6");
+	else
+		blkid_probe_set_version(pr, "3.5");
+
+	return 0;
+}
+
+static int probe_reiser4(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct reiser4_super_block *rs4;
+
+	rs4 = blkid_probe_get_sb(pr, mag, struct reiser4_super_block);
+	if (!rs4)
+		return errno ? -errno : 1;
+
+	if (*rs4->rs4_label)
+		blkid_probe_set_label(pr, rs4->rs4_label, sizeof(rs4->rs4_label));
+	blkid_probe_set_uuid(pr, rs4->rs4_uuid);
+	blkid_probe_set_version(pr, "4");
+
+	return 0;
+}
+
+
+const struct blkid_idinfo reiser_idinfo =
+{
+	.name		= "reiserfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_reiser,
+	.minsz		= 128 * 1024,
+	.magics		=
+	{
+		{ .magic = "ReIsErFs",  .len = 8, .kboff = 8,  .sboff = 0x34 },
+		{ .magic = "ReIsEr2Fs", .len = 9, .kboff = 64, .sboff = 0x34 },
+		{ .magic = "ReIsEr3Fs", .len = 9, .kboff = 64, .sboff = 0x34 },
+		{ .magic = "ReIsErFs",  .len = 8, .kboff = 64, .sboff = 0x34 },
+		{ .magic = "ReIsErFs",  .len = 8, .kboff =  8, .sboff = 20   },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo reiser4_idinfo =
+{
+	.name		= "reiser4",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_reiser4,
+	.minsz		= 128 * 1024,
+	.magics		=
+	{
+		{ .magic = "ReIsEr4", .len = 7, .kboff = 64 },
+		{ NULL }
+	}
+};
+
+
+
+
diff --git a/libblkid/src/superblocks/romfs.c b/libblkid/src/superblocks/romfs.c
new file mode 100644
index 0000000..8e63c10
--- /dev/null
+++ b/libblkid/src/superblocks/romfs.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1999, 2001 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct romfs_super_block {
+	unsigned char	ros_magic[8];
+	uint32_t	ros_dummy1[2];
+	unsigned char	ros_volume[16];
+} __attribute__((packed));
+
+static int probe_romfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct romfs_super_block *ros;
+
+	ros = blkid_probe_get_sb(pr, mag, struct romfs_super_block);
+	if (!ros)
+		return errno ? -errno : 1;
+
+	if (strlen((char *) ros->ros_volume))
+		blkid_probe_set_label(pr, ros->ros_volume,
+				sizeof(ros->ros_volume));
+	return 0;
+}
+
+const struct blkid_idinfo romfs_idinfo =
+{
+	.name		= "romfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_romfs,
+	.magics		=
+	{
+		{ .magic = "-rom1fs-", .len = 8 },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/silicon_raid.c b/libblkid/src/superblocks/silicon_raid.c
new file mode 100644
index 0000000..edbefbc
--- /dev/null
+++ b/libblkid/src/superblocks/silicon_raid.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "superblocks.h"
+
+struct silicon_metadata {
+	uint8_t		unknown0[0x2E];
+	uint8_t		ascii_version[0x36 - 0x2E];
+	int8_t		diskname[0x56 - 0x36];
+	int8_t		unknown1[0x60 - 0x56];
+	uint32_t	magic;
+	int8_t		unknown1a[0x6C - 0x64];
+	uint32_t	array_sectors_low;
+	uint32_t	array_sectors_high;
+	int8_t		unknown2[0x78 - 0x74];
+	uint32_t	thisdisk_sectors;
+	int8_t		unknown3[0x100 - 0x7C];
+	int8_t		unknown4[0x104 - 0x100];
+	uint16_t	product_id;
+	uint16_t	vendor_id;
+	uint16_t	minor_ver;
+	uint16_t	major_ver;
+	uint8_t		seconds;
+	uint8_t		minutes;
+	uint8_t		hour;
+	uint8_t		day;
+	uint8_t		month;
+	uint8_t		year;
+	uint16_t	raid0_stride;
+	int8_t		unknown6[0x116 - 0x114];
+	uint8_t		disk_number;
+	uint8_t		type;			/* SILICON_TYPE_* */
+	int8_t		drives_per_striped_set;
+	int8_t		striped_set_number;
+	int8_t		drives_per_mirrored_set;
+	int8_t		mirrored_set_number;
+	uint32_t	rebuild_ptr_low;
+	uint32_t	rebuild_ptr_high;
+	uint32_t	incarnation_no;
+	uint8_t		member_status;
+	uint8_t		mirrored_set_state;	/* SILICON_MIRROR_* */
+	uint8_t		reported_device_location;
+	uint8_t		idechannel;
+	uint8_t		auto_rebuild;
+	uint8_t		unknown8;
+	uint8_t		text_type[0x13E - 0x12E];
+	uint16_t	checksum1;
+	int8_t		assumed_zeros[0x1FE - 0x140];
+	uint16_t	checksum2;
+} __attribute__((packed));
+
+#define SILICON_MAGIC		0x2F000000
+
+static uint16_t silraid_checksum(struct silicon_metadata *sil)
+{
+	int sum = 0;
+	unsigned short count = offsetof(struct silicon_metadata, checksum1) / 2;
+	uint16_t *p = (uint16_t *) sil;
+
+	while (count--) {
+		uint16_t x = *p++;
+		sum += le16_to_cpu(x);
+	}
+
+	return (-sum & 0xFFFF);
+}
+
+static int probe_silraid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	uint64_t off;
+	struct silicon_metadata *sil;
+
+	if (pr->size < 0x10000)
+		return 1;
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+
+	off = ((pr->size / 0x200) - 1) * 0x200;
+
+	sil = (struct silicon_metadata *)
+			blkid_probe_get_buffer(pr, off,
+				sizeof(struct silicon_metadata));
+	if (!sil)
+		return errno ? -errno : 1;
+
+	if (le32_to_cpu(sil->magic) != SILICON_MAGIC)
+		return 1;
+	if (sil->disk_number >= 8)
+		return 1;
+	if (!blkid_probe_verify_csum(pr, silraid_checksum(sil), le16_to_cpu(sil->checksum1)))
+		return 1;
+
+	if (blkid_probe_sprintf_version(pr, "%u.%u",
+				le16_to_cpu(sil->major_ver),
+				le16_to_cpu(sil->minor_ver)) != 0)
+		return 1;
+
+	if (blkid_probe_set_magic(pr,
+			off + offsetof(struct silicon_metadata, magic),
+			sizeof(sil->magic),
+			(unsigned char *) &sil->magic))
+		return 1;
+	return 0;
+}
+
+const struct blkid_idinfo silraid_idinfo = {
+	.name		= "silicon_medley_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_silraid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/squashfs.c b/libblkid/src/superblocks/squashfs.c
new file mode 100644
index 0000000..8ed2838
--- /dev/null
+++ b/libblkid/src/superblocks/squashfs.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "bitops.h"	/* swab16() */
+#include "superblocks.h"
+
+struct sqsh_super_block {
+	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;
+} __attribute__((packed));
+
+static int probe_squashfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct sqsh_super_block *sq;
+	uint16_t major;
+	uint16_t minor;
+
+	sq = blkid_probe_get_sb(pr, mag, struct sqsh_super_block);
+	if (!sq)
+		return errno ? -errno : 1;
+
+	major = le16_to_cpu(sq->s_major);
+	minor = le16_to_cpu(sq->s_minor);
+	if (major < 4)
+		return 1;
+
+	blkid_probe_sprintf_version(pr, "%u.%u", major, minor);
+
+	return 0;
+}
+
+static int probe_squashfs3(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct sqsh_super_block *sq;
+	uint16_t major;
+	uint16_t minor;
+
+	sq = blkid_probe_get_sb(pr, mag, struct sqsh_super_block);
+	if (!sq)
+		return errno ? -errno : 1;
+
+	if (strcmp(mag->magic, "sqsh") == 0) {
+		major = be16_to_cpu(sq->s_major);
+		minor = be16_to_cpu(sq->s_minor);
+	} else {
+		major = le16_to_cpu(sq->s_major);
+		minor = le16_to_cpu(sq->s_minor);
+	}
+
+	if (major > 3)
+		return 1;
+
+	blkid_probe_sprintf_version(pr, "%u.%u", major, minor);
+
+	return 0;
+}
+
+const struct blkid_idinfo squashfs_idinfo =
+{
+	.name		= "squashfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_squashfs,
+	.magics		=
+	{
+		{ .magic = "hsqs", .len = 4 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo squashfs3_idinfo =
+{
+	.name		= "squashfs3",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_squashfs3,
+	.magics		=
+	{
+		{ .magic = "sqsh", .len = 4 }, /* big endian */
+		{ .magic = "hsqs", .len = 4 }, /* little endian */
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/superblocks.c b/libblkid/src/superblocks/superblocks.c
new file mode 100644
index 0000000..80bd6e5
--- /dev/null
+++ b/libblkid/src/superblocks/superblocks.c
@@ -0,0 +1,813 @@
+/*
+ * 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 "superblocks.h"
+
+/**
+ * SECTION:superblocks
+ * @title: Superblocks probing
+ * @short_description: filesystems and raids superblocks probing.
+ *
+ * The library API has been originally 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 controlled 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_SUB: subvolume uuid (e.g. btrfs)
+ *
+ * @LOGUUID: external log UUID (e.g. xfs)
+ *
+ * @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
+ *
+ * @SBMAGIC_OFFSET: offset of SBMAGIC
+ *
+ * @FSSIZE: size of filessystem [not-implemented yet]
+ *
+ * @SYSTEM_ID: ISO9660 system identifier
+ *
+ * @PUBLISHER_ID: ISO9660 publisher identifier
+ *
+ * @APPLICATION_ID: ISO9660 application identifier
+ *
+ * @BOOT_SYSTEM_ID: ISO9660 boot system identifier
+ */
+
+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,
+
+	&bcache_idinfo,
+	&drbd_idinfo,
+	&drbdproxy_datalog_idinfo,
+	&lvm2_idinfo,
+	&lvm1_idinfo,
+	&snapcow_idinfo,
+	&verity_hash_idinfo,
+	&luks_idinfo,
+	&vmfs_volume_idinfo,
+
+	/* Filesystems */
+	&vfat_idinfo,
+	&swsuspend_idinfo,
+	&swap_idinfo,
+	&xfs_idinfo,
+	&xfs_log_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,
+	&refs_idinfo,
+	&cramfs_idinfo,
+	&romfs_idinfo,
+	&minix_idinfo,
+	&gfs_idinfo,
+	&gfs2_idinfo,
+	&ocfs_idinfo,
+	&ocfs2_idinfo,
+	&oracleasm_idinfo,
+	&vxfs_idinfo,
+	&squashfs_idinfo,
+	&squashfs3_idinfo,
+	&netware_idinfo,
+	&btrfs_idinfo,
+	&ubifs_idinfo,
+	&bfs_idinfo,
+	&vmfs_fs_idinfo,
+	&befs_idinfo,
+	&nilfs2_idinfo,
+	&exfat_idinfo,
+	&f2fs_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,
+};
+
+/**
+ * blkid_probe_enable_superblocks:
+ * @pr: probe
+ * @enable: TRUE/FALSE
+ *
+ * Enables/disables the superblocks probing for non-binary interface.
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int blkid_probe_enable_superblocks(blkid_probe pr, int enable)
+{
+	if (!pr)
+		return -1;
+	pr->chains[BLKID_CHAIN_SUBLKS].enabled = enable;
+	return 0;
+}
+
+/**
+ * blkid_probe_set_superblocks_flags:
+ * @pr: prober
+ * @flags: BLKID_SUBLKS_* flags
+ *
+ * Sets probing flags to the superblocks prober. This function is optional, the
+ * default are BLKID_SUBLKS_DEFAULTS flags.
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int blkid_probe_set_superblocks_flags(blkid_probe pr, int flags)
+{
+	if (!pr)
+		return -1;
+
+	pr->chains[BLKID_CHAIN_SUBLKS].flags = flags;
+	return 0;
+}
+
+/**
+ * blkid_probe_reset_superblocks_filter:
+ * @pr: prober
+ *
+ * Resets superblocks probing filter
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int blkid_probe_reset_superblocks_filter(blkid_probe pr)
+{
+	return __blkid_probe_reset_filter(pr, BLKID_CHAIN_SUBLKS);
+}
+
+/**
+ * blkid_probe_invert_superblocks_filter:
+ * @pr: prober
+ *
+ * Inverts superblocks probing filter
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int blkid_probe_invert_superblocks_filter(blkid_probe pr)
+{
+	return __blkid_probe_invert_filter(pr, BLKID_CHAIN_SUBLKS);
+}
+
+/**
+ * blkid_probe_filter_superblocks_type:
+ * @pr: prober
+ * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
+ * @names: NULL terminated array of probing function names (e.g. "vfat").
+ *
+ *  %BLKID_FLTR_NOTIN  - probe for all items which are NOT IN @names;
+ *
+ *  %BLKID_FLTR_ONLYIN - probe for items which are IN @names
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int blkid_probe_filter_superblocks_type(blkid_probe pr, int flag, char *names[])
+{
+	return __blkid_probe_filter_types(pr, BLKID_CHAIN_SUBLKS, flag, names);
+}
+
+/**
+ * blkid_probe_filter_superblocks_usage:
+ * @pr: prober
+ * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
+ * @usage: BLKID_USAGE_* flags
+ *
+ *  %BLKID_FLTR_NOTIN  - probe for all items which are NOT IN @usage;
+ *
+ *  %BLKID_FLTR_ONLYIN - probe for items which are IN @usage
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ */
+int blkid_probe_filter_superblocks_usage(blkid_probe pr, int flag, int usage)
+{
+	unsigned long *fltr;
+	struct blkid_chain *chn;
+	size_t i;
+
+	fltr = blkid_probe_get_filter(pr, BLKID_CHAIN_SUBLKS, TRUE);
+	if (!fltr)
+		return -1;
+
+	chn = &pr->chains[BLKID_CHAIN_SUBLKS];
+
+	for (i = 0; i < chn->driver->nidinfos; i++) {
+		const struct blkid_idinfo *id = chn->driver->idinfos[i];
+
+		if (id->usage & usage) {
+			if (flag & BLKID_FLTR_NOTIN)
+				blkid_bmp_set_item(chn->fltr, i);
+		} else if (flag & BLKID_FLTR_ONLYIN)
+			blkid_bmp_set_item(chn->fltr, i);
+	}
+	DBG(LOWPROBE, ul_debug("a new probing usage-filter initialized"));
+	return 0;
+}
+
+/**
+ * blkid_known_fstype:
+ * @fstype: filesystem name
+ *
+ * Returns: 1 for known filesytems, or 0 for unknown filesystem.
+ */
+int blkid_known_fstype(const char *fstype)
+{
+	size_t i;
+
+	if (!fstype)
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
+		const struct blkid_idinfo *id = idinfos[i];
+		if (strcmp(id->name, fstype) == 0)
+			return 1;
+	}
+	return 0;
+}
+
+/**
+ * blkid_superblocks_get_name:
+ * @idx: number >= 0
+ * @name: returns name of supported filesystem/raid (optional)
+ * @usage: returns BLKID_USAGE_* flags, (optional)
+ *
+ * Returns: -1 if @idx is out of range, or 0 on success.
+ */
+int blkid_superblocks_get_name(size_t idx, const char **name, int *usage)
+{
+	if (idx < ARRAY_SIZE(idinfos)) {
+		if (name)
+			*name = idinfos[idx]->name;
+		if (usage)
+			*usage = idinfos[idx]->usage;
+		return 0;
+	}
+	return -1;
+}
+
+/*
+ * The blkid_do_probe() backend.
+ */
+static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
+{
+	size_t i;
+	int rc = BLKID_PROBE_NONE;
+
+	if (!pr || chn->idx < -1)
+		return -EINVAL;
+
+	blkid_probe_chain_reset_vals(pr, chn);
+
+	if (pr->flags & BLKID_FL_NOSCAN_DEV)
+		return BLKID_PROBE_NONE;
+
+	if (pr->size <= 0 || (pr->size <= 1024 && !S_ISCHR(pr->mode)))
+		/* Ignore very very small block devices or regular files (e.g.
+		 * extended partitions). Note that size of the UBI char devices
+		 * is 1 byte */
+		return BLKID_PROBE_NONE;
+
+	DBG(LOWPROBE, ul_debug("--> starting probing loop [SUBLKS idx=%d]",
+		chn->idx));
+
+	i = chn->idx < 0 ? 0 : chn->idx + 1U;
+
+	for ( ; i < ARRAY_SIZE(idinfos); i++) {
+		const struct blkid_idinfo *id;
+		const struct blkid_idmag *mag = NULL;
+		blkid_loff_t off = 0;
+
+		chn->idx = i;
+		id = idinfos[i];
+
+		if (chn->fltr && blkid_bmp_get_item(chn->fltr, i)) {
+			DBG(LOWPROBE, ul_debug("filter out: %s", id->name));
+			rc = BLKID_PROBE_NONE;
+			continue;
+		}
+
+		if (id->minsz && id->minsz > pr->size) {
+			rc = BLKID_PROBE_NONE;
+			continue;	/* the device is too small */
+		}
+
+		/* don't probe for RAIDs, swap or journal on CD/DVDs */
+		if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) &&
+		    blkid_probe_is_cdrom(pr)) {
+			rc = BLKID_PROBE_NONE;
+			continue;
+		}
+
+		/* don't probe for RAIDs on floppies */
+		if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) {
+			rc = BLKID_PROBE_NONE;
+			continue;
+		}
+
+		DBG(LOWPROBE, ul_debug("[%zd] %s:", i, id->name));
+
+		rc = blkid_probe_get_idmag(pr, id, &off, &mag);
+		if (rc < 0)
+			break;
+		if (rc != BLKID_PROBE_OK)
+			continue;
+
+		/* final check by probing function */
+		if (id->probefunc) {
+			DBG(LOWPROBE, ul_debug("\tcall probefunc()"));
+			rc = id->probefunc(pr, mag);
+			if (rc != BLKID_PROBE_OK) {
+				blkid_probe_chain_reset_vals(pr, chn);
+				if (rc < 0)
+					break;
+				continue;
+			}
+		}
+
+		/* all cheks passed */
+		if (chn->flags & BLKID_SUBLKS_TYPE)
+			rc = blkid_probe_set_value(pr, "TYPE",
+				(unsigned char *) id->name,
+				strlen(id->name) + 1);
+
+		if (!rc)
+			rc = blkid_probe_set_usage(pr, id->usage);
+
+		if (!rc && mag)
+			rc = blkid_probe_set_magic(pr, off, mag->len,
+					(unsigned char *) mag->magic);
+		if (rc) {
+			blkid_probe_chain_reset_vals(pr, chn);
+			DBG(LOWPROBE, ul_debug("failed to set result -- ignore"));
+			continue;
+		}
+
+		DBG(LOWPROBE, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]",
+			id->name, chn->idx));
+		return BLKID_PROBE_OK;
+	}
+
+	DBG(LOWPROBE, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]",
+			rc, chn->idx));
+	return rc;
+}
+
+/*
+ * 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 or crypto signature
+ * is detected.  The function also does not check for collision between RAIDs
+ * and crypto devices. The first detected RAID or crypto device is returned.
+ *
+ * The function does not probe for ambivalent results on very small devices
+ * (e.g. floppies), on small devices the first detected filesystem 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;
+
+	if (pr->flags & BLKID_FL_NOSCAN_DEV)
+		return BLKID_PROBE_NONE;
+
+	while ((rc = superblocks_probe(pr, chn)) == 0) {
+
+		if (blkid_probe_is_tiny(pr) && !count)
+			return BLKID_PROBE_OK;	/* floppy or so -- returns the first result. */
+
+		count++;
+
+		if (chn->idx >= 0 &&
+		    idinfos[chn->idx]->usage & (BLKID_USAGE_RAID | BLKID_USAGE_CRYPTO))
+			break;
+
+		if (chn->idx >= 0 &&
+		    !(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT))
+			intol++;
+
+		if (count == 1) {
+			/* save the first result */
+			nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
+			idx = chn->idx;
+		}
+	}
+
+	if (rc < 0)
+		return rc;		/* error */
+
+	if (count > 1 && intol) {
+		DBG(LOWPROBE, ul_debug("ERROR: superblocks chain: "
+			       "ambivalent result detected (%d filesystems)!",
+			       count));
+		return -2;		/* error, ambivalent result (more FS) */
+	}
+	if (!count)
+		return BLKID_PROBE_NONE;
+
+	if (idx != -1) {
+		/* restore the first result */
+		blkid_probe_chain_reset_vals(pr, chn);
+		blkid_probe_append_vals(pr, vals, nvals);
+		chn->idx = idx;
+	}
+
+	/*
+	 * The RAID device could be partitioned. The problem are RAID1 devices
+	 * where the partition table is visible from underlaying devices. We
+	 * have to ignore such partition tables.
+	 */
+	if (chn->idx >= 0 && idinfos[chn->idx]->usage & BLKID_USAGE_RAID)
+		pr->prob_flags |= BLKID_PROBE_FL_IGNORE_PT;
+
+	return BLKID_PROBE_OK;
+}
+
+int blkid_probe_set_version(blkid_probe pr, const char *version)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+
+	if (chn->flags & BLKID_SUBLKS_VERSION)
+		return blkid_probe_set_value(pr, "VERSION",
+			   (unsigned char *) version, strlen(version) + 1);
+	return 0;
+}
+
+
+int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+	int rc = 0;
+
+	if (chn->flags & BLKID_SUBLKS_VERSION) {
+		va_list ap;
+
+		va_start(ap, fmt);
+		rc = blkid_probe_vsprintf_value(pr, "VERSION", fmt, ap);
+		va_end(ap);
+	}
+	return rc;
+}
+
+static int blkid_probe_set_usage(blkid_probe pr, int usage)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+	char *u = NULL;
+
+	if (!(chn->flags & BLKID_SUBLKS_USAGE))
+		return 0;
+
+	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);
+}
+
+int blkid_probe_set_id_label(blkid_probe pr, const char *name,
+			     unsigned char *data, size_t len)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+	struct blkid_prval *v;
+
+	if (!(chn->flags & BLKID_SUBLKS_LABEL))
+		return 0;
+
+	v = blkid_probe_assign_value(pr, name);
+	if (!v)
+		return -1;
+
+	if (len >= BLKID_PROBVAL_BUFSIZ)
+		len = BLKID_PROBVAL_BUFSIZ - 1;			/* make a space for \0 */
+
+	memcpy(v->data, data, len);
+	v->data[len] = '\0';
+
+	/* remove white spaces */
+	v->len = blkid_rtrim_whitespace(v->data) + 1;
+	if (v->len > 1)
+		v->len = blkid_ltrim_whitespace(v->data) + 1;
+
+	if (v->len <= 1)
+		blkid_probe_reset_last_value(pr);		/* ignore empty */
+	return 0;
+}
+
+int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+	struct blkid_prval *v;
+	if (len > BLKID_PROBVAL_BUFSIZ)
+		len = BLKID_PROBVAL_BUFSIZ;
+
+	if ((chn->flags & BLKID_SUBLKS_LABELRAW) &&
+	    blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0)
+		return -1;
+	if (!(chn->flags & BLKID_SUBLKS_LABEL))
+		return 0;
+	v = blkid_probe_assign_value(pr, "LABEL");
+	if (!v)
+		return -1;
+
+	if (len == BLKID_PROBVAL_BUFSIZ)
+		len--;				/* make a space for \0 */
+
+	memcpy(v->data, label, len);
+	v->data[len] = '\0';
+
+	v->len = blkid_rtrim_whitespace(v->data) + 1;
+	if (v->len == 1)
+		blkid_probe_reset_last_value(pr);
+	return 0;
+}
+
+int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label,
+				size_t len, int enc)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+	struct blkid_prval *v;
+
+	if ((chn->flags & BLKID_SUBLKS_LABELRAW) &&
+	    blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0)
+		return -1;
+	if (!(chn->flags & BLKID_SUBLKS_LABEL))
+		return 0;
+	v = blkid_probe_assign_value(pr, "LABEL");
+	if (!v)
+		return -1;
+
+	blkid_encode_to_utf8(enc, v->data, sizeof(v->data), label, len);
+	v->len = blkid_rtrim_whitespace(v->data) + 1;
+	if (v->len == 1)
+		blkid_probe_reset_last_value(pr);
+	return 0;
+}
+
+int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
+				size_t len, const char *fmt, ...)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+	int rc = -1;
+	va_list ap;
+
+	if (len > BLKID_PROBVAL_BUFSIZ)
+		len = BLKID_PROBVAL_BUFSIZ;
+
+	if (blkid_uuid_is_empty(uuid, len))
+		return 0;
+
+	if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
+	    blkid_probe_set_value(pr, "UUID_RAW", uuid, len) < 0)
+		return -1;
+	if (!(chn->flags & BLKID_SUBLKS_UUID))
+		return 0;
+
+	va_start(ap, fmt);
+	rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap);
+	va_end(ap);
+
+	/* convert to lower case (..be paranoid) */
+	if (!rc) {
+		size_t i;
+		struct blkid_prval *v = __blkid_probe_get_value(pr,
+						blkid_probe_numof_values(pr));
+		if (v) {
+			for (i = 0; i < v->len; i++)
+				if (v->data[i] >= 'A' && v->data[i] <= 'F')
+					v->data[i] = (v->data[i] - 'A') + 'a';
+		}
+	}
+	return rc;
+}
+
+/* function to set UUIDs that are in suberblocks stored as strings */
+int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+	struct blkid_prval *v;
+
+	if (str == NULL || *str == '\0')
+		return -1;
+	if (!len)
+		len = strlen((char *) str);
+	if (len > BLKID_PROBVAL_BUFSIZ)
+		len = BLKID_PROBVAL_BUFSIZ;
+
+	if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
+	    blkid_probe_set_value(pr, "UUID_RAW", str, len) < 0)
+		return -1;
+	if (!(chn->flags & BLKID_SUBLKS_UUID))
+		return 0;
+
+	v = blkid_probe_assign_value(pr, "UUID");
+	if (v) {
+		if (len == BLKID_PROBVAL_BUFSIZ)
+			len--;		/* make a space for \0 */
+
+		memcpy((char *) v->data, str, len);
+		v->data[len] = '\0';
+		v->len = len + 1;
+		return 0;
+	}
+	return -1;
+}
+
+/* default _set_uuid function to set DCE UUIDs */
+int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name)
+{
+	struct blkid_chain *chn = blkid_probe_get_chain(pr);
+	struct blkid_prval *v;
+
+	if (blkid_uuid_is_empty(uuid, 16))
+		return 0;
+
+	if (!name) {
+		if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
+		    blkid_probe_set_value(pr, "UUID_RAW", uuid, 16) < 0)
+			return -1;
+		if (!(chn->flags & BLKID_SUBLKS_UUID))
+			return 0;
+
+		v = blkid_probe_assign_value(pr, "UUID");
+	} else
+		v = blkid_probe_assign_value(pr, name);
+
+	blkid_unparse_uuid(uuid, (char *) v->data, sizeof(v->data));
+	v->len = 37;
+
+	return 0;
+}
+
+int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid)
+{
+	return blkid_probe_set_uuid_as(pr, uuid, NULL);
+}
+
+/**
+ * blkid_probe_set_request:
+ * @pr: probe
+ * @flags: BLKID_PROBREQ_* (deprecated) or BLKID_SUBLKS_* flags
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ *
+ * Deprecated: Use blkid_probe_set_superblocks_flags().
+ */
+int blkid_probe_set_request(blkid_probe pr, int flags)
+{
+	return blkid_probe_set_superblocks_flags(pr, flags);
+}
+
+/**
+ * blkid_probe_reset_filter:
+ * @pr: prober
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ *
+ * Deprecated: Use blkid_probe_reset_superblocks_filter().
+ */
+int blkid_probe_reset_filter(blkid_probe pr)
+{
+	return __blkid_probe_reset_filter(pr, BLKID_CHAIN_SUBLKS);
+}
+
+/**
+ * blkid_probe_invert_filter:
+ * @pr: prober
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ *
+ * Deprecated: Use blkid_probe_invert_superblocks_filter().
+ */
+int blkid_probe_invert_filter(blkid_probe pr)
+{
+	return __blkid_probe_invert_filter(pr, BLKID_CHAIN_SUBLKS);
+}
+
+/**
+ * blkid_probe_filter_types
+ * @pr: prober
+ * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
+ * @names: NULL terminated array of probing function names (e.g. "vfat").
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ *
+ * Deprecated: Use blkid_probe_filter_superblocks_types().
+ */
+int blkid_probe_filter_types(blkid_probe pr, int flag, char *names[])
+{
+	return __blkid_probe_filter_types(pr, BLKID_CHAIN_SUBLKS, flag, names);
+}
+
+/**
+ * blkid_probe_filter_usage
+ * @pr: prober
+ * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
+ * @usage: BLKID_USAGE_* flags
+ *
+ * Returns: 0 on success, or -1 in case of error.
+ *
+ * Deprecated: Use blkid_probe_filter_superblocks_usage().
+ */
+int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage)
+{
+	return blkid_probe_filter_superblocks_usage(pr, flag, usage);
+}
+
+
diff --git a/libblkid/src/superblocks/superblocks.h b/libblkid/src/superblocks/superblocks.h
new file mode 100644
index 0000000..3bbfb9c
--- /dev/null
+++ b/libblkid/src/superblocks/superblocks.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#ifndef _BLKID_SUPERBLOCKS_H
+#define _BLKID_SUPERBLOCKS_H
+
+#include "blkidP.h"
+
+extern const struct blkid_idinfo cramfs_idinfo;
+extern const struct blkid_idinfo swap_idinfo;
+extern const struct blkid_idinfo swsuspend_idinfo;
+extern const struct blkid_idinfo adraid_idinfo;
+extern const struct blkid_idinfo ddfraid_idinfo;
+extern const struct blkid_idinfo iswraid_idinfo;
+extern const struct blkid_idinfo jmraid_idinfo;
+extern const struct blkid_idinfo lsiraid_idinfo;
+extern const struct blkid_idinfo nvraid_idinfo;
+extern const struct blkid_idinfo pdcraid_idinfo;
+extern const struct blkid_idinfo silraid_idinfo;
+extern const struct blkid_idinfo viaraid_idinfo;
+extern const struct blkid_idinfo linuxraid_idinfo;
+extern const struct blkid_idinfo ext4dev_idinfo;
+extern const struct blkid_idinfo ext4_idinfo;
+extern const struct blkid_idinfo ext3_idinfo;
+extern const struct blkid_idinfo ext2_idinfo;
+extern const struct blkid_idinfo jbd_idinfo;
+extern const struct blkid_idinfo jfs_idinfo;
+extern const struct blkid_idinfo xfs_idinfo;
+extern const struct blkid_idinfo xfs_log_idinfo;
+extern const struct blkid_idinfo gfs_idinfo;
+extern const struct blkid_idinfo gfs2_idinfo;
+extern const struct blkid_idinfo romfs_idinfo;
+extern const struct blkid_idinfo ocfs_idinfo;
+extern const struct blkid_idinfo ocfs2_idinfo;
+extern const struct blkid_idinfo oracleasm_idinfo;
+extern const struct blkid_idinfo reiser_idinfo;
+extern const struct blkid_idinfo reiser4_idinfo;
+extern const struct blkid_idinfo hfs_idinfo;
+extern const struct blkid_idinfo hfsplus_idinfo;
+extern const struct blkid_idinfo ntfs_idinfo;
+extern const struct blkid_idinfo refs_idinfo;
+extern const struct blkid_idinfo iso9660_idinfo;
+extern const struct blkid_idinfo udf_idinfo;
+extern const struct blkid_idinfo vxfs_idinfo;
+extern const struct blkid_idinfo minix_idinfo;
+extern const struct blkid_idinfo vfat_idinfo;
+extern const struct blkid_idinfo ufs_idinfo;
+extern const struct blkid_idinfo hpfs_idinfo;
+extern const struct blkid_idinfo lvm2_idinfo;
+extern const struct blkid_idinfo lvm1_idinfo;
+extern const struct blkid_idinfo snapcow_idinfo;
+extern const struct blkid_idinfo verity_hash_idinfo;
+extern const struct blkid_idinfo luks_idinfo;
+extern const struct blkid_idinfo highpoint37x_idinfo;
+extern const struct blkid_idinfo highpoint45x_idinfo;
+extern const struct blkid_idinfo squashfs_idinfo;
+extern const struct blkid_idinfo squashfs3_idinfo;
+extern const struct blkid_idinfo netware_idinfo;
+extern const struct blkid_idinfo sysv_idinfo;
+extern const struct blkid_idinfo xenix_idinfo;
+extern const struct blkid_idinfo btrfs_idinfo;
+extern const struct blkid_idinfo ubifs_idinfo;
+extern const struct blkid_idinfo zfs_idinfo;
+extern const struct blkid_idinfo bfs_idinfo;
+extern const struct blkid_idinfo vmfs_volume_idinfo;
+extern const struct blkid_idinfo vmfs_fs_idinfo;
+extern const struct blkid_idinfo drbd_idinfo;
+extern const struct blkid_idinfo drbdproxy_datalog_idinfo;
+extern const struct blkid_idinfo befs_idinfo;
+extern const struct blkid_idinfo nilfs2_idinfo;
+extern const struct blkid_idinfo exfat_idinfo;
+extern const struct blkid_idinfo f2fs_idinfo;
+extern const struct blkid_idinfo bcache_idinfo;
+
+/*
+ * superblock functions
+ */
+extern int blkid_probe_set_version(blkid_probe pr, const char *version);
+extern int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
+		__attribute__ ((__format__ (__printf__, 2, 3)));
+
+extern int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len);
+extern int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label,
+                size_t len, int enc);
+extern int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
+                size_t len, const char *fmt, ...)
+		__attribute__ ((__format__ (__printf__, 4, 5)));
+extern int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len);
+
+extern int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid);
+extern int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name);
+
+extern int blkid_probe_set_id_label(blkid_probe pr, const char *name,
+			     unsigned char *data, size_t len);
+
+#endif /* _BLKID_SUPERBLOCKS_H */
diff --git a/libblkid/src/superblocks/swap.c b/libblkid/src/superblocks/swap.c
new file mode 100644
index 0000000..3f21391
--- /dev/null
+++ b/libblkid/src/superblocks/swap.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+/* linux-2.6/include/linux/swap.h */
+struct swap_header_v1_2 {
+     /*	char		bootbits[1024];	*/ /* Space for disklabel etc. */
+	uint32_t	version;
+	uint32_t	lastpage;
+	uint32_t	nr_badpages;
+	unsigned char	uuid[16];
+	unsigned char	volume[16];
+	uint32_t	padding[117];
+	uint32_t	badpages[1];
+} __attribute__((packed));
+
+#define PAGESIZE_MIN	0xff6	/* 4086 (arm, i386, ...) */
+#define PAGESIZE_MAX	0xfff6	/* 65526 (ia64) */
+
+#define TOI_MAGIC_STRING	"\xed\xc3\x02\xe9\x98\x56\xe5\x0c"
+#define TOI_MAGIC_STRLEN	(sizeof(TOI_MAGIC_STRING) - 1)
+
+static int swap_set_info(blkid_probe pr, const char *version)
+{
+	struct swap_header_v1_2 *hdr;
+
+	/* Swap header always located at offset of 1024 bytes */
+	hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024,
+				sizeof(struct swap_header_v1_2));
+	if (!hdr)
+		return errno ? -errno : 1;
+
+	/* SWAPSPACE2 - check for wrong version or zeroed pagecount */
+	if (strcmp(version, "1") == 0) {
+		if (hdr->version != 1 && swab32(hdr->version) != 1) {
+			DBG(LOWPROBE, ul_debug("incorrect swap version"));
+			return 1;
+		}
+		if (hdr->lastpage == 0) {
+			DBG(LOWPROBE, ul_debug("not set last swap page"));
+			return 1;
+		}
+	}
+
+	/* arbitrary sanity check.. is there any garbage down there? */
+	if (hdr->padding[32] == 0 && hdr->padding[33] == 0) {
+		if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume,
+				sizeof(hdr->volume)) < 0)
+			return 1;
+		if (blkid_probe_set_uuid(pr, hdr->uuid) < 0)
+			return 1;
+	}
+
+	blkid_probe_set_version(pr, version);
+	return 0;
+}
+
+static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	unsigned char *buf;
+
+	if (!mag)
+		return 1;
+
+	/* TuxOnIce keeps valid swap header at the end of the 1st page */
+	buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN);
+	if (!buf)
+		return errno ? -errno : 1;
+
+	if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0)
+		return 1;	/* Ignore swap signature, it's TuxOnIce */
+
+	if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) {
+		/* swap v0 doesn't support LABEL or UUID */
+		blkid_probe_set_version(pr, "0");
+		return 0;
+
+	} else if (!memcmp(mag->magic, "SWAPSPACE2", mag->len))
+		return swap_set_info(pr, "1");
+
+	return 1;
+}
+
+static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	if (!mag)
+		return 1;
+	if (!memcmp(mag->magic, "S1SUSPEND", mag->len))
+		return swap_set_info(pr, "s1suspend");
+	if (!memcmp(mag->magic, "S2SUSPEND", mag->len))
+		return swap_set_info(pr, "s2suspend");
+	if (!memcmp(mag->magic, "ULSUSPEND", mag->len))
+		return swap_set_info(pr, "ulsuspend");
+	if (!memcmp(mag->magic, TOI_MAGIC_STRING, mag->len))
+		return swap_set_info(pr, "tuxonice");
+	if (!memcmp(mag->magic, "LINHIB0001", mag->len))
+		return swap_set_info(pr, "linhib0001");
+
+	return 1;	/* no signature detected */
+}
+
+const struct blkid_idinfo swap_idinfo =
+{
+	.name		= "swap",
+	.usage		= BLKID_USAGE_OTHER,
+	.probefunc	= probe_swap,
+	.minsz		= 10 * 4096,	/* 10 pages */
+	.magics		=
+	{
+		{ "SWAP-SPACE", 10, 0,  0xff6 },
+		{ "SWAPSPACE2", 10, 0,  0xff6 },
+		{ "SWAP-SPACE", 10, 0, 0x1ff6 },
+		{ "SWAPSPACE2", 10, 0, 0x1ff6 },
+		{ "SWAP-SPACE", 10, 0, 0x3ff6 },
+		{ "SWAPSPACE2", 10, 0, 0x3ff6 },
+		{ "SWAP-SPACE", 10, 0, 0x7ff6 },
+		{ "SWAPSPACE2", 10, 0, 0x7ff6 },
+		{ "SWAP-SPACE", 10, 0, 0xfff6 },
+		{ "SWAPSPACE2", 10, 0, 0xfff6 },
+		{ NULL }
+	}
+};
+
+
+const struct blkid_idinfo swsuspend_idinfo =
+{
+	.name		= "swsuspend",
+	.usage		= BLKID_USAGE_OTHER,
+	.probefunc	= probe_swsuspend,
+	.minsz		= 10 * 4096,	/* 10 pages */
+	.magics		=
+	{
+		{ TOI_MAGIC_STRING, TOI_MAGIC_STRLEN, 0, 0 },
+		{ "S1SUSPEND", 9, 0, 0xff6 },
+		{ "S2SUSPEND", 9, 0, 0xff6 },
+		{ "ULSUSPEND", 9, 0, 0xff6 },
+		{ "LINHIB0001",10,0, 0xff6 },
+
+		{ "S1SUSPEND", 9, 0, 0x1ff6 },
+		{ "S2SUSPEND", 9, 0, 0x1ff6 },
+		{ "ULSUSPEND", 9, 0, 0x1ff6 },
+		{ "LINHIB0001",10,0, 0x1ff6 },
+
+		{ "S1SUSPEND", 9, 0, 0x3ff6 },
+		{ "S2SUSPEND", 9, 0, 0x3ff6 },
+		{ "ULSUSPEND", 9, 0, 0x3ff6 },
+		{ "LINHIB0001",10,0, 0x3ff6 },
+
+		{ "S1SUSPEND", 9, 0, 0x7ff6 },
+		{ "S2SUSPEND", 9, 0, 0x7ff6 },
+		{ "ULSUSPEND", 9, 0, 0x7ff6 },
+		{ "LINHIB0001",10,0, 0x7ff6 },
+
+		{ "S1SUSPEND", 9, 0, 0xfff6 },
+		{ "S2SUSPEND", 9, 0, 0xfff6 },
+		{ "ULSUSPEND", 9, 0, 0xfff6 },
+		{ "LINHIB0001",10,0, 0xfff6 },
+
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/sysv.c b/libblkid/src/superblocks/sysv.c
new file mode 100644
index 0000000..4b34591
--- /dev/null
+++ b/libblkid/src/superblocks/sysv.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This is written from sratch according to Linux kernel fs/sysv/super.c file.
+ * It seems that sysv probing code in libvolume_id and also in the original
+ * blkid is useless.
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "superblocks.h"
+
+#define XENIX_NICINOD				100
+#define XENIX_NICFREE				100
+
+struct xenix_super_block {
+	uint16_t	s_isize;
+	uint32_t	s_fsize;
+	uint16_t	s_nfree;
+	uint32_t	s_free[XENIX_NICFREE];
+	uint16_t	s_ninode;
+	uint16_t	s_inode[XENIX_NICINOD];
+	uint8_t		s_flock;
+	uint8_t		s_ilock;
+	uint8_t		s_fmod;
+	uint8_t		s_ronly;
+	uint32_t	s_time;
+	uint32_t	s_tfree;
+	uint16_t	s_tinode;
+	uint16_t	s_dinfo[4];
+	uint8_t		s_fname[6];
+	uint8_t		s_fpack[6];
+	uint8_t		s_clean;
+	uint8_t		s_fill[371];
+	uint32_t	s_magic;
+	uint32_t	s_type;
+} __attribute__((packed));
+
+
+#define SYSV_NICINOD			100
+#define SYSV_NICFREE			50
+
+struct sysv_super_block
+{
+	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;
+};
+
+static int probe_xenix(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct xenix_super_block *sb;
+
+	sb = blkid_probe_get_sb(pr, mag, struct xenix_super_block);
+	if (!sb)
+		return errno ? -errno : 1;
+	blkid_probe_set_label(pr, sb->s_fname, sizeof(sb->s_fname));
+	return 0;
+}
+
+#define SYSV_BLOCK_SIZE	1024
+
+/* Note that we don't probe for Coherent FS, this FS does not have
+ * magic string. (It requires to probe fname/fpack field..)
+ */
+static int probe_sysv(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct sysv_super_block *sb;
+	int blocks[] = {0, 9, 15, 18};
+	size_t i;
+
+	for (i = 0; i < ARRAY_SIZE(blocks); i++) {
+		int off = blocks[i] * SYSV_BLOCK_SIZE + SYSV_BLOCK_SIZE/2;
+
+		sb = (struct sysv_super_block *)
+			blkid_probe_get_buffer(pr,
+					off,
+					sizeof(struct sysv_super_block));
+		if (!sb)
+			return errno ? -errno : 1;
+
+		if (sb->s_magic == cpu_to_le32(0xfd187e20) ||
+		    sb->s_magic == cpu_to_be32(0xfd187e20)) {
+
+			if (blkid_probe_set_label(pr, sb->s_fname,
+						sizeof(sb->s_fname)))
+				return 1;
+
+			if (blkid_probe_set_magic(pr,
+					off + offsetof(struct sysv_super_block,
+								s_magic),
+					sizeof(sb->s_magic),
+					(unsigned char *) &sb->s_magic))
+				return 1;
+
+			return 0;
+		}
+	}
+	return 1;
+}
+
+const struct blkid_idinfo xenix_idinfo =
+{
+	.name		= "xenix",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_xenix,
+	.magics		=
+	{
+		{ .magic = "\x2b\x55\x44", .len = 3, .kboff = 1, .sboff = 0x400 },
+		{ .magic = "\x44\x55\x2b", .len = 3, .kboff = 1, .sboff = 0x400 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo sysv_idinfo =
+{
+	.name		= "sysv",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_sysv,
+
+	/* SYSV is BE and LE and superblock could be on four positions. It's
+	 * simpler to probe for the magic string by .probefunc().
+	 */
+	.magics		= BLKID_NONE_MAGIC
+};
+
diff --git a/libblkid/src/superblocks/ubifs.c b/libblkid/src/superblocks/ubifs.c
new file mode 100644
index 0000000..dc84260
--- /dev/null
+++ b/libblkid/src/superblocks/ubifs.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009 Corentin Chary <corentincj@iksaif.net>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+/*
+ * struct ubifs_ch - common header node.
+ * @magic: UBIFS node magic number (%UBIFS_NODE_MAGIC)
+ * @crc: CRC-32 checksum of the node header
+ * @sqnum: sequence number
+ * @len: full node length
+ * @node_type: node type
+ * @group_type: node group type
+ * @padding: reserved for future, zeroes
+ *
+ * Every UBIFS node starts with this common part. If the node has a key, the
+ * key always goes next.
+ */
+struct ubifs_ch {
+	uint32_t magic;
+	uint32_t crc;
+	uint64_t sqnum;
+	uint32_t len;
+	uint8_t node_type;
+	uint8_t group_type;
+	uint8_t padding[2];
+} __attribute__ ((packed));
+
+/*
+ * struct ubifs_sb_node - superblock node.
+ * @ch: common header
+ * @padding: reserved for future, zeroes
+ * @key_hash: type of hash function used in keys
+ * @key_fmt: format of the key
+ * @flags: file-system flags (%UBIFS_FLG_BIGLPT, etc)
+ * @min_io_size: minimal input/output unit size
+ * @leb_size: logical eraseblock size in bytes
+ * @leb_cnt: count of LEBs used by file-system
+ * @max_leb_cnt: maximum count of LEBs used by file-system
+ * @max_bud_bytes: maximum amount of data stored in buds
+ * @log_lebs: log size in logical eraseblocks
+ * @lpt_lebs: number of LEBs used for lprops table
+ * @orph_lebs: number of LEBs used for recording orphans
+ * @jhead_cnt: count of journal heads
+ * @fanout: tree fanout (max. number of links per indexing node)
+ * @lsave_cnt: number of LEB numbers in LPT's save table
+ * @fmt_version: UBIFS on-flash format version
+ * @default_compr: default compression algorithm (%UBIFS_COMPR_LZO, etc)
+ * @padding1: reserved for future, zeroes
+ * @rp_uid: reserve pool UID
+ * @rp_gid: reserve pool GID
+ * @rp_size: size of the reserved pool in bytes
+ * @padding2: reserved for future, zeroes
+ * @time_gran: time granularity in nanoseconds
+ * @uuid: UUID generated when the file system image was created
+ * @ro_compat_version: UBIFS R/O compatibility version
+ */
+struct ubifs_sb_node {
+	struct ubifs_ch ch;
+	uint8_t padding[2];
+	uint8_t key_hash;
+	uint8_t key_fmt;
+	uint32_t flags;
+	uint32_t min_io_size;
+	uint32_t leb_size;
+	uint32_t leb_cnt;
+	uint32_t max_leb_cnt;
+	uint64_t max_bud_bytes;
+	uint32_t log_lebs;
+	uint32_t lpt_lebs;
+	uint32_t orph_lebs;
+	uint32_t jhead_cnt;
+	uint32_t fanout;
+	uint32_t lsave_cnt;
+	uint32_t fmt_version;
+	uint16_t default_compr;
+	uint8_t padding1[2];
+	uint32_t rp_uid;
+	uint32_t rp_gid;
+	uint64_t rp_size;
+	uint32_t time_gran;
+	uint8_t uuid[16];
+	uint32_t ro_compat_version;
+	uint8_t padding2[3968];
+} __attribute__ ((packed));
+
+static int probe_ubifs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct ubifs_sb_node *sb;
+
+	sb = blkid_probe_get_sb(pr, mag, struct ubifs_sb_node);
+	if (!sb)
+		return errno ? -errno : 1;
+
+	blkid_probe_set_uuid(pr, sb->uuid);
+	blkid_probe_sprintf_version(pr, "w%dr%d",
+			le32_to_cpu(sb->fmt_version),
+			le32_to_cpu(sb->ro_compat_version));
+	return 0;
+}
+
+const struct blkid_idinfo ubifs_idinfo =
+{
+	.name		= "ubifs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ubifs,
+	.magics		=
+	{
+		{ .magic = "\x31\x18\x10\x06", .len = 4 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/udf.c b/libblkid/src/superblocks/udf.c
new file mode 100644
index 0000000..5cde3cc
--- /dev/null
+++ b/libblkid/src/superblocks/udf.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+#include "iso9660.h"
+
+struct volume_descriptor {
+	struct descriptor_tag {
+		uint16_t	id;
+		uint16_t	version;
+		uint8_t		checksum;
+		uint8_t		reserved;
+		uint16_t	serial;
+		uint16_t	crc;
+		uint16_t	crc_len;
+		uint32_t	location;
+	} __attribute__((packed)) tag;
+
+	union {
+		struct anchor_descriptor {
+			uint32_t	length;
+			uint32_t	location;
+		} __attribute__((packed)) anchor;
+
+		struct primary_descriptor {
+			uint32_t	seq_num;
+			uint32_t	desc_num;
+			struct dstring {
+				uint8_t	clen;
+				uint8_t	c[31];
+			} __attribute__((packed)) ident;
+		} __attribute__((packed)) primary;
+
+	} __attribute__((packed)) type;
+
+} __attribute__((packed));
+
+struct volume_structure_descriptor {
+	uint8_t		type;
+	uint8_t		id[5];
+	uint8_t		version;
+} __attribute__((packed));
+
+#define UDF_VSD_OFFSET			0x8000LL
+
+static int probe_udf(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	struct volume_descriptor *vd;
+	struct volume_structure_descriptor *vsd;
+	unsigned int bs;
+	unsigned int pbs[2];
+	unsigned int b;
+	unsigned int type;
+	unsigned int count;
+	unsigned int loc;
+	unsigned int i;
+
+	/* The block size of a UDF filesystem is that of the underlying
+	 * storage; we check later on for the special case of image files,
+	 * which may have the 2048-byte block size of optical media. */
+	pbs[0] = blkid_probe_get_sectorsize(pr);
+	pbs[1] = 0x800;
+
+	/* check for a Volume Structure Descriptor (VSD); each is
+	 * 2048 bytes long */
+	for (b = 0; b < 0x8000; b += 0x800) {
+		vsd = (struct volume_structure_descriptor *)
+			blkid_probe_get_buffer(pr,
+					UDF_VSD_OFFSET + b,
+					sizeof(*vsd));
+		if (!vsd)
+			return errno ? -errno : 1;
+		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 *)
+			blkid_probe_get_buffer(pr,
+					UDF_VSD_OFFSET + ((blkid_loff_t) b * 0x800),
+					sizeof(*vsd));
+		if (!vsd)
+			return errno ? -errno : 1;
+		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 (AVDP), checking block size */
+	for (i = 0; i < 2; i++) {
+		vd = (struct volume_descriptor *)
+			blkid_probe_get_buffer(pr, 256 * pbs[i], sizeof(*vd));
+		if (!vd)
+			return errno ? -errno : 1;
+
+		type = le16_to_cpu(vd->tag.id);
+		if (type == 2) /* TAG_ID_AVDP */
+			goto real_blksz;
+	}
+	return 0;
+
+real_blksz:
+	/* Use the actual block size from here on out */
+	bs = pbs[i];
+
+	/* get descriptor list address and block count */
+	count = le32_to_cpu(vd->type.anchor.length) / bs;
+	loc = le32_to_cpu(vd->type.anchor.location);
+
+	/* check if the list is usable */
+	for (b = 0; b < count; b++) {
+		vd = (struct volume_descriptor *)
+			blkid_probe_get_buffer(pr,
+					(blkid_loff_t) (loc + b) * bs,
+					sizeof(*vd));
+		if (!vd)
+			return errno ? -errno : 1;
+	}
+
+	/* Try extract all possible ISO9660 information -- if there is
+	 * usable LABEL in ISO header then use it, otherwise read UDF
+	 * specific LABEL */
+	if (probe_iso9660(pr, mag) == 0 &&
+	    __blkid_probe_lookup_value(pr, "LABEL") != NULL)
+		return 0;
+
+	/* Read UDF label */
+	for (b = 0; b < count; b++) {
+		vd = (struct volume_descriptor *)
+			blkid_probe_get_buffer(pr,
+					(blkid_loff_t) (loc + b) * bs,
+					sizeof(*vd));
+		if (!vd)
+			return errno ? -errno : 1;
+		type = le16_to_cpu(vd->tag.id);
+		if (type == 0)
+			break;
+		if (le32_to_cpu(vd->tag.location) != loc + b)
+			break;
+		if (type == 1) { /* TAG_ID_PVD */
+			uint8_t clen = vd->type.primary.ident.clen;
+
+			if (clen == 8)
+				blkid_probe_set_label(pr,
+						vd->type.primary.ident.c, 31);
+			else if (clen == 16)
+				blkid_probe_set_utf8label(pr,
+						vd->type.primary.ident.c,
+						31, BLKID_ENC_UTF16BE);
+
+			if (clen == 8 || clen == 16)
+				break;
+		}
+	}
+
+	return 0;
+}
+
+
+const struct blkid_idinfo udf_idinfo =
+{
+	.name		= "udf",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_udf,
+	.flags		= BLKID_IDINFO_TOLERANT,
+	.magics		=
+	{
+		{ .magic = "BEA01", .len = 5, .kboff = 32, .sboff = 1 },
+		{ .magic = "BOOT2", .len = 5, .kboff = 32, .sboff = 1 },
+		{ .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 },
+		{ .magic = "CDW02", .len = 5, .kboff = 32, .sboff = 1 },
+		{ .magic = "NSR02", .len = 5, .kboff = 32, .sboff = 1 },
+		{ .magic = "NSR03", .len = 5, .kboff = 32, .sboff = 1 },
+		{ .magic = "TEA01", .len = 5, .kboff = 32, .sboff = 1 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/ufs.c b/libblkid/src/superblocks/ufs.c
new file mode 100644
index 0000000..6ef2acd
--- /dev/null
+++ b/libblkid/src/superblocks/ufs.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "superblocks.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;
+	} 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];
+		} 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];
+			} fs_cstotal;
+			struct ufs_timeval {
+				int32_t		tv_sec;
+				int32_t		tv_usec;
+			} fs_time;
+			int64_t		fs_size;
+			int64_t		fs_dsize;
+			uint64_t	fs_csaddr;
+			int64_t		fs_pendingblocks;
+			int32_t		fs_pendinginodes;
+		} __attribute__((packed)) fs_u2;
+	}  fs_u11;
+	union {
+		struct {
+			int32_t		fs_sparecon[53];
+			int32_t		fs_reclaim;
+			int32_t		fs_sparecon2[1];
+			int32_t		fs_state;
+			uint32_t	fs_qbmask[2];
+			uint32_t	fs_qfmask[2];
+		} 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];
+		} 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;
+		} fs_44;
+	} fs_u2;
+	int32_t		fs_postblformat;
+	int32_t		fs_nrpos;
+	int32_t		fs_postbloff;
+	int32_t		fs_rotbloff;
+	uint32_t	fs_magic;
+	uint8_t		fs_space[1];
+} __attribute__((packed));
+
+#define UFS_MAGIC			0x00011954
+#define UFS2_MAGIC			0x19540119
+#define UFS_MAGIC_FEA			0x00195612
+#define UFS_MAGIC_LFN			0x00095014
+#define UFS_MAGIC_SEC			0x00612195
+#define UFS_MAGIC_4GB			0x05231994
+
+static int probe_ufs(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	int offsets[] = { 0, 8, 64, 256 };
+	uint32_t mags[] = {
+		UFS2_MAGIC, UFS_MAGIC, UFS_MAGIC_FEA, UFS_MAGIC_LFN,
+		UFS_MAGIC_SEC, UFS_MAGIC_4GB
+	};
+	size_t i;
+	uint32_t magic;
+	struct ufs_super_block *ufs;
+	int is_be;
+
+	for (i = 0; i < ARRAY_SIZE(offsets); i++) {
+		uint32_t magLE, magBE;
+		size_t y;
+
+		ufs = (struct ufs_super_block *)
+				blkid_probe_get_buffer(pr,
+					offsets[i] * 1024,
+					sizeof(struct ufs_super_block));
+		if (!ufs)
+			return errno ? -errno : 1;
+
+		magBE = be32_to_cpu(ufs->fs_magic);
+		magLE = le32_to_cpu(ufs->fs_magic);
+
+		for (y = 0; y < ARRAY_SIZE(mags); y++) {
+			if (magLE == mags[y] || magBE == mags[y]) {
+				magic = mags[y];
+				is_be = (magBE == mags[y]);
+				goto found;
+			}
+		}
+	}
+
+	return 1;
+
+found:
+	if (magic == UFS2_MAGIC) {
+		blkid_probe_set_version(pr, "2");
+		blkid_probe_set_label(pr, ufs->fs_u11.fs_u2.fs_volname,
+				sizeof(ufs->fs_u11.fs_u2.fs_volname));
+	} else
+		blkid_probe_set_version(pr, "1");
+	if (ufs->fs_id[0] || ufs->fs_id[1])
+	{
+		if (is_be)
+			blkid_probe_sprintf_uuid(pr,
+					 (unsigned char *) &ufs->fs_id,
+						 sizeof(ufs->fs_id),
+						 "%08x%08x",
+						 be32_to_cpu(ufs->fs_id[0]),
+						 be32_to_cpu(ufs->fs_id[1]));
+		else
+			blkid_probe_sprintf_uuid(pr,
+					 (unsigned char *) &ufs->fs_id,
+						 sizeof(ufs->fs_id),
+						 "%08x%08x",
+						 le32_to_cpu(ufs->fs_id[0]),
+						 le32_to_cpu(ufs->fs_id[1]));
+	}
+
+	if (blkid_probe_set_magic(pr,
+			(offsets[i] * 1024) +
+				offsetof(struct ufs_super_block, fs_magic),
+			sizeof(ufs->fs_magic),
+			(unsigned char *) &ufs->fs_magic))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * According to libvolume_id the UFS superblock could be on four positions.
+ * The original libblkid has checked one position (.kboff=8) only.
+ *
+ * We know four UFS magic strings and UFS could be both little-endian and
+ * big-endian. ... so we have:
+ *
+ *	4 position * 4 string * 2 version = 32 magic strings
+ *
+ * It seems simpler to check for these string in probing function that hardcode
+ * all in the .magic array.
+ */
+const struct blkid_idinfo ufs_idinfo =
+{
+	.name		= "ufs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_ufs,
+	.magics		= BLKID_NONE_MAGIC
+};
+
diff --git a/libblkid/src/superblocks/vfat.c b/libblkid/src/superblocks/vfat.c
new file mode 100644
index 0000000..f38deac
--- /dev/null
+++ b/libblkid/src/superblocks/vfat.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+/* Yucky misaligned values */
+struct vfat_super_block {
+/* 00*/	unsigned char	vs_ignored[3];
+/* 03*/	unsigned char	vs_sysid[8];
+/* 0b*/	unsigned char	vs_sector_size[2];
+/* 0d*/	uint8_t		vs_cluster_size;
+/* 0e*/	uint16_t	vs_reserved;
+/* 10*/	uint8_t		vs_fats;
+/* 11*/	unsigned char	vs_dir_entries[2];
+/* 13*/	unsigned char	vs_sectors[2];
+/* 15*/	unsigned char	vs_media;
+/* 16*/	uint16_t	vs_fat_length;
+/* 18*/	uint16_t	vs_secs_track;
+/* 1a*/	uint16_t	vs_heads;
+/* 1c*/	uint32_t	vs_hidden;
+/* 20*/	uint32_t	vs_total_sect;
+/* 24*/	uint32_t	vs_fat32_length;
+/* 28*/	uint16_t	vs_flags;
+/* 2a*/	uint8_t		vs_version[2];
+/* 2c*/	uint32_t	vs_root_cluster;
+/* 30*/	uint16_t	vs_fsinfo_sector;
+/* 32*/	uint16_t	vs_backup_boot;
+/* 34*/	uint16_t	vs_reserved2[6];
+/* 40*/	unsigned char	vs_unknown[3];
+/* 43*/	unsigned char	vs_serno[4];
+/* 47*/	unsigned char	vs_label[11];
+/* 52*/	unsigned char   vs_magic[8];
+/* 5a*/	unsigned char	vs_dummy2[0x1fe - 0x5a];
+/*1fe*/	unsigned char	vs_pmagic[2];
+} __attribute__((packed));
+
+/* Yucky misaligned values */
+struct msdos_super_block {
+/* 00*/	unsigned char	ms_ignored[3];
+/* 03*/	unsigned char	ms_sysid[8];
+/* 0b*/	unsigned char	ms_sector_size[2];
+/* 0d*/	uint8_t		ms_cluster_size;
+/* 0e*/	uint16_t	ms_reserved;
+/* 10*/	uint8_t		ms_fats;
+/* 11*/	unsigned char	ms_dir_entries[2];
+/* 13*/	unsigned char	ms_sectors[2]; /* =0 iff V3 or later */
+/* 15*/	unsigned char	ms_media;
+/* 16*/	uint16_t	ms_fat_length; /* Sectors per FAT */
+/* 18*/	uint16_t	ms_secs_track;
+/* 1a*/	uint16_t	ms_heads;
+/* 1c*/	uint32_t	ms_hidden;
+/* V3 BPB */
+/* 20*/	uint32_t	ms_total_sect; /* iff ms_sectors == 0 */
+/* V4 BPB */
+/* 24*/	unsigned char	ms_unknown[3]; /* Phys drive no., resvd, V4 sig (0x29) */
+/* 27*/	unsigned char	ms_serno[4];
+/* 2b*/	unsigned char	ms_label[11];
+/* 36*/	unsigned char   ms_magic[8];
+/* 3e*/	unsigned char	ms_dummy2[0x1fe - 0x3e];
+/*1fe*/	unsigned char	ms_pmagic[2];
+} __attribute__((packed));
+
+struct vfat_dir_entry {
+	uint8_t		name[11];
+	uint8_t		attr;
+	uint16_t	time_creat;
+	uint16_t	date_creat;
+	uint16_t	time_acc;
+	uint16_t	date_acc;
+	uint16_t	cluster_high;
+	uint16_t	time_write;
+	uint16_t	date_write;
+	uint16_t	cluster_low;
+	uint32_t	size;
+} __attribute__((packed));
+
+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];
+} __attribute__((packed));
+
+/* maximum number of clusters */
+#define FAT12_MAX 0xFF4
+#define FAT16_MAX 0xFFF4
+#define FAT32_MAX 0x0FFFFFF6
+
+#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
+
+static const char *no_name = "NO NAME    ";
+
+#define unaligned_le16(x) \
+		(((unsigned char *) x)[0] + (((unsigned char *) x)[1] << 8))
+
+/*
+ * Look for LABEL (name) in the FAT root directory.
+ */
+static unsigned char *search_fat_label(blkid_probe pr,
+				uint64_t offset, uint32_t entries)
+{
+	struct vfat_dir_entry *ent, *dir = NULL;
+	uint32_t i;
+
+	DBG(LOWPROBE, ul_debug("\tlook for label in root-dir "
+			"(entries: %d, offset: %jd)", entries, offset));
+
+	if (!blkid_probe_is_tiny(pr)) {
+		/* large disk, read whole root directory */
+		dir = (struct vfat_dir_entry *)
+			blkid_probe_get_buffer(pr,
+					offset,
+					(blkid_loff_t) entries *
+						sizeof(struct vfat_dir_entry));
+		if (!dir)
+			return NULL;
+	}
+
+	for (i = 0; i < entries; i++) {
+		/*
+		 * The root directory could be relatively large (4-16kB).
+		 * Fortunately, the LABEL is usually the first entry in the
+		 * directory. On tiny disks we call read() per entry.
+		 */
+		if (!dir)
+			ent = (struct vfat_dir_entry *)
+				blkid_probe_get_buffer(pr,
+					(blkid_loff_t) offset + (i *
+						sizeof(struct vfat_dir_entry)),
+					sizeof(struct vfat_dir_entry));
+		else
+			ent = &dir[i];
+
+		if (!ent || ent->name[0] == 0x00)
+			break;
+
+		if ((ent->name[0] == FAT_ENTRY_FREE) ||
+		    (ent->cluster_high != 0 || ent->cluster_low != 0) ||
+		    ((ent->attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
+			continue;
+
+		if ((ent->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
+		    FAT_ATTR_VOLUME_ID) {
+			DBG(LOWPROBE, ul_debug("\tfound fs LABEL at entry %d", i));
+			return ent->name;
+		}
+	}
+	return NULL;
+}
+
+static int fat_valid_superblock(const struct blkid_idmag *mag,
+			struct msdos_super_block *ms,
+			struct vfat_super_block *vs,
+			uint32_t *cluster_count, uint32_t *fat_size)
+{
+	uint16_t sector_size, dir_entries, reserved;
+	uint32_t sect_count, __fat_size, dir_size, __cluster_count, fat_length;
+	uint32_t max_count;
+
+	/* extra check for FATs without magic strings */
+	if (mag->len <= 2) {
+		/* Old floppies have a valid MBR signature */
+		if (ms->ms_pmagic[0] != 0x55 || ms->ms_pmagic[1] != 0xAA)
+			return 0;
+
+		/*
+		 * OS/2 and apparently DFSee will place a FAT12/16-like
+		 * pseudo-superblock in the first 512 bytes of non-FAT
+		 * filesystems --- at least JFS and HPFS, and possibly others.
+		 * So we explicitly check for those filesystems at the
+		 * FAT12/16 filesystem magic field identifier, and if they are
+		 * present, we rule this out as a FAT filesystem, despite the
+		 * FAT-like pseudo-header.
+		 */
+		if ((memcmp(ms->ms_magic, "JFS     ", 8) == 0) ||
+		    (memcmp(ms->ms_magic, "HPFS    ", 8) == 0))
+			return 0;
+	}
+
+	/* fat counts(Linux kernel expects at least 1 FAT table) */
+	if (!ms->ms_fats)
+		return 0;
+	if (!ms->ms_reserved)
+		return 0;
+	if (!(0xf8 <= ms->ms_media || ms->ms_media == 0xf0))
+		return 0;
+	if (!is_power_of_2(ms->ms_cluster_size))
+		return 0;
+
+	sector_size = unaligned_le16(&ms->ms_sector_size);
+	if (!is_power_of_2(sector_size) ||
+	    sector_size < 512 || sector_size > 4096)
+		return 0;
+
+	dir_entries = unaligned_le16(&ms->ms_dir_entries);
+	reserved =  le16_to_cpu(ms->ms_reserved);
+	sect_count = unaligned_le16(&ms->ms_sectors);
+
+	if (sect_count == 0)
+		sect_count = le32_to_cpu(ms->ms_total_sect);
+
+	fat_length = le16_to_cpu(ms->ms_fat_length);
+	if (fat_length == 0)
+		fat_length = le32_to_cpu(vs->vs_fat32_length);
+
+	__fat_size = fat_length * ms->ms_fats;
+	dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
+					(sector_size-1)) / sector_size;
+
+	__cluster_count = (sect_count - (reserved + __fat_size + dir_size)) /
+							ms->ms_cluster_size;
+	if (!ms->ms_fat_length && vs->vs_fat32_length)
+		max_count = FAT32_MAX;
+	else
+		max_count = __cluster_count > FAT12_MAX ? FAT16_MAX : FAT12_MAX;
+
+	if (__cluster_count > max_count)
+		return 0;
+
+	if (fat_size)
+		*fat_size = __fat_size;
+	if (cluster_count)
+		*cluster_count = __cluster_count;
+
+	return 1;	/* valid */
+}
+
+/*
+ * This function is used by MBR partition table parser to avoid
+ * misinterpretation of FAT filesystem.
+ */
+int blkid_probe_is_vfat(blkid_probe pr)
+{
+	struct vfat_super_block *vs;
+	struct msdos_super_block *ms;
+	const struct blkid_idmag *mag = NULL;
+	int rc;
+
+	rc = blkid_probe_get_idmag(pr, &vfat_idinfo, NULL, &mag);
+	if (rc < 0)
+		return rc;	/* error */
+	if (rc != BLKID_PROBE_OK || !mag)
+		return 0;
+
+	ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block);
+	if (!ms)
+		return errno ? -errno : 0;
+	vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block);
+	if (!vs)
+		return errno ? -errno : 0;
+
+	return fat_valid_superblock(mag, ms, vs, NULL, NULL);
+}
+
+/* FAT label extraction from the root directory taken from Kay
+ * Sievers's volume_id library */
+static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct vfat_super_block *vs;
+	struct msdos_super_block *ms;
+	const unsigned char *vol_label = 0;
+	unsigned char *vol_serno = NULL, vol_label_buf[11];
+	uint16_t sector_size = 0, reserved;
+	uint32_t cluster_count, fat_size;
+	const char *version = NULL;
+
+	ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block);
+	if (!ms)
+		return errno ? -errno : 1;
+
+	vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block);
+	if (!vs)
+		return errno ? -errno : 1;
+
+	if (!fat_valid_superblock(mag, ms, vs, &cluster_count, &fat_size))
+		return 1;
+
+	sector_size = unaligned_le16(&ms->ms_sector_size);
+	reserved =  le16_to_cpu(ms->ms_reserved);
+
+	if (ms->ms_fat_length) {
+		/* the label may be an attribute in the root directory */
+		uint32_t root_start = (reserved + fat_size) * sector_size;
+		uint32_t root_dir_entries = unaligned_le16(&vs->vs_dir_entries);
+
+		vol_label = search_fat_label(pr, root_start, root_dir_entries);
+		if (vol_label) {
+			memcpy(vol_label_buf, vol_label, 11);
+			vol_label = vol_label_buf;
+		}
+
+		if (!vol_label || !memcmp(vol_label, no_name, 11))
+			vol_label = ms->ms_label;
+		vol_serno = ms->ms_serno;
+
+		blkid_probe_set_value(pr, "SEC_TYPE", (unsigned char *) "msdos",
+                              sizeof("msdos"));
+
+		if (cluster_count < FAT12_MAX)
+			version = "FAT12";
+		else if (cluster_count < FAT16_MAX)
+			version = "FAT16";
+
+	} else if (vs->vs_fat32_length) {
+		unsigned char *buf;
+		uint16_t fsinfo_sect;
+		int maxloop = 100;
+
+		/* Search the FAT32 root dir for the label attribute */
+		uint32_t buf_size = vs->vs_cluster_size * sector_size;
+		uint32_t start_data_sect = reserved + fat_size;
+		uint32_t entries = le32_to_cpu(vs->vs_fat32_length) *
+					sector_size / sizeof(uint32_t);
+		uint32_t next = le32_to_cpu(vs->vs_root_cluster);
+
+		while (next && next < entries && --maxloop) {
+			uint32_t next_sect_off;
+			uint64_t next_off, fat_entry_off;
+			int count;
+
+			next_sect_off = (next - 2) * vs->vs_cluster_size;
+			next_off = (uint64_t)(start_data_sect + next_sect_off) *
+				sector_size;
+
+			count = buf_size / sizeof(struct vfat_dir_entry);
+
+			vol_label = search_fat_label(pr, next_off, count);
+			if (vol_label) {
+				memcpy(vol_label_buf, vol_label, 11);
+				vol_label = vol_label_buf;
+				break;
+			}
+
+			/* get FAT entry */
+			fat_entry_off = ((uint64_t) reserved * sector_size) +
+				(next * sizeof(uint32_t));
+			buf = blkid_probe_get_buffer(pr, fat_entry_off, buf_size);
+			if (buf == NULL)
+				break;
+
+			/* set next cluster */
+			next = le32_to_cpu(*((uint32_t *) buf)) & 0x0fffffff;
+		}
+
+		version = "FAT32";
+
+		if (!vol_label || !memcmp(vol_label, no_name, 11))
+			vol_label = vs->vs_label;
+		vol_serno = vs->vs_serno;
+
+		/*
+		 * 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->vs_fsinfo_sector);
+		if (fsinfo_sect) {
+			struct fat32_fsinfo *fsinfo;
+
+			buf = blkid_probe_get_buffer(pr,
+					(blkid_loff_t) fsinfo_sect * sector_size,
+					sizeof(struct fat32_fsinfo));
+			if (buf == NULL)
+				return errno ? -errno : 1;
+
+			fsinfo = (struct fat32_fsinfo *) buf;
+			if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 &&
+			    memcmp(fsinfo->signature1, "\x52\x52\x64\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;
+		}
+	}
+
+	if (vol_label && memcmp(vol_label, no_name, 11))
+		blkid_probe_set_label(pr, (unsigned char *) vol_label, 11);
+
+	/* We can't just print them as %04X, because they are unaligned */
+	if (vol_serno)
+		blkid_probe_sprintf_uuid(pr, vol_serno, 4, "%02X%02X-%02X%02X",
+			vol_serno[3], vol_serno[2], vol_serno[1], vol_serno[0]);
+	if (version)
+		blkid_probe_set_version(pr, version);
+
+	return 0;
+}
+
+
+const struct blkid_idinfo vfat_idinfo =
+{
+	.name		= "vfat",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_vfat,
+	.magics		=
+	{
+		{ .magic = "MSWIN",    .len = 5, .sboff = 0x52 },
+		{ .magic = "FAT32   ", .len = 8, .sboff = 0x52 },
+		{ .magic = "MSDOS",    .len = 5, .sboff = 0x36 },
+		{ .magic = "FAT16   ", .len = 8, .sboff = 0x36 },
+		{ .magic = "FAT12   ", .len = 8, .sboff = 0x36 },
+		{ .magic = "FAT     ", .len = 8, .sboff = 0x36 },
+		{ .magic = "\353",     .len = 1, },
+		{ .magic = "\351",     .len = 1, },
+		{ .magic = "\125\252", .len = 2, .sboff = 0x1fe },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/via_raid.c b/libblkid/src/superblocks/via_raid.c
new file mode 100644
index 0000000..ee3ab65
--- /dev/null
+++ b/libblkid/src/superblocks/via_raid.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * Inspired by libvolume_id by
+ *     Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct via_metadata {
+	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;
+	} __attribute__((packed)) array;
+	uint32_t	serial_checksum[8];
+	uint8_t		checksum;
+} __attribute__((packed));
+
+#define VIA_SIGNATURE		0xAA55
+
+/* 8 bit checksum on first 50 bytes of metadata. */
+static uint8_t via_checksum(struct via_metadata *v)
+{
+	uint8_t i = 50, cs = 0;
+
+	while (i--)
+		cs += ((uint8_t*) v)[i];
+
+	return cs;
+}
+
+static int probe_viaraid(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	uint64_t off;
+	struct via_metadata *v;
+
+	if (pr->size < 0x10000)
+		return 1;
+	if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+		return 1;
+
+	off = ((pr->size / 0x200)-1) * 0x200;
+
+	v = (struct via_metadata *)
+			blkid_probe_get_buffer(pr,
+				off,
+				sizeof(struct via_metadata));
+	if (!v)
+		return errno ? -errno : 1;
+
+	if (le16_to_cpu(v->signature) != VIA_SIGNATURE)
+		return 1;
+	if (v->version_number > 2)
+		return 1;
+	if (!blkid_probe_verify_csum(pr, via_checksum(v), v->checksum))
+		return 1;
+
+	if (blkid_probe_sprintf_version(pr, "%u", v->version_number) != 0)
+		return 1;
+	if (blkid_probe_set_magic(pr, off,
+				sizeof(v->signature),
+				(unsigned char *) &v->signature))
+		return 1;
+	return 0;
+}
+
+const struct blkid_idinfo viaraid_idinfo = {
+	.name		= "via_raid_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_viaraid,
+	.magics		= BLKID_NONE_MAGIC
+};
+
+
diff --git a/libblkid/src/superblocks/vmfs.c b/libblkid/src/superblocks/vmfs.c
new file mode 100644
index 0000000..fac87ab
--- /dev/null
+++ b/libblkid/src/superblocks/vmfs.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009 Mike Hommey <mh@glandium.org>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include "superblocks.h"
+
+struct vmfs_fs_info {
+	uint32_t magic;
+	uint32_t volume_version;
+	uint8_t version;
+	uint8_t uuid[16];
+	uint32_t mode;
+	char label[128];
+} __attribute__ ((__packed__));
+
+struct vmfs_volume_info {
+	uint32_t magic;
+	uint32_t ver;
+	uint8_t irrelevant[122];
+	uint8_t uuid[16];
+} __attribute__ ((__packed__));
+
+static int probe_vmfs_fs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct vmfs_fs_info *header;
+
+	header = blkid_probe_get_sb(pr, mag, struct vmfs_fs_info);
+	if (header == NULL)
+		return errno ? -errno : 1;
+
+	blkid_probe_sprintf_uuid(pr, (unsigned char *) header->uuid, 16,
+		"%02x%02x%02x%02x-%02x%02x%02x%02x-"
+		"%02x%02x-%02x%02x%02x%02x%02x%02x",
+		header->uuid[3], header->uuid[2], header->uuid[1],
+		header->uuid[0], header->uuid[7], header->uuid[6],
+		header->uuid[5], header->uuid[4], header->uuid[9],
+		header->uuid[8], header->uuid[10], header->uuid[11],
+		header->uuid[12], header->uuid[13], header->uuid[14],
+		header->uuid[15]);
+
+	blkid_probe_set_label(pr, (unsigned char *) header->label,
+					sizeof(header->label));
+	blkid_probe_sprintf_version(pr, "%u", header->version);
+	return 0;
+}
+
+static int probe_vmfs_volume(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct vmfs_volume_info *header;
+	unsigned char *lvm_uuid;
+
+	header = blkid_probe_get_sb(pr, mag, struct vmfs_volume_info);
+	if (header == NULL)
+		return errno ? -errno : 1;
+
+	blkid_probe_sprintf_value(pr, "UUID_SUB",
+		"%02x%02x%02x%02x-%02x%02x%02x%02x-"
+		"%02x%02x-%02x%02x%02x%02x%02x%02x",
+		header->uuid[3], header->uuid[2], header->uuid[1],
+		header->uuid[0], header->uuid[7], header->uuid[6],
+		header->uuid[5], header->uuid[4], header->uuid[9],
+		header->uuid[8], header->uuid[10], header->uuid[11],
+		header->uuid[12], header->uuid[13], header->uuid[14],
+		header->uuid[15]);
+	blkid_probe_sprintf_version(pr, "%u", le32_to_cpu(header->ver));
+
+	lvm_uuid = blkid_probe_get_buffer(pr,
+				1024 * 1024 /* Start of the volume info */
+				+ 512 /* Offset to lvm info */
+				+ 20 /* Offset in lvm info */, 35);
+	if (lvm_uuid)
+		blkid_probe_strncpy_uuid(pr, lvm_uuid, 35);
+
+	return 0;
+}
+
+const struct blkid_idinfo vmfs_fs_idinfo =
+{
+	.name		= "VMFS",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_vmfs_fs,
+	.magics		=
+	{
+		{ .magic = "\x5e\xf1\xab\x2f", .len = 4, .kboff = 2048 },
+		{ NULL }
+	}
+};
+
+const struct blkid_idinfo vmfs_volume_idinfo =
+{
+	.name		= "VMFS_volume_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_vmfs_volume,
+	.magics		=
+	{
+		{ .magic = "\x0d\xd0\x01\xc0", .len = 4, .kboff = 1024 },
+		{ NULL }
+	}
+};
diff --git a/libblkid/src/superblocks/vxfs.c b/libblkid/src/superblocks/vxfs.c
new file mode 100644
index 0000000..19d284c
--- /dev/null
+++ b/libblkid/src/superblocks/vxfs.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+
+#include "superblocks.h"
+
+struct vxfs_super_block {
+	uint32_t		vs_magic;
+	int32_t			vs_version;
+};
+
+static int probe_vxfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct vxfs_super_block *vxs;
+
+	vxs = blkid_probe_get_sb(pr, mag, struct vxfs_super_block);
+	if (!vxs)
+		return errno ? -errno : 1;
+
+	blkid_probe_sprintf_version(pr, "%u", (unsigned int) vxs->vs_version);
+	return 0;
+}
+
+
+const struct blkid_idinfo vxfs_idinfo =
+{
+	.name		= "vxfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_vxfs,
+	.magics		=
+	{
+		{ .magic = "\365\374\001\245", .len = 4, .kboff = 1 },
+		{ NULL }
+	}
+};
+
diff --git a/libblkid/src/superblocks/xfs.c b/libblkid/src/superblocks/xfs.c
new file mode 100644
index 0000000..a6c04a2
--- /dev/null
+++ b/libblkid/src/superblocks/xfs.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ * Copyright (C) 2013 Eric Sandeen <sandeen@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "superblocks.h"
+
+struct xfs_super_block {
+	uint32_t	sb_magicnum;	/* magic number == XFS_SB_MAGIC */
+	uint32_t	sb_blocksize;	/* logical block size, bytes */
+	uint64_t	sb_dblocks;	/* number of data blocks */
+	uint64_t	sb_rblocks;	/* number of realtime blocks */
+	uint64_t	sb_rextents;	/* number of realtime extents */
+	unsigned char	sb_uuid[16];	/* file system unique id */
+	uint64_t	sb_logstart;	/* starting block of log if internal */
+	uint64_t	sb_rootino;	/* root inode number */
+	uint64_t	sb_rbmino;	/* bitmap inode for realtime extents */
+	uint64_t	sb_rsumino;	/* summary inode for rt bitmap */
+	uint32_t	sb_rextsize;	/* realtime extent size, blocks */
+	uint32_t	sb_agblocks;	/* size of an allocation group */
+	uint32_t	sb_agcount;	/* number of allocation groups */
+	uint32_t	sb_rbmblocks;	/* number of rt bitmap blocks */
+	uint32_t	sb_logblocks;	/* number of log blocks */
+
+	uint16_t	sb_versionnum;	/* header version == XFS_SB_VERSION */
+	uint16_t	sb_sectsize;	/* volume sector size, bytes */
+	uint16_t	sb_inodesize;	/* inode size, bytes */
+	uint16_t	sb_inopblock;	/* inodes per block */
+	char		sb_fname[12];	/* file system name */
+	uint8_t		sb_blocklog;	/* log2 of sb_blocksize */
+	uint8_t		sb_sectlog;	/* log2 of sb_sectsize */
+	uint8_t		sb_inodelog;	/* log2 of sb_inodesize */
+	uint8_t		sb_inopblog;	/* log2 of sb_inopblock */
+	uint8_t		sb_agblklog;	/* log2 of sb_agblocks (rounded up) */
+	uint8_t		sb_rextslog;	/* log2 of sb_rextents */
+	uint8_t		sb_inprogress;	/* mkfs is in progress, don't mount */
+	uint8_t		sb_imax_pct;	/* max % of fs for inode space */
+					/* statistics */
+	uint64_t	sb_icount;	/* allocated inodes */
+	uint64_t	sb_ifree;	/* free inodes */
+	uint64_t	sb_fdblocks;	/* free data blocks */
+	uint64_t	sb_frextents;	/* free realtime extents */
+
+	/* this is not all... but enough for libblkid */
+
+} __attribute__((packed));
+
+#define XFS_MIN_BLOCKSIZE_LOG	9	/* i.e. 512 bytes */
+#define XFS_MAX_BLOCKSIZE_LOG	16	/* i.e. 65536 bytes */
+#define XFS_MIN_BLOCKSIZE	(1 << XFS_MIN_BLOCKSIZE_LOG)
+#define XFS_MAX_BLOCKSIZE	(1 << XFS_MAX_BLOCKSIZE_LOG)
+#define XFS_MIN_SECTORSIZE_LOG	9	/* i.e. 512 bytes */
+#define XFS_MAX_SECTORSIZE_LOG	15	/* i.e. 32768 bytes */
+#define XFS_MIN_SECTORSIZE	(1 << XFS_MIN_SECTORSIZE_LOG)
+#define XFS_MAX_SECTORSIZE	(1 << XFS_MAX_SECTORSIZE_LOG)
+
+#define	XFS_DINODE_MIN_LOG	8
+#define	XFS_DINODE_MAX_LOG	11
+#define	XFS_DINODE_MIN_SIZE	(1 << XFS_DINODE_MIN_LOG)
+#define	XFS_DINODE_MAX_SIZE	(1 << XFS_DINODE_MAX_LOG)
+
+#define	XFS_MAX_RTEXTSIZE	(1024 * 1024 * 1024)	/* 1GB */
+#define	XFS_DFL_RTEXTSIZE	(64 * 1024)	        /* 64kB */
+#define	XFS_MIN_RTEXTSIZE	(4 * 1024)		/* 4kB */
+
+#define XFS_MIN_AG_BLOCKS	64
+#define XFS_MAX_DBLOCKS(s) ((uint64_t)(s)->sb_agcount * (s)->sb_agblocks)
+#define XFS_MIN_DBLOCKS(s) ((uint64_t)((s)->sb_agcount - 1) *	\
+			 (s)->sb_agblocks + XFS_MIN_AG_BLOCKS)
+
+
+static void sb_from_disk(struct xfs_super_block *from,
+			 struct xfs_super_block *to)
+{
+
+	to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
+	to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
+	to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
+	to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
+	to->sb_rextents = be64_to_cpu(from->sb_rextents);
+	to->sb_logstart = be64_to_cpu(from->sb_logstart);
+	to->sb_rootino = be64_to_cpu(from->sb_rootino);
+	to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
+	to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
+	to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
+	to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
+	to->sb_agcount = be32_to_cpu(from->sb_agcount);
+	to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
+	to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
+	to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
+	to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
+	to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
+	to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
+	to->sb_blocklog = from->sb_blocklog;
+	to->sb_sectlog = from->sb_sectlog;
+	to->sb_inodelog = from->sb_inodelog;
+	to->sb_inopblog = from->sb_inopblog;
+	to->sb_agblklog = from->sb_agblklog;
+	to->sb_rextslog = from->sb_rextslog;
+	to->sb_inprogress = from->sb_inprogress;
+	to->sb_imax_pct = from->sb_imax_pct;
+	to->sb_icount = be64_to_cpu(from->sb_icount);
+	to->sb_ifree = be64_to_cpu(from->sb_ifree);
+	to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
+	to->sb_frextents = be64_to_cpu(from->sb_frextents);
+}
+
+static int xfs_verify_sb(struct xfs_super_block *ondisk)
+{
+	struct xfs_super_block sb, *sbp = &sb;
+
+	/* beXX_to_cpu(), but don't convert UUID and fsname! */
+	sb_from_disk(ondisk, sbp);
+
+	/* sanity checks, we don't want to rely on magic string only */
+	if (sbp->sb_agcount <= 0					||
+	    sbp->sb_sectsize < XFS_MIN_SECTORSIZE			||
+	    sbp->sb_sectsize > XFS_MAX_SECTORSIZE			||
+	    sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG			||
+	    sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG			||
+	    sbp->sb_sectsize != (1 << sbp->sb_sectlog)			||
+	    sbp->sb_blocksize < XFS_MIN_BLOCKSIZE			||
+	    sbp->sb_blocksize > XFS_MAX_BLOCKSIZE			||
+	    sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG			||
+	    sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG			||
+	    sbp->sb_blocksize != (1 << sbp->sb_blocklog)		||
+	    sbp->sb_inodesize < XFS_DINODE_MIN_SIZE			||
+	    sbp->sb_inodesize > XFS_DINODE_MAX_SIZE			||
+	    sbp->sb_inodelog < XFS_DINODE_MIN_LOG			||
+	    sbp->sb_inodelog > XFS_DINODE_MAX_LOG			||
+	    sbp->sb_inodesize != (1 << sbp->sb_inodelog)		||
+	    (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog)	||
+	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
+	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
+	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */)	||
+	    sbp->sb_dblocks == 0					||
+	    sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp)			||
+	    sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))
+		return 0;
+
+	/* TODO: version 5 has also checksum CRC32, maybe we can check it too */
+
+	return 1;
+}
+
+static int probe_xfs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	struct xfs_super_block *xs;
+
+	xs = blkid_probe_get_sb(pr, mag, struct xfs_super_block);
+	if (!xs)
+		return errno ? -errno : 1;
+
+	if (!xfs_verify_sb(xs))
+		return 1;
+
+	if (strlen(xs->sb_fname))
+		blkid_probe_set_label(pr, (unsigned char *) xs->sb_fname,
+				sizeof(xs->sb_fname));
+	blkid_probe_set_uuid(pr, xs->sb_uuid);
+	return 0;
+}
+
+const struct blkid_idinfo xfs_idinfo =
+{
+	.name		= "xfs",
+	.usage		= BLKID_USAGE_FILESYSTEM,
+	.probefunc	= probe_xfs,
+	.magics		=
+	{
+		{ .magic = "XFSB", .len = 4 },
+		{ NULL }
+	}
+};
+
+struct xlog_rec_header {
+	uint32_t	h_magicno;
+	uint32_t	h_dummy1[1];
+	uint32_t	h_version;
+	uint32_t	h_len;
+	uint32_t	h_dummy2[71];
+	uint32_t	h_fmt;
+	unsigned char	h_uuid[16];
+} __attribute__((packed));
+
+#define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe
+
+/*
+ * For very small filesystems, the minimum log size
+ * can be smaller, but that seems vanishingly unlikely
+ * when used with an external log (which is used for
+ * performance reasons; tiny conflicts with that goal).
+ */
+#define XFS_MIN_LOG_BYTES	(10 * 1024 * 1024)
+
+#define XLOG_FMT_LINUX_LE	1
+#define XLOG_FMT_LINUX_BE	2
+#define XLOG_FMT_IRIX_BE	3
+
+#define XLOG_VERSION_1		1
+#define XLOG_VERSION_2		2	/* Large IClogs, Log sunit */
+#define XLOG_VERSION_OKBITS	(XLOG_VERSION_1 | XLOG_VERSION_2)
+
+static int xlog_valid_rec_header(struct xlog_rec_header *rhead)
+{
+	uint32_t hlen;
+
+	if (rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM))
+		return 0;
+
+	if (!rhead->h_version ||
+            (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS)))
+		return 0;
+
+	/* LR body must have data or it wouldn't have been written */
+	hlen = be32_to_cpu(rhead->h_len);
+	if (hlen <= 0 || hlen > INT_MAX)
+		return 0;
+
+	if (rhead->h_fmt != cpu_to_be32(XLOG_FMT_LINUX_LE) &&
+	    rhead->h_fmt != cpu_to_be32(XLOG_FMT_LINUX_BE) &&
+	    rhead->h_fmt != cpu_to_be32(XLOG_FMT_IRIX_BE))
+		return 0;
+
+	return 1;
+}
+
+/* xlog record header will be in some sector in the first 256k */
+static int probe_xfs_log(blkid_probe pr, const struct blkid_idmag *mag)
+{
+	int i;
+	struct xlog_rec_header *rhead;
+	unsigned char *buf;
+
+	buf = blkid_probe_get_buffer(pr, 0, 256*1024);
+	if (!buf)
+		return errno ? -errno : 1;
+
+	if (memcmp(buf, "XFSB", 4) == 0)
+		return 1;			/* this is regular XFS, ignore */
+
+	/* check the first 512 512-byte sectors */
+	for (i = 0; i < 512; i++) {
+		rhead = (struct xlog_rec_header *)&buf[i*512];
+
+		if (xlog_valid_rec_header(rhead)) {
+			blkid_probe_set_uuid_as(pr, rhead->h_uuid, "LOGUUID");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+const struct blkid_idinfo xfs_log_idinfo =
+{
+	.name		= "xfs_external_log",
+	.usage		= BLKID_USAGE_OTHER,
+	.probefunc	= probe_xfs_log,
+	.magics		= BLKID_NONE_MAGIC,
+	.minsz		= XFS_MIN_LOG_BYTES,
+};
diff --git a/libblkid/src/superblocks/zfs.c b/libblkid/src/superblocks/zfs.c
new file mode 100644
index 0000000..86da59d
--- /dev/null
+++ b/libblkid/src/superblocks/zfs.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2009-2010 by Andreas Dilger <adilger@sun.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+
+#include "superblocks.h"
+
+#define VDEV_LABEL_UBERBLOCK	(128 * 1024ULL)
+#define VDEV_LABEL_NVPAIR	( 16 * 1024ULL)
+#define VDEV_LABEL_SIZE		(256 * 1024ULL)
+
+/* #include <sys/uberblock_impl.h> */
+#define UBERBLOCK_MAGIC         0x00bab10c              /* oo-ba-bloc!  */
+struct zfs_uberblock {
+	uint64_t	ub_magic;	/* UBERBLOCK_MAGIC		*/
+	uint64_t	ub_version;	/* SPA_VERSION			*/
+	uint64_t	ub_txg;		/* txg of last sync		*/
+	uint64_t	ub_guid_sum;	/* sum of all vdev guids	*/
+	uint64_t	ub_timestamp;	/* UTC time of last sync	*/
+	char		ub_rootbp;	/* MOS objset_phys_t		*/
+} __attribute__((packed));
+
+#define ZFS_TRIES	64
+#define ZFS_WANT	 4
+
+#define DATA_TYPE_UINT64 8
+#define DATA_TYPE_STRING 9
+
+struct nvpair {
+	uint32_t	nvp_size;
+	uint32_t	nvp_unkown;
+	uint32_t	nvp_namelen;
+	char		nvp_name[0]; /* aligned to 4 bytes */
+	/* aligned ptr array for string arrays */
+	/* aligned array of data for value */
+};
+
+struct nvstring {
+	uint32_t	nvs_type;
+	uint32_t	nvs_elem;
+	uint32_t	nvs_strlen;
+	unsigned char	nvs_string[0];
+};
+
+struct nvuint64 {
+	uint32_t	nvu_type;
+	uint32_t	nvu_elem;
+	uint64_t	nvu_value;
+};
+
+struct nvlist {
+	uint32_t	nvl_unknown[3];
+	struct nvpair	nvl_nvpair;
+};
+
+#define nvdebug(fmt, ...)	do { } while(0)
+/*#define nvdebug(fmt, a...)	fprintf(stderr, fmt, ##a)*/
+
+static void zfs_extract_guid_name(blkid_probe pr, loff_t offset)
+{
+	struct nvlist *nvl;
+	struct nvpair *nvp;
+	size_t left = 4096;
+	int found = 0;
+
+	offset = (offset & ~(VDEV_LABEL_SIZE - 1)) + VDEV_LABEL_NVPAIR;
+
+	/* Note that we currently assume that the desired fields are within
+	 * the first 4k (left) of the nvlist.  This is true for all pools
+	 * I've seen, and simplifies this code somewhat, because we don't
+	 * have to handle an nvpair crossing a buffer boundary. */
+	nvl = (struct nvlist *)blkid_probe_get_buffer(pr, offset, left);
+	if (nvl == NULL)
+		return;
+
+	nvdebug("zfs_extract: nvlist offset %llu\n", offset);
+
+	nvp = &nvl->nvl_nvpair;
+	while (left > sizeof(*nvp) && nvp->nvp_size != 0 && found < 3) {
+		int avail;   /* tracks that name/value data fits in nvp_size */
+		int namesize;
+
+		nvp->nvp_size = be32_to_cpu(nvp->nvp_size);
+		nvp->nvp_namelen = be32_to_cpu(nvp->nvp_namelen);
+		avail = nvp->nvp_size - nvp->nvp_namelen - sizeof(*nvp);
+
+		nvdebug("left %zd nvp_size %u\n", left, nvp->nvp_size);
+		if (left < nvp->nvp_size || avail < 0)
+			break;
+
+		namesize = (nvp->nvp_namelen + 3) & ~3;
+
+		nvdebug("nvlist: size %u, namelen %u, name %*s\n",
+			nvp->nvp_size, nvp->nvp_namelen, nvp->nvp_namelen,
+			nvp->nvp_name);
+		if (strncmp(nvp->nvp_name, "name", nvp->nvp_namelen) == 0) {
+			struct nvstring *nvs = (void *)(nvp->nvp_name+namesize);
+
+			nvs->nvs_type = be32_to_cpu(nvs->nvs_type);
+			nvs->nvs_strlen = be32_to_cpu(nvs->nvs_strlen);
+			if (nvs->nvs_strlen > UINT_MAX - sizeof(*nvs))
+				break;
+			avail -= nvs->nvs_strlen + sizeof(*nvs);
+			nvdebug("nvstring: type %u string %*s\n", nvs->nvs_type,
+				nvs->nvs_strlen, nvs->nvs_string);
+			if (nvs->nvs_type == DATA_TYPE_STRING && avail >= 0)
+				blkid_probe_set_label(pr, nvs->nvs_string,
+						      nvs->nvs_strlen);
+			found++;
+		} else if (strncmp(nvp->nvp_name, "guid",
+				   nvp->nvp_namelen) == 0) {
+			struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize);
+			uint64_t nvu_value;
+
+			memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value));
+			nvu->nvu_type = be32_to_cpu(nvu->nvu_type);
+			nvu_value = be64_to_cpu(nvu_value);
+			avail -= sizeof(*nvu);
+			nvdebug("nvuint64: type %u value %"PRIu64"\n",
+				nvu->nvu_type, nvu_value);
+			if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0)
+				blkid_probe_sprintf_value(pr, "UUID_SUB",
+							  "%"PRIu64, nvu_value);
+			found++;
+		} else if (strncmp(nvp->nvp_name, "pool_guid",
+				   nvp->nvp_namelen) == 0) {
+			struct nvuint64 *nvu = (void *)(nvp->nvp_name+namesize);
+			uint64_t nvu_value;
+
+			memcpy(&nvu_value, &nvu->nvu_value, sizeof(nvu_value));
+			nvu->nvu_type = be32_to_cpu(nvu->nvu_type);
+			nvu_value = be64_to_cpu(nvu_value);
+			avail -= sizeof(*nvu);
+			nvdebug("nvuint64: type %u value %"PRIu64"\n",
+				nvu->nvu_type, nvu_value);
+			if (nvu->nvu_type == DATA_TYPE_UINT64 && avail >= 0)
+				blkid_probe_sprintf_uuid(pr, (unsigned char *)
+							 &nvu_value,
+							 sizeof(nvu_value),
+							 "%"PRIu64, nvu_value);
+			found++;
+		}
+		if (left > nvp->nvp_size)
+			left -= nvp->nvp_size;
+		else
+			left = 0;
+		nvp = (struct nvpair *)((char *)nvp + nvp->nvp_size);
+	}
+}
+
+#define zdebug(fmt, ...)	do {} while(0)
+/*#define zdebug(fmt, a...)	fprintf(stderr, fmt, ##a)*/
+
+/* ZFS has 128x1kB host-endian root blocks, stored in 2 areas at the start
+ * of the disk, and 2 areas at the end of the disk.  Check only some of them...
+ * #4 (@ 132kB) is the first one written on a new filesystem. */
+static int probe_zfs(blkid_probe pr,
+		const struct blkid_idmag *mag __attribute__((__unused__)))
+{
+	uint64_t swab_magic = swab64(UBERBLOCK_MAGIC);
+	struct zfs_uberblock *ub;
+	int swab_endian;
+	loff_t offset, ub_offset = 0;
+	int tried;
+	int found;
+
+	zdebug("probe_zfs\n");
+	/* Look for at least 4 uberblocks to ensure a positive match */
+	for (tried = found = 0, offset = VDEV_LABEL_UBERBLOCK;
+	     tried < ZFS_TRIES && found < ZFS_WANT;
+	     tried++, offset += 4096) {
+		/* also try the second uberblock copy */
+		if (tried == (ZFS_TRIES / 2))
+			offset = VDEV_LABEL_SIZE + VDEV_LABEL_UBERBLOCK;
+
+		ub = (struct zfs_uberblock *)
+			blkid_probe_get_buffer(pr, offset,
+					       sizeof(struct zfs_uberblock));
+		if (ub == NULL)
+			return errno ? -errno : 1;
+
+		if (ub->ub_magic == UBERBLOCK_MAGIC) {
+			ub_offset = offset;
+			found++;
+		}
+
+		if ((swab_endian = (ub->ub_magic == swab_magic))) {
+			ub_offset = offset;
+			found++;
+		}
+
+		zdebug("probe_zfs: found %s-endian uberblock at %llu\n",
+		       swab_endian ? "big" : "little", offset >> 10);
+	}
+
+	if (found < 4)
+		return 1;
+
+	/* If we found the 4th uberblock, then we will have exited from the
+	 * scanning loop immediately, and ub will be a valid uberblock. */
+	blkid_probe_sprintf_version(pr, "%" PRIu64, swab_endian ?
+				    swab64(ub->ub_version) : ub->ub_version);
+
+	zfs_extract_guid_name(pr, offset);
+
+	if (blkid_probe_set_magic(pr, ub_offset,
+				sizeof(ub->ub_magic),
+				(unsigned char *) &ub->ub_magic))
+		return 1;
+
+	return 0;
+}
+
+const struct blkid_idinfo zfs_idinfo =
+{
+	.name		= "zfs_member",
+	.usage		= BLKID_USAGE_RAID,
+	.probefunc	= probe_zfs,
+	.minsz		= 64 * 1024 * 1024,
+	.magics		= BLKID_NONE_MAGIC
+};
+