[lttng-dev] [PATCH lttng-tools] Replace libuuid with internal implementation

Michael Jeanson mjeanson at efficios.com
Thu Oct 24 11:36:47 EDT 2019


We use a very small subset of libuuid features to transform UUIDs
between their string and binary representation. Plus we have a lot of
compat code for different platforms with some unspecified default
behavior regarding the use of upper/lower case.

Drop the dependency on libuuid and replace it with a minimal internal
implementation that respects RFC4122.

Signed-off-by: Michael Jeanson <mjeanson at efficios.com>
---
 .gitignore                                   |   1 +
 configure.ac                                 |  42 ----
 src/bin/lttng-relayd/cmd-2-11.h              |   2 +-
 src/bin/lttng-relayd/main.c                  |   6 +-
 src/bin/lttng-relayd/session.c               |   4 +-
 src/bin/lttng-relayd/session.h               |   2 +-
 src/bin/lttng-relayd/sessiond-trace-chunks.c |  16 +-
 src/bin/lttng-relayd/sessiond-trace-chunks.h |   2 +-
 src/bin/lttng-sessiond/globals.c             |   2 +-
 src/bin/lttng-sessiond/lttng-sessiond.h      |   2 +-
 src/bin/lttng-sessiond/main.c                |   2 +-
 src/bin/lttng-sessiond/ust-app.h             |   2 +-
 src/bin/lttng-sessiond/ust-clock.h           |   2 +-
 src/bin/lttng-sessiond/ust-metadata.c        |   4 +-
 src/bin/lttng-sessiond/ust-registry.h        |   4 +-
 src/common/Makefile.am                       |   6 +-
 src/common/compat/Makefile.am                |   2 +-
 src/common/compat/uuid.c                     |  48 -----
 src/common/consumer/consumer.c               |   2 +-
 src/common/consumer/consumer.h               |   4 +-
 src/common/sessiond-comm/relayd.h            |   2 +-
 src/common/sessiond-comm/sessiond-comm.h     |   4 +-
 src/common/uuid.c                            | 130 +++++++++++++
 src/common/{compat => }/uuid.h               |  66 +++----
 tests/unit/Makefile.am                       |   6 +-
 tests/unit/test_uuid.c                       | 193 +++++++++++++++++++
 26 files changed, 393 insertions(+), 163 deletions(-)
 delete mode 100644 src/common/compat/uuid.c
 create mode 100644 src/common/uuid.c
 rename src/common/{compat => }/uuid.h (58%)
 create mode 100644 tests/unit/test_uuid.c

diff --git a/.gitignore b/.gitignore
index 00a68d427..1bdbacb5c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -83,6 +83,7 @@ compile_commands.json
 /tests/unit/test_utils_parse_size_suffix
 /tests/unit/test_utils_parse_time_suffix
 /tests/unit/test_utils_expand_path
+/tests/unit/test_uuid
 /tests/unit/test_notification
 /tests/unit/test_directory_handle
 kernel_all_events_basic
diff --git a/configure.ac b/configure.ac
index dd708883b..8c0683fe2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -448,48 +448,6 @@ AC_SUBST(POPT_LIBS)
 
 PKG_CHECK_MODULES([libxml2], [libxml-2.0 >= 2.7.6])
 
-# First, check for uuid in system libs
-AH_TEMPLATE([LTTNG_HAVE_LIBUUID], [Define if you have libuuid support])
-AC_CHECK_FUNCS([uuid_generate],
-  [
-    AC_DEFINE([LTTNG_HAVE_LIBUUID], [1])
-    UUID_LIBS=""
-  ],
-  [
-    # Then, check if the pkg-config module is available, otherwise explicitly check
-    # for libuuid, or uuid support in the C-library.
-    PKG_CHECK_MODULES([UUID], [uuid],
-      [
-        AC_DEFINE([LTTNG_HAVE_LIBUUID], [1])
-        dnl PKG_CHECK_MODULES defines UUID_LIBS
-      ],
-      [
-        AC_MSG_WARN([pkg-config was unable to find a valid .pc for libuuid. Set PKG_CONFIG_PATH to specify the pkgconfig configuration file location])
-        AC_MSG_WARN([Finding libuuid without pkg-config.])
-        AC_CHECK_LIB([uuid], [uuid_generate],
-          [
-            AC_DEFINE([LTTNG_HAVE_LIBUUID], [1])
-            UUID_LIBS="-luuid"
-          ],
-          [
-            # libuuid not found, check for uuid_create in libc.
-            AC_CHECK_LIB([c], [uuid_create],
-              [
-                AC_DEFINE([LTTNG_HAVE_LIBUUID], [1])
-                UUID_LIBS="-lc"
-              ],
-              [
-                AC_MSG_FAILURE([Cannot find libuuid uuid_generate nor libc uuid_create. Either set PKG_CONFIG_PATH to the configuration file location or use LDFLAGS=-Ldir to specify the library location])
-              ]
-            )
-          ]
-        )
-      ]
-    )
-  ]
-)
-AC_SUBST(UUID_LIBS)
-
 AC_CHECK_FUNC([clock_gettime], [AC_DEFINE_UNQUOTED([LTTNG_HAVE_CLOCK_GETTIME], 1, [Has clock_gettime() support.])])
 
 # URCU library version needed or newer
