Upload Tizen:Base source
[framework/base/util-linux-ng.git] / shlibs / blkid / src / probers / lvm.c
1 /*
2  * Copyright (C) 1999 by Andries Brouwer
3  * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
4  * Copyright (C) 2001 by Andreas Dilger
5  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
7  *
8  * This file may be redistributed under the terms of the
9  * GNU Lesser General Public License.
10  */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <stdint.h>
16
17 #include "blkidP.h"
18
19 #define LVM1_ID_LEN 128
20 #define LVM2_ID_LEN 32
21
22 struct lvm2_pv_label_header {
23         /* label_header */
24         uint8_t         id[8];          /* LABELONE */
25         uint64_t        sector_xl;      /* Sector number of this label */
26         uint32_t        crc_xl;         /* From next field to end of sector */
27         uint32_t        offset_xl;      /* Offset from start of struct to contents */
28         uint8_t         type[8];        /* LVM2 001 */
29         /* pv_header */
30         uint8_t         pv_uuid[LVM2_ID_LEN];
31 } __attribute__ ((packed));
32
33 struct lvm1_pv_label_header {
34         uint8_t id[2];                  /* HM */
35         uint16_t version;               /* version 1 or 2 */
36         uint32_t _notused[10];          /* lvm1 internals */
37         uint8_t pv_uuid[LVM1_ID_LEN];
38 } __attribute__ ((packed));
39
40 #define LVM2_LABEL_SIZE 512
41 static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
42 {
43         static const unsigned int crctab[] = {
44                 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
45                 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
46                 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
47                 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
48         };
49         unsigned int i, crc = 0xf597a6cf;
50         const uint8_t *data = (const uint8_t *) buf;
51
52         for (i = 0; i < size; i++) {
53                 crc ^= *data++;
54                 crc = (crc >> 4) ^ crctab[crc & 0xf];
55                 crc = (crc >> 4) ^ crctab[crc & 0xf];
56         }
57         return crc;
58 }
59
60 /* Length of real UUID is always LVM2_ID_LEN */
61 static void format_lvm_uuid(char *dst_uuid, char *src_uuid)
62 {
63         unsigned int i, b;
64
65         for (i = 0, b = 1; i < LVM2_ID_LEN; i++, b <<= 1) {
66                 if (b & 0x4444440)
67                         *dst_uuid++ = '-';
68                 *dst_uuid++ = *src_uuid++;
69         }
70         *dst_uuid = '\0';
71 }
72
73 static int probe_lvm2(blkid_probe pr, const struct blkid_idmag *mag)
74 {
75         int sector = mag->kboff << 1;
76         struct lvm2_pv_label_header *label;
77         char uuid[LVM2_ID_LEN + 7];
78         unsigned char *buf;
79
80         buf = blkid_probe_get_buffer(pr,
81                         mag->kboff << 10,
82                         512 + sizeof(struct lvm2_pv_label_header));
83         if (!buf)
84                 return -1;
85
86         /* buf is at 0k or 1k offset; find label inside */
87         if (memcmp(buf, "LABELONE", 8) == 0) {
88                 label = (struct lvm2_pv_label_header *) buf;
89         } else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
90                 label = (struct lvm2_pv_label_header *)(buf + 512);
91                 sector++;
92         } else {
93                 return 1;
94         }
95
96         if (le64_to_cpu(label->sector_xl) != (unsigned) sector)
97                 return 1;
98
99         if (lvm2_calc_crc(&label->offset_xl, LVM2_LABEL_SIZE -
100                         ((char *) &label->offset_xl - (char *) label)) !=
101                         le32_to_cpu(label->crc_xl)) {
102                 DBG(DEBUG_PROBE,
103                     printf("LVM2: label checksum incorrect at sector %d\n",
104                            sector));
105                 return 1;
106         }
107
108         format_lvm_uuid(uuid, (char *) label->pv_uuid);
109         blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
110                         "%s", uuid);
111
112         /* the mag->magic is the same string as label->type,
113          * but zero terminated */
114         blkid_probe_set_version(pr, mag->magic);
115         return 0;
116 }
117
118 static int probe_lvm1(blkid_probe pr, const struct blkid_idmag *mag)
119 {
120         struct lvm1_pv_label_header *label;
121         char uuid[LVM2_ID_LEN + 7];
122         unsigned int version;
123
124         label = blkid_probe_get_sb(pr, mag, struct lvm1_pv_label_header);
125         if (!label)
126                 return -1;
127
128         version = le16_to_cpu(label->version);
129         if (version != 1 && version != 2)
130                 return 1;
131
132         format_lvm_uuid(uuid, (char *) label->pv_uuid);
133         blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
134                         "%s", uuid);
135
136         return 0;
137 }
138
139 /* NOTE: the original libblkid uses "lvm2pv" as a name */
140 const struct blkid_idinfo lvm2_idinfo =
141 {
142         .name           = "LVM2_member",
143         .usage          = BLKID_USAGE_RAID,
144         .probefunc      = probe_lvm2,
145         .magics         =
146         {
147                 { .magic = "LVM2 001", .len = 8, .sboff = 0x218 },
148                 { .magic = "LVM2 001", .len = 8, .sboff = 0x018 },
149                 { .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x018 },
150                 { .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x218 },
151                 { NULL }
152         }
153 };
154
155 const struct blkid_idinfo lvm1_idinfo =
156 {
157         .name           = "LVM1_member",
158         .usage          = BLKID_USAGE_RAID,
159         .probefunc      = probe_lvm1,
160         .magics         =
161         {
162                 { .magic = "HM", .len = 2 },
163                 { NULL }
164         }
165 };
166
167 const struct blkid_idinfo snapcow_idinfo =
168 {
169         .name           = "DM_snapshot_cow",
170         .usage          = BLKID_USAGE_OTHER,
171         .magics         =
172         {
173                 { .magic = "SnAp", .len = 4 },
174                 { NULL }
175         }
176 };