"Fossies" - the Fresh Open Source Software Archive 
Member "netxms-3.8.166/src/libnetxms/uuid.cpp" (23 Feb 2021, 6833 Bytes) of package /linux/misc/netxms-3.8.166.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "uuid.cpp" see the
Fossies "Dox" file reference documentation.
1 /*
2 ** libuuid integrated into NetXMS project
3 ** Copyright (C) 1996, 1997 Theodore Ts'o.
4 ** Integrated into NetXMS by Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: uuid.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25 #include <uuid.h>
26
27 #if _WITH_ENCRYPTION
28 #include <openssl/rand.h>
29 #endif
30
31 /**
32 * NULL GUID
33 */
34 const uuid __EXPORT uuid::NULL_UUID = uuid();
35
36 /*
37 * Offset between 15-Oct-1582 and 1-Jan-70
38 */
39 #define TIME_OFFSET_HIGH 0x01B21DD2
40 #define TIME_OFFSET_LOW 0x13814000
41
42 /**
43 * Unpacked UUID structure
44 */
45 struct __uuid
46 {
47 uint32_t time_low;
48 uint16_t time_mid;
49 uint16_t time_hi_and_version;
50 uint16_t clock_seq;
51 uint8_t node[6];
52 };
53
54 /**
55 * Internal routine for packing UUID's
56 */
57 static void uuid_pack(struct __uuid *uu, uuid_t ptr)
58 {
59 uint32_t tmp;
60 uint8_t *out = ptr;
61
62 tmp = uu->time_low;
63 out[3] = (uint8_t)tmp;
64 tmp >>= 8;
65 out[2] = (uint8_t)tmp;
66 tmp >>= 8;
67 out[1] = (uint8_t)tmp;
68 tmp >>= 8;
69 out[0] = (uint8_t)tmp;
70
71 tmp = uu->time_mid;
72 out[5] = (uint8_t)tmp;
73 tmp >>= 8;
74 out[4] = (uint8_t)tmp;
75
76 tmp = uu->time_hi_and_version;
77 out[7] = (uint8_t)tmp;
78 tmp >>= 8;
79 out[6] = (uint8_t)tmp;
80
81 tmp = uu->clock_seq;
82 out[9] = (uint8_t)tmp;
83 tmp >>= 8;
84 out[8] = (uint8_t)tmp;
85
86 memcpy(out + 10, uu->node, 6);
87 }
88
89 /**
90 * Internal routine for unpacking UUID
91 */
92 static void uuid_unpack(const uuid_t in, struct __uuid *uu)
93 {
94 const uint8_t *ptr = in;
95 uint32_t tmp;
96
97 tmp = *ptr++;
98 tmp = (tmp << 8) | *ptr++;
99 tmp = (tmp << 8) | *ptr++;
100 tmp = (tmp << 8) | *ptr++;
101 uu->time_low = tmp;
102
103 tmp = *ptr++;
104 tmp = (tmp << 8) | *ptr++;
105 uu->time_mid = tmp;
106
107 tmp = *ptr++;
108 tmp = (tmp << 8) | *ptr++;
109 uu->time_hi_and_version = tmp;
110
111 tmp = *ptr++;
112 tmp = (tmp << 8) | *ptr++;
113 uu->clock_seq = tmp;
114
115 memcpy(uu->node, ptr, 6);
116 }
117
118 /**
119 * Clear a UUID
120 */
121 void LIBNETXMS_EXPORTABLE _uuid_clear(uuid_t uu)
122 {
123 memset(uu, 0, 16);
124 }
125
126 #define UUCMP(u1,u2) if (u1 != u2) return((u1 < u2) ? -1 : 1);
127
128 /**
129 * compare whether or not two UUID's are the same
130 *
131 * Returns 1/-1 if the two UUID's are different, and 0 if they are the same.
132 */
133 int LIBNETXMS_EXPORTABLE _uuid_compare(const uuid_t uu1, const uuid_t uu2)
134 {
135 struct __uuid uuid1, uuid2;
136
137 uuid_unpack(uu1, &uuid1);
138 uuid_unpack(uu2, &uuid2);
139
140 UUCMP(uuid1.time_low, uuid2.time_low);
141 UUCMP(uuid1.time_mid, uuid2.time_mid);
142 UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
143 UUCMP(uuid1.clock_seq, uuid2.clock_seq);
144 return memcmp(uuid1.node, uuid2.node, 6);
145 }
146
147 /**
148 * isnull.c --- Check whether or not the UUID is null
149 * Returns true if the uuid is the NULL uuid
150 */
151 bool LIBNETXMS_EXPORTABLE _uuid_is_null(const uuid_t uu)
152 {
153 const uint8_t *cp = uu;
154 for (int i = 0; i < 16; i++)
155 if (*cp++)
156 return false;
157 return true;
158 }
159
160 /**
161 * Parse UUID
162 */
163 int LIBNETXMS_EXPORTABLE _uuid_parse(const TCHAR *in, uuid_t uu)
164 {
165 struct __uuid uuid;
166 int i;
167 const TCHAR *cp;
168 TCHAR buf[3];
169
170 if (_tcslen(in) != 36)
171 return -1;
172 for (i=0, cp = in; i <= 36; i++,cp++) {
173 if ((i == 8) || (i == 13) || (i == 18) ||
174 (i == 23))
175 if (*cp == _T('-'))
176 continue;
177 if (i == 36)
178 if (*cp == 0)
179 continue;
180 if (!_istxdigit(*cp))
181 return -1;
182 }
183 uuid.time_low = _tcstoul(in, NULL, 16);
184 uuid.time_mid = (WORD)_tcstoul(in + 9, NULL, 16);
185 uuid.time_hi_and_version = (WORD)_tcstoul(in + 14, NULL, 16);
186 uuid.clock_seq = (WORD)_tcstoul(in + 19, NULL, 16);
187 cp = in + 24;
188 buf[2] = 0;
189 for(i = 0; i < 6; i++)
190 {
191 buf[0] = *cp++;
192 buf[1] = *cp++;
193 uuid.node[i] = (BYTE)_tcstoul(buf, NULL, 16);
194 }
195
196 uuid_pack(&uuid, uu);
197 return 0;
198 }
199
200 /**
201 * Convert packed UUID to string
202 */
203 TCHAR LIBNETXMS_EXPORTABLE *_uuid_to_string(const uuid_t uu, TCHAR *out)
204 {
205 struct __uuid uuid;
206 uuid_unpack(uu, &uuid);
207 _sntprintf(out, 37,
208 _T("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"),
209 uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
210 uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
211 uuid.node[0], uuid.node[1], uuid.node[2],
212 uuid.node[3], uuid.node[4], uuid.node[5]);
213 return out;
214 }
215
216 #ifdef UNICODE
217
218 /**
219 * Convert packed UUID to string (non-UNICODE version)
220 */
221 char LIBNETXMS_EXPORTABLE *_uuid_to_stringA(const uuid_t uu, char *out)
222 {
223 struct __uuid uuid;
224 uuid_unpack(uu, &uuid);
225 snprintf(out, 37,
226 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
227 uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
228 uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
229 uuid.node[0], uuid.node[1], uuid.node[2],
230 uuid.node[3], uuid.node[4], uuid.node[5]);
231 return out;
232 }
233
234 #endif
235
236 #ifndef _WIN32
237
238 static int get_random_fd()
239 {
240 int fd = open("/dev/urandom", O_RDONLY);
241 if (fd == -1)
242 fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
243 return fd;
244 }
245
246 /*
247 * Generate a series of random bytes. Use /dev/urandom if possible,
248 * and if not, use srandom/random.
249 */
250 static void get_random_bytes(void *buf, int nbytes)
251 {
252 #if _WITH_ENCRYPTION
253 if (RAND_bytes(static_cast<unsigned char*>(buf), nbytes))
254 return;
255 #endif
256
257 char *cp = (char *)buf;
258 int fd = get_random_fd();
259 if (fd >= 0)
260 {
261 int lose_counter = 0;
262
263 while (nbytes > 0)
264 {
265 int i = read(fd, cp, nbytes);
266 if ((i < 0) &&
267 ((errno == EINTR) || (errno == EAGAIN)))
268 continue;
269 if (i <= 0)
270 {
271 if (lose_counter++ == 8)
272 break;
273 continue;
274 }
275 nbytes -= i;
276 cp += i;
277 lose_counter = 0;
278 }
279 close(fd);
280 }
281 if (nbytes == 0)
282 return;
283
284 // Use libc rand() as last resort
285 for(int i = 0; i < nbytes; i++)
286 *cp++ = rand() & 0xFF;
287 }
288
289 static void uuid_generate_random(uuid_t out)
290 {
291 uuid_t buf;
292 struct __uuid uu;
293
294 get_random_bytes(buf, sizeof(buf));
295 uuid_unpack(buf, &uu);
296
297 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
298 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
299 uuid_pack(&uu, out);
300 }
301
302 #endif /* _WIN32 */
303
304 /*
305 * This is the generic front-end to uuid_generate_random and
306 * uuid_generate_time. It uses uuid_generate_random only if
307 * /dev/urandom is available, since otherwise we won't have
308 * high-quality randomness.
309 */
310 void LIBNETXMS_EXPORTABLE _uuid_generate(uuid_t out)
311 {
312 #ifdef _WIN32
313 UUID uuid;
314 UuidCreate(&uuid);
315 memcpy(out, &uuid, UUID_LENGTH);
316 #else
317 uuid_generate_random(out);
318 #endif
319 }