]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libuuid: add support for RFC9562 UUIDs
authorThomas Weißschuh <thomas@t-8ch.de>
Mon, 12 Feb 2024 17:44:41 +0000 (18:44 +0100)
committerThomas Weißschuh <thomas@t-8ch.de>
Fri, 10 May 2024 08:36:14 +0000 (10:36 +0200)
Signed-off-by: Thomas Weißschuh <thomas@t-8ch.de>
libuuid/src/gen_uuid.c
libuuid/src/libuuid.sym
libuuid/src/uuid.h
libuuid/src/uuid_time.c

index 59e8c23f01a8afe8fcbe4c0e2f9eb3f2189d04a8..aa353e443621036f9560c170dbba894314e1c341 100644 (file)
@@ -89,6 +89,7 @@
 #include "c.h"
 #include "md5.h"
 #include "sha1.h"
+#include "timeutils.h"
 
 #ifdef HAVE_TLS
 #define THREAD_LOCAL static __thread
@@ -661,6 +662,44 @@ int uuid_generate_time_safe(uuid_t out)
        return uuid_generate_time_generic(out);
 }
 
+void uuid_generate_time_v6(uuid_t out)
+{
+       struct uuid uu = {};
+       uint64_t clock_reg;
+
+       clock_reg = get_clock_counter();
+
+       uu.time_low = clock_reg >> 28;
+       uu.time_mid = clock_reg >> 12;
+       uu.time_hi_and_version = (clock_reg & 0x0FFF) | (6 << 12);
+
+       ul_random_get_bytes(&uu.clock_seq, 8);
+       uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
+
+       uuid_pack(&uu, out);
+}
+
+// FIXME variable additional information
+void uuid_generate_time_v7(uuid_t out)
+{
+       struct timeval tv;
+       struct uuid uu;
+       uint64_t ms;
+
+       gettimeofday(&tv, NULL);
+
+       ms = tv.tv_sec * MSEC_PER_SEC + tv.tv_usec / USEC_PER_MSEC;
+
+       uu.time_low = ms >> 16;
+       uu.time_mid = ms;
+
+       ul_random_get_bytes(&uu.time_hi_and_version, 10);
+       uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | (7 << 12);
+       uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
+
+       uuid_pack(&uu, out);
+}
+
 
 int __uuid_generate_random(uuid_t out, int *num)
 {
index 0f67ede0d5228f361ca3d7133b6c8a3dee4be54d..4c4b4eba2e608b3cfa035d6cbe46d70dcc26371d 100644 (file)
@@ -60,6 +60,15 @@ global:
         uuid_time64; /* only on 32bit architectures with 64bit time_t */
 } UUID_2.36;
 
+/*
+ * version(s) since util-linux.2.41
+ */
+UUID_2.41 {
+global:
+       uuid_generate_time_v6;
+       uuid_generate_time_v7;
+} UUID_2.40;
+
 
 
 /*
index 2e3642cd63731587dead817a4037dd08c4a15b32..2e0f70aa9cfbfe0e260cf9b449080f01077ab987 100644 (file)
@@ -59,6 +59,9 @@ typedef unsigned char uuid_t[16];
 #define UUID_TYPE_DCE_MD5    3
 #define UUID_TYPE_DCE_RANDOM 4
 #define UUID_TYPE_DCE_SHA1   5
+#define UUID_TYPE_DCE_TIME_V6    6
+#define UUID_TYPE_DCE_TIME_V7    7
+#define UUID_TYPE_DCE_VENDOR     8
 
 #define UUID_TYPE_SHIFT      4
 #define UUID_TYPE_MASK     0xf
@@ -92,6 +95,8 @@ extern void uuid_generate(uuid_t out);
 extern void uuid_generate_random(uuid_t out);
 extern void uuid_generate_time(uuid_t out);
 extern int uuid_generate_time_safe(uuid_t out);
+extern void uuid_generate_time_v6(uuid_t out);
+extern void uuid_generate_time_v7(uuid_t out);
 
 extern void uuid_generate_md5(uuid_t out, const uuid_t ns, const char *name, size_t len);
 extern void uuid_generate_sha1(uuid_t out, const uuid_t ns, const char *name, size_t len);
index 9b415b3ee73a20788d372673f5425f970b6ac879..d52c2f3070ffeeb663aaaaaca36eee9dba5d939f 100644 (file)
 #include <time.h>
 
 #include "uuidP.h"
+#include "timeutils.h"
 
 #undef uuid_time
 
 /* prototype to make compiler happy */
 time_t __uuid_time(const uuid_t uu, struct timeval *ret_tv);
 
