~hikiko/nux/arb-srgba-shader

« back to all changes in this revision

Viewing changes to NuxCore/Crypto/NUUID.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-01 19:25:37 UTC
  • Revision ID: neil.patel@canonical.com-20100901192537-mfz7rm6q262pewg6
Import and build NuxCore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "NKernel.h"
 
2
#include "NUUID.h"
 
3
#include "NMD5.h"
 
4
#include "NSHA1.h"
 
5
#include "NSHA2.h"
 
6
 
 
7
#ifdef _WIN32
 
8
    #include "Winsock2.h"
 
9
    #pragma comment(lib, "ws2_32")
 
10
#endif
 
11
 
 
12
#ifdef INL_PS3
 
13
    #include <netinet/in.h>
 
14
#endif
 
15
 
 
16
#include <string.h>
 
17
#include <stdio.h>
 
18
#include <stdlib.h>
 
19
#include <time.h>
 
20
 
 
21
NAMESPACE_BEGIN
 
22
 
 
23
#define MD5_Final MD5Final
 
24
#define MD5_Init MD5Init
 
25
#define MD5_Update MD5Update
 
26
 
 
27
#define SHA1_Final SHA1Result
 
28
#define SHA1_Init SHA1Reset
 
29
#define SHA1_Update SHA1Input
 
30
 
 
31
////////////////////////////////////////////////////////////////
 
32
//// Begin system dependent
 
33
//// system dependent call to get IEEE node ID.
 
34
//// This sample implementation generates a random node ID.
 
35
////////////////////////////////////////////////////////////////
 
36
 
 
37
// See: http://xml.resource.org/public/rfc/html/rfc4122.html
 
38
 
 
39
 
 
40
/* set the following to the number of 100ns ticks of the actual
 
41
resolution of your system's clock */
 
42
#define UUIDS_PER_TICK 1024
 
43
 
 
44
/* Set the following to a calls to get and release a global lock */
 
45
#define LOCK
 
46
#define UNLOCK
 
47
 
 
48
 
 
49
/* Set this to what your compiler uses for 64-bit data type */
 
50
#ifdef _WIN32
 
51
    #define unsigned64_t t_u64
 
52
    #define I64(C) C
 
53
#elif _WIN64
 
54
    #define unsigned64_t unsigned long long
 
55
    #define I64(C) C##LL
 
56
#elif INL_PS3
 
57
    #define unsigned64_t t_u64
 
58
    #define I64(C) C
 
59
#endif
 
60
 
 
61
typedef unsigned64_t uuid_time_t;
 
62
typedef struct {
 
63
    unsigned char nodeID[6];
 
64
} uuid_node_t;
 
65
 
 
66
void get_ieee_node_identifier(uuid_node_t *node);
 
67
void get_system_time(uuid_time_t *uuid_time);
 
68
void get_random_info(char seed[16]);
 
69
 
 
70
 
 
71
/* uuid_create -- generate a UUID version 1 */
 
72
int uuid_create(uuid_t * uuid);
 
73
 
 
74
/* 
 
75
    uuid_create_md5_from_name -- create a version 3 (MD5) UUID using a
 
76
    "name" from a "name space"
 
77
*/
 
78
void uuid_create_md5_from_name(
 
79
                               uuid_t *uuid,         /* resulting UUID */
 
80
                               uuid_t nsid,          /* UUID of the namespace */
 
81
                               void *name,           /* the name from which to generate a UUID */
 
82
                               int namelen           /* the length of the name */
 
83
                               );
 
84
 
 
85
/*
 
86
    uuid_create_sha1_from_name -- create a version 5 (SHA-1) UUID
 
87
    using a "name" from a "name space"
 
88
*/
 
89
void uuid_create_sha1_from_name(
 
90
 
 
91
                                uuid_t *uuid,         /* resulting UUID */
 
92
                                uuid_t nsid,          /* UUID of the namespace */
 
93
                                void *name,           /* the name from which to generate a UUID */
 
94
                                int namelen           /* the length of the name */
 
95
                                );
 
96
 
 
97
/* uuid_compare --  Compare two UUID's "lexically" and return
 
98
    -1   u1 is lexically before u2
 
99
    0   u1 is equal to u2
 
100
    1   u1 is lexically after u2
 
101
    Note that lexical ordering is not temporal ordering!
 
102
*/
 
