Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /* NOTE: for this file to work correctly, the random number generator
14 : * must have been seeded (srand) with something like the current time */
15 :
16 : #include "monetdb_config.h"
17 : #include "muuid.h"
18 : #include <string.h> /* strdup */
19 : #include <unistd.h> /* for getentropy on FreeBSD */
20 : #if defined(HAVE_GETENTROPY) && defined(HAVE_SYS_RANDOM_H)
21 : #include <sys/random.h>
22 : #endif
23 :
24 : #if !defined(HAVE_GETENTROPY) && defined(HAVE_RAND_S)
25 : static inline bool
26 : generate_uuid(char *out)
27 : {
28 : union {
29 : unsigned int randbuf[4];
30 : unsigned char uuid[16];
31 : } u;
32 : for (int i = 0; i < 4; i++)
33 : if (rand_s(&u.randbuf[i]) != 0)
34 : return false;
35 : /* make sure this is a variant 1 UUID (RFC 4122/DCE 1.1) */
36 : u.uuid[8] = (u.uuid[8] & 0x3F) | 0x80;
37 : /* make sure this is version 4 (random UUID) */
38 : u.uuid[6] = (u.uuid[6] & 0x0F) | 0x40;
39 : snprintf(out, 37,
40 : "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
41 : "%02x%02x%02x%02x%02x%02x",
42 : u.uuid[0], u.uuid[1], u.uuid[2], u.uuid[3],
43 : u.uuid[4], u.uuid[5], u.uuid[6], u.uuid[7],
44 : u.uuid[8], u.uuid[9], u.uuid[10], u.uuid[11],
45 : u.uuid[12], u.uuid[13], u.uuid[14], u.uuid[15]);
46 : return true;
47 : }
48 : #endif
49 :
50 : char *
51 511 : generateUUID(void)
52 : {
53 511 : char out[37];
54 : #if defined(HAVE_GETENTROPY)
55 511 : unsigned char randbuf[16];
56 511 : if (getentropy(randbuf, 16) == 0) {
57 : /* make sure this is a variant 1 UUID (RFC 4122/DCE 1.1) */
58 511 : randbuf[8] = (randbuf[8] & 0x3F) | 0x80;
59 : /* make sure this is version 4 (random UUID) */
60 511 : randbuf[6] = (randbuf[6] & 0x0F) | 0x40;
61 511 : snprintf(out, sizeof(out),
62 : "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
63 : "%02x%02x%02x%02x%02x%02x",
64 511 : randbuf[0], randbuf[1], randbuf[2], randbuf[3],
65 511 : randbuf[4], randbuf[5], randbuf[6], randbuf[7],
66 511 : randbuf[8], randbuf[9], randbuf[10], randbuf[11],
67 511 : randbuf[12], randbuf[13], randbuf[14], randbuf[15]);
68 : } else
69 : #elif defined(HAVE_RAND_S)
70 : if (!generate_uuid(out))
71 : #endif
72 : {
73 : /* generate something like this:
74 : * cefa7a9c-1dd2-41b2-8350-880020adbeef
75 : * ("%08x-%04x-%04x-%04x-%012x") */
76 : #ifdef __COVERITY__
77 : /* avoid rand() when checking with coverity */
78 : snprintf(out, sizeof(out),
79 : "00000000-0000-0000-0000-000000000000");
80 : #else
81 0 : snprintf(out, sizeof(out),
82 : "%04x%04x-%04x-4%03x-8%03x-%04x%04x%04x",
83 0 : (unsigned) rand() & 0xFFFF, (unsigned) rand() & 0xFFFF,
84 0 : (unsigned) rand() & 0xFFFF, (unsigned) rand() & 0x0FFF,
85 0 : (unsigned) rand() & 0x0FFF, (unsigned) rand() & 0xFFFF,
86 0 : (unsigned) rand() & 0xFFFF, (unsigned) rand() & 0xFFFF);
87 : #endif
88 : }
89 511 : return strdup(out);
90 : }
|