OSSP CVS Repository

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

Check-in Number: 3718
Date: 2004-Jan-09 22:59:57 (local)
2004-Jan-09 21:59:57 (UTC)
User:rse
Branch:
Comment: add generator framework and implement version 4 UUIDs (random number only)
Tickets:
Inspections:
Files:
ossp-pkg/uuid/uuid.c      1.8 -> 1.9     126 inserted, 2 deleted

ossp-pkg/uuid/uuid.c 1.8 -> 1.9

--- uuid.c       2004/01/09 21:01:04     1.8
+++ uuid.c       2004/01/09 21:59:57     1.9
@@ -33,6 +33,10 @@
 #include <string.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <time.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
 
 #include "config.h"
 #include "uuid.h"
@@ -398,17 +402,137 @@
     return UUID_RC_OK;
 }
 
+/* pseudo-random number generator (PRNG) */
+static void uuid_prng_getdata(uuid_uint8_t *data_ptr, size_t data_len)
+{
+    static int initialized = FALSE;
+    static int fd = -1;
+    struct timeval tv;
+    pid_t pid;
+    size_t n;
+    size_t i;
+    uuid_uint8_t *p;
+    int cnt;
+
+    if (!initialized) {
+        /* try to open the system PRNG device */
+        if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
+            fd = open("/dev/random", O_RDONLY|O_NONBLOCK);
+        if (fd != -1)
+            fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+        /* seed the PRNG once */
+        gettimeofday(&tv, NULL);
+        pid = getpid();
+        srand((unsigned int)(
+              ((uuid_uint32_t)pid << 16)
+            ^ (uuid_uint32_t)pid
+            ^ (uuid_uint32_t)tv.tv_sec
+            ^ (uuid_uint32_t)tv.tv_usec));
+
+        /* crank the PRNG a few times */
+        gettimeofday(&tv, NULL);
+        for (i = (unsigned int)(tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
+            (void)rand();
+
+        initialized = TRUE;
+    }
+
+    /* try to gather data from the system PRNG device */
+    if (fd != -1) {
+        p = data_ptr;
+        n = data_len;
+        cnt = 0;
+        while (n > 0) {
+            i = read(fd, (void *)p, n);
+            if (i <= 0) {
+                if (cnt++ > 16)
+                    break;
+                continue;
+            }
+            n -= i;
+            p += i;
+            cnt = 0;
+        }
+    }
+
+    /* always also apply the weaker PRNG. In case the stronger PRNG device
+       based source failed, this is the only remaining randomness, of course */
+    for (p = data_ptr, n = 0; n < data_len; n++)
+        *p++ ^= (uuid_uint8_t)(((uuid_uint32_t)rand() >> 7) & 0xFF);
+
+    return;
+}
+
+/* brand UUID with version and variant */
+static void uuid_brand(uuid_t *uuid, int version)
+{
+    /* set version (as given) */
+    uuid->time_hi_and_version &= 0x0fff;
+    uuid->time_hi_and_version |= (((uuid_uint16_t)version & 0x0fff) << 12);
+
+    /* set variant (always DCE 1.1 only) */
+    uuid->clock_seq_hi_and_reserved &= ~((0x03) << 6);
+    uuid->clock_seq_hi_and_reserved |= (0x02 << 6);
+    return;
+}
+
+/* generate UUID version 1: time, clock and node based */
+static uuid_rc_t uuid_generate_v1(uuid_t *uuid, unsigned int mode, va_list ap)
+{
+    /* brand with version and variant */
+    uuid_brand(uuid, 1);
+
+    /* FIXME */
+
+    return UUID_RC_OK;
+}
+
+/* generate UUID version 3: name based */
+static uuid_rc_t uuid_generate_v3(uuid_t *uuid, unsigned int mode, va_list ap)
+{
+    /* brand with version and variant */
+    uuid_brand(uuid, 3);
+
+    /* FIXME */
+
+    return UUID_RC_OK;
+}
+
+/* generate UUID version 4: random number based */
+static uuid_rc_t uuid_generate_v4(uuid_t *uuid, unsigned int mode, va_list ap)
+{
+    /* fill with random data */
+    uuid_prng_getdata((void *)uuid, sizeof(uuid_t));
+
+    /* brand with version and variant */
+    uuid_brand(uuid, 4);
+
+    return UUID_RC_OK;
+}
+
 uuid_rc_t uuid_generate(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);
-    /* FIXME */
+    if (mode & UUID_VERSION1)
+        rc = uuid_generate_v1(uuid, mode, ap);
+    else if (mode & UUID_VERSION3)
+        rc = uuid_generate_v3(uuid, mode, ap);
+    else if (mode & UUID_VERSION4)
+        rc = uuid_generate_v4(uuid, mode, ap);
+    else
+        rc = UUID_RC_ARG;
     va_end(ap);
-    return UUID_RC_OK;
+
+    return rc;
 }
 
 uuid_rc_t uuid_dump(uuid_t *uuid, char **str)

CVSTrac 2.0.1