]> sourceware.org Git - lvm2.git/blob - lib/uuid/uuid.c
thin: fix recent commits
[lvm2.git] / lib / uuid / uuid.c
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 int lvid_create(union lvid *lvid, struct id *vgid)
33 {
34 memcpy(lvid->id, vgid, sizeof(*lvid->id));
35 return id_create(&lvid->id[1]);
36 }
37
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 }
46 }
47
48 int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num)
49 {
50 int i;
51
52 memcpy(lvid->id, vgid, sizeof(*lvid->id));
53
54 for (i = ID_LEN; i; i--) {
55 lvid->id[1].uuid[i - 1] = _c[lv_num % (sizeof(_c) - 1)];
56 lv_num /= sizeof(_c) - 1;
57 }
58
59 lvid->s[sizeof(lvid->s) - 1] = '\0';
60
61 return 1;
62 }
63
64 int lvnum_from_lvid(union lvid *lvid)
65 {
66 int i, lv_num = 0;
67 char *c;
68
69 for (i = 0; i < ID_LEN; i++) {
70 lv_num *= sizeof(_c) - 1;
71 if ((c = strchr(_c, lvid->id[1].uuid[i])))
72 lv_num += (int) (c - _c);
73 if (lv_num < 0)
74 lv_num = 0;
75 }
76
77 return lv_num;
78 }
79
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
96 int id_create(struct id *id)
97 {
98 unsigned i;
99 size_t len = sizeof(id->uuid);
100
101 memset(id->uuid, 0, len);
102 if (!read_urandom(&id->uuid, len)) {
103 return 0;
104 }
105
106 /*
107 * Skip out the last 2 chars in randomized creation for LVM1
108 * backwards compatibility.
109 */
110 for (i = 0; i < len; i++)
111 id->uuid[i] = _c[id->uuid[i] % (sizeof(_c) - 3)];
112
113 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 static void _build_inverse(void)
122 {
123 const char *ptr;
124
125 if (_built_inverse)
126 return;
127
128 _built_inverse = 1;
129 memset(_inverse_c, 0, sizeof(_inverse_c));
130
131 for (ptr = _c; *ptr; ptr++)
132 _inverse_c[(int) *ptr] = (char) 0x1;
133 }
134
135 int id_valid(struct id *id)
136 {
137 int i;
138
139 _build_inverse();
140
141 for (i = 0; i < ID_LEN; i++)
142 if (!_inverse_c[id->uuid[i]]) {
143 log_error("UUID contains invalid character");
144 return 0;
145 }
146
147 return 1;
148 }
149
150 int id_equal(const struct id *lhs, const struct id *rhs)
151 {
152 return !memcmp(lhs->uuid, rhs->uuid, sizeof(lhs->uuid));
153 }
154
155 #define GROUPS (ID_LEN / 4)
156
157 int id_write_format(const struct id *id, char *buffer, size_t size)
158 {
159 int i, tot;
160
161 static const unsigned group_size[] = { 6, 4, 4, 4, 4, 4, 6 };
162
163 assert(ID_LEN == 32);
164
165 /* split into groups separated by dashes */
166 if (size < (32 + 6 + 1)) {
167 log_error("Couldn't write uuid, buffer too small.");
168 return 0;
169 }
170
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++ = '-';
176 }
177
178 *--buffer = '\0';
179 return 1;
180 }
181
182 int id_read_format(struct id *id, const char *buffer)
183 {
184 int out = 0;
185
186 /* just strip out any dashes */
187 while (*buffer) {
188
189 if (*buffer == '-') {
190 buffer++;
191 continue;
192 }
193
194 if (out >= ID_LEN) {
195 log_error("Too many characters to be uuid.");
196 return 0;
197 }
198
199 id->uuid[out++] = *buffer++;
200 }
201
202 if (out != ID_LEN) {
203 log_error("Couldn't read uuid: incorrect number of "
204 "characters.");
205 return 0;
206 }
207
208 return id_valid(id);
209 }
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 }
This page took 0.047022 seconds and 5 git commands to generate.