Fix: use of strnlen breaks build on Solaris 10
[lttng-tools.git] / src / common / uuid.c
1 /*
2 * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 * Copyright (C) 2019 Michael Jeanson <mjeanson@efficios.com>
4 *
5 * This library is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License, version 2.1 only,
7 * as published by the Free Software Foundation.
8 *
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <common/compat/string.h>
20 #include <stddef.h>
21 #include <stdint.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26
27 #include "uuid.h"
28
29 static const lttng_uuid nil_uuid;
30 static bool lttng_uuid_is_init;
31
32 void lttng_uuid_to_str(const lttng_uuid uuid, char *uuid_str)
33 {
34 sprintf(uuid_str, LTTNG_UUID_FMT, LTTNG_UUID_FMT_VALUES(uuid));
35 }
36
37 int lttng_uuid_from_str(const char *str_in, lttng_uuid uuid_out)
38 {
39 int ret = 0;
40 lttng_uuid uuid_scan;
41
42 if ((str_in == NULL) || (uuid_out == NULL)) {
43 ret = -1;
44 goto end;
45 }
46
47 if (lttng_strnlen(str_in, LTTNG_UUID_STR_LEN) != LTTNG_UUID_STR_LEN - 1) {
48 ret = -1;
49 goto end;
50 }
51
52 /* Scan to a temporary location in case of a partial match. */
53 if (sscanf(str_in, LTTNG_UUID_FMT, LTTNG_UUID_SCAN_VALUES(uuid_scan)) !=
54 LTTNG_UUID_LEN) {
55 ret = -1;
56 }
57
58 lttng_uuid_copy(uuid_out, uuid_scan);
59 end:
60 return ret;
61 }
62
63 bool lttng_uuid_is_equal(const lttng_uuid a, const lttng_uuid b)
64 {
65 return memcmp(a, b, LTTNG_UUID_LEN) == 0;
66 }
67
68 bool lttng_uuid_is_nil(const lttng_uuid uuid)
69 {
70 return memcmp(nil_uuid, uuid, sizeof(lttng_uuid)) == 0;
71 }
72
73 void lttng_uuid_copy(lttng_uuid dst, const lttng_uuid src)
74 {
75 memcpy(dst, src, LTTNG_UUID_LEN);
76 }
77
78 /*
79 * Generate a random UUID according to RFC4122, section 4.4.
80 */
81 int lttng_uuid_generate(lttng_uuid uuid_out)
82 {
83 int i, ret = 0;
84
85 if (uuid_out == NULL) {
86 ret = -1;
87 goto end;
88 }
89
90 if (!lttng_uuid_is_init) {
91 /*
92 * We don't need cryptographic quality randomness to
93 * generate UUIDs, seed rand with the epoch.
94 */
95 const time_t epoch = time(NULL);
96
97 if (epoch == (time_t) -1) {
98 ret = -1;
99 goto end;
100 }
101 srand(epoch);
102
103 lttng_uuid_is_init = true;
104 }
105
106 /*
107 * Generate 16 bytes of random bits.
108 */
109 for (i = 0; i < LTTNG_UUID_LEN; i++) {
110 uuid_out[i] = (uint8_t) rand();
111 }
112
113 /*
114 * Set the two most significant bits (bits 6 and 7) of the
115 * clock_seq_hi_and_reserved to zero and one, respectively.
116 */
117 uuid_out[8] &= ~(1 << 6);
118 uuid_out[8] |= (1 << 7);
119
120 /*
121 * Set the four most significant bits (bits 12 through 15) of the
122 * time_hi_and_version field to the 4-bit version number from
123 * Section 4.1.3.
124 */
125 uuid_out[6] &= 0x0f;
126 uuid_out[6] |= (LTTNG_UUID_VER << 4);
127
128 end:
129 return ret;
130 }
This page took 0.03158 seconds and 4 git commands to generate.