OSSP CVS Repository

ossp - Check-in [4378]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 4378
Date: 2004-Jan-19 13:15:04 (local)
2004-Jan-19 12:15:04 (UTC)
User:rse
Branch:
Comment: o Include <string.h> in uuid.h because of size_t usage.

o INCOMPATIBILITY: Refactor the API and rename uuid_generate() to uuid_make() and use a "uuid_t" pointer for the namespace on UUID_VERSION3 generation. To allow access to the internal pre-defined namespace UUIDs, provide a new uuid_load() function. Because uuid_load() now also allows the loading of the "nil" UUID, remove uuid_nil() from the API. After this second refactoring the API is now the one we originally wished for the forthcoming version 1.0 of OSSP uuid.

Tickets:
Inspections:
Files:
ossp-pkg/uuid/ChangeLog      1.28 -> 1.29     18 inserted, 4 deleted
ossp-pkg/uuid/uuid.c      added-> 1.41
ossp-pkg/uuid/uuid.h      1.14 -> 1.15     5 inserted, 2 deleted
ossp-pkg/uuid/uuid.pod      1.11 -> 1.12     41 inserted, 18 deleted
ossp-pkg/uuid/uuid_cli.c      1.12 -> 1.13     23 inserted, 12 deleted

ossp-pkg/uuid/ChangeLog 1.28 -> 1.29

--- ChangeLog    2004/01/18 20:19:23     1.28
+++ ChangeLog    2004/01/19 12:15:04     1.29
@@ -13,14 +13,28 @@
 
   Changes between 0.9.3 and 0.9.4 (16-Jan-2004 to xx-Jan-2004)
 
+   o Include <string.h> in uuid.h because of size_t usage.
+     [Ralf S. Engelschall]
+
+   o INCOMPATIBILITY: Refactor the API and rename uuid_generate()
+     to uuid_make() and use a "uuid_t" pointer for the namespace
+     on UUID_VERSION3 generation. To allow access to the internal
+     pre-defined namespace UUIDs, provide a new uuid_load() function.
+     Because uuid_load() now also allows the loading of the "nil" UUID,
+     remove uuid_nil() from the API. After this second refactoring the
+     API is now the one we originally wished for the forthcoming version
+     1.0 of OSSP uuid.
+     [Ralf S. Engelschall]
+
    o Add version support to API via UUID_VERSION (compile-time)
      and uuid_version() (link-time).
      [Ralf S. Engelschall]
 
-   o Refactor the API by merging uuid_{unpack,pack,parse,format,dump}()
-     functions into unified uuid_{import,export}() functions. This
-     allows us to easily add support for other formats (e.g. XML) in the
-     future without having the change the API in principle.
+   o INCOMPATIBILITY: Refactor the API by merging
+     uuid_{unpack,pack,parse,format,dump}() functions into unified
+     uuid_{import,export}() functions. This allows us to easily add
+     support for other formats (e.g. XML) in the future without having
+     the change the API in principle.
      [Ralf S. Engelschall]
 
    o Document what DCE 1.1 UUID versions exist and what they are


ossp-pkg/uuid/uuid.c -> 1.41

