From: Michael Jeanson Date: Wed, 23 Oct 2019 20:07:37 +0000 (-0400) Subject: Replace libuuid with internal implementation X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=commitdiff_plain;h=c70636a7342f34e3be68fcf411cf3e3718b8e73f Replace libuuid with internal implementation 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 Change-Id: I744e3cf65d6a22d0acf7a9943c10943ba64e8468 Signed-off-by: Jérémie Galarneau --- diff --git a/.gitignore b/.gitignore index e5b639ada..5cd2d2b39 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 /tests/unit/test_relayd_backward_compat_group_by_session diff --git a/configure.ac b/configure.ac index 7517dd62e..ec5d72ec4 100644 --- a/configure.ac +++ b/configure.ac @@ -444,48 +444,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 -#include +#include 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 6e5b612f2..b3983b163 100644 --- a/src/bin/lttng-relayd/main.c +++ b/src/bin/lttng-relayd/main.c @@ -2332,7 +2332,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 @@ -2532,7 +2532,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, @@ -2638,7 +2638,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 241a3c23f..8f61e715f 100644 --- a/src/bin/lttng-relayd/session.c +++ b/src/bin/lttng-relayd/session.c @@ -19,9 +19,10 @@ #define _LGPL_SOURCE #include -#include +#include #include #include +#include #include #include @@ -328,7 +329,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 8d60ed95f..3f3ac02af 100644 --- a/src/bin/lttng-relayd/session.h +++ b/src/bin/lttng-relayd/session.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include 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 +#include #include #include 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 +#include 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 #include #include -#include +#include #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 -#include +#include #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 #include -#include +#include /* 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 #include -#include +#include #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 e6628f8a4..dc69f179a 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 - * - * 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 -#include -#include -#include - -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/compat/uuid.h b/src/common/compat/uuid.h deleted file mode 100644 index a283ea42a..000000000 --- a/src/common/compat/uuid.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2011 Mathieu Desnoyers - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef LTTNG_UUID_H -#define LTTNG_UUID_H - -#include -#include - -/* - * Includes final \0. - */ -#define UUID_STR_LEN 37 -#define UUID_LEN 16 - -typedef unsigned char lttng_uuid[UUID_LEN]; - -#ifdef LTTNG_HAVE_LIBUUID -#include - -/* - * uuid_out is of len UUID_LEN. - */ -static inline -int lttng_uuid_generate(lttng_uuid uuid_out) -{ - uuid_generate(uuid_out); - return 0; -} - -#elif defined(LTTNG_HAVE_LIBC_UUID) -#include -#include - -/* - * uuid_out is of len UUID_LEN. - */ -static inline -int lttng_uuid_generate(lttng_uuid uuid_out) -{ - uint32_t status; - - 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 - -/* - * 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. - */ -LTTNG_HIDDEN -void lttng_uuid_to_str(const lttng_uuid uuid, char *uuid_str); - -LTTNG_HIDDEN -bool lttng_uuid_is_equal(const lttng_uuid a, const lttng_uuid b); - -LTTNG_HIDDEN -bool lttng_uuid_is_nil(const lttng_uuid uuid); - -LTTNG_HIDDEN -void lttng_uuid_copy(lttng_uuid dst, const lttng_uuid src); - -#endif /* LTTNG_UUID_H */ diff --git a/src/common/consumer/consumer.c b/src/common/consumer/consumer.c index d903c54c2..e99dc54ed 100644 --- a/src/common/consumer/consumer.c +++ b/src/common/consumer/consumer.c @@ -4355,7 +4355,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 #include -#include +#include #include #include #include @@ -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 #include #include -#include +#include #include #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 #include #include -#include +#include #include #include @@ -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..68fddc0a2 --- /dev/null +++ b/src/common/uuid.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2018 Jérémie Galarneau + * Copyright (C) 2019 Michael Jeanson + * + * 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 +#include +#include +#include +#include +#include + +#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; + + 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 epoch. + */ + const time_t epoch = time(NULL); + + if (epoch == (time_t) -1) { + ret = -1; + goto end; + } + srand(epoch); + + 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/uuid.h b/src/common/uuid.h new file mode 100644 index 000000000..c89c861d9 --- /dev/null +++ b/src/common/uuid.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2011 Mathieu Desnoyers + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef LTTNG_UUID_H +#define LTTNG_UUID_H + +#include +#include +#include +#include + +/* + * Includes final \0. + */ +#define LTTNG_UUID_STR_LEN 37 +#define LTTNG_UUID_LEN 16 +#define LTTNG_UUID_VER 4 + +#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 + +#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] + +#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] + +typedef uint8_t lttng_uuid[LTTNG_UUID_LEN]; + +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 LTTNG_UUID_STR_LEN byte long. + */ +LTTNG_HIDDEN +void lttng_uuid_to_str(const lttng_uuid uuid, char *uuid_str); + +LTTNG_HIDDEN +bool lttng_uuid_is_equal(const lttng_uuid a, const lttng_uuid b); + +LTTNG_HIDDEN +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 5410e730e..b13481f4b 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -18,7 +18,8 @@ TESTS = test_kernel_data \ test_directory_handle \ test_relayd_backward_compat_group_by_session \ ini_config/test_ini_config \ - test_fd_tracker + test_fd_tracker \ + test_uuid LIBTAP=$(top_builddir)/tests/utils/tap/libtap.la @@ -36,7 +37,7 @@ noinst_PROGRAMS = test_uri test_session test_kernel_data \ test_utils_expand_path test_utils_compat_poll \ test_string_utils test_notification test_directory_handle \ test_relayd_backward_compat_group_by_session \ - test_fd_tracker + test_fd_tracker test_uuid if HAVE_LIBLTTNG_UST_CTL noinst_PROGRAMS += test_ust_data @@ -186,3 +187,7 @@ test_relayd_backward_compat_group_by_session_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_s # fd tracker unit test test_fd_tracker_SOURCES = test_fd_tracker.c test_fd_tracker_LDADD = $(LIBTAP) $(LIBFDTRACKER) $(DL_LIBS) -lurcu $(LIBCOMMON) $(LIBHASHTABLE) + +# uuid unit test +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 + * + * 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 +#include +#include + +#include + +#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(); +}