diff --git a/src/bin/lttng-relayd/cmd-2-11.h b/src/bin/lttng-relayd/cmd-2-11.h
index fc9021024..8ac089482 100644
--- a/src/bin/lttng-relayd/cmd-2-11.h
+++ b/src/bin/lttng-relayd/cmd-2-11.h
@@ -19,7 +19,7 @@
 
 #include "lttng-relayd.h"
 #include <common/buffer-view.h>
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 
 int cmd_create_session_2_11(const struct lttng_buffer_view *payload,
 		char *session_name, char *hostname, char *base_path,
diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c
index 5f72c32a9..66505bfd5 100644
--- a/src/bin/lttng-relayd/main.c
+++ b/src/bin/lttng-relayd/main.c
@@ -2265,7 +2265,7 @@ static int relay_rotate_session_streams(
 				session->sessiond_uuid, session->id,
 				rotate_streams.new_chunk_id.value);
 		if (!next_trace_chunk) {
-			char uuid_str[UUID_STR_LEN];
+			char uuid_str[LTTNG_UUID_STR_LEN];
 
 			lttng_uuid_to_str(session->sessiond_uuid, uuid_str);
 			ERR("Unknown next trace chunk in ROTATE_STREAMS command: sessiond_uuid = {%s}, session_id = %" PRIu64
@@ -2465,7 +2465,7 @@ static int relay_create_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
 			conn->session->id,
 			chunk);
 	if (!published_chunk) {
-		char uuid_str[UUID_STR_LEN];
+		char uuid_str[LTTNG_UUID_STR_LEN];
 
 		lttng_uuid_to_str(conn->session->sessiond_uuid, uuid_str);
 		ERR("Failed to publish chunk: sessiond_uuid = %s, session_id = %" PRIu64 ", chunk_id = %" PRIu64,
@@ -2571,7 +2571,7 @@ static int relay_close_trace_chunk(const struct lttcomm_relayd_hdr *recv_hdr,
 			conn->session->id,
 			chunk_id);
 	if (!chunk) {
-		char uuid_str[UUID_STR_LEN];
+		char uuid_str[LTTNG_UUID_STR_LEN];
 
 		lttng_uuid_to_str(conn->session->sessiond_uuid, uuid_str);
 		ERR("Failed to find chunk to close: sessiond_uuid = %s, session_id = %" PRIu64 ", chunk_id = %" PRIu64,
diff --git a/src/bin/lttng-relayd/session.c b/src/bin/lttng-relayd/session.c
index 2f65848a9..d6e666407 100644
--- a/src/bin/lttng-relayd/session.c
+++ b/src/bin/lttng-relayd/session.c
@@ -20,7 +20,7 @@
 #define _LGPL_SOURCE
 #include <common/common.h>
 #include <common/utils.h>
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 #include <urcu/rculist.h>
 
 #include <sys/stat.h>
@@ -274,7 +274,7 @@ struct relay_session *session_create(const char *session_name,
 					session->id_sessiond.value,
 					*current_chunk_id);
 		if (!session->current_trace_chunk) {
-		        char uuid_str[UUID_STR_LEN];
+		        char uuid_str[LTTNG_UUID_STR_LEN];
 
 			lttng_uuid_to_str(sessiond_uuid, uuid_str);
 			ERR("Could not find trace chunk: sessiond = {%s}, sessiond session id = %" PRIu64 ", trace chunk id = %" PRIu64,
diff --git a/src/bin/lttng-relayd/session.h b/src/bin/lttng-relayd/session.h
index 288672dcc..e96fbbc0e 100644
--- a/src/bin/lttng-relayd/session.h
+++ b/src/bin/lttng-relayd/session.h
@@ -28,7 +28,7 @@
 
 #include <lttng/constant.h>
 #include <common/hashtable/hashtable.h>
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 #include <common/trace-chunk.h>
 #include <common/optional.h>
 
diff --git a/src/bin/lttng-relayd/sessiond-trace-chunks.c b/src/bin/lttng-relayd/sessiond-trace-chunks.c
index f2dfa23a1..db9f55801 100644
--- a/src/bin/lttng-relayd/sessiond-trace-chunks.c
+++ b/src/bin/lttng-relayd/sessiond-trace-chunks.c
@@ -120,7 +120,7 @@ void trace_chunk_registry_ht_element_release(struct urcu_ref *ref)
 {
 	struct trace_chunk_registry_ht_element *element =
 			container_of(ref, typeof(*element), ref);
-	char uuid_str[UUID_STR_LEN];
+	char uuid_str[LTTNG_UUID_STR_LEN];
 
 	lttng_uuid_to_str(element->key.sessiond_uuid, uuid_str);
 
@@ -197,7 +197,7 @@ int trace_chunk_registry_ht_element_create(
 	int ret = 0;
 	struct trace_chunk_registry_ht_element *new_element;
 	struct lttng_trace_chunk_registry *trace_chunk_registry;
-	char uuid_str[UUID_STR_LEN];
+	char uuid_str[LTTNG_UUID_STR_LEN];
 
 	lttng_uuid_to_str(key->sessiond_uuid, uuid_str);
 
@@ -313,7 +313,7 @@ int sessiond_trace_chunk_registry_session_created(
 
 	element = trace_chunk_registry_ht_element_find(sessiond_registry, &key);
 	if (element) {
-		char uuid_str[UUID_STR_LEN];
+		char uuid_str[LTTNG_UUID_STR_LEN];
 
 		lttng_uuid_to_str(sessiond_uuid, uuid_str);
 		DBG("Acquired reference to trace chunk registry of sessiond {%s}",
@@ -334,7 +334,7 @@ int sessiond_trace_chunk_registry_session_destroyed(
 	int ret = 0;
 	struct trace_chunk_registry_ht_key key;
 	struct trace_chunk_registry_ht_element *element;
-	char uuid_str[UUID_STR_LEN];
+	char uuid_str[LTTNG_UUID_STR_LEN];
 
 	lttng_uuid_to_str(sessiond_uuid, uuid_str);
 	lttng_uuid_copy(key.sessiond_uuid, sessiond_uuid);
@@ -367,7 +367,7 @@ struct lttng_trace_chunk *sessiond_trace_chunk_registry_publish_chunk(
 	bool is_anonymous_chunk;
 	struct trace_chunk_registry_ht_key key;
 	struct trace_chunk_registry_ht_element *element = NULL;
-	char uuid_str[UUID_STR_LEN];
+	char uuid_str[LTTNG_UUID_STR_LEN];
 	char chunk_id_str[MAX_INT_DEC_LEN(typeof(chunk_id))] = "-1";
 	struct lttng_trace_chunk *published_chunk = NULL;
 
@@ -432,7 +432,7 @@ sessiond_trace_chunk_registry_get_anonymous_chunk(
 	struct lttng_trace_chunk *chunk = NULL;
 	struct trace_chunk_registry_ht_element *element;
 	struct trace_chunk_registry_ht_key key;
-	char uuid_str[UUID_STR_LEN];
+	char uuid_str[LTTNG_UUID_STR_LEN];
 
 	lttng_uuid_to_str(sessiond_uuid, uuid_str);
 
@@ -461,7 +461,7 @@ sessiond_trace_chunk_registry_get_chunk(
 	struct lttng_trace_chunk *chunk = NULL;
 	struct trace_chunk_registry_ht_element *element;
 	struct trace_chunk_registry_ht_key key;
-	char uuid_str[UUID_STR_LEN];
+	char uuid_str[LTTNG_UUID_STR_LEN];
 
 	lttng_uuid_to_str(sessiond_uuid, uuid_str);
 
@@ -493,7 +493,7 @@ int sessiond_trace_chunk_registry_chunk_exists(
 	lttng_uuid_copy(key.sessiond_uuid, sessiond_uuid);
 	element = trace_chunk_registry_ht_element_find(sessiond_registry, &key);
 	if (!element) {
-		char uuid_str[UUID_STR_LEN];
+		char uuid_str[LTTNG_UUID_STR_LEN];
 
 		lttng_uuid_to_str(sessiond_uuid, uuid_str);
 		/*
diff --git a/src/bin/lttng-relayd/sessiond-trace-chunks.h b/src/bin/lttng-relayd/sessiond-trace-chunks.h
index c62fd3e6f..f05877ac9 100644
--- a/src/bin/lttng-relayd/sessiond-trace-chunks.h
+++ b/src/bin/lttng-relayd/sessiond-trace-chunks.h
@@ -18,7 +18,7 @@
 #ifndef SESSIOND_TRACE_CHUNK_REGISTRY_H
 #define SESSIOND_TRACE_CHUNK_REGISTRY_H
 
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 #include <common/trace-chunk.h>
 #include <stdint.h>
 
diff --git a/src/bin/lttng-sessiond/globals.c b/src/bin/lttng-sessiond/globals.c
index ef57a960d..6646202b8 100644
--- a/src/bin/lttng-sessiond/globals.c
+++ b/src/bin/lttng-sessiond/globals.c
@@ -18,7 +18,7 @@
  */
 
 #include "lttng-sessiond.h"
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 
 lttng_uuid sessiond_uuid;
 
diff --git a/src/bin/lttng-sessiond/lttng-sessiond.h b/src/bin/lttng-sessiond/lttng-sessiond.h
index 8846262b6..92f051c16 100644
--- a/src/bin/lttng-sessiond/lttng-sessiond.h
+++ b/src/bin/lttng-sessiond/lttng-sessiond.h
@@ -25,7 +25,7 @@
 #include <common/sessiond-comm/sessiond-comm.h>
 #include <common/compat/poll.h>
 #include <common/compat/socket.h>
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 
 #include "session.h"
 #include "ust-app.h"
diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c
index 38ff2fd26..fce327314 100644
--- a/src/bin/lttng-sessiond/main.c
+++ b/src/bin/lttng-sessiond/main.c
@@ -1286,7 +1286,7 @@ static int launch_run_as_worker(const char *procname)
 
 static void sessiond_uuid_log(void)
 {
-	char uuid_str[UUID_STR_LEN];
+	char uuid_str[LTTNG_UUID_STR_LEN];
 
 	lttng_uuid_to_str(sessiond_uuid, uuid_str);
 	DBG("Starting lttng-sessiond {%s}", uuid_str);
diff --git a/src/bin/lttng-sessiond/ust-app.h b/src/bin/lttng-sessiond/ust-app.h
index 4c8c3cc62..86f747d6b 100644
--- a/src/bin/lttng-sessiond/ust-app.h
+++ b/src/bin/lttng-sessiond/ust-app.h
@@ -21,7 +21,7 @@
 
 #include <stdint.h>
 
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 
 #include "trace-ust.h"
 #include "ust-registry.h"
diff --git a/src/bin/lttng-sessiond/ust-clock.h b/src/bin/lttng-sessiond/ust-clock.h
index 58ff8b9d0..07920e060 100644
--- a/src/bin/lttng-sessiond/ust-clock.h
+++ b/src/bin/lttng-sessiond/ust-clock.h
@@ -29,7 +29,7 @@
 #include <urcu/arch.h>
 #include <lttng/ust-clock.h>
 
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 
 /* TRACE CLOCK */
 
diff --git a/src/bin/lttng-sessiond/ust-metadata.c b/src/bin/lttng-sessiond/ust-metadata.c
index 08199a16a..c29ed348b 100644
--- a/src/bin/lttng-sessiond/ust-metadata.c
+++ b/src/bin/lttng-sessiond/ust-metadata.c
@@ -1008,8 +1008,8 @@ int ust_metadata_session_statedump(struct ust_registry_session *session,
 		uint32_t major,
 		uint32_t minor)
 {
-	char uuid_s[UUID_STR_LEN],
-		clock_uuid_s[UUID_STR_LEN];
+	char uuid_s[LTTNG_UUID_STR_LEN],
+		clock_uuid_s[LTTNG_UUID_STR_LEN];
 	int ret = 0;
 
 	assert(session);
diff --git a/src/bin/lttng-sessiond/ust-registry.h b/src/bin/lttng-sessiond/ust-registry.h
index e118ac8cc..0b52cc1e1 100644
--- a/src/bin/lttng-sessiond/ust-registry.h
+++ b/src/bin/lttng-sessiond/ust-registry.h
@@ -22,7 +22,7 @@
 #include <stdint.h>
 
 #include <common/hashtable/hashtable.h>
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 
 #include "lttng-ust-ctl.h"
 
@@ -48,7 +48,7 @@ struct ust_registry_session {
 	/* Next enumeration ID available. */
 	uint64_t next_enum_id;
 	/* Universal unique identifier used by the tracer. */
-	unsigned char uuid[UUID_LEN];
+	unsigned char uuid[LTTNG_UUID_LEN];
 
 	/* session ABI description */
 
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 896e2d6a1..953a366ac 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -30,7 +30,8 @@ libcommon_la_SOURCES = error.h error.c utils.c utils.h runas.h runas.c \
                        userspace-probe.c event.c time.c \
                        session-descriptor.c credentials.h \
                        trace-chunk.c trace-chunk.h trace-chunk-registry.h \
-                       dynamic-array.h dynamic-array.c optional.h
+                       dynamic-array.h dynamic-array.c optional.h \
+                       uuid.c uuid.h
 
 if HAVE_ELF_H
 libcommon_la_SOURCES += lttng-elf.h lttng-elf.c
@@ -39,8 +40,7 @@ endif
 libcommon_la_LIBADD = \
 		$(top_builddir)/src/common/config/libconfig.la \
 		$(top_builddir)/src/common/compat/libcompat.la \
-		$(top_builddir)/src/common/hashtable/libhashtable.la \
-		$(UUID_LIBS)
+		$(top_builddir)/src/common/hashtable/libhashtable.la
 
 if BUILD_LIB_COMPAT
 SUBDIRS += compat
diff --git a/src/common/compat/Makefile.am b/src/common/compat/Makefile.am
index 50c8da298..93528375d 100644
--- a/src/common/compat/Makefile.am
+++ b/src/common/compat/Makefile.am
@@ -7,6 +7,6 @@ COMPAT=compat-poll.c
 endif
 
 libcompat_la_SOURCES = poll.h fcntl.h endian.h mman.h dirent.h \
-		socket.h compat-fcntl.c uuid.h uuid.c tid.h \
+		socket.h compat-fcntl.c tid.h \
 		getenv.h string.h prctl.h paths.h netdb.h $(COMPAT) \
 		time.h directory-handle.h directory-handle.c
diff --git a/src/common/compat/uuid.c b/src/common/compat/uuid.c
deleted file mode 100644
index 72c5c0a0c..000000000
--- a/src/common/compat/uuid.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2018 - Jérémie Galarneau <jeremie.galarneau at efficios.com>
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License, version 2.1 only,
- * as published by the Free Software Foundation.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdio.h>
-#include <common/compat/uuid.h>
-#include <string.h>
-#include <stddef.h>
-
-static const lttng_uuid nil_uuid;
-
-void lttng_uuid_to_str(const lttng_uuid uuid, char *uuid_str)
-{
-	sprintf(uuid_str,
-			"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
-			uuid[0], uuid[1], uuid[2], uuid[3],
-			uuid[4], uuid[5], uuid[6], uuid[7],
-			uuid[8], uuid[9], uuid[10], uuid[11],
-			uuid[12], uuid[13], uuid[14], uuid[15]);
-}
-
-bool lttng_uuid_is_equal(const lttng_uuid a, const lttng_uuid b)
-{
-	return memcmp(a, b, (sizeof(lttng_uuid))) == 0;
-}
-
-bool lttng_uuid_is_nil(const lttng_uuid uuid)
-{
-	return memcmp(nil_uuid, uuid, sizeof(lttng_uuid)) == 0;
-}
-
-void lttng_uuid_copy(lttng_uuid dst, const lttng_uuid src)
-{
-	memcpy(dst, src, sizeof(lttng_uuid));
-}
diff --git a/src/common/consumer/consumer.c b/src/common/consumer/consumer.c
index 09f0f0983..00c0b5137 100644
--- a/src/common/consumer/consumer.c
+++ b/src/common/consumer/consumer.c
@@ -4435,7 +4435,7 @@ enum lttcomm_return_code lttng_consumer_init_command(
 		const lttng_uuid sessiond_uuid)
 {
 	enum lttcomm_return_code ret;
-	char uuid_str[UUID_STR_LEN];
+	char uuid_str[LTTNG_UUID_STR_LEN];
 
 	if (ctx->sessiond_uuid.is_set) {
 		ret = LTTCOMM_CONSUMERD_ALREADY_SET;
diff --git a/src/common/consumer/consumer.h b/src/common/consumer/consumer.h
index 1aaddb5ab..72c580eb2 100644
--- a/src/common/consumer/consumer.h
+++ b/src/common/consumer/consumer.h
@@ -30,7 +30,7 @@
 
 #include <common/hashtable/hashtable.h>
 #include <common/compat/fcntl.h>
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 #include <common/sessiond-comm/sessiond-comm.h>
 #include <common/pipe.h>
 #include <common/index/ctf-index.h>
@@ -159,7 +159,7 @@ struct lttng_consumer_channel {
 	/* For UST */
 	uid_t ust_app_uid;	/* Application UID. */
 	struct ustctl_consumer_channel *uchan;
-	unsigned char uuid[UUID_STR_LEN];
+	unsigned char uuid[LTTNG_UUID_STR_LEN];
 	/*
 	 * Temporary stream list used to store the streams once created and waiting
 	 * to be sent to the session daemon by receiving the
diff --git a/src/common/sessiond-comm/relayd.h b/src/common/sessiond-comm/relayd.h
index efb577e99..de0c7f254 100644
--- a/src/common/sessiond-comm/relayd.h
+++ b/src/common/sessiond-comm/relayd.h
@@ -26,7 +26,7 @@
 #include <common/defaults.h>
 #include <common/index/ctf-index.h>
 #include <common/macros.h>
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 #include <common/optional.h>
 
 #define RELAYD_VERSION_COMM_MAJOR             VERSION_MAJOR
diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h
index a80a6ee97..8c2a47538 100644
--- a/src/common/sessiond-comm/sessiond-comm.h
+++ b/src/common/sessiond-comm/sessiond-comm.h
@@ -35,7 +35,7 @@
 #include <common/compat/socket.h>
 #include <common/uri.h>
 #include <common/defaults.h>
-#include <common/compat/uuid.h>
+#include <common/uuid.h>
 #include <common/macros.h>
 #include <common/optional.h>
 
@@ -543,7 +543,7 @@ struct lttcomm_consumer_msg {
 			uint64_t key;				/* Unique channel key. */
 			/* ID of the session's current trace chunk. */
 			LTTNG_OPTIONAL_COMM(uint64_t) LTTNG_PACKED chunk_id;
-			unsigned char uuid[UUID_LEN];	/* uuid for ust tracer. */
+			unsigned char uuid[LTTNG_UUID_LEN];	/* uuid for ust tracer. */
 			uint32_t chan_id;			/* Channel ID on the tracer side. */
 			uint64_t tracefile_size;	/* bytes */
 			uint32_t tracefile_count;	/* number of tracefiles */
diff --git a/src/common/uuid.c b/src/common/uuid.c
new file mode 100644
index 000000000..850540e16
--- /dev/null
+++ b/src/common/uuid.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 Jérémie Galarneau <jeremie.galarneau at efficios.com>
+ * Copyright (C) 2019 Michael Jeanson <mjeanson at efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License, version 2.1 only,
+ * as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "uuid.h"
+
+static const lttng_uuid nil_uuid;
+static bool lttng_uuid_is_init;
+
+void lttng_uuid_to_str(const lttng_uuid uuid, char *uuid_str)
+{
+	sprintf(uuid_str, LTTNG_UUID_FMT, LTTNG_UUID_FMT_VALUES(uuid));
+}
+
+int lttng_uuid_from_str(const char *str_in, lttng_uuid uuid_out)
+{
+	int ret = 0;
+	lttng_uuid uuid_scan;
+
+	if ((str_in == NULL) || (uuid_out == NULL)) {
+		ret = -1;
+		goto end;
+	}
+
+	if (strnlen(str_in, LTTNG_UUID_STR_LEN) != LTTNG_UUID_STR_LEN - 1) {
+		ret = -1;
+		goto end;
+	}
+
+	/* Scan to a temporary location in case of a partial match. */
+	if (sscanf(str_in, LTTNG_UUID_FMT, LTTNG_UUID_SCAN_VALUES(uuid_scan)) !=
+			LTTNG_UUID_LEN) {
+		ret = -1;
+	}
+
+	lttng_uuid_copy(uuid_out, uuid_scan);
+end:
+	return ret;
+}
+
+bool lttng_uuid_is_equal(const lttng_uuid a, const lttng_uuid b)
+{
+	return memcmp(a, b, LTTNG_UUID_LEN) == 0;
+}
+
+bool lttng_uuid_is_nil(const lttng_uuid uuid)
+{
+	return memcmp(nil_uuid, uuid, sizeof(lttng_uuid)) == 0;
+}
+
+void lttng_uuid_copy(lttng_uuid dst, const lttng_uuid src)
+{
+	memcpy(dst, src, LTTNG_UUID_LEN);
+}
+
+/*
+ * Generate a random UUID according to RFC4122, section 4.4.
+ */
+int lttng_uuid_generate(lttng_uuid uuid_out)
+{
+	int i, ret = 0;
+	time_t epoc;
+
+	if (uuid_out == NULL) {
+		ret = -1;
+		goto end;
+	}
+
+	if (!lttng_uuid_is_init) {
+		/*
+		 * We don't need cryptographic quality randomness to
+		 * generate UUIDs, seed rand with the epoc.
+		 */
+		epoc = time(NULL);
+
+		if (epoc == (time_t) -1) {
+			ret = -1;
+			goto end;
+		}
+		srand(epoc);
+
+		lttng_uuid_is_init = true;
+	}
+
+	/*
+	 * Generate 16 bytes of random bits.
+	 */
+	for (i = 0; i < LTTNG_UUID_LEN; i++) {
+		uuid_out[i] = (uint8_t) rand();
+	}
+
+	/*
+	 * Set the two most significant bits (bits 6 and 7) of the
+	 * clock_seq_hi_and_reserved to zero and one, respectively.
+	 */
+	uuid_out[8] &= ~(1 << 6);
+	uuid_out[8] |= (1 << 7);
+
+	/*
+	 * Set the four most significant bits (bits 12 through 15) of the
+	 * time_hi_and_version field to the 4-bit version number from
+	 * Section 4.1.3.
+	 */
+	uuid_out[6] &= 0x0f;
+	uuid_out[6] |= (LTTNG_UUID_VER << 4);
+
+end:
+	return ret;
+}
diff --git a/src/common/compat/uuid.h b/src/common/uuid.h
similarity index 58%
rename from src/common/compat/uuid.h
rename to src/common/uuid.h
index a283ea42a..c89c861d9 100644
--- a/src/common/compat/uuid.h
+++ b/src/common/uuid.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011  Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -25,56 +25,42 @@
 
 #include <common/macros.h>
 #include <stdbool.h>
+#include <stdint.h>
+#include <inttypes.h>
 
 /*
  * Includes final \0.
  */
-#define UUID_STR_LEN		37
-#define UUID_LEN		16
+#define LTTNG_UUID_STR_LEN	37
+#define LTTNG_UUID_LEN		16
+#define LTTNG_UUID_VER		4
 
-typedef unsigned char lttng_uuid[UUID_LEN];
+#define LTTNG_UUID_FMT \
+	"%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "-%02" SCNx8 \
+	"%02" SCNx8 "-%02" SCNx8 "%02" SCNx8 "-%02" SCNx8 "%02" SCNx8 \
+	"-%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 "%02" SCNx8 \
+	"%02" SCNx8
 
-#ifdef LTTNG_HAVE_LIBUUID
-#include <uuid/uuid.h>
+#define LTTNG_UUID_FMT_VALUES(uuid) \
+	(uuid)[0], (uuid)[1], (uuid)[2], (uuid)[3], (uuid)[4], (uuid)[5], \
+	(uuid)[6], (uuid)[7], (uuid)[8], (uuid)[9], (uuid)[10], (uuid)[11], \
+	(uuid)[12], (uuid)[13], (uuid)[14], (uuid)[15]
 
-/*
- * uuid_out is of len UUID_LEN.
- */
-static inline
-int lttng_uuid_generate(lttng_uuid uuid_out)
-{
-	uuid_generate(uuid_out);
-	return 0;
-}
+#define LTTNG_UUID_SCAN_VALUES(uuid) \
+	&(uuid)[0], &(uuid)[1], &(uuid)[2], &(uuid)[3], &(uuid)[4], &(uuid)[5], \
+	&(uuid)[6], &(uuid)[7], &(uuid)[8], &(uuid)[9], &(uuid)[10], &(uuid)[11], \
+	&(uuid)[12], &(uuid)[13], &(uuid)[14], &(uuid)[15]
 
-#elif defined(LTTNG_HAVE_LIBC_UUID)
-#include <uuid.h>
-#include <stdint.h>
-
-/*
- * uuid_out is of len UUID_LEN.
- */
-static inline
-int lttng_uuid_generate(lttng_uuid uuid_out)
-{
-	uint32_t status;
+typedef uint8_t lttng_uuid[LTTNG_UUID_LEN];
 
-	uuid_create((uuid_t *) uuid_out, &status);
-	if (status == uuid_s_ok)
-		return 0;
-	else
-		return -1;
-}
-
-#else
-#error "LTTng-Tools needs to have a UUID generator configured."
-#endif
+LTTNG_HIDDEN
+int lttng_uuid_from_str(const char *str_in, lttng_uuid uuid_out);
 
 /*
  * Convert a UUID to a human-readable, NULL-terminated, string of the form
  * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
  *
- * Assumes uuid_str is at least UUID_STR_LEN byte long.
+ * Assumes uuid_str is at least LTTNG_UUID_STR_LEN byte long.
  */
 LTTNG_HIDDEN
 void lttng_uuid_to_str(const lttng_uuid uuid, char *uuid_str);
@@ -88,4 +74,10 @@ bool lttng_uuid_is_nil(const lttng_uuid uuid);
 LTTNG_HIDDEN
 void lttng_uuid_copy(lttng_uuid dst, const lttng_uuid src);
 
+/*
+ * Generate a random UUID according to RFC4122, section 4.4.
+ */
+LTTNG_HIDDEN
+int lttng_uuid_generate(lttng_uuid uuid_out);
+
 #endif /* LTTNG_UUID_H */
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index dd83bc636..b2f058e1b 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -16,6 +16,7 @@ TESTS = test_kernel_data \
 	test_string_utils \
 	test_notification \
 	test_directory_handle \
+	test_uuid \
 	ini_config/test_ini_config
 
 LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la
@@ -28,7 +29,7 @@ LIBRELAYD=$(top_builddir)/src/common/relayd/librelayd.la
 LIBLTTNG_CTL=$(top_builddir)/src/lib/lttng-ctl/liblttng-ctl.la
 
 # Define test programs
-noinst_PROGRAMS = test_uri test_session test_kernel_data \
+noinst_PROGRAMS = test_uri test_session test_kernel_data test_uuid \
                   test_utils_parse_size_suffix test_utils_parse_time_suffix \
                   test_utils_expand_path test_utils_compat_poll \
                   test_string_utils test_notification test_directory_handle
@@ -170,3 +171,6 @@ test_string_utils_LDADD = $(LIBTAP) $(LIBCOMMON) $(LIBSTRINGUTILS) $(DL_LIBS)
 # Notification api
 test_notification_SOURCES = test_notification.c
 test_notification_LDADD = $(LIBTAP) $(LIBLTTNG_CTL) $(DL_LIBS)
+
+test_uuid_SOURCES = test_uuid.c
+test_uuid_LDADD = $(LIBTAP) $(LIBCOMMON)
diff --git a/tests/unit/test_uuid.c b/tests/unit/test_uuid.c
new file mode 100644
index 000000000..c75727bd4
--- /dev/null
+++ b/tests/unit/test_uuid.c
@@ -0,0 +1,193 @@
+/*
+ * test_uuid.c
+ *
+ * Copyright 2019 Michael Jeanson <mjeanson at efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include <tap/tap.h>
+
+#include "common/uuid.h"
+
+#define NR_TESTS 21
+
+static const char valid_str_1[] = "3d260c88-75ea-47b8-a7e2-d6077c0378d9";
+static const char valid_str_2[] = "611cf3a6-a68b-4515-834f-208bc2762592";
+static const char valid_str_3[] = "1b4855cc-96de-4ae8-abe3-86449c2a43c4";
+static const char valid_str_4[] = "8ADED5B9-ACD2-439F-A60C-897403AA2AB4";
+static const char valid_str_5[] = "f109e0a2-C619-4d18-b760-20EA20E0F69A";
+
+static lttng_uuid valid_uuid_1 = {
+	0x3d, 0x26, 0x0c, 0x88, 0x75, 0xea, 0x47, 0xb8,
+	0xa7, 0xe2, 0xd6, 0x07, 0x7c, 0x03, 0x78, 0xd9
+};
+static lttng_uuid valid_uuid_2 = {
+	0x61, 0x1c, 0xf3, 0xa6, 0xa6, 0x8b, 0x45, 0x15,
+	0x83, 0x4f, 0x20, 0x8b, 0xc2, 0x76, 0x25, 0x92
+};
+static lttng_uuid valid_uuid_3 = {
+	0x1b, 0x48, 0x55, 0xcc, 0x96, 0xde, 0x4a, 0xe8,
+	0xab, 0xe3, 0x86, 0x44, 0x9c, 0x2a, 0x43, 0xc4
+};
+
+static const char invalid_str_1[] = "1b485!cc-96de-4XX8-abe3-86449c2a43?4";
+static const char invalid_str_2[] = "c2e6eddb&3955&4006&be3a&70bb63bd5f25";
+static const char invalid_str_3[] = "81b1cb88-ff42-45b9-ba4d-964088ee45";
+static const char invalid_str_4[] = "2d-6c6d756574-470e-9142-a4e6ad03f143";
+static const char invalid_str_5[] = "4542ad19-9e4f-4931-8261-2101c3e089ae7";
+static const char invalid_str_6[] = "XX0123";
+
+static
+void run_test_lttng_uuid_from_str(void)
+{
+	int ret;
+	lttng_uuid uuid1;
+
+	/*
+	 * Parse valid UUID strings, expect success.
+	 */
+	ret = lttng_uuid_from_str(valid_str_1, uuid1);
+	ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_1);
+
+	ret = lttng_uuid_from_str(valid_str_2, uuid1);
+	ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_2);
+
+	ret = lttng_uuid_from_str(valid_str_3, uuid1);
+	ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_3);
+
+	ret = lttng_uuid_from_str(valid_str_4, uuid1);
+	ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_4);
+
+	ret = lttng_uuid_from_str(valid_str_5, uuid1);
+	ok(ret == 0, "lttng_uuid_from_str - Parse valid string '%s', expect success", valid_str_5);
+
+	/*
+	 * Parse invalid UUID strings, expect failure.
+	 */
+	ret = lttng_uuid_from_str(invalid_str_1, uuid1);
+	ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_1);
+
+	ret = lttng_uuid_from_str(invalid_str_2, uuid1);
+	ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_2);
+
+	ret = lttng_uuid_from_str(invalid_str_3, uuid1);
+	ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_3);
+
+	ret = lttng_uuid_from_str(invalid_str_4, uuid1);
+	ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_4);
+
+	ret = lttng_uuid_from_str(invalid_str_5, uuid1);
+	ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_5);
+
+	ret = lttng_uuid_from_str(invalid_str_6, uuid1);
+	ok(ret != 0, "lttng_uuid_from_str - Parse invalid string '%s', expect failure", invalid_str_6);
+}
+
+static
+void run_test_lttng_uuid_to_str(void)
+{
+	char uuid_str[LTTNG_UUID_STR_LEN];
+
+	lttng_uuid_to_str(valid_uuid_1, uuid_str);
+	ok(strcmp(uuid_str, valid_str_1) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_1);
+
+	lttng_uuid_to_str(valid_uuid_2, uuid_str);
+	ok(strcmp(uuid_str, valid_str_2) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_2);
+
+	lttng_uuid_to_str(valid_uuid_3, uuid_str);
+	ok(strcmp(uuid_str, valid_str_3) == 0, "lttng_uuid_to_str - Convert UUID '%s' to string, expect success", valid_str_3);
+}
+
+static
+void run_test_lttng_uuid_is_equal(void)
+{
+	int ret;
+	lttng_uuid uuid1, uuid2;
+
+	lttng_uuid_from_str(valid_str_1, uuid1);
+	lttng_uuid_from_str(valid_str_1, uuid2);
+	ret = lttng_uuid_is_equal(uuid1, uuid2);
+	ok(ret == true, "lttng_uuid_is_equal - Compare same UUID, expect success");
+
+	lttng_uuid_from_str(valid_str_2, uuid2);
+	ret = lttng_uuid_is_equal(uuid1, uuid2);
+	ok(ret == false, "lttng_uuid_is_equal - Compare different UUID, expect failure");
+}
+
+static
+void run_test_lttng_uuid_copy(void)
+{
+	int ret;
+	lttng_uuid uuid1;
+
+	lttng_uuid_copy(uuid1, valid_uuid_1);
+	ret = lttng_uuid_is_equal(uuid1, valid_uuid_1);
+
+	ok(ret == true, "lttng_uuid_copy - Compare copied UUID with source, expect success");
+}
+
+static
+void run_test_lttng_uuid_generate(void)
+{
+	int ret;
+	lttng_uuid uuid1, uuid2;
+
+	lttng_uuid_generate(uuid1);
+	lttng_uuid_generate(uuid2);
+
+	ok(lttng_uuid_is_equal(uuid1, uuid2) == false, "lttng_uuid_generate - Generated UUIDs are different");
+
+	/*
+	 * Set the two most significant bits (bits 6 and 7) of the
+	 * clock_seq_hi_and_reserved to zero and one, respectively.
+	 */
+	ret = uuid1[8] & (1 << 6);
+	ok(ret == 0, "lttng_uuid_generate - bit 6 of clock_seq_hi_and_reserved is set to zero");
+
+	ret = uuid1[8] & (1 << 7);
+	ok(ret != 0, "lttng_uuid_generate - bit 7 of clock_seq_hi_and_reserved is set to one");
+
+	/*
+	 * Set the four most significant bits (bits 12 through 15) of the
+	 * time_hi_and_version field to the 4-bit version number from
+	 * Section 4.1.3.
+	 */
+	ret = uuid1[6] >> 4;
+	ok(ret == LTTNG_UUID_VER, "lttng_uuid_generate - Generated UUID version check");
+}
+
+static
+void run_test(void)
+{
+	plan_tests(NR_TESTS);
+
+	run_test_lttng_uuid_from_str();
+	run_test_lttng_uuid_to_str();
+	run_test_lttng_uuid_is_equal();
+	run_test_lttng_uuid_copy();
+	run_test_lttng_uuid_generate();
+}
+
+int main(int argc, char **argv)
+{
+	/* Run tap-formated tests */
+	run_test();
+
+	return exit_status();
+}
-- 
2.17.1



More information about the lttng-dev mailing list