xref: /dflybsd-src/contrib/lvm2/dist/lib/uuid/uuid.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*	$NetBSD: uuid.c,v 1.1.1.3 2009/12/02 00:26:49 haad Exp $	*/
286d7f5d3SJohn Marino 
386d7f5d3SJohn Marino /*
486d7f5d3SJohn Marino  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
586d7f5d3SJohn Marino  * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
686d7f5d3SJohn Marino  *
786d7f5d3SJohn Marino  * This file is part of LVM2.
886d7f5d3SJohn Marino  *
986d7f5d3SJohn Marino  * This copyrighted material is made available to anyone wishing to use,
1086d7f5d3SJohn Marino  * modify, copy, or redistribute it subject to the terms and conditions
1186d7f5d3SJohn Marino  * of the GNU Lesser General Public License v.2.1.
1286d7f5d3SJohn Marino  *
1386d7f5d3SJohn Marino  * You should have received a copy of the GNU Lesser General Public License
1486d7f5d3SJohn Marino  * along with this program; if not, write to the Free Software Foundation,
1586d7f5d3SJohn Marino  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
1686d7f5d3SJohn Marino  */
1786d7f5d3SJohn Marino 
1886d7f5d3SJohn Marino #include "lib.h"
1986d7f5d3SJohn Marino #include "uuid.h"
2086d7f5d3SJohn Marino #include "lvm-wrappers.h"
2186d7f5d3SJohn Marino 
2286d7f5d3SJohn Marino #include <assert.h>
2386d7f5d3SJohn Marino #include <sys/stat.h>
2486d7f5d3SJohn Marino #include <fcntl.h>
2586d7f5d3SJohn Marino #include <unistd.h>
2686d7f5d3SJohn Marino #include <ctype.h>
2786d7f5d3SJohn Marino 
2886d7f5d3SJohn Marino static const char _c[] =
2986d7f5d3SJohn Marino     "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#";
3086d7f5d3SJohn Marino 
3186d7f5d3SJohn Marino static int _built_inverse;
3286d7f5d3SJohn Marino static char _inverse_c[256];
3386d7f5d3SJohn Marino 
lvid_create(union lvid * lvid,struct id * vgid)3486d7f5d3SJohn Marino int lvid_create(union lvid *lvid, struct id *vgid)
3586d7f5d3SJohn Marino {
3686d7f5d3SJohn Marino 	memcpy(lvid->id, vgid, sizeof(*lvid->id));
3786d7f5d3SJohn Marino 	return id_create(&lvid->id[1]);
3886d7f5d3SJohn Marino }
3986d7f5d3SJohn Marino 
uuid_from_num(char * uuid,uint32_t num)4086d7f5d3SJohn Marino void uuid_from_num(char *uuid, uint32_t num)
4186d7f5d3SJohn Marino {
4286d7f5d3SJohn Marino 	unsigned i;
4386d7f5d3SJohn Marino 
4486d7f5d3SJohn Marino 	for (i = ID_LEN; i; i--) {
4586d7f5d3SJohn Marino 		uuid[i - 1] = _c[num % (sizeof(_c) - 1)];
4686d7f5d3SJohn Marino 		num /= sizeof(_c) - 1;
4786d7f5d3SJohn Marino 	}
4886d7f5d3SJohn Marino }
4986d7f5d3SJohn Marino 
lvid_from_lvnum(union lvid * lvid,struct id * vgid,uint32_t lv_num)5086d7f5d3SJohn Marino int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num)
5186d7f5d3SJohn Marino {
5286d7f5d3SJohn Marino 	int i;
5386d7f5d3SJohn Marino 
5486d7f5d3SJohn Marino 	memcpy(lvid->id, vgid, sizeof(*lvid->id));
5586d7f5d3SJohn Marino 
5686d7f5d3SJohn Marino 	for (i = ID_LEN; i; i--) {
5786d7f5d3SJohn Marino 		lvid->id[1].uuid[i - 1] = _c[lv_num % (sizeof(_c) - 1)];
5886d7f5d3SJohn Marino 		lv_num /= sizeof(_c) - 1;
5986d7f5d3SJohn Marino 	}
6086d7f5d3SJohn Marino 
6186d7f5d3SJohn Marino 	lvid->s[sizeof(lvid->s) - 1] = '\0';
6286d7f5d3SJohn Marino 
6386d7f5d3SJohn Marino 	return 1;
6486d7f5d3SJohn Marino }
6586d7f5d3SJohn Marino 
lvnum_from_lvid(union lvid * lvid)6686d7f5d3SJohn Marino int lvnum_from_lvid(union lvid *lvid)
6786d7f5d3SJohn Marino {
6886d7f5d3SJohn Marino 	int i, lv_num = 0;
6986d7f5d3SJohn Marino 	char *c;
7086d7f5d3SJohn Marino 
7186d7f5d3SJohn Marino 	for (i = 0; i < ID_LEN; i++) {
7286d7f5d3SJohn Marino 		lv_num *= sizeof(_c) - 1;
7386d7f5d3SJohn Marino 		if ((c = strchr(_c, lvid->id[1].uuid[i])))
7486d7f5d3SJohn Marino 			lv_num += (int) (c - _c);
7586d7f5d3SJohn Marino 		if (lv_num < 0)
7686d7f5d3SJohn Marino 			lv_num = 0;
7786d7f5d3SJohn Marino 	}
7886d7f5d3SJohn Marino 
7986d7f5d3SJohn Marino 	return lv_num;
8086d7f5d3SJohn Marino }
8186d7f5d3SJohn Marino 
lvid_in_restricted_range(union lvid * lvid)8286d7f5d3SJohn Marino int lvid_in_restricted_range(union lvid *lvid)
8386d7f5d3SJohn Marino {
8486d7f5d3SJohn Marino 	int i;
8586d7f5d3SJohn Marino 
8686d7f5d3SJohn Marino 	for (i = 0; i < ID_LEN - 3; i++)
8786d7f5d3SJohn Marino 		if (lvid->id[1].uuid[i] != '0')
8886d7f5d3SJohn Marino 			return 0;
8986d7f5d3SJohn Marino 
9086d7f5d3SJohn Marino 	for (i = ID_LEN - 3; i < ID_LEN; i++)
9186d7f5d3SJohn Marino 		if (!isdigit(lvid->id[1].uuid[i]))
9286d7f5d3SJohn Marino 			return 0;
9386d7f5d3SJohn Marino 
9486d7f5d3SJohn Marino 	return 1;
9586d7f5d3SJohn Marino }
9686d7f5d3SJohn Marino 
9786d7f5d3SJohn Marino 
id_create(struct id * id)9886d7f5d3SJohn Marino int id_create(struct id *id)
9986d7f5d3SJohn Marino {
10086d7f5d3SJohn Marino 	unsigned i;
10186d7f5d3SJohn Marino 	size_t len = sizeof(id->uuid);
10286d7f5d3SJohn Marino 
10386d7f5d3SJohn Marino 	memset(id->uuid, 0, len);
10486d7f5d3SJohn Marino 	if (!read_urandom(&id->uuid, len)) {
10586d7f5d3SJohn Marino 		return 0;
10686d7f5d3SJohn Marino 	}
10786d7f5d3SJohn Marino 
10886d7f5d3SJohn Marino 	/*
10986d7f5d3SJohn Marino 	 * Skip out the last 2 chars in randomized creation for LVM1
11086d7f5d3SJohn Marino 	 * backwards compatibility.
11186d7f5d3SJohn Marino 	 */
11286d7f5d3SJohn Marino 	for (i = 0; i < len; i++)
11386d7f5d3SJohn Marino 		id->uuid[i] = _c[id->uuid[i] % (sizeof(_c) - 3)];
11486d7f5d3SJohn Marino 
11586d7f5d3SJohn Marino 	return 1;
11686d7f5d3SJohn Marino }
11786d7f5d3SJohn Marino 
11886d7f5d3SJohn Marino /*
11986d7f5d3SJohn Marino  * The only validity check we have is that
12086d7f5d3SJohn Marino  * the uuid just contains characters from
12186d7f5d3SJohn Marino  * '_c'.  A checksum would have been nice :(
12286d7f5d3SJohn Marino  */
_build_inverse(void)12386d7f5d3SJohn Marino static void _build_inverse(void)
12486d7f5d3SJohn Marino {
12586d7f5d3SJohn Marino 	const char *ptr;
12686d7f5d3SJohn Marino 
12786d7f5d3SJohn Marino 	if (_built_inverse)
12886d7f5d3SJohn Marino 		return;
12986d7f5d3SJohn Marino 
13086d7f5d3SJohn Marino 	memset(_inverse_c, 0, sizeof(_inverse_c));
13186d7f5d3SJohn Marino 
13286d7f5d3SJohn Marino 	for (ptr = _c; *ptr; ptr++)
13386d7f5d3SJohn Marino 		_inverse_c[(int) *ptr] = (char) 0x1;
13486d7f5d3SJohn Marino }
13586d7f5d3SJohn Marino 
id_valid(struct id * id)13686d7f5d3SJohn Marino int id_valid(struct id *id)
13786d7f5d3SJohn Marino {
13886d7f5d3SJohn Marino 	int i;
13986d7f5d3SJohn Marino 
14086d7f5d3SJohn Marino 	_build_inverse();
14186d7f5d3SJohn Marino 
14286d7f5d3SJohn Marino 	for (i = 0; i < ID_LEN; i++)
14386d7f5d3SJohn Marino 		if (!_inverse_c[id->uuid[i]]) {
14486d7f5d3SJohn Marino 			log_error("UUID contains invalid character");
14586d7f5d3SJohn Marino 			return 0;
14686d7f5d3SJohn Marino 		}
14786d7f5d3SJohn Marino 
14886d7f5d3SJohn Marino 	return 1;
14986d7f5d3SJohn Marino }
15086d7f5d3SJohn Marino 
id_equal(const struct id * lhs,const struct id * rhs)15186d7f5d3SJohn Marino int id_equal(const struct id *lhs, const struct id *rhs)
15286d7f5d3SJohn Marino {
15386d7f5d3SJohn Marino 	return !memcmp(lhs->uuid, rhs->uuid, sizeof(lhs->uuid));
15486d7f5d3SJohn Marino }
15586d7f5d3SJohn Marino 
15686d7f5d3SJohn Marino #define GROUPS (ID_LEN / 4)
15786d7f5d3SJohn Marino 
id_write_format(const struct id * id,char * buffer,size_t size)15886d7f5d3SJohn Marino int id_write_format(const struct id *id, char *buffer, size_t size)
15986d7f5d3SJohn Marino {
16086d7f5d3SJohn Marino 	int i, tot;
16186d7f5d3SJohn Marino 
16286d7f5d3SJohn Marino 	static unsigned group_size[] = { 6, 4, 4, 4, 4, 4, 6 };
16386d7f5d3SJohn Marino 
16486d7f5d3SJohn Marino 	assert(ID_LEN == 32);
16586d7f5d3SJohn Marino 
16686d7f5d3SJohn Marino 	/* split into groups separated by dashes */
16786d7f5d3SJohn Marino 	if (size < (32 + 6 + 1)) {
16886d7f5d3SJohn Marino 		log_error("Couldn't write uuid, buffer too small.");
16986d7f5d3SJohn Marino 		return 0;
17086d7f5d3SJohn Marino 	}
17186d7f5d3SJohn Marino 
17286d7f5d3SJohn Marino 	for (i = 0, tot = 0; i < 7; i++) {
17386d7f5d3SJohn Marino 		memcpy(buffer, id->uuid + tot, group_size[i]);
17486d7f5d3SJohn Marino 		buffer += group_size[i];
17586d7f5d3SJohn Marino 		tot += group_size[i];
17686d7f5d3SJohn Marino 		*buffer++ = '-';
17786d7f5d3SJohn Marino 	}
17886d7f5d3SJohn Marino 
17986d7f5d3SJohn Marino 	*--buffer = '\0';
18086d7f5d3SJohn Marino 	return 1;
18186d7f5d3SJohn Marino }
18286d7f5d3SJohn Marino 
id_read_format(struct id * id,const char * buffer)18386d7f5d3SJohn Marino int id_read_format(struct id *id, const char *buffer)
18486d7f5d3SJohn Marino {
18586d7f5d3SJohn Marino 	int out = 0;
18686d7f5d3SJohn Marino 
18786d7f5d3SJohn Marino 	/* just strip out any dashes */
18886d7f5d3SJohn Marino 	while (*buffer) {
18986d7f5d3SJohn Marino 
19086d7f5d3SJohn Marino 		if (*buffer == '-') {
19186d7f5d3SJohn Marino 			buffer++;
19286d7f5d3SJohn Marino 			continue;
19386d7f5d3SJohn Marino 		}
19486d7f5d3SJohn Marino 
19586d7f5d3SJohn Marino 		if (out >= ID_LEN) {
19686d7f5d3SJohn Marino 			log_error("Too many characters to be uuid.");
19786d7f5d3SJohn Marino 			return 0;
19886d7f5d3SJohn Marino 		}
19986d7f5d3SJohn Marino 
20086d7f5d3SJohn Marino 		id->uuid[out++] = *buffer++;
20186d7f5d3SJohn Marino 	}
20286d7f5d3SJohn Marino 
20386d7f5d3SJohn Marino 	if (out != ID_LEN) {
20486d7f5d3SJohn Marino 		log_error("Couldn't read uuid: incorrect number of "
20586d7f5d3SJohn Marino 			  "characters.");
20686d7f5d3SJohn Marino 		return 0;
20786d7f5d3SJohn Marino 	}
20886d7f5d3SJohn Marino 
20986d7f5d3SJohn Marino 	return id_valid(id);
21086d7f5d3SJohn Marino }
211