X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblutil%2Fuuid.c;h=a466090d9d37e30de1b3f2ed83372eb278ae4426;hb=198879bd5f1baa09e5dc7a951db980a932cd5db5;hp=d85f6f139ab2e5e04efb9b57f4ae5aa54a8b9f29;hpb=93046479aeb4f10075afdbadf1c7e8c0fb327372;p=openldap
diff --git a/libraries/liblutil/uuid.c b/libraries/liblutil/uuid.c
index d85f6f139a..a466090d9d 100644
--- a/libraries/liblutil/uuid.c
+++ b/libraries/liblutil/uuid.c
@@ -1,14 +1,29 @@
-/*
- * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
- * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
+/* uuid.c -- Universally Unique Identifier routines */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software .
+ *
+ * Copyright 2000-2009 The OpenLDAP Foundation.
+ * Portions Copyright 2000-2003 Kurt D. Zeilenga.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * .
*/
-/* Portions
- * Copyright 2000, John E. Schimmel, All rights reserved.
+/* Portions Copyright 2000, John E. Schimmel, All rights reserved.
* This software is not subject to any license of Mirapoint, Inc.
*
* This is free software; you can redistribute and use it
* under the same terms as OpenLDAP itself.
*/
+/* This work was initially developed by John E. Schimmel and adapted
+ * for inclusion in OpenLDAP Software by Kurt D. Zeilenga.
+ */
+
/*
* Sorry this file is so scary, but it needs to run on a wide range of
* platforms. The only exported routine is lutil_uuidstr() which is all
@@ -17,22 +32,22 @@
*/
#include "portable.h"
+#include
#include
#include
#include
+#include /* get memcmp() */
#ifdef HAVE_UUID_TO_STR
# include
+#elif defined( HAVE_UUID_GENERATE )
+# include
#elif defined( _WIN32 )
# include
#else
# include
# include
-
- /* 100 usec intervals from 10/10/1582 to 1/1/1970 */
-# define UUID_TPLUS 0x01B21DD2138140LL
-
# ifdef HAVE_SYS_SYSCTL_H
# include
# include
@@ -43,7 +58,7 @@
#include
/* not needed for Windows */
-#if !defined(HAVE_UUID_TO_STR) && !defined(_WIN32)
+#if !defined(HAVE_UUID_TO_STR) && !defined(HAVE_UUID_GENERATE) && !defined(_WIN32)
static unsigned char *
lutil_eaddr( void )
{
@@ -156,14 +171,90 @@ lutil_eaddr( void )
if (memcmp(eaddr, zero, sizeof(eaddr)) == 0) {
/* XXX - who knows? */
lutil_entropy( eaddr, sizeof(eaddr) );
- eaddr[0] |= 0x80; /* turn it into a multicast address */
+ eaddr[0] |= 0x01; /* turn it into a multicast address */
}
return eaddr;
#endif
}
+
+#if (ULONG_MAX >> 31 >> 31) > 1 || defined HAVE_LONG_LONG
+
+#if (ULONG_MAX >> 31 >> 31) > 1
+ typedef unsigned long UI64;
+ /* 100 usec intervals from 10/10/1582 to 1/1/1970 */
+# define UUID_TPLUS 0x01B21DD2138140ul
+#else
+ typedef unsigned long long UI64;
+# define UUID_TPLUS 0x01B21DD2138140ull
#endif
+#define high32(i) ((unsigned long) ((i) >> 32))
+#define low32(i) ((unsigned long) (i) & 0xFFFFFFFFul)
+#define set_add64(res, i) ((res) += (i))
+#define set_add64l(res, i) ((res) += (i))
+#define mul64ll(i1, i2) ((UI64) (i1) * (i2))
+
+#else /* ! (ULONG_MAX >= 64 bits || HAVE_LONG_LONG) */
+
+typedef struct {
+ unsigned long high, low;
+} UI64;
+
+static const UI64 UUID_TPLUS = { 0x01B21Dul, 0xD2138140ul };
+
+#define high32(i) ((i).high)
+#define low32(i) ((i).low)
+
+/* res += ui64 */
+#define set_add64(res, ui64) \
+{ \
+ res.high += ui64.high; \
+ res.low = (res.low + ui64.low) & 0xFFFFFFFFul; \
+ if (res.low < ui64.low) res.high++; \
+}
+
+/* res += ul32 */
+#define set_add64l(res, ul32) \
+{ \
+ res.low = (res.low + ul32) & 0xFFFFFFFFul; \
+ if (res.low < ul32) res.high++; \
+}
+
+/* compute i1 * i2 */
+static UI64
+mul64ll(unsigned long i1, unsigned long i2)
+{
+ const unsigned int high1 = (i1 >> 16), low1 = (i1 & 0xffff);
+ const unsigned int high2 = (i2 >> 16), low2 = (i2 & 0xffff);
+
+ UI64 res;
+ unsigned long tmp;
+
+ res.high = (unsigned long) high1 * high2;
+ res.low = (unsigned long) low1 * low2;
+
+ tmp = (unsigned long) low1 * high2;
+ res.high += (tmp >> 16);
+ tmp = (tmp << 16) & 0xFFFFFFFFul;
+ res.low = (res.low + tmp) & 0xFFFFFFFFul;
+ if (res.low < tmp)
+ res.high++;
+
+ tmp = (unsigned long) low2 * high1;
+ res.high += (tmp >> 16);
+ tmp = (tmp << 16) & 0xFFFFFFFFul;
+ res.low = (res.low + tmp) & 0xFFFFFFFFul;
+ if (res.low < tmp)
+ res.high++;
+
+ return res;
+}
+
+#endif /* ULONG_MAX >= 64 bits || HAVE_LONG_LONG */
+
+#endif /* !HAVE_UUID_TO_STR && !HAVE_UUID_GENERATE && !_WIN32 */
+
/*
** All we really care about is an ISO UUID string. The format of a UUID is:
** field octet note
@@ -209,6 +300,13 @@ lutil_uuidstr( char *buf, size_t len )
return l;
+#elif defined( HAVE_UUID_GENERATE )
+ uuid_t uu;
+
+ uuid_generate( uu );
+ uuid_unparse_lower( uu, buf );
+ return strlen( buf );
+
#elif defined( _WIN32 )
UUID uuid;
unsigned char *uuidstr;
@@ -234,10 +332,11 @@ lutil_uuidstr( char *buf, size_t len )
#else
struct timeval tv;
- unsigned long long tl;
+ UI64 tl;
unsigned char *nl;
unsigned short t2, t3, s1;
- unsigned int t1;
+ unsigned long t1, tl_high;
+ unsigned int rc;
/*
* Theoretically we should delay if seq wraps within 100usec but for now
@@ -258,25 +357,70 @@ lutil_uuidstr( char *buf, size_t len )
tv.tv_usec = 0;
#endif
- tl = ( tv.tv_sec * 10000000LL ) + ( tv.tv_usec * 10LL ) + UUID_TPLUS;
+ tl = mul64ll(tv.tv_sec, 10000000UL);
+ set_add64l(tl, tv.tv_usec * 10UL);
+ set_add64(tl, UUID_TPLUS);
+
nl = lutil_eaddr();
- t1 = tl & 0xffffffff; /* time_low */
- t2 = ( tl >> 32 ) & 0xffff; /* time_mid */
- t3 = ( ( tl >> 48 ) & 0x0fff ) | 0x1000; /* time_hi_and_version */
+ t1 = low32(tl); /* time_low */
+ tl_high = high32(tl);
+ t2 = tl_high & 0xffff; /* time_mid */
+ t3 = ((tl_high >> 16) & 0x0fff) | 0x1000; /* time_hi_and_version */
s1 = ( ++seq & 0x1fff ) | 0x8000; /* clock_seq_and_reserved */
- t1 = snprintf( buf, len,
- "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
- t1, (unsigned) t2, (unsigned) t3, (unsigned) s1,
+ rc = snprintf( buf, len,
+ "%08lx-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ t1, (unsigned) t2, (unsigned) t3, (unsigned) s1,
(unsigned) nl[0], (unsigned) nl[1],
(unsigned) nl[2], (unsigned) nl[3],
(unsigned) nl[4], (unsigned) nl[5] );
- return (0 < t1 && t1 < len) ? t1 : 0;
+ return rc < len ? rc : 0;
#endif
}
+int
+lutil_uuidstr_from_normalized(
+ char *uuid,
+ size_t uuidlen,
+ char *buf,
+ size_t buflen )
+{
+ unsigned char nibble;
+ int i, d = 0;
+
+ assert( uuid != NULL );
+ assert( buf != NULL );
+
+ if ( uuidlen != 16 ) return -1;
+ if ( buflen < 36 ) return -1;
+
+ for ( i = 0; i < 16; i++ ) {
+ if ( i == 4 || i == 6 || i == 8 || i == 10 ) {
+ buf[(i<<1)+d] = '-';
+ d += 1;
+ }
+
+ nibble = (uuid[i] >> 4) & 0xF;
+ if ( nibble < 10 ) {
+ buf[(i<<1)+d] = nibble + '0';
+ } else {
+ buf[(i<<1)+d] = nibble - 10 + 'a';
+ }
+
+ nibble = (uuid[i]) & 0xF;
+ if ( nibble < 10 ) {
+ buf[(i<<1)+d+1] = nibble + '0';
+ } else {
+ buf[(i<<1)+d+1] = nibble - 10 + 'a';
+ }
+ }
+
+ if ( buflen > 36 ) buf[36] = '\0';
+ return 36;
+}
+
#ifdef TEST
int
main(int argc, char **argv)