QOF  0.8.7
Files | Data Structures | Macros | Typedefs | Functions

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

621 {
622  if (guid_1 && guid_2)
623  return (memcmp (guid_1, guid_2, GUID_DATA_SIZE) == 0);
624  else
625  return FALSE;
626 }
#define GUID_DATA_SIZE
Definition: guid.h:52
guint guid_hash_to_guint ( gconstpointer  ptr)

Given a GUID *, hash it to a guint

Definition at line 645 of file guid.c.

646 {
647  const GUID *guid = ptr;
648  guint hash = 0;
649  unsigned int i, j;
650 
651  if (!guid)
652  {
653  PERR ("received NULL guid pointer.");
654  return 0;
655  }
656 
657  for (i = 0, j = 0; i < sizeof (guint); i++, j++)
658  {
659  if (j == GUID_DATA_SIZE)
660  j = 0;
661 
662  hash <<= 4;
663  hash |= guid->data[j];
664  }
665 
666  return hash;
667 }
#define PERR(format, args...)
Definition: qoflog.h:183
#define GUID_DATA_SIZE
Definition: guid.h:52
Definition: guid.h:53
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 285 of file guid.c.

286 {
287  size_t bytes = 0;
288 
289  /* Not needed; taken care of on first malloc.
290  * guid_memchunk_init(); */
291 
292  md5_init_ctx (&guid_context);
293 
294  /* entropy pool */
295  bytes += init_from_file ("/dev/urandom", 512);
296 
297  /* files */
298  {
299  const char *files[] = { "/etc/passwd",
300  "/proc/loadavg",
301  "/proc/meminfo",
302  "/proc/net/dev",
303  "/proc/rtc",
304  "/proc/self/environ",
305  "/proc/self/stat",
306  "/proc/stat",
307  "/proc/uptime",
308  NULL
309  };
310  int i;
311 
312  for (i = 0; files[i] != NULL; i++)
313  bytes += init_from_file (files[i], BLOCKSIZE);
314  }
315 
316  /* directories */
317  {
318  const char *dirname;
319  const char *dirs[] = {
320  "/proc",
321  P_tmpdir,
322  "/var/lock",
323  "/var/log",
324  "/var/mail",
325  "/var/spool/mail",
326  "/var/run",
327  NULL
328  };
329  int i;
330 
331  for (i = 0; dirs[i] != NULL; i++)
332  bytes += init_from_dir (dirs[i], 32);
333 
334  dirname = g_get_home_dir ();
335  if (dirname != NULL)
336  bytes += init_from_dir (dirname, 32);
337  }
338 
339  /* process and parent ids */
340  {
341  pid_t pid;
342 
343  pid = getpid ();
344  md5_process_bytes (&pid, sizeof (pid), &guid_context);
345  bytes += sizeof (pid);
346 
347 #ifdef HAVE_GETPPID
348  pid = getppid ();
349  md5_process_bytes (&pid, sizeof (pid), &guid_context);
350  bytes += sizeof (pid);
351 #endif
352  }
353 
354  /* user info */
355  {
356 #ifdef HAVE_GETUID
357  uid_t uid;
358  gid_t gid;
359  char *s;
360 
361  s = getlogin ();
362  if (s != NULL)
363  {
364  md5_process_bytes (s, strlen (s), &guid_context);
365  bytes += strlen (s);
366  }
367 
368  uid = getuid ();
369  md5_process_bytes (&uid, sizeof (uid), &guid_context);
370  bytes += sizeof (uid);
371 
372  gid = getgid ();
373  md5_process_bytes (&gid, sizeof (gid), &guid_context);
374  bytes += sizeof (gid);
375 #endif
376  }
377 
378  /* host info */
379  {
380 #ifdef HAVE_GETHOSTNAME
381  char string[1024];
382 
383  memset (string, 0, sizeof (string));
384  gethostname (string, sizeof (string));
385  md5_process_bytes (string, sizeof (string), &guid_context);
386  bytes += sizeof (string);
387 #endif
388  }
389 
390  /* plain old random */
391  {
392  int n, i;
393 
394  srand ((unsigned int) time (NULL));
395 
396  for (i = 0; i < 32; i++)
397  {
398  n = rand ();
399 
400  md5_process_bytes (&n, sizeof (n), &guid_context);
401  bytes += sizeof (n);
402  }
403  }
404 
405  /* time in secs and clock ticks */
406  bytes += init_from_time ();
407 
408  PINFO ("got %llu bytes", (unsigned long long int) bytes);
409 
410  if (bytes < THRESHOLD)
411  PWARN ("only got %llu bytes.\n"
412  "The identifiers might not be very random.\n",
413  (unsigned long long int) bytes);
414 
415  guid_initialized = TRUE;
416 }
#define PINFO(format, args...)
Definition: qoflog.h:199
#define PWARN(format, args...)
Definition: qoflog.h:191
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 427 of file guid.c.

