diff options
author | LaMont Jones <lamont@debian.org> | 2010-08-02 23:02:28 -0600 |
---|---|---|
committer | LaMont Jones <lamont@debian.org> | 2010-08-02 23:02:28 -0600 |
commit | 0864d694ca05ea9383ef09bc1bc3a182e15e2ffa (patch) | |
tree | 2e5237f1d4e2cac2efad97ce31abc386c1e37b6d /shlibs/blkid/src/superblocks | |
parent | 3cbdfd84fde6159d7778e70618fbbc8df219cafe (diff) | |
parent | 6c91f5e3e1de32c45ea0b38227ce35eb43eb2ebc (diff) | |
download | util-linux-old-0864d694ca05ea9383ef09bc1bc3a182e15e2ffa.tar.gz |
Merge remote branch 'origin/master'
Conflicts:
mount/Makefile.am
sys-utils/ipcs.c
tests/ts/blkid/images-fs/befs.img.bz2
tests/ts/blkid/images-fs/ddf-raid.img.bz2
Diffstat (limited to 'shlibs/blkid/src/superblocks')
-rw-r--r-- | shlibs/blkid/src/superblocks/Makefile.am | 4 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/adaptec_raid.c | 3 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/ddf_raid.c | 71 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/exfat.c | 146 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/hfs.c | 1 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/highpoint_raid.c | 11 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/isw_raid.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/jmicron_raid.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/linux_raid.c | 124 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/lsi_raid.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/nilfs.c | 120 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/nvidia_raid.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/promise_raid.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/silicon_raid.c | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/superblocks.c | 120 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/superblocks.h | 2 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/udf.c | 3 | ||||
-rw-r--r-- | shlibs/blkid/src/superblocks/via_raid.c | 2 |
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; |