Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / lib / uuid / uuid.c
blob82d510692bbaff5f9a218a07d176e71f26e15453
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include "lib.h"
19 #include "uuid.h"
20 #include "lvm-wrappers.h"
22 #include <assert.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 #include <ctype.h>
28 static const char _c[] =
29 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#";
31 static int _built_inverse;
32 static char _inverse_c[256];
34 int lvid_create(union lvid *lvid, struct id *vgid)
36 memcpy(lvid->id, vgid, sizeof(*lvid->id));
37 return id_create(&lvid->id[1]);
40 void uuid_from_num(char *uuid, uint32_t num)
42 unsigned i;
44 for (i = ID_LEN; i; i--) {
45 uuid[i - 1] = _c[num % (sizeof(_c) - 1)];
46 num /= sizeof(_c) - 1;
50 int lvid_from_lvnum(union lvid *lvid, struct id *vgid, uint32_t lv_num)
52 int i;
54 memcpy(lvid->id, vgid, sizeof(*lvid->id));
56 for (i = ID_LEN; i; i--) {
57 lvid->id[1].uuid[i - 1] = _c[lv_num % (sizeof(_c) - 1)];
58 lv_num /= sizeof(_c) - 1;
61 lvid->s[sizeof(lvid->s) - 1] = '\0';
63 return 1;
66 int lvnum_from_lvid(union lvid *lvid)
68 int i, lv_num = 0;
69 char *c;
71 for (i = 0; i < ID_LEN; i++) {
72 lv_num *= sizeof(_c) - 1;
73 if ((c = strchr(_c, lvid->id[1].uuid[i])))
74 lv_num += (int) (c - _c);
75 if (lv_num < 0)
76 lv_num = 0;
79 return lv_num;
82 int lvid_in_restricted_range(union lvid *lvid)
84 int i;
86 for (i = 0; i < ID_LEN - 3; i++)
87 if (lvid->id[1].uuid[i] != '0')
88 return 0;
90 for (i = ID_LEN - 3; i < ID_LEN; i++)
91 if (!isdigit(lvid->id[1].uuid[i]))
92 return 0;
94 return 1;
98 int id_create(struct id *id)
100 unsigned i;
101 size_t len = sizeof(id->uuid);
103 memset(id->uuid, 0, len);
104 if (!read_urandom(&id->uuid, len)) {
105 return 0;
109 * Skip out the last 2 chars in randomized creation for LVM1
110 * backwards compatibility.
112 for (i = 0; i < len; i++)
113 id->uuid[i] = _c[id->uuid[i] % (sizeof(_c) - 3)];
115 return 1;
119 * The only validity check we have is that
120 * the uuid just contains characters from
121 * '_c'. A checksum would have been nice :(
123 static void _build_inverse(void)
125 const char *ptr;
127 if (_built_inverse)
128 return;
130 memset(_inverse_c, 0, sizeof(_inverse_c));
132 for (ptr = _c; *ptr; ptr++)
133 _inverse_c[(int) *ptr] = (char) 0x1;
136 int id_valid(struct id *id)
138 int i;
140 _build_inverse();
142 for (i = 0; i < ID_LEN; i++)
143 if (!_inverse_c[id->uuid[i]]) {
144 log_error("UUID contains invalid character");
145 return 0;
148 return 1;
151 int id_equal(const struct id *lhs, const struct id *rhs)
153 return !memcmp(lhs->uuid, rhs->uuid, sizeof(lhs->uuid));
156 #define GROUPS (ID_LEN / 4)
158 int id_write_format(const struct id *id, char *buffer, size_t size)
160 int i, tot;
162 static unsigned group_size[] = { 6, 4, 4, 4, 4, 4, 6 };
164 assert(ID_LEN == 32);
166 /* split into groups separated by dashes */
167 if (size < (32 + 6 + 1)) {
168 log_error("Couldn't write uuid, buffer too small.");
169 return 0;
172 for (i = 0, tot = 0; i < 7; i++) {
173 memcpy(buffer, id->uuid + tot, group_size[i]);
174 buffer += group_size[i];
175 tot += group_size[i];
176 *buffer++ = '-';
179 *--buffer = '\0';
180 return 1;
183 int id_read_format(struct id *id, const char *buffer)
185 int out = 0;
187 /* just strip out any dashes */
188 while (*buffer) {
190 if (*buffer == '-') {
191 buffer++;
192 continue;
195 if (out >= ID_LEN) {
196 log_error("Too many characters to be uuid.");
197 return 0;
200 id->uuid[out++] = *buffer++;
203 if (out != ID_LEN) {
204 log_error("Couldn't read uuid: incorrect number of "
205 "characters.");
206 return 0;
209 return id_valid(id);