GUID
[Entity: Types, Identity and Instance Framework]


Data Structures

union  GNC_INTERNAL_GUID

Files

file  guid.h
 globally unique ID User API

Defines

#define GUID_DATA_SIZE   16
#define GNC_TYPE_GUID   (gnc_guid_get_type())
#define GNC_VALUE_HOLDS_GUID(value)   G_VALUE_HOLDS(value, GNC_TYPE_GUID)
#define GUID_ENCODING_LENGTH   32

Typedefs

typedef union GNC_INTERNAL_GUID GUID

Functions

GType gnc_guid_get_type (void)
G_CONST_RETURN GUID * gnc_value_get_guid (const GValue *value)
void guid_init (void)
void guid_init_with_salt (const void *salt, size_t salt_len)
void guid_init_only_salt (const void *salt, size_t salt_len)
void guid_shutdown (void)
void guid_new (GUID *guid)
GUID guid_new_return (void)
const GUID * guid_null (void)
GUID * guid_malloc (void)
void guid_free (GUID *guid)
GUID * guid_copy (const GUID *guid)
const gchar * guid_to_string (const GUID *guid)
gchar * guid_to_string_buff (const GUID *guid, gchar *buff)
gboolean string_to_guid (const gchar *string, GUID *guid)
gboolean guid_equal (const GUID *guid_1, const GUID *guid_2)
gint guid_compare (const GUID *g1, const GUID *g2)
guint guid_hash_to_guint (gconstpointer ptr)
GHashTable * guid_hash_table_new (void)

Detailed Description

Globally Unique ID's provide a way to uniquely identify some thing. A GUID is a unique, cryptographically random 128-bit value. The identifier is so random that it is safe to assume that there is no other such item on the planet Earth, and indeed, not even in the Galaxy or beyond.

QOF GUID's can be used independently of any other subsystem in QOF. In particular, they do not require the use of other parts of the object subsystem. New GUID's are usually created by initialising a new entity using qof_instance_init, rather than calling GUID functions directly.


Define Documentation

#define GUID_DATA_SIZE   16

The type used to store guids

Definition at line 53 of file guid.h.

#define GUID_ENCODING_LENGTH   32

number of characters needed to encode a guid as a string not including the null terminator.

Definition at line 71 of file guid.h.


Function Documentation

G_CONST_RETURN GUID* gnc_value_get_guid ( const GValue *  value  ) 

gnc_value_get_guid

Parameters:
value a GValue whose value we want to get.
Returns:
the value stored in value

Definition at line 75 of file guid.c.

00076 {
00077     GUID *val;
00078 
00079     g_return_val_if_fail (value && G_IS_VALUE (value), NULL);
00080     g_return_val_if_fail (GNC_VALUE_HOLDS_GUID (value), NULL);
00081 
00082     val = (GUID*) g_value_get_boxed (value);
00083 
00084     return val;
00085 }

gboolean guid_equal ( const GUID *  guid_1,
const GUID *  guid_2 
)

Given two GUIDs, return TRUE if they are non-NULL and equal. Return FALSE, otherwise.

Definition at line 658 of file guid.c.

00659 {
00660     if (guid_1 && guid_2)
00661         return (memcmp(guid_1, guid_2, GUID_DATA_SIZE) == 0);
00662     else
00663         return FALSE;
00664 }

guint guid_hash_to_guint ( gconstpointer  ptr  ) 

Given a GUID *, hash it to a guint

Definition at line 683 of file guid.c.

00684 {
00685     const GUID *guid = ptr;
00686 
00687     if (!guid)
00688     {
00689         PERR ("received NULL guid pointer.");
00690         return 0;
00691     }
00692 
00693     if (sizeof(guint) <= sizeof(guid->data))
00694     {
00695         const guint* ptr_data = (const guint *) guid->data;
00696         return (*ptr_data);
00697     }
00698     else
00699     {
00700         guint hash = 0;
00701         unsigned int i, j;
00702 
00703         for (i = 0, j = 0; i < sizeof(guint); i++, j++)
00704         {
00705             if (j == GUID_DATA_SIZE) j = 0;
00706 
00707             hash <<= 4;
00708             hash |= guid->data[j];
00709         }
00710 
00711         return hash;
00712     }
00713 }

