#include "c.h"
#include "md5.h"
#include "sha1.h"
+#include "timeutils.h"
#ifdef HAVE_TLS
#define THREAD_LOCAL static __thread
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)
{
#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
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);
#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;
#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
{
in_time32_t_range(time_t t)
{
int32_t s;
-
+
s = t;
return s == t;
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)