Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:20

0001 /*
0002  * gen_uuid.c --- generate a DCE-compatible uuid
0003  *
0004  * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
0005  *
0006  * %Begin-Header%
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, and the entire permission notice in its entirety,
0012  *    including the disclaimer of warranties.
0013  * 2. Redistributions in binary form must reproduce the above copyright
0014  *    notice, this list of conditions and the following disclaimer in the
0015  *    documentation and/or other materials provided with the distribution.
0016  * 3. The name of the author may not be used to endorse or promote
0017  *    products derived from this software without specific prior
0018  *    written permission.
0019  *
0020  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
0021  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0022  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
0023  * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
0024  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0025  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0026  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
0027  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0029  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
0030  * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
0031  * DAMAGE.
0032  * %End-Header%
0033  */
0034 
0035 #ifdef HAVE_CONFIG_H
0036 #include "config.h"
0037 #endif
0038 
0039 /*
0040  * Force inclusion of SVID stuff since we need it if we're compiling in
0041  * gcc-wall wall mode
0042  */
0043 #define _SVID_SOURCE
0044 
0045 #ifdef _WIN32
0046 #define _WIN32_WINNT 0x0500
0047 #include <windows.h>
0048 #define UUID MYUUID
0049 #endif
0050 #include <stdio.h>
0051 #include <limits.h> /* for CHAR_BIT */
0052 #ifdef HAVE_UNISTD_H
0053 #include <unistd.h>
0054 #endif
0055 #ifdef HAVE_STDLIB_H
0056 #include <stdlib.h>
0057 #endif
0058 #include <string.h>
0059 #include <fcntl.h>
0060 #include <errno.h>
0061 #include <sys/types.h>
0062 #ifdef HAVE_SYS_TIME_H
0063 #include <sys/time.h>
0064 #endif
0065 #include <sys/wait.h>
0066 #include <sys/stat.h>
0067 #ifdef HAVE_SYS_FILE_H
0068 #include <sys/file.h>
0069 #endif
0070 #ifdef HAVE_SYS_IOCTL_H
0071 #include <sys/ioctl.h>
0072 #endif
0073 #ifdef HAVE_SYS_SOCKET_H
0074 #include <sys/socket.h>
0075 #endif
0076 #ifdef HAVE_SYS_UN_H
0077 #include <sys/un.h>
0078 #endif
0079 #ifdef HAVE_SYS_SOCKIO_H
0080 #include <sys/sockio.h>
0081 #endif
0082 #ifdef HAVE_NET_IF_H
0083 #include <net/if.h>
0084 #endif
0085 #ifdef HAVE_NETINET_IN_H
0086 #include <netinet/in.h>
0087 #endif
0088 #ifdef HAVE_NET_IF_DL_H
0089 #include <net/if_dl.h>
0090 #endif
0091 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
0092 #include <sys/syscall.h>
0093 #endif
0094 #ifdef HAVE_SYS_RESOURCE_H
0095 #include <sys/resource.h>
0096 #endif
0097 
0098 #if SIZEOF_TIME_T == 8
0099 #define PRIutime_t  PRIu64
0100 #define SCNutime_t  SCNu64
0101 #define utime_t     uint64_t
0102 #elif SIZEOF_TIME_T == 4
0103 #define PRIutime_t  PRIu32
0104 #define SCNutime_t  SCNu32
0105 #define utime_t     uint32_t
0106 #else
0107 #error "unsupport size of time_t"
0108 #endif
0109 
0110 #include "uuidP.h"
0111 #include "uuidd.h"
0112 
0113 #ifdef HAVE_SRANDOM
0114 #define srand(x)    srandom(x)
0115 #define rand()      random()
0116 #endif
0117 
0118 #ifdef TLS
0119 #define THREAD_LOCAL static TLS
0120 #else
0121 #define THREAD_LOCAL static
0122 #endif
0123 
0124 #if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
0125 #define DO_JRAND_MIX
0126 THREAD_LOCAL unsigned short jrand_seed[3];
0127 #endif
0128 
0129 #ifdef _WIN32
0130 static void gettimeofday (struct timeval *__restrict tv, void *__restrict dummy)
0131 {
0132     FILETIME    ftime;
0133     uint64_t    n;
0134 
0135     GetSystemTimeAsFileTime (&ftime);
0136     n = (((uint64_t) ftime.dwHighDateTime << 32)
0137          + (uint64_t) ftime.dwLowDateTime);
0138     if (n) {
0139         n /= 10;
0140         n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000;
0141     }
0142 
0143     tv->tv_sec = n / 1000000;
0144     tv->tv_usec = n % 1000000;
0145 }
0146 
0147 static int getuid (void)
0148 {
0149     return 1;
0150 }
0151 #endif
0152 
0153 static int get_random_fd(void)
0154 {
0155     struct timeval  tv;
0156     static int  fd = -2;
0157     int     i;
0158 
0159     if (fd == -2) {
0160         gettimeofday(&tv, 0);
0161 #ifndef _WIN32
0162         fd = open("/dev/urandom", O_RDONLY);
0163         if (fd == -1)
0164             fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
0165         if (fd >= 0) {
0166             i = fcntl(fd, F_GETFD);
0167             if (i >= 0)
0168             #ifdef __rtems__
0169                 (void)
0170             #endif
0171                 fcntl(fd, F_SETFD, i | FD_CLOEXEC);
0172         }
0173 #endif
0174 #ifdef __rtems__
0175         srand((((time_t)getpid()) << ((sizeof(pid_t)*CHAR_BIT)>>1)) ^ getuid()
0176               ^ tv.tv_sec ^ tv.tv_usec);
0177 #else
0178         srand((getpid() << ((sizeof(pid_t)*CHAR_BIT)>>1)) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
0179 #endif
0180 #ifdef DO_JRAND_MIX
0181         jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
0182         jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
0183         jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
0184 #endif
0185     }
0186     /* Crank the random number generator a few times */
0187     gettimeofday(&tv, 0);
0188     for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
0189         rand();
0190     return fd;
0191 }
0192 
0193 
0194 /*
0195  * Generate a series of random bytes.  Use /dev/urandom if possible,
0196  * and if not, use srandom/random.
0197  */
0198 static void get_random_bytes(void *buf, int nbytes)
0199 {
0200     int i, n = nbytes, fd = get_random_fd();
0201     int lose_counter = 0;
0202     unsigned char *cp = (unsigned char *) buf;
0203 #ifdef DO_JRAND_MIX
0204     unsigned short tmp_seed[3];
0205 #endif
0206 
0207     if (fd >= 0) {
0208         while (n > 0) {
0209             i = read(fd, cp, n);
0210             if (i <= 0) {
0211                 if (lose_counter++ > 16)
0212                     break;
0213                 continue;
0214             }
0215             n -= i;
0216             cp += i;
0217             lose_counter = 0;
0218         }
0219     }
0220 
0221     /*
0222      * We do this all the time, but this is the only source of
0223      * randomness if /dev/random/urandom is out to lunch.
0224      */
0225     for (cp = buf, i = 0; i < nbytes; i++)
0226         *cp++ ^= (rand() >> 7) & 0xFF;
0227 #ifdef DO_JRAND_MIX
0228     memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed));
0229     jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid);
0230     for (cp = buf, i = 0; i < nbytes; i++)
0231         *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
0232     memcpy(jrand_seed, tmp_seed,
0233            sizeof(jrand_seed)-sizeof(unsigned short));
0234 #endif
0235 
0236     return;
0237 }
0238 
0239 /*
0240  * Get the ethernet hardware address, if we can find it...
0241  *
0242  * XXX for a windows version, probably should use GetAdaptersInfo:
0243  * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451
0244  * commenting out get_node_id just to get gen_uuid to compile under windows
0245  * is not the right way to go!
0246  */
0247 static int get_node_id(unsigned char *node_id)
0248 {
0249 #ifdef HAVE_NET_IF_H
0250     int         sd;
0251     struct ifreq    ifr, *ifrp;
0252     struct ifconf   ifc;
0253     char buf[1024];
0254     int     n, i;
0255     unsigned char   *a;
0256 #ifdef HAVE_NET_IF_DL_H
0257     struct sockaddr_dl *sdlp;
0258 #endif
0259 
0260 /*
0261  * BSD 4.4 defines the size of an ifreq to be
0262  * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
0263  * However, under earlier systems, sa_len isn't present, so the size is
0264  * just sizeof(struct ifreq)
0265  */
0266 #ifdef HAVE_SA_LEN
0267 #ifndef max
0268 #define max(a,b) ((a) > (b) ? (a) : (b))
0269 #endif
0270 #define ifreq_size(i) max(sizeof(struct ifreq),\
0271      sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
0272 #else
0273 #define ifreq_size(i) sizeof(struct ifreq)
0274 #endif /* HAVE_SA_LEN*/
0275 
0276     sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
0277     if (sd < 0) {
0278         return -1;
0279     }
0280     memset(buf, 0, sizeof(buf));
0281     ifc.ifc_len = sizeof(buf);
0282     ifc.ifc_buf = buf;
0283     if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
0284         close(sd);
0285         return -1;
0286     }
0287     n = ifc.ifc_len;
0288     for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
0289         ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
0290         strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
0291 #ifdef SIOCGIFHWADDR
0292         if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
0293             continue;
0294         a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
0295 #else
0296 #ifdef SIOCGENADDR
0297         if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
0298             continue;
0299         a = (unsigned char *) ifr.ifr_enaddr;
0300 #else
0301 #ifdef HAVE_NET_IF_DL_H
0302         sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
0303         if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
0304             continue;
0305         a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
0306 #else
0307         /*
0308          * XXX we don't have a way of getting the hardware
0309          * address
0310          */
0311         close(sd);
0312         return 0;
0313 #endif /* HAVE_NET_IF_DL_H */
0314 #endif /* SIOCGENADDR */
0315 #endif /* SIOCGIFHWADDR */
0316         if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
0317             continue;
0318         if (node_id) {
0319             memcpy(node_id, a, 6);
0320             close(sd);
0321             return 1;
0322         }
0323     }
0324     close(sd);
0325 #endif
0326     return 0;
0327 }
0328 
0329 /* Assume that the gettimeofday() has microsecond granularity */
0330 #define MAX_ADJUSTMENT 10
0331 
0332 static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
0333              uint16_t *ret_clock_seq, int *num)
0334 {
0335     THREAD_LOCAL int        adjustment = 0;
0336     THREAD_LOCAL struct timeval last = {0, 0};
0337     THREAD_LOCAL int        state_fd = -2;
0338     THREAD_LOCAL FILE       *state_f;
0339     THREAD_LOCAL uint16_t       clock_seq;
0340     struct timeval          tv;
0341     struct flock            fl;
0342     uint64_t            clock_reg;
0343     mode_t              save_umask;
0344     int             len;
0345 
0346     if (state_fd == -2) {
0347         save_umask = umask(0);
0348         state_fd = open("/var/lib/libuuid/clock.txt",
0349                 O_RDWR|O_CREAT, 0660);
0350         (void) umask(save_umask);
0351 #ifdef __rtems__
0352         if (state_fd >= 0) {
0353 #endif
0354         state_f = fdopen(state_fd, "r+");
0355         if (!state_f) {
0356             close(state_fd);
0357             state_fd = -1;
0358         }
0359 #ifdef __rtems__
0360         }
0361 #endif
0362     }
0363     fl.l_type = F_WRLCK;
0364     fl.l_whence = SEEK_SET;
0365     fl.l_start = 0;
0366     fl.l_len = 0;
0367     fl.l_pid = 0;
0368     if (state_fd >= 0) {
0369         rewind(state_f);
0370         while (fcntl(state_fd, F_SETLKW, &fl) < 0) {
0371             if ((errno == EAGAIN) || (errno == EINTR))
0372                 continue;
0373             fclose(state_f);
0374             close(state_fd);
0375             state_fd = -1;
0376             break;
0377         }
0378     }
0379     if (state_fd >= 0) {
0380         unsigned int cl;
0381         utime_t tv1;
0382         unsigned long tv2;
0383         int a;
0384 
0385         if (fscanf(state_f, "clock: %04x tv: %" SCNutime_t " %lu adj: %d\n",
0386                &cl, &tv1, &tv2, &a) == 4) {
0387             clock_seq = cl & 0x3FFF;
0388             last.tv_sec = tv1;
0389             last.tv_usec = tv2;
0390             adjustment = a;
0391         }
0392     }
0393 
0394     if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
0395         get_random_bytes(&clock_seq, sizeof(clock_seq));
0396         clock_seq &= 0x3FFF;
0397         gettimeofday(&last, 0);
0398         last.tv_sec--;
0399     }
0400 
0401 try_again:
0402     gettimeofday(&tv, 0);
0403     if ((tv.tv_sec < last.tv_sec) ||
0404         ((tv.tv_sec == last.tv_sec) &&
0405          (tv.tv_usec < last.tv_usec))) {
0406         clock_seq = (clock_seq+1) & 0x3FFF;
0407         adjustment = 0;
0408         last = tv;
0409     } else if ((tv.tv_sec == last.tv_sec) &&
0410         (tv.tv_usec == last.tv_usec)) {
0411         if (adjustment >= MAX_ADJUSTMENT)
0412             goto try_again;
0413         adjustment++;
0414     } else {
0415         adjustment = 0;
0416         last = tv;
0417     }
0418 
0419     clock_reg = ((uint64_t) tv.tv_usec)*10 + adjustment;
0420     clock_reg += ((uint64_t) tv.tv_sec)*10000000;
0421     clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
0422 
0423     if (num && (*num > 1)) {
0424         adjustment += *num - 1;
0425         last.tv_usec += adjustment / 10;
0426         adjustment = adjustment % 10;
0427         last.tv_sec += last.tv_usec / 1000000;
0428         last.tv_usec = last.tv_usec % 1000000;
0429     }
0430 
0431     if (state_fd > 0) {
0432         rewind(state_f);
0433         len = fprintf(state_f,
0434                   "clock: %04x tv: %016" PRIutime_t " %08lu adj: %08d\n",
0435                   clock_seq, last.tv_sec, last.tv_usec, adjustment);
0436         fflush(state_f);
0437         if (ftruncate(state_fd, len) < 0) {
0438             fprintf(state_f, "                   \n");
0439             fflush(state_f);
0440         }
0441         rewind(state_f);
0442         fl.l_type = F_UNLCK;
0443     #ifdef __rtems__
0444         (void)
0445     #endif
0446         fcntl(state_fd, F_SETLK, &fl);
0447     }
0448 
0449     *clock_high = clock_reg >> 32;
0450     *clock_low = clock_reg;
0451     *ret_clock_seq = clock_seq;
0452     return 0;
0453 }
0454 
0455 /* unused */
0456 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
0457 static ssize_t read_all(int fd, char *buf, size_t count)
0458 {
0459     ssize_t ret;
0460     ssize_t c = 0;
0461 
0462     memset(buf, 0, count);
0463     while (count > 0) {
0464         ret = read(fd, buf, count);
0465         if (ret < 0) {
0466             if ((errno == EAGAIN) || (errno == EINTR))
0467                 continue;
0468             return -1;
0469         }
0470         count -= ret;
0471         buf += ret;
0472         c += ret;
0473     }
0474     return c;
0475 }
0476 #endif
0477 
0478 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
0479 
0480 /*
0481  * Close all file descriptors
0482  */
0483 static void close_all_fds(void)
0484 {
0485     int i, max;
0486 
0487 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
0488     max = sysconf(_SC_OPEN_MAX);
0489 #elif defined(HAVE_GETDTABLESIZE)
0490     max = getdtablesize();
0491 #elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
0492     struct rlimit rl;
0493 
0494     getrlimit(RLIMIT_NOFILE, &rl);
0495     max = rl.rlim_cur;
0496 #else
0497     max = OPEN_MAX;
0498 #endif
0499 
0500     for (i=0; i < max; i++)
0501         close(i);
0502 }
0503 
0504 #endif
0505 
0506 
0507 /*
0508  * Try using the uuidd daemon to generate the UUID
0509  *
0510  * Returns 0 on success, non-zero on failure.
0511  */
0512 static int get_uuid_via_daemon(int op, uuid_t out, int *num)
0513 {
0514 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
0515     char op_buf[64];
0516     int op_len;
0517     int s;
0518     ssize_t ret;
0519     int32_t reply_len = 0, expected = 16;
0520     struct sockaddr_un srv_addr;
0521     pid_t pid;
0522     static const char *uuidd_path = UUIDD_PATH;
0523     static int access_ret = -2;
0524     static int start_attempts = 0;
0525 
0526     if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
0527         return -1;
0528 
0529     srv_addr.sun_family = AF_UNIX;
0530     strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH);
0531 
0532     if (connect(s, (const struct sockaddr *) &srv_addr,
0533             sizeof(struct sockaddr_un)) < 0) {
0534         if (access_ret == -2)
0535             access_ret = access(uuidd_path, X_OK);
0536         if (access_ret == 0 && start_attempts++ < 5) {
0537             if ((pid = fork()) == 0) {
0538                 close_all_fds();
0539                 execl(uuidd_path, "uuidd", "-qT", "300",
0540                       (char *) NULL);
0541                 exit(1);
0542             }
0543             (void) waitpid(pid, 0, 0);
0544             if (connect(s, (const struct sockaddr *) &srv_addr,
0545                     sizeof(struct sockaddr_un)) < 0)
0546                 goto fail;
0547         } else
0548             goto fail;
0549     }
0550     op_buf[0] = op;
0551     op_len = 1;
0552     if (op == UUIDD_OP_BULK_TIME_UUID) {
0553         memcpy(op_buf+1, num, sizeof(*num));
0554         op_len += sizeof(*num);
0555         expected += sizeof(*num);
0556     }
0557 
0558     ret = write(s, op_buf, op_len);
0559     if (ret < 1)
0560         goto fail;
0561 
0562     ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
0563     if (ret < 0)
0564         goto fail;
0565 
0566     if (reply_len != expected)
0567         goto fail;
0568 
0569     ret = read_all(s, op_buf, reply_len);
0570 
0571     if (op == UUIDD_OP_BULK_TIME_UUID)
0572         memcpy(op_buf+16, num, sizeof(int));
0573 
0574     memcpy(out, op_buf, 16);
0575 
0576     close(s);
0577     return ((ret == expected) ? 0 : -1);
0578 
0579 fail:
0580     close(s);
0581 #endif
0582     return -1;
0583 }
0584 
0585 void uuid__generate_time(uuid_t out, int *num)
0586 {
0587     static unsigned char node_id[6];
0588     static int has_init = 0;
0589     struct uuid uu;
0590     uint32_t    clock_mid;
0591 
0592     if (!has_init) {
0593         if (get_node_id(node_id) <= 0) {
0594             get_random_bytes(node_id, 6);
0595             /*
0596              * Set multicast bit, to prevent conflicts
0597              * with IEEE 802 addresses obtained from
0598              * network cards
0599              */
0600             node_id[0] |= 0x01;
0601         }
0602         has_init = 1;
0603     }
0604     get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num);
0605     uu.clock_seq |= 0x8000;
0606     uu.time_mid = (uint16_t) clock_mid;
0607     uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
0608     memcpy(uu.node, node_id, 6);
0609     uuid_pack(&uu, out);
0610 }
0611 
0612 void uuid_generate_time(uuid_t out)
0613 {
0614 #ifdef TLS
0615     THREAD_LOCAL int        num = 0;
0616     THREAD_LOCAL struct uuid    uu;
0617     THREAD_LOCAL time_t     last_time = 0;
0618     time_t              now;
0619 
0620     if (num > 0) {
0621         now = time(0);
0622         if (now > last_time+1)
0623             num = 0;
0624     }
0625     if (num <= 0) {
0626         num = 1000;
0627         if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID,
0628                     out, &num) == 0) {
0629             last_time = time(0);
0630             uuid_unpack(out, &uu);
0631             num--;
0632             return;
0633         }
0634         num = 0;
0635     }
0636     if (num > 0) {
0637         uu.time_low++;
0638         if (uu.time_low == 0) {
0639             uu.time_mid++;
0640             if (uu.time_mid == 0)
0641                 uu.time_hi_and_version++;
0642         }
0643         num--;
0644         uuid_pack(&uu, out);
0645         return;
0646     }
0647 #else
0648     if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0)
0649         return;
0650 #endif
0651 
0652     uuid__generate_time(out, 0);
0653 }
0654 
0655 
0656 void uuid__generate_random(uuid_t out, int *num)
0657 {
0658     uuid_t  buf;
0659     struct uuid uu;
0660     int i, n;
0661 
0662     if (!num || !*num)
0663         n = 1;
0664     else
0665         n = *num;
0666 
0667     for (i = 0; i < n; i++) {
0668         get_random_bytes(buf, sizeof(buf));
0669         uuid_unpack(buf, &uu);
0670 
0671         uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
0672         uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
0673             | 0x4000;
0674         uuid_pack(&uu, out);
0675         out += sizeof(uuid_t);
0676     }
0677 }
0678 
0679 void uuid_generate_random(uuid_t out)
0680 {
0681     int num = 1;
0682     /* No real reason to use the daemon for random uuid's -- yet */
0683 
0684     uuid__generate_random(out, &num);
0685 }
0686 
0687 
0688 /*
0689  * This is the generic front-end to uuid_generate_random and
0690  * uuid_generate_time.  It uses uuid_generate_random only if
0691  * /dev/urandom is available, since otherwise we won't have
0692  * high-quality randomness.
0693  */
0694 void uuid_generate(uuid_t out)
0695 {
0696     if (get_random_fd() >= 0)
0697         uuid_generate_random(out);
0698     else
0699         uuid_generate_time(out);
0700 }