void guid_init ( void   ) 

Initialize the id generator with a variety of random sources.

Note:
Only one of guid_init(), guid_init_with_salt() and guid_init_only_salt() should be called. Calling any initialization function a second time will reset the generator and erase the effect of the first call.

Definition at line 326 of file guid.c.

00327 {
00328     size_t bytes = 0;
00329 
00330     /* Not needed; taken care of on first malloc.
00331      * guid_memchunk_init(); */
00332 
00333     md5_init_ctx(&guid_context);
00334 
00335     /* entropy pool */
00336     bytes += init_from_file ("/dev/urandom", 512);
00337 
00338     /* files */
00339     {
00340         const char * files[] =
00341         {
00342             "/etc/passwd",
00343             "/proc/loadavg",
00344             "/proc/meminfo",
00345             "/proc/net/dev",
00346             "/proc/rtc",
00347             "/proc/self/environ",
00348             "/proc/self/stat",
00349             "/proc/stat",
00350             "/proc/uptime",
00351             NULL
00352         };
00353         int i;
00354 
00355         for (i = 0; files[i] != NULL; i++)
00356             bytes += init_from_file(files[i], BLOCKSIZE);
00357     }
00358 
00359     /* directories */
00360     {
00361         const char * dirname;
00362         const char * dirs[] =
00363         {
00364             "/proc",
00365             P_tmpdir,
00366             "/var/lock",
00367             "/var/log",
00368             "/var/mail",
00369             "/var/spool/mail",
00370             "/var/run",
00371             NULL
00372         };
00373         int i;
00374 
00375         for (i = 0; dirs[i] != NULL; i++)
00376             bytes += init_from_dir(dirs[i], 32);
00377 
00378         dirname = g_get_home_dir();
00379         if (dirname != NULL)
00380             bytes += init_from_dir(dirname, 32);
00381     }
00382 
00383     /* process and parent ids */
00384     {
00385 #ifdef HAVE_UNISTD_H
00386         pid_t pid;
00387 
00388         pid = getpid();
00389         md5_process_bytes(&pid, sizeof(pid), &guid_context);
00390         bytes += sizeof(pid);
00391 
00392 #ifdef HAVE_GETPPID
00393         pid = getppid();
00394         md5_process_bytes(&pid, sizeof(pid), &guid_context);
00395         bytes += sizeof(pid);
00396 #endif
00397 #endif
00398     }
00399 
00400     /* user info */
00401     {
00402 #ifdef HAVE_GETUID
00403         uid_t uid;
00404         gid_t gid;
00405         char *s;
00406 
00407         s = getlogin();
00408         if (s != NULL)
00409         {
00410             md5_process_bytes(s, strlen(s), &guid_context);
00411             bytes += strlen(s);
00412         }
00413 
00414         uid = getuid();
00415         md5_process_bytes(&uid, sizeof(uid), &guid_context);
00416         bytes += sizeof(uid);
00417 
00418         gid = getgid();
00419         md5_process_bytes(&gid, sizeof(gid), &guid_context);
00420         bytes += sizeof(gid);
00421 #endif
00422     }
00423 
00424     /* host info */
00425     {
00426 #ifdef HAVE_GETHOSTNAME
00427         char string[1024];
00428 
00429         memset(string, 0, sizeof(string));
00430         gethostname(string, sizeof(string));
00431         md5_process_bytes(string, sizeof(string), &guid_context);
00432         bytes += sizeof(string);
00433 #endif
00434     }
00435 
00436     /* plain old random */
00437     {
00438         int n, i;
00439 
00440         srand((unsigned int) time(NULL));
00441 
00442         for (i = 0; i < 32; i++)
00443         {
00444             n = rand();
00445 
00446             md5_process_bytes(&n, sizeof(n), &guid_context);
00447             bytes += sizeof(n);
00448         }
00449     }
00450 
00451     /* time in secs and clock ticks */
00452     bytes += init_from_time();
00453 
00454 #ifdef HAVE_SCANF_LLD
00455     PINFO ("got %llu bytes", (unsigned long long int) bytes);
00456 
00457     if (bytes < THRESHOLD)
00458         PWARN("only got %llu bytes.\n"
00459               "The identifiers might not be very random.\n",
00460               (unsigned long long int)bytes);
00461 #else
00462     PINFO ("got %lu bytes", (unsigned long int) bytes);
00463 
00464     if (bytes < THRESHOLD)
00465         PWARN("only got %lu bytes.\n"
00466               "The identifiers might not be very random.\n",
00467               (unsigned long int)bytes);
00468 #endif
00469 
00470     guid_initialized = TRUE;
00471 }

