]> err.no Git - util-linux/commitdiff
blkid: add LVM2 support and a fix _sprintf_uuid() bug
authorKarel Zak <kzak@redhat.com>
Thu, 16 Oct 2008 12:46:50 +0000 (14:46 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 11 Feb 2009 22:21:46 +0000 (23:21 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libs/blkid/src/blkidP.h
libs/blkid/src/probe.c
libs/blkid/src/probers/Makefile.am
libs/blkid/src/probers/lvm.c [new file with mode: 0644]
libs/blkid/src/probers/probers.h

index 13f66f7c9444a503c2a7334810bbfdff0bb84cbc..c48a203100e2a2c78aa5f18ae06824cf575b509c 100644 (file)
@@ -250,6 +250,7 @@ extern void blkid_free_dev(blkid_dev dev);
 unsigned char *blkid_probe_get_buffer(blkid_probe pr,
                                 blkid_loff_t off, blkid_loff_t len);
 
+/* returns superblok according to 'struct blkid_idmag' */
 #define blkid_probe_get_sb(_pr, _mag, type) \
                        ((type *) blkid_probe_get_buffer((_pr),\
                                        (_mag)->kboff << 10, sizeof(type)))
index a379d5c5ae26ff11352df02f41bc557c4343b607..5b7fe6fa70ac890d500a7498444751592ea967a1 100644 (file)
@@ -67,7 +67,8 @@ static const struct blkid_idinfo *idinfos[] =
        &hfsplus_idinfo,
        &hfs_idinfo,
        &ntfs_idinfo,
-       &iso9660_idinfo
+       &iso9660_idinfo,
+       &lvm2_idinfo
 };
 
 #ifndef ARRAY_SIZE
@@ -630,9 +631,9 @@ int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
                if (str && *str)
                        v = blkid_probe_assign_value(pr, "UUID");
                if (v) {
-                       memcpy(v->data, str, len);
-                       v->data[len] = '\0';
-                       v->len = len;
+                       strncpy((char *) v->data, str, BLKID_PROBVAL_BUFSIZ);
+                       v->data[BLKID_PROBVAL_BUFSIZ - 1] = '\0';
+                       v->len = strlen((char *) v->data);
                        rc = 0;
                }
        } else
index 7a1c34f230fc8c0e4b60b066f98101c5092499f9..62c31fa7aa5b89e7df38337d5632eea822dad4c6 100644 (file)
@@ -26,6 +26,7 @@ libprobers_a_SOURCES =        probers.h \
                        romfs.c \
                        ntfs.c \
                        hfs.c \
-                       iso9660.c
+                       iso9660.c \
+                       lvm.c
 
 all-local: $(lib_LIBRARIES)
diff --git a/libs/blkid/src/probers/lvm.c b/libs/blkid/src/probers/lvm.c
new file mode 100644 (file)
index 0000000..e02f904
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 1999 by Andries Brouwer
+ * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
+ * Copyright (C) 2001 by Andreas Dilger
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This file 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 General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "blkidP.h"
+
+/* TODO: add lvm1 support -- magic string detection required only */
+
+#define LVM2_ID_LEN 32
+
+struct lvm2_pv_label_header {
+       /* label_header */
+       __u8    id[8];          /* LABELONE */
+       __u64   sector_xl;      /* Sector number of this label */
+       __u32   crc_xl;         /* From next field to end of sector */
+       __u32   offset_xl;      /* Offset from start of struct to contents */
+       __u8    type[8];        /* LVM2 001 */
+       /* pv_header */
+       __u8    pv_uuid[LVM2_ID_LEN];
+} __attribute__ ((packed));
+
+#define LVM2_LABEL_SIZE 512
+static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
+{
+       static const unsigned int crctab[] = {
+               0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
+               0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
+               0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
+               0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
+       };
+       unsigned int i, crc = 0xf597a6cf;
+       const __u8 *data = (const __u8 *) buf;
+
+       for (i = 0; i < size; i++) {
+               crc ^= *data++;
+               crc = (crc >> 4) ^ crctab[crc & 0xf];
+               crc = (crc >> 4) ^ crctab[crc & 0xf];
+       }
+       return crc;
+}
+
+static int probe_lvm2(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       int sector = mag->kboff << 1;
+       struct lvm2_pv_label_header *label;
+       char *p, *q, uuid[40];
+       unsigned int i, b;
+       unsigned char *buf;
+
+       buf = blkid_probe_get_buffer(pr,
+                       mag->kboff << 10,
+                       512 + sizeof(struct lvm2_pv_label_header));
+       if (!buf)
+               return -1;
+
+       /* buf is at 0k or 1k offset; find label inside */
+       if (memcmp(buf, "LABELONE", 8) == 0) {
+               label = (struct lvm2_pv_label_header *) buf;
+       } else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
+               label = (struct lvm2_pv_label_header *)(buf + 512);
+               sector++;
+       } else {
+               return 1;
+       }
+
+       if (le64_to_cpu(label->sector_xl) != (unsigned) sector) {
+               DBG(DEBUG_PROBE,
+                   printf("LVM2: label for sector %llu found at sector %d\n",
+                          le64_to_cpu(label->sector_xl), 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(DEBUG_PROBE,
+                   printf("LVM2: label checksum incorrect at sector %d\n",
+                          sector));
+               return 1;
+       }
+
+       for (i = 0, b = 1, p = uuid, q = (char *) label->pv_uuid; i <= 32;
+            i++, b <<= 1) {
+               if (b & 0x4444440)
+                       *p++ = '-';
+               *p++ = *q++;
+       }
+
+       uuid[LVM2_ID_LEN+6] = '\0';
+       blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
+                       "%s", uuid);
+       return 0;
+}
+
+
+/* NOTE: libblkid uses "lvm2pv" as a name */
+
+const struct blkid_idinfo lvm2_idinfo =
+{
+       .name           = "LVM2_member",
+       .usage          = BLKID_USAGE_RAID,
+       .probefunc      = probe_lvm2,
+       .magics         =
+       {
+               { .magic = "LVM2 001", .len = 8, .sboff = 0x218 },
+               { .magic = "LVM2 001", .len = 8, .sboff = 0x018 },
+               { .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x018 },
+               { .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x218 },
+               { NULL }
+       }
+};
+
+
index 378c673cbd9e25c7b30f929879fe0694cf9876ce..ae6df7e636a77201bddd6fecda6713e6da92e292 100644 (file)
@@ -47,5 +47,6 @@ extern const struct blkid_idinfo hfs_idinfo;
 extern const struct blkid_idinfo hfsplus_idinfo;
 extern const struct blkid_idinfo ntfs_idinfo;
 extern const struct blkid_idinfo iso9660_idinfo;
+extern const struct blkid_idinfo lvm2_idinfo;
 
 #endif /* _BLKID_PROBE_H */