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.am3
-rw-r--r--shlibs/blkid/src/superblocks/befs.c207
-rw-r--r--shlibs/blkid/src/superblocks/drbd.c3
-rw-r--r--shlibs/blkid/src/superblocks/gfs.c2
-rw-r--r--shlibs/blkid/src/superblocks/jfs.c1
-rw-r--r--shlibs/blkid/src/superblocks/minix.c70
-rw-r--r--shlibs/blkid/src/superblocks/ocfs.c3
-rw-r--r--shlibs/blkid/src/superblocks/reiserfs.c2
-rw-r--r--shlibs/blkid/src/superblocks/superblocks.c35
-rw-r--r--shlibs/blkid/src/superblocks/superblocks.h1
-rw-r--r--shlibs/blkid/src/superblocks/swap.c2
-rw-r--r--shlibs/blkid/src/superblocks/vfat.c143
-rw-r--r--shlibs/blkid/src/superblocks/zfs.c1
13 files changed, 378 insertions, 95 deletions
diff --git a/shlibs/blkid/src/superblocks/Makefile.am b/shlibs/blkid/src/superblocks/Makefile.am
index 33e5d0c3..f5b88b8e 100644
--- a/shlibs/blkid/src/superblocks/Makefile.am
+++ b/shlibs/blkid/src/superblocks/Makefile.am
@@ -45,4 +45,5 @@ libblkid_superblocks_la_SOURCES = \
ubifs.c \
bfs.c \
drbd.c \
- vmfs.c
+ vmfs.c \
+ befs.c
diff --git a/shlibs/blkid/src/superblocks/befs.c b/shlibs/blkid/src/superblocks/befs.c
new file mode 100644
index 00000000..b341402a
--- /dev/null
+++ b/shlibs/blkid/src/superblocks/befs.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2010 Jeroen Oortwijn <oortwijn@gmail.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"
+
+#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 B_UINT64_TYPE 0x554C4C47 /* ULLG */
+
+#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[12];
+ 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[1];
+} __attribute__((packed));
+
+struct small_data {
+ uint32_t type;
+ uint16_t name_size;
+ uint16_t data_size;
+ char name[0];
+} __attribute__((packed));
+
+static int probe_befs(blkid_probe pr, const struct blkid_idmag *mag)
+{
+ struct befs_super_block *bs;
+ struct befs_inode *bi;
+ struct small_data *sd;
+ int fs_le;
+ uint64_t volume_id = 0;
+ const char *version = NULL;
+
+ bs = (struct befs_super_block *) blkid_probe_get_buffer(pr,
+ mag->sboff - B_OS_NAME_LENGTH,
+ sizeof(struct befs_super_block));
+ if (!bs)
+ return -1;
+
+ 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 -1;
+
+ bi = (struct befs_inode *) blkid_probe_get_buffer(pr,
+ (FS32_TO_CPU(bs->root_dir.allocation_group, fs_le)
+ << FS32_TO_CPU(bs->ag_shift, fs_le)
+ << FS32_TO_CPU(bs->block_shift, fs_le))
+ + (FS16_TO_CPU(bs->root_dir.start, fs_le)
+ << FS32_TO_CPU(bs->block_shift, fs_le)),
+ FS16_TO_CPU(bs->root_dir.len, fs_le)
+ << FS32_TO_CPU(bs->block_shift, fs_le));
+ if (!bi)
+ return -1;
+
+ if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1)
+ return -1;
+
+ /*
+ * all checks pass, set LABEL and VERSION
+ */
+ if (strlen(bs->name))
+ blkid_probe_set_label(pr, (unsigned char *) bs->name,
+ sizeof(bs->name));
+ if (version)
+ blkid_probe_set_version(pr, version);
+
+ /*
+ * search for UUID
+ */
+ 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) == 12
+ && FS16_TO_CPU(sd->data_size, fs_le) == 8
+ && strcmp(sd->name, "be:volume_id") == 0) {
+ volume_id = *(uint64_t *) ((uint8_t *) sd->name
+ + FS16_TO_CPU(sd->name_size, fs_le)
+ + 3);
+ blkid_probe_sprintf_uuid(pr,
+ (unsigned char *) &volume_id,
+ sizeof(volume_id),
+ "%016" PRIx64,
+ FS64_TO_CPU(volume_id, fs_le));
+ 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
+ + FS32_TO_CPU(bi->inode_size, fs_le)
+ - sizeof(struct small_data));
+
+ if (volume_id == 0) {
+ /*
+ * TODO: Search for the be:volume_id attribute in the
+ * attributes directory of the root directory.
+ */
+ }
+
+ return 0;
+}
+
+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/shlibs/blkid/src/superblocks/drbd.c b/shlibs/blkid/src/superblocks/drbd.c
index e0bbb4d6..a56486e9 100644
--- a/shlibs/blkid/src/superblocks/drbd.c
+++ b/shlibs/blkid/src/superblocks/drbd.c
@@ -78,7 +78,8 @@ static int probe_drbd(blkid_probe pr, const struct blkid_idmag *mag)
blkid_probe_get_buffer(pr,
off,
sizeof(struct md_on_disk_08));
-
+ if (!md)
+ return -1;
if (be32_to_cpu(md->magic) != DRBD_MD_MAGIC_08)
return -1;
diff --git a/shlibs/blkid/src/superblocks/gfs.c b/shlibs/blkid/src/superblocks/gfs.c
index 8ad81bcb..b2c01630 100644
--- a/shlibs/blkid/src/superblocks/gfs.c
+++ b/shlibs/blkid/src/superblocks/gfs.c
@@ -108,6 +108,7 @@ 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 },
@@ -120,6 +121,7 @@ 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 },
diff --git a/shlibs/blkid/src/superblocks/jfs.c b/shlibs/blkid/src/superblocks/jfs.c
index e6e44505..9a49c674 100644
--- a/shlibs/blkid/src/superblocks/jfs.c
+++ b/shlibs/blkid/src/superblocks/jfs.c
@@ -61,6 +61,7 @@ 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 },
diff --git a/shlibs/blkid/src/superblocks/minix.c b/shlibs/blkid/src/superblocks/minix.c
index 784f0758..7b314abc 100644
--- a/shlibs/blkid/src/superblocks/minix.c
+++ b/shlibs/blkid/src/superblocks/minix.c
@@ -11,20 +11,84 @@
#include "superblocks.h"
+struct minix_super_block {
+ uint16_t s_ninodes;
+ uint16_t s_nzones;
+ uint16_t s_imap_blocks;
+ uint16_t s_zmap_blocks;
+ uint16_t s_firstdatazone;
+ uint16_t s_log_zone_size;
+ uint32_t s_max_size;
+ uint16_t s_magic;
+ uint16_t s_state;
+ uint32_t s_zones;
+};
+
+struct minix3_super_block {
+ uint32_t s_ninodes;
+ uint16_t s_pad0;
+ uint16_t s_imap_blocks;
+ uint16_t s_zmap_blocks;
+ uint16_t s_firstdatazone;
+ uint16_t s_log_zone_size;
+ uint16_t s_pad1;
+ uint32_t s_max_size;
+ uint32_t s_zones;
+ uint16_t s_magic;
+ uint16_t s_pad2;
+ uint16_t s_blocksize;
+ uint8_t s_disk_version;
+};
+
+#define MINIX_BLOCK_SIZE_BITS 10
+#define MINIX_BLOCK_SIZE (1 << MINIX_BLOCK_SIZE_BITS)
+
static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
{
+ int version;
+
/* for more details see magic strings below */
switch(mag->magic[1]) {
case '\023':
- blkid_probe_set_version(pr, "1");
+ version = 1;
break;
case '\044':
- blkid_probe_set_version(pr, "2");
+ version = 2;
break;
case '\115':
- blkid_probe_set_version(pr, "3");
+ version = 3;
break;
+ default:
+ return -1;
+ break;
+ }
+
+ if (version <= 2) {
+ struct minix_super_block *sb;
+ uint32_t zones;
+
+ sb = blkid_probe_get_sb(pr, mag, struct minix_super_block);
+ if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
+ return -1;
+
+ zones = version == 2 ? sb->s_zones : sb->s_nzones;
+
+ /* sanity checks to be sure that the FS is really minix */
+ if (sb->s_imap_blocks * MINIX_BLOCK_SIZE * 8 < sb->s_ninodes + 1)
+ return -1;
+ if (sb->s_zmap_blocks * MINIX_BLOCK_SIZE * 8 < zones - sb->s_firstdatazone + 1)
+ return -1;
+
+ } else if (version == 3) {
+ struct minix3_super_block *sb;
+
+ sb = blkid_probe_get_sb(pr, mag, struct minix3_super_block);
+ if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
+ return -1;
+
}
+
+ blkid_probe_sprintf_version(pr, "%d", version);
return 0;
}
diff --git a/shlibs/blkid/src/superblocks/ocfs.c b/shlibs/blkid/src/superblocks/ocfs.c
index 6e58b37a..9dbf41b1 100644
--- a/shlibs/blkid/src/superblocks/ocfs.c
+++ b/shlibs/blkid/src/superblocks/ocfs.c
@@ -174,6 +174,7 @@ const struct blkid_idinfo ocfs_idinfo =
.name = "ocfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_ocfs,
+ .minsz = 108 * 1024 * 1024,
.magics =
{
{ .magic = "OracleCFS", .len = 9, .kboff = 8 },
@@ -186,6 +187,7 @@ const struct blkid_idinfo ocfs2_idinfo =
.name = "ocfs2",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_ocfs2,
+ .minsz = 108 * 1024 * 1024,
.magics =
{
{ .magic = "OCFSV2", .len = 6, .kboff = 1 },
@@ -196,6 +198,7 @@ const struct blkid_idinfo ocfs2_idinfo =
}
};
+/* Oracle ASM (Automatic Storage Management) */
const struct blkid_idinfo oracleasm_idinfo =
{
.name = "oracleasm",
diff --git a/shlibs/blkid/src/superblocks/reiserfs.c b/shlibs/blkid/src/superblocks/reiserfs.c
index 4222a307..921f5237 100644
--- a/shlibs/blkid/src/superblocks/reiserfs.c
+++ b/shlibs/blkid/src/superblocks/reiserfs.c
@@ -98,6 +98,7 @@ const struct blkid_idinfo reiser_idinfo =
.name = "reiserfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_reiser,
+ .minsz = 4096 * 512, /* not sure, this is minimal size of journal */
.magics =
{
{ .magic = "ReIsErFs", .len = 8, .kboff = 8, .sboff = 0x34 },
@@ -114,6 +115,7 @@ const struct blkid_idinfo reiser4_idinfo =
.name = "reiser4",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_reiser4,
+ .minsz = 4096 * 512, /* not sure, this is minimal size of journal */
.magics =
{
{ .magic = "ReIsEr4", .len = 7, .kboff = 64 },
diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c
index e77c511d..fd12e5ec 100644
--- a/shlibs/blkid/src/superblocks/superblocks.c
+++ b/shlibs/blkid/src/superblocks/superblocks.c
@@ -138,7 +138,8 @@ static const struct blkid_idinfo *idinfos[] =
&btrfs_idinfo,
&ubifs_idinfo,
&bfs_idinfo,
- &vmfs_fs_idinfo
+ &vmfs_fs_idinfo,
+ &befs_idinfo
};
/*
@@ -310,6 +311,12 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
printf("--> starting probing loop [SUBLKS idx=%d]\n",
chn->idx));
+ if (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 1;
+
i = chn->idx + 1;
for ( ; i < ARRAY_SIZE(idinfos); i++) {
@@ -325,8 +332,19 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
continue;
id = idinfos[i];
+
+ if (id->minsz && id->minsz > pr->size)
+ continue; /* the device is too small */
+
mag = id->magics ? &id->magics[0] : NULL;
+ /* don't probe for RAIDs, swap or journal on floppies */
+ if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) &&
+ blkid_probe_is_tiny(pr))
+ continue;
+
+ DBG(DEBUG_LOWPROBE, printf("[%d] %s:\n", i, id->name));
+
/* try to detect by magic string */
while(mag && mag->magic) {
unsigned char *buf;
@@ -337,8 +355,8 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
if (buf && !memcmp(mag->magic,
buf + (mag->sboff & 0x3ff), mag->len)) {
DBG(DEBUG_LOWPROBE, printf(
- "%s: magic sboff=%u, kboff=%ld\n",
- id->name, mag->sboff, mag->kboff));
+ "\tmagic sboff=%u, kboff=%ld\n",
+ mag->sboff, mag->kboff));
hasmag = 1;
off += mag->sboff & 0x3ff;
break;
@@ -352,8 +370,7 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
/* final check by probing function */
if (id->probefunc) {
- DBG(DEBUG_LOWPROBE, printf(
- "%s: call probefunc()\n", id->name));
+ DBG(DEBUG_LOWPROBE, printf("\tcall probefunc()\n"));
if (id->probefunc(pr, mag) != 0)
continue;
}
@@ -393,6 +410,9 @@ static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
* 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)
{
@@ -404,6 +424,11 @@ static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
int rc;
while ((rc = superblocks_probe(pr, chn)) == 0) {
+
+ if (blkid_probe_is_tiny(pr) && !count)
+ /* floppy or so -- returns the first result. */
+ return 0;
+
if (!count) {
/* save the first result */
nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
diff --git a/shlibs/blkid/src/superblocks/superblocks.h b/shlibs/blkid/src/superblocks/superblocks.h
index 893ae72a..12f197e5 100644
--- a/shlibs/blkid/src/superblocks/superblocks.h
+++ b/shlibs/blkid/src/superblocks/superblocks.h
@@ -64,6 +64,7 @@ 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 befs_idinfo;
/*
* superblock functions
diff --git a/shlibs/blkid/src/superblocks/swap.c b/shlibs/blkid/src/superblocks/swap.c
index 4fb4ab7a..8aaa6f31 100644
--- a/shlibs/blkid/src/superblocks/swap.c
+++ b/shlibs/blkid/src/superblocks/swap.c
@@ -99,6 +99,7 @@ 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 },
@@ -121,6 +122,7 @@ const struct blkid_idinfo swsuspend_idinfo =
.name = "swsuspend",
.usage = BLKID_USAGE_OTHER,
.probefunc = probe_swsuspend,
+ .minsz = 10 * 4096, /* 10 pages */
.magics =
{
{ "S1SUSPEND", 9, 0, 0xff6 },
diff --git a/shlibs/blkid/src/superblocks/vfat.c b/shlibs/blkid/src/superblocks/vfat.c
index 7587f8dd..b24f6075 100644
--- a/shlibs/blkid/src/superblocks/vfat.c
+++ b/shlibs/blkid/src/superblocks/vfat.c
@@ -18,62 +18,8 @@
#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));
+/* {msdos,vfat}_super_block is defined in ../fat.h */
+#include "fat.h"
struct vfat_dir_entry {
uint8_t name[11];
@@ -111,25 +57,59 @@ struct fat32_fsinfo {
static const char *no_name = "NO NAME ";
-static unsigned char *search_fat_label(struct vfat_dir_entry *dir, int count)
+/*
+ * Look for LABEL (name) in the FAT root directory.
+ */
+static unsigned char *search_fat_label(blkid_probe pr,
+ uint32_t offset, uint32_t entries)
{
+ struct vfat_dir_entry *ent, *dir = NULL;
int i;
- for (i = 0; i < count; i++) {
- if (dir[i].name[0] == 0x00)
+ DBG(DEBUG_LOWPROBE,
+ printf("\tlook for label in root-dir "
+ "(entries: %d, offset: %d)\n", 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,
+ 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,
+ offset + (i * sizeof(struct vfat_dir_entry)),
+ sizeof(struct vfat_dir_entry));
+ else
+ ent = &dir[i];
+
+ if (!ent || ent->name[0] == 0x00)
break;
- if ((dir[i].name[0] == FAT_ENTRY_FREE) ||
- (dir[i].cluster_high != 0 || dir[i].cluster_low != 0) ||
- ((dir[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME))
+ 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 ((dir[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
+ if ((ent->attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) ==
FAT_ATTR_VOLUME_ID) {
- return dir[i].name;
+ DBG(DEBUG_LOWPROBE,
+ printf("\tfound fs LABEL at entry %d\n", i));
+ return ent->name;
}
}
- return 0;
+ return NULL;
}
/*
@@ -159,7 +139,7 @@ static int probe_fat_nomagic(blkid_probe pr, const struct blkid_idmag *mag)
return 1;
/* media check */
- if (ms->ms_media < 0xf8 && ms->ms_media != 0xf0)
+ if (!blkid_fat_valid_media(ms))
return 1;
/* fat counts(Linux kernel expects at least 1 FAT table) */
@@ -188,16 +168,14 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
{
struct vfat_super_block *vs;
struct msdos_super_block *ms;
- struct vfat_dir_entry *dir;
const unsigned char *vol_label = 0, *tmp;
- unsigned char *vol_serno;
+ unsigned char *vol_serno, vol_label_buf[11];
int maxloop = 100;
uint16_t sector_size, dir_entries, reserved;
uint32_t sect_count, fat_size, dir_size, cluster_count, fat_length;
uint32_t buf_size, start_data_sect, next, root_start, root_dir_entries;
const char *version = NULL;
-
/* non-standard magic strings */
if (mag->len <= 2 && probe_fat_nomagic(pr, mag) != 0)
return 1;
@@ -211,10 +189,7 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
return -1;
/* sector size check */
- tmp = (unsigned char *) &ms->ms_sector_size;
- sector_size = tmp[0] + (tmp[1] << 8);
- if (sector_size != 0x200 && sector_size != 0x400 &&
- sector_size != 0x800 && sector_size != 0x1000)
+ if (!blkid_fat_valid_sectorsize(ms, &sector_size))
return 1;
tmp = (unsigned char *) &ms->ms_dir_entries;
@@ -247,11 +222,11 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
root_dir_entries = vs->vs_dir_entries[0] +
(vs->vs_dir_entries[1] << 8);
- buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
- dir = (struct vfat_dir_entry *)
- blkid_probe_get_buffer(pr, root_start, buf_size);
- if (dir)
- vol_label = search_fat_label(dir, root_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;
@@ -284,16 +259,14 @@ static int probe_vfat(blkid_probe pr, const struct blkid_idmag *mag)
next_off = (start_data_sect + next_sect_off) *
sector_size;
- dir = (struct vfat_dir_entry *)
- blkid_probe_get_buffer(pr, next_off, buf_size);
- if (dir == NULL)
- break;
-
count = buf_size / sizeof(struct vfat_dir_entry);
- vol_label = search_fat_label(dir, count);
- if (vol_label)
+ 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 = (reserved * sector_size) +
diff --git a/shlibs/blkid/src/superblocks/zfs.c b/shlibs/blkid/src/superblocks/zfs.c
index 2d626427..0f580262 100644
--- a/shlibs/blkid/src/superblocks/zfs.c
+++ b/shlibs/blkid/src/superblocks/zfs.c
@@ -54,6 +54,7 @@ const struct blkid_idinfo zfs_idinfo =
.name = "zfs",
.usage = BLKID_USAGE_FILESYSTEM,
.probefunc = probe_zfs,
+ .minsz = 64 * 1024 * 1024,
.magics =
{
{ .magic = "\0\0\x02\xf5\xb0\x07\xb1\x0c", .len = 8, .kboff = 8 },