+static uint64_t gregorian_to_unix(uint64_t ts)
+{
+       return ts - ((((uint64_t) 0x01B21DD2) << 32) + 0x13814000);
+}
+
+static void uuid_time_v1(const struct uuid *uuid, struct timeval *tv)
+{
+       uint32_t high;
+       uint64_t clock_reg;
+
+       high = uuid->time_mid | ((uuid->time_hi_and_version & 0xFFF) << 16);
+       clock_reg = uuid->time_low | ((uint64_t) high << 32);
+
+       clock_reg = gregorian_to_unix(clock_reg);
+       tv->tv_sec = clock_reg / 10000000;
+       tv->tv_usec = (clock_reg % 10000000) / 10;
+}
+
+static void uuid_time_v6(const struct uuid *uuid, struct timeval *tv)
+{
+       uint64_t clock_reg;
+
+       clock_reg = uuid->time_low;
+       clock_reg <<= 16;
+       clock_reg |= uuid->time_mid;
+       clock_reg <<= 12;
+       clock_reg |= uuid->time_hi_and_version & 0xFFF;
+
+       clock_reg = gregorian_to_unix(clock_reg);
+       tv->tv_sec = clock_reg / 10000000;
+       tv->tv_usec = (clock_reg % 10000000) / 10;
+}
+
+static void uuid_time_v7(const struct uuid *uuid, struct timeval *tv)
+{
+       uint64_t clock_reg;
+
+       clock_reg = uuid->time_low;
+       clock_reg <<= 16;
+       clock_reg |= uuid->time_mid;
+
+       tv->tv_sec = clock_reg / MSEC_PER_SEC;
+       tv->tv_usec = (clock_reg % MSEC_PER_SEC) * USEC_PER_MSEC;
+}
+
+static uint8_t __uuid_type(const struct uuid *uuid)
+{
+       return (uuid->time_hi_and_version >> 12) & 0xF;
+}
 
 /* this function could be 32bit time_t and 32bit timeval or 64bit,
    depending on compiler flags and architecture. */
 time_t __uuid_time(const uuid_t uu, struct timeval *ret_tv)
 {
-       struct timeval          tv;
-       struct uuid             uuid;
-       uint32_t                high;
-       uint64_t                clock_reg;
+       struct timeval  tv;
+       struct uuid     uuid;
+       uint8_t         type;
 
        uuid_unpack(uu, &uuid);
+       type = __uuid_type(&uuid);
 
-       high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16);
-       clock_reg = uuid.time_low | ((uint64_t) high << 32);
-
-       clock_reg -= (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
-       tv.tv_sec = clock_reg / 10000000;
-       tv.tv_usec = (clock_reg % 10000000) / 10;
+       switch (type) {
+       case UUID_TYPE_DCE_TIME:
+               uuid_time_v1(&uuid, &tv);
+               break;
+       case UUID_TYPE_DCE_TIME_V6:
+               uuid_time_v6(&uuid, &tv);
+               break;
+       case UUID_TYPE_DCE_TIME_V7:
+               uuid_time_v7(&uuid, &tv);
+               break;
+       default:
+               tv.tv_sec = -1;
+               tv.tv_usec = -1;
+               break;
+       }
 
        if (ret_tv)
                *ret_tv = tv;
@@ -88,7 +147,7 @@ extern time_t uuid_time64(const uuid_t uu, struct timeval *ret_tv) __attribute__
 #else
 extern time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) __attribute__((weak, alias("__uuid_time")));
 #endif
-     
+
 #if defined(__USE_TIME_BITS64) && defined(__GLIBC__)
 struct timeval32
 {
@@ -104,7 +163,7 @@ static inline int
 in_time32_t_range(time_t t)
 {
        int32_t         s;
+
        s = t;
 
        return s == t;
@@ -137,7 +196,7 @@ int uuid_type(const uuid_t uu)
        struct uuid             uuid;
 
        uuid_unpack(uu, &uuid);
-       return ((uuid.time_hi_and_version >> 12) & 0xF);
+       return __uuid_type(&uuid);
 }
 
 int uuid_variant(const uuid_t uu)