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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 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 #include <uuid/uuid.h>
52 #include <stdlib.h>
53 #include <strings.h>
54 #include "uuid_misc.h"
55
56 #define UUCMP(u1, u2) if (u1 != u2) return ((u1 < u2) ? -1 : 1)
57 #define UUIDS_PER_TOD_CALL 10 /* tv_usec is multiplied by 10 */
58
59 void struct_to_string(uuid_t, struct uuid *);
60 void string_to_struct(struct uuid *, uuid_t);
61 void get_system_time(uuid_time_t *);
62
63 /*
64 * Name: get_current_time
65 *
66 * Description: get-current_time -- get time as 60 bit 100ns ticks
67 * since the beginning of unix time.
68 * Compensate for the fact that real clock resolution is
69 * less than 100ns.
70 *
71 * Returns: None.
72 *
73 */
74 void
get_current_time(uuid_time_t * timestamp)75 get_current_time(uuid_time_t *timestamp)
76 {
77 uuid_time_t time_now;
78 static uuid_time_t time_last = 0;
79 static uint16_t uuids_this_tick = 0;
80 int done;
81
82 done = 0;
83 while (!done) {
84 get_system_time(&time_now);
85
86 /*
87 * if clock reading changed since last UUID generated...
88 */
89 if (time_last != time_now) {
90 /*
91 * reset count of uuids generated with
92 * this clock reading
93 */
94 uuids_this_tick = 0;
95 done = 1;
96 } else {
97 uuids_this_tick++;
98 if (uuids_this_tick < UUIDS_PER_TOD_CALL)
99 done = 1;
100 }
101 /*
102 * too many UUIDs for this gettimeofday call; spin
103 */
104 }
105 time_last = time_now;
106 /*
107 * add the count of uuids to low order bits of the clock reading
108 */
109 *timestamp = time_now + uuids_this_tick;
110 }
111
112 /*
113 * Name: get_random
114 *
115 * Description: Gets a random number.
116 *
117 * Returns: nbytes of random information.
118 *
119 */
120 uint16_t
get_random(void)121 get_random(void)
122 {
123 static int initted = 0;
124 uuid_time_t time_now;
125 long seed;
126
127 if (!initted) {
128 get_system_time(&time_now);
129 time_now = time_now/UUIDS_PER_TOD_CALL;
130 seed = (unsigned)(((time_now >> 32) ^ time_now)&0xffffffff);
131 srand48(seed);
132 initted = 1;
133 }
134 return (mrand48());
135 }
136
137 /*
138 * Name: uuid_compare
139 *
140 * Description: Compares 2 uuid strings
141 *
142 * Returns: -1 if u1 < u2, 1 if u1 > u2 and 0 if both are equal
143 */
144 int
uuid_compare(uuid_t uu1,uuid_t uu2)145 uuid_compare(uuid_t uu1, uuid_t uu2)
146 {
147
148 struct uuid uuid1, uuid2;
149
150 string_to_struct(&uuid1, uu1);
151 string_to_struct(&uuid2, uu2);
152 UUCMP(uuid1.time_low, uuid2.time_low);
153 UUCMP(uuid1.time_mid, uuid2.time_mid);
154 UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version);
155 UUCMP(uuid1.clock_seq_hi_and_reserved, uuid2.clock_seq_hi_and_reserved);
156 UUCMP(uuid1.clock_seq_low, uuid2.clock_seq_low);
157 return (memcmp(uuid1.node_addr, uuid2.node_addr, 6));
158 }
159
160 /*
161 * Name: get_system_time
162 *
163 * Description: system dependent call to get the current system time.
164 * Returned as 100ns ticks since Oct 15, 1582, but
165 * resolution may be less than 100ns.
166 *
167 * Returns: None
168 */
169 void
get_system_time(uuid_time_t * uuid_time)170 get_system_time(uuid_time_t *uuid_time)
171 {
172 struct timeval tp;
173
174 (void) gettimeofday(&tp, (struct timezone *)0);
175
176 /*
177 * Offset between UUID formatted times and Unix formatted times.
178 * UUID UTC base time is October 15, 1582.
179 * Unix base time is January 1, 1970.
180 */
181 *uuid_time = (uint64_t)tp.tv_sec * 10000000;
182 *uuid_time += tp.tv_usec * 10;
183 *uuid_time += 0x01B21DD213814000ULL;
184 }
185