From: Karel Zak Date: Thu, 16 Oct 2008 12:46:50 +0000 (+0200) Subject: blkid: add LVM2 support and a fix _sprintf_uuid() bug X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=828f432e1279cf9de0d01d728564947d533a9a07;p=util-linux blkid: add LVM2 support and a fix _sprintf_uuid() bug Signed-off-by: Karel Zak --- diff --git a/libs/blkid/src/blkidP.h b/libs/blkid/src/blkidP.h index 13f66f7c..c48a2031 100644 --- a/libs/blkid/src/blkidP.h +++ b/libs/blkid/src/blkidP.h @@ -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))) diff --git a/libs/blkid/src/probe.c b/libs/blkid/src/probe.c index a379d5c5..5b7fe6fa 100644 --- a/libs/blkid/src/probe.c +++ b/libs/blkid/src/probe.c @@ -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 diff --git a/libs/blkid/src/probers/Makefile.am b/libs/blkid/src/probers/Makefile.am index 7a1c34f2..62c31fa7 100644 --- a/libs/blkid/src/probers/Makefile.am +++ b/libs/blkid/src/probers/Makefile.am @@ -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 index 00000000..e02f9048 --- /dev/null +++ b/libs/blkid/src/probers/lvm.c @@ -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 + * Copyright (C) 2008 Karel Zak + * + * 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 +#include +#include +#include +#include +#include +#include + +#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 } + } +}; + + diff --git a/libs/blkid/src/probers/probers.h b/libs/blkid/src/probers/probers.h index 378c673c..ae6df7e6 100644 --- a/libs/blkid/src/probers/probers.h +++ b/libs/blkid/src/probers/probers.h @@ -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 */