Home | History | Annotate | Download | only in common
      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
     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
    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
    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
    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