QOF  0.7.5

Files

file  guid.h
 globally unique ID User API
 

Data Structures

union  _GUID
 

Macros

#define GUID_DATA_SIZE   16
 
#define GUID_ENCODING_LENGTH   32
 

Typedefs

typedef union _GUID GUID
 

Functions

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 GUIDguid_null (void)
 
GUIDguid_malloc (void)
 
void guid_free (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.

Macro Definition Documentation

#define GUID_DATA_SIZE   16

The type used to store guids

Definition at line 52 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 64 of file guid.h.

Function Documentation

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 652 of file guid.c.

653 {
654  if (guid_1 && guid_2)
655  return (memcmp (guid_1, guid_2, GUID_DATA_SIZE) == 0);
656  else
657  return FALSE;
658 }
guint guid_hash_to_guint ( gconstpointer  ptr)

Given a GUID *, hash it to a guint

Definition at line 677 of file guid.c.

678 {
679  const GUID *guid = ptr;
680 
681  if (!guid)
682  {
683  PERR ("received NULL guid pointer.");
684  return 0;
685  }
686 
687  if (sizeof (guint) <= sizeof (guid->data))
688  {
689  return (*((guint *) guid->data));
690  }
691  else
692  {
693  guint hash = 0;
694  unsigned int i, j;
695 
696  for (i = 0, j = 0; i < sizeof (guint); i++, j++)
697  {
698  if (j == GUID_DATA_SIZE)
699  j = 0;
700 
701  hash <<= 4;
702  hash |= guid->data[j];
703  }
704 
705  return hash;
706  }
707 }
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 325 of file guid.c.

326 {
327  size_t bytes = 0;
328 
329  /* Not needed; taken care of on first malloc.
330  * guid_memchunk_init(); */
331 
332  md5_init_ctx (&guid_context);
333 
334  /* entropy pool */
335  bytes += init_from_file ("/dev/urandom", 512);
336 
337  /* files */
338  {
339  const char *files[] = { "/etc/passwd",
340  "/proc/loadavg",
341  "/proc/meminfo",
342  "/proc/net/dev",
343  "/proc/rtc",
344  "/proc/self/environ",
345  "/proc/self/stat",
346  "/proc/stat",
347  "/proc/uptime",
348  NULL
349  };
350  int i;
351 
352  for (i = 0; files[i] != NULL; i++)
353  bytes += init_from_file (files[i], BLOCKSIZE);
354  }
355 
356  /* directories */
357  {
358  const char *dirname;
359  const char *dirs[] = {
360  "/proc",
361  P_tmpdir,
362  "/var/lock",
363  "/var/log",
364  "/var/mail",
365  "/var/spool/mail",
366  "/var/run",
367  NULL
368  };
369  int i;
370 
371  for (i = 0; dirs[i] != NULL; i++)
372  bytes += init_from_dir (dirs[i], 32);
373 
374  dirname = g_get_home_dir ();
375  if (dirname != NULL)
376  bytes += init_from_dir (dirname, 32);
377  }
378 
379  /* process and parent ids */
380  {
381  pid_t pid;
382 
383  pid = getpid ();
384  md5_process_bytes (&pid, sizeof (pid), &guid_context);
385  bytes += sizeof (pid);
386 
387 #ifdef HAVE_GETPPID
388  pid = getppid ();
389  md5_process_bytes (&pid, sizeof (pid), &guid_context);
390  bytes += sizeof (pid);
391 #endif
392  }
393 
394  /* user info */
395  {
396 #ifdef HAVE_GETUID
397  uid_t uid;
398  gid_t gid;
399  char *s;
400 
401  s = getlogin ();
402  if (s != NULL)
403  {
404  md5_process_bytes (s, strlen (s), &guid_context);
405  bytes += strlen (s);
406  }
407 
408  uid = getuid ();
409  md5_process_bytes (&uid, sizeof (uid), &guid_context);
410  bytes += sizeof (uid);
411 
412  gid = getgid ();
413  md5_process_bytes (&gid, sizeof (gid), &guid_context);
414  bytes += sizeof (gid);
415 #endif
416  }
417 
418  /* host info */
419  {
420 #ifdef HAVE_GETHOSTNAME
421  char string[1024];
422 
423  memset (string, 0, sizeof (string));
424  gethostname (string, sizeof (string));
425  md5_process_bytes (string, sizeof (string), &guid_context);
426  bytes += sizeof (string);
427 #endif
428  }
429 
430  /* plain old random */
431  {
432  int n, i;
433 
434  srand ((unsigned int) time (NULL));
435 
436  for (i = 0; i < 32; i++)
437  {
438  n = rand ();
439 
440  md5_process_bytes (&n, sizeof (n), &guid_context);
441  bytes += sizeof (n);
442  }
443  }
444 
445  /* time in secs and clock ticks */
446  bytes += init_from_time ();
447 
448  PINFO ("got %llu bytes", (unsigned long long int) bytes);
449 
450  if (bytes < THRESHOLD)
451  PWARN ("only got %llu bytes.\n"
452  "The identifiers might not be very random.\n",
453  (unsigned long long int) bytes);
454 
455  guid_initialized = TRUE;
456 }
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
saltThe additional random values to add to the generator.
salt_lenThe 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 467 of file guid.c.

468 {
469  md5_init_ctx (&guid_context);
470 
471  md5_process_bytes (salt, salt_len, &guid_context);
472 
473  guid_initialized = TRUE;
474 }
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
saltThe additional random values to add to the generator.
salt_lenThe 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 459 of file guid.c.

460 {
461  guid_init ();
462 
463  md5_process_bytes (salt, salt_len, &guid_context);
464 }
GUID* guid_malloc ( void  )

Efficiently allocate & free memory for GUIDs

Definition at line 100 of file guid.c.

101 {
102  if (!guid_memchunk)
103  guid_memchunk_init ();
104  return g_chunk_new (GUID, guid_memchunk);
105 }
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
guidA 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 487 of file guid.c.

488 {
489  static int counter = 0;
490  struct md5_ctx ctx;
491 
492  if (guid == NULL)
493  return;
494 
495  if (!guid_initialized)
496  guid_init ();
497 
498  /* make the id */
499  ctx = guid_context;
500  md5_finish_ctx (&ctx, guid->data);
501 
502  /* update the global context */
503  init_from_time ();
504 
505  /* Make it a little extra salty. I think init_from_time was buggy,
506  * or something, since duplicate id's actually happened. Or something
507  * like that. I think this is because init_from_time kept returning
508  * the same values too many times in a row. So we'll do some 'block
509  * chaining', and feed in the old guid as new random data.
510  *
511  * Anyway, I think the whole fact that I saw a bunch of duplicate
512  * id's at one point, but can't reproduce the bug is rather alarming.
513  * Something must be broken somewhere, and merely adding more salt
514  * is just hiding the problem, not fixing it.
515  */
516  init_from_int (433781 * counter);
517  init_from_buff (guid->data, GUID_DATA_SIZE);
518 
519  if (counter == 0)
520  {
521  FILE *fp;
522 
523  fp = fopen ("/dev/urandom", "r");
524  if (fp == NULL)
525  return;
526 
527  init_from_stream (fp, 32);
528 
529  fclose (fp);
530 
531  counter = GUID_PERIOD;
532  }
533 
534  counter--;
535 }
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 538 of file guid.c.

539 {
540  GUID guid;
541 
542  guid_new (&guid);
543 
544  return guid;
545 }
const GUID* guid_null ( void  )
Returns a GUID which is guaranteed

to never reference any entity.

Definition at line 119 of file guid.c.

120 {
121  static int null_inited = 0;
122  static GUID null_guid;
123 
124  if (!null_inited)
125  {
126  int i;
127  char *tmp = "NULLGUID.EMPTY.";
128 
129  /* 16th space for '\O' */
130  for (i = 0; i < GUID_DATA_SIZE; i++)
131  null_guid.data[i] = tmp[i];
132 
133  null_inited = 1;
134  }
135 
136  return &null_guid;
137 }
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 477 of file guid.c.

478 {
479 #ifndef HAVE_GLIB29
480  guid_memchunk_shutdown ();
481 #endif
482 }
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
guidThe 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 611 of file guid.c.

612 {
613 #ifdef G_THREADS_ENABLED
614  static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT;
615  gchar *string;
616 
617  string = g_static_private_get (&guid_buffer_key);
618  if (string == NULL)
619  {
620  string = malloc (GUID_ENCODING_LENGTH + 1);
621  g_static_private_set (&guid_buffer_key, string, g_free);
622  }
623 #else
624  static char string[64];
625 #endif
626 
627  encode_md5_data (guid->data, string);
628  string[GUID_ENCODING_LENGTH] = '\0';
629 
630  return string;
631 }
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
guidThe guid to print.
buffThe 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.