]>
Commit | Line | Data |
---|---|---|
72a5e12b | 1 | /* |
67cdbd7e | 2 | * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
be684599 | 3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
72a5e12b | 4 | * |
6606c3ae AK |
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 | |
be684599 | 9 | * of the GNU Lesser General Public License v.2.1. |
6606c3ae | 10 | * |
be684599 | 11 | * You should have received a copy of the GNU Lesser General Public License |
6606c3ae AK |
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 | |
72a5e12b JT |
14 | */ |
15 | ||
d1d9800e | 16 | #include "lib.h" |
72a5e12b | 17 | #include "uuid.h" |
b721056e | 18 | #include "lvm-wrappers.h" |
72a5e12b | 19 | |
56d88440 | 20 | #include <assert.h> |
72a5e12b JT |
21 | #include <sys/stat.h> |
22 | #include <fcntl.h> | |
23 | #include <unistd.h> | |
18c8a64d | 24 | #include <ctype.h> |
72a5e12b | 25 | |
1e35409b | 26 | static const char _c[] = |
4c22730b | 27 | "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#"; |
72a5e12b | 28 | |
db73838c | 29 | static int _built_inverse; |
72b2cb61 | 30 | static char _inverse_c[256]; |
db73838c | 31 | |
25b73380 AK |
32 | int lvid_create(union lvid *lvid, struct id *vgid) |
33 | { | |
34 | memcpy(lvid->id, vgid, sizeof(*lvid->id)); | |
52f9afec | 35 | return id_create(&lvid->id[1]); |
25b73380 AK |
36 | } |
37 | ||
cc8f6e3d AK |
38 | void uuid_from_num(char *uuid, uint32_t num) |
39 | { | |
40 | unsigned i; | |
41 | ||
42 | for (i = ID_LEN; i; i--) { | |
43 | uuid[i - 1] = _c[num % (sizeof(_c) - 1)]; | |
44 | num /= sizeof(_c) - 1; | |
45 | } | |
cc8f6e3d AK |
46 | } |
47 | ||
8ef2b021 | 48 | int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num) |
b5ed5327 AK |
49 | { |
50 | int i; | |
51 | ||
15c325f0 AK |
52 | memcpy(lvid->id, vgid, sizeof(*lvid->id)); |
53 | ||
b5ed5327 | 54 | for (i = ID_LEN; i; i--) { |
15c325f0 | 55 | lvid->id[1].uuid[i - 1] = _c[lv_num % (sizeof(_c) - 1)]; |
b5ed5327 AK |
56 | lv_num /= sizeof(_c) - 1; |
57 | } | |
58 | ||
15c325f0 AK |
59 | lvid->s[sizeof(lvid->s) - 1] = '\0'; |
60 | ||
b5ed5327 AK |
61 | return 1; |
62 | } | |
63 | ||
15c325f0 | 64 | int lvnum_from_lvid(union lvid *lvid) |
b5ed5327 AK |
65 | { |
66 | int i, lv_num = 0; | |
72b2cb61 | 67 | char *c; |
b5ed5327 AK |
68 | |
69 | for (i = 0; i < ID_LEN; i++) { | |
70 | lv_num *= sizeof(_c) - 1; | |
15c325f0 | 71 | if ((c = strchr(_c, lvid->id[1].uuid[i]))) |
b5ed5327 | 72 | lv_num += (int) (c - _c); |
9c520b11 MB |
73 | if (lv_num < 0) |
74 | lv_num = 0; | |
b5ed5327 AK |
75 | } |
76 | ||
77 | return lv_num; | |
78 | } | |
79 | ||
9c520b11 MB |
80 | int lvid_in_restricted_range(union lvid *lvid) |
81 | { | |
82 | int i; | |
83 | ||
84 | for (i = 0; i < ID_LEN - 3; i++) | |
85 | if (lvid->id[1].uuid[i] != '0') | |
86 | return 0; | |
87 | ||
88 | for (i = ID_LEN - 3; i < ID_LEN; i++) | |
89 | if (!isdigit(lvid->id[1].uuid[i])) | |
90 | return 0; | |
91 | ||
92 | return 1; | |
93 | } | |
94 | ||
95 | ||
72a5e12b JT |
96 | int id_create(struct id *id) |
97 | { | |
72b2cb61 | 98 | unsigned i; |
8ef2b021 | 99 | size_t len = sizeof(id->uuid); |
72a5e12b JT |
100 | |
101 | memset(id->uuid, 0, len); | |
b721056e | 102 | if (!read_urandom(&id->uuid, len)) { |
72a5e12b JT |
103 | return 0; |
104 | } | |
105 | ||
67cdbd7e AK |
106 | /* |
107 | * Skip out the last 2 chars in randomized creation for LVM1 | |
108 | * backwards compatibility. | |
109 | */ | |
72a5e12b | 110 | for (i = 0; i < len; i++) |
6a5b8035 | 111 | id->uuid[i] = _c[id->uuid[i] % (sizeof(_c) - 3)]; |
72a5e12b JT |
112 | |
113 | return 1; | |
114 | } | |
115 | ||
db73838c JT |
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 | */ | |
8ef2b021 | 121 | static void _build_inverse(void) |
db73838c | 122 | { |
1e35409b | 123 | const char *ptr; |
db73838c JT |
124 | |
125 | if (_built_inverse) | |
126 | return; | |
127 | ||
65fc4dae | 128 | _built_inverse = 1; |
db73838c JT |
129 | memset(_inverse_c, 0, sizeof(_inverse_c)); |
130 | ||
131 | for (ptr = _c; *ptr; ptr++) | |
132 | _inverse_c[(int) *ptr] = (char) 0x1; | |
133 | } | |
134 | ||
72a5e12b JT |
135 | int id_valid(struct id *id) |
136 | { | |
db73838c | 137 | int i; |
db73838c JT |
138 | |
139 | _build_inverse(); | |
140 | ||
141 | for (i = 0; i < ID_LEN; i++) | |
142 | if (!_inverse_c[id->uuid[i]]) { | |
b8f47d5f | 143 | log_error("UUID contains invalid character"); |
db73838c JT |
144 | return 0; |
145 | } | |
146 | ||
72a5e12b JT |
147 | return 1; |
148 | } | |
149 | ||
8ef2b021 | 150 | int id_equal(const struct id *lhs, const struct id *rhs) |
72a5e12b | 151 | { |
6036e5e0 | 152 | return !memcmp(lhs->uuid, rhs->uuid, sizeof(lhs->uuid)); |
72a5e12b | 153 | } |
db73838c JT |
154 | |
155 | #define GROUPS (ID_LEN / 4) | |
2041d905 | 156 | |
8ef2b021 | 157 | int id_write_format(const struct id *id, char *buffer, size_t size) |
db73838c | 158 | { |
9640f93d JT |
159 | int i, tot; |
160 | ||
aec21154 | 161 | static const unsigned group_size[] = { 6, 4, 4, 4, 4, 4, 6 }; |
db73838c | 162 | |
9640f93d JT |
163 | assert(ID_LEN == 32); |
164 | ||
685d88b2 | 165 | /* split into groups separated by dashes */ |
9640f93d | 166 | if (size < (32 + 6 + 1)) { |
b8f47d5f | 167 | log_error("Couldn't write uuid, buffer too small."); |
db73838c | 168 | return 0; |
9640f93d | 169 | } |
db73838c | 170 | |
9640f93d JT |
171 | for (i = 0, tot = 0; i < 7; i++) { |
172 | memcpy(buffer, id->uuid + tot, group_size[i]); | |
173 | buffer += group_size[i]; | |
174 | tot += group_size[i]; | |
175 | *buffer++ = '-'; | |
db73838c JT |
176 | } |
177 | ||
9640f93d | 178 | *--buffer = '\0'; |
db73838c JT |
179 | return 1; |
180 | } | |
181 | ||
8ef2b021 | 182 | int id_read_format(struct id *id, const char *buffer) |
db73838c | 183 | { |
9640f93d | 184 | int out = 0; |
0803634c | 185 | |
9640f93d JT |
186 | /* just strip out any dashes */ |
187 | while (*buffer) { | |
188 | ||
189 | if (*buffer == '-') { | |
190 | buffer++; | |
191 | continue; | |
192 | } | |
193 | ||
194 | if (out >= ID_LEN) { | |
b8f47d5f | 195 | log_error("Too many characters to be uuid."); |
9640f93d JT |
196 | return 0; |
197 | } | |
198 | ||
199 | id->uuid[out++] = *buffer++; | |
db73838c JT |
200 | } |
201 | ||
9640f93d | 202 | if (out != ID_LEN) { |
b8f47d5f AK |
203 | log_error("Couldn't read uuid: incorrect number of " |
204 | "characters."); | |
9640f93d JT |
205 | return 0; |
206 | } | |
db73838c JT |
207 | |
208 | return id_valid(id); | |
209 | } | |
f4fd4155 DW |
210 | |
211 | char *id_format_and_copy(struct dm_pool *mem, const struct id *id) | |
212 | { | |
213 | char *repstr = NULL; | |
214 | ||
215 | if (!(repstr = dm_pool_alloc(mem, 40))) { | |
216 | log_error("dm_pool_alloc failed"); | |
217 | return NULL; | |
218 | } | |
219 | ||
220 | if (!id_write_format(id, repstr, 40)) | |
221 | return_NULL; | |
222 | ||
223 | return repstr; | |
224 | } |