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