summaryrefslogtreecommitdiff
path: root/shlibs/blkid/src/superblocks
diff options
context:
space:
mode:
Diffstat (limited to 'shlibs/blkid/src/superblocks')
-rw-r--r--shlibs/blkid/src/superblocks/Makefile.am4
-rw-r--r--shlibs/blkid/src/superblocks/adaptec_raid.c3
-rw-r--r--shlibs/blkid/src/superblocks/ddf_raid.c71
-rw-r--r--shlibs/blkid/src/superblocks/exfat.c146
-rw-r--r--shlibs/blkid/src/superblocks/hfs.c1
-rw-r--r--shlibs/blkid/src/superblocks/highpoint_raid.c11
-rw-r--r--shlibs/blkid/src/superblocks/isw_raid.c2
-rw-r--r--shlibs/blkid/src/superblocks/jmicron_raid.c2
-rw-r--r--shlibs/blkid/src/superblocks/linux_raid.c124
-rw-r--r--shlibs/blkid/src/superblocks/lsi_raid.c2
-rw-r--r--shlibs/blkid/src/superblocks/nilfs.c120
-rw-r--r--shlibs/blkid/src/superblocks/nvidia_raid.c2
-rw-r--r--shlibs/blkid/src/superblocks/promise_raid.c2
-rw-r--r--shlibs/blkid/src/superblocks/silicon_raid.c2
-rw-r--r--shlibs/blkid/src/superblocks/superblocks.c120
-rw-r--r--shlibs/blkid/src/superblocks/superblocks.h2
-rw-r--r--shlibs/blkid/src/superblocks/udf.c3
-rw-r--r--shlibs/blkid/src/superblocks/via_raid.c2
18 files changed, 492 insertions, 127 deletions
diff --git a/shlibs/blkid/src/superblocks/Makefile.am b/shlibs/blkid/src/superblocks/Makefile.am
index f5b88b8e..1501fab1 100644
--- a/shlibs/blkid/src/superblocks/Makefile.am
+++ b/shlibs/blkid/src/superblocks/Makefile.am
@@ -46,4 +46,6 @@ libblkid_superblocks_la_SOURCES = \
bfs.c \
drbd.c \
vmfs.c \
- befs.c
+ befs.c \
+ nilfs.c \
+ exfat.c
diff --git a/shlibs/blkid/src/superblocks/adaptec_raid.c b/shlibs/blkid/src/superblocks/adaptec_raid.c
index 73b146c6..570e75e9 100644
--- a/shlibs/blkid/src/superblocks/adaptec_raid.c
+++ b/shlibs/blkid/src/superblocks/adaptec_raid.c
@@ -81,6 +81,9 @@ static int probe_adraid(blkid_probe pr, const struct blkid_idmag *mag)
if (pr->size < 0x10000)
return -1;
+ if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+ return -1;
+
off = ((pr->size / 0x200)-1) * 0x200;
ad = (struct adaptec_metadata *)
blkid_probe_get_buffer(pr,
diff --git a/shlibs/blkid/src/superblocks/ddf_raid.c b/shlibs/blkid/src/superblocks/ddf_raid.c
index a48735d2..c0ba3351 100644
--- a/shlibs/blkid/src/superblocks/ddf_raid.c
+++ b/shlibs/blkid/src/superblocks/ddf_raid.c
@@ -18,12 +18,57 @@
/* http://www.snia.org/standards/home */
#define DDF_GUID_LENGTH 24
#define DDF_REV_LENGTH 8
+#define DDF_MAGIC 0xDE11DE11
+
struct ddf_header {
- uint8_t signature[4];
+ uint32_t signature;
uint32_t crc;
uint8_t guid[DDF_GUID_LENGTH];
- uint8_t ddf_rev[DDF_REV_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)
@@ -32,7 +77,7 @@ static int probe_ddf(blkid_probe pr, const struct blkid_idmag *mag)
int i;
struct ddf_header *ddf = NULL;
char version[DDF_REV_LENGTH + 1];
- uint64_t off;
+ uint64_t off, lba;
if (pr->size < 0x30000)
return -1;
@@ -46,8 +91,8 @@ static int probe_ddf(blkid_probe pr, const struct blkid_idmag *mag)
if (!ddf)
return -1;
- if (memcmp(ddf->signature, "\x11\xde\x11\xde", 4) == 0 ||
- memcmp(ddf->signature, "\xde\x11\xde\x11", 4) == 0)
+ if (ddf->signature == cpu_to_be32(DDF_MAGIC) ||
+ ddf->signature == cpu_to_le32(DDF_MAGIC))
break;
ddf = NULL;
}
@@ -55,6 +100,20 @@ static int probe_ddf(blkid_probe pr, const struct blkid_idmag *mag)
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 || memcmp(buf, &ddf->signature, 4))
+ return -1;
+ }
+
blkid_probe_strncpy_uuid(pr, ddf->guid, sizeof(ddf->guid));
memcpy(version, ddf->ddf_rev, sizeof(ddf->ddf_rev));
@@ -64,7 +123,7 @@ static int probe_ddf(blkid_probe pr, const struct blkid_idmag *mag)
return -1;
if (blkid_probe_set_magic(pr, off,
sizeof(ddf->signature),
- (unsigned char *) ddf->signature))
+ (unsigned char *) &ddf->signature))
return -1;
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/exfat.c b/shlibs/blkid/src/superblocks/exfat.c
new file mode 100644
index 00000000..bada3a83
--- /dev/null
+++ b/shlibs/blkid/src/superblocks/exfat.c
@@ -0,0 +1,146 @@
+/*
+ * 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 -1;
+
+ label = find_label(pr, sb);
+ if (label)
+ blkid_probe_set_utf8label(pr, label->name,
+ min(label->length * 2, 30), BLKID_ENC_UTF16LE);
+
+ 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, "%hu.%hu",
+ sb->version.major, sb->version.minor);
+
+ return 0;
+}
+
+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/shlibs/blkid/src/superblocks/hfs.c b/shlibs/blkid/src/superblocks/hfs.c
index 8ebff68d..033a65de 100644
--- a/shlibs/blkid/src/superblocks/hfs.c
+++ b/shlibs/blkid/src/superblocks/hfs.c
@@ -291,6 +291,7 @@ 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 },
diff --git a/shlibs/blkid/src/superblocks/highpoint_raid.c b/shlibs/blkid/src/superblocks/highpoint_raid.c
index 98343c41..25e3114b 100644
--- a/shlibs/blkid/src/superblocks/highpoint_raid.c
+++ b/shlibs/blkid/src/superblocks/highpoint_raid.c
@@ -30,6 +30,8 @@ static int probe_highpoint45x(blkid_probe pr, const struct blkid_idmag *mag)
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 *)
@@ -47,6 +49,14 @@ static int probe_highpoint45x(blkid_probe pr, const struct blkid_idmag *mag)
return 0;
}
+static int probe_highpoint37x(blkid_probe pr, const struct blkid_idmag *mag)
+{
+ 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,
@@ -57,6 +67,7 @@ const struct blkid_idinfo highpoint45x_idinfo = {
const struct blkid_idinfo highpoint37x_idinfo = {
.name = "hpt37x_raid_member",
.usage = BLKID_USAGE_RAID,
+ .probefunc = probe_highpoint37x,
.magics = {
/*
* Superblok offset: 4608 bytes (9 sectors)
diff --git a/shlibs/blkid/src/superblocks/isw_raid.c b/shlibs/blkid/src/superblocks/isw_raid.c
index 5149c38a..ac6251d7 100644
--- a/shlibs/blkid/src/superblocks/isw_raid.c
+++ b/shlibs/blkid/src/superblocks/isw_raid.c
@@ -33,6 +33,8 @@ static int probe_iswraid(blkid_probe pr, const struct blkid_idmag *mag)
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 *)
diff --git a/shlibs/blkid/src/superblocks/jmicron_raid.c b/shlibs/blkid/src/superblocks/jmicron_raid.c
index 24430bf9..d35b17f8 100644
--- a/shlibs/blkid/src/superblocks/jmicron_raid.c
+++ b/shlibs/blkid/src/superblocks/jmicron_raid.c
@@ -32,6 +32,8 @@ static int probe_jmraid(blkid_probe pr, const struct blkid_idmag *mag)
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 *)
diff --git a/shlibs/blkid/src/superblocks/linux_raid.c b/shlibs/blkid/src/superblocks/linux_raid.c
index 6f823f15..b73214a4 100644
--- a/shlibs/blkid/src/superblocks/linux_raid.c
+++ b/shlibs/blkid/src/superblocks/linux_raid.c
@@ -34,27 +34,82 @@ struct mdp0_super_block {
uint32_t set_uuid3;
};
+/*
+ * Version-1, little-endian.
+ */
struct mdp1_super_block {
- uint32_t magic;
- uint32_t major_version;
- uint32_t feature_map;
- uint32_t pad0;
- uint8_t set_uuid[16];
- uint8_t set_name[32];
+ /* 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 upto 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, off_t off)
+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 < 0x10000)
+ if (pr->size < MD_RESERVED_BYTES)
return -1;
mdp0 = (struct mdp0_super_block *)
blkid_probe_get_buffer(pr,
@@ -72,11 +127,10 @@ static int probe_raid0(blkid_probe pr, off_t off)
uuid.ints[2] = swab32(mdp0->set_uuid2);
uuid.ints[3] = swab32(mdp0->set_uuid3);
}
- if (blkid_probe_sprintf_version(pr, "%u.%u.%u",
- le32_to_cpu(mdp0->major_version),
- le32_to_cpu(mdp0->minor_version),
- le32_to_cpu(mdp0->patch_version)) != 0)
- return -1;
+ 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;
@@ -85,14 +139,41 @@ static int probe_raid0(blkid_probe pr, off_t off)
uuid.ints[2] = mdp0->set_uuid2;
uuid.ints[3] = mdp0->set_uuid3;
}
- if (blkid_probe_sprintf_version(pr, "%u.%u.%u",
- be32_to_cpu(mdp0->major_version),
- be32_to_cpu(mdp0->minor_version),
- be32_to_cpu(mdp0->patch_version)) != 0)
- return -1;
+ 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;
+ return 1;
+
+ size <<= 10; /* convert KiB to bytes */
+
+ if (pr->size < size + MD_RESERVED_BYTES)
+ /* device is too small */
+ return 1;
+
+ if (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 possition 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),
@@ -115,8 +196,13 @@ static int probe_raid1(blkid_probe pr, off_t off)
return -1;
if (le32_to_cpu(mdp1->major_version) != 1)
return -1;
+ if (le64_to_cpu(mdp1->super_offset) != 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;
diff --git a/shlibs/blkid/src/superblocks/lsi_raid.c b/shlibs/blkid/src/superblocks/lsi_raid.c
index 3010eb6b..5217a009 100644
--- a/shlibs/blkid/src/superblocks/lsi_raid.c
+++ b/shlibs/blkid/src/superblocks/lsi_raid.c
@@ -30,6 +30,8 @@ static int probe_lsiraid(blkid_probe pr, const struct blkid_idmag *mag)
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 *)
diff --git a/shlibs/blkid/src/superblocks/nilfs.c b/shlibs/blkid/src/superblocks/nilfs.c
new file mode 100644
index 00000000..bf169182
--- /dev/null
+++ b/shlibs/blkid/src/superblocks/nilfs.c
@@ -0,0 +1,120 @@
+/*
+ * 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];
+};
+
+/* nilfs2 magic string */
+#define NILFS_SB_MAGIC "\x34\x34"
+/* nilfs2 super block offset */
+#define NILFS_SB_OFF 0x400
+/* nilfs2 super block offset in kB */
+#define NILFS_SB_KBOFF (NILFS_SB_OFF >> 10)
+/* nilfs2 magic string offset within super block */
+#define NILFS_MAG_OFF 6
+
+static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag)
+{
+ 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;
+
+ sb = blkid_probe_get_sb(pr, mag, struct nilfs_super_block);
+ if (!sb)
+ return -1;
+
+ bytes = le32_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);
+
+ if (crc != le32_to_cpu(sb->s_sum))
+ return -1;
+
+ 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,
+ .magics =
+ {
+ {
+ .magic = NILFS_SB_MAGIC,
+ .len = 2,
+ .kboff = NILFS_SB_KBOFF,
+ .sboff = NILFS_MAG_OFF
+ },
+ { NULL }
+ }
+};
diff --git a/shlibs/blkid/src/superblocks/nvidia_raid.c b/shlibs/blkid/src/superblocks/nvidia_raid.c
index e75bec84..c3db949a 100644
--- a/shlibs/blkid/src/superblocks/nvidia_raid.c
+++ b/shlibs/blkid/src/superblocks/nvidia_raid.c
@@ -32,6 +32,8 @@ static int probe_nvraid(blkid_probe pr, const struct blkid_idmag *mag)
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 *)
diff --git a/shlibs/blkid/src/superblocks/promise_raid.c b/shlibs/blkid/src/superblocks/promise_raid.c
index 1cc70e65..0e91d3c2 100644
--- a/shlibs/blkid/src/superblocks/promise_raid.c
+++ b/shlibs/blkid/src/superblocks/promise_raid.c
@@ -33,6 +33,8 @@ static int probe_pdcraid(blkid_probe pr, const struct blkid_idmag *mag)
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;
diff --git a/shlibs/blkid/src/superblocks/silicon_raid.c b/shlibs/blkid/src/superblocks/silicon_raid.c
index 11277ad6..b72b7276 100644
--- a/shlibs/blkid/src/superblocks/silicon_raid.c
+++ b/shlibs/blkid/src/superblocks/silicon_raid.c
@@ -48,6 +48,8 @@ static int probe_silraid(blkid_probe pr, const struct blkid_idmag *mag)
if (pr->size < 0x10000)
return -1;
+ if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+ return -1;
off = ((pr->size / 0x200) - 1) * 0x200;
diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c
index 1d952737..3d66d98c 100644
--- a/shlibs/blkid/src/superblocks/superblocks.c
+++ b/shlibs/blkid/src/superblocks/superblocks.c
@@ -71,7 +71,6 @@
static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn);
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn);
-static void superblocks_free(blkid_probe pr, void *data);
static int blkid_probe_set_usage(blkid_probe pr, int usage);
@@ -140,7 +139,9 @@ static const struct blkid_idinfo *idinfos[] =
&ubifs_idinfo,
&bfs_idinfo,
&vmfs_fs_idinfo,
- &befs_idinfo
+ &befs_idinfo,
+ &nilfs2_idinfo,
+ &exfat_idinfo
};
/*
@@ -156,23 +157,8 @@ const struct blkid_chaindrv superblocks_drv = {
.has_fltr = TRUE,
.probe = superblocks_probe,
.safeprobe = superblocks_safeprobe,
- .free_data = superblocks_free
};
-/*
- * Private chain data
- *
- * TODO: export this data by binary interface (see topology.c or partitions.c
- * for more details) by blkid_probe_get_superblock() or so.
- */
-struct blkid_struct_superblock {
- blkid_loff_t magic_off; /* offset of the magic string */
- int usage;
-};
-
-/* TODO: move to blkid.h */
-typedef struct blkid_struct_superblock *blkid_superblock;
-
/**
* blkid_probe_enable_superblocks:
* @pr: probe
@@ -311,39 +297,6 @@ int blkid_known_fstype(const char *fstype)
return 0;
}
-/* init and returns private data */
-static blkid_superblock superblocks_init_data(blkid_probe pr,
- struct blkid_chain *chn)
-{
- DBG(DEBUG_LOWPROBE, printf("initialize superblocks binary data\n"));
-
- if (chn->data)
- memset(chn->data, 0,
- sizeof(struct blkid_struct_superblock));
- else {
- chn->data = calloc(1,
- sizeof(struct blkid_struct_superblock));
- if (!chn->data)
- return NULL;
- }
- return chn->data;
-}
-
-static void superblocks_free(blkid_probe pr, void *data)
-{
- free(data);
-}
-
-static blkid_superblock superblocks_copy_data(blkid_superblock dest,
- blkid_superblock src)
-{
- if (!src || !dest)
- return NULL;
-
- memcpy(dest, src, sizeof(struct blkid_struct_superblock));
- return dest;
-}
-
/*
* The blkid_do_probe() backend.
*/
@@ -365,9 +318,6 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
* is 1 byte */
goto nothing;
- if (chn->binary)
- superblocks_init_data(pr, chn);
-
i = chn->idx + 1;
for ( ; i < ARRAY_SIZE(idinfos); i++) {
@@ -472,44 +422,37 @@ nothing:
*/
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
{
- blkid_superblock sb = NULL;
- struct blkid_struct_superblock sb_buff;
-
struct blkid_prval vals[BLKID_NVALS_SUBLKS];
int nvals = BLKID_NVALS_SUBLKS;
int idx = -1;
int count = 0;
int intol = 0;
- int rc, bin_org = chn->binary;
-
- chn->binary = TRUE;
+ int rc;
while ((rc = superblocks_probe(pr, chn)) == 0) {
- if (blkid_probe_is_tiny(pr) && !count) {
+ if (blkid_probe_is_tiny(pr) && !count)
/* floppy or so -- returns the first result. */
- chn->binary = bin_org;
return 0;
- }
- if (!count) {
- /* save the first result */
- nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
- idx = chn->idx;
- if (chn->data)
- sb = superblocks_copy_data(&sb_buff, chn->data);
- }
+
count++;
if (idinfos[chn->idx]->usage & (BLKID_USAGE_RAID | BLKID_USAGE_CRYPTO))
break;
+
if (!(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT))
intol++;
- }
- chn->binary = bin_org;
+ 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(DEBUG_LOWPROBE,
printf("ERROR: superblocks chain: "
@@ -520,27 +463,11 @@ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
if (!count)
return 1; /* nothing detected */
- /* restore the first result */
- blkid_probe_chain_reset_vals(pr, chn);
- blkid_probe_append_vals(pr, vals, nvals);
- if (sb && chn->data)
- superblocks_copy_data(chn->data, sb);
- chn->idx = idx;
-
- /*
- * Check for collisions between RAID and partition table
- */
- if (sb && sb->usage == BLKID_USAGE_RAID &&
- sb->magic_off > pr->size / 2 &&
- (S_ISREG(pr->mode) || blkid_probe_is_wholedisk(pr)) &&
- blkid_probe_is_covered_by_pt(pr, sb->magic_off, 0x200)) {
- /*
- * Ignore the result if the detected RAID superblock is
- * within some existing partition (for example RAID on
- * the last partition).
- */
+ if (idx != -1) {
+ /* restore the first result */
blkid_probe_chain_reset_vals(pr, chn);
- return 1;
+ blkid_probe_append_vals(pr, vals, nvals);
+ chn->idx = idx;
}
/*
@@ -548,7 +475,7 @@ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
* where the partition table is visible from underlaying devices. We
* have to ignore such partition tables.
*/
- if (sb && sb->usage == BLKID_USAGE_RAID)
+ if (chn->idx >= 0 && idinfos[chn->idx]->usage & BLKID_USAGE_RAID)
pr->prob_flags |= BLKID_PARTS_IGNORE_PT;
return 0;
@@ -567,10 +494,6 @@ int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset,
rc = blkid_probe_sprintf_value(pr, "SBMAGIC_OFFSET",
"%llu", offset);
}
- if (!rc && chn->data) {
- blkid_superblock sb = (blkid_superblock) chn->data;
- sb->magic_off = offset;
- }
return rc;
}
@@ -604,11 +527,6 @@ 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->data) {
- blkid_superblock sb = (blkid_superblock) chn->data;
- sb->usage = usage;
- }
-
if (!(chn->flags & BLKID_SUBLKS_USAGE))
return 0;
diff --git a/shlibs/blkid/src/superblocks/superblocks.h b/shlibs/blkid/src/superblocks/superblocks.h
index b1fa49d5..a79d7cb6 100644
--- a/shlibs/blkid/src/superblocks/superblocks.h
+++ b/shlibs/blkid/src/superblocks/superblocks.h
@@ -65,6 +65,8 @@ 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 befs_idinfo;
+extern const struct blkid_idinfo nilfs2_idinfo;
+extern const struct blkid_idinfo exfat_idinfo;
/*
* superblock functions
diff --git a/shlibs/blkid/src/superblocks/udf.c b/shlibs/blkid/src/superblocks/udf.c
index 55c96adb..78ddda68 100644
--- a/shlibs/blkid/src/superblocks/udf.c
+++ b/shlibs/blkid/src/superblocks/udf.c
@@ -136,6 +136,9 @@ anchor:
blkid_probe_set_utf8label(pr,
vd->type.primary.ident.c,
31, BLKID_ENC_UTF16BE);
+
+ if (clen == 8 || clen == 16)
+ break;
}
}
diff --git a/shlibs/blkid/src/superblocks/via_raid.c b/shlibs/blkid/src/superblocks/via_raid.c
index 58650454..20131380 100644
--- a/shlibs/blkid/src/superblocks/via_raid.c
+++ b/shlibs/blkid/src/superblocks/via_raid.c
@@ -52,6 +52,8 @@ static int probe_viaraid(blkid_probe pr, const struct blkid_idmag *mag)
if (pr->size < 0x10000)
return -1;
+ if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr))
+ return -1;
off = ((pr->size / 0x200)-1) * 0x200;