Home | History | Annotate | Download | only in uuid
      1 /*
      2  * gen_uuid.c --- generate a DCE-compatible uuid
      3  *
      4  * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
      5  *
      6  * %Begin-Header%
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, and the entire permission notice in its entirety,
     12  *    including the disclaimer of warranties.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote
     17  *    products derived from this software without specific prior
     18  *    written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
     21  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
     23  * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
     24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
     26  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     27  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
     30  * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
     31  * DAMAGE.
     32  * %End-Header%
     33  */
     34 
     35 /*
     36  * Force inclusion of SVID stuff since we need it if we're compiling in
     37  * gcc-wall wall mode
     38  */
     39 #define _SVID_SOURCE
     40 #define _DEFAULT_SOURCE	  /* since glibc 2.20 _SVID_SOURCE is deprecated */
     41 
     42 #include "config.h"
     43 
     44 #ifdef _WIN32
     45 #define _WIN32_WINNT 0x0500
     46 #include <windows.h>
     47 #define UUID MYUUID
     48 #endif
     49 #include <stdio.h>
     50 #ifdef HAVE_UNISTD_H
     51 #include <unistd.h>
     52 #endif
     53 #ifdef HAVE_STDLIB_H
     54 #include <stdlib.h>
     55 #endif
     56 #include <string.h>
     57 #include <fcntl.h>
     58 #include <errno.h>
     59 #include <sys/types.h>
     60 #ifdef HAVE_SYS_TIME_H
     61 #include <sys/time.h>
     62 #endif
     63 #include <sys/wait.h>
     64 #include <sys/stat.h>
     65 #ifdef HAVE_SYS_FILE_H
     66 #include <sys/file.h>
     67 #endif
     68 #ifdef HAVE_SYS_IOCTL_H
     69 #include <sys/ioctl.h>
     70 #endif
     71 #ifdef HAVE_SYS_SOCKET_H
     72 #include <sys/socket.h>
     73 #endif
     74 #ifdef HAVE_SYS_UN_H
     75 #include <sys/un.h>
     76 #endif
     77 #ifdef HAVE_SYS_SOCKIO_H
     78 #include <sys/sockio.h>
     79 #endif
     80 #ifdef HAVE_NET_IF_H
     81 #include <net/if.h>
     82 #endif
     83 #ifdef HAVE_NETINET_IN_H
     84 #include <netinet/in.h>
     85 #endif
     86 #ifdef HAVE_NET_IF_DL_H
     87 #include <net/if_dl.h>
     88 #endif
     89 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
     90 #include <sys/syscall.h>
     91 #endif
     92 #ifdef HAVE_SYS_RESOURCE_H
     93 #include <sys/resource.h>
     94 #endif
     95 
     96 #include "uuidP.h"
     97 #include "uuidd.h"
     98 
     99 #ifdef HAVE_SRANDOM
    100 #define srand(x) 	srandom(x)
    101 #define rand() 		random()
    102 #endif
    103 
    104 #ifdef TLS
    105 #define THREAD_LOCAL static TLS
    106 #else
    107 #define THREAD_LOCAL static
    108 #endif
    109 
    110 #if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
    111 #define DO_JRAND_MIX
    112 THREAD_LOCAL unsigned short jrand_seed[3];
    113 #endif
    114 
    115 #ifdef _WIN32
    116 static void gettimeofday (struct timeval *tv, void *dummy)
    117 {
    118 	FILETIME	ftime;
    119 	uint64_t	n;
    120 
    121 	GetSystemTimeAsFileTime (&ftime);
    122 	n = (((uint64_t) ftime.dwHighDateTime << 32)
    123 	     + (uint64_t) ftime.dwLowDateTime);
    124 	if (n) {
    125 		n /= 10;
    126 		n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000;
    127 	}
    128 
    129 	tv->tv_sec = n / 1000000;
    130 	tv->tv_usec = n % 1000000;
    131 }
    132 
    133 static int getuid (void)
    134 {
    135 	return 1;
    136 }
    137 #endif
    138 
    139 static int get_random_fd(void)
    140 {
    141 	struct timeval	tv;
    142 	static int	fd = -2;
    143 	int		i;
    144 
    145 	if (fd == -2) {
    146 		gettimeofday(&tv, 0);
    147 #ifndef _WIN32
    148 		fd = open("/dev/urandom", O_RDONLY);
    149 		if (fd == -1)
    150 			fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
    151 		if (fd >= 0) {
    152 			i = fcntl(fd, F_GETFD);
    153 			if (i >= 0)
    154 				fcntl(fd, F_SETFD, i | FD_CLOEXEC);
    155 		}
    156 #endif
    157 		srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
    158 #ifdef DO_JRAND_MIX
    159 		jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
    160 		jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
    161 		jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
    162 #endif
    163 	}
    164 	/* Crank the random number generator a few times */
    165 	gettimeofday(&tv, 0);
    166 	for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
    167 		rand();
    168 	return fd;
    169 }
    170 
    171 
    172 /*
    173  * Generate a series of random bytes.  Use /dev/urandom if possible,
    174  * and if not, use srandom/random.
    175  */
    176 static void get_random_bytes(void *buf, int nbytes)
    177 {
    178 	int i, n = nbytes, fd = get_random_fd();
    179 	int lose_counter = 0;
    180 	unsigned char *cp = buf;
    181 
    182 	if (fd >= 0) {
    183 		while (n > 0) {
    184 			i = read(fd, cp, n);
    185 			if (i <= 0) {
    186 				if (lose_counter++ > 16)
    187 					break;
    188 				continue;
    189 			}
    190 			n -= i;
    191 			cp += i;
    192 			lose_counter = 0;
    193 		}
    194 	}
    195 
    196 	/*
    197 	 * We do this all the time, but this is the only source of
    198 	 * randomness if /dev/random/urandom is out to lunch.
    199 	 */
    200 	for (cp = buf, i = 0; i < nbytes; i++)
    201 		*cp++ ^= (rand() >> 7) & 0xFF;
    202 #ifdef DO_JRAND_MIX
    203 	{
    204 		unsigned short tmp_seed[3];
    205 
    206 		memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed));
    207 		jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid);
    208 		for (cp = buf, i = 0; i < nbytes; i++)
    209 			*cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
    210 		memcpy(jrand_seed, tmp_seed,
    211 		       sizeof(jrand_seed) - sizeof(unsigned short));
    212 	}
    213 #endif
    214 
    215 	return;
    216 }
    217 
    218 /*
    219  * Get the ethernet hardware address, if we can find it...
    220  *
    221  * XXX for a windows version, probably should use GetAdaptersInfo:
    222  * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451
    223  * commenting out get_node_id just to get gen_uuid to compile under windows
    224  * is not the right way to go!
    225  */
    226 static int get_node_id(unsigned char *node_id)
    227 {
    228 #ifdef HAVE_NET_IF_H
    229 	int 		sd;
    230 	struct ifreq 	ifr, *ifrp;
    231 	struct ifconf 	ifc;
    232 	char buf[1024];
    233 	int		n, i;
    234 	unsigned char 	*a;
    235 #ifdef HAVE_NET_IF_DL_H
    236 	struct sockaddr_dl *sdlp;
    237 #endif
    238 
    239 /*
    240  * BSD 4.4 defines the size of an ifreq to be
    241  * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
    242  * However, under earlier systems, sa_len isn't present, so the size is
    243  * just sizeof(struct ifreq)
    244  */
    245 #ifdef HAVE_SA_LEN
    246 #ifndef max
    247 #define max(a,b) ((a) > (b) ? (a) : (b))
    248 #endif
    249 #define ifreq_size(i) max(sizeof(struct ifreq),\
    250      sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
    251 #else
    252 #define ifreq_size(i) sizeof(struct ifreq)
    253 #endif /* HAVE_SA_LEN*/
    254 
    255 	sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
    256 	if (sd < 0) {
    257 		return -1;
    258 	}
    259 	memset(buf, 0, sizeof(buf));
    260 	ifc.ifc_len = sizeof(buf);
    261 	ifc.ifc_buf = buf;
    262 	if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
    263 		close(sd);
    264 		return -1;
    265 	}
    266 	n = ifc.ifc_len;
    267 	for (i = 0; i < n; i+= ifreq_size(*ifrp) ) {
    268 		ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
    269 		strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
    270 #ifdef SIOCGIFHWADDR
    271 		if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
    272 			continue;
    273 		a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
    274 #else
    275 #ifdef SIOCGENADDR
    276 		if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
    277 			continue;
    278 		a = (unsigned char *) ifr.ifr_enaddr;
    279 #else
    280 #ifdef HAVE_NET_IF_DL_H
    281 		sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr;
    282 		if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6))
    283 			continue;
    284 		a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen];
    285 #else
    286 		/*
    287 		 * XXX we don't have a way of getting the hardware
    288 		 * address
    289 		 */
    290 		close(sd);
    291 		return 0;
    292 #endif /* HAVE_NET_IF_DL_H */
    293 #endif /* SIOCGENADDR */
    294 #endif /* SIOCGIFHWADDR */
    295 		if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
    296 			continue;
    297 		if (node_id) {
    298 			memcpy(node_id, a, 6);
    299 			close(sd);
    300 			return 1;
    301 		}
    302 	}
    303 	close(sd);
    304 #endif
    305 	return 0;
    306 }
    307 
    308 /* Assume that the gettimeofday() has microsecond granularity */
    309 #define MAX_ADJUSTMENT 10
    310 
    311 static int get_clock(uint32_t *clock_high, uint32_t *clock_low,
    312 		     uint16_t *ret_clock_seq, int *num)
    313 {
    314 	THREAD_LOCAL int		adjustment = 0;
    315 	THREAD_LOCAL struct timeval	last = {0, 0};
    316 	THREAD_LOCAL int		state_fd = -2;
    317 	THREAD_LOCAL FILE		*state_f;
    318 	THREAD_LOCAL uint16_t		clock_seq;
    319 	struct timeval 			tv;
    320 	struct flock			fl;
    321 	uint64_t			clock_reg;
    322 	mode_t				save_umask;
    323 	int				len;
    324 
    325 	if (state_fd == -2) {
    326 		save_umask = umask(0);
    327 		state_fd = open("/var/lib/libuuid/clock.txt",
    328 				O_RDWR|O_CREAT, 0660);
    329 		(void) umask(save_umask);
    330 		if (state_fd >= 0) {
    331 			state_f = fdopen(state_fd, "r+");
    332 			if (!state_f) {
    333 				close(state_fd);
    334 				state_fd = -1;
    335 			}
    336 		}
    337 	}
    338 	fl.l_type = F_WRLCK;
    339 	fl.l_whence = SEEK_SET;
    340 	fl.l_start = 0;
    341 	fl.l_len = 0;
    342 	fl.l_pid = 0;
    343 	if (state_fd >= 0) {
    344 		rewind(state_f);
    345 		while (fcntl(state_fd, F_SETLKW, &fl) < 0) {
    346 			if ((errno == EAGAIN) || (errno == EINTR))
    347 				continue;
    348 			fclose(state_f);
    349 			state_fd = -1;
    350 			break;
    351 		}
    352 	}
    353 	if (state_fd >= 0) {
    354 		unsigned int cl;
    355 		unsigned long tv1, tv2;
    356 		int a;
    357 
    358 		if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n",
    359 			   &cl, &tv1, &tv2, &a) == 4) {
    360 			clock_seq = cl & 0x3FFF;
    361 			last.tv_sec = tv1;
    362 			last.tv_usec = tv2;
    363 			adjustment = a;
    364 		}
    365 	}
    366 
    367 	if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
    368 		get_random_bytes(&clock_seq, sizeof(clock_seq));
    369 		clock_seq &= 0x3FFF;
    370 		gettimeofday(&last, 0);
    371 		last.tv_sec--;
    372 	}
    373 
    374 try_again:
    375 	gettimeofday(&tv, 0);
    376 	if ((tv.tv_sec < last.tv_sec) ||
    377 	    ((tv.tv_sec == last.tv_sec) &&
    378 	     (tv.tv_usec < last.tv_usec))) {
    379 		clock_seq = (clock_seq+1) & 0x3FFF;
    380 		adjustment = 0;
    381 		last = tv;
    382 	} else if ((tv.tv_sec == last.tv_sec) &&
    383 	    (tv.tv_usec == last.tv_usec)) {
    384 		if (adjustment >= MAX_ADJUSTMENT)
    385 			goto try_again;
    386 		adjustment++;
    387 	} else {
    388 		adjustment = 0;
    389 		last = tv;
    390 	}
    391 
    392 	clock_reg = tv.tv_usec*10 + adjustment;
    393 	clock_reg += ((uint64_t) tv.tv_sec)*10000000;
    394 	clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000;
    395 
    396 	if (num && (*num > 1)) {
    397 		adjustment += *num - 1;
    398 		last.tv_usec += adjustment / 10;
    399 		adjustment = adjustment % 10;
    400 		last.tv_sec += last.tv_usec / 1000000;
    401 		last.tv_usec = last.tv_usec % 1000000;
    402 	}
    403 
    404 	if (state_fd > 0) {
    405 		rewind(state_f);
    406 		len = fprintf(state_f,
    407 			      "clock: %04x tv: %016lu %08lu adj: %08d\n",
    408 			      clock_seq, last.tv_sec, (long)last.tv_usec,
    409 			      adjustment);
    410 		fflush(state_f);
    411 		if (ftruncate(state_fd, len) < 0) {
    412 			fprintf(state_f, "                   \n");
    413 			fflush(state_f);
    414 		}
    415 		rewind(state_f);
    416 		fl.l_type = F_UNLCK;
    417 		if (fcntl(state_fd, F_SETLK, &fl) < 0) {
    418 			fclose(state_f);
    419 			state_fd = -1;
    420 		}
    421 	}
    422 
    423 	*clock_high = clock_reg >> 32;
    424 	*clock_low = clock_reg;
    425 	*ret_clock_seq = clock_seq;
    426 	return 0;
    427 }
    428 
    429 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
    430 static ssize_t read_all(int fd, char *buf, size_t count)
    431 {
    432 	ssize_t ret;
    433 	ssize_t c = 0;
    434 	int tries = 0;
    435 
    436 	memset(buf, 0, count);
    437 	while (count > 0) {
    438 		ret = read(fd, buf, count);
    439 		if (ret <= 0) {
    440 			if ((errno == EAGAIN || errno == EINTR || ret == 0) &&
    441 			    (tries++ < 5))
    442 				continue;
    443 			return c ? c : -1;
    444 		}
    445 		if (ret > 0)
    446 			tries = 0;
    447 		count -= ret;
    448 		buf += ret;
    449 		c += ret;
    450 	}
    451 	return c;
    452 }
    453 
    454 /*
    455  * Close all file descriptors
    456  */
    457 static void close_all_fds(void)
    458 {
    459 	int i, max;
    460 
    461 #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
    462 	max = sysconf(_SC_OPEN_MAX);
    463 #elif defined(HAVE_GETDTABLESIZE)
    464 	max = getdtablesize();
    465 #elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
    466 	struct rlimit rl;
    467 
    468 	getrlimit(RLIMIT_NOFILE, &rl);
    469 	max = rl.rlim_cur;
    470 #else
    471 	max = OPEN_MAX;
    472 #endif
    473 
    474 	for (i=0; i < max; i++) {
    475 		close(i);
    476 		if (i <= 2)
    477 			open("/dev/null", O_RDWR);
    478 	}
    479 }
    480 #endif /* defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) */
    481 
    482 #pragma GCC diagnostic push
    483 #if !defined(USE_UUIDD) || !defined(HAVE_SYS_UN_H)
    484 #pragma GCC diagnostic ignored "-Wunused-parameter"
    485 #endif
    486 /*
    487  * Try using the uuidd daemon to generate the UUID
    488  *
    489  * Returns 0 on success, non-zero on failure.
    490  */
    491 static int get_uuid_via_daemon(int op, uuid_t out, int *num)
    492 {
    493 #if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H)
    494 	char op_buf[64];
    495 	int op_len;
    496 	int s;
    497 	ssize_t ret;
    498 	int32_t reply_len = 0, expected = 16;
    499 	struct sockaddr_un srv_addr;
    500 	struct stat st;
    501 	pid_t pid;
    502 	static const char *uuidd_path = UUIDD_PATH;
    503 	static int access_ret = -2;
    504 	static int start_attempts = 0;
    505 
    506 	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    507 		return -1;
    508 
    509 	srv_addr.sun_family = AF_UNIX;
    510 	strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH);
    511 
    512 	if (connect(s, (const struct sockaddr *) &srv_addr,
    513 		    sizeof(struct sockaddr_un)) < 0) {
    514 		if (access_ret == -2)
    515 			access_ret = access(uuidd_path, X_OK);
    516 		if (access_ret == 0)
    517 			access_ret = stat(uuidd_path, &st);
    518 		if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0)
    519 			access_ret = access(UUIDD_DIR, W_OK);
    520 		if (access_ret == 0 && start_attempts++ < 5) {
    521 			if ((pid = fork()) == 0) {
    522 				close_all_fds();
    523 				execl(uuidd_path, "uuidd", "-qT", "300",
    524 				      (char *) NULL);
    525 				exit(1);
    526 			}
    527 			(void) waitpid(pid, 0, 0);
    528 			if (connect(s, (const struct sockaddr *) &srv_addr,
    529 				    sizeof(struct sockaddr_un)) < 0)
    530 				goto fail;
    531 		} else
    532 			goto fail;
    533 	}
    534 	op_buf[0] = op;
    535 	op_len = 1;
    536 	if (op == UUIDD_OP_BULK_TIME_UUID) {
    537 		memcpy(op_buf+1, num, sizeof(*num));
    538 		op_len += sizeof(*num);
    539 		expected += sizeof(*num);
    540 	}
    541 
    542 	ret = write(s, op_buf, op_len);
    543 	if (ret < 1)
    544 		goto fail;
    545 
    546 	ret = read_all(s, (char *) &reply_len, sizeof(reply_len));
    547 	if (ret < 0)
    548 		goto fail;
    549 
    550 	if (reply_len != expected)
    551 		goto fail;
    552 
    553 	ret = read_all(s, op_buf, reply_len);
    554 
    555 	if (op == UUIDD_OP_BULK_TIME_UUID)
    556 		memcpy(op_buf+16, num, sizeof(int));
    557 
    558 	memcpy(out, op_buf, 16);
    559 
    560 	close(s);
    561 	return ((ret == expected) ? 0 : -1);
    562 
    563 fail:
    564 	close(s);
    565 #endif
    566 	return -1;
    567 }
    568 #pragma GCC diagnostic pop
    569 
    570 void uuid__generate_time(uuid_t out, int *num)
    571 {
    572 	static unsigned char node_id[6];
    573 	static int has_init = 0;
    574 	struct uuid uu;
    575 	uint32_t	clock_mid;
    576 
    577 	if (!has_init) {
    578 		if (get_node_id(node_id) <= 0) {
    579 			get_random_bytes(node_id, 6);
    580 			/*
    581 			 * Set multicast bit, to prevent conflicts
    582 			 * with IEEE 802 addresses obtained from
    583 			 * network cards
    584 			 */
    585 			node_id[0] |= 0x01;
    586 		}
    587 		has_init = 1;
    588 	}
    589 	get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num);
    590 	uu.clock_seq |= 0x8000;
    591 	uu.time_mid = (uint16_t) clock_mid;
    592 	uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000;
    593 	memcpy(uu.node, node_id, 6);
    594 	uuid_pack(&uu, out);
    595 }
    596 
    597 void uuid_generate_time(uuid_t out)
    598 {
    599 #ifdef TLS
    600 	THREAD_LOCAL int		num = 0;
    601 	THREAD_LOCAL struct uuid	uu;
    602 	THREAD_LOCAL time_t		last_time = 0;
    603 	time_t				now;
    604 
    605 	if (num > 0) {
    606 		now = time(0);
    607 		if (now > last_time+1)
    608 			num = 0;
    609 	}
    610 	if (num <= 0) {
    611 		num = 1000;
    612 		if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID,
    613 					out, &num) == 0) {
    614 			last_time = time(0);
    615 			uuid_unpack(out, &uu);
    616 			num--;
    617 			return;
    618 		}
    619 		num = 0;
    620 	}
    621 	if (num > 0) {
    622 		uu.time_low++;
    623 		if (uu.time_low == 0) {
    624 			uu.time_mid++;
    625 			if (uu.time_mid == 0)
    626 				uu.time_hi_and_version++;
    627 		}
    628 		num--;
    629 		uuid_pack(&uu, out);
    630 		return;
    631 	}
    632 #else
    633 	if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0)
    634 		return;
    635 #endif
    636 
    637 	uuid__generate_time(out, 0);
    638 }
    639 
    640 
    641 void uuid__generate_random(uuid_t out, int *num)
    642 {
    643 	uuid_t	buf;
    644 	struct uuid uu;
    645 	int i, n;
    646 
    647 	if (!num || !*num)
    648 		n = 1;
    649 	else
    650 		n = *num;
    651 
    652 	for (i = 0; i < n; i++) {
    653 		get_random_bytes(buf, sizeof(buf));
    654 		uuid_unpack(buf, &uu);
    655 
    656 		uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
    657 		uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF)
    658 			| 0x4000;
    659 		uuid_pack(&uu, out);
    660 		out += sizeof(uuid_t);
    661 	}
    662 }
    663 
    664 void uuid_generate_random(uuid_t out)
    665 {
    666 	int	num = 1;
    667 	/* No real reason to use the daemon for random uuid's -- yet */
    668 
    669 	uuid__generate_random(out, &num);
    670 }
    671 
    672 
    673 /*
    674  * This is the generic front-end to uuid_generate_random and
    675  * uuid_generate_time.  It uses uuid_generate_random only if
    676  * /dev/urandom is available, since otherwise we won't have
    677  * high-quality randomness.
    678  */
    679 void uuid_generate(uuid_t out)
    680 {
    681 	if (get_random_fd() >= 0)
    682 		uuid_generate_random(out);
    683 	else
    684 		uuid_generate_time(out);
    685 }
    686