mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
1709 lines
57 KiB
Plaintext
1709 lines
57 KiB
Plaintext
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Network Working Group Paul J. Leach, Microsoft
|
|||
|
INTERNET-DRAFT Rich Salz, Certco
|
|||
|
<draft-leach-uuids-guids-01.txt>
|
|||
|
Category: Standards Track
|
|||
|
Expires August 4, 1998 February 4, 1998
|
|||
|
|
|||
|
|
|||
|
|
|||
|
UUIDs and GUIDs
|
|||
|
|
|||
|
STATUS OF THIS MEMO
|
|||
|
|
|||
|
This document is an Internet-Draft. Internet-Drafts are working
|
|||
|
documents of the Internet Engineering Task Force (IETF), its areas,
|
|||
|
and its working groups. Note that other groups may also distribute
|
|||
|
working documents as Internet-Drafts.
|
|||
|
|
|||
|
Internet-Drafts are draft documents valid for a maximum of six months
|
|||
|
and may be updated, replaced, or obsoleted by other documents at any
|
|||
|
time. It is inappropriate to use Internet-Drafts as reference
|
|||
|
material or to cite them other than as "work in progress".
|
|||
|
|
|||
|
To learn the current status of any Internet-Draft, please check the
|
|||
|
"1id-abstracts.txt" listing contained in the Internet-Drafts Shadow
|
|||
|
Directories on ftp.is.co.za (Africa), nic.nordu.net (Europe),
|
|||
|
munnari.oz.au (Pacific Rim), ds.internic.net (US East Coast), or
|
|||
|
ftp.isi.edu (US West Coast).
|
|||
|
|
|||
|
Distribution of this document is unlimited. Please send comments to
|
|||
|
the authors or the CIFS mailing list at <cifs@discuss.microsoft.com>.
|
|||
|
Discussions of the mailing list are archived at
|
|||
|
<URL:http://discuss.microsoft.com/archives/index.
|
|||
|
|
|||
|
|
|||
|
ABSTRACT
|
|||
|
|
|||
|
This specification defines the format of UUIDs (Universally Unique
|
|||
|
IDentifier), also known as GUIDs (Globally Unique IDentifier). A UUID
|
|||
|
is 128 bits long, and if generated according to the one of the
|
|||
|
mechanisms in this document, is either guaranteed to be different
|
|||
|
from all other UUIDs/GUIDs generated until 3400 A.D. or extremely
|
|||
|
likely to be different (depending on the mechanism chosen). UUIDs
|
|||
|
were originally used in the Network Computing System (NCS) [1] and
|
|||
|
later in the Open Software Foundation's (OSF) Distributed Computing
|
|||
|
Environment [2].
|
|||
|
|
|||
|
This specification is derived from the latter specification with the
|
|||
|
kind permission of the OSF.
|
|||
|
|
|||
|
|
|||
|
Table of Contents
|
|||
|
|
|||
|
1. Introduction .......................................................3
|
|||
|
|
|||
|
|
|||
|
[Page 1]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
2. Motivation .........................................................3
|
|||
|
|
|||
|
3. Specification ......................................................3
|
|||
|
|
|||
|
3.1 Format............................................................4
|
|||
|
|
|||
|
3.1.1 Variant......................................................4
|
|||
|
|
|||
|
3.1.2 UUID layout..................................................5
|
|||
|
|
|||
|
3.1.3 Version......................................................5
|
|||
|
|
|||
|
3.1.4 Timestamp....................................................6
|
|||
|
|
|||
|
3.1.5 Clock sequence...............................................6
|
|||
|
|
|||
|
3.1.6 Node.........................................................7
|
|||
|
|
|||
|
3.1.7 Nil UUID.....................................................7
|
|||
|
|
|||
|
3.2 Algorithms for creating a time-based UUID.........................7
|
|||
|
|
|||
|
3.2.1 Basic algorithm..............................................7
|
|||
|
|
|||
|
3.2.2 Reading stable storage.......................................8
|
|||
|
|
|||
|
3.2.3 System clock resolution......................................8
|
|||
|
|
|||
|
3.2.4 Writing stable storage.......................................9
|
|||
|
|
|||
|
3.2.5 Sharing state across processes...............................9
|
|||
|
|
|||
|
3.2.6 UUID Generation details......................................9
|
|||
|
|
|||
|
3.3 Algorithm for creating a name-based UUID.........................10
|
|||
|
|
|||
|
3.4 Algorithms for creating a UUID from truly random or pseudo-random
|
|||
|
numbers .............................................................11
|
|||
|
|
|||
|
3.5 String Representation of UUIDs...................................12
|
|||
|
|
|||
|
3.6 Comparing UUIDs for equality.....................................12
|
|||
|
|
|||
|
3.7 Comparing UUIDs for relative order...............................13
|
|||
|
|
|||
|
3.8 Byte order of UUIDs..............................................13
|
|||
|
|
|||
|
4. Node IDs when no IEEE 802 network card is available ...............14
|
|||
|
|
|||
|
5. Obtaining IEEE 802 addresses ......................................15
|
|||
|
|
|||
|
6. Security Considerations ...........................................15
|
|||
|
|
|||
|
7. Acknowledgements ..................................................15
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 2]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
8. References ........................................................15
|
|||
|
|
|||
|
9. Authors' addresses ................................................16
|
|||
|
|
|||
|
10.Notice ............................................................16
|
|||
|
|
|||
|
11.Full Copyright Statement ..........................................16
|
|||
|
|
|||
|
Appendix A _ UUID Sample Implementation...............................17
|
|||
|
|
|||
|
Appendix B _ Sample output of utest...................................27
|
|||
|
|
|||
|
Appendix C _ Some name space IDs......................................27
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
1. Introduction
|
|||
|
|
|||
|
This specification defines the format of UUIDs (Universally Unique
|
|||
|
IDentifiers), also known as GUIDs (Globally Unique IDentifiers). A
|
|||
|
UUID is 128 bits long, and if generated according to the one of the
|
|||
|
mechanisms in this document, is either guaranteed to be different
|
|||
|
from all other UUIDs/GUIDs generated until 3400 A.D. or extremely
|
|||
|
likely to be different (depending on the mechanism chosen).
|
|||
|
|
|||
|
|
|||
|
2. Motivation
|
|||
|
|
|||
|
One of the main reasons for using UUIDs is that no centralized
|
|||
|
authority is required to administer them (beyond the one that
|
|||
|
allocates IEEE 802.1 node identifiers). As a result, generation on
|
|||
|
demand can be completely automated, and they can be used for a wide
|
|||
|
variety of purposes. The UUID generation algorithm described here
|
|||
|
supports very high allocation rates: 10 million per second per
|
|||
|
machine if you need it, so that they could even be used as
|
|||
|
transaction IDs.
|
|||
|
|
|||
|
UUIDs are fixed-size (128-bits) which is reasonably small relative to
|
|||
|
other alternatives. This fixed, relatively small size lends itself
|
|||
|
well to sorting, ordering, and hashing of all sorts, storing in
|
|||
|
databases, simple allocation, and ease of programming in general.
|
|||
|
|
|||
|
|
|||
|
3. Specification
|
|||
|
|
|||
|
A UUID is an identifier that is unique across both space and time,
|
|||
|
with respect to the space of all UUIDs. To be precise, the UUID
|
|||
|
consists of a finite bit space. Thus the time value used for
|
|||
|
constructing a UUID is limited and will roll over in the future
|
|||
|
(approximately at A.D. 3400, based on the specified algorithm). A
|
|||
|
UUID can be used for multiple purposes, from tagging objects with an
|
|||
|
extremely short lifetime, to reliably identifying very persistent
|
|||
|
objects across a network.
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 3]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
The generation of UUIDs does not require that a registration
|
|||
|
authority be contacted for each identifier. Instead, it requires a
|
|||
|
unique value over space for each UUID generator. This spatially
|
|||
|
unique value is specified as an IEEE 802 address, which is usually
|
|||
|
already available to network-connected systems. This 48-bit address
|
|||
|
can be assigned based on an address block obtained through the IEEE
|
|||
|
registration authority. This section of the UUID specification
|
|||
|
assumes the availability of an IEEE 802 address to a system desiring
|
|||
|
to generate a UUID, but if one is not available section 4 specifies a
|
|||
|
way to generate a probabilistically unique one that can not conflict
|
|||
|
with any properly assigned IEEE 802 address.
|
|||
|
|
|||
|
|
|||
|
3.1 Format
|
|||
|
|
|||
|
In its most general form, all that can be said of the UUID format is
|
|||
|
that a UUID is 16 octets, and that some bits of octet 8 of the UUID
|
|||
|
called the variant field (specified in the next section) determine
|
|||
|
finer structure.
|
|||
|
|
|||
|
|
|||
|
3.1.1 Variant
|
|||
|
The variant field determines the layout of the UUID. That is, the
|
|||
|
interpretation of all other bits in the UUID depends on the setting
|
|||
|
of the bits in the variant field. The variant field consists of a
|
|||
|
variable number of the msbs of octet 8 of the UUID.
|
|||
|
|
|||
|
The following table lists the contents of the variant field.
|
|||
|
|
|||
|
Msb0 Msb1 Msb2 Description
|
|||
|
|
|||
|
0 - - Reserved, NCS backward compatibility.
|
|||
|
|
|||
|
1 0 - The variant specified in this document.
|
|||
|
|
|||
|
1 1 0 Reserved, Microsoft Corporation backward
|
|||
|
compatibility
|
|||
|
|
|||
|
1 1 1 Reserved for future definition.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Other UUID variants may not interoperate with the UUID variant
|
|||
|
specified in this document, where interoperability is defined as the
|
|||
|
applicability of operations such as string conversion and lexical
|
|||
|
ordering across different systems. However, UUIDs allocated according
|
|||
|
to the stricture of different variants, though they may define
|
|||
|
different interpretations of the bits outside the variant field, will
|
|||
|
not result in duplicate UUID allocation, because of the differing
|
|||
|
values of the variant field itself.
|
|||
|
|
|||
|
The remaining fields described below (version, timestamp, etc.) are
|
|||
|
defined only for the UUID variant noted above.
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 4]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
3.1.2 UUID layout
|
|||
|
The following table gives the format of a UUID for the variant
|
|||
|
specified herein. The UUID consists of a record of 16 octets. To
|
|||
|
minimize confusion about bit assignments within octets, the UUID
|
|||
|
record definition is defined only in terms of fields that are
|
|||
|
integral numbers of octets. The fields are in order of significance
|
|||
|
for comparison purposes, with "time_low" the most significant, and
|
|||
|
"node" the least significant.
|
|||
|
|
|||
|
Field Data Type Octet Note
|
|||
|
#
|
|||
|
|
|||
|
time_low unsigned 32 0-3 The low field of the
|
|||
|
bit integer timestamp.
|
|||
|
|
|||
|
time_mid unsigned 16 4-5 The middle field of the
|
|||
|
bit integer timestamp.
|
|||
|
|
|||
|
time_hi_and_version unsigned 16 6-7 The high field of the
|
|||
|
bit integer timestamp multiplexed
|
|||
|
with the version number.
|
|||
|
|
|||
|
clock_seq_hi_and_rese unsigned 8 8 The high field of the
|
|||
|
rved bit integer clock sequence
|
|||
|
multiplexed with the
|
|||
|
variant.
|
|||
|
|
|||
|
clock_seq_low unsigned 8 9 The low field of the
|
|||
|
bit integer clock sequence.
|
|||
|
|
|||
|
node unsigned 48 10-15 The spatially unique
|
|||
|
bit integer node identifier.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
3.1.3 Version
|
|||
|
The version number is in the most significant 4 bits of the time
|
|||
|
stamp (time_hi_and_version).
|
|||
|
|
|||
|
The following table lists currently defined versions of the UUID.
|
|||
|
|
|||
|
Msb0 Msb1 Msb2 Msb3 Version Description
|
|||
|
|
|||
|
0 0 0 1 1 The time-based version
|
|||
|
specified in this
|
|||
|
document.
|
|||
|
|
|||
|
0 0 1 0 2 Reserved for DCE
|
|||
|
Security version, with
|
|||
|
embedded POSIX UIDs.
|
|||
|
|
|||
|
0 0 1 1 3 The name-based version
|
|||
|
specified in this
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 5]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
document
|
|||
|
|
|||
|
0 1 0 0 4 The randomly or pseudo-
|
|||
|
randomly generated
|
|||
|
version specified in
|
|||
|
this document
|
|||
|
|
|||
|
|
|||
|
3.1.4 Timestamp
|
|||
|
The timestamp is a 60 bit value. For UUID version 1, this is
|
|||
|
represented by Coordinated Universal Time (UTC) as a count of 100-
|
|||
|
nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
|
|||
|
Gregorian reform to the Christian calendar).
|
|||
|
|
|||
|
For systems that do not have UTC available, but do have local time,
|
|||
|
they MAY use local time instead of UTC, as long as they do so
|
|||
|
consistently throughout the system. This is NOT RECOMMENDED, however,
|
|||
|
and it should be noted that all that is needed to generate UTC, given
|
|||
|
local time, is a time zone offset.
|
|||
|
|
|||
|
For UUID version 3, it is a 60 bit value constructed from a name.
|
|||
|
|
|||
|
For UUID version 4, it is a randomly or pseudo-randomly generated 60
|
|||
|
bit value.
|
|||
|
|
|||
|
|
|||
|
3.1.5 Clock sequence
|
|||
|
For UUID version 1, the clock sequence is used to help avoid
|
|||
|
duplicates that could arise when the clock is set backwards in time
|
|||
|
or if the node ID changes.
|
|||
|
|
|||
|
If the clock is set backwards, or even might have been set backwards
|
|||
|
(e.g., while the system was powered off), and the UUID generator can
|
|||
|
not be sure that no UUIDs were generated with timestamps larger than
|
|||
|
the value to which the clock was set, then the clock sequence has to
|
|||
|
be changed. If the previous value of the clock sequence is known, it
|
|||
|
can be just incremented; otherwise it should be set to a random or
|
|||
|
high-quality pseudo random value.
|
|||
|
|
|||
|
Similarly, if the node ID changes (e.g. because a network card has
|
|||
|
been moved between machines), setting the clock sequence to a random
|
|||
|
number minimizes the probability of a duplicate due to slight
|
|||
|
differences in the clock settings of the machines. (If the value of
|
|||
|
clock sequence associated with the changed node ID were known, then
|
|||
|
the clock sequence could just be incremented, but that is unlikely.)
|
|||
|
|
|||
|
The clock sequence MUST be originally (i.e., once in the lifetime of
|
|||
|
a system) initialized to a random number to minimize the correlation
|
|||
|
across systems. This provides maximum protection against node
|
|||
|
identifiers that may move or switch from system to system rapidly.
|
|||
|
The initial value MUST NOT be correlated to the node identifier.
|
|||
|
|
|||
|
For UUID version 3, it is a 14 bit value constructed from a name.
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 6]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
For UUID version 4, it is a randomly or pseudo-randomly generated 14
|
|||
|
bit value.
|
|||
|
|
|||
|
|
|||
|
3.1.6 Node
|
|||
|
For UUID version 1, the node field consists of the IEEE address,
|
|||
|
usually the host address. For systems with multiple IEEE 802
|
|||
|
addresses, any available address can be used. The lowest addressed
|
|||
|
octet (octet number 10) contains the global/local bit and the
|
|||
|
unicast/multicast bit, and is the first octet of the address
|
|||
|
transmitted on an 802.3 LAN.
|
|||
|
|
|||
|
For systems with no IEEE address, a randomly or pseudo-randomly
|
|||
|
generated value may be used (see section 4). The multicast bit must
|
|||
|
be set in such addresses, in order that they will never conflict with
|
|||
|
addresses obtained from network cards.
|
|||
|
|
|||
|
For UUID version 3, the node field is a 48 bit value constructed from
|
|||
|
a name.
|
|||
|
|
|||
|
For UUID version 4, the node field is a randomly or pseudo-randomly
|
|||
|
generated 48 bit value.
|
|||
|
|
|||
|
|
|||
|
3.1.7 Nil UUID
|
|||
|
The nil UUID is special form of UUID that is specified to have all
|
|||
|
128 bits set to 0 (zero).
|
|||
|
|
|||
|
|
|||
|
3.2 Algorithms for creating a time-based UUID
|
|||
|
|
|||
|
Various aspects of the algorithm for creating a version 1 UUID are
|
|||
|
discussed in the following sections. UUID generation requires a
|
|||
|
guarantee of uniqueness within the node ID for a given variant and
|
|||
|
version. Interoperability is provided by complying with the specified
|
|||
|
data structure.
|
|||
|
|
|||
|
|
|||
|
3.2.1 Basic algorithm
|
|||
|
The following algorithm is simple, correct, and inefficient:
|
|||
|
|
|||
|
. Obtain a system wide global lock
|
|||
|
|
|||
|
. From a system wide shared stable store (e.g., a file), read the
|
|||
|
UUID generator state: the values of the time stamp, clock sequence,
|
|||
|
and node ID used to generate the last UUID.
|
|||
|
|
|||
|
. Get the current time as a 60 bit count of 100-nanosecond intervals
|
|||
|
since 00:00:00.00, 15 October 1582
|
|||
|
|
|||
|
. Get the current node ID
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 7]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
. If the state was unavailable (non-existent or corrupted), or the
|
|||
|
saved node ID is different than the current node ID, generate a
|
|||
|
random clock sequence value
|
|||
|
|
|||
|
. If the state was available, but the saved time stamp is later than
|
|||
|
the current time stamp, increment the clock sequence value
|
|||
|
|
|||
|
. Format a UUID from the current time stamp, clock sequence, and node
|
|||
|
ID values according to the structure in section 3.1 (see section
|
|||
|
3.2.6 for more details)
|
|||
|
|
|||
|
. Save the state (current time stamp, clock sequence, and node ID)
|
|||
|
back to the stable store
|
|||
|
|
|||
|
. Release the system wide global lock
|
|||
|
|
|||
|
If UUIDs do not need to be frequently generated, the above algorithm
|
|||
|
may be perfectly adequate. For higher performance requirements,
|
|||
|
however, issues with the basic algorithm include:
|
|||
|
|
|||
|
. Reading the state from stable storage each time is inefficient
|
|||
|
|
|||
|
. The resolution of the system clock may not be 100-nanoseconds
|
|||
|
|
|||
|
. Writing the state to stable storage each time is inefficient
|
|||
|
|
|||
|
. Sharing the state across process boundaries may be inefficient
|
|||
|
|
|||
|
Each of these issues can be addressed in a modular fashion by local
|
|||
|
improvements in the functions that read and write the state and read
|
|||
|
the clock. We address each of them in turn in the following sections.
|
|||
|
|
|||
|
|
|||
|
3.2.2 Reading stable storage
|
|||
|
The state only needs to be read from stable storage once at boot
|
|||
|
time, if it is read into a system wide shared volatile store (and
|
|||
|
updated whenever the stable store is updated).
|
|||
|
|
|||
|
If an implementation does not have any stable store available, then
|
|||
|
it can always say that the values were unavailable. This is the least
|
|||
|
desirable implementation, because it will increase the frequency of
|
|||
|
creation of new clock sequence numbers, which increases the
|
|||
|
probability of duplicates.
|
|||
|
|
|||
|
If the node ID can never change (e.g., the net card is inseparable
|
|||
|
from the system), or if any change also reinitializes the clock
|
|||
|
sequence to a random value, then instead of keeping it in stable
|
|||
|
store, the current node ID may be returned.
|
|||
|
|
|||
|
|
|||
|
3.2.3 System clock resolution
|
|||
|
The time stamp is generated from the system time, whose resolution
|
|||
|
may be less than the resolution of the UUID time stamp.
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 8]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
If UUIDs do not need to be frequently generated, the time stamp can
|
|||
|
simply be the system time multiplied by the number of 100-nanosecond
|
|||
|
intervals per system time interval.
|
|||
|
|
|||
|
If a system overruns the generator by requesting too many UUIDs
|
|||
|
within a single system time interval, the UUID service MUST either:
|
|||
|
return an error, or stall the UUID generator until the system clock
|
|||
|
catches up.
|
|||
|
|
|||
|
A high resolution time stamp can be simulated by keeping a count of
|
|||
|
how many UUIDs have been generated with the same value of the system
|
|||
|
time, and using it to construction the low-order bits of the time
|
|||
|
stamp. The count will range between zero and the number of 100-
|
|||
|
nanosecond intervals per system time interval.
|
|||
|
|
|||
|
Note: if the processors overrun the UUID generation frequently,
|
|||
|
additional node identifiers can be allocated to the system, which
|
|||
|
will permit higher speed allocation by making multiple UUIDs
|
|||
|
potentially available for each time stamp value.
|
|||
|
|
|||
|
|
|||
|
3.2.4 Writing stable storage
|
|||
|
The state does not always need to be written to stable store every
|
|||
|
time a UUID is generated. The timestamp in the stable store can be
|
|||
|
periodically set to a value larger than any yet used in a UUID; as
|
|||
|
long as the generated UUIDs have time stamps less than that value,
|
|||
|
and the clock sequence and node ID remain unchanged, only the shared
|
|||
|
volatile copy of the state needs to be updated. Furthermore, if the
|
|||
|
time stamp value in stable store is in the future by less than the
|
|||
|
typical time it takes the system to reboot, a crash will not cause a
|
|||
|
reinitialization of the clock sequence.
|
|||
|
|
|||
|
|
|||
|
3.2.5 Sharing state across processes
|
|||
|
If it is too expensive to access shared state each time a UUID is
|
|||
|
generated, then the system wide generator can be implemented to
|
|||
|
allocate a block of time stamps each time it is called, and a per-
|
|||
|
process generator can allocate from that block until it is exhausted.
|
|||
|
|
|||
|
|
|||
|
3.2.6 UUID Generation details
|
|||
|
UUIDs are generated according to the following algorithm:
|
|||
|
|
|||
|
- Determine the values for the UTC-based timestamp and clock sequence
|
|||
|
to be used in the UUID, as described above.
|
|||
|
|
|||
|
- For the purposes of this algorithm, consider the timestamp to be a
|
|||
|
60-bit unsigned integer and the clock sequence to be a 14-bit
|
|||
|
unsigned integer. Sequentially number the bits in a field, starting
|
|||
|
from 0 (zero) for the least significant bit.
|
|||
|
|
|||
|
- Set the time_low field equal to the least significant 32-bits (bits
|
|||
|
numbered 0 to 31 inclusive) of the time stamp in the same order of
|
|||
|
significance.
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 9]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
- Set the time_mid field equal to the bits numbered 32 to 47
|
|||
|
inclusive of the time stamp in the same order of significance.
|
|||
|
|
|||
|
- Set the 12 least significant bits (bits numbered 0 to 11 inclusive)
|
|||
|
of the time_hi_and_version field equal to the bits numbered 48 to 59
|
|||
|
inclusive of the time stamp in the same order of significance.
|
|||
|
|
|||
|
- Set the 4 most significant bits (bits numbered 12 to 15 inclusive)
|
|||
|
of the time_hi_and_version field to the 4-bit version number
|
|||
|
corresponding to the UUID version being created, as shown in the
|
|||
|
table in section 3.1.3.
|
|||
|
|
|||
|
- Set the clock_seq_low field to the 8 least significant bits (bits
|
|||
|
numbered 0 to 7 inclusive) of the clock sequence in the same order of
|
|||
|
significance.
|
|||
|
|
|||
|
- Set the 6 least significant bits (bits numbered 0 to 5 inclusive)
|
|||
|
of the clock_seq_hi_and_reserved field to the 6 most significant bits
|
|||
|
(bits numbered 8 to 13 inclusive) of the clock sequence in the same
|
|||
|
order of significance.
|
|||
|
|
|||
|
- Set the 2 most significant bits (bits numbered 6 and 7) of the
|
|||
|
clock_seq_hi_and_reserved to 0 and 1, respectively.
|
|||
|
|
|||
|
- Set the node field to the 48-bit IEEE address in the same order of
|
|||
|
significance as the address.
|
|||
|
|
|||
|
|
|||
|
3.3 Algorithm for creating a name-based UUID
|
|||
|
|
|||
|
The version 3 UUID is meant for generating UUIDs from "names" that
|
|||
|
are drawn from, and unique within, some "name space". Some examples
|
|||
|
of names (and, implicitly, name spaces) might be DNS names, URLs, ISO
|
|||
|
Object IDs (OIDs), reserved words in a programming language, or X.500
|
|||
|
Distinguished Names (DNs); thus, the concept of name and name space
|
|||
|
should be broadly construed, and not limited to textual names. The
|
|||
|
mechanisms or conventions for allocating names from, and ensuring
|
|||
|
their uniqueness within, their name spaces are beyond the scope of
|
|||
|
this specification.
|
|||
|
|
|||
|
The requirements for such UUIDs are as follows:
|
|||
|
|
|||
|
. The UUIDs generated at different times from the same name in the
|
|||
|
same namespace MUST be equal
|
|||
|
|
|||
|
. The UUIDs generated from two different names in the same namespace
|
|||
|
should be different (with very high probability)
|
|||
|
|
|||
|
. The UUIDs generated from the same name in two different namespaces
|
|||
|
should be different with (very high probability)
|
|||
|
|
|||
|
. If two UUIDs that were generated from names are equal, then they
|
|||
|
were generated from the same name in the same namespace (with very
|
|||
|
high probability).
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 10]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
The algorithm for generating the a UUID from a name and a name space
|
|||
|
are as follows:
|
|||
|
|
|||
|
. Allocate a UUID to use as a "name space ID" for all UUIDs generated
|
|||
|
from names in that name space
|
|||
|
|
|||
|
. Convert the name to a canonical sequence of octets (as defined by
|
|||
|
the standards or conventions of its name space); put the name space
|
|||
|
ID in network byte order
|
|||
|
|
|||
|
. Compute the MD5 [3] hash of the name space ID concatenated with the
|
|||
|
name
|
|||
|
|
|||
|
. Set octets 0-3 of time_low field to octets 0-3 of the MD5 hash
|
|||
|
|
|||
|
. Set octets 0-1 of time_mid field to octets 4-5 of the MD5 hash
|
|||
|
|
|||
|
. Set octets 0-1 of time_hi_and_version field to octets 6-7 of the
|
|||
|
MD5 hash
|
|||
|
|
|||
|
. Set the clock_seq_hi_and_reserved field to octet 8 of the MD5 hash
|
|||
|
|
|||
|
. Set the clock_seq_low field to octet 9 of the MD5 hash
|
|||
|
|
|||
|
. Set octets 0-5 of the node field to octets 10-15 of the MD5 hash
|
|||
|
|
|||
|
. Set the 2 most significant bits (bits numbered 6 and 7) of the
|
|||
|
clock_seq_hi_and_reserved to 0 and 1, respectively.
|
|||
|
|
|||
|
. Set the 4 most significant bits (bits numbered 12 to 15 inclusive)
|
|||
|
of the time_hi_and_version field to the 4-bit version number
|
|||
|
corresponding to the UUID version being created, as shown in the
|
|||
|
table above.
|
|||
|
|
|||
|
. Convert the resulting UUID to local byte order.
|
|||
|
|
|||
|
|
|||
|
3.4 Algorithms for creating a UUID from truly random or pseudo-random
|
|||
|
numbers
|
|||
|
|
|||
|
The version 4 UUID is meant for generating UUIDs from truly-random or
|
|||
|
pseudo-random numbers.
|
|||
|
|
|||
|
The algorithm is as follows:
|
|||
|
|
|||
|
. Set the 2 most significant bits (bits numbered 6 and 7) of the
|
|||
|
clock_seq_hi_and_reserved to 0 and 1, respectively.
|
|||
|
|
|||
|
. Set the 4 most significant bits (bits numbered 12 to 15 inclusive)
|
|||
|
of the time_hi_and_version field to the 4-bit version number
|
|||
|
corresponding to the UUID version being created, as shown in the
|
|||
|
table above.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 11]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
. Set all the other bits to randomly (or pseudo-randomly) chosen
|
|||
|
values.
|
|||
|
|
|||
|
Here are several possible ways to generate the random values:
|
|||
|
|
|||
|
. Use a physical source of randomness: for example, a white noise
|
|||
|
generator, radioactive decay, or a lava lamp.
|
|||
|
|
|||
|
. Use a cryptographic strength random number generator.
|
|||
|
|
|||
|
|
|||
|
3.5 String Representation of UUIDs
|
|||
|
|
|||
|
For use in human readable text, a UUID string representation is
|
|||
|
specified as a sequence of fields, some of which are separated by
|
|||
|
single dashes.
|
|||
|
|
|||
|
Each field is treated as an integer and has its value printed as a
|
|||
|
zero-filled hexadecimal digit string with the most significant digit
|
|||
|
first. The hexadecimal values a to f inclusive are output as lower
|
|||
|
case characters, and are case insensitive on input. The sequence is
|
|||
|
the same as the UUID constructed type.
|
|||
|
|
|||
|
The formal definition of the UUID string representation is provided
|
|||
|
by the following extended BNF:
|
|||
|
|
|||
|
UUID = <time_low> "-" <time_mid> "-"
|
|||
|
<time_high_and_version> "-"
|
|||
|
<clock_seq_and_reserved>
|
|||
|
<clock_seq_low> "-" <node>
|
|||
|
time_low = 4*<hexOctet>
|
|||
|
time_mid = 2*<hexOctet>
|
|||
|
time_high_and_version = 2*<hexOctet>
|
|||
|
clock_seq_and_reserved = <hexOctet>
|
|||
|
clock_seq_low = <hexOctet>
|
|||
|
node = 6*<hexOctet
|
|||
|
hexOctet = <hexDigit> <hexDigit>
|
|||
|
hexDigit =
|
|||
|
"0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
|
|||
|
| "a" | "b" | "c" | "d" | "e" | "f"
|
|||
|
| "A" | "B" | "C" | "D" | "E" | "F"
|
|||
|
|
|||
|
The following is an example of the string representation of a UUID:
|
|||
|
|
|||
|
f81d4fae-7dec-11d0-a765-00a0c91e6bf6
|
|||
|
|
|||
|
3.6 Comparing UUIDs for equality
|
|||
|
|
|||
|
Consider each field of the UUID to be an unsigned integer as shown in
|
|||
|
the table in section 3.1. Then, to compare a pair of UUIDs,
|
|||
|
arithmetically compare the corresponding fields from each UUID in
|
|||
|
order of significance and according to their data type. Two UUIDs are
|
|||
|
equal if and only if all the corresponding fields are equal.
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 12]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
Note: as a practical matter, on many systems comparison of two UUIDs
|
|||
|
for equality can be performed simply by comparing the 128 bits of
|
|||
|
their in-memory representation considered as a 128 bit unsigned
|
|||
|
integer. Here, it is presumed that by the time the in-memory
|
|||
|
representation is obtained the appropriate byte-order
|
|||
|
canonicalizations have been carried out.
|
|||
|
|
|||
|
|
|||
|
3.7 Comparing UUIDs for relative order
|
|||
|
|
|||
|
Two UUIDs allocated according to the same variant can also be ordered
|
|||
|
lexicographically. For the UUID variant herein defined, the first of
|
|||
|
two UUIDs follows the second if the most significant field in which
|
|||
|
the UUIDs differ is greater for the first UUID. The first of a pair
|
|||
|
of UUIDs precedes the second if the most significant field in which
|
|||
|
the UUIDs differ is greater for the second UUID.
|
|||
|
|
|||
|
|
|||
|
3.8 Byte order of UUIDs
|
|||
|
|
|||
|
UUIDs may be transmitted in many different forms, some of which may
|
|||
|
be dependent on the presentation or application protocol where the
|
|||
|
UUID may be used. In such cases, the order, sizes and byte orders of
|
|||
|
the UUIDs fields on the wire will depend on the relevant presentation
|
|||
|
or application protocol. However, it is strongly RECOMMENDED that
|
|||
|
the order of the fields conform with ordering set out in section 3.1
|
|||
|
above. Furthermore, the payload size of each field in the application
|
|||
|
or presentation protocol MUST be large enough that no information
|
|||
|
lost in the process of encoding them for transmission.
|
|||
|
|
|||
|
In the absence of explicit application or presentation protocol
|
|||
|
specification to the contrary, a UUID is encoded as a 128-bit object,
|
|||
|
as follows: the fields are encoded as 16 octets, with the sizes and
|
|||
|
order of the fields defined in section 3.1, and with each field
|
|||
|
encoded with the Most Significant Byte first (also known as network
|
|||
|
byte order).
|
|||
|
|
|||
|
0 1 2 3
|
|||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|||
|
| time_low |
|
|||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|||
|
| time_mid | time_hi_and_version |
|
|||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|||
|
|clk_seq_hi_res | clk_seq_low | node (0-1) |
|
|||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|||
|
| node (2-5) |
|
|||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 13]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
4. Node IDs when no IEEE 802 network card is available
|
|||
|
|
|||
|
If a system wants to generate UUIDs but has no IEE 802 compliant
|
|||
|
network card or other source of IEEE 802 addresses, then this section
|
|||
|
describes how to generate one.
|
|||
|
|
|||
|
The ideal solution is to obtain a 47 bit cryptographic quality random
|
|||
|
number, and use it as the low 47 bits of the node ID, with the most
|
|||
|
significant bit of the first octet of the node ID set to 1. This bit
|
|||
|
is the unicast/multicast bit, which will never be set in IEEE 802
|
|||
|
addresses obtained from network cards; hence, there can never be a
|
|||
|
conflict between UUIDs generated by machines with and without network
|
|||
|
cards.
|
|||
|
|
|||
|
If a system does not have a primitive to generate cryptographic
|
|||
|
quality random numbers, then in most systems there are usually a
|
|||
|
fairly large number of sources of randomness available from which one
|
|||
|
can be generated. Such sources are system specific, but often
|
|||
|
include:
|
|||
|
|
|||
|
- the percent of memory in use
|
|||
|
- the size of main memory in bytes
|
|||
|
- the amount of free main memory in bytes
|
|||
|
- the size of the paging or swap file in bytes
|
|||
|
- free bytes of paging or swap file
|
|||
|
- the total size of user virtual address space in bytes
|
|||
|
- the total available user address space bytes
|
|||
|
- the size of boot disk drive in bytes
|
|||
|
- the free disk space on boot drive in bytes
|
|||
|
- the current time
|
|||
|
- the amount of time since the system booted
|
|||
|
- the individual sizes of files in various system directories
|
|||
|
- the creation, last read, and modification times of files in various
|
|||
|
system directories
|
|||
|
- the utilization factors of various system resources (heap, etc.)
|
|||
|
- current mouse cursor position
|
|||
|
- current caret position
|
|||
|
- current number of running processes, threads
|
|||
|
- handles or IDs of the desktop window and the active window
|
|||
|
- the value of stack pointer of the caller
|
|||
|
- the process and thread ID of caller
|
|||
|
- various processor architecture specific performance counters
|
|||
|
(instructions executed, cache misses, TLB misses)
|
|||
|
|
|||
|
(Note that it precisely the above kinds of sources of randomness that
|
|||
|
are used to seed cryptographic quality random number generators on
|
|||
|
systems without special hardware for their construction.)
|
|||
|
|
|||
|
In addition, items such as the computer's name and the name of the
|
|||
|
operating system, while not strictly speaking random, will help
|
|||
|
differentiate the results from those obtained by other systems.
|
|||
|
|
|||
|
The exact algorithm to generate a node ID using these data is system
|
|||
|
specific, because both the data available and the functions to obtain
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 14]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
them are often very system specific. However, assuming that one can
|
|||
|
concatenate all the values from the randomness sources into a buffer,
|
|||
|
and that a cryptographic hash function such as MD5 [3] is available,
|
|||
|
then any 6 bytes of the MD5 hash of the buffer, with the multicast
|
|||
|
bit (the high bit of the first byte) set will be an appropriately
|
|||
|
random node ID.
|
|||
|
|
|||
|
Other hash functions, such as SHA-1 [4], can also be used. The only
|
|||
|
requirement is that the result be suitably random _ in the sense that
|
|||
|
the outputs from a set uniformly distributed inputs are themselves
|
|||
|
uniformly distributed, and that a single bit change in the input can
|
|||
|
be expected to cause half of the output bits to change.
|
|||
|
|
|||
|
|
|||
|
5. Obtaining IEEE 802 addresses
|
|||
|
|
|||
|
At the time of writing, the following URL
|
|||
|
|
|||
|
http://standards.ieee.org/db/oui/forms/
|
|||
|
|
|||
|
contains information on how to obtain an IEEE 802 address block. At
|
|||
|
the time of writing, the cost is $1250 US.
|
|||
|
|
|||
|
|
|||
|
6. Security Considerations
|
|||
|
|
|||
|
It should not be assumed that UUIDs are hard to guess; they should
|
|||
|
not be used as capabilities.
|
|||
|
|
|||
|
|
|||
|
7. Acknowledgements
|
|||
|
|
|||
|
This document draws heavily on the OSF DCE specification for UUIDs.
|
|||
|
Ted Ts'o provided helpful comments, especially on the byte ordering
|
|||
|
section which we mostly plagiarized from a proposed wording he
|
|||
|
supplied (all errors in that section are our responsibility,
|
|||
|
however).
|
|||
|
|
|||
|
|
|||
|
8. References
|
|||
|
|
|||
|
[1] Lisa Zahn, et. al., Network Computing Architecture, Prentice
|
|||
|
Hall, Englewood Cliffs, NJ, 1990
|
|||
|
|
|||
|
[2] DCE: Remote Procedure Call, Open Group CAE Specification C309
|
|||
|
ISBN 1-85912-041-5 28cm. 674p. pbk. 1,655g. 8/94
|
|||
|
|
|||
|
[3] R. Rivest, RFC 1321, "The MD5 Message-Digest Algorithm",
|
|||
|
04/16/1992.
|
|||
|
|
|||
|
[4] NIST FIPS PUB 180-1, "Secure Hash Standard," National Institute
|
|||
|
of Standards and Technology, U.S. Department of Commerce, DRAFT, May
|
|||
|
31, 1994.
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 15]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
9. Authors' addresses
|
|||
|
|
|||
|
Paul J. Leach
|
|||
|
Microsoft
|
|||
|
1 Microsoft Way
|
|||
|
Redmond, WA, 98052, U.S.A.
|
|||
|
paulle@microsoft.com
|
|||
|
Tel. 425 882 8080
|
|||
|
Fax. 425 936 7329
|
|||
|
|
|||
|
Rich Salz
|
|||
|
100 Cambridge Park Drive
|
|||
|
Cambridge MA 02140
|
|||
|
salzr@certco.com
|
|||
|
Tel. 617 499 4075
|
|||
|
Fax. 617 576 0019
|
|||
|
|
|||
|
|
|||
|
10. Notice
|
|||
|
|
|||
|
The IETF takes no position regarding the validity or scope of any
|
|||
|
intellectual property or other rights that might be claimed to
|
|||
|
pertain to the implementation or use of the technology described in
|
|||
|
this document or the extent to which any license under such rights
|
|||
|
might or might not be available; neither does it represent that it
|
|||
|
has made any effort to identify any such rights. Information on the
|
|||
|
IETF's procedures with respect to rights in standards-track and
|
|||
|
standards-related documentation can be found in BCP-11. Copies of
|
|||
|
claims of rights made available for publication and any assurances of
|
|||
|
licenses to be made available, or the result of an attempt made to
|
|||
|
obtain a general license or permission for the use of such
|
|||
|
proprietary rights by implementors or users of this specification can
|
|||
|
be obtained from the IETF Secretariat.
|
|||
|
|
|||
|
The IETF invites any interested party to bring to its attention any
|
|||
|
copyrights, patents or patent applications, or other proprietary
|
|||
|
rights which may cover technology that may be required to practice
|
|||
|
this standard. Please address the information to the IETF Executive
|
|||
|
Director.
|
|||
|
|
|||
|
|
|||
|
11. Full Copyright Statement
|
|||
|
|
|||
|
Copyright (C) The Internet Society 1997. All Rights Reserved.
|
|||
|
|
|||
|
This document and translations of it may be copied and furnished to
|
|||
|
others, and derivative works that comment on or otherwise explain it
|
|||
|
or assist in its implementation may be prepared, copied, published
|
|||
|
and distributed, in whole or in part, without restriction of any
|
|||
|
kind, provided that the above copyright notice and this paragraph are
|
|||
|
included on all such copies and derivative works. However, this
|
|||
|
document itself may not be modified in any way, such as by removing
|
|||
|
the copyright notice or references to the Internet Society or other
|
|||
|
Internet organizations, except as needed for the purpose of
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 16]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
developing Internet standards in which case the procedures for
|
|||
|
copyrights defined in the Internet Standards process must be
|
|||
|
followed, or as required to translate it into languages other than
|
|||
|
English.
|
|||
|
|
|||
|
The limited permissions granted above are perpetual and will not be
|
|||
|
revoked by the Internet Society or its successors or assigns.
|
|||
|
|
|||
|
This document and the information contained herein is provided on an
|
|||
|
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
|
|||
|
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
|||
|
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
|
|||
|
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
|
|||
|
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
|||
|
|
|||
|
|
|||
|
Appendix A _ UUID Sample Implementation
|
|||
|
|
|||
|
This implementation consists of 5 files: uuid.h, uuid.c, sysdep.h,
|
|||
|
sysdep.c and utest.c. The uuid.* files are the system independent
|
|||
|
implementation of the UUID generation algorithms described above,
|
|||
|
with all the optimizations described above except efficient state
|
|||
|
sharing across processes included. The code has been tested on Linux
|
|||
|
(Red Hat 4.0) with GCC (2.7.2), and Windows NT 4.0 with VC++ 5.0. The
|
|||
|
code assumes 64 bit integer support, which makes it a lot clearer.
|
|||
|
|
|||
|
All the following source files should be considered to have the
|
|||
|
following copyright notice included:
|
|||
|
|
|||
|
copyrt.h
|
|||
|
|
|||
|
/*
|
|||
|
** Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc.
|
|||
|
** Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. &
|
|||
|
** Digital Equipment Corporation, Maynard, Mass.
|
|||
|
** Copyright (c) 1998 Microsoft.
|
|||
|
** To anyone who acknowledges that this file is provided "AS IS"
|
|||
|
** without any express or implied warranty: permission to use, copy,
|
|||
|
** modify, and distribute this file for any purpose is hereby
|
|||
|
** granted without fee, provided that the above copyright notices and
|
|||
|
** this notice appears in all source code copies, and that none of
|
|||
|
** the names of Open Software Foundation, Inc., Hewlett-Packard
|
|||
|
** Company, or Digital Equipment Corporation be used in advertising
|
|||
|
** or publicity pertaining to distribution of the software without
|
|||
|
** specific, written prior permission. Neither Open Software
|
|||
|
** Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital
|
|||
|
Equipment
|
|||
|
** Corporation makes any representations about the suitability of
|
|||
|
** this software for any purpose.
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
uuid.h
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 17]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
#include "copyrt.h"
|
|||
|
#undef uuid_t
|
|||
|
typedef struct _uuid_t {
|
|||
|
unsigned32 time_low;
|
|||
|
unsigned16 time_mid;
|
|||
|
unsigned16 time_hi_and_version;
|
|||
|
unsigned8 clock_seq_hi_and_reserved;
|
|||
|
unsigned8 clock_seq_low;
|
|||
|
byte node[6];
|
|||
|
} uuid_t;
|
|||
|
|
|||
|
/* uuid_create -- generate a UUID */
|
|||
|
int uuid_create(uuid_t * uuid);
|
|||
|
|
|||
|
/* uuid_create_from_name -- create a UUID using a "name"
|
|||
|
from a "name space" */
|
|||
|
void uuid_create_from_name(
|
|||
|
uuid_t * uuid, /* resulting UUID */
|
|||
|
uuid_t nsid, /* UUID to serve as context, so identical
|
|||
|
names from different name spaces generate
|
|||
|
different UUIDs */
|
|||
|
void * name, /* the name from which to generate a UUID */
|
|||
|
int namelen /* the length of the name */
|
|||
|
);
|
|||
|
|
|||
|
/* uuid_compare -- Compare two UUID's "lexically" and return
|
|||
|
-1 u1 is lexically before u2
|
|||
|
0 u1 is equal to u2
|
|||
|
1 u1 is lexically after u2
|
|||
|
Note: lexical ordering is not temporal ordering!
|
|||
|
*/
|
|||
|
int uuid_compare(uuid_t *u1, uuid_t *u2);
|
|||
|
|
|||
|
uuid.c
|
|||
|
|
|||
|
#include "copyrt.h"
|
|||
|
#include <string.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <time.h>
|
|||
|
#include "sysdep.h"
|
|||
|
#include "uuid.h"
|
|||
|
|
|||
|
/* various forward declarations */
|
|||
|
static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp,
|
|||
|
uuid_node_t * node);
|
|||
|
static void write_state(unsigned16 clockseq, uuid_time_t timestamp,
|
|||
|
uuid_node_t node);
|
|||
|
static void format_uuid_v1(uuid_t * uuid, unsigned16 clockseq,
|
|||
|
uuid_time_t timestamp, uuid_node_t node);
|
|||
|
static void format_uuid_v3(uuid_t * uuid, unsigned char hash[16]);
|
|||
|
static void get_current_time(uuid_time_t * timestamp);
|
|||
|
static unsigned16 true_random(void);
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 18]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
/* uuid_create -- generator a UUID */
|
|||
|
int uuid_create(uuid_t * uuid) {
|
|||
|
uuid_time_t timestamp, last_time;
|
|||
|
unsigned16 clockseq;
|
|||
|
uuid_node_t node;
|
|||
|
uuid_node_t last_node;
|
|||
|
int f;
|
|||
|
|
|||
|
/* acquire system wide lock so we're alone */
|
|||
|
LOCK;
|
|||
|
|
|||
|
/* get current time */
|
|||
|
get_current_time(×tamp);
|
|||
|
|
|||
|
/* get node ID */
|
|||
|
get_ieee_node_identifier(&node);
|
|||
|
|
|||
|
/* get saved state from NV storage */
|
|||
|
f = read_state(&clockseq, &last_time, &last_node);
|
|||
|
|
|||
|
/* if no NV state, or if clock went backwards, or node ID changed
|
|||
|
(e.g., net card swap) change clockseq */
|
|||
|
if (!f || memcmp(&node, &last_node, sizeof(uuid_node_t)))
|
|||
|
clockseq = true_random();
|
|||
|
else if (timestamp < last_time)
|
|||
|
clockseq++;
|
|||
|
|
|||
|
/* stuff fields into the UUID */
|
|||
|
format_uuid_v1(uuid, clockseq, timestamp, node);
|
|||
|
|
|||
|
/* save the state for next time */
|
|||
|
write_state(clockseq, timestamp, node);
|
|||
|
|
|||
|
UNLOCK;
|
|||
|
return(1);
|
|||
|
};
|
|||
|
|
|||
|
/* format_uuid_v1 -- make a UUID from the timestamp, clockseq,
|
|||
|
and node ID */
|
|||
|
void format_uuid_v1(uuid_t * uuid, unsigned16 clock_seq, uuid_time_t
|
|||
|
timestamp, uuid_node_t node) {
|
|||
|
/* Construct a version 1 uuid with the information we've gathered
|
|||
|
* plus a few constants. */
|
|||
|
uuid->time_low = (unsigned long)(timestamp & 0xFFFFFFFF);
|
|||
|
uuid->time_mid = (unsigned short)((timestamp >> 32) & 0xFFFF);
|
|||
|
uuid->time_hi_and_version = (unsigned short)((timestamp >> 48) &
|
|||
|
0x0FFF);
|
|||
|
uuid->time_hi_and_version |= (1 << 12);
|
|||
|
uuid->clock_seq_low = clock_seq & 0xFF;
|
|||
|
uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8;
|
|||
|
uuid->clock_seq_hi_and_reserved |= 0x80;
|
|||
|
memcpy(&uuid->node, &node, sizeof uuid->node);
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 19]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
/* data type for UUID generator persistent state */
|
|||
|
typedef struct {
|
|||
|
uuid_time_t ts; /* saved timestamp */
|
|||
|
uuid_node_t node; /* saved node ID */
|
|||
|
unsigned16 cs; /* saved clock sequence */
|
|||
|
} uuid_state;
|
|||
|
|
|||
|
static uuid_state st;
|
|||
|
|
|||
|
/* read_state -- read UUID generator state from non-volatile store */
|
|||
|
int read_state(unsigned16 *clockseq, uuid_time_t *timestamp,
|
|||
|
uuid_node_t *node) {
|
|||
|
FILE * fd;
|
|||
|
static int inited = 0;
|
|||
|
|
|||
|
/* only need to read state once per boot */
|
|||
|
if (!inited) {
|
|||
|
fd = fopen("state", "rb");
|
|||
|
if (!fd)
|
|||
|
return (0);
|
|||
|
fread(&st, sizeof(uuid_state), 1, fd);
|
|||
|
fclose(fd);
|
|||
|
inited = 1;
|
|||
|
};
|
|||
|
*clockseq = st.cs;
|
|||
|
*timestamp = st.ts;
|
|||
|
*node = st.node;
|
|||
|
return(1);
|
|||
|
};
|
|||
|
|
|||
|
/* write_state -- save UUID generator state back to non-volatile
|
|||
|
storage */
|
|||
|
void write_state(unsigned16 clockseq, uuid_time_t timestamp,
|
|||
|
uuid_node_t node) {
|
|||
|
FILE * fd;
|
|||
|
static int inited = 0;
|
|||
|
static uuid_time_t next_save;
|
|||
|
|
|||
|
if (!inited) {
|
|||
|
next_save = timestamp;
|
|||
|
inited = 1;
|
|||
|
};
|
|||
|
/* always save state to volatile shared state */
|
|||
|
st.cs = clockseq;
|
|||
|
st.ts = timestamp;
|
|||
|
st.node = node;
|
|||
|
if (timestamp >= next_save) {
|
|||
|
fd = fopen("state", "wb");
|
|||
|
fwrite(&st, sizeof(uuid_state), 1, fd);
|
|||
|
fclose(fd);
|
|||
|
/* schedule next save for 10 seconds from now */
|
|||
|
next_save = timestamp + (10 * 10 * 1000 * 1000);
|
|||
|
};
|
|||
|
};
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 20]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* get-current_time -- get time as 60 bit 100ns ticks since whenever.
|
|||
|
Compensate for the fact that real clock resolution is
|
|||
|
less than 100ns. */
|
|||
|
void get_current_time(uuid_time_t * timestamp) {
|
|||
|
uuid_time_t time_now;
|
|||
|
static uuid_time_t time_last;
|
|||
|
static unsigned16 uuids_this_tick;
|
|||
|
static int inited = 0;
|
|||
|
|
|||
|
if (!inited) {
|
|||
|
get_system_time(&time_now);
|
|||
|
uuids_this_tick = UUIDS_PER_TICK;
|
|||
|
inited = 1;
|
|||
|
};
|
|||
|
|
|||
|
while (1) {
|
|||
|
get_system_time(&time_now);
|
|||
|
|
|||
|
/* if clock reading changed since last UUID generated... */
|
|||
|
if (time_last != time_now) {
|
|||
|
/* reset count of uuids gen'd with this clock reading */
|
|||
|
uuids_this_tick = 0;
|
|||
|
break;
|
|||
|
};
|
|||
|
if (uuids_this_tick < UUIDS_PER_TICK) {
|
|||
|
uuids_this_tick++;
|
|||
|
break;
|
|||
|
};
|
|||
|
/* going too fast for our clock; spin */
|
|||
|
};
|
|||
|
/* add the count of uuids to low order bits of the clock reading */
|
|||
|
*timestamp = time_now + uuids_this_tick;
|
|||
|
};
|
|||
|
|
|||
|
/* true_random -- generate a crypto-quality random number.
|
|||
|
This sample doesn't do that. */
|
|||
|
static unsigned16
|
|||
|
true_random(void)
|
|||
|
{
|
|||
|
static int inited = 0;
|
|||
|
uuid_time_t time_now;
|
|||
|
|
|||
|
if (!inited) {
|
|||
|
get_system_time(&time_now);
|
|||
|
time_now = time_now/UUIDS_PER_TICK;
|
|||
|
srand((unsigned int)(((time_now >> 32) ^ time_now)&0xffffffff));
|
|||
|
inited = 1;
|
|||
|
};
|
|||
|
|
|||
|
return (rand());
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 21]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
/* uuid_create_from_name -- create a UUID using a "name" from a "name
|
|||
|
space" */
|
|||
|
void uuid_create_from_name(
|
|||
|
uuid_t * uuid, /* resulting UUID */
|
|||
|
uuid_t nsid, /* UUID to serve as context, so identical
|
|||
|
names from different name spaces generate
|
|||
|
different UUIDs */
|
|||
|
void * name, /* the name from which to generate a UUID */
|
|||
|
int namelen /* the length of the name */
|
|||
|
) {
|
|||
|
MD5_CTX c;
|
|||
|
unsigned char hash[16];
|
|||
|
uuid_t net_nsid; /* context UUID in network byte order */
|
|||
|
|
|||
|
/* put name space ID in network byte order so it hashes the same
|
|||
|
no matter what endian machine we're on */
|
|||
|
net_nsid = nsid;
|
|||
|
htonl(net_nsid.time_low);
|
|||
|
htons(net_nsid.time_mid);
|
|||
|
htons(net_nsid.time_hi_and_version);
|
|||
|
|
|||
|
MD5Init(&c);
|
|||
|
MD5Update(&c, &net_nsid, sizeof(uuid_t));
|
|||
|
MD5Update(&c, name, namelen);
|
|||
|
MD5Final(hash, &c);
|
|||
|
|
|||
|
/* the hash is in network byte order at this point */
|
|||
|
format_uuid_v3(uuid, hash);
|
|||
|
};
|
|||
|
|
|||
|
/* format_uuid_v3 -- make a UUID from a (pseudo)random 128 bit number
|
|||
|
*/
|
|||
|
void format_uuid_v3(uuid_t * uuid, unsigned char hash[16]) {
|
|||
|
/* Construct a version 3 uuid with the (pseudo-)random number
|
|||
|
* plus a few constants. */
|
|||
|
|
|||
|
memcpy(uuid, hash, sizeof(uuid_t));
|
|||
|
|
|||
|
/* convert UUID to local byte order */
|
|||
|
ntohl(uuid->time_low);
|
|||
|
ntohs(uuid->time_mid);
|
|||
|
ntohs(uuid->time_hi_and_version);
|
|||
|
|
|||
|
/* put in the variant and version bits */
|
|||
|
uuid->time_hi_and_version &= 0x0FFF;
|
|||
|
uuid->time_hi_and_version |= (3 << 12);
|
|||
|
uuid->clock_seq_hi_and_reserved &= 0x3F;
|
|||
|
uuid->clock_seq_hi_and_reserved |= 0x80;
|
|||
|
};
|
|||
|
|
|||
|
/* uuid_compare -- Compare two UUID's "lexically" and return
|
|||
|
-1 u1 is lexically before u2
|
|||
|
0 u1 is equal to u2
|
|||
|
1 u1 is lexically after u2
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 22]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
Note: lexical ordering is not temporal ordering!
|
|||
|
*/
|
|||
|
int uuid_compare(uuid_t *u1, uuid_t *u2)
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
#define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
|
|||
|
CHECK(u1->time_low, u2->time_low);
|
|||
|
CHECK(u1->time_mid, u2->time_mid);
|
|||
|
CHECK(u1->time_hi_and_version, u2->time_hi_and_version);
|
|||
|
CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved);
|
|||
|
CHECK(u1->clock_seq_low, u2->clock_seq_low)
|
|||
|
for (i = 0; i < 6; i++) {
|
|||
|
if (u1->node[i] < u2->node[i])
|
|||
|
return -1;
|
|||
|
if (u1->node[i] > u2->node[i])
|
|||
|
return 1;
|
|||
|
}
|
|||
|
return 0;
|
|||
|
};
|
|||
|
|
|||
|
sysdep.h
|
|||
|
|
|||
|
#include "copyrt.h"
|
|||
|
/* remove the following define if you aren't running WIN32 */
|
|||
|
#define WININC 0
|
|||
|
|
|||
|
#ifdef WININC
|
|||
|
#include <windows.h>
|
|||
|
#else
|
|||
|
#include <sys/types.h>
|
|||
|
#include <sys/time.h>
|
|||
|
#include <sys/sysinfo.h>
|
|||
|
#endif
|
|||
|
|
|||
|
/* change to point to where MD5 .h's live */
|
|||
|
/* get MD5 sample implementation from RFC 1321 */
|
|||
|
#include "global.h"
|
|||
|
#include "md5.h"
|
|||
|
|
|||
|
/* set the following to the number of 100ns ticks of the actual
|
|||
|
resolution of
|
|||
|
your system's clock */
|
|||
|
#define UUIDS_PER_TICK 1024
|
|||
|
|
|||
|
/* Set the following to a call to acquire a system wide global lock
|
|||
|
*/
|
|||
|
#define LOCK
|
|||
|
#define UNLOCK
|
|||
|
|
|||
|
typedef unsigned long unsigned32;
|
|||
|
typedef unsigned short unsigned16;
|
|||
|
typedef unsigned char unsigned8;
|
|||
|
typedef unsigned char byte;
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 23]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/* Set this to what your compiler uses for 64 bit data type */
|
|||
|
#ifdef WININC
|
|||
|
#define unsigned64_t unsigned __int64
|
|||
|
#define I64(C) C
|
|||
|
#else
|
|||
|
#define unsigned64_t unsigned long long
|
|||
|
#define I64(C) C##LL
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
typedef unsigned64_t uuid_time_t;
|
|||
|
typedef struct {
|
|||
|
char nodeID[6];
|
|||
|
} uuid_node_t;
|
|||
|
|
|||
|
void get_ieee_node_identifier(uuid_node_t *node);
|
|||
|
void get_system_time(uuid_time_t *uuid_time);
|
|||
|
void get_random_info(char seed[16]);
|
|||
|
|
|||
|
|
|||
|
sysdep.c
|
|||
|
|
|||
|
#include "copyrt.h"
|
|||
|
#include <stdio.h>
|
|||
|
#include "sysdep.h"
|
|||
|
|
|||
|
/* system dependent call to get IEEE node ID.
|
|||
|
This sample implementation generates a random node ID
|
|||
|
*/
|
|||
|
void get_ieee_node_identifier(uuid_node_t *node) {
|
|||
|
char seed[16];
|
|||
|
FILE * fd;
|
|||
|
static inited = 0;
|
|||
|
static uuid_node_t saved_node;
|
|||
|
|
|||
|
if (!inited) {
|
|||
|
fd = fopen("nodeid", "rb");
|
|||
|
if (fd) {
|
|||
|
fread(&saved_node, sizeof(uuid_node_t), 1, fd);
|
|||
|
fclose(fd);
|
|||
|
}
|
|||
|
else {
|
|||
|
get_random_info(seed);
|
|||
|
seed[0] |= 0x80;
|
|||
|
memcpy(&saved_node, seed, sizeof(uuid_node_t));
|
|||
|
fd = fopen("nodeid", "wb");
|
|||
|
if (fd) {
|
|||
|
fwrite(&saved_node, sizeof(uuid_node_t), 1, fd);
|
|||
|
fclose(fd);
|
|||
|
};
|
|||
|
};
|
|||
|
inited = 1;
|
|||
|
};
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 24]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
*node = saved_node;
|
|||
|
};
|
|||
|
|
|||
|
/* system dependent call to get the current system time.
|
|||
|
Returned as 100ns ticks since Oct 15, 1582, but resolution may be
|
|||
|
less than 100ns.
|
|||
|
*/
|
|||
|
#ifdef _WINDOWS_
|
|||
|
|
|||
|
void get_system_time(uuid_time_t *uuid_time) {
|
|||
|
ULARGE_INTEGER time;
|
|||
|
|
|||
|
GetSystemTimeAsFileTime((FILETIME *)&time);
|
|||
|
|
|||
|
/* NT keeps time in FILETIME format which is 100ns ticks since
|
|||
|
Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
|
|||
|
The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
|
|||
|
+ 18 years and 5 leap days.
|
|||
|
*/
|
|||
|
|
|||
|
time.QuadPart +=
|
|||
|
(unsigned __int64) (1000*1000*10) // seconds
|
|||
|
* (unsigned __int64) (60 * 60 * 24) // days
|
|||
|
* (unsigned __int64) (17+30+31+365*18+5); // # of days
|
|||
|
|
|||
|
*uuid_time = time.QuadPart;
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
void get_random_info(char seed[16]) {
|
|||
|
MD5_CTX c;
|
|||
|
typedef struct {
|
|||
|
MEMORYSTATUS m;
|
|||
|
SYSTEM_INFO s;
|
|||
|
FILETIME t;
|
|||
|
LARGE_INTEGER pc;
|
|||
|
DWORD tc;
|
|||
|
DWORD l;
|
|||
|
char hostname[MAX_COMPUTERNAME_LENGTH + 1];
|
|||
|
} randomness;
|
|||
|
randomness r;
|
|||
|
|
|||
|
MD5Init(&c);
|
|||
|
/* memory usage stats */
|
|||
|
GlobalMemoryStatus(&r.m);
|
|||
|
/* random system stats */
|
|||
|
GetSystemInfo(&r.s);
|
|||
|
/* 100ns resolution (nominally) time of day */
|
|||
|
GetSystemTimeAsFileTime(&r.t);
|
|||
|
/* high resolution performance counter */
|
|||
|
QueryPerformanceCounter(&r.pc);
|
|||
|
/* milliseconds since last boot */
|
|||
|
r.tc = GetTickCount();
|
|||
|
r.l = MAX_COMPUTERNAME_LENGTH + 1;
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 25]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
GetComputerName(r.hostname, &r.l );
|
|||
|
MD5Update(&c, &r, sizeof(randomness));
|
|||
|
MD5Final(seed, &c);
|
|||
|
};
|
|||
|
#else
|
|||
|
|
|||
|
void get_system_time(uuid_time_t *uuid_time)
|
|||
|
{
|
|||
|
struct timeval tp;
|
|||
|
|
|||
|
gettimeofday(&tp, (struct timezone *)0);
|
|||
|
|
|||
|
/* Offset between UUID formatted times and Unix formatted times.
|
|||
|
UUID UTC base time is October 15, 1582.
|
|||
|
Unix base time is January 1, 1970.
|
|||
|
*/
|
|||
|
*uuid_time = (tp.tv_sec * 10000000) + (tp.tv_usec * 10) +
|
|||
|
I64(0x01B21DD213814000);
|
|||
|
};
|
|||
|
|
|||
|
void get_random_info(char seed[16]) {
|
|||
|
MD5_CTX c;
|
|||
|
typedef struct {
|
|||
|
struct sysinfo s;
|
|||
|
struct timeval t;
|
|||
|
char hostname[257];
|
|||
|
} randomness;
|
|||
|
randomness r;
|
|||
|
|
|||
|
MD5Init(&c);
|
|||
|
sysinfo(&r.s);
|
|||
|
gettimeofday(&r.t, (struct timezone *)0);
|
|||
|
gethostname(r.hostname, 256);
|
|||
|
MD5Update(&c, &r, sizeof(randomness));
|
|||
|
MD5Final(seed, &c);
|
|||
|
};
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
utest.c
|
|||
|
|
|||
|
#include "copyrt.h"
|
|||
|
#include "sysdep.h"
|
|||
|
#include <stdio.h>
|
|||
|
#include "uuid.h"
|
|||
|
|
|||
|
uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */
|
|||
|
0x6ba7b810,
|
|||
|
0x9dad,
|
|||
|
0x11d1,
|
|||
|
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 26]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
/* puid -- print a UUID */
|
|||
|
void puid(uuid_t u);
|
|||
|
|
|||
|
/* Simple driver for UUID generator */
|
|||
|
void main(int argc, char **argv) {
|
|||
|
uuid_t u;
|
|||
|
int f;
|
|||
|
|
|||
|
uuid_create(&u);
|
|||
|
printf("uuid_create() -> "); puid(u);
|
|||
|
|
|||
|
f = uuid_compare(&u, &u);
|
|||
|
printf("uuid_compare(u,u): %d\n", f); /* should be 0 */
|
|||
|
f = uuid_compare(&u, &NameSpace_DNS);
|
|||
|
printf("uuid_compare(u, NameSpace_DNS): %d\n", f); /* s.b. 1 */
|
|||
|
f = uuid_compare(&NameSpace_DNS, &u);
|
|||
|
printf("uuid_compare(NameSpace_DNS, u): %d\n", f); /* s.b. -1 */
|
|||
|
|
|||
|
uuid_create_from_name(&u, NameSpace_DNS, "www.widgets.com", 15);
|
|||
|
printf("uuid_create_from_name() -> "); puid(u);
|
|||
|
};
|
|||
|
|
|||
|
void puid(uuid_t u) {
|
|||
|
int i;
|
|||
|
|
|||
|
printf("%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", u.time_low, u.time_mid,
|
|||
|
u.time_hi_and_version, u.clock_seq_hi_and_reserved,
|
|||
|
u.clock_seq_low);
|
|||
|
for (i = 0; i < 6; i++)
|
|||
|
printf("%2.2x", u.node[i]);
|
|||
|
printf("\n");
|
|||
|
};
|
|||
|
|
|||
|
Appendix B _ Sample output of utest
|
|||
|
|
|||
|
uuid_create() -> 7d444840-9dc0-11d1-b245-5ffdce74fad2
|
|||
|
uuid_compare(u,u): 0
|
|||
|
uuid_compare(u, NameSpace_DNS): 1
|
|||
|
uuid_compare(NameSpace_DNS, u): -1
|
|||
|
uuid_create_from_name() -> e902893a-9d22-3c7e-a7b8-d6e313b71d9f
|
|||
|
|
|||
|
Appendix C _ Some name space IDs
|
|||
|
|
|||
|
This appendix lists the name space IDs for some potentially
|
|||
|
interesting name spaces, as initialized C structures and in the
|
|||
|
string representation defined in section 3.5
|
|||
|
|
|||
|
uuid_t NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */
|
|||
|
0x6ba7b810,
|
|||
|
0x9dad,
|
|||
|
0x11d1,
|
|||
|
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
Leach, Salz expires Aug 1998 [Page 27]
|
|||
|
|
|||
|
|
|||
|
Internet-Draft UUIDs and GUIDs (DRAFT) 02/04/98
|
|||
|
|
|||
|
|
|||
|
uuid_t NameSpace_URL = { /* 6ba7b811-9dad-11d1-80b4-00c04fd430c8 */
|
|||
|
0x6ba7b811,
|
|||
|
0x9dad,
|
|||
|
0x11d1,
|
|||
|
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
|
|||
|
};
|
|||
|
|
|||
|
uuid_t NameSpace_OID = { /* 6ba7b812-9dad-11d1-80b4-00c04fd430c8 */
|
|||
|
0x6ba7b812,
|
|||
|
0x9dad,
|
|||
|
0x11d1,
|
|||
|
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
|
|||
|
};
|
|||
|
|
|||
|
uuid_t NameSpace_X500 = { /* 6ba7b814-9dad-11d1-80b4-00c04fd430c8 */
|
|||
|
0x6ba7b814,
|
|||
|
0x9dad,
|
|||
|
0x11d1,
|
|||
|
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|