QOF: GUID

QOF 0.7.5

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

Files | Data Structures | Macros | Typedefs | Functions
GUID
Query Object Framework » Class: Getting and setting entity values.

## 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 GUID * | guid_null (void)
GUID * | guid_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 }
GUID_DATA_SIZE
#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 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 }
PERR
#define PERR(format, args...)
Definition: qoflog.h:183
GUID_DATA_SIZE
#define GUID_DATA_SIZE
Definition: guid.h:52
_GUID
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 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 }
PINFO
#define PINFO(format, args...)
Definition: qoflog.h:199
PWARN
#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

  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 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

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

460 {
461 guid_init ();
462
463 md5_process_bytes (salt, salt_len, &guid_context);
464 }
guid_init
void guid_init(void)
Definition: guid.c:325

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 }
_GUID
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

  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 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_DATA_SIZE
#define GUID_DATA_SIZE
Definition: guid.h:52
guid_init
void guid_init(void)
Definition: guid.c:325
md5_ctx
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 538 of file guid.c.

539 {
540 GUID guid;
541
542 guid_new (&guid);
543
544 return guid;
545 }
_GUID
Definition: guid.h:53
guid_new
void guid_new(GUID *guid)
Definition: guid.c:487

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 }
GUID_DATA_SIZE
#define GUID_DATA_SIZE
Definition: guid.h:52
_GUID
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 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

  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 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 }
GUID_ENCODING_LENGTH
#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

  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.