X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libraries%2Fliblutil%2Fuuid.c;h=a466090d9d37e30de1b3f2ed83372eb278ae4426;hb=198879bd5f1baa09e5dc7a951db980a932cd5db5;hp=9800cc9cad7c612093aa2763684d3623fed05225;hpb=268ee5ff4a9a596648089be518c96cfe34495446;p=openldap diff --git a/libraries/liblutil/uuid.c b/libraries/liblutil/uuid.c index 9800cc9cad..a466090d9d 100644 --- a/libraries/liblutil/uuid.c +++ b/libraries/liblutil/uuid.c @@ -1,15 +1,28 @@ -/* - * Copyright 1998-2000 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. */ -/* Adapted for incorporatation into OpenLDAP by Kurt Zeilenga */ +/* 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 @@ -19,27 +32,33 @@ */ #include "portable.h" +#include #include #include -#ifdef HAVE_SYS_UUID_H +#include +#include /* get memcmp() */ + +#ifdef HAVE_UUID_TO_STR # include +#elif defined( HAVE_UUID_GENERATE ) +# include +#elif defined( _WIN32 ) +# include #else # include -# include -# include -# include -# include +# include # ifdef HAVE_SYS_SYSCTL_H +# include # include # include # endif #endif -/* 100 usec intervals from 10/10/1582 to 1/1/1970 */ -#define UUID_TPLUS 0x01B21DD2138140LL +#include -#ifndef HAVE_SYS_UUID_H +/* not needed for Windows */ +#if !defined(HAVE_UUID_TO_STR) && !defined(HAVE_UUID_GENERATE) && !defined(_WIN32) static unsigned char * lutil_eaddr( void ) { @@ -82,7 +101,7 @@ lutil_eaddr( void ) sdl = (struct sockaddr_dl *)(ifm + 1); if ( sdl->sdl_family != AF_LINK || sdl->sdl_alen == 6 ) { - memcpy(eaddr, + AC_MEMCPY(eaddr, (unsigned char *)sdl->sdl_data + sdl->sdl_nlen, sizeof(eaddr)); free(buf); @@ -93,7 +112,7 @@ lutil_eaddr( void ) free(buf); return NULL; -#elif defined (SIOCGIFADDR) +#elif defined( SIOCGIFADDR ) && defined( AFLINK ) char buf[sizeof(struct ifreq) * 32]; struct ifconf ifc; struct ifreq *ifr; @@ -139,7 +158,7 @@ lutil_eaddr( void ) sdl = (struct sockaddr_dl *)sa; if ( sdl->sdl_alen == 6 ) { - memcpy(eaddr, + AC_MEMCPY(eaddr, (unsigned char *)sdl->sdl_data + sdl->sdl_nlen, sizeof(eaddr)); return eaddr; @@ -152,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 mutlicast 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 @@ -175,13 +270,14 @@ lutil_eaddr( void ) ** We use DCE version one, and the DCE variant. Our unique identifier is ** the first ethernet address on the system. */ -int +size_t lutil_uuidstr( char *buf, size_t len ) { -#ifdef HAVE_SYS_UUID_H +#ifdef HAVE_UUID_TO_STR uuid_t uu = {0}; unsigned rc; char *s; + size_t l; uuid_create( &uu, &rc ); if ( rc != uuid_s_ok ) { @@ -192,7 +288,9 @@ lutil_uuidstr( char *buf, size_t len ) if ( rc != uuid_s_ok ) { return 0; } - if ( strlen( s ) >= len ) { + + l = strlen( s ); + if ( l >= len ) { free( s ); return 0; } @@ -200,14 +298,45 @@ lutil_uuidstr( char *buf, size_t len ) strncpy( buf, s, len ); free( s ); - return 1; + 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; + size_t uuidlen; + + if( UuidCreate( &uuid ) != RPC_S_OK ) { + return 0; + } + + if( UuidToString( &uuid, &uuidstr ) != RPC_S_OK ) { + return 0; + } + + uuidlen = strlen( uuidstr ); + if( uuidlen >= len ) { + return 0; + } + strncpy( buf, uuidstr, len ); + RpcStringFree( &uuidstr ); + + return uuidlen; + #else struct timeval tv; - unsigned long long tl; + UI64 tl; unsigned char *nl; - unsigned short t2, t3, s1, n1, n2, n3; - unsigned int t1; + unsigned short t2, t3, s1; + unsigned long t1, tl_high; + unsigned int rc; /* * Theoretically we should delay if seq wraps within 100usec but for now @@ -217,7 +346,7 @@ lutil_uuidstr( char *buf, size_t len ) static unsigned short seq; if (!inited) { - lutil_entropy( &seq, sizeof(seq) ); + lutil_entropy( (unsigned char *) &seq, sizeof(seq) ); inited++; } @@ -228,32 +357,77 @@ 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 (t1 < len) ? 1 : 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) { char buf1[8], buf2[64]; -#ifndef HAVE_SYS_UUID_H +#ifndef HAVE_UUID_TO_STR unsigned char *p = lutil_eaddr(); if( p ) {