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 | |
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')
26 files changed, 531 insertions, 316 deletions
diff --git a/shlibs/blkid/Makefile.am b/shlibs/blkid/Makefile.am index 041fa79b..59362cfe 100644 --- a/shlibs/blkid/Makefile.am +++ b/shlibs/blkid/Makefile.am @@ -12,5 +12,5 @@ pkgconfig_DATA = blkid.pc dist_man_MANS = libblkid.3 -EXTRA_DIST = README.blkid blkid.pc.in libblkid.3 +EXTRA_DIST = COPYING.libblkid README.blkid blkid.pc.in libblkid.3 diff --git a/shlibs/blkid/libblkid.3 b/shlibs/blkid/libblkid.3 index 46eb868b..ab4c5736 100644 --- a/shlibs/blkid/libblkid.3 +++ b/shlibs/blkid/libblkid.3 @@ -9,7 +9,7 @@ .SH NAME libblkid \- block device identification library .SH SYNOPSIS -.B #include <blkid/blkid.h> +.B #include <blkid.h> .sp .B cc .I file.c diff --git a/shlibs/blkid/src/Makefile.am b/shlibs/blkid/src/Makefile.am index 2d798b6a..bb395c71 100644 --- a/shlibs/blkid/src/Makefile.am +++ b/shlibs/blkid/src/Makefile.am @@ -24,14 +24,15 @@ nodist_blkidinc_HEADERS = blkid.h usrlib_exec_LTLIBRARIES = libblkid.la libblkid_la_SOURCES = cache.c dev.c devname.c devno.c getsize.c llseek.c \ probe.c read.c resolve.c save.c tag.c version.c verify.c \ - encode.c list.h blkidP.h superblocks/superblocks.h \ + encode.c blkidP.h superblocks/superblocks.h \ config.c evaluate.c fat.h \ $(blkidinc_HEADERS) \ $(top_srcdir)/lib/blkdev.c \ $(top_srcdir)/lib/linux_version.c \ $(top_srcdir)/lib/canonicalize.c \ $(top_srcdir)/lib/md5.c \ - $(top_srcdir)/lib/crc32.c + $(top_srcdir)/lib/crc32.c \ + $(top_srcdir)/include/list.h nodist_libblkid_la_SOURCES = blkid.h @@ -45,7 +46,7 @@ libblkid_la_DEPENDENCIES = $(libblkid_la_LIBADD) blkid.sym blkid.h.in libblkid_la_LDFLAGS = -Wl,--version-script=$(ul_libblkid_srcdir)/blkid.sym \ -version-info $(LIBBLKID_VERSION_INFO) -tests = test_cache test_config test_dev test_devname test_devno test_getsize \ +tests = test_cache test_config test_dev test_devname test_devno \ test_read test_resolve test_save test_tag test_verify test_evaluate EXTRA_DIST = blkid.sym tst_types.c blkid.h.in diff --git a/shlibs/blkid/src/list.h b/shlibs/blkid/src/list.h deleted file mode 100644 index c1cbfec5..00000000 --- a/shlibs/blkid/src/list.h +++ /dev/null @@ -1,179 +0,0 @@ -#if !defined(_BLKID_LIST_H) && !defined(LIST_HEAD) -#define _BLKID_LIST_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __GNUC__ -#define _INLINE_ static __inline__ -#else /* For Watcom C */ -#define _INLINE_ static inline -#endif - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -_INLINE_ void __list_add(struct list_head * add, - struct list_head * prev, - struct list_head * next) -{ - next->prev = add; - add->next = next; - add->prev = prev; - prev->next = add; -} - -/** - * list_add - add a new entry - * @add: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -_INLINE_ void list_add(struct list_head *add, struct list_head *head) -{ - __list_add(add, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @add: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head) -{ - __list_add(add, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -_INLINE_ void __list_del(struct list_head * prev, - struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * - * list_empty() on @entry does not return true after this, @entry is - * in an undefined state. - */ -_INLINE_ void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -_INLINE_ void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -_INLINE_ int list_empty(struct list_head *head) -{ - return head->next == head; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -_INLINE_ void list_splice(struct list_head *list, struct list_head *head) -{ - struct list_head *first = list->next; - - if (first != list) { - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over elements in a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_safe - iterate over elements in a list, but don't dereference - * pos after the body is done (in case it is freed) - * @pos: the &struct list_head to use as a loop counter. - * @pnext: the &struct list_head to use as a pointer to the next item. - * @head: the head for your list (not included in iteration). - */ -#define list_for_each_safe(pos, pnext, head) \ - for (pos = (head)->next, pnext = pos->next; pos != (head); \ - pos = pnext, pnext = pos->next) - -#undef _INLINE_ - -#ifdef __cplusplus -} -#endif - -#endif /* _BLKID_LIST_H */ diff --git a/shlibs/blkid/src/partitions/partitions.c b/shlibs/blkid/src/partitions/partitions.c index c670cc18..5597181a 100644 --- a/shlibs/blkid/src/partitions/partitions.c +++ b/shlibs/blkid/src/partitions/partitions.c @@ -829,6 +829,19 @@ int blkid_probe_is_covered_by_pt(blkid_probe pr, end = (offset + size) >> 9; start = offset >> 9; + /* check if the partition table fits into the device */ + for (i = 0; i < nparts; i++) { + blkid_partition par = &ls->parts[i]; + + if (par->start + par->size > pr->size) { + DBG(DEBUG_LOWPROBE, printf("partition #%d overflows " + "device (off=%lu size=%lu)\n", + par->partno, par->start, par->size)); + goto done; + } + } + + /* check if the requested area is covered by PT */ for (i = 0; i < nparts; i++) { blkid_partition par = &ls->parts[i]; diff --git a/shlibs/blkid/src/probe.c b/shlibs/blkid/src/probe.c index 89c59504..200a52c5 100644 --- a/shlibs/blkid/src/probe.c +++ b/shlibs/blkid/src/probe.c @@ -103,6 +103,7 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif +#include <inttypes.h> #include <stdint.h> #include <stdarg.h> @@ -542,7 +543,7 @@ unsigned char *blkid_probe_get_buffer(blkid_probe pr, static void blkid_probe_reset_buffer(blkid_probe pr) { - ssize_t read_ct = 0, len_ct = 0; + uint64_t read_ct = 0, len_ct = 0; if (!pr || list_empty(&pr->buffers)) return; @@ -560,7 +561,8 @@ static void blkid_probe_reset_buffer(blkid_probe pr) } DBG(DEBUG_LOWPROBE, - printf("buffers summary: %jd bytes by %jd read() call(s)\n", + printf("buffers summary: %"PRIu64" bytes " + "by %"PRIu64" read() call(s)\n", len_ct, read_ct)); INIT_LIST_HEAD(&pr->buffers); @@ -650,9 +652,6 @@ int blkid_probe_set_device(blkid_probe pr, int fd, pr->size -= pr->off; } - DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%jd, size=%jd\n", - pr->off, pr->size)); - if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode)) pr->flags |= BLKID_TINY_DEV; @@ -660,6 +659,13 @@ int blkid_probe_set_device(blkid_probe pr, int fd, if (S_ISBLK(sb.st_mode) && ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0) pr->flags |= BLKID_CDROM_DEV; #endif + + DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%jd, size=%jd\n", + pr->off, pr->size)); + DBG(DEBUG_LOWPROBE, printf("whole-disk: %s, regfile: %s\n", + blkid_probe_is_wholedisk(pr) ?"YES" : "NO", + S_ISREG(pr->mode) ? "YES" : "NO")); + return 0; err: DBG(DEBUG_LOWPROBE, 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; diff --git a/shlibs/blkid/src/topology/evms.c b/shlibs/blkid/src/topology/evms.c index baab16ed..574d9f55 100644 --- a/shlibs/blkid/src/topology/evms.c +++ b/shlibs/blkid/src/topology/evms.c @@ -23,6 +23,11 @@ #include "topology.h" #define EVMS_MAJOR 117 + +#ifndef _IOT__IOTBASE_u_int32_t +#define _IOT__IOTBASE_u_int32_t IOT_SIMPLE(u_int32_t) +#endif +#define _IOT_evms_stripe_info _IOT (_IOTS(u_int32_t), 2, 0, 0, 0, 0) #define EVMS_GET_STRIPE_INFO _IOR(EVMS_MAJOR, 0xF0, struct evms_stripe_info) struct evms_stripe_info { diff --git a/shlibs/blkid/src/topology/md.c b/shlibs/blkid/src/topology/md.c index a761e170..d7275edd 100644 --- a/shlibs/blkid/src/topology/md.c +++ b/shlibs/blkid/src/topology/md.c @@ -26,6 +26,10 @@ #define MD_MAJOR 9 #endif +#ifndef _IOT__IOTBASE_uint32_t +#define _IOT__IOTBASE_uint32_t IOT_SIMPLE(uint32_t) +#endif +#define _IOT_md_array_info _IOT (_IOTS(uint32_t), 18, 0, 0, 0, 0) #define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, struct md_array_info) struct md_array_info { |