diff options
| author | Richard Maw <richard.maw@codethink.co.uk> | 2014-06-12 12:04:01 +0100 |
|---|---|---|
| committer | Richard Maw <richard.maw@codethink.co.uk> | 2014-06-12 12:04:01 +0100 |
| commit | c5c1033c5c7deda8abe3448ec81bbb33c72219e0 (patch) | |
| tree | 6e5cef29b85161eea8a7488a029f5a32f982c6ab /libblkid | |
| parent | 462008f79be9e195670b202cb43827b8aeb1e60b (diff) | |
| parent | 2fb567c080e1762ec6a2147564f03068f55d4f14 (diff) | |
| download | util-linux-baserock/morph.tar.gz | |
Merge branch 'baserock/richardmaw/yakshave/util-linux-blkid' into baserock/morphbaserock/morph
Reviewed-by: Lars Wirzenius
Reviewed-by: Sam Thursfield
Diffstat (limited to 'libblkid')
30 files changed, 723 insertions, 489 deletions
diff --git a/libblkid/COPYING b/libblkid/COPYING index 41fe6fd62..be1a5b3a1 100644 --- a/libblkid/COPYING +++ b/libblkid/COPYING @@ -4,5 +4,5 @@ License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. -The complete text of the license is available at the -Documentation/licenses/COPYING.LGPLv2.1 file. +The complete text of the license is available in the +../Documentation/licenses/COPYING.LGPLv2.1 file. diff --git a/libblkid/docs/libblkid-docs.xml b/libblkid/docs/libblkid-docs.xml index 3ff754aa7..1f412c105 100644 --- a/libblkid/docs/libblkid-docs.xml +++ b/libblkid/docs/libblkid-docs.xml @@ -50,6 +50,7 @@ available from ftp://ftp.kernel.org/pub/linux/utils/util-linux/. </part> <part> <title>Low-level</title> + <xi:include href="xml/init.xml"/> <xi:include href="xml/lowprobe.xml"/> <xi:include href="xml/lowprobe-tags.xml"/> <xi:include href="xml/superblocks.xml"/> diff --git a/libblkid/docs/libblkid-sections.txt b/libblkid/docs/libblkid-sections.txt index 86b8040fa..69723459e 100644 --- a/libblkid/docs/libblkid-sections.txt +++ b/libblkid/docs/libblkid-sections.txt @@ -180,6 +180,7 @@ BLKID_PROBREQ_USAGE BLKID_PROBREQ_UUID BLKID_PROBREQ_UUIDRAW BLKID_PROBREQ_VERSION +BLKID_SUBLKS_BADCSUM BLKID_SUBLKS_DEFAULT BLKID_SUBLKS_LABEL BLKID_SUBLKS_LABELRAW diff --git a/libblkid/src/Makemodule.am b/libblkid/src/Makemodule.am index 04d862100..013877e60 100644 --- a/libblkid/src/Makemodule.am +++ b/libblkid/src/Makemodule.am @@ -26,14 +26,12 @@ libblkid_la_SOURCES = \ libblkid/src/tag.c \ libblkid/src/verify.c \ libblkid/src/version.c \ - $(blkidinc_HEADERS) \ + $(nodist_blkidinc_HEADERS) \ \ libblkid/src/partitions/aix.c \ libblkid/src/partitions/aix.h \ - libblkid/src/partitions/blkid_parttypes.h \ libblkid/src/partitions/bsd.c \ libblkid/src/partitions/dos.c \ - libblkid/src/partitions/dos.h \ libblkid/src/partitions/gpt.c \ libblkid/src/partitions/mac.c \ libblkid/src/partitions/minix.c \ @@ -46,6 +44,7 @@ libblkid_la_SOURCES = \ libblkid/src/partitions/unixware.c \ \ libblkid/src/superblocks/adaptec_raid.c \ + libblkid/src/superblocks/bcache.c \ libblkid/src/superblocks/befs.c \ libblkid/src/superblocks/bfs.c \ libblkid/src/superblocks/btrfs.c \ @@ -111,23 +110,24 @@ endif nodist_libblkid_la_SOURCES = libblkid/src/blkid.h libblkid_la_LIBADD = libcommon.la +libblkid_la_DEPENDENCIES = \ + libcommon.la \ + libblkid/src/blkid.sym \ + libblkid/src/blkid.h.in libblkid_la_CFLAGS = \ + $(SOLIB_CFLAGS) \ -I$(ul_libblkid_incdir) \ -I$(top_srcdir)/libblkid/src if BUILD_LIBUUID libblkid_la_LIBADD += libuuid.la +libblkid_la_DEPENDENCIES += libuuid.la libblkid_la_CFLAGS += -I$(ul_libuuid_incdir) endif - -libblkid_la_DEPENDENCIES = \ - $(libblkid_la_LIBADD) \ - libblkid/src/blkid.sym \ - libblkid/src/blkid.h.in - libblkid_la_LDFLAGS = \ + $(SOLIB_LDFLAGS) \ -Wl,--version-script=$(top_srcdir)/libblkid/src/blkid.sym \ -version-info $(LIBBLKID_VERSION_INFO) diff --git a/libblkid/src/blkid.h.in b/libblkid/src/blkid.h.in index 2a7d6b47c..c140fc6b2 100644 --- a/libblkid/src/blkid.h.in +++ b/libblkid/src/blkid.h.in @@ -260,6 +260,7 @@ extern int blkid_probe_enable_superblocks(blkid_probe pr, int enable); #define BLKID_SUBLKS_USAGE (1 << 7) /* define USAGE result value */ #define BLKID_SUBLKS_VERSION (1 << 8) /* read FS type from superblock */ #define BLKID_SUBLKS_MAGIC (1 << 9) /* define SBMAGIC and SBMAGIC_OFFSET */ +#define BLKID_SUBLKS_BADCSUM (1 << 10) /* allow a bad checksum */ #define BLKID_SUBLKS_DEFAULT (BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | \ BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE) diff --git a/libblkid/src/blkidP.h b/libblkid/src/blkidP.h index 7cc585932..0bbf310a0 100644 --- a/libblkid/src/blkidP.h +++ b/libblkid/src/blkidP.h @@ -516,8 +516,13 @@ extern int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset, size_t len, unsigned char *magic) __attribute__((nonnull)); +extern int blkid_probe_verify_csum(blkid_probe pr, uint64_t csum, uint64_t expected) + __attribute__((nonnull)); + extern void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len) __attribute__((nonnull)); +extern int blkid_uuid_is_empty(const unsigned char *buf, size_t len); + extern size_t blkid_rtrim_whitespace(unsigned char *str) __attribute__((nonnull)); extern size_t blkid_ltrim_whitespace(unsigned char *str) diff --git a/libblkid/src/evaluate.c b/libblkid/src/evaluate.c index 8853009c9..8ef927756 100644 --- a/libblkid/src/evaluate.c +++ b/libblkid/src/evaluate.c @@ -24,6 +24,7 @@ #include "pathnames.h" #include "canonicalize.h" +#include "closestream.h" #include "blkidP.h" @@ -123,7 +124,8 @@ int blkid_send_uevent(const char *devname, const char *action) rc = 0; if (fputs(action, f) >= 0) rc = 0; - fclose(f); + if (close_stream(f) != 0) + DBG(EVALUATE, blkid_debug("write failed: %s", uevent)); } DBG(EVALUATE, blkid_debug("%s: send uevent %s", uevent, rc == 0 ? "SUCCES" : "FAILED")); diff --git a/libblkid/src/init.c b/libblkid/src/init.c index 4ca4db171..bb6f950fb 100644 --- a/libblkid/src/init.c +++ b/libblkid/src/init.c @@ -40,7 +40,7 @@ void blkid_init_debug(int mask) libblkid_debug_mask |= BLKID_DEBUG_INIT; - if (libblkid_debug_mask && libblkid_debug_mask != BLKID_DEBUG_INIT) { + if (libblkid_debug_mask != BLKID_DEBUG_INIT) { const char *ver = NULL; const char *date = NULL; diff --git a/libblkid/src/partitions/blkid_parttypes.h b/libblkid/src/partitions/blkid_parttypes.h deleted file mode 100644 index b0aad86e6..000000000 --- a/libblkid/src/partitions/blkid_parttypes.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Partition types - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/* Note, _L32M means <32M (less), for example FAT16_L32M */ - -enum { - BLKID_EMPTY_PARTITION = 0x00, - BLKID_FAT12_PARTITION = 0x01, - BLKID_XENIX_ROOT_PARTITION = 0x02, - BLKID_XENIX_USR_PARTITION = 0x03, - BLKID_FAT16_LESS32M_PARTITION = 0x04, - BLKID_DOS_EXTENDED_PARTITION = 0x05, - BLKID_FAT16_PARTITION = 0x06, /* DOS 16-bit >=32M */ - BLKID_HPFS_NTFS_PARTITION = 0x07, /* OS/2 IFS, eg, HPFS or NTFS or QNX */ - BLKID_AIX_PARTITION = 0x08, /* AIX boot (AIX -- PS/2 port) or SplitDrive */ - BLKID_AIX_BOOTABLE_PARTITION = 0x09, /* AIX data or Coherent */ - BLKID_OS2_BOOTMNGR_PARTITION = 0x0a, /* OS/2 Boot Manager */ - BLKID_W95_FAT32_PARTITION = 0x0b, - BLKID_W95_FAT32_LBA_PARTITION = 0x0c, /* LBA really is `Extended Int 13h' */ - BLKID_W95_FAT16_LBA_PARTITION = 0x0e, - BLKID_W95_EXTENDED_PARTITION = 0x0f, - BLKID_OPUS_PARTITION = 0x10, - BLKID_HIDDEN_FAT12_PARTITION = 0x11, - BLKID_COMPAQ_DIAGNOSTICS_PARTITION = 0x12, - BLKID_HIDDEN_FAT16_L32M_PARTITION = 0x14, - BLKID_HIDDEN_FAT16_PARTITION = 0x16, - BLKID_HIDDEN_HPFS_NTFS_PARTITION = 0x17, - BLKID_AST_SMARTSLEEP_PARTITION = 0x18, - BLKID_HIDDEN_W95_FAT32_PARTITION = 0x1b, - BLKID_HIDDEN_W95_FAT32LBA_PARTITION = 0x1c, - BLKID_HIDDEN_W95_FAT16LBA_PARTITION = 0x1e, - BLKID_NEC_DOS_PARTITION = 0x24, - BLKID_PLAN9_PARTITION = 0x39, - BLKID_PARTITIONMAGIC_PARTITION = 0x3c, - BLKID_VENIX80286_PARTITION = 0x40, - BLKID_PPC_PREP_BOOT_PARTITION = 0x41, - BLKID_SFS_PARTITION = 0x42, - BLKID_QNX_4X_PARTITION = 0x4d, - BLKID_QNX_4X_2ND_PARTITION = 0x4e, - BLKID_QNX_4X_3RD_PARTITION = 0x4f, - BLKID_DM_PARTITION = 0x50, - BLKID_DM6_AUX1_PARTITION = 0x51, /* (or Novell) */ - BLKID_CPM_PARTITION = 0x52, /* CP/M or Microport SysV/AT */ - BLKID_DM6_AUX3_PARTITION = 0x53, - BLKID_DM6_PARTITION = 0x54, - BLKID_EZ_DRIVE_PARTITION = 0x55, - BLKID_GOLDEN_BOW_PARTITION = 0x56, - BLKID_PRIAM_EDISK_PARTITION = 0x5c, - BLKID_SPEEDSTOR_PARTITION = 0x61, - BLKID_GNU_HURD_PARTITION = 0x63, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ - BLKID_UNIXWARE_PARTITION = BLKID_GNU_HURD_PARTITION, - BLKID_NETWARE_286_PARTITION = 0x64, - BLKID_NETWARE_386_PARTITION = 0x65, - BLKID_DISKSECURE_MULTIBOOT_PARTITION = 0x70, - BLKID_PC_IX_PARTITION = 0x75, - BLKID_OLD_MINIX_PARTITION = 0x80, /* Minix 1.4a and earlier */ - BLKID_MINIX_PARTITION = 0x81, /* Minix 1.4b and later */ - BLKID_LINUX_SWAP_PARTITION = 0x82, - BLKID_SOLARIS_X86_PARTITION = BLKID_LINUX_SWAP_PARTITION, - BLKID_LINUX_DATA_PARTITION = 0x83, - BLKID_OS2_HIDDEN_DRIVE_PARTITION = 0x84, - BLKID_LINUX_EXTENDED_PARTITION = 0x85, - BLKID_NTFS_VOL_SET1_PARTITION = 0x86, - BLKID_NTFS_VOL_SET2_PARTITION = 0x87, - BLKID_LINUX_PLAINTEXT_PARTITION = 0x88, - BLKID_LINUX_LVM_PARTITION = 0x8e, - BLKID_AMOEBA_PARTITION = 0x93, - BLKID_AMOEBA_BBT_PARTITION = 0x94, /* (bad block table) */ - BLKID_BSD_OS_PARTITION = 0x9f, /* BSDI */ - BLKID_THINKPAD_HIBERNATION_PARTITION = 0xa0, - BLKID_FREEBSD_PARTITION = 0xa5, /* various BSD flavours */ - BLKID_OPENBSD_PARTITION = 0xa6, - BLKID_NEXTSTEP_PARTITION = 0xa7, - BLKID_DARWIN_UFS_PARTITION = 0xa8, - BLKID_NETBSD_PARTITION = 0xa9, - BLKID_DARWIN_BOOT_PARTITION = 0xab, - BLKID_HFS_HFS_PARTITION = 0xaf, - BLKID_BSDI_FS_PARTITION = 0xb7, - BLKID_BSDI_SWAP_PARTITION = 0xb8, - BLKID_BOOTWIZARD_HIDDEN_PARTITION = 0xbb, - BLKID_SOLARIS_BOOT_PARTITION = 0xbe, - BLKID_SOLARIS_PARTITION = 0xbf, - BLKID_DRDOS_FAT12_PARTITION = 0xc1, - BLKID_DRDOS_FAT16_L32M_PARTITION = 0xc4, - BLKID_DRDOS_FAT16_PARTITION = 0xc6, - BLKID_SYRINX_PARTITION = 0xc7, - BLKID_NONFS_DATA_PARTITION = 0xda, - BLKID_CPM_CTOS_PARTITION = 0xdb, /* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */ - BLKID_DELL_UTILITY_PARTITION = 0xde, /* Dell PowerEdge Server utilities */ - BLKID_BOOTIT_PARTITION = 0xdf, /* BootIt EMBRM */ - BLKID_DOS_ACCESS_PARTITION = 0xe1, /* DOS access or SpeedStor 12-bit FAT extended partition */ - BLKID_DOS_RO_PARTITION = 0xe3, /* DOS R/O or SpeedStor */ - BLKID_SPEEDSTOR_EXTENDED_PARTITION = 0xe4, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */ - BLKID_BEOS_FS_PARTITION = 0xeb, - BLKID_GPT_PARTITION = 0xee, /* Intel EFI GUID Partition Table */ - BLKID_EFI_SYSTEM_PARTITION = 0xef, /* Intel EFI System Partition */ - BLKID_LINUX_PARISC_BOOT_PARTITION = 0xf0, /* Linux/PA-RISC boot loader */ - BLKID_SPEEDSTOR1_PARTITION = 0xf1, - BLKID_SPEEDSTOR2_PARTITION = 0xf4, /* SpeedStor large partition */ - BLKID_DOS_SECONDARY_PARTITION = 0xf2, /* DOS 3.3+ secondary */ - BLKID_VMWARE_VMFS_PARTITION = 0xfb, - BLKID_VMWARE_VMKCORE_PARTITION = 0xfc, /* VMware kernel dump partition */ - BLKID_LINUX_RAID_PARTITION = 0xfd, /* New (2.2.x) raid partition with autodetect using persistent superblock */ - BLKID_LANSTEP_PARTITION = 0xfe, /* SpeedStor >1024 cyl. or LANstep */ - BLKID_XENIX_BBT_PARTITION = 0xff, /* Xenix Bad Block Table */ -}; diff --git a/libblkid/src/partitions/bsd.c b/libblkid/src/partitions/bsd.c index 08fcad892..3de6a589e 100644 --- a/libblkid/src/partitions/bsd.c +++ b/libblkid/src/partitions/bsd.c @@ -14,90 +14,13 @@ #include <stdint.h> #include "partitions.h" - -#define BSD_MAXPARTITIONS 16 -#define BSD_FS_UNUSED 0 - -struct bsd_disklabel { - uint32_t d_magic; /* the magic number */ - int16_t d_type; /* drive type */ - int16_t d_subtype; /* controller/d_type specific */ - char d_typename[16]; /* type name, e.g. "eagle" */ - char d_packname[16]; /* pack identifier */ - - /* disk geometry: */ - uint32_t d_secsize; /* # of bytes per sector */ - uint32_t d_nsectors; /* # of data sectors per track */ - uint32_t d_ntracks; /* # of tracks per cylinder */ - uint32_t d_ncylinders; /* # of data cylinders per unit */ - uint32_t d_secpercyl; /* # of data sectors per cylinder */ - uint32_t d_secperunit; /* # of data sectors per unit */ - - /* - * Spares (bad sector replacements) below - * are not counted in d_nsectors or d_secpercyl. - * Spare sectors are assumed to be physical sectors - * which occupy space at the end of each track and/or cylinder. - */ - uint16_t d_sparespertrack; /* # of spare sectors per track */ - uint16_t d_sparespercyl; /* # of spare sectors per cylinder */ - - /* - * Alternate cylinders include maintenance, replacement, - * configuration description areas, etc. - */ - uint32_t d_acylinders; /* # of alt. cylinders per unit */ - - /* hardware characteristics: */ - /* - * d_interleave, d_trackskew and d_cylskew describe perturbations - * in the media format used to compensate for a slow controller. - * Interleave is physical sector interleave, set up by the formatter - * or controller when formatting. When interleaving is in use, - * logically adjacent sectors are not physically contiguous, - * but instead are separated by some number of sectors. - * It is specified as the ratio of physical sectors traversed - * per logical sector. Thus an interleave of 1:1 implies contiguous - * layout, while 2:1 implies that logical sector 0 is separated - * by one sector from logical sector 1. - * d_trackskew is the offset of sector 0 on track N - * relative to sector 0 on track N-1 on the same cylinder. - * Finally, d_cylskew is the offset of sector 0 on cylinder N - * relative to sector 0 on cylinder N-1. - */ - uint16_t d_rpm; /* rotational speed */ - uint16_t d_interleave; /* hardware sector interleave */ - uint16_t d_trackskew; /* sector 0 skew, per track */ - uint16_t d_cylskew; /* sector 0 skew, per cylinder */ - uint32_t d_headswitch; /* head switch time, usec */ - uint32_t d_trkseek; /* track-to-track seek, usec */ - uint32_t d_flags; /* generic flags */ - uint32_t d_drivedata[5]; /* drive-type specific information */ - uint32_t d_spare[5]; /* reserved for future use */ - uint32_t d_magic2; /* the magic number (again) */ - uint16_t d_checksum; /* xor of data incl. partitions */ - - /* filesystem and partition information: */ - uint16_t d_npartitions; /* number of partitions in following */ - uint32_t d_bbsize; /* size of boot area at sn0, bytes */ - uint32_t d_sbsize; /* max size of fs superblock, bytes */ - - struct bsd_partition { /* the partition table */ - uint32_t p_size; /* number of sectors in partition */ - uint32_t p_offset; /* starting sector */ - uint32_t p_fsize; /* filesystem basic fragment size */ - uint8_t p_fstype; /* filesystem type, see below */ - uint8_t p_frag; /* filesystem fragments per block */ - uint16_t p_cpg; /* filesystem cylinders per group */ - } __attribute__((packed)) d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */ -} __attribute__((packed)); - +#include "pt-bsd.h" /* Returns 'blkid_idmag' in 512-sectors */ -#define BLKID_MAG_SECTOR(_mag) (((_mag)->kboff * 2) + ((_mag)->sboff >> 9)) +#define BLKID_MAG_SECTOR(_mag) (((_mag)->kboff / 2) + ((_mag)->sboff >> 9)) /* Returns 'blkid_idmag' in bytes */ -#define BLKID_MAG_OFFSET(_mag) ((_mag)->kboff >> 10) + ((_mag)->sboff) +#define BLKID_MAG_OFFSET(_mag) ((_mag)->kboff << 10) + ((_mag)->sboff) /* Returns 'blkid_idmag' offset in bytes within the last sector */ #define BLKID_MAG_LASTOFFSET(_mag) \ @@ -133,13 +56,13 @@ static int probe_bsd_pt(blkid_probe pr, const struct blkid_idmag *mag) parent = blkid_partlist_get_parent(ls); if (parent) { switch(blkid_partition_get_type(parent)) { - case BLKID_FREEBSD_PARTITION: + case MBR_FREEBSD_PARTITION: name = "freebsd"; break; - case BLKID_NETBSD_PARTITION: + case MBR_NETBSD_PARTITION: name = "netbsd"; break; - case BLKID_OPENBSD_PARTITION: + case MBR_OPENBSD_PARTITION: name = "openbsd"; break; default: diff --git a/libblkid/src/partitions/dos.c b/libblkid/src/partitions/dos.c index 3a0a6d73e..14f326d20 100644 --- a/libblkid/src/partitions/dos.c +++ b/libblkid/src/partitions/dos.c @@ -14,7 +14,6 @@ #include <stdint.h> #include "partitions.h" -#include "dos.h" #include "aix.h" /* see superblocks/vfat.c */ @@ -24,19 +23,19 @@ static const struct dos_subtypes { unsigned char type; const struct blkid_idinfo *id; } dos_nested[] = { - { BLKID_FREEBSD_PARTITION, &bsd_pt_idinfo }, - { BLKID_NETBSD_PARTITION, &bsd_pt_idinfo }, - { BLKID_OPENBSD_PARTITION, &bsd_pt_idinfo }, - { BLKID_UNIXWARE_PARTITION, &unixware_pt_idinfo }, - { BLKID_SOLARIS_X86_PARTITION, &solaris_x86_pt_idinfo }, - { BLKID_MINIX_PARTITION, &minix_pt_idinfo } + { MBR_FREEBSD_PARTITION, &bsd_pt_idinfo }, + { MBR_NETBSD_PARTITION, &bsd_pt_idinfo }, + { MBR_OPENBSD_PARTITION, &bsd_pt_idinfo }, + { MBR_UNIXWARE_PARTITION, &unixware_pt_idinfo }, + { MBR_SOLARIS_X86_PARTITION, &solaris_x86_pt_idinfo }, + { MBR_MINIX_PARTITION, &minix_pt_idinfo } }; static inline int is_extended(struct dos_partition *p) { - return (p->sys_type == BLKID_DOS_EXTENDED_PARTITION || - p->sys_type == BLKID_W95_EXTENDED_PARTITION || - p->sys_type == BLKID_LINUX_EXTENDED_PARTITION); + return (p->sys_ind == MBR_DOS_EXTENDED_PARTITION || + p->sys_ind == MBR_W95_EXTENDED_PARTITION || + p->sys_ind == MBR_LINUX_EXTENDED_PARTITION); } static int parse_dos_extended(blkid_probe pr, blkid_parttable tab, @@ -58,10 +57,10 @@ static int parse_dos_extended(blkid_probe pr, blkid_parttable tab, if (!data) goto leave; /* malformed partition? */ - if (!is_valid_mbr_signature(data)) + if (!mbr_is_valid_magic(data)) goto leave; - p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET); + p0 = mbr_get_partition(data, 0); /* Usually, the first entry is the real data partition, * the 2nd entry is the next extended partition, or empty, @@ -80,8 +79,8 @@ static int parse_dos_extended(blkid_probe pr, blkid_parttable tab, blkid_partition par; /* the start is relative to the parental ext.partition */ - start = dos_partition_start(p) * ssf; - size = dos_partition_size(p) * ssf; + start = dos_partition_get_start(p) * ssf; + size = dos_partition_get_size(p) * ssf; abs_start = cur_start + start; /* absolute start */ if (!size || is_extended(p)) @@ -101,8 +100,9 @@ static int parse_dos_extended(blkid_probe pr, blkid_parttable tab, if (!par) goto err; - blkid_partition_set_type(par, p->sys_type); + blkid_partition_set_type(par, p->sys_ind); blkid_partition_set_flags(par, p->boot_ind); + blkid_partition_gen_uuid(par); ct_nodata = 0; } /* The first nested ext.partition should be a link to the next @@ -110,8 +110,8 @@ static int parse_dos_extended(blkid_probe pr, blkid_parttable tab, * is junk. */ for (p = p0, i = 0; i < 4; i++, p++) { - start = dos_partition_start(p) * ssf; - size = dos_partition_size(p) * ssf; + start = dos_partition_get_start(p) * ssf; + size = dos_partition_get_size(p) * ssf; if (size && is_extended(p)) break; @@ -138,6 +138,8 @@ static int probe_dos_pt(blkid_probe pr, struct dos_partition *p0, *p; unsigned char *data; uint32_t start, size, id; + char idstr[37]; + data = blkid_probe_get_sector(pr, 0); if (!data) @@ -157,7 +159,7 @@ static int probe_dos_pt(blkid_probe pr, goto nothing; } - p0 = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET); + p0 = mbr_get_partition(data, 0); /* * Reject PT where boot indicator is not 0 or 0x80. @@ -172,21 +174,28 @@ static int probe_dos_pt(blkid_probe pr, * GPT uses valid MBR */ for (p = p0, i = 0; i < 4; i++, p++) { - if (p->sys_type == BLKID_GPT_PARTITION) { + if (p->sys_ind == MBR_GPT_PARTITION) { DBG(LOWPROBE, blkid_debug("probably GPT -- ignore")); goto nothing; } } - blkid_probe_use_wiper(pr, BLKID_MSDOS_PT_OFFSET, - 512 - BLKID_MSDOS_PT_OFFSET); + blkid_probe_use_wiper(pr, MBR_PT_OFFSET, 512 - MBR_PT_OFFSET); + + id = mbr_get_id(data); + if (id) + snprintf(idstr, sizeof(idstr), "%08x", id); /* * Well, all checks pass, it's MS-DOS partiton table */ - if (blkid_partitions_need_typeonly(pr)) - /* caller does not ask for details about partitions */ + if (blkid_partitions_need_typeonly(pr)) { + /* Non-binary interface -- caller does not ask for details + * about partitions, just set generic varibles only. */ + if (id) + blkid_partitions_strcpy_ptuuid(pr, idstr); return 0; + } ls = blkid_probe_get_partlist(pr); @@ -196,25 +205,19 @@ static int probe_dos_pt(blkid_probe pr, ssf = blkid_probe_get_sectorsize(pr) / 512; /* allocate a new partition table */ - tab = blkid_partlist_new_parttable(ls, "dos", BLKID_MSDOS_PT_OFFSET); + tab = blkid_partlist_new_parttable(ls, "dos", MBR_PT_OFFSET); if (!tab) goto err; - id = dos_parttable_id(data); - if (id) { - char buf[37]; - - snprintf(buf, sizeof(buf), "0x%08x", id); - blkid_parttable_set_id(tab, (unsigned char *) buf); - } - + if (id) + blkid_parttable_set_id(tab, (unsigned char *) idstr); /* Parse primary partitions */ for (p = p0, i = 0; i < 4; i++, p++) { blkid_partition par; - start = dos_partition_start(p) * ssf; - size = dos_partition_size(p) * ssf; + start = dos_partition_get_start(p) * ssf; + size = dos_partition_get_size(p) * ssf; if (!size) { /* Linux kernel ignores empty partitions, but partno for @@ -226,8 +229,9 @@ static int probe_dos_pt(blkid_probe pr, if (!par) goto err; - blkid_partition_set_type(par, p->sys_type); + blkid_partition_set_type(par, p->sys_ind); blkid_partition_set_flags(par, p->boot_ind); + blkid_partition_gen_uuid(par); } /* Linux uses partition numbers greater than 4 @@ -237,8 +241,8 @@ static int probe_dos_pt(blkid_probe pr, /* Parse logical partitions */ for (p = p0, i = 0; i < 4; i++, p++) { - start = dos_partition_start(p) * ssf; - size = dos_partition_size(p) * ssf; + start = dos_partition_get_start(p) * ssf; + size = dos_partition_get_size(p) * ssf; if (!size) continue; @@ -252,11 +256,11 @@ static int probe_dos_pt(blkid_probe pr, for (p = p0, i = 0; i < 4; i++, p++) { size_t n; - if (!dos_partition_size(p) || is_extended(p)) + if (!dos_partition_get_size(p) || is_extended(p)) continue; for (n = 0; n < ARRAY_SIZE(dos_nested); n++) { - if (dos_nested[n].type != p->sys_type) + if (dos_nested[n].type != p->sys_ind) continue; if (blkid_partitions_do_subprobe(pr, diff --git a/libblkid/src/partitions/dos.h b/libblkid/src/partitions/dos.h deleted file mode 100644 index d7588a856..000000000 --- a/libblkid/src/partitions/dos.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef BLKID_PARTITIONS_DOS_H -#define BLKID_PARTITIONS_DOS_H - -struct dos_partition { - unsigned char boot_ind; /* 0x80 - active */ - unsigned char bh, bs, bc; /* begin CHS */ - unsigned char sys_type; - unsigned char eh, es, ec; /* end CHS */ - unsigned char start_sect[4]; - unsigned char nr_sects[4]; -} __attribute__((packed)); - -#define BLKID_MSDOS_PT_OFFSET 0x1be - -/* assemble badly aligned little endian integer */ -static inline unsigned int assemble4le(const unsigned char *p) -{ - return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); -} - -static inline unsigned int dos_partition_start(struct dos_partition *p) -{ - return assemble4le(&(p->start_sect[0])); -} - -static inline unsigned int dos_partition_size(struct dos_partition *p) -{ - return assemble4le(&(p->nr_sects[0])); -} - -static inline int is_valid_mbr_signature(const unsigned char *mbr) -{ - return mbr[510] == 0x55 && mbr[511] == 0xaa ? 1 : 0; -} - -static inline unsigned int dos_parttable_id(const unsigned char *mbr) -{ - return assemble4le(&mbr[440]); -} - -#endif /* BLKID_PARTITIONS_DOS_H */ diff --git a/libblkid/src/partitions/gpt.c b/libblkid/src/partitions/gpt.c index 444193929..14a255af6 100644 --- a/libblkid/src/partitions/gpt.c +++ b/libblkid/src/partitions/gpt.c @@ -20,7 +20,6 @@ #include "partitions.h" #include "crc32.h" -#include "dos.h" #define GPT_PRIMARY_LBA 1 @@ -156,13 +155,15 @@ static int last_lba(blkid_probe pr, uint64_t *lba) * Note that the PMBR detection is optional (enabled by default) and could be * disabled by BLKID_PARTS_FOPCE_GPT flag (see also blkid_paertitions_set_flags()). */ -static int is_pmbr_valid(blkid_probe pr) +static int is_pmbr_valid(blkid_probe pr, int *has) { int flags = blkid_partitions_get_flags(pr); unsigned char *data; struct dos_partition *p; int i; + if (has) + *has = 0; if (flags & BLKID_PARTS_FORCE_GPT) goto ok; /* skip PMBR check */ @@ -170,18 +171,18 @@ static int is_pmbr_valid(blkid_probe pr) if (!data) goto failed; - if (!is_valid_mbr_signature(data)) + if (!mbr_is_valid_magic(data)) goto failed; - p = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET); - - for (i = 0; i < 4; i++, p++) { - if (p->sys_type == BLKID_GPT_PARTITION) + for (i = 0, p = mbr_get_partition(data, 0); i < 4; i++, p++) { + if (p->sys_ind == MBR_GPT_PARTITION) goto ok; } failed: return 0; ok: + if (has) + *has = 1; return 1; } @@ -305,7 +306,7 @@ static int probe_gpt_pt(blkid_probe pr, if (last_lba(pr, &lastlba)) goto nothing; - if (!is_pmbr_valid(pr)) + if (!is_pmbr_valid(pr, NULL)) goto nothing; h = get_gpt_header(pr, &hdr, &e, (lba = GPT_PRIMARY_LBA), lastlba); @@ -322,9 +323,15 @@ static int probe_gpt_pt(blkid_probe pr, (unsigned char *) GPT_HEADER_SIGNATURE_STR)) goto err; - if (blkid_partitions_need_typeonly(pr)) - /* caller does not ask for details about partitions */ + guid = h->disk_guid; + swap_efi_guid(&guid); + + if (blkid_partitions_need_typeonly(pr)) { + /* Non-binary interface -- caller does not ask for details + * about partitions, just set generic varibles only. */ + blkid_partitions_set_ptuuid(pr, (unsigned char *) &guid); return 0; + } ls = blkid_probe_get_partlist(pr); if (!ls) @@ -334,9 +341,7 @@ static int probe_gpt_pt(blkid_probe pr, if (!tab) goto err; - guid = h->disk_guid; - swap_efi_guid(&guid); - blkid_parttable_set_id(tab, (const unsigned char *) &guid); + blkid_parttable_set_uuid(tab, (const unsigned char *) &guid); ssf = blkid_probe_get_sectorsize(pr) / 512; @@ -410,3 +415,39 @@ const struct blkid_idinfo gpt_pt_idinfo = .magics = BLKID_NONE_MAGIC }; + + +/* probe for *alone* protective MBR */ +static int probe_pmbr_pt(blkid_probe pr, + const struct blkid_idmag *mag __attribute__((__unused__))) +{ + int has = 0; + struct gpt_entry *e; + uint64_t lastlba = 0; + struct gpt_header hdr; + + if (last_lba(pr, &lastlba)) + goto nothing; + + is_pmbr_valid(pr, &has); + if (!has) + goto nothing; + + if (!get_gpt_header(pr, &hdr, &e, GPT_PRIMARY_LBA, lastlba) && + !get_gpt_header(pr, &hdr, &e, lastlba, lastlba)) + return 0; +nothing: + return 1; +} + +const struct blkid_idinfo pmbr_pt_idinfo = +{ + .name = "PMBR", + .probefunc = probe_pmbr_pt, + .magics = + { + { .magic = "\x55\xAA", .len = 2, .sboff = 510 }, + { NULL } + } +}; + diff --git a/libblkid/src/partitions/minix.c b/libblkid/src/partitions/minix.c index 0cd9f432e..0a597fbc4 100644 --- a/libblkid/src/partitions/minix.c +++ b/libblkid/src/partitions/minix.c @@ -12,7 +12,6 @@ #include <stdint.h> #include "partitions.h" -#include "dos.h" #include "minix.h" static int probe_minix_pt(blkid_probe pr, @@ -40,28 +39,28 @@ static int probe_minix_pt(blkid_probe pr, if (!parent) goto nothing; - if (blkid_partition_get_type(parent) != BLKID_MINIX_PARTITION) + if (blkid_partition_get_type(parent) != MBR_MINIX_PARTITION) goto nothing; if (blkid_partitions_need_typeonly(pr)) /* caller does not ask for details about partitions */ return 0; - p = (struct dos_partition *) (data + BLKID_MSDOS_PT_OFFSET); - - tab = blkid_partlist_new_parttable(ls, "minix", BLKID_MSDOS_PT_OFFSET); + tab = blkid_partlist_new_parttable(ls, "minix", MBR_PT_OFFSET); if (!tab) goto err; - for (i = 0; i < MINIX_MAXPARTITIONS; i++, p++) { + for (i = 0, p = mbr_get_partition(data, 0); + i < MINIX_MAXPARTITIONS; i++, p++) { + uint32_t start, size; blkid_partition par; - if (p->sys_type != BLKID_MINIX_PARTITION) + if (p->sys_ind != MBR_MINIX_PARTITION) continue; - start = dos_partition_start(p); - size = dos_partition_size(p); + start = dos_partition_get_start(p); + size = dos_partition_get_size(p); if (parent && !blkid_is_nested_dimension(parent, start, size)) { DBG(LOWPROBE, blkid_debug( @@ -74,7 +73,7 @@ static int probe_minix_pt(blkid_probe pr, if (!par) goto err; - blkid_partition_set_type(par, p->sys_type); + blkid_partition_set_type(par, p->sys_ind); blkid_partition_set_flags(par, p->boot_ind); } diff --git a/libblkid/src/partitions/partitions.c b/libblkid/src/partitions/partitions.c index 87ca0c1f8..6c915d92f 100644 --- a/libblkid/src/partitions/partitions.c +++ b/libblkid/src/partitions/partitions.c @@ -37,6 +37,8 @@ * * @PTTYPE: partition table type (dos, gpt, etc.). * + * @PTUUID: partition table id (uuid for gpt, hex for dos). + * @PART_ENTRY_SCHEME: partition table type * * @PART_ENTRY_NAME: partition name (gpt and mac only) @@ -125,6 +127,7 @@ static const struct blkid_idinfo *idinfos[] = &sun_pt_idinfo, &dos_pt_idinfo, &gpt_pt_idinfo, + &pmbr_pt_idinfo, /* always after GPT */ &mac_pt_idinfo, &ultrix_pt_idinfo, &bsd_pt_idinfo, @@ -601,11 +604,16 @@ static int partitions_probe(blkid_probe pr, struct blkid_chain *chn) name = idinfos[i]->name; - /* all checks passed */ if (!chn->binary) + /* + * Non-binary interface, set generic variables. Note + * that the another variables could be set in prober + * functions. + */ blkid_probe_set_value(pr, "PTTYPE", (unsigned char *) name, strlen(name) + 1); + DBG(LOWPROBE, blkid_debug("<-- leaving probing loop (type=%s) [PARTS idx=%d]", name, chn->idx)); rc = 0; @@ -994,19 +1002,69 @@ blkid_partition blkid_partlist_devno_to_partition(blkid_partlist ls, dev_t devno return NULL; } +int blkid_parttable_set_uuid(blkid_parttable tab, const unsigned char *id) +{ + if (!tab) + return -1; + + blkid_unparse_uuid(id, tab->id, sizeof(tab->id)); + return 0; +} + int blkid_parttable_set_id(blkid_parttable tab, const unsigned char *id) { if (!tab) return -1; - if (strcmp(tab->type, "gpt") == 0) - blkid_unparse_uuid(id, tab->id, sizeof(tab->id)); - else if (strcmp(tab->type, "dos") == 0) - strncpy(tab->id, (const char *) id, sizeof(tab->id)); + strncpy(tab->id, (const char *) id, sizeof(tab->id)); + return 0; +} + +/* set PTUUID variable for non-binary API */ +int blkid_partitions_set_ptuuid(blkid_probe pr, unsigned char *uuid) +{ + struct blkid_chain *chn = blkid_probe_get_chain(pr); + struct blkid_prval *v; + + if (chn->binary || blkid_uuid_is_empty(uuid, 16)) + return 0; + + v = blkid_probe_assign_value(pr, "PTUUID"); + + blkid_unparse_uuid(uuid, (char *) v->data, sizeof(v->data)); + v->len = 37; return 0; } +/* set PTUUID variable for non-binary API for tables where + * the ID is just a string */ +int blkid_partitions_strcpy_ptuuid(blkid_probe pr, char *str) +{ + struct blkid_chain *chn = blkid_probe_get_chain(pr); + struct blkid_prval *v; + size_t len; + + if (chn->binary || !str || !*str) + return 0; + + len = strlen((char *) str); + if (len > BLKID_PROBVAL_BUFSIZ) + len = BLKID_PROBVAL_BUFSIZ; + + v = blkid_probe_assign_value(pr, "PTUUID"); + if (v) { + if (len == BLKID_PROBVAL_BUFSIZ) + len--; /* make a space for \0 */ + + memcpy((char *) v->data, str, len); + v->data[len] = '\0'; + v->len = len + 1; + return 0; + } + return -1; +} + /** * blkid_parttable_get_id: * @tab: partition table @@ -1134,9 +1192,9 @@ static int partition_get_logical_type(blkid_partition par) if (par->partno > 4) return 'L'; /* logical */ - if(par->type == BLKID_DOS_EXTENDED_PARTITION || - par->type == BLKID_W95_EXTENDED_PARTITION || - par->type == BLKID_LINUX_EXTENDED_PARTITION) + if(par->type == MBR_DOS_EXTENDED_PARTITION || + par->type == MBR_W95_EXTENDED_PARTITION || + par->type == MBR_LINUX_EXTENDED_PARTITION) return 'E'; } return 'P'; @@ -1224,6 +1282,16 @@ int blkid_partition_set_uuid(blkid_partition par, const unsigned char *uuid) return 0; } +int blkid_partition_gen_uuid(blkid_partition par) +{ + if (!par || !par->tab || !*par->tab->id) + return -1; + + snprintf(par->uuid, sizeof(par->uuid), "%s-%02x", + par->tab->id, par->partno); + return 0; +} + /** * blkid_partition_get_name: * @par: partition diff --git a/libblkid/src/partitions/partitions.h b/libblkid/src/partitions/partitions.h index 496bd4a1e..3651bbb4d 100644 --- a/libblkid/src/partitions/partitions.h +++ b/libblkid/src/partitions/partitions.h @@ -2,13 +2,14 @@ #define BLKID_PARTITIONS_H #include "blkidP.h" -#include "blkid_parttypes.h" +#include "pt-mbr.h" extern int blkid_partitions_get_flags(blkid_probe pr); extern blkid_parttable blkid_partlist_new_parttable(blkid_partlist ls, const char *type, blkid_loff_t offset); +extern int blkid_parttable_set_uuid(blkid_parttable tab, const unsigned char *id); extern int blkid_parttable_set_id(blkid_parttable tab, const unsigned char *id); extern blkid_partition blkid_partlist_add_partition(blkid_partlist ls, @@ -24,6 +25,10 @@ extern int blkid_partitions_do_subprobe(blkid_probe pr, blkid_partition parent, const struct blkid_idinfo *id); extern int blkid_partitions_need_typeonly(blkid_probe pr); +extern int blkid_partitions_set_ptuuid(blkid_probe pr, unsigned char *uuid); +extern int blkid_partitions_strcpy_ptuuid(blkid_probe pr, char *str); + + extern int blkid_is_nested_dimension(blkid_partition par, blkid_loff_t start, blkid_loff_t size); @@ -35,6 +40,7 @@ extern int blkid_partition_set_utf8name(blkid_partition par, extern int blkid_partition_set_uuid(blkid_partition par, const unsigned char *uuid); +extern int blkid_partition_gen_uuid(blkid_partition par); extern int blkid_partition_set_type(blkid_partition par, int type); @@ -59,6 +65,7 @@ extern const struct blkid_idinfo mac_pt_idinfo; extern const struct blkid_idinfo dos_pt_idinfo; extern const struct blkid_idinfo minix_pt_idinfo; extern const struct blkid_idinfo gpt_pt_idinfo; +extern const struct blkid_idinfo pmbr_pt_idinfo; extern const struct blkid_idinfo ultrix_pt_idinfo; #endif /* BLKID_PARTITIONS_H */ diff --git a/libblkid/src/partitions/sgi.c b/libblkid/src/partitions/sgi.c index b292e7150..bcde84f2a 100644 --- a/libblkid/src/partitions/sgi.c +++ b/libblkid/src/partitions/sgi.c @@ -13,81 +13,7 @@ #include <stdint.h> #include "partitions.h" - -#define SGI_MAXPARTITIONS 16 - -/* partition type */ -#define SGI_TYPE_VOLHDR 0x00 -#define SGI_TYPE_VOLULME 0x06 /* entire disk */ - -struct sgi_device_parameter { - unsigned char skew; - unsigned char gap1; - unsigned char gap2; - unsigned char sparecyl; - - uint16_t pcylcount; - uint16_t head_vol0; - uint16_t ntrks; /* tracks in cyl 0 or vol 0 */ - - unsigned char cmd_tag_queue_depth; - unsigned char unused0; - - uint16_t unused1; - uint16_t nsect; /* sectors/tracks in cyl 0 or vol 0 */ - uint16_t bytes; - uint16_t ilfact; - uint32_t flags; /* controller flags */ - uint32_t datarate; - uint32_t retries_on_error; - uint32_t ms_per_word; - uint16_t xylogics_gap1; - uint16_t xylogics_syncdelay; - uint16_t xylogics_readdelay; - uint16_t xylogics_gap2; - uint16_t xylogics_readgate; - uint16_t xylogics_writecont; -} __attribute__((packed)); - -struct sgi_disklabel { - uint32_t magic; /* magic number */ - uint16_t root_part_num; /* # root partition */ - uint16_t swap_part_num; /* # swap partition */ - unsigned char boot_file[16]; /* name of boot file */ - - struct sgi_device_parameter devparam; /* not used now */ - - struct sgi_volume { - unsigned char name[8]; /* name of volume */ - uint32_t block_num; /* logical block number */ - uint32_t num_bytes; /* how big, in bytes */ - } __attribute__((packed)) volume[15]; - - struct sgi_partition { - uint32_t num_blocks; /* size in logical blocks */ - uint32_t first_block; /* first logical block */ - uint32_t type; /* type of this partition */ - } __attribute__((packed)) partitions[SGI_MAXPARTITIONS]; - - /* checksum is the 32bit 2's complement sum of the disklabel */ - uint32_t csum; /* disk label checksum */ - uint32_t padding; /* padding */ -} __attribute__((packed)); - -static uint32_t count_checksum(struct sgi_disklabel *label) -{ - int i; - uint32_t *ptr = (uint32_t *) label; - uint32_t sum = 0; - - i = sizeof(*label) / sizeof(*ptr); - - while (i--) - sum += be32_to_cpu(ptr[i]); - - return sum; -} - +#include "pt-sgi.h" static int probe_sgi_pt(blkid_probe pr, const struct blkid_idmag *mag __attribute__((__unused__))) @@ -102,7 +28,7 @@ static int probe_sgi_pt(blkid_probe pr, if (!l) goto nothing; - if (count_checksum(l)) { + if (sgi_pt_checksum(l)) { DBG(LOWPROBE, blkid_debug( "detected corrupted sgi disk label -- ignore")); goto nothing; @@ -126,7 +52,7 @@ static int probe_sgi_pt(blkid_probe pr, uint32_t type = be32_to_cpu(p->type); blkid_partition par; - if (size == 0 || type == SGI_TYPE_VOLULME || + if (size == 0 || type == SGI_TYPE_ENTIRE_DISK || type == SGI_TYPE_VOLHDR) { blkid_partlist_increment_partno(ls); continue; diff --git a/libblkid/src/probe.c b/libblkid/src/probe.c index 954b08708..4b0c99796 100644 --- a/libblkid/src/probe.c +++ b/libblkid/src/probe.c @@ -336,6 +336,16 @@ struct blkid_chain *blkid_probe_get_chain(blkid_probe pr) return pr->cur_chain; } +static const char *blkid_probe_get_probername(blkid_probe pr) +{ + struct blkid_chain *chn = blkid_probe_get_chain(pr); + + if (chn && chn->idx >= 0 && chn->idx < chn->driver->nidinfos) + return chn->driver->idinfos[chn->idx]->name; + + return NULL; +} + void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn) { int rc, org_prob_flags; @@ -1341,6 +1351,31 @@ int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset, return rc; } +int blkid_probe_verify_csum(blkid_probe pr, uint64_t csum, uint64_t expected) +{ + if (csum != expected) { + struct blkid_chain *chn = blkid_probe_get_chain(pr); + + DBG(LOWPROBE, blkid_debug( + "incorrect checksum for type %s," + " got %jX, expected %jX", + blkid_probe_get_probername(pr), + csum, expected)); + /* + * Accept bad checksum if BLKID_SUBLKS_BADCSUM flags is set + */ + if (chn->driver->id == BLKID_CHAIN_SUBLKS + && (chn->flags & BLKID_SUBLKS_BADCSUM)) { + blkid_probe_set_value(pr, "SBBADCSUM", (unsigned char *) "1", 2); + goto accept; + } + return 0; /* bad checksum */ + } + +accept: + return 1; +} + /** * blkid_probe_get_devno: * @pr: probe @@ -1637,6 +1672,16 @@ void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len) } #endif +/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */ +int blkid_uuid_is_empty(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + if (buf[i]) + return 0; + return 1; +} /* Removes whitespace from the right-hand side of a string (trailing * whitespace). diff --git a/libblkid/src/save.c b/libblkid/src/save.c index 86eda6cbc..424017a32 100644 --- a/libblkid/src/save.c +++ b/libblkid/src/save.c @@ -21,6 +21,9 @@ #ifdef HAVE_ERRNO_H #include <errno.h> #endif + +#include "closestream.h" + #include "blkidP.h" static int save_dev(blkid_dev dev, FILE *file) @@ -148,7 +151,9 @@ int blkid_flush_cache(blkid_cache cache) ret = 1; } - fclose(file); + if (close_stream(file) != 0) + DBG(SAVE, blkid_debug("write failed: %s", filename)); + if (opened != filename) { if (ret < 0) { unlink(opened); diff --git a/libblkid/src/superblocks/bcache.c b/libblkid/src/superblocks/bcache.c new file mode 100644 index 000000000..303f7eeb9 --- /dev/null +++ b/libblkid/src/superblocks/bcache.c @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2013 Rolf Fokkens <rolf@fokkens.nl> + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + * + * Based on code fragments from bcache-tools by Kent Overstreet: + * http://evilpiepirate.org/git/bcache-tools.git + */ + +#include <stddef.h> +#include <stdio.h> + +#include "superblocks.h" +#include "crc64.h" + +#define SB_LABEL_SIZE 32 +#define SB_JOURNAL_BUCKETS 256U + +#define node(i, j) ((i)->d + (j)) +#define end(i) node(i, (i)->keys) + +static const char bcache_magic[] = { + 0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca, + 0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81 +}; + +struct bcache_super_block { + uint64_t csum; + uint64_t offset; /* sector where this sb was written */ + uint64_t version; + + uint8_t magic[16]; + + uint8_t uuid[16]; + union { + uint8_t set_uuid[16]; + uint64_t set_magic; + }; + uint8_t label[SB_LABEL_SIZE]; + + uint64_t flags; + uint64_t seq; + uint64_t pad[8]; + + union { + struct { + /* Cache devices */ + uint64_t nbuckets; /* device size */ + + uint16_t block_size; /* sectors */ + uint16_t bucket_size; /* sectors */ + + uint16_t nr_in_set; + uint16_t nr_this_dev; + }; + struct { + /* Backing devices */ + uint64_t data_offset; + + /* + * block_size from the cache device section is still used by + * backing devices, so don't add anything here until we fix + * things to not need it for backing devices anymore + */ + }; + }; + + uint32_t last_mount; /* time_t */ + + uint16_t first_bucket; + union { + uint16_t njournal_buckets; + uint16_t keys; + }; + uint64_t d[SB_JOURNAL_BUCKETS]; /* journal buckets */ +}; + +/* magic string */ +#define BCACHE_SB_MAGIC bcache_magic +/* magic string len */ +#define BCACHE_SB_MAGIC_LEN sizeof (bcache_magic) +/* super block offset */ +#define BCACHE_SB_OFF 0x1000 +/* supper block offset in kB */ +#define BCACHE_SB_KBOFF (BCACHE_SB_OFF >> 10) +/* magic string offset within super block */ +#define BCACHE_SB_MAGIC_OFF offsetof (struct bcache_super_block, magic) + +static uint64_t bcache_crc64(struct bcache_super_block *bcs) +{ + unsigned char *data = (unsigned char *) bcs; + size_t sz; + + data += 8; /* skip csum field */ + sz = (unsigned char *) end(bcs) - data; + + return crc64(0xFFFFFFFFFFFFFFFFULL, data, sz) ^ 0xFFFFFFFFFFFFFFFFULL; +} + +static int probe_bcache (blkid_probe pr, const struct blkid_idmag *mag) +{ + struct bcache_super_block *bcs; + + bcs = blkid_probe_get_sb(pr, mag, struct bcache_super_block); + if (!bcs) + return -1; + + if (le64_to_cpu(bcs->offset) != BCACHE_SB_OFF / 512) + return 1; + if (!blkid_probe_verify_csum(pr, bcache_crc64(bcs), le64_to_cpu(bcs->csum))) + return 1; + + if (blkid_probe_set_uuid(pr, bcs->uuid) < 0) + return -1; + + return 0; +}; + +const struct blkid_idinfo bcache_idinfo = +{ + .name = "bcache", + .usage = BLKID_USAGE_OTHER, + .probefunc = probe_bcache, + .minsz = 8192, + .magics = + { + { .magic = BCACHE_SB_MAGIC + , .len = BCACHE_SB_MAGIC_LEN + , .kboff = BCACHE_SB_KBOFF + , .sboff = BCACHE_SB_MAGIC_OFF + } , + { NULL } + } +}; + diff --git a/libblkid/src/superblocks/ext.c b/libblkid/src/superblocks/ext.c index c23959322..8d57cb5e4 100644 --- a/libblkid/src/superblocks/ext.c +++ b/libblkid/src/superblocks/ext.c @@ -333,6 +333,8 @@ static int probe_jbd(blkid_probe pr, return -BLKID_ERR_PARAM; ext_get_info(pr, 2, es); + blkid_probe_set_uuid_as(pr, es->s_uuid, "LOGUUID"); + return 0; } diff --git a/libblkid/src/superblocks/lvm.c b/libblkid/src/superblocks/lvm.c index dc38f2e2c..65c7c35a4 100644 --- a/libblkid/src/superblocks/lvm.c +++ b/libblkid/src/superblocks/lvm.c @@ -97,13 +97,12 @@ static int probe_lvm2(blkid_probe pr, const struct blkid_idmag *mag) if (le64_to_cpu(label->sector_xl) != (unsigned) sector) return 1; - if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE - - ((char *) &label->offset_xl - (char *) label)) != - le32_to_cpu(label->crc_xl)) { - DBG(PROBE, blkid_debug("LVM2: label checksum incorrect at sector %d", - sector)); + if (!blkid_probe_verify_csum( + pr, lvm2_calc_crc( + &label->offset_xl, LVM2_LABEL_SIZE - + ((char *) &label->offset_xl - (char *) label)), + le32_to_cpu(label->crc_xl))) return 1; - } format_lvm_uuid(uuid, (char *) label->pv_uuid); blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid), diff --git a/libblkid/src/superblocks/nilfs.c b/libblkid/src/superblocks/nilfs.c index 1f8f3a69f..24ccf633e 100644 --- a/libblkid/src/superblocks/nilfs.c +++ b/libblkid/src/superblocks/nilfs.c @@ -63,35 +63,60 @@ struct nilfs_super_block { 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 +#define NILFS_SB_MAGIC 0x3434 +#define NILFS_SB_OFFSET 0x400 -static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag) +static int nilfs_valid_sb(blkid_probe pr, struct nilfs_super_block *sb) { - 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; + if (!sb || le16_to_cpu(sb->s_magic) != NILFS_SB_MAGIC) + return 0; bytes = le16_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 blkid_probe_verify_csum(pr, crc, le32_to_cpu(sb->s_sum)); +} + +static int probe_nilfs2(blkid_probe pr, const struct blkid_idmag *mag) +{ + struct nilfs_super_block *sb, *sbp, *sbb; + int valid[2], swp = 0; + + /* primary */ + sbp = (struct nilfs_super_block *) blkid_probe_get_buffer( + pr, NILFS_SB_OFFSET, sizeof(struct nilfs_super_block)); + if (!sbp) + return -1; + /* backup */ + sbb = (struct nilfs_super_block *) blkid_probe_get_buffer( + pr, ((pr->size / 0x200) - 8) * 0x200, sizeof(struct nilfs_super_block)); + if (!sbp) return -1; + /* + * Compare two super blocks and set 1 in swp if the secondary + * super block is valid and newer. Otherwise, set 0 in swp. + */ + valid[0] = nilfs_valid_sb(pr, sbp); + valid[1] = nilfs_valid_sb(pr, sbb); + if (!valid[0] && !valid[1]) + return 1; + + swp = valid[1] && (!valid[0] || + le64_to_cpu(sbp->s_last_cno) > + le64_to_cpu(sbb->s_last_cno)); + sb = swp ? sbb : sbp; + + DBG(LOWPROBE, blkid_debug("nilfs2: primary=%d, backup=%d, swap=%d", + valid[0], valid[1], swp)); + if (strlen(sb->s_volume_name)) blkid_probe_set_label(pr, (unsigned char *) sb->s_volume_name, sizeof(sb->s_volume_name)); @@ -107,14 +132,7 @@ 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 } - } + /* default min.size is 128MiB, but 1MiB for "mkfs.nilfs2 -b 1024 -B 16" */ + .minsz = (1024 * 1024), + .magics = BLKID_NONE_MAGIC }; diff --git a/libblkid/src/superblocks/silicon_raid.c b/libblkid/src/superblocks/silicon_raid.c index aeab4bf31..10a302313 100644 --- a/libblkid/src/superblocks/silicon_raid.c +++ b/libblkid/src/superblocks/silicon_raid.c @@ -67,7 +67,7 @@ struct silicon_metadata { #define SILICON_MAGIC 0x2F000000 -static int checksum(struct silicon_metadata *sil) +static uint16_t silraid_checksum(struct silicon_metadata *sil) { int sum = 0; unsigned short count = offsetof(struct silicon_metadata, checksum1) / 2; @@ -78,7 +78,7 @@ static int checksum(struct silicon_metadata *sil) sum += le16_to_cpu(x); } - return (-sum & 0xFFFF) == le16_to_cpu(sil->checksum1); + return (-sum & 0xFFFF); } static int probe_silraid(blkid_probe pr, @@ -101,13 +101,11 @@ static int probe_silraid(blkid_probe pr, return -1; if (le32_to_cpu(sil->magic) != SILICON_MAGIC) - return -1; + return 1; if (sil->disk_number >= 8) - return -1; - if (!checksum(sil)) { - DBG(LOWPROBE, blkid_debug("silicon raid: incorrect checksum")); - return -1; - } + return 1; + if (!blkid_probe_verify_csum(pr, silraid_checksum(sil), le16_to_cpu(sil->checksum1))) + return 1; if (blkid_probe_sprintf_version(pr, "%u.%u", le16_to_cpu(sil->major_ver), diff --git a/libblkid/src/superblocks/superblocks.c b/libblkid/src/superblocks/superblocks.c index 03bcabc91..c6394c4b3 100644 --- a/libblkid/src/superblocks/superblocks.c +++ b/libblkid/src/superblocks/superblocks.c @@ -49,6 +49,8 @@ * * @UUID_SUB: subvolume uuid (e.g. btrfs) * + * @LOGUUID: external log UUID (e.g. xfs) + * * @UUID_RAW: raw UUID from FS superblock * * @EXT_JOURNAL: external journal UUID @@ -99,6 +101,7 @@ static const struct blkid_idinfo *idinfos[] = &adraid_idinfo, &jmraid_idinfo, + &bcache_idinfo, &drbd_idinfo, &drbdproxy_datalog_idinfo, &lvm2_idinfo, @@ -113,6 +116,7 @@ static const struct blkid_idinfo *idinfos[] = &swsuspend_idinfo, &swap_idinfo, &xfs_idinfo, + &xfs_log_idinfo, &ext4dev_idinfo, &ext4_idinfo, &ext3_idinfo, @@ -617,17 +621,6 @@ int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label, return 0; } -/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */ -static int uuid_is_empty(const unsigned char *buf, size_t len) -{ - size_t i; - - for (i = 0; i < len; i++) - if (buf[i]) - return 0; - return 1; -} - int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid, size_t len, const char *fmt, ...) { @@ -638,7 +631,7 @@ int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid, if (len > BLKID_PROBVAL_BUFSIZ) len = BLKID_PROBVAL_BUFSIZ; - if (uuid_is_empty(uuid, len)) + if (blkid_uuid_is_empty(uuid, len)) return 0; if ((chn->flags & BLKID_SUBLKS_UUIDRAW) && @@ -703,7 +696,7 @@ int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *nam struct blkid_chain *chn = blkid_probe_get_chain(pr); struct blkid_prval *v; - if (uuid_is_empty(uuid, 16)) + if (blkid_uuid_is_empty(uuid, 16)) return 0; if (!name) { diff --git a/libblkid/src/superblocks/superblocks.h b/libblkid/src/superblocks/superblocks.h index 2e5235113..2cae66a41 100644 --- a/libblkid/src/superblocks/superblocks.h +++ b/libblkid/src/superblocks/superblocks.h @@ -29,6 +29,7 @@ extern const struct blkid_idinfo ext2_idinfo; extern const struct blkid_idinfo jbd_idinfo; extern const struct blkid_idinfo jfs_idinfo; extern const struct blkid_idinfo xfs_idinfo; +extern const struct blkid_idinfo xfs_log_idinfo; extern const struct blkid_idinfo gfs_idinfo; extern const struct blkid_idinfo gfs2_idinfo; extern const struct blkid_idinfo romfs_idinfo; @@ -71,6 +72,7 @@ extern const struct blkid_idinfo befs_idinfo; extern const struct blkid_idinfo nilfs2_idinfo; extern const struct blkid_idinfo exfat_idinfo; extern const struct blkid_idinfo f2fs_idinfo; +extern const struct blkid_idinfo bcache_idinfo; /* * superblock functions diff --git a/libblkid/src/superblocks/swap.c b/libblkid/src/superblocks/swap.c index 679c81804..4297a9c40 100644 --- a/libblkid/src/superblocks/swap.c +++ b/libblkid/src/superblocks/swap.c @@ -47,7 +47,7 @@ static int swap_set_info(blkid_probe pr, const char *version) return -1; /* SWAPSPACE2 - check for wrong version or zeroed pagecount */ - if (strcmp(version, "2") == 0) { + if (strcmp(version, "1") == 0) { if (hdr->version != 1 && swab32(hdr->version) != 1) { DBG(LOWPROBE, blkid_debug("incorrect swap version")); return -1; @@ -88,11 +88,11 @@ static int probe_swap(blkid_probe pr, const struct blkid_idmag *mag) if (!memcmp(mag->magic, "SWAP-SPACE", mag->len)) { /* swap v0 doesn't support LABEL or UUID */ - blkid_probe_set_version(pr, "1"); + blkid_probe_set_version(pr, "0"); return 0; } else if (!memcmp(mag->magic, "SWAPSPACE2", mag->len)) - return swap_set_info(pr, "2"); + return swap_set_info(pr, "1"); return -1; } diff --git a/libblkid/src/superblocks/via_raid.c b/libblkid/src/superblocks/via_raid.c index eba7e4bf2..5c15167aa 100644 --- a/libblkid/src/superblocks/via_raid.c +++ b/libblkid/src/superblocks/via_raid.c @@ -42,7 +42,7 @@ static uint8_t via_checksum(struct via_metadata *v) while (i--) cs += ((uint8_t*) v)[i]; - return cs == v->checksum; + return cs; } static int probe_viaraid(blkid_probe pr, @@ -52,9 +52,9 @@ static int probe_viaraid(blkid_probe pr, struct via_metadata *v; if (pr->size < 0x10000) - return -1; + return 1; if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) - return -1; + return 1; off = ((pr->size / 0x200)-1) * 0x200; @@ -64,12 +64,14 @@ static int probe_viaraid(blkid_probe pr, sizeof(struct via_metadata)); if (!v) return -1; + if (le16_to_cpu(v->signature) != VIA_SIGNATURE) - return -1; + return 1; if (v->version_number > 2) - return -1; - if (!via_checksum(v)) - return -1; + return 1; + if (!blkid_probe_verify_csum(pr, via_checksum(v), v->checksum)) + return 1; + if (blkid_probe_sprintf_version(pr, "%u", v->version_number) != 0) return -1; if (blkid_probe_set_magic(pr, off, diff --git a/libblkid/src/superblocks/xfs.c b/libblkid/src/superblocks/xfs.c index 1399fe13a..f4bb72188 100644 --- a/libblkid/src/superblocks/xfs.c +++ b/libblkid/src/superblocks/xfs.c @@ -4,6 +4,7 @@ * Copyright (C) 2001 by Andreas Dilger * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> * Copyright (C) 2008 Karel Zak <kzak@redhat.com> + * Copyright (C) 2013 Eric Sandeen <sandeen@redhat.com> * * This file may be redistributed under the terms of the * GNU Lesser General Public License. @@ -20,20 +21,143 @@ #include "superblocks.h" struct xfs_super_block { - unsigned char xs_magic[4]; - uint32_t xs_blocksize; - uint64_t xs_dblocks; - uint64_t xs_rblocks; - uint32_t xs_dummy1[2]; - unsigned char xs_uuid[16]; - uint32_t xs_dummy2[15]; - char xs_fname[12]; - uint32_t xs_dummy3[2]; - uint64_t xs_icount; - uint64_t xs_ifree; - uint64_t xs_fdblocks; + uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ + uint32_t sb_blocksize; /* logical block size, bytes */ + uint64_t sb_dblocks; /* number of data blocks */ + uint64_t sb_rblocks; /* number of realtime blocks */ + uint64_t sb_rextents; /* number of realtime extents */ + unsigned char sb_uuid[16]; /* file system unique id */ + uint64_t sb_logstart; /* starting block of log if internal */ + uint64_t sb_rootino; /* root inode number */ + uint64_t sb_rbmino; /* bitmap inode for realtime extents */ + uint64_t sb_rsumino; /* summary inode for rt bitmap */ + uint32_t sb_rextsize; /* realtime extent size, blocks */ + uint32_t sb_agblocks; /* size of an allocation group */ + uint32_t sb_agcount; /* number of allocation groups */ + uint32_t sb_rbmblocks; /* number of rt bitmap blocks */ + uint32_t sb_logblocks; /* number of log blocks */ + + uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */ + uint16_t sb_sectsize; /* volume sector size, bytes */ + uint16_t sb_inodesize; /* inode size, bytes */ + uint16_t sb_inopblock; /* inodes per block */ + char sb_fname[12]; /* file system name */ + uint8_t sb_blocklog; /* log2 of sb_blocksize */ + uint8_t sb_sectlog; /* log2 of sb_sectsize */ + uint8_t sb_inodelog; /* log2 of sb_inodesize */ + uint8_t sb_inopblog; /* log2 of sb_inopblock */ + uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ + uint8_t sb_rextslog; /* log2 of sb_rextents */ + uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ + uint8_t sb_imax_pct; /* max % of fs for inode space */ + /* statistics */ + uint64_t sb_icount; /* allocated inodes */ + uint64_t sb_ifree; /* free inodes */ + uint64_t sb_fdblocks; /* free data blocks */ + uint64_t sb_frextents; /* free realtime extents */ + + /* this is not all... but enough for libblkid */ + } __attribute__((packed)); +#define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */ +#define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */ +#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG) +#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG) +#define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */ +#define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */ +#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG) +#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG) + +#define XFS_DINODE_MIN_LOG 8 +#define XFS_DINODE_MAX_LOG 11 +#define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG) +#define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG) + +#define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ +#define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */ +#define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */ + +#define XFS_MIN_AG_BLOCKS 64 +#define XFS_MAX_DBLOCKS(s) ((uint64_t)(s)->sb_agcount * (s)->sb_agblocks) +#define XFS_MIN_DBLOCKS(s) ((uint64_t)((s)->sb_agcount - 1) * \ + (s)->sb_agblocks + XFS_MIN_AG_BLOCKS) + + +static void sb_from_disk(struct xfs_super_block *from, + struct xfs_super_block *to) +{ + + to->sb_magicnum = be32_to_cpu(from->sb_magicnum); + to->sb_blocksize = be32_to_cpu(from->sb_blocksize); + to->sb_dblocks = be64_to_cpu(from->sb_dblocks); + to->sb_rblocks = be64_to_cpu(from->sb_rblocks); + to->sb_rextents = be64_to_cpu(from->sb_rextents); + to->sb_logstart = be64_to_cpu(from->sb_logstart); + to->sb_rootino = be64_to_cpu(from->sb_rootino); + to->sb_rbmino = be64_to_cpu(from->sb_rbmino); + to->sb_rsumino = be64_to_cpu(from->sb_rsumino); + to->sb_rextsize = be32_to_cpu(from->sb_rextsize); + to->sb_agblocks = be32_to_cpu(from->sb_agblocks); + to->sb_agcount = be32_to_cpu(from->sb_agcount); + to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks); + to->sb_logblocks = be32_to_cpu(from->sb_logblocks); + to->sb_versionnum = be16_to_cpu(from->sb_versionnum); + to->sb_sectsize = be16_to_cpu(from->sb_sectsize); + to->sb_inodesize = be16_to_cpu(from->sb_inodesize); + to->sb_inopblock = be16_to_cpu(from->sb_inopblock); + to->sb_blocklog = from->sb_blocklog; + to->sb_sectlog = from->sb_sectlog; + to->sb_inodelog = from->sb_inodelog; + to->sb_inopblog = from->sb_inopblog; + to->sb_agblklog = from->sb_agblklog; + to->sb_rextslog = from->sb_rextslog; + to->sb_inprogress = from->sb_inprogress; + to->sb_imax_pct = from->sb_imax_pct; + to->sb_icount = be64_to_cpu(from->sb_icount); + to->sb_ifree = be64_to_cpu(from->sb_ifree); + to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks); + to->sb_frextents = be64_to_cpu(from->sb_frextents); +} + +static int xfs_verify_sb(struct xfs_super_block *ondisk) +{ + struct xfs_super_block sb, *sbp = &sb; + + /* beXX_to_cpu(), but don't convert UUID and fsname! */ + sb_from_disk(ondisk, sbp); + + /* sanity checks, we don't want to rely on magic string only */ + if (sbp->sb_agcount <= 0 || + sbp->sb_sectsize < XFS_MIN_SECTORSIZE || + sbp->sb_sectsize > XFS_MAX_SECTORSIZE || + sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG || + sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG || + sbp->sb_sectsize != (1 << sbp->sb_sectlog) || + sbp->sb_blocksize < XFS_MIN_BLOCKSIZE || + sbp->sb_blocksize > XFS_MAX_BLOCKSIZE || + sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || + sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || + sbp->sb_blocksize != (1 << sbp->sb_blocklog) || + sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || + sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || + sbp->sb_inodelog < XFS_DINODE_MIN_LOG || + sbp->sb_inodelog > XFS_DINODE_MAX_LOG || + sbp->sb_inodesize != (1 << sbp->sb_inodelog) || + (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) || + (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || + (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || + (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */) || + sbp->sb_dblocks == 0 || + sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || + sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp)) + return 0; + + /* TODO: version 5 has also checksum CRC32, maybe we can check it too */ + + return 1; +} + static int probe_xfs(blkid_probe pr, const struct blkid_idmag *mag) { struct xfs_super_block *xs; @@ -42,10 +166,13 @@ static int probe_xfs(blkid_probe pr, const struct blkid_idmag *mag) if (!xs) return -1; - if (strlen(xs->xs_fname)) - blkid_probe_set_label(pr, (unsigned char *) xs->xs_fname, - sizeof(xs->xs_fname)); - blkid_probe_set_uuid(pr, xs->xs_uuid); + if (!xfs_verify_sb(xs)) + return 1; + + if (strlen(xs->sb_fname)) + blkid_probe_set_label(pr, (unsigned char *) xs->sb_fname, + sizeof(xs->sb_fname)); + blkid_probe_set_uuid(pr, xs->sb_uuid); return 0; } @@ -61,3 +188,90 @@ const struct blkid_idinfo xfs_idinfo = } }; +struct xlog_rec_header { + uint32_t h_magicno; + uint32_t h_dummy1[1]; + uint32_t h_version; + uint32_t h_len; + uint32_t h_dummy2[71]; + uint32_t h_fmt; + unsigned char h_uuid[16]; +} __attribute__((packed)); + +#define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe + +/* + * For very small filesystems, the minimum log size + * can be smaller, but that seems vanishingly unlikely + * when used with an external log (which is used for + * performance reasons; tiny conflicts with that goal). + */ +#define XFS_MIN_LOG_BYTES (10 * 1024 * 1024) + +#define XLOG_FMT_LINUX_LE 1 +#define XLOG_FMT_LINUX_BE 2 +#define XLOG_FMT_IRIX_BE 3 + +#define XLOG_VERSION_1 1 +#define XLOG_VERSION_2 2 /* Large IClogs, Log sunit */ +#define XLOG_VERSION_OKBITS (XLOG_VERSION_1 | XLOG_VERSION_2) + +static int xlog_valid_rec_header(struct xlog_rec_header *rhead) +{ + uint32_t hlen; + + if (rhead->h_magicno != cpu_to_be32(XLOG_HEADER_MAGIC_NUM)) + return 0; + + if (!rhead->h_version || + (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))) + return 0; + + /* LR body must have data or it wouldn't have been written */ + hlen = be32_to_cpu(rhead->h_len); + if (hlen <= 0 || hlen > INT_MAX) + return 0; + + if (rhead->h_fmt != cpu_to_be32(XLOG_FMT_LINUX_LE) && + rhead->h_fmt != cpu_to_be32(XLOG_FMT_LINUX_BE) && + rhead->h_fmt != cpu_to_be32(XLOG_FMT_IRIX_BE)) + return 0; + + return 1; +} + +/* xlog record header will be in some sector in the first 256k */ +static int probe_xfs_log(blkid_probe pr, const struct blkid_idmag *mag) +{ + int i; + struct xlog_rec_header *rhead; + unsigned char *buf; + + buf = blkid_probe_get_buffer(pr, 0, 256*1024); + if (!buf) + return -1; + + if (memcmp(buf, "XFSB", 4) == 0) + return 1; /* this is regular XFS, ignore */ + + /* check the first 512 512-byte sectors */ + for (i = 0; i < 512; i++) { + rhead = (struct xlog_rec_header *)&buf[i*512]; + + if (xlog_valid_rec_header(rhead)) { + blkid_probe_set_uuid_as(pr, rhead->h_uuid, "LOGUUID"); + return 0; + } + } + + return -1; +} + +const struct blkid_idinfo xfs_log_idinfo = +{ + .name = "xfs_external_log", + .usage = BLKID_USAGE_OTHER, + .probefunc = probe_xfs_log, + .magics = BLKID_NONE_MAGIC, + .minsz = XFS_MIN_LOG_BYTES, +}; diff --git a/libblkid/src/tag.c b/libblkid/src/tag.c index 3a7095013..e095ab1be 100644 --- a/libblkid/src/tag.c +++ b/libblkid/src/tag.c @@ -237,14 +237,18 @@ int blkid_parse_tag_string(const char *token, char **ret_type, char **ret_val) goto errout; /* missing closing quote */ *cp = '\0'; } - value = value && *value ? strdup(value) : NULL; - if (!value) - goto errout; + + if (ret_val) { + value = value && *value ? strdup(value) : NULL; + if (!value) + goto errout; + *ret_val = value; + } if (ret_type) *ret_type = name; - if (ret_val) - *ret_val = value; + else + free(name); return 0; |