428 {
429  md5_init_ctx (&guid_context);
430 
431  md5_process_bytes (salt, salt_len, &guid_context);
432 
433  guid_initialized = TRUE;
434 }
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 419 of file guid.c.

420 {
421  guid_init ();
422 
423  md5_process_bytes (salt, salt_len, &guid_context);
424 }
void guid_init(void)
Definition: guid.c:285
GUID* guid_malloc ( void  )

Efficiently allocate & free memory for GUIDs

Definition at line 64 of file guid.c.

65 {
66  return g_slice_new (GUID);
67 }
Definition: guid.h:53
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 444 of file guid.c.

445 {
446  static int counter = 0;
447  struct md5_ctx ctx;
448 
449  if (guid == NULL)
450  return;
451 
452  if (!guid_initialized)
453  guid_init ();
454 
455  /* make the id */
456  ctx = guid_context;
457  md5_finish_ctx (&ctx, guid->data);
458 
459  /* update the global context */
460  init_from_time ();
461 
462  /* Make it a little extra salty. I think init_from_time was buggy,
463  * or something, since duplicate id's actually happened. Or something
464  * like that. I think this is because init_from_time kept returning
465  * the same values too many times in a row. So we'll do some 'block
466  * chaining', and feed in the old guid as new random data.
467  *
468  * Anyway, I think the whole fact that I saw a bunch of duplicate
469  * id's at one point, but can't reproduce the bug is rather alarming.
470  * Something must be broken somewhere, and merely adding more salt
471  * is just hiding the problem, not fixing it.
472  */
473  init_from_int (433781 * counter);
474  init_from_buff (guid->data, GUID_DATA_SIZE);
475 
476  if (counter == 0)
477  {
478  FILE *fp;
479 
480  fp = fopen ("/dev/urandom", "r");
481  if (fp == NULL)
482  return;
483 
484  init_from_stream (fp, 32);
485 
486  fclose (fp);
487 
488  counter = GUID_PERIOD;
489  }
490 
491  counter--;
492 }
#define GUID_DATA_SIZE
Definition: guid.h:52
void guid_init(void)
Definition: guid.c:285
Definition: md5.h:80
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 495 of file guid.c.

496 {
497  GUID guid;
498 
499  guid_new (&guid);
500 
501  return guid;
502 }
Definition: guid.h:53
void guid_new(GUID *guid)
Definition: guid.c:444
const GUID* guid_null ( void  )

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

Definition at line 79 of file guid.c.

80 {
81  static int null_inited = 0;
82  static GUID null_guid;
83 
84  if (!null_inited)
85  {
86  int i;
87  char *tmp = "NULLGUID.EMPTY.";
88 
89  /* 16th space for '\O' */
90  for (i = 0; i < GUID_DATA_SIZE; i++)
91  null_guid.data[i] = tmp[i];
92 
93  null_inited = 1;
94  }
95 
96  return &null_guid;
97 }
#define GUID_DATA_SIZE
Definition: guid.h:52
Definition: guid.h:53
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 437 of file guid.c.

438 {
439 }
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 568 of file guid.c.

569 {
570 #ifdef G_THREADS_ENABLED
571 #ifdef GLIB_DEPRECATED_IN_2_32
572  static GPrivate guid_buffer_key = G_PRIVATE_INIT (g_free);
573 #else
574  static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT;
575 #endif
576  gchar *string;
577 #ifdef GLIB_DEPRECATED_IN_2_32
578  string = g_private_get (&guid_buffer_key);
579 #else
580  string = g_static_private_get (&guid_buffer_key);
581 #endif
582  if (string == NULL)
583  {
584  string = malloc (GUID_ENCODING_LENGTH + 1);
585 #ifdef GLIB_DEPRECATED_IN_2_32
586  g_private_set (&guid_buffer_key, string);
587 #else
588  g_static_private_set (&guid_buffer_key, string, g_free);
589 #endif
590  }
591 #else
592  static char string[64];
593 #endif
594 
595  encode_md5_data (guid->data, string);
596  string[GUID_ENCODING_LENGTH] = '\0';
597 
598  return string;
599 }
#define GUID_ENCODING_LENGTH
Definition: guid.h:64
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.