Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 : : * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
4 : : *
5 : : * This file is part of LVM2.
6 : : *
7 : : * This copyrighted material is made available to anyone wishing to use,
8 : : * modify, copy, or redistribute it subject to the terms and conditions
9 : : * of the GNU Lesser General Public License v.2.1.
10 : : *
11 : : * You should have received a copy of the GNU Lesser General Public License
12 : : * along with this program; if not, write to the Free Software Foundation,
13 : : * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14 : : */
15 : :
16 : : #include "lib.h"
17 : : #include "uuid.h"
18 : : #include "lvm-wrappers.h"
19 : :
20 : : #include <assert.h>
21 : : #include <sys/stat.h>
22 : : #include <fcntl.h>
23 : : #include <unistd.h>
24 : : #include <ctype.h>
25 : :
26 : : static const char _c[] =
27 : : "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#";
28 : :
29 : : static int _built_inverse;
30 : : static char _inverse_c[256];
31 : :
32 : 0 : int lvid_create(union lvid *lvid, struct id *vgid)
33 : : {
34 : 0 : memcpy(lvid->id, vgid, sizeof(*lvid->id));
35 : 0 : return id_create(&lvid->id[1]);
36 : : }
37 : :
38 : 0 : void uuid_from_num(char *uuid, uint32_t num)
39 : : {
40 : : unsigned i;
41 : :
42 [ # # ]: 0 : for (i = ID_LEN; i; i--) {
43 : 0 : uuid[i - 1] = _c[num % (sizeof(_c) - 1)];
44 : 0 : num /= sizeof(_c) - 1;
45 : : }
46 : 0 : }
47 : :
48 : 0 : int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num)
49 : : {
50 : : int i;
51 : :
52 : 0 : memcpy(lvid->id, vgid, sizeof(*lvid->id));
53 : :
54 [ # # ]: 0 : for (i = ID_LEN; i; i--) {
55 : 0 : lvid->id[1].uuid[i - 1] = _c[lv_num % (sizeof(_c) - 1)];
56 : 0 : lv_num /= sizeof(_c) - 1;
57 : : }
58 : :
59 : 0 : lvid->s[sizeof(lvid->s) - 1] = '\0';
60 : :
61 : 0 : return 1;
62 : : }
63 : :
64 : 0 : int lvnum_from_lvid(union lvid *lvid)
65 : : {
66 : 0 : int i, lv_num = 0;
67 : : char *c;
68 : :
69 [ # # ]: 0 : for (i = 0; i < ID_LEN; i++) {
70 : 0 : lv_num *= sizeof(_c) - 1;
71 [ # # ]: 0 : if ((c = strchr(_c, lvid->id[1].uuid[i])))
72 : 0 : lv_num += (int) (c - _c);
73 [ # # ]: 0 : if (lv_num < 0)
74 : 0 : lv_num = 0;
75 : : }
76 : :
77 : 0 : return lv_num;
78 : : }
79 : :
80 : 0 : int lvid_in_restricted_range(union lvid *lvid)
81 : : {
82 : : int i;
83 : :
84 [ # # ]: 0 : for (i = 0; i < ID_LEN - 3; i++)
85 [ # # ]: 0 : if (lvid->id[1].uuid[i] != '0')
86 : 0 : return 0;
87 : :
88 [ # # ]: 0 : for (i = ID_LEN - 3; i < ID_LEN; i++)
89 [ # # ]: 0 : if (!isdigit(lvid->id[1].uuid[i]))
90 : 0 : return 0;
91 : :
92 : 0 : return 1;
93 : : }
94 : :
95 : :
96 : 0 : int id_create(struct id *id)
97 : : {
98 : : unsigned i;
99 : 0 : size_t len = sizeof(id->uuid);
100 : :
101 : 0 : memset(id->uuid, 0, len);
102 [ # # ]: 0 : if (!read_urandom(&id->uuid, len)) {
103 : 0 : return 0;
104 : : }
105 : :
106 : : /*
107 : : * Skip out the last 2 chars in randomized creation for LVM1
108 : : * backwards compatibility.
109 : : */
110 [ # # ]: 0 : for (i = 0; i < len; i++)
111 : 0 : id->uuid[i] = _c[id->uuid[i] % (sizeof(_c) - 3)];
112 : :
113 : 0 : return 1;
114 : : }
115 : :
116 : : /*
117 : : * The only validity check we have is that
118 : : * the uuid just contains characters from
119 : : * '_c'. A checksum would have been nice :(
120 : : */
121 : 0 : static void _build_inverse(void)
122 : : {
123 : : const char *ptr;
124 : :
125 [ # # ]: 0 : if (_built_inverse)
126 : 0 : return;
127 : :
128 : 0 : memset(_inverse_c, 0, sizeof(_inverse_c));
129 : :
130 [ # # ]: 0 : for (ptr = _c; *ptr; ptr++)
131 : 0 : _inverse_c[(int) *ptr] = (char) 0x1;
132 : : }
133 : :
134 : 0 : int id_valid(struct id *id)
135 : : {
136 : : int i;
137 : :
138 : 0 : _build_inverse();
139 : :
140 [ # # ]: 0 : for (i = 0; i < ID_LEN; i++)
141 [ # # ]: 0 : if (!_inverse_c[id->uuid[i]]) {
142 : 0 : log_error("UUID contains invalid character");
143 : 0 : return 0;
144 : : }
145 : :
146 : 0 : return 1;
147 : : }
148 : :
149 : 0 : int id_equal(const struct id *lhs, const struct id *rhs)
150 : : {
151 : 0 : return !memcmp(lhs->uuid, rhs->uuid, sizeof(lhs->uuid));
152 : : }
153 : :
154 : : #define GROUPS (ID_LEN / 4)
155 : :
156 : 0 : int id_write_format(const struct id *id, char *buffer, size_t size)
157 : : {
158 : : int i, tot;
159 : :
160 : : static unsigned group_size[] = { 6, 4, 4, 4, 4, 4, 6 };
161 : :
162 : : assert(ID_LEN == 32);
163 : :
164 : : /* split into groups separated by dashes */
165 [ # # ]: 0 : if (size < (32 + 6 + 1)) {
166 : 0 : log_error("Couldn't write uuid, buffer too small.");
167 : 0 : return 0;
168 : : }
169 : :
170 [ # # ]: 0 : for (i = 0, tot = 0; i < 7; i++) {
171 : 0 : memcpy(buffer, id->uuid + tot, group_size[i]);
172 : 0 : buffer += group_size[i];
173 : 0 : tot += group_size[i];
174 : 0 : *buffer++ = '-';
175 : : }
176 : :
177 : 0 : *--buffer = '\0';
178 : 0 : return 1;
179 : : }
180 : :
181 : 0 : int id_read_format(struct id *id, const char *buffer)
182 : : {
183 : 0 : int out = 0;
184 : :
185 : : /* just strip out any dashes */
186 [ # # ]: 0 : while (*buffer) {
187 : :
188 [ # # ]: 0 : if (*buffer == '-') {
189 : 0 : buffer++;
190 : 0 : continue;
191 : : }
192 : :
193 [ # # ]: 0 : if (out >= ID_LEN) {
194 : 0 : log_error("Too many characters to be uuid.");
195 : 0 : return 0;
196 : : }
197 : :
198 : 0 : id->uuid[out++] = *buffer++;
199 : : }
200 : :
201 [ # # ]: 0 : if (out != ID_LEN) {
202 : 0 : log_error("Couldn't read uuid: incorrect number of "
203 : : "characters.");
204 : 0 : return 0;
205 : : }
206 : :
207 : 0 : return id_valid(id);
208 : : }
|