void guid_init_only_salt ( const void *  salt,
size_t  salt_len 
)

Initialize the id generator with the data given in the salt argument, but not with any other source. Calling this function with a specific argument will reliably produce a specific sequence of ids.

Parameters:
salt The additional random values to add to the generator.
salt_len The length of the additional random values.
Note:
Only one of guid_init(), guid_init_with_salt() and guid_init_only_salt() should be called. Calling any initialization function a second time will reset the generator and erase the effect of the first call.

Definition at line 482 of file guid.c.

00483 {
00484     md5_init_ctx(&guid_context);
00485 
00486     md5_process_bytes(salt, salt_len, &guid_context);
00487 
00488     guid_initialized = TRUE;
00489 }

void guid_init_with_salt ( const void *  salt,
size_t  salt_len 
)

Initialize the id generator with a variety of random sources. and with the data given in the salt argument. This argument can be used to add additional randomness to the generated ids.

Parameters:
salt The additional random values to add to the generator.
salt_len The length of the additional random values.
Note:
Only one of guid_init(), guid_init_with_salt() and guid_init_only_salt() should be called. Calling any initialization function a second time will reset the generator and erase the effect of the first call.

Definition at line 474 of file guid.c.

00475 {
00476     guid_init();
00477 
00478     md5_process_bytes(salt, salt_len, &guid_context);
00479 }

GUID* guid_malloc ( void   ) 

Efficiently allocate & free memory for GUIDs

Definition at line 90 of file guid.c.

00091 {
00092     return g_slice_new(GUID);
00093 }

void guid_new ( GUID *  guid  ) 

Generate a new id. If no initialization function has been called, guid_init() will be called before the id is created.

Parameters:
guid A pointer to an existing guid data structure. The existing value will be replaced with a new value.
This routine uses the md5 algorithm to build strong random guids. Note that while guid's are generated randomly, the odds of this routine returning a non-unique id are astronomically small. (Literally astronomically: If you had Cray's on every solar system in the universe running for the entire age of the universe, you'd still have less than a one-in-a-million chance of coming up with a duplicate id. 2^128 == 10^38 is a really really big number.)

Definition at line 499 of file guid.c.

00500 {
00501     static int counter = 0;
00502     struct md5_ctx ctx;
00503 
00504     if (guid == NULL)
00505         return;
00506 
00507     if (!guid_initialized)
00508         guid_init();
00509 
00510     /* make the id */
00511     ctx = guid_context;
00512     md5_finish_ctx(&ctx, guid->data);
00513 
00514     /* update the global context */
00515     init_from_time();
00516 
00517     /* Make it a little extra salty.  I think init_from_time was buggy,
00518     * or something, since duplicate id's actually happened. Or something
00519     * like that.  I think this is because init_from_time kept returning
00520     * the same values too many times in a row.  So we'll do some 'block
00521     * chaining', and feed in the old guid as new random data.
00522     *
00523     * Anyway, I think the whole fact that I saw a bunch of duplicate
00524     * id's at one point, but can't reproduce the bug is rather alarming.
00525     * Something must be broken somewhere, and merely adding more salt
00526     * is just hiding the problem, not fixing it.
00527     */
00528     init_from_int (433781 * counter);
00529     init_from_buff (guid->data, GUID_DATA_SIZE);
00530 
00531     if (counter == 0)
00532     {
00533         FILE *fp;
00534 
00535         fp = g_fopen ("/dev/urandom", "r");
00536         if (fp == NULL)
00537             return;
00538 
00539         init_from_stream(fp, 32);
00540 
00541         fclose(fp);
00542 
00543         counter = GUID_PERIOD;
00544     }
00545 
00546     counter--;
00547 }

