00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "copyrt.h"
00022 #include <string.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <time.h>
00026 #include <netinet/in.h>
00027 #include "sysdep.h"
00028 #include "uuid.h"
00029
00030
00031 static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp,
00032 uuid_node_t * node);
00033 static void write_state(unsigned16 clockseq, uuid_time_t timestamp,
00034 uuid_node_t node);
00035 static void format_uuid_v1(uuid__t * uuid, unsigned16 clockseq,
00036 uuid_time_t timestamp, uuid_node_t node);
00037 static void format_uuid_v3(uuid__t * uuid, unsigned char hash[16]);
00038 static void get_current_time(uuid_time_t * timestamp);
00039 static unsigned16 true_random(void);
00040
00041
00042 int uuid_create(uuid__t * uuid) {
00043 uuid_time_t timestamp, last_time;
00044 unsigned16 clockseq;
00045 uuid_node_t node;
00046 uuid_node_t last_node;
00047 int f;
00048
00049
00050 LOCK;
00051
00052
00053 get_current_time(×tamp);
00054
00055
00056 get_ieee_node_identifier(&node);
00057
00058
00059 f = read_state(&clockseq, &last_time, &last_node);
00060
00061
00062
00063 if (!f || memcmp(&node, &last_node, sizeof(uuid_node_t)))
00064 clockseq = true_random();
00065 else if (timestamp < last_time)
00066 clockseq++;
00067
00068
00069 format_uuid_v1(uuid, clockseq, timestamp, node);
00070
00071
00072 write_state(clockseq, timestamp, node);
00073
00074 UNLOCK;
00075 return(1);
00076 };
00077
00078
00079
00080 void format_uuid_v1(uuid__t * uuid, unsigned16 clock_seq, uuid_time_t
00081 timestamp, uuid_node_t node) {
00082
00083
00084 uuid->time_low = (unsigned long)(timestamp & 0xFFFFFFFF);
00085 uuid->time_mid = (unsigned short)((timestamp >> 32) & 0xFFFF);
00086 uuid->time_hi_and_version = (unsigned short)((timestamp >> 48) &
00087 0x0FFF);
00088 uuid->time_hi_and_version |= (1 << 12);
00089 uuid->clock_seq_low = clock_seq & 0xFF;
00090 uuid->clock_seq_hi_and_reserved = (clock_seq & 0x3F00) >> 8;
00091 uuid->clock_seq_hi_and_reserved |= 0x80;
00092 memcpy(&uuid->node, &node, sizeof uuid->node);
00093 };
00094
00095
00096 typedef struct {
00097 uuid_time_t ts;
00098 uuid_node_t node;
00099 unsigned16 cs;
00100 } uuid_state;
00101
00102 static uuid_state st;
00103
00104
00105 int read_state(unsigned16 *clockseq, uuid_time_t *timestamp,
00106 uuid_node_t *node) {
00107 FILE * fd;
00108 static int inited = 0;
00109
00110
00111 if (!inited) {
00112 fd = fopen("state", "rb");
00113 if (!fd)
00114 return (0);
00115 fread(&st, sizeof(uuid_state), 1, fd);
00116 fclose(fd);
00117 inited = 1;
00118 };
00119 *clockseq = st.cs;
00120 *timestamp = st.ts;
00121 *node = st.node;
00122 return(1);
00123 };
00124
00125
00126
00127 void write_state(unsigned16 clockseq, uuid_time_t timestamp,
00128 uuid_node_t node) {
00129 FILE * fd;
00130 static int inited = 0;
00131 static uuid_time_t next_save;
00132
00133 if (!inited) {
00134 next_save = timestamp;
00135 inited = 1;
00136 };
00137
00138 st.cs = clockseq;
00139 st.ts = timestamp;
00140 st.node = node;
00141 if (timestamp >= next_save) {
00142 fd = fopen("state", "wb");
00143 fwrite(&st, sizeof(uuid_state), 1, fd);
00144 fclose(fd);
00145
00146 next_save = timestamp + (10 * 10 * 1000 * 1000);
00147 };
00148 };
00149
00150
00151
00152
00153 void get_current_time(uuid_time_t * timestamp) {
00154 uuid_time_t time_now;
00155 static uuid_time_t time_last;
00156 static unsigned16 uuids_this_tick;
00157 static int inited = 0;
00158
00159 if (!inited) {
00160
00161 get_system_time(&time_now);
00162 uuids_this_tick = UUIDS_PER_TICK;
00163 inited = 1;
00164 };
00165
00166 while (1) {
00167 get_system_time(&time_now);
00168
00169
00170 if (time_last != time_now) {
00171
00172 uuids_this_tick = 0;
00173 break;
00174 };
00175 if (uuids_this_tick < UUIDS_PER_TICK) {
00176 uuids_this_tick++;
00177 break;
00178 };
00179
00180 };
00181
00182 *timestamp = time_now + uuids_this_tick;
00183
00184 time_last = time_now;
00185
00186 };
00187
00188
00189
00190 static unsigned16
00191 true_random(void)
00192 {
00193 static int inited = 0;
00194 uuid_time_t time_now;
00195
00196 if (!inited) {
00197 get_system_time(&time_now);
00198 time_now = time_now/UUIDS_PER_TICK;
00199 srand((unsigned int)(((time_now >> 32) ^ time_now)&0xffffffff));
00200 inited = 1;
00201 };
00202
00203 return (rand());
00204 }
00205 #ifdef _WINDOWS_
00206 #else
00207
00208
00209 void uuid_create_from_name(
00210 uuid__t * uuid,
00211 uuid__t nsid,
00212
00213
00214 void * name,
00215 int namelen
00216 ) {
00217 MD5_CTX c;
00218 unsigned char hash[16];
00219 uuid__t net_nsid;
00220
00221
00222
00223 net_nsid = nsid;
00224 (net_nsid.time_low);
00225 htons(net_nsid.time_mid);
00226 htons(net_nsid.time_hi_and_version);
00227
00228 MD5Init(&c);
00229 MD5Update(&c, (unsigned char*)&net_nsid, sizeof(uuid__t));
00230 MD5Update(&c, (unsigned char*)name, namelen);
00231 MD5Final(hash, &c);
00232
00233
00234 format_uuid_v3(uuid, hash);
00235 };
00236
00237
00238
00239 void format_uuid_v3(uuid__t * uuid, unsigned char hash[16]) {
00240
00241
00242
00243 memcpy(uuid, hash, sizeof(uuid__t));
00244
00245
00246 ntohl(uuid->time_low);
00247 ntohs(uuid->time_mid);
00248 ntohs(uuid->time_hi_and_version);
00249
00250
00251 uuid->time_hi_and_version &= 0x0FFF;
00252 uuid->time_hi_and_version |= (3 << 12);
00253 uuid->clock_seq_hi_and_reserved &= 0x3F;
00254 uuid->clock_seq_hi_and_reserved |= 0x80;
00255 };
00256 #endif
00257
00258
00259
00260
00261
00262
00263
00264 int uuid_compare(uuid__t *u1, uuid__t *u2)
00265 {
00266 int i;
00267
00268 #define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
00269 CHECK(u1->time_low, u2->time_low);
00270 CHECK(u1->time_mid, u2->time_mid);
00271 CHECK(u1->time_hi_and_version, u2->time_hi_and_version);
00272 CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved);
00273 CHECK(u1->clock_seq_low, u2->clock_seq_low)
00274 for (i = 0; i < 6; i++) {
00275 if (u1->node[i] < u2->node[i])
00276 return -1;
00277 if (u1->node[i] > u2->node[i])
00278 return 1;
00279 }
00280 return 0;
00281 };