103
int uuid_compare(uuid_t *u1, uuid_t *u2);
 
104
 
 
105
 
 
106
void get_ieee_node_identifier(uuid_node_t *node)
 
107
{
 
108
    static int inited = 0;
 
109
    static uuid_node_t saved_node;
 
110
    char seed[16];
 
111
    FILE *fp = NULL;
 
112
 
 
113
    if (!inited)
 
114
    {
 
115
#if (defined INL_VISUAL_STUDIO_2005) || (defined INL_VISUAL_STUDIO_2008)
 
116
        fopen_s(&fp, "nodeid", "rb");
 
117
#else
 
118
        fp = fopen("nodeid", "rb");
 
119
#endif
 
120
        if (fp)
 
121
        {
 
122
            fread(&saved_node, sizeof(saved_node), 1, fp);
 
123
            fclose(fp);
 
124
        }
 
125
        else
 
126
        {
 
127
            get_random_info(seed);
 
128
            seed[0] |= 0x01;
 
129
            memcpy(&saved_node, seed, sizeof(saved_node));
 
130
#if (defined INL_VISUAL_STUDIO_2005) || (defined INL_VISUAL_STUDIO_2008)
 
131
            fopen_s(&fp, "nodeid", "wb");
 
132
#else
 
133
            fp = fopen("nodeid", "wb");
 
134
#endif
 
135
            if (fp)
 
136
            {
 
137
                fwrite(&saved_node, sizeof(saved_node), 1, fp);
 
138
                fclose(fp);
 
139
            }
 
140
        }
 
141
        inited = 1;
 
142
    }
 
143
 
 
144
    *node = saved_node;
 
145
}
 
146
 
 
147
/* system dependent call to get the current system time. Returned as
 
148
100ns ticks since UUID epoch, but resolution may be less than
 
149
100ns. */
 
150
#ifdef _WINDOWS_
 
151
 
 
152
void get_system_time(uuid_time_t *uuid_time)
 
153
{
 
154
    ULARGE_INTEGER time;
 
155
 
 
156
    /* NT keeps time in FILETIME format which is 100ns ticks since
 
157
    Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
 
158
    The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
 
159
    + 18 years and 5 leap days. */
 
160
    GetSystemTimeAsFileTime((FILETIME *)&time);
 
161
    time.QuadPart +=
 
162
 
 
163
        (unsigned __int64) (1000*1000*10)       // seconds
 
164
        * (unsigned __int64) (60 * 60 * 24)       // days
 
165
        * (unsigned __int64) (17+30+31+365*18+5); // # of days
 
166
    *uuid_time = time.QuadPart;
 
167
}
 
168
 
 
169
/* Sample code, not for use in production; see RFC 1750 */
 
170
void get_random_info(char seed[16])
 
171
{
 
172
    MD5_CTX c;
 
173
    struct {
 
174
        MEMORYSTATUS m;
 
175
        SYSTEM_INFO s;
 
176
        FILETIME t;
 
177
        LARGE_INTEGER pc;
 
178
        DWORD tc;
 
179
        DWORD l;
 
180
        TCHAR hostname[MAX_COMPUTERNAME_LENGTH + 1];
 
181
    } r;
 
182
 
 
183
    MD5_Init(&c);
 
184
    GlobalMemoryStatus(&r.m);
 
185
    GetSystemInfo(&r.s);
 
186
    GetSystemTimeAsFileTime(&r.t);
 
187
    QueryPerformanceCounter(&r.pc);
 
188
    r.tc = GetTickCount();
 
189
 
 
190
 
 
191
    r.l = MAX_COMPUTERNAME_LENGTH + 1;
 
192
    GetComputerName(r.hostname, &r.l);
 
193
    MD5_Update(&c, (unsigned char*)&r, sizeof r);
 
194
    MD5_Final(&c);
 
195
    memcpy((void*)&(seed[0]), (void*)&(c.digest[0]), 16);
 
196
}
 
197
 
 
198
#else
 
199
 
 
200
void get_system_time(uuid_time_t *uuid_time)
 
201
{
 
202
#ifdef _WIN32
 
203
    struct timeval tp;
 
204
 
 
205
    gettimeofday(&tp, (struct timezone *)0);
 
206
 
 
207
    // Offset between UUID formatted times and Unix formatted times.  UUID UTC base time is October 15, 1582.
 
208
    // Unix base time is January 1, 1970.
 
209
    *uuid_time = ((unsigned64)tp.tv_sec * 10000000) + ((unsigned64)tp.tv_usec * 10) + I64(0x01B21DD213814000LL);
 
210
#else
 
211
    inlAssert(0);
 
212
#endif
 
213
}
 