*** /dev/null    Fri Nov 22 14:56:37 2024
--- -    Fri Nov 22 14:56:43 2024
***************
*** 0 ****
--- 1,1015 ----
+ /*
+ **  OSSP uuid - Universally Unique Identifier
+ **  Copyright (c) 2004 Ralf S. Engelschall <rse@engelschall.com>
+ **  Copyright (c) 2004 The OSSP Project <http://www.ossp.org/>
+ **
+ **  This file is part of OSSP uuid, a library for the generation
+ **  of UUIDs which can found at http://www.ossp.org/pkg/lib/uuid/
+ **
+ **  Permission to use, copy, modify, and distribute this software for
+ **  any purpose with or without fee is hereby granted, provided that
+ **  the above copyright notice and this permission notice appear in all
+ **  copies.
+ **
+ **  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ **  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ **  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ **  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
+ **  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ **  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ **  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ **  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ **  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ **  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ **  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ **  SUCH DAMAGE.
+ **
+ **  uuid.c: library API implementation
+ */
+ 
+ /* system headers */
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <stdarg.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <ctype.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <time.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ 
+ /* own headers */
+ #include "config.h"
+ #include "uuid.h"
+ #include "uuid_vers.h"
+ #include "uuid_md5.h"
+ #include "uuid_prng.h"
+ #include "uuid_mac.h"
+ #include "uuid_ui64.h"
+ #include "uuid_str.h"
+ #include "uuid_bm.h"
+ #include "uuid_ac.h"
+ 
+ /* maximum number of 100ns ticks of the actual resolution of system clock
+    (which in our case is 1us (= 1000ns) because we use gettimeofday(2) */
+ #define UUIDS_PER_TICK 10
+ 
+ /* time offset between UUID and Unix Epoch time according to standards.
+    (UUID UTC base time is October 15, 1582
+     Unix UTC base time is January  1, 1970) */
+ #define UUID_TIMEOFFSET "01B21DD213814000"
+ 
+ /* IEEE 802 MAC address encoding/decoding bit fields
+ 
+    ATTENTION:
+ 
+    In case no real/physical IEEE 802 address is available, both
+    "draft-leach-uuids-guids-01" (section "4. Node IDs when no IEEE 802
+    network card is available") and RFC 2518 (section "6.4.1 Node Field
+    Generation Without the IEEE 802 Address") recommend (quoted from RFC
+    2518):
+ 
+      "The ideal solution is to obtain a 47 bit cryptographic quality
+      random number, and use it as the low 47 bits of the node ID, with
+      the most significant bit of the first octet of the node ID set to
+      1. This bit is the unicast/multicast bit, which will never be set
+      in IEEE 802 addresses obtained from network cards; hence, there can
+      never be a conflict between UUIDs generated by machines with and
+      without network cards."
+ 
+    This passage clearly explains the intention to use IEEE 802 multicast
+    addresses. Unfortunately, it incorrectly explains how to implement
+    this! It should instead specify the "*LEAST* significant bit of the
+    first octet of the node ID" as the multicast bit in a memory and
+    hexadecimal string representation of a 48-bit IEEE 802 MAC address.
+ 
+    Unfortunately, even the reference implementation included in the
+    expired IETF "draft-leach-uuids-guids-01" incorrectly set the
+    multicast bit with an OR bit operation and an incorrect mask of
+    0x80. Hence, several other UUID implementations found on the
+    Internet have inherited this bug.
+ 
+    Luckily, neither DCE 1.1 nor ISO/IEC 11578:1996 are affected by this
+    problem. They disregard the topic of missing IEEE 802 addresses
+    entirely, and thus avoid adopting this bug from the original draft
+    and code ;-)
+ 
+    It seems that this standards bug arises from a false interpretation,
+    as the multicast bit is actually is the *MOST* significant bit in
+    IEEE 802.3 (Ethernet) _transmission order_ of an IEEE 802 MAC address.
+    The authors were likely not aware that the bitwise order of an octet
+    from a MAC address memory and hexadecimal string representation is
+    still always from left (MSB, bit 7) to right (LSB, bit 0).
+ 
+    For more information, see "Understanding Physical Addresses" in
+    "Ethernet -- The Definitive Guide", p.43, and the section "ETHERNET
+    MULTICAST ADDRESSES" in http://www.iana.org/assignments/ethernet-numbers.
+ 
+    At OSSP, we do it the intended/correct way and generate a real IEEE 802
+    multicast address. Those wanting to encode broken IEEE 802 MAC addresses
+    (as specified) can nevertheless use a brain dead compile-time option
+    to switch off the correct behavior. When decoding we always use the
+    correct behavior of course. */
+ 
+ /* encoding */
+ #ifdef WITH_RFC2518
+ #define IEEE_MAC_MCBIT_ENC BM_OCTET(1,0,0,0,0,0,0,0)
+ #else
+ #define IEEE_MAC_MCBIT_ENC BM_OCTET(0,0,0,0,0,0,0,1)
+ #endif
+ #define IEEE_MAC_LOBIT_ENC BM_OCTET(0,0,0,0,0,0,1,0)
+ 
+ /* decoding */
+ #define IEEE_MAC_MCBIT_DEC BM_OCTET(0,0,0,0,0,0,0,1)
+ #define IEEE_MAC_LOBIT_DEC BM_OCTET(0,0,0,0,0,0,1,0)
+ 
+ /* IEEE 802 MAC address octet length */
+ #define IEEE_MAC_OCTETS 6
+ 
+ /* UUID binary representation according to UUID standards */
+ typedef struct {
+     uuid_uint32_t  time_low;                  /* bits  0-31 of time field */
+     uuid_uint16_t  time_mid;                  /* bits 32-47 of time field */
+     uuid_uint16_t  time_hi_and_version;       /* bits 48-59 of time field plus 4 bit version */
+     uuid_uint8_t   clock_seq_hi_and_reserved; /* bits  8-13 of clock sequence field plus 2 bit variant */
+     uuid_uint8_t   clock_seq_low;             /* bits  0-7  of clock sequence field */
+     uuid_uint8_t   node[IEEE_MAC_OCTETS];     /* bits  0-47 of node MAC address */
+ } uuid_obj_t;
+ 
+ /* abstract data type (ADT) of API */
+ struct uuid_st {
+     uuid_obj_t     obj;                       /* inlined UUID object */
+     prng_t        *prng;                      /* RPNG sub-object */
+     md5_t         *md5;                       /* MD5 sub-object */
+     uuid_uint8_t   mac[IEEE_MAC_OCTETS];      /* pre-determined MAC address */
+     struct timeval time_last;                 /* last retrieved timestamp */
+     unsigned long  time_seq;                  /* last timestamp sequence counter */
+ };
+ 
+ /* create UUID object */
+ uuid_rc_t uuid_create(uuid_t **uuid)
+ {
+     /* argument sanity check */
+     if (uuid == NULL)
+         return UUID_RC_ARG;
+ 
+     /* allocate UUID object */
+     if ((*uuid = (uuid_t *)malloc(sizeof(uuid_t))) == NULL)
+         return UUID_RC_MEM;
+ 
+     /* set UUID object initially to "Nil UUID" */
+     uuid_load(*uuid, "nil");
+ 
+     /* create PRNG and MD5 sub-objects */
+     if (prng_create(&(*uuid)->prng) != PRNG_RC_OK)
+         return UUID_RC_INT;
+     if (md5_create(&(*uuid)->md5) != MD5_RC_OK)
+         return UUID_RC_INT;
+ 
+     /* resolve MAC address for insertion into node field of UUIDs */
+     if (!mac_address((unsigned char *)((*uuid)->mac), sizeof((*uuid)->mac))) {
+         memset((*uuid)->mac, '\0', sizeof((*uuid)->mac));
+         (*uuid)->mac[0] = BM_OCTET(1,0,0,0,0,0,0,0);
+     }
+ 
+     /* initialize time attributes */
+     (*uuid)->time_last.tv_sec  = 0;
+     (*uuid)->time_last.tv_usec = 0;
+     (*uuid)->time_seq = 0;
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* destroy UUID object */
+ uuid_rc_t uuid_destroy(uuid_t *uuid)
+ {
+     /* argument sanity check */
+     if (uuid == NULL)
+         return UUID_RC_ARG;
+ 
+     /* destroy PRNG and MD5 sub-objects */
+     prng_destroy(uuid->prng);
+     md5_destroy(uuid->md5);
+ 
+     /* free UUID object */
+     free(uuid);
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* check whether UUID object represents "Nil UUID" */
+ uuid_rc_t uuid_isnil(uuid_t *uuid, int *result)
+ {
+     const unsigned char *ucp;
+     int i;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL || result == NULL)
+         return UUID_RC_ARG;
+ 
+     /* a "Nil UUID" is defined as all octets zero, so check for this case */
+     *result = UUID_TRUE;
+     for (i = 0, ucp = (unsigned char *)&(uuid->obj); i < UUID_LEN_BIN; i++) {
+         if (*ucp++ != '\0') {
+             *result = UUID_FALSE;
+             break;
+         }
+     }
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* compare UUID objects */
+ uuid_rc_t uuid_compare(uuid_t *uuid1, uuid_t *uuid2, int *result)
+ {
+     int r;
+ 
+     /* argument sanity check */
+     if (result == NULL)
+         return UUID_RC_ARG;
+ 
+     /* convinience macro for setting result */
+ #   define RESULT(r) \
+     do { \
+         *result = (r); \
+         goto result_exit; \
+     } while (0)
+ 
+     /* special cases: NULL or equal UUIDs */
+     if (uuid1 == uuid2)
+         RESULT(0);
+     if (uuid1 == NULL && uuid2 == NULL)
+         RESULT(0);
+     if (uuid1 == NULL)
+         RESULT((uuid_isnil(uuid2, &r), r) ? 0 : -1);
+     if (uuid2 == NULL)
+         RESULT((uuid_isnil(uuid1, &r), r) ? 0 : 1);
+ 
+     /* standard cases: regular different UUIDs */
+     if (uuid1->obj.time_low != uuid2->obj.time_low)
+         RESULT((uuid1->obj.time_low < uuid2->obj.time_low) ? -1 : 1);
+     if ((r = (int)uuid1->obj.time_mid
+            - (int)uuid2->obj.time_mid) != 0)
+         RESULT((r < 0) ? -1 : 1);
+     if ((r = (int)uuid1->obj.time_hi_and_version
+            - (int)uuid2->obj.time_hi_and_version) != 0)
+         RESULT((r < 0) ? -1 : 1);
+     if ((r = (int)uuid1->obj.clock_seq_hi_and_reserved
+            - (int)uuid2->obj.clock_seq_hi_and_reserved) != 0)
+         RESULT((r < 0) ? -1 : 1);
+     if ((r = (int)uuid1->obj.clock_seq_low
+            - (int)uuid2->obj.clock_seq_low) != 0)
+         RESULT((r < 0) ? -1 : 1);
+     if ((r = memcmp(uuid1->obj.node, uuid2->obj.node, sizeof(uuid1->obj.node))) != 0)
+         RESULT((r < 0) ? -1 : 1);
+ 
+     /* default case: the keys are equal */
+     *result = 0;
+ 
+     result_exit:
+     return UUID_RC_OK;
+ }
+ 
+ /* INTERNAL: unpack UUID binary presentation into UUID object
+    (allows in-place operation for internal efficiency!) */
+ static uuid_rc_t uuid_import_bin(uuid_t *uuid, const void *data_ptr, size_t data_len)
+ {
+     const uuid_uint8_t *in;
+     uuid_uint32_t tmp32;
+     uuid_uint16_t tmp16;
+     unsigned int i;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL || data_ptr == NULL || data_len < UUID_LEN_BIN)
+         return UUID_RC_ARG;
+ 
+     /* treat input data buffer as octet stream */
+     in = (const uuid_uint8_t *)data_ptr;
+ 
+     /* unpack "time_low" field */
+     tmp32 = *in++;
+     tmp32 = (tmp32 << 8) | *in++;
+     tmp32 = (tmp32 << 8) | *in++;
+     tmp32 = (tmp32 << 8) | *in++;
+     uuid->obj.time_low = tmp32;
+ 
+     /* unpack "time_mid" field */
+     tmp16 = *in++;
+     tmp16 = (tmp16 << 8) | *in++;
+     uuid->obj.time_mid = tmp16;
+ 
+     /* unpack "time_hi_and_version" field */
+     tmp16 = *in++;
+     tmp16 = (tmp16 << 8) | *in++;
+     uuid->obj.time_hi_and_version = tmp16;
+ 
+     /* unpack "clock_seq_hi_and_reserved" field */
+     uuid->obj.clock_seq_hi_and_reserved = *in++;
+ 
+     /* unpack "clock_seq_low" field */
+     uuid->obj.clock_seq_low = *in++;
+ 
+     /* unpack "node" field */
+     for (i = 0; i < sizeof(uuid->obj.node); i++)
+         uuid->obj.node[i] = *in++;
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* INTERNAL: pack UUID object into binary representation
+    (allows in-place operation for internal efficiency!) */
+ static uuid_rc_t uuid_export_bin(uuid_t *uuid, void **data_ptr, size_t *data_len)
+ {
+     uuid_uint8_t *out;
+     uuid_uint32_t tmp32;
+     uuid_uint16_t tmp16;
+     unsigned int i;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL || data_ptr == NULL)
+         return UUID_RC_ARG;
+ 
+     /* optionally allocate octet data buffer */
+     if (*data_ptr == NULL) {
+         if ((*data_ptr = malloc(sizeof(uuid_t))) == NULL)
+             return UUID_RC_MEM;
+         if (data_len != NULL)
+             *data_len = UUID_LEN_BIN;
+     }
+     else {
+         if (data_len == NULL)
+             return UUID_RC_ARG;
+         if (*data_len < UUID_LEN_BIN)
+             return UUID_RC_MEM;
+         *data_len = UUID_LEN_BIN;
+     }
+ 
+     /* treat output data buffer as octet stream */
+     out = (uuid_uint8_t *)(*data_ptr);
+ 
+     /* pack "time_low" field */
+     tmp32 = uuid->obj.time_low;
+     out[3] = (uuid_uint8_t)(tmp32 & 0xff); tmp32 >>= 8;
+     out[2] = (uuid_uint8_t)(tmp32 & 0xff); tmp32 >>= 8;
+     out[1] = (uuid_uint8_t)(tmp32 & 0xff); tmp32 >>= 8;
+     out[0] = (uuid_uint8_t)(tmp32 & 0xff);
+ 
+     /* pack "time_mid" field */
+     tmp16 = uuid->obj.time_mid;
+     out[5] = (uuid_uint8_t)(tmp16 & 0xff); tmp16 >>= 8;
+     out[4] = (uuid_uint8_t)(tmp16 & 0xff);
+ 
+     /* pack "time_hi_and_version" field */
+     tmp16 = uuid->obj.time_hi_and_version;
+     out[7] = (uuid_uint8_t)(tmp16 & 0xff); tmp16 >>= 8;
+     out[6] = (uuid_uint8_t)(tmp16 & 0xff);
+ 
+     /* pack "clock_seq_hi_and_reserved" field */
+     out[8] = uuid->obj.clock_seq_hi_and_reserved;
+ 
+     /* pack "clock_seq_low" field */
+     out[9] = uuid->obj.clock_seq_low;
+ 
+     /* pack "node" field */
+     for (i = 0; i < sizeof(uuid->obj.node); i++)
+         out[10+i] = uuid->obj.node[i];
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* INTERNAL: check for valid UUID string representation syntax */
+ static int uuid_isstr(const char *str, size_t str_len)
+ {
+     int i;
+     const char *cp;
+ 
+     /* example reference:
+        f81d4fae-7dec-11d0-a765-00a0c91e6bf6
+        012345678901234567890123456789012345
+        0         1         2         3       */
+     if (str == NULL)
+         return UUID_FALSE;
+     if (str_len == 0)
+         str_len = strlen(str);
+     if (str_len < UUID_LEN_STR)
+         return UUID_FALSE;
+     for (i = 0, cp = str; i < UUID_LEN_STR; i++, cp++) {
+         if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
+             if (*cp == '-')
+                 continue;
+             else
+                 return UUID_FALSE;
+         }
+         if (!isxdigit((int)(*cp)))
+             return UUID_FALSE;
+     }
+     return UUID_TRUE;
+ }
+ 
+ /* INTERNAL: import UUID object from string representation */
+ static uuid_rc_t uuid_import_str(uuid_t *uuid, const void *data_ptr, size_t data_len)
+ {
+     uuid_uint16_t tmp16;
+     const char *cp;
+     char hexbuf[3];
+     const char *str;
+     unsigned int i;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL || data_ptr == NULL || data_len < UUID_LEN_STR)
+         return UUID_RC_ARG;
+ 
+     /* check for correct UUID string representation syntax */
+     str = (const char *)data_ptr;
+     if (!uuid_isstr(str, 0))
+         return UUID_RC_ARG;
+ 
+     /* parse hex values of "time" parts */
+     uuid->obj.time_low            = (uuid_uint32_t)strtoul(str,    NULL, 16);
+     uuid->obj.time_mid            = (uuid_uint16_t)strtoul(str+9,  NULL, 16);
+     uuid->obj.time_hi_and_version = (uuid_uint16_t)strtoul(str+14, NULL, 16);
+ 
+     /* parse hex values of "clock" parts */
+     tmp16 = (uuid_uint16_t)strtoul(str+19, NULL, 16);
+     uuid->obj.clock_seq_low             = (uuid_uint8_t)(tmp16 & 0xff); tmp16 >>= 8;
+     uuid->obj.clock_seq_hi_and_reserved = (uuid_uint8_t)(tmp16 & 0xff);
+ 
+     /* parse hex values of "node" part */
+     cp = str+24;
+     hexbuf[2] = '\0';
+     for (i = 0; i < sizeof(uuid->obj.node); i++) {
+         hexbuf[0] = *cp++;
+         hexbuf[1] = *cp++;
+         uuid->obj.node[i] = strtoul(hexbuf, NULL, 16);
+     }
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* INTERNAL: export UUID object to string representation */
+ static uuid_rc_t uuid_export_str(uuid_t *uuid, void **data_ptr, size_t *data_len)
+ {
+     /* sanity check argument(s) */
+     if (uuid == NULL || data_ptr == NULL)
+         return UUID_RC_ARG;
+ 
+     /* allocate output buffer */
+     if (*data_ptr == NULL) {
+         if ((*data_ptr = (void *)malloc(UUID_LEN_STR+1)) == NULL)
+             return UUID_RC_MEM;
+         if (data_len != NULL)
+             *data_len = UUID_LEN_STR+1;
+     }
+     else {
+         if (data_len == NULL)
+             return UUID_RC_ARG;
+         if (*data_len < UUID_LEN_STR+1)
+             return UUID_RC_MEM;
+         *data_len = UUID_LEN_STR+1;
+     }
+ 
+     /* format UUID into string representation */
+     str_snprintf((char *)(*data_ptr), UUID_LEN_STR+1,
+         "%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+         (unsigned long)uuid->obj.time_low,
+         (unsigned int)uuid->obj.time_mid,
+         (unsigned int)uuid->obj.time_hi_and_version,
+         (unsigned int)uuid->obj.clock_seq_hi_and_reserved,
+         (unsigned int)uuid->obj.clock_seq_low,
+         (unsigned int)uuid->obj.node[0],
+         (unsigned int)uuid->obj.node[1],
+         (unsigned int)uuid->obj.node[2],
+         (unsigned int)uuid->obj.node[3],
+         (unsigned int)uuid->obj.node[4],
+         (unsigned int)uuid->obj.node[5]);
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* decoding tables */
+ static struct {
+     uuid_uint8_t num;
+     const char *desc;
+ } uuid_dectab_variant[] = {
+     { BM_OCTET(0,0,0,0,0,0,0,0), "reserved (NCS backward compatible)" },
+     { BM_OCTET(1,0,0,0,0,0,0,0), "DCE 1.1, ISO/IEC 11578:1996" },
+     { BM_OCTET(1,1,0,0,0,0,0,0), "reserved (Microsoft GUID)" },
+     { BM_OCTET(1,1,1,0,0,0,0,0), "reserved (future use)" }
+ };
+ static struct {
+     int num;
+     const char *desc;
+ } uuid_dectab_version[] = {
+     { 1, "time and node based" },
+     { 3, "name based" },
+     { 4, "random data based" }
+ };
+ 
+ /* INTERNAL: dump UUID object as descriptive text */
+ static uuid_rc_t uuid_export_txt(uuid_t *uuid, void **data_ptr, size_t *data_len)
+ {
+     uuid_rc_t rc;
+     char **out;
+     char *out_ptr;
+     size_t out_len;
+     const char *version;
+     const char *variant;
+     char *content;
+     int isnil;
+     uuid_uint8_t tmp8;
+     uuid_uint16_t tmp16;
+     uuid_uint32_t tmp32;
+     uuid_uint8_t tmp_bin[UUID_LEN_BIN];
+     char tmp_str[UUID_LEN_STR+1];
+     void *tmp_ptr;
+     size_t tmp_len;
+     ui64_t t;
+     ui64_t t_offset;
+     int t_nsec;
+     int t_usec;
+     time_t t_sec;
+     char t_buf[19+1]; /* YYYY-MM-DD HH:MM:SS */
+     struct tm *tm;
+     unsigned int i;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL || data_ptr == NULL)
+         return UUID_RC_ARG;
+ 
+     /* initialize output buffer */
+     out_ptr = NULL;
+     out = &out_ptr;
+ 
+     /* check for special case of "Nil UUID" */
+     if ((rc = uuid_isnil(uuid, &isnil)) != UUID_RC_OK)
+         return rc;
+ 
+     /* decode into string representation */
+     tmp_ptr = (void *)&tmp_str;
+     tmp_len = sizeof(tmp_str);
+     if ((rc = uuid_export(uuid, UUID_FMT_STR, &tmp_ptr, &tmp_len)) != UUID_RC_OK)
+         return rc;
+     str_rsprintf(out, "UUID:    %s\n", tmp_str);
+ 
+     /* decode UUID variant */
+     tmp8 = uuid->obj.clock_seq_hi_and_reserved;
+     if (isnil)
+         variant = "n.a.";
+     else {
+         variant = "unknown";
+         for (i = 7; i >= 0; i--) {
+             if ((tmp8 & BM_BIT(i,1)) == 0) {
+                 tmp8 &= ~BM_MASK(i,0);
+                 break;
+             }
+         }
+         for (i = 0; i < sizeof(uuid_dectab_variant)/sizeof(uuid_dectab_variant[0]); i++) {
+             if (uuid_dectab_variant[i].num == tmp8) {
+                 variant = uuid_dectab_variant[i].desc;
+                 break;
+             }
+         }
+     }
+     str_rsprintf(out, "variant: %s\n", variant);
+ 
+     /* decode UUID version */
+     tmp16 = (BM_SHR(uuid->obj.time_hi_and_version, 12) & BM_MASK(3,0));
+     if (isnil)
+         version = "n.a.";
+     else {
+         version = "unknown";
+         for (i = 0; i < sizeof(uuid_dectab_version)/sizeof(uuid_dectab_version[0]); i++) {
+             if (uuid_dectab_version[i].num == (int)tmp16) {
+                 version = uuid_dectab_version[i].desc;
+                 break;
+             }
+         }
+     }
+     str_rsprintf(out, "version: %d (%s)\n", (int)tmp16, version);
+ 
+     /*
+      * decode UUID content
+      */
+ 
+     if (tmp8 == BM_OCTET(1,0,0,0,0,0,0,0) && tmp16 == 1) {
+         /* decode DCE 1.1 version 1 UUID */
+ 
+         /* decode system time */
+         t = ui64_rol(ui64_n2i((unsigned long)(uuid->obj.time_hi_and_version & BM_MASK(11,0))), 48, NULL),
+         t = ui64_or(t, ui64_rol(ui64_n2i((unsigned long)(uuid->obj.time_mid)), 32, NULL));
+         t = ui64_or(t, ui64_n2i((unsigned long)(uuid->obj.time_low)));
+         t_offset = ui64_s2i(UUID_TIMEOFFSET, NULL, 16);
+         t = ui64_sub(t, t_offset, NULL);
+         t = ui64_divn(t, 10, &t_nsec);
+         t = ui64_divn(t, 1000000, &t_usec);
+         t_sec = (time_t)ui64_i2n(t);
+         tm = gmtime(&t_sec);
+         strftime(t_buf, sizeof(t_buf), "%Y-%m-%d %H:%M:%S", tm);
+         str_rsprintf(out, "content: time:  %s.%06d.%d UTC\n", t_buf, t_usec, t_nsec);
+ 
+         /* decode clock sequence */
+         tmp32 = ((uuid->obj.clock_seq_hi_and_reserved & BM_MASK(5,0)) << 8)
+                 + uuid->obj.clock_seq_low;
+         str_rsprintf(out, "         clock: %ld (usually random)\n", (long)tmp32);
+ 
+         /* decode node MAC address */
+         str_rsprintf(out, "         node:  %02x:%02x:%02x:%02x:%02x:%02x (%s %s)\n",
+             (unsigned int)uuid->obj.node[0],
+             (unsigned int)uuid->obj.node[1],
+             (unsigned int)uuid->obj.node[2],
+             (unsigned int)uuid->obj.node[3],
+             (unsigned int)uuid->obj.node[4],
+             (unsigned int)uuid->obj.node[5],
+             (uuid->obj.node[0] & IEEE_MAC_LOBIT_DEC ? "local" : "global"),
+             (uuid->obj.node[0] & IEEE_MAC_MCBIT_DEC ? "multicast" : "unicast"));
+     }
+     else {
+         /* decode anything else as hexadecimal byte-string only */
+ 
+         /* determine annotational hint */
+         content = "not decipherable, because unknown UUID version";
+         if (isnil)
+             content = "special case of DCE 1.1 Nil UUID";
+         else if (tmp16 == 3)
+             content = "not decipherable, because message digest only";
+         else if (tmp16 == 4)
+             content = "no semantics, because random data only";
+ 
+         /* pack UUID into binary representation */
+         tmp_ptr = (void *)&tmp_bin;
+         tmp_len = sizeof(tmp_bin);
+         if ((rc = uuid_export(uuid, UUID_FMT_BIN, &tmp_ptr, &tmp_len)) != UUID_RC_OK)
+             return rc;
+ 
+         /* mask out version and variant parts */
+         tmp_bin[6] &= BM_MASK(3,0);
+         tmp_bin[8] &= BM_MASK(5,0);
+ 
+         /* dump as colon-seperated hexadecimal byte-string */
+         str_rsprintf(out,
+             "content: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n"
+             "         (%s)\n",
+             (unsigned int)tmp_bin[0],  (unsigned int)tmp_bin[1],  (unsigned int)tmp_bin[2],
+             (unsigned int)tmp_bin[3],  (unsigned int)tmp_bin[4],  (unsigned int)tmp_bin[5],
+             (unsigned int)tmp_bin[6],  (unsigned int)tmp_bin[7],  (unsigned int)tmp_bin[8],
+             (unsigned int)tmp_bin[9],  (unsigned int)tmp_bin[10], (unsigned int)tmp_bin[11],
+             (unsigned int)tmp_bin[12], (unsigned int)tmp_bin[13], (unsigned int)tmp_bin[14],
+             (unsigned int)tmp_bin[15], content);
+     }
+ 
+     /* provide result */
+     out_len = strlen(out_ptr)+1;
+     if (*data_ptr == NULL) {
+         *data_ptr = (void *)out_ptr;
+         if (data_len != NULL)
+             *data_len = out_len;
+     }
+     else {
+         if (data_len == NULL)
+             return UUID_RC_ARG;
+         if (*data_len < out_len)
+             return UUID_RC_MEM;
+         memcpy(*data_ptr, &out_ptr, out_len);
+     }
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* UUID importing */
+ uuid_rc_t uuid_import(uuid_t *uuid, uuid_fmt_t fmt, const void *data_ptr, size_t data_len)
+ {
+     uuid_rc_t rc;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL || data_ptr == NULL)
+         return UUID_RC_ARG;
+ 
+     /* dispatch into format-specific functions */
+     switch (fmt) {
+         case UUID_FMT_BIN: rc = uuid_import_bin(uuid, data_ptr, data_len); break;
+         case UUID_FMT_STR: rc = uuid_import_str(uuid, data_ptr, data_len); break;
+         case UUID_FMT_TXT: rc = UUID_RC_IMP; /* not implemented */ break;
+         default:           rc = UUID_RC_ARG;
+     }
+ 
+     return rc;
+ }
+ 
+ /* UUID exporting */
+ uuid_rc_t uuid_export(uuid_t *uuid, uuid_fmt_t fmt, void **data_ptr, size_t *data_len)
+ {
+     uuid_rc_t rc;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL || data_ptr == NULL)
+         return UUID_RC_ARG;
+ 
+     /* dispatch into format-specific functions */
+     switch (fmt) {
+         case UUID_FMT_BIN: rc = uuid_export_bin(uuid, data_ptr, data_len); break;
+         case UUID_FMT_STR: rc = uuid_export_str(uuid, data_ptr, data_len); break;
+         case UUID_FMT_TXT: rc = uuid_export_txt(uuid, data_ptr, data_len); break;
+         default:           rc = UUID_RC_ARG;
+     }
+ 
+     return rc;
+ }
+ 
+ /* INTERNAL: brand UUID with version and variant */
+ static void uuid_brand(uuid_t *uuid, int version)
+ {
+     /* set version (as given) */
+     uuid->obj.time_hi_and_version &= BM_MASK(11,0);
+     uuid->obj.time_hi_and_version |= BM_SHL((uuid_uint16_t)version, 12);
+ 
+     /* set variant (always DCE 1.1 only) */
+     uuid->obj.clock_seq_hi_and_reserved &= BM_MASK(5,0);
+     uuid->obj.clock_seq_hi_and_reserved |= BM_SHL(0x02, 6);
+     return;
+ }
+ 
+ /* INTERNAL: generate UUID version 1: time, clock and node based */
+ static uuid_rc_t uuid_make_v1(uuid_t *uuid, unsigned int mode, va_list ap)
+ {
+     struct timeval time_now;
+ #ifdef HAVE_NANOSLEEP
+     struct timespec ts;
+ #else
+     struct timeval tv;
+ #endif
+     ui64_t t;
+     ui64_t offset;
+     ui64_t ov;
+     uuid_uint16_t clck;
+ 
+     /*
+      *  GENERATE TIME
+      */
+ 
+     /* determine current system time and sequence counter */
+     while (1) {
+         /* determine current system time */
+         if (gettimeofday(&time_now, NULL) == -1)
+             return UUID_RC_SYS;
+ 
+         /* check whether system time changed since last retrieve */
+         if (!(   time_now.tv_sec  == uuid->time_last.tv_sec
+               && time_now.tv_usec == uuid->time_last.tv_usec))
+             /* reset time sequence counter */
+             uuid->time_seq = 0;
+ 
+         /* until we are out of UUIDs per tick, increment
+            the time/tick sequence counter and continue */
+         if (uuid->time_seq < UUIDS_PER_TICK) {
+             uuid->time_seq++;
+             break;
+         }
+ 
+         /* stall the UUID generation until the system clock (which
+            has a gettimeofday(2) resolution of 1us) catches up */
+ #ifdef HAVE_NANOSLEEP
+         /* sleep for 500ns (1/2us) */
+         ts.tv_sec  = 0;
+         ts.tv_nsec = 500;
+         nanosleep(&ts, NULL);
+ #else
+         /* sleep for 1000ns (1us) */
+         tv.tv_sec  = 0;
+         tv.tv_usec = 1;
+         select(0, NULL, NULL, NULL, &tv);
+ #endif
+     }
+ 
+     /* convert from timeval (sec,usec) to OSSP ui64 (100*nsec) format */
+     t = ui64_n2i(time_now.tv_sec);
+     t = ui64_muln(t, 1000000, NULL);
+     t = ui64_addn(t, time_now.tv_usec, NULL);
+     t = ui64_muln(t, 10, NULL);
+ 
+     /* adjust for offset between UUID and Unix Epoch time */
+     offset = ui64_s2i(UUID_TIMEOFFSET, NULL, 16);
+     t = ui64_add(t, offset, NULL);
+ 
+     /* compensate for low resolution system clock by adding
+        the time/tick sequence counter */
+     if (uuid->time_seq > 0)
+         t = ui64_addn(t, uuid->time_seq, NULL);
+ 
+     /* store the 60 LSB of the time in the UUID */
+     t = ui64_rol(t, 16, &ov);
+     uuid->obj.time_hi_and_version =
+         (uuid_uint16_t)(ui64_i2n(ov) & 0x00000fff); /* 12 of 16 bit only! */
+     t = ui64_rol(t, 16, &ov);
+     uuid->obj.time_mid =
+         (uuid_uint16_t)(ui64_i2n(ov) & 0x0000ffff); /* all 16 bit */
+     t = ui64_rol(t, 32, &ov);
+     uuid->obj.time_low =
+         (uuid_uint32_t)(ui64_i2n(ov) & 0xffffffff); /* all 32 bit */
+ 
+     /*
+      *  GENERATE CLOCK
+      */
+ 
+     /* retrieve current clock sequence */
+     clck = ((uuid->obj.clock_seq_hi_and_reserved & BM_MASK(5,0)) << 8)
+            + uuid->obj.clock_seq_low;
+ 
+     /* generate new random clock sequence (initially or if the
+        time has stepped backwards) or else just increase it */
+     if (   clck == 0
+         || (   time_now.tv_sec < uuid->time_last.tv_sec
+             || (   time_now.tv_sec == uuid->time_last.tv_sec
+                 && time_now.tv_usec < uuid->time_last.tv_usec)))
+         prng_data(uuid->prng, (void *)&clck, sizeof(clck));
+     else
+         clck++;
+     clck %= BM_POW2(14);
+ 
+     /* store back new clock sequence */
+     uuid->obj.clock_seq_hi_and_reserved =
+         (uuid->obj.clock_seq_hi_and_reserved & BM_MASK(7,6))
+         | (uuid_uint8_t)((clck >> 8) & 0xff);
+     uuid->obj.clock_seq_low =
+         (uuid_uint8_t)(clck & 0xff);
+ 
+     /*
+      *  GENERATE NODE
+      */
+ 
+     if ((mode & UUID_MCASTRND) || (uuid->mac[0] & BM_OCTET(1,0,0,0,0,0,0,0))) {
+         /* generate random IEEE 802 local multicast MAC address */
+         prng_data(uuid->prng, (void *)&(uuid->obj.node), sizeof(uuid->obj.node));
+         uuid->obj.node[0] |= IEEE_MAC_MCBIT_ENC;
+         uuid->obj.node[0] |= IEEE_MAC_LOBIT_ENC;
+     }
+     else {
+         /* use real regular MAC address */
+         memcpy(uuid->obj.node, uuid->mac, sizeof(uuid->mac));
+     }
+ 
+     /*
+      *  FINISH
+      */
+ 
+     /* remember current system time for next iteration */
+     uuid->time_last.tv_sec  = time_now.tv_sec;
+     uuid->time_last.tv_usec = time_now.tv_usec;
+ 
+     /* brand with version and variant */
+     uuid_brand(uuid, 1);
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* INTERNAL: pre-defined UUID values.
+    (defined as network byte ordered octet stream) */
+ static struct {
+     char *name;
+     uuid_uint8_t uuid[UUID_LEN_BIN];
+ } uuid_value_table[] = {
+     { "nil",     /* 00000000-0000-0000-0000-000000000000 ("Nil UUID") */
+       { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } },
+     { "ns:DNS",  /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 (see draft-leach-uuids-guids-01.txt) */
+       { 0x6b,0xa7,0xb8,0x10,0x9d,0xad,0x11,0xd1,0x80,0xb4,0x00,0xc0,0x4f,0xd4,0x30,0xc8 } },
+     { "ns:URL",  /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 (see draft-leach-uuids-guids-01.txt) */
+       { 0x6b,0xa7,0xb8,0x11,0x9d,0xad,0x11,0xd1,0x80,0xb4,0x00,0xc0,0x4f,0xd4,0x30,0xc8 } },
+     { "ns:OID",  /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 (see draft-leach-uuids-guids-01.txt) */
+       { 0x6b,0xa7,0xb8,0x12,0x9d,0xad,0x11,0xd1,0x80,0xb4,0x00,0xc0,0x4f,0xd4,0x30,0xc8 } },
+     { "ns:X500", /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 (see draft-leach-uuids-guids-01.txt) */
+       { 0x6b,0xa7,0xb8,0x14,0x9d,0xad,0x11,0xd1,0x80,0xb4,0x00,0xc0,0x4f,0xd4,0x30,0xc8 } }
+ };
+ 
+ /* load UUID object with pre-defined value */
+ uuid_rc_t uuid_load(uuid_t *uuid, const char *name)
+ {
+     uuid_uint8_t *uuid_octets;
+     uuid_rc_t rc;
+     unsigned int i;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL || name == NULL)
+         return UUID_RC_ARG;
+ 
+     /* search for UUID in table */
+     uuid_octets = NULL;
+     for (i = 0; i < sizeof(uuid_value_table)/sizeof(uuid_value_table[0]); i++) {
+          if (strcmp(uuid_value_table[i].name, name) == 0) {
+              uuid_octets = uuid_value_table[i].uuid;
+              break;
+          }
+     }
+     if (uuid_octets == NULL)
+         return UUID_RC_ARG;
+ 
+     /* import value into UUID object */
+     if ((rc = uuid_import(uuid, UUID_FMT_BIN, uuid_octets, UUID_LEN_BIN)) != UUID_RC_OK)
+         return rc;
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* INTERNAL: generate UUID version 3: name based */
+ static uuid_rc_t uuid_make_v3(uuid_t *uuid, unsigned int mode, va_list ap)
+ {
+     char *str;
+     uuid_t *uuid_ns;
+     uuid_uint8_t uuid_buf[UUID_LEN_BIN];
+     void *uuid_ptr;
+     size_t uuid_len;
+ 
+     /* determine namespace UUID and name string arguments */
+     if ((uuid_ns = (uuid_t *)va_arg(ap, void *)) == NULL)
+         return UUID_RC_ARG;
+     if ((str = (char *)va_arg(ap, char *)) == NULL)
+         return UUID_RC_ARG;
+ 
+     /* initialize MD5 context */
+     if (md5_init(uuid->md5) != MD5_RC_OK)
+         return UUID_RC_MEM;
+ 
+     /* load the namespace UUID into MD5 context */
+     uuid_ptr = (void *)&uuid_buf;
+     uuid_len = sizeof(uuid_buf);
+     uuid_export(uuid_ns, UUID_FMT_BIN, &uuid_ptr, &uuid_len);
+     md5_update(uuid->md5, uuid_buf, uuid_len);
+ 
+     /* load the argument name string into MD5 context */
+     md5_update(uuid->md5, str, strlen(str));
+ 
+     /* store MD5 result into UUID
+        (requires MD5_LEN_BIN space, UUID_LEN_BIN space is available,
+        and both are equal in size, so we are safe!) */
+     uuid_ptr = (void *)&(uuid->obj);
+     md5_store(uuid->md5, &uuid_ptr, NULL);
+ 
+     /* fulfill requirement of standard and convert UUID data into
+        local/host byte order (this uses fact that uuid_import_bin() is
+        able to operate in-place!) */
+     uuid_import(uuid, UUID_FMT_BIN, (void *)&(uuid->obj), UUID_LEN_BIN);
+ 
+     /* brand UUID with version and variant */
+     uuid_brand(uuid, 3);
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* INTERNAL: generate UUID version 4: random number based */
+ static uuid_rc_t uuid_make_v4(uuid_t *uuid, unsigned int mode, va_list ap)
+ {
+     /* fill UUID with random data */
+     prng_data(uuid->prng, (void *)&(uuid->obj), sizeof(uuid->obj));
+ 
+     /* brand UUID with version and variant */
+     uuid_brand(uuid, 4);
+ 
+     return UUID_RC_OK;
+ }
+ 
+ /* generate UUID */
+ uuid_rc_t uuid_make(uuid_t *uuid, unsigned int mode, ...)
+ {
+     va_list ap;
+     uuid_rc_t rc;
+ 
+     /* sanity check argument(s) */
+     if (uuid == NULL)
+         return UUID_RC_ARG;
+ 
+     /* dispatch into version dependent generation functions */
+     va_start(ap, mode);
+     if (mode & UUID_VERSION1)
+         rc = uuid_make_v1(uuid, mode, ap);
+     else if (mode & UUID_VERSION3)
+         rc = uuid_make_v3(uuid, mode, ap);
+     else if (mode & UUID_VERSION4)
+         rc = uuid_make_v4(uuid, mode, ap);
+     else
+         rc = UUID_RC_ARG;
+     va_end(ap);
+ 
+     return rc;
+ }
+ 
+ /* translate UUID API error code into corresponding error string */
+ char *uuid_error(uuid_rc_t rc)
+ {
+     char *str;
+ 
+     switch (rc) {
+         case UUID_RC_OK:  str = "everything ok";    break;
+         case UUID_RC_ARG: str = "invalid argument"; break;
+         case UUID_RC_MEM: str = "out of memory";    break;
+         case UUID_RC_SYS: str = "system error";     break;
+         default:          str = NULL;               break;
+     }
+     return str;
+ }
+ 
+ /* OSSP uuid version (link-time information) */
+ unsigned long uuid_version(void)
+ {
+     return (unsigned long)(_UUID_VERSION);
+ }
+ 


ossp-pkg/uuid/uuid.h 1.14 -> 1.15

--- uuid.h       2004/01/18 20:19:23     1.14
+++ uuid.h       2004/01/19 12:15:05     1.15
@@ -30,6 +30,9 @@
 #ifndef __UUID_H__
 #define __UUID_H__
 
+/* required system headers */
+#include <string.h>
+
 /* OSSP uuid version (compile-time information) */
 #define UUID_VERSION 0x009204
 
@@ -82,8 +85,8 @@
 extern uuid_rc_t  uuid_destroy  (uuid_t  *_uuid);
 
 /* UUID generation */
-extern uuid_rc_t  uuid_nil      (uuid_t  *_uuid);
-extern uuid_rc_t  uuid_generate (uuid_t  *_uuid, unsigned int _mode, ...);
+extern uuid_rc_t  uuid_load     (uuid_t  *_uuid, const char *_name);
+extern uuid_rc_t  uuid_make     (uuid_t  *_uuid, unsigned int _mode, ...);
 
 /* UUID comparison */
 extern uuid_rc_t  uuid_isnil    (uuid_t  *_uuid,                 int *_result);


ossp-pkg/uuid/uuid.pod 1.11 -> 1.12

--- uuid.pod     2004/01/18 19:59:12     1.11
+++ uuid.pod     2004/01/19 12:15:05     1.12
@@ -186,7 +186,7 @@
 
 =item B<UUID_VERSION1>, B<UUID_VERSION3>, B<UUID_VERSION4>, B<UUID_MCASTRND>
 
-The I<mode> bits for use with B<uuid_generate>(). The
+The I<mode> bits for use with B<uuid_make>(). The
 B<UUID_VERSION>I<N> specify which UUID version to generate. The
 B<UUID_MCASTRND> forces the use of a random multi-cast MAC address
 instead of the real physical MAC address in version 1 UUIDs.
@@ -223,10 +223,6 @@
 
 Destroy UUID object I<uuid>.
 
-=item uuid_rc_t B<uuid_nil>(uuid_t *I<uuid>);
-
-Sets or resets the UUID in I<uuid> to the I<Nil> UUID.
-
 =item uuid_rc_t B<uuid_isnil>(uuid_t *I<uuid>, int *I<result>);
 
 Checks whether the UUID in I<uuid> is the I<Nil> UUID.
@@ -240,7 +236,6 @@
 smaller than I<uuid2>, C<0> if I<uuid1> is equal to I<uuid2>
 and C<+1> if I<uuid1> is greater than I<uuid2>.
 
-
 =item uuid_rc_t B<uuid_import>(uuid_t *I<uuid>, uuid_fmt_t I<fmt>, const void *I<data_ptr>, size_t I<data_len>);
 
 Imports a UUID I<uuid> from an external representation of format I<fmt>.
@@ -264,7 +259,31 @@
 minimum required length in C<*>I<data_len> depends on it. Valid values
 for I<fmt> are B<UUID_FMT_BIN>, B<UUID_FMT_STR> and B<UUID_FMT_TXT>.
 
-=item uuid_rc_t B<uuid_generate>(uuid_t *I<uuid>, unsigned int I<mode>, ...);
+=item uuid_rc_t B<uuid_load>(uuid_t *I<uuid>, const char *I<name>);
+
+Loads a pre-defined UUID value into the UUID object I<uuid>. The
+following I<name> arguments are currently known:
+
+=over 4
+
+=item I<name>      I<UUID>
+
+=item nil       00000000-0000-0000-0000-000000000000
+
+=item ns:DNS    6ba7b810-9dad-11d1-80b4-00c04fd430c8
+
+=item ns:URL    6ba7b811-9dad-11d1-80b4-00c04fd430c8
+
+=item ns:OID    6ba7b812-9dad-11d1-80b4-00c04fd430c8
+
+=item ns:X500   6ba7b814-9dad-11d1-80b4-00c04fd430c8
+
+=back
+
+The "C<ns:>I<XXX>" are names of pre-defined name-space UUIDs for use in
+the generation of DCE 1.1 version 3 UUIDs.
+
+=item uuid_rc_t B<uuid_make>(uuid_t *I<uuid>, unsigned int I<mode>, ...);
 
 Generates a new UUID in I<uuid> according to I<mode> and optional
 arguments (dependent on I<mode>).
@@ -302,27 +321,31 @@
 code.
 
  /* generate a DCE 1.1 v1 UUID from system environment */
- char *uuid_v1(void) 
+ char *uuid_v1(void)
  {
      uuid_t *uuid;
      char *str = NULL;
 
      uuid_create(&uuid);
-     uuid_generate(uuid, UUID_VERSION1);
-     uuid_export(uuid, UUID_FMT_STR, &str, NULL);
+     uuid_make(uuid, UUID_VERSION1);
+     uuid_export(uuid, UUID_FMT_STR, (void **)&str, NULL);
      uuid_destroy(uuid);
      return str;
  }
 
  /* generate a DCE 1.1 v3 UUID from an URL */
- char *uuid_v3(const char *url) 
+ char *uuid_v3(const char *url)
  {
      uuid_t *uuid;
+     uuid_t *uuid_ns;
      char *str = NULL;
 
      uuid_create(&uuid);
-     uuid_generate(uuid, UUID_VERSION3, "URL", url);
-     uuid_export(uuid, UUID_FMT_STR, &str, NULL);
+     uuid_create(&uuid_ns);
+     uuid_load(uuid_ns, "ns:URL");
+     uuid_make(uuid, UUID_VERSION3, uuid_ns, url);
+     uuid_export(uuid, UUID_FMT_STR, (void **)&str, NULL);
+     uuid_destroy(uuid_ns);
      uuid_destroy(uuid);
      return str;
  }
@@ -333,7 +356,7 @@
 
 =over 4
 
-=item 
+=item
 
 B<UUIDs and GUIDs>,
 IETF Internet Draft (expired),
@@ -341,7 +364,7 @@
 February 1998, 27 pages,
 http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
 
-=item 
+=item
 
 B<DCE 1.1: Remote Procedure Call>,
 appendix B<Universally Unique Identifier>,
@@ -349,16 +372,16 @@
 Document Number C706, August 1997, 737 pages,
 (supersedes C309 DCE: Remote Procedure Call 8/1994,
 which was basis for ISO/IEC 11578:1996 specification),
-http://www.opengroup.org/publications/catalog/c706.htm 
+http://www.opengroup.org/publications/catalog/c706.htm
 
-=item 
+=item
 
 B<Information technology -- Open Systems Interconnection (OSI) -- Remote Procedure Call (RPC)>,
 ISO/IEC 11578:1996,
 August 2001, 570 pages, (CHF 340,00),
 http://www.iso.ch/cate/d2229.html
 
-=item 
+=item
 
 B<HTTP Extensions for Distributed Authoring (WebDAV)>,
 section B<6.4.1 Node Field Generation Without the IEEE 802 Address>,


ossp-pkg/uuid/uuid_cli.c 1.12 -> 1.13

--- uuid_cli.c   2004/01/19 09:11:00     1.12
+++ uuid_cli.c   2004/01/19 12:15:05     1.13
@@ -71,6 +71,7 @@
 int main(int argc, char *argv[])
 {
     uuid_t *uuid;
+    uuid_t *uuid_ns;
     uuid_rc_t rc;
     FILE *fp;
     char *p;
@@ -149,10 +150,10 @@
         if (strlen(argv[0]) != UUID_LEN_STR)
             error(1, "invalid length of UUID string representation");
         if ((rc = uuid_import(uuid, UUID_FMT_STR, argv[0], strlen(argv[0]))) != UUID_RC_OK)
-            error(1, "uuid_parse: %s", uuid_error(rc));
+            error(1, "uuid_import: %s", uuid_error(rc));
         vp = NULL;
         if ((rc = uuid_export(uuid, UUID_FMT_TXT, &vp, NULL)) != UUID_RC_OK)
-            error(1, "uuid_dump: %s", uuid_error(rc));
+            error(1, "uuid_export: %s", uuid_error(rc));
         fprintf(stdout, "%s", (char *)vp);
         free(vp);
         if ((rc = uuid_destroy(uuid)) != UUID_RC_OK)
@@ -171,19 +172,29 @@
             if (strlen(argv[0]) != UUID_LEN_STR)
                 error(1, "invalid length of UUID string representation");
             if ((rc = uuid_import(uuid, UUID_FMT_STR, argv[0], strlen(argv[0]))) != UUID_RC_OK)
-                error(1, "uuid_parse: %s", uuid_error(rc));
+                error(1, "uuid_import: %s", uuid_error(rc));
         }
         for (i = 0; i < count; i++) {
             if (iterate) {
-                if ((rc = uuid_nil(uuid)) != UUID_RC_OK)
-                    error(1, "uuid_nil: %s", uuid_error(rc));
+                if ((rc = uuid_load(uuid, "nil")) != UUID_RC_OK)
+                    error(1, "uuid_load: %s", uuid_error(rc));
+            }
+            if (version == UUID_VERSION3) {
+                if ((rc = uuid_create(&uuid_ns)) != UUID_RC_OK)
+                    error(1, "uuid_create: %s", uuid_error(rc));
+                if ((rc = uuid_load(uuid_ns, argv[0])) != UUID_RC_OK) {
+                    if ((rc = uuid_import(uuid_ns, UUID_FMT_STR, argv[0], strlen(argv[0]))) != UUID_RC_OK)
+                        error(1, "uuid_import: %s", uuid_error(rc));
+                }
+                if ((rc = uuid_make(uuid, version, uuid_ns, argv[1])) != UUID_RC_OK)
+                    error(1, "uuid_make: %s", uuid_error(rc));
+                if ((rc = uuid_destroy(uuid_ns)) != UUID_RC_OK)
+                    error(1, "uuid_destroy: %s", uuid_error(rc));
+            }
+            else {
+                if ((rc = uuid_make(uuid, version)) != UUID_RC_OK)
+                    error(1, "uuid_make: %s", uuid_error(rc));
             }
-            if (version == UUID_VERSION3)
-                rc = uuid_generate(uuid, version, argv[0], argv[1]);
-            else
-                rc = uuid_generate(uuid, version);
-            if (rc != UUID_RC_OK)
-                error(1, "uuid_generate: %s", uuid_error(rc));
             if (raw) {
                 vp = NULL;
                 if ((rc = uuid_export(uuid, UUID_FMT_BIN, &vp, &n)) != UUID_RC_OK)
@@ -194,7 +205,7 @@
             else {
                 vp = NULL;
                 if ((rc = uuid_export(uuid, UUID_FMT_STR, &vp, &n)) != UUID_RC_OK)
-                    error(1, "uuid_format: %s", uuid_error(rc));
+                    error(1, "uuid_export: %s", uuid_error(rc));
                 fprintf(fp, "%s\n", (char *)vp);
                 free(vp);
             }

CVSTrac 2.0.1