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.
Files | |
file | guid.h |
globally unique ID User API | |
Data Structures | |
union | _GUID |
Defines | |
#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) |
#define GUID_ENCODING_LENGTH 32 |
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.
00653 { 00654 if (guid_1 && guid_2) 00655 return (memcmp (guid_1, guid_2, GUID_DATA_SIZE) == 0); 00656 else 00657 return FALSE; 00658 }
guint guid_hash_to_guint | ( | gconstpointer | ptr | ) |
Given a GUID *, hash it to a guint
Definition at line 677 of file guid.c.
00678 { 00679 const GUID *guid = ptr; 00680 00681 if (!guid) 00682 { 00683 PERR ("received NULL guid pointer."); 00684 return 0; 00685 } 00686 00687 if (sizeof (guint) <= sizeof (guid->data)) 00688 { 00689 return (*((guint *) guid->data)); 00690 } 00691 else 00692 { 00693 guint hash = 0; 00694 unsigned int i, j; 00695 00696 for (i = 0, j = 0; i < sizeof (guint); i++, j++) 00697 { 00698 if (j == GUID_DATA_SIZE) 00699 j = 0; 00700 00701 hash <<= 4; 00702 hash |= guid->data[j]; 00703 } 00704 00705 return hash; 00706 } 00707 }
void guid_init | ( | void | ) |
Initialize the id generator with a variety of random sources.
Definition at line 325 of file guid.c.
00326 { 00327 size_t bytes = 0; 00328 00329 /* Not needed; taken care of on first malloc. 00330 * guid_memchunk_init(); */ 00331 00332 md5_init_ctx (&guid_context); 00333 00334 /* entropy pool */ 00335 bytes += init_from_file ("/dev/urandom", 512); 00336 00337 /* files */ 00338 { 00339 const char *files[] = { "/etc/passwd", 00340 "/proc/loadavg", 00341 "/proc/meminfo", 00342 "/proc/net/dev", 00343 "/proc/rtc", 00344 "/proc/self/environ", 00345 "/proc/self/stat", 00346 "/proc/stat", 00347 "/proc/uptime", 00348 NULL 00349 }; 00350 int i; 00351 00352 for (i = 0; files[i] != NULL; i++) 00353 bytes += init_from_file (files[i], BLOCKSIZE); 00354 } 00355 00356 /* directories */ 00357 { 00358 const char *dirname; 00359 const char *dirs[] = { 00360 "/proc", 00361 P_tmpdir, 00362 "/var/lock", 00363 "/var/log", 00364 "/var/mail", 00365 "/var/spool/mail", 00366 "/var/run", 00367 NULL 00368 }; 00369 int i; 00370 00371 for (i = 0; dirs[i] != NULL; i++) 00372 bytes += init_from_dir (dirs[i], 32); 00373 00374 dirname = g_get_home_dir (); 00375 if (dirname != NULL) 00376 bytes += init_from_dir (dirname, 32); 00377 } 00378 00379 /* process and parent ids */ 00380 { 00381 pid_t pid; 00382 00383 pid = getpid (); 00384 md5_process_bytes (&pid, sizeof (pid), &guid_context); 00385 bytes += sizeof (pid); 00386 00387 #ifdef HAVE_GETPPID 00388 pid = getppid (); 00389 md5_process_bytes (&pid, sizeof (pid), &guid_context); 00390 bytes += sizeof (pid); 00391 #endif 00392 } 00393 00394 /* user info */ 00395 { 00396 #ifdef HAVE_GETUID 00397 uid_t uid; 00398 gid_t gid; 00399 char *s; 00400 00401 s = getlogin (); 00402 if (s != NULL) 00403 { 00404 md5_process_bytes (s, strlen (s), &guid_context); 00405 bytes += strlen (s); 00406 } 00407 00408 uid = getuid (); 00409 md5_process_bytes (&uid, sizeof (uid), &guid_context); 00410 bytes += sizeof (uid); 00411 00412 gid = getgid (); 00413 md5_process_bytes (&gid, sizeof (gid), &guid_context); 00414 bytes += sizeof (gid); 00415 #endif 00416 } 00417 00418 /* host info */ 00419 { 00420 #ifdef HAVE_GETHOSTNAME 00421 char string[1024]; 00422 00423 memset (string, 0, sizeof (string)); 00424 gethostname (string, sizeof (string)); 00425 md5_process_bytes (string, sizeof (string), &guid_context); 00426 bytes += sizeof (string); 00427 #endif 00428 } 00429 00430 /* plain old random */ 00431 { 00432 int n, i; 00433 00434 srand ((unsigned int) time (NULL)); 00435 00436 for (i = 0; i < 32; i++) 00437 { 00438 n = rand (); 00439 00440 md5_process_bytes (&n, sizeof (n), &guid_context); 00441 bytes += sizeof (n); 00442 } 00443 } 00444 00445 /* time in secs and clock ticks */ 00446 bytes += init_from_time (); 00447 00448 PINFO ("got %llu bytes", (unsigned long long int) bytes); 00449 00450 if (bytes < THRESHOLD) 00451 PWARN ("only got %llu bytes.\n" 00452 "The identifiers might not be very random.\n", 00453 (unsigned long long int) bytes); 00454 00455 guid_initialized = TRUE; 00456 }
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.
salt | The additional random values to add to the generator. | |
salt_len | The length of the additional random values. |
Definition at line 467 of file guid.c.
00468 { 00469 md5_init_ctx (&guid_context); 00470 00471 md5_process_bytes (salt, salt_len, &guid_context); 00472 00473 guid_initialized = TRUE; 00474 }
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.
salt | The additional random values to add to the generator. | |
salt_len | The length of the additional random values. |
Definition at line 459 of file guid.c.
00460 { 00461 guid_init (); 00462 00463 md5_process_bytes (salt, salt_len, &guid_context); 00464 }
GUID* guid_malloc | ( | void | ) |
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.
guid | A pointer to an existing guid data structure. The existing value will be replaced with a new value. |
Definition at line 487 of file guid.c.
00488 { 00489 static int counter = 0; 00490 struct md5_ctx ctx; 00491 00492 if (guid == NULL) 00493 return; 00494 00495 if (!guid_initialized) 00496 guid_init (); 00497 00498 /* make the id */ 00499 ctx = guid_context; 00500 md5_finish_ctx (&ctx, guid->data); 00501 00502 /* update the global context */ 00503 init_from_time (); 00504 00505 /* Make it a little extra salty. I think init_from_time was buggy, 00506 * or something, since duplicate id's actually happened. Or something 00507 * like that. I think this is because init_from_time kept returning 00508 * the same values too many times in a row. So we'll do some 'block 00509 * chaining', and feed in the old guid as new random data. 00510 * 00511 * Anyway, I think the whole fact that I saw a bunch of duplicate 00512 * id's at one point, but can't reproduce the bug is rather alarming. 00513 * Something must be broken somewhere, and merely adding more salt 00514 * is just hiding the problem, not fixing it. 00515 */ 00516 init_from_int (433781 * counter); 00517 init_from_buff (guid->data, GUID_DATA_SIZE); 00518 00519 if (counter == 0) 00520 { 00521 FILE *fp; 00522 00523 fp = fopen ("/dev/urandom", "r"); 00524 if (fp == NULL) 00525 return; 00526 00527 init_from_stream (fp, 32); 00528 00529 fclose (fp); 00530 00531 counter = GUID_PERIOD; 00532 } 00533 00534 counter--; 00535 }
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.
Definition at line 538 of file guid.c.
00539 { 00540 GUID guid; 00541 00542 guid_new (&guid); 00543 00544 return guid; 00545 }
const GUID* guid_null | ( | void | ) |
Returns a GUID which is guaranteed to never reference any entity.
Definition at line 119 of file guid.c.
00120 { 00121 static int null_inited = 0; 00122 static GUID null_guid; 00123 00124 if (!null_inited) 00125 { 00126 int i; 00127 char *tmp = "NULLGUID.EMPTY."; 00128 00129 /* 16th space for '\O' */ 00130 for (i = 0; i < GUID_DATA_SIZE; i++) 00131 null_guid.data[i] = tmp[i]; 00132 00133 null_inited = 1; 00134 } 00135 00136 return &null_guid; 00137 }
void guid_shutdown | ( | void | ) |
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.
guid | The guid to print. |
Definition at line 611 of file guid.c.
00612 { 00613 #ifdef G_THREADS_ENABLED 00614 static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT; 00615 gchar *string; 00616 00617 string = g_static_private_get (&guid_buffer_key); 00618 if (string == NULL) 00619 { 00620 string = malloc (GUID_ENCODING_LENGTH + 1); 00621 g_static_private_set (&guid_buffer_key, string, g_free); 00622 } 00623 #else 00624 static char string[64]; 00625 #endif 00626 00627 encode_md5_data (guid->data, string); 00628 string[GUID_ENCODING_LENGTH] = '\0'; 00629 00630 return string; 00631 }
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)
guid | The guid to print. | |
buff | The buffer to print it into. |
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.