diff options
Diffstat (limited to 'shlibs/blkid/src/superblocks')
-rw-r--r-- | shlibs/blkid/src/superblocks/Makefile.am | 3 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/befs.c | 207 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/drbd.c | 3 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/gfs.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/jfs.c | 1 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/minix.c | 70 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/ocfs.c | 3 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/reiserfs.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/superblocks.c | 35 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/superblocks.h | 1 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/swap.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/vfat.c | 143 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/zfs.c | 1 |
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, §or_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 }, |