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