xref: /titanic_50/usr/src/lib/libuuid/common/uuid_misc.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2000,2002 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * The copyright in this file is taken from the original Leach
29  * & Salz UUID specification, from which this implementation
30  * is derived.
31  */
32 
33 /*
34  * Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
35  * Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
36  * Digital Equipment Corporation, Maynard, Mass.  Copyright (c) 1998
37  * Microsoft.  To anyone who acknowledges that this file is provided
38  * "AS IS" without any express or implied warranty: permission to use,
39  * copy, modify, and distribute this file for any purpose is hereby
40  * granted without fee, provided that the above copyright notices and
41  * this notice appears in all source code copies, and that none of the
42  * names of Open Software Foundation, Inc., Hewlett-Packard Company,
43  * or Digital Equipment Corporation be used in advertising or
44  * publicity pertaining to distribution of the software without
45  * specific, written prior permission.  Neither Open Software
46  * Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital
47  * Equipment Corporation makes any representations about the
48  * suitability of this software for any purpose.
49  */
50 
51 #pragma ident	"%Z%%M%	%I%	%E% SMI"
52 
53 #include <uuid/uuid.h>
54 #include <stdlib.h>
55 #include <strings.h>
56 #include "uuid_misc.h"
57 
58 #define	UUCMP(u1, u2)		if (u1 != u2) return ((u1 < u2) ? -1 : 1)
59 #define	UUIDS_PER_TOD_CALL	10	/* tv_usec is multiplied by 10 */
60 
61 void		struct_to_string(uuid_t, struct uuid *);
62 void		string_to_struct(struct uuid *, uuid_t);
63 void		get_system_time(uuid_time_t *);
64 
65 /*
66  * Name:	_get_current_time
67  *
68  * Description:	get-current_time -- get time as 60 bit 100ns ticks
69  *		since the beginning of unix time.
70  *		Compensate for the fact that real clock resolution is
71  *		less than 100ns.
72  *
73  * Returns:	None.
74  *
75  */
76 void
77 _get_current_time(uuid_time_t *timestamp)
78 {
79 	uuid_time_t		time_now;
80 	static uuid_time_t	time_last = 0;
81 	static uint16_t		uuids_this_tick = 0;
82 	int			done;
83 
84 	done = 0;
85 	while (!done) {
86 		get_system_time(&time_now);
87 
88 		/*
89 		 * if clock reading changed since last UUID generated...
90 		 */
91 		if (time_last != time_now) {
92 			/*
93 			 * reset count of uuids generated with
94 			 * this clock reading
95 			 */
96 			uuids_this_tick = 0;
97 			done = 1;
98 		} else {
99 			uuids_this_tick++;
100 			if (uuids_this_tick < UUIDS_PER_TOD_CALL)
101 				done = 1;
102 		}
103 		/*
104 		 * too many UUIDs for this gettimeofday call; spin
105 		 */
106 	}
107 	time_last = time_now;
108 	/*
109 	 * add the count of uuids to low order bits of the clock reading
110 	 */
111 	*timestamp = time_now + uuids_this_tick;
112 }
113 
114 /*
115  * Name:	_get_random
116  *
117  * Description:	Gets a random number.
118  *
119  * Returns:	nbytes of random information.
120  *
121  */
122 uint16_t
123 _get_random(void)
124 {
125 	static int	initted = 0;
126 	uuid_time_t	time_now;
127 	long		seed;
128 
129 	if (!initted) {
130 		get_system_time(&time_now);
131 		time_now = time_now/UUIDS_PER_TOD_CALL;
132 		seed = (unsigned)(((time_now >> 32) ^ time_now)&0xffffffff);
133 		srand48(seed);
134 		initted = 1;
135 	}
136 	return (mrand48());
137 }
138 
139 /*
140  * Name:	uuid_compare
141  *
142  * Description: Compares 2 uuid strings
143  *
144  * Returns:	-1 if u1 < u2, 1 if u1 > u2 and 0 if both are equal
145  */
146 int
147 uuid_compare(uuid_t uu1, uuid_t uu2)
148 {
149 
150 	struct uuid	uuid1, uuid2;
151 
152 	string_to_struct(&uuid1, uu1);
153 	string_to_struct(&uuid2, uu2);
154 	UUCMP(uuid1.time_low, uuid2.time_low);
155 	UUCMP(uuid1.time_mid, uuid2.time_mid);
156 	UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
157 	UUCMP(uuid1.clock_seq_hi_and_reserved, uuid2.clock_seq_hi_and_reserved);
158 	UUCMP(uuid1.clock_seq_low, uuid2.clock_seq_low);
159 	return (memcmp(uuid1.node_addr, uuid2.node_addr, 6));
160 }
161 
162 /*
163  * Name:	get_system_time
164  *
165  * Description:	system dependent call to get the current system time.
166  *		Returned as 100ns ticks since Oct 15, 1582, but
167  *		resolution may be less than 100ns.
168  *
169  * Returns:	None
170  */
171 void
172 get_system_time(uuid_time_t *uuid_time)
173 {
174 	struct timeval tp;
175 
176 	(void) gettimeofday(&tp, (struct timezone *)0);
177 
178 	/*
179 	 * Offset between UUID formatted times and Unix formatted times.
180 	 * UUID UTC base time is October 15, 1582.
181 	 * Unix base time is January 1, 1970.
182 	 */
183 	*uuid_time = (uint64_t)tp.tv_sec * 10000000;
184 	*uuid_time += tp.tv_usec * 10;
185 	*uuid_time += 0x01B21DD213814000;
186 }
187