214
 
 
215
/* Sample code, not for use in production; see RFC 1750 */
 
216
void get_random_info(char seed[16])
 
217
{
 
218
#ifdef _WIN32
 
219
    MD5_CTX c;
 
220
    struct {
 
221
        struct sysinfo s;
 
222
        struct timeval t;
 
223
        char hostname[257];
 
224
    } r;
 
225
 
 
226
    MD5_Init(&c);
 
227
    sysinfo(&r.s);
 
228
    gettimeofday(&r.t, (struct timezone *)0);
 
229
    gethostname(r.hostname, 256);
 
230
    MD5_Update(&c, &r, sizeof r);
 
231
    MD5_Final(seed, &c);
 
232
 
 
233
#else
 
234
    inlAssert(0);
 
235
#endif
 
236
}
 
237
 
 
238
#endif
 
239
 
 
240
////////////////////////////////////////////////////////////////
 
241
//// End system dependent
 
242
////////////////////////////////////////////////////////////////
 
243
 
 
244
/* various forward declarations */
 
245
static int read_state(unsigned16 *clockseq, uuid_time_t *timestamp,
 
246
                      uuid_node_t *node);
 
247
static void write_state(unsigned16 clockseq, uuid_time_t timestamp,
 
248
                        uuid_node_t node);
 
249
static void format_uuid_v1(uuid_t *uuid, unsigned16 clockseq,
 
250
                           uuid_time_t timestamp, uuid_node_t node);
 
251
 
 
252
static void format_uuid_v3or5(uuid_t *uuid, unsigned char hash[16],
 
253
                              int v);
 
254
static void get_current_time(uuid_time_t *timestamp);
 
255
static unsigned16 true_random(void);
 
256
 
 
257
// uuid_create -- generator a UUID
 
258
// Using IEEE 802 MAC addresses as a source of uniqueness.
 
259
// UUID version 1 values are computed using the MAC address of the host.
 
260
int GenerateUUID1(uuid_t *uuid)
 
261
{
 
262
    uuid_time_t timestamp, last_time;
 
263
    unsigned16 clockseq;
 
264
    uuid_node_t node;
 
265
    uuid_node_t last_node;
 
266
    int f;
 
267
 
 
268
    // acquire system-wide lock so we're alone
 
269
    LOCK;
 
270
    // get time, node ID, saved state from non-volatile storage
 
271
 
 
272
    // The timestap is a 60 bit value, representing the number of 100 nanosecond intervals since 15 October 1582 00:00:000000000.
 
273
    get_current_time(&timestamp);
 
274
    get_ieee_node_identifier(&node);
 
275
    // The clock ID is a 14 bit value
 
276
    f = read_state(&clockseq, &last_time, &last_node);
 
277
 
 
278
    // if no NV (non-volatile) state, or if clock went backwards, or node ID changed (e.g., new network card) change clockseq
 
279
    if (!f || memcmp(&node, &last_node, sizeof(node)))
 
280
        clockseq = true_random();
 
281
    else if (timestamp < last_time)
 
282
        clockseq++;
 
283
 
 
284
    // save the state for next time
 
285
    write_state(clockseq, timestamp, node);
 
286
 
 
287
    UNLOCK;
 
288
 
 
289
    // stuff fields into the UUID
 
290
    format_uuid_v1(uuid, clockseq, timestamp, node);
 
291
    return 1;
 
292
}
 
293
 
 
294
// This class defines a UUID (Universally Unique IDentifier), also      
 
295
// known as GUIDs (Globally Unique IDentifier). A UUID is 128 bits      
 
296
// long, and if generated according to this algorithm, is either        
 
297
// guaranteed to be different from all other UUIDs/GUIDs generated      
 
298
// until 3400 A.D. or extremely likely to be different. UUIDs were      
 
299
// originally used in the Network Computing System (NCS) and            
 
300
// later in the Open Software Foundation's (OSF) Distributed Computing  
 
301
// Environment (DCE).                                                   
 
302
//                                                                      
 
303
// Structure of universal unique IDs (UUIDs).                           
 
304
//                                                                      
 
305
// Depending on the network data representation, the multi-             
 
306
// octet unsigned integer fields are subject to byte swapping           
 
307
// when communicated between dissimilar endian machines.                
 
308
//                                                                      
 
309
 
 
310
// Field                        Data Type                   Octet  Note
 
311
//
 
312
// time_low                     unsigned 32 bit integer     0-3    The low field of the timestamp
 
313
// time_mid                     unsigned 16 bit integer     4-5    The middle field of the timestamp
 
314
// time_hi_and_version          unsigned 16 bit integer     6-7    The high field of the timestamp multiplexed with the version number
 
315
// clock_seq_hi_and_reserved    unsigned 8 bit integer      8      The high field of the clock sequence multiplexed with the variant
 
316
// clock_seq_low                unsigned 8 bit integer      9      The low field of the clock sequence
 
317
// node                         unsigned 48 bit integer     10-15  The spatially unique node identifier
 
318
 
 
319
//   0                   1                   2                   3
 
320
//   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
 
321
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
322
//   |                          time_low                             |
 
323
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
324
//   |       time_mid                |         time_hi_and_version   |
 
325
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
326
//   |clk_seq_hi_res |  clk_seq_low  |         node (0-1)            |
 
327
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
328
//   |                         node (2-5)                            |
 
329
//   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
330
 
 
331
// The version number is in the most significant 4 bits of the time_hi_and_version field.
 
332
//     Msb0  Msb1  Msb2  Msb3   Version Description
 
333
//     0     0     0     1        1     The time-based version specified in this document.
 
334
//     0     0     1     0        2     DCE Security version, with embedded POSIX UIDs.
 
335
//     0     0     1     1        3     The name-based version specified in this document that uses MD5 hashing.
 
336
//     0     1     0     0        4     The randomly or pseudo-randomly generated version specified in this document.
 
337
//     0     1     0     1        5     The name-based version specified in this document that uses SHA-1 hashing.
 
338
 
 
339
 
 
340
// format_uuid_v1 -- make a UUID from the timestamp, clockseq, and node ID
 
341
void format_uuid_v1(uuid_t* uuid, unsigned16 clock_seq, uuid_time_t timestamp, uuid_node_t node)
 
342
{
 
343
    // Construct a version 1 uuid with the information we've gathered plus a few constants.
 
344
    uuid->time_low              = (unsigned long)(timestamp & 0xFFFFFFFF);
 
345
    uuid->time_mid              = (unsigned short)((timestamp >> 32) & 0xFFFF);
 
346
    uuid->time_hi_and_version   = (unsigned short)((timestamp >> 48) & 0x0FFF);
 
347
 
 
348
 
 
349
    uuid->time_hi_and_version           |= (1 << 12);   
 
350
    uuid->clock_seq_low                 = clock_seq & 0xFF;
 
351
    uuid->clock_seq_hi_and_reserved     = (clock_seq & 0x3F00) >> 8;
 
352
    uuid->clock_seq_hi_and_reserved     |= 0x80;
 
353
    memcpy(&uuid->node, &node, sizeof(uuid->node));
 
354
}
 
355
 
 
356
/* data type for UUID generator persistent state */
 
357
typedef struct
 
358
{
 
359
    uuid_time_t  ts;       /* saved timestamp */
 
360
    uuid_node_t  node;     /* saved node ID */
 
361
    unsigned16   cs;       /* saved clock sequence */
 
362
} uuid_state;
 
363
 
 
364
static uuid_state st;
 
365
 
 
366
// read_state -- read UUID generator state from non-volatile store
 
367
int read_state(unsigned16 *clockseq, uuid_time_t *timestamp,
 
368
               uuid_node_t *node)
 
369
{
 
370
    static int inited = 0;
 
371
    FILE *fp;
 
372
 
 
373
    /* only need to read state once per boot */
 
374
    if (!inited)
 
375
    {
 
376
#if (defined INL_VISUAL_STUDIO_2005) || (defined INL_VISUAL_STUDIO_2008)
 
377
        fopen_s(&fp, "state", "rb");
 
378
#else
 
379
        fp = fopen("state", "rb");
 
380
#endif
 
381
        if (fp == NULL)
 
382
            return 0;
 
383
        fread(&st, sizeof st, 1, fp);
 
384
        fclose(fp);
 
385
        inited = 1;
 
386
    }
 
387
    *clockseq = st.cs;
 
388
    *timestamp = st.ts;
 
389
    *node = st.node;
 
390
    return 1;
 
391
}
 
392
 
 
393
// write_state -- save UUID generator state back to non-volatile storage
 
394
void write_state(unsigned16 clockseq, uuid_time_t timestamp,
 
395
                 uuid_node_t node)
 
396
{
 
397
    static int inited = 0;
 
398
    static uuid_time_t next_save;
 
399
    FILE* fp = NULL;
 
400
    if (!inited) {
 
401
        next_save = timestamp;
 
402
        inited = 1;
 
403
    }
 
404
 
 
405
    /* always save state to volatile shared state */
 
406
    st.cs = clockseq;
 
407
    st.ts = timestamp;
 
408
    st.node = node;
 
409
    if (timestamp >= next_save)
 
410
    {
 
411
#if (defined INL_VISUAL_STUDIO_2005) || (defined INL_VISUAL_STUDIO_2008)
 
412
        fopen_s(&fp, "state", "wb");
 
413
#else
 
414
        fp = fopen("state", "wb");
 
415
#endif
 
416
        fwrite(&st, sizeof st, 1, fp);
 
417
        fclose(fp);
 
418
        /* schedule next save for 10 seconds from now */
 
419
        next_save = timestamp + (10 * 10 * 1000 * 1000);
 
420
    }
 
421
}
 
422
 
 
423
// get-current_time -- get time as 60-bit 100ns ticks since UUID epoch.
 
424
// Compensate for the fact that real clock resolution is
 
425
// less than 100ns.
 
426
void get_current_time(uuid_time_t *timestamp)
 
427
{
 
428
    static int inited = 0;
 
429
    static uuid_time_t time_last;
 
430
    static unsigned16 uuids_this_tick;
 
431
    uuid_time_t time_now;
 
432
 
 
433
    if (!inited) {
 
434
        get_system_time(&time_now);
 
435
        uuids_this_tick = UUIDS_PER_TICK;
 
436
        inited = 1;
 
437
    }
 
438
 
 
439
    for ( ; ; ) {
 
440
        get_system_time(&time_now);
 
441
 
 
442
        /* if clock reading changed since last UUID generated, */
 
443
        if (time_last != time_now) {
 
444
            /* reset count of uuids gen'd with this clock reading */
 
445
            uuids_this_tick = 0;
 
446
            time_last = time_now;
 
447
            break;
 
448
        }
 
449
        if (uuids_this_tick < UUIDS_PER_TICK) {
 
450
            uuids_this_tick++;
 
451
            break;
 
452
        }
 
453
        /* going too fast for our clock; spin */
 
454
    }
 
455
    /* add the count of uuids to low order bits of the clock reading */
 
456
    *timestamp = time_now + uuids_this_tick;
 
457
}
 
458
 
 
459
// true_random -- generate a crypto-quality random number. This sample doesn't do that.
 
460
static unsigned16 true_random(void)
 
461
{
 
462
    static int inited = 0;
 
463
    uuid_time_t time_now;
 
464
 
 
465
    if (!inited) {
 
466
        get_system_time(&time_now);
 
467
        time_now = time_now / UUIDS_PER_TICK;
 
468
        srand((unsigned int)
 
469
            (((time_now >> 32) ^ time_now) & 0xffffffff));
 
470
        inited = 1;
 
471
    }
 
472
 
 
473
    return rand();
 
474
}
 
475
 
 
476
// create a version 3 (MD5) UUID using a "name" from a "name space"
 
477
void uuid_create_md5_from_name(uuid_t *uuid, uuid_t nsid, void *name, int namelen)
 
478
{
 
479
    MD5_CTX c;
 
480
    unsigned char hash[16];
 
481
    uuid_t net_nsid;
 
482
 
 
483
    /* put name space ID in network byte order so it hashes the same
 
484
    no matter what endian machine we're on */
 
485
    net_nsid = nsid;
 
486
    net_nsid.time_low = htonl(net_nsid.time_low);
 
487
    net_nsid.time_mid = htons(net_nsid.time_mid);
 
488
    net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version);
 
489
 
 
490
    MD5_Init(&c);
 
491
    MD5_Update(&c, (unsigned char*)&net_nsid, sizeof net_nsid);
 
492
    MD5_Update(&c, (unsigned char*)name, namelen);
 
493
    MD5_Final(&c);
 
494
    memcpy((void*)&(hash[0]), (void*)&(c.digest[0]), 16);
 
495
 
 
496
    /* the hash is in network byte order at this point */
 
497
    format_uuid_v3or5(uuid, hash, 3);
 
498
}
 
499
 
 
500
void GenerateUUID3(uuid_t *uuid, uuid_t nsid, void *name, int namelen)
 
501
{
 
502
    uuid_create_md5_from_name(uuid, nsid, name, namelen);
 
503
}
 
504
 
 
505
#define SHA_CTX SHA1Context
 
506
 
 
507
//  format_uuid_v3or5 -- make a UUID from a (pseudo)random 128-bit number
 
508
void format_uuid_v3or5(uuid_t *uuid, unsigned char hash[16], int version)
 
509
{
 
510
    /* convert UUID to local byte order */
 
511
    memcpy(uuid, hash, sizeof *uuid);
 
512
    uuid->time_low = ntohl(uuid->time_low);
 
513
    uuid->time_mid = ntohs(uuid->time_mid);
 
514
    uuid->time_hi_and_version = ntohs(uuid->time_hi_and_version);
 
515
 
 
516
    /* put in the variant and version bits */
 
517
    uuid->time_hi_and_version &= 0x0FFF;
 
518
    uuid->time_hi_and_version |= (version << 12);
 
519
    uuid->clock_seq_hi_and_reserved &= 0x3F;
 
520
    uuid->clock_seq_hi_and_reserved |= 0x80;
 
521
}
 
522
 
 
523
// Create a version 5 (SHA-1) UUID using a "name" from a "name space"
 
524
void uuid_create_sha1_from_name(uuid_t *uuid, uuid_t nsid, void *name, int namelen)
 
525
{
 
526
    SHA_CTX c;
 
527
    unsigned char hash[20];
 
528
    uuid_t net_nsid;
 
529
 
 
530
    /* put name space ID in network byte order so it hashes the same
 
531
    no matter what endian machine we're on */
 
532
    net_nsid = nsid;
 
533
    net_nsid.time_low = htonl(net_nsid.time_low);
 
534
    net_nsid.time_mid = htons(net_nsid.time_mid);
 
535
    net_nsid.time_hi_and_version = htons(net_nsid.time_hi_and_version);
 
536
 
 
537
    SHA1_Init(&c);
 
538
    SHA1_Update(&c, (const unsigned char*)&net_nsid, sizeof net_nsid);
 
539
    SHA1_Update(&c, (const unsigned char*)name, namelen);
 
540
    SHA1_Final(/*hash,*/ &c);
 
541
    memcpy((void*)&(hash[0]), (void*)&(c.Message_Digest[0]), 16);
 
542
 
 
543
    /* the hash is in network byte order at this point */
 
544
    format_uuid_v3or5(uuid, hash, 5);
 
545
}
 
546
 
 
547
void GenerateUUID5(uuid_t *uuid, uuid_t nsid, void *name, int namelen)
 
548
{
 
549
    uuid_create_sha1_from_name(uuid, nsid, name, namelen);
 
550
}
 
551
 
 
552
// uuid_compare --  Compare two UUID's "lexically" and return 0 if they are identical
 
553
#define CHECK(f1, f2) if (f1 != f2) return f1 < f2 ? -1 : 1;
 
554
int uuid_compare(uuid_t *u1, uuid_t *u2)
 
555
{
 
556
    int i;
 
557
 
 
558
    CHECK(u1->time_low, u2->time_low);
 
559
    CHECK(u1->time_mid, u2->time_mid);
 
560
    CHECK(u1->time_hi_and_version, u2->time_hi_and_version);
 
561
    CHECK(u1->clock_seq_hi_and_reserved, u2->clock_seq_hi_and_reserved);
 
562
    CHECK(u1->clock_seq_low, u2->clock_seq_low)
 
563
    for (i = 0; i < 6; i++)
 
564
    {
 
565
        if (u1->node[i] < u2->node[i])
 
566
            return -1;
 
567
        if (u1->node[i] > u2->node[i])
 
568
            return 1;
 
569
    }
 
570
    return 0;
 
571
}
 
572
#undef CHECK
 
573
 
 
574
NAMESPACE_END
 
575