Change log level at g_log_remove_handler
[platform/upstream/glib.git] / glib / guuid.c
1 /* guuid.c - UUID functions
2  *
3  * Copyright (C) 2013-2015, 2017 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as
7  * published by the Free Software Foundation; either version 2.1 of the
8  * licence, or (at your option) any later version.
9  *
10  * This is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
13  * License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
18  * USA.
19  *
20  * Authors: Marc-AndrĂ© Lureau <marcandre.lureau@redhat.com>
21  */
22
23 #include "config.h"
24 #include <string.h>
25
26 #include "gi18n.h"
27 #include "gstrfuncs.h"
28 #include "grand.h"
29 #include "gmessages.h"
30 #include "gchecksum.h"
31
32 #include "guuid.h"
33
34 typedef struct {
35   guint8 bytes[16];
36 } GUuid;
37
38 /**
39  * SECTION:uuid
40  * @title: GUuid
41  * @short_description: a universally unique identifier
42  *
43  * A UUID, or Universally unique identifier, is intended to uniquely
44  * identify information in a distributed environment. For the
45  * definition of UUID, see [RFC 4122](https://tools.ietf.org/html/rfc4122.html).
46  *
47  * The creation of UUIDs does not require a centralized authority.
48  *
49  * UUIDs are of relatively small size (128 bits, or 16 bytes). The
50  * common string representation (ex:
51  * 1d6c0810-2bd6-45f3-9890-0268422a6f14) needs 37 bytes.
52  *
53  * The UUID specification defines 5 versions, and calling
54  * g_uuid_string_random() will generate a unique (or rather random)
55  * UUID of the most common version, version 4.
56  *
57  * Since: 2.52
58  */
59
60 /*
61  * g_uuid_to_string:
62  * @uuid: a #GUuid
63  *
64  * Creates a string representation of @uuid, of the form
65  * 06e023d5-86d8-420e-8103-383e4566087a (no braces nor urn:uuid:
66  * prefix).
67  *
68  * Returns: (transfer full): A string that should be freed with g_free().
69  * Since: STATIC
70  */
71 static gchar *
72 g_uuid_to_string (const GUuid *uuid)
73 {
74   const guint8 *bytes;
75
76   g_return_val_if_fail (uuid != NULL, NULL);
77
78   bytes = uuid->bytes;
79
80   return g_strdup_printf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x"
81                           "-%02x%02x%02x%02x%02x%02x",
82                           bytes[0], bytes[1], bytes[2], bytes[3],
83                           bytes[4], bytes[5], bytes[6], bytes[7],
84                           bytes[8], bytes[9], bytes[10], bytes[11],
85                           bytes[12], bytes[13], bytes[14], bytes[15]);
86 }
87
88 static gboolean
89 uuid_parse_string (const gchar *str,
90                    GUuid       *uuid)
91 {
92   GUuid tmp;
93   guint8 *bytes = tmp.bytes;
94   gint i, j, hi, lo;
95   guint expected_len = 36;
96
97   if (strlen (str) != expected_len)
98     return FALSE;
99
100   for (i = 0, j = 0; i < 16;)
101     {
102       if (j == 8 || j == 13 || j == 18 || j == 23)
103         {
104           if (str[j++] != '-')
105             return FALSE;
106
107           continue;
108         }
109
110       hi = g_ascii_xdigit_value (str[j++]);
111       lo = g_ascii_xdigit_value (str[j++]);
112
113       if (hi == -1 || lo == -1)
114         return FALSE;
115
116       bytes[i++] = hi << 4 | lo;
117     }
118
119   if (uuid != NULL)
120     *uuid = tmp;
121
122   return TRUE;
123 }
124
125 /**
126  * g_uuid_string_is_valid:
127  * @str: a string representing a UUID
128  *
129  * Parses the string @str and verify if it is a UUID.
130  *
131  * The function accepts the following syntax:
132  *
133  * - simple forms (e.g. `f81d4fae-7dec-11d0-a765-00a0c91e6bf6`)
134  *
135  * Note that hyphens are required within the UUID string itself,
136  * as per the aforementioned RFC.
137  *
138  * Returns: %TRUE if @str is a valid UUID, %FALSE otherwise.
139  * Since: 2.52
140  */
141 gboolean
142 g_uuid_string_is_valid (const gchar *str)
143 {
144   g_return_val_if_fail (str != NULL, FALSE);
145
146   return uuid_parse_string (str, NULL);
147 }
148
149 static void
150 uuid_set_version (GUuid *uuid, guint version)
151 {
152   guint8 *bytes = uuid->bytes;
153
154   /*
155    * Set the four most significant bits (bits 12 through 15) of the
156    * time_hi_and_version field to the 4-bit version number from
157    * Section 4.1.3.
158    */
159   bytes[6] &= 0x0f;
160   bytes[6] |= version << 4;
161   /*
162    * Set the two most significant bits (bits 6 and 7) of the
163    * clock_seq_hi_and_reserved to zero and one, respectively.
164    */
165   bytes[8] &= 0x3f;
166   bytes[8] |= 0x80;
167 }
168
169 /*
170  * g_uuid_generate_v4:
171  * @uuid: a #GUuid
172  *
173  * Generates a random UUID (RFC 4122 version 4).
174  * Since: STATIC
175  */
176 static void
177 g_uuid_generate_v4 (GUuid *uuid)
178 {
179   int i;
180   guint8 *bytes;
181   guint32 *ints;
182
183   g_return_if_fail (uuid != NULL);
184
185   bytes = uuid->bytes;
186   ints = (guint32 *) bytes;
187   for (i = 0; i < 4; i++)
188     ints[i] = g_random_int ();
189
190   uuid_set_version (uuid, 4);
191 }
192
193 /**
194  * g_uuid_string_random:
195  *
196  * Generates a random UUID (RFC 4122 version 4) as a string. It has the same
197  * randomness guarantees as #GRand, so must not be used for cryptographic
198  * purposes such as key generation, nonces, salts or one-time pads.
199  *
200  * Returns: (transfer full): A string that should be freed with g_free().
201  * Since: 2.52
202  */
203 gchar *
204 g_uuid_string_random (void)
205 {
206   GUuid uuid;
207
208   g_uuid_generate_v4 (&uuid);
209
210   return g_uuid_to_string (&uuid);
211 }