GUID guid_new_return ( void   ) 

Generate a new id. If no initialization function has been called, guid_init() will be called before the id is created.

Returns:
guid A data structure containing a newly allocated GUID. Caller is responsible for calling guid_free().

Definition at line 550 of file guid.c.

00551 {
00552     GUID guid;
00553 
00554     guid_new (&guid);
00555 
00556     return guid;
00557 }

const GUID* guid_null ( void   ) 

Returns a GUID which is guaranteed to never reference any entity.

Definition at line 117 of file guid.c.

00118 {
00119     static int null_inited = 0;
00120     static GUID null_guid;
00121 
00122     if (!null_inited)
00123     {
00124         int i;
00125 
00126         for (i = 0; i < GUID_DATA_SIZE; i++)
00127             null_guid.data[i] = '\0';
00128 
00129         null_inited = 1;
00130     }
00131 
00132     return &null_guid;
00133 }

void guid_shutdown ( void   ) 

Release the memory chunk associated with gui storage. Use this only when shutting down the program, as it invalidates *all* GUIDs at once.

Definition at line 492 of file guid.c.

00493 {
00494 }

const gchar* guid_to_string ( const GUID *  guid  ) 

The guid_to_string() routine returns a null-terminated string encoding of the id. String encodings of identifiers are hex numbers printed only with the characters '0' through '9' and 'a' through 'f'. The encoding will always be GUID_ENCODING_LENGTH characters long.

XXX This routine is not thread safe and is deprecated. Please use the routine guid_to_string_buff() instead.

Parameters:
guid The guid to print.
Returns:
A pointer to the starting character of the string. The returned memory is owned by this routine and may not be freed by the caller.

Definition at line 618 of file guid.c.

00619 {
00620 #ifdef G_THREADS_ENABLED
00621     static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT;
00622     gchar *string;
00623 
00624     string = g_static_private_get (&guid_buffer_key);
00625     if (string == NULL)
00626     {
00627         string = malloc(GUID_ENCODING_LENGTH + 1);
00628         g_static_private_set (&guid_buffer_key, string, g_free);
00629     }
00630 #else
00631     static char string[64];
00632 #endif
00633 
00634     encode_md5_data(guid->data, string);
00635     string[GUID_ENCODING_LENGTH] = '\0';
00636 
00637     return string;
00638 }

gchar* guid_to_string_buff ( const GUID *  guid,
gchar *  buff 
)

The guid_to_string_buff() routine puts a null-terminated string encoding of the id into the memory pointed at by buff. The buffer must be at least GUID_ENCODING_LENGTH+1 characters long. This routine is handy for avoiding a malloc/free cycle. It returns a pointer to the >>end<< of what was written. (i.e. it can be used like 'stpcpy' during string concatenation)

Parameters:
guid The guid to print.
buff The buffer to print it into.
Returns:
A pointer to the terminating null character of the string.

gboolean string_to_guid ( const gchar *  string,
GUID *  guid 
)

Given a string, decode the id into the guid if guid is non-NULL. The function returns TRUE if the string was a valid 32 character hexadecimal number. This function accepts both upper and lower case hex digits. If the return value is FALSE, the effect on guid is undefined.


Generated on Sat Mar 27 04:50:44 2010 for GnuCash by  doxygen 1.5.7.1