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 | 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 _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) |
| #define GUID_ENCODING_LENGTH 32 |
| G_CONST_RETURN GUID* gnc_value_get_guid | ( | const GValue * | value | ) |
gnc_value_get_guid : a GValue whose value we want to get.
Returns: the value stored in .
Definition at line 73 of file guid.c.
00074 { 00075 GUID *val; 00076 00077 g_return_val_if_fail (value && G_IS_VALUE (value), NULL); 00078 g_return_val_if_fail (GNC_VALUE_HOLDS_GUID (value), NULL); 00079 00080 val = (GUID*) g_value_get_boxed (value); 00081 00082 return val; 00083 }
Given two GUIDs, return TRUE if they are non-NULL and equal. Return FALSE, otherwise.
Definition at line 675 of file guid.c.
00676 { 00677 if (guid_1 && guid_2) 00678 return (memcmp(guid_1, guid_2, GUID_DATA_SIZE) == 0); 00679 else 00680 return FALSE; 00681 }
| guint guid_hash_to_guint | ( | gconstpointer | ptr | ) |
Given a GUID *, hash it to a guint
Definition at line 700 of file guid.c.
00701 { 00702 const GUID *guid = ptr; 00703 00704 if (!guid) 00705 { 00706 PERR ("received NULL guid pointer."); 00707 return 0; 00708 } 00709 00710 if (sizeof(guint) <= sizeof(guid->data)) 00711 { 00712 return (*((guint *) guid->data)); 00713 } 00714 else 00715 { 00716 guint hash = 0; 00717 unsigned int i, j; 00718 00719 for (i = 0, j = 0; i < sizeof(guint); i++, j++) { 00720 if (j == GUID_DATA_SIZE) j = 0; 00721 00722 hash <<= 4; 00723 hash |= guid->data[j]; 00724 } 00725 00726 return hash; 00727 } 00728 }
| void guid_init | ( | void | ) |
Initialize the id generator with a variety of random sources.
Definition at line 353 of file guid.c.
00354 { 00355 size_t bytes = 0; 00356 00357 /* Not needed; taken care of on first malloc. 00358 * guid_memchunk_init(); */ 00359 00360 md5_init_ctx(&guid_context); 00361 00362 /* entropy pool */ 00363 bytes += init_from_file ("/dev/urandom", 512); 00364 00365 /* files */ 00366 { 00367 const char * files[] = 00368 { "/etc/passwd", 00369 "/proc/loadavg", 00370 "/proc/meminfo", 00371 "/proc/net/dev", 00372 "/proc/rtc", 00373 "/proc/self/environ", 00374 "/proc/self/stat", 00375 "/proc/stat", 00376 "/proc/uptime", 00377 NULL 00378 }; 00379 int i; 00380 00381 for (i = 0; files[i] != NULL; i++) 00382 bytes += init_from_file(files[i], BLOCKSIZE); 00383 } 00384 00385 /* directories */ 00386 { 00387 const char * dirname; 00388 const char * dirs[] = 00389 { 00390 "/proc", 00391 P_tmpdir, 00392 "/var/lock", 00393 "/var/log", 00394 "/var/mail", 00395 "/var/spool/mail", 00396 "/var/run", 00397 NULL 00398 }; 00399 int i; 00400 00401 for (i = 0; dirs[i] != NULL; i++) 00402 bytes += init_from_dir(dirs[i], 32); 00403 00404 dirname = g_get_home_dir(); 00405 if (dirname != NULL) 00406 bytes += init_from_dir(dirname, 32); 00407 } 00408 00409 /* process and parent ids */ 00410 { 00411 pid_t pid; 00412 00413 pid = getpid(); 00414 md5_process_bytes(&pid, sizeof(pid), &guid_context); 00415 bytes += sizeof(pid); 00416 00417 #ifdef HAVE_GETPPID 00418 pid = getppid(); 00419 md5_process_bytes(&pid, sizeof(pid), &guid_context); 00420 bytes += sizeof(pid); 00421 #endif 00422 } 00423 00424 /* user info */ 00425 { 00426 #ifdef HAVE_GETUID 00427 uid_t uid; 00428 gid_t gid; 00429 char *s; 00430 00431 s = getlogin(); 00432 if (s != NULL) 00433 { 00434 md5_process_bytes(s, strlen(s), &guid_context); 00435 bytes += strlen(s); 00436 } 00437 00438 uid = getuid(); 00439 md5_process_bytes(&uid, sizeof(uid), &guid_context); 00440 bytes += sizeof(uid); 00441 00442 gid = getgid(); 00443 md5_process_bytes(&gid, sizeof(gid), &guid_context); 00444 bytes += sizeof(gid); 00445 #endif 00446 } 00447 00448 /* host info */ 00449 { 00450 #ifdef HAVE_GETHOSTNAME 00451 char string[1024]; 00452 00453 memset(string, 0, sizeof(string)); 00454 gethostname(string, sizeof(string)); 00455 md5_process_bytes(string, sizeof(string), &guid_context); 00456 bytes += sizeof(string); 00457 #endif 00458 } 00459 00460 /* plain old random */ 00461 { 00462 int n, i; 00463 00464 srand((unsigned int) time(NULL)); 00465 00466 for (i = 0; i < 32; i++) 00467 { 00468 n = rand(); 00469 00470 md5_process_bytes(&n, sizeof(n), &guid_context); 00471 bytes += sizeof(n); 00472 } 00473 } 00474 00475 /* time in secs and clock ticks */ 00476 bytes += init_from_time(); 00477 00478 PINFO ("got %llu bytes", (unsigned long long int) bytes); 00479 00480 if (bytes < THRESHOLD) 00481 PWARN("only got %llu bytes.\n" 00482 "The identifiers might not be very random.\n", 00483 (unsigned long long int)bytes); 00484 00485 guid_initialized = TRUE; 00486 }
| 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 497 of file guid.c.
00498 { 00499 md5_init_ctx(&guid_context); 00500 00501 md5_process_bytes(salt, salt_len, &guid_context); 00502 00503 guid_initialized = TRUE; 00504 }
| 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 489 of file guid.c.
00490 { 00491 guid_init(); 00492 00493 md5_process_bytes(salt, salt_len, &guid_context); 00494 }
| 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 517 of file guid.c.
00518 { 00519 static int counter = 0; 00520 struct md5_ctx ctx; 00521 00522 if (guid == NULL) 00523 return; 00524 00525 if (!guid_initialized) 00526 guid_init(); 00527 00528 /* make the id */ 00529 ctx = guid_context; 00530 md5_finish_ctx(&ctx, guid->data); 00531 00532 /* update the global context */ 00533 init_from_time(); 00534 00535 /* Make it a little extra salty. I think init_from_time was buggy, 00536 * or something, since duplicate id's actually happened. Or something 00537 * like that. I think this is because init_from_time kept returning 00538 * the same values too many times in a row. So we'll do some 'block 00539 * chaining', and feed in the old guid as new random data. 00540 * 00541 * Anyway, I think the whole fact that I saw a bunch of duplicate 00542 * id's at one point, but can't reproduce the bug is rather alarming. 00543 * Something must be broken somewhere, and merely adding more salt 00544 * is just hiding the problem, not fixing it. 00545 */ 00546 init_from_int (433781*counter); 00547 init_from_buff (guid->data, GUID_DATA_SIZE); 00548 00549 if (counter == 0) 00550 { 00551 FILE *fp; 00552 00553 fp = g_fopen ("/dev/urandom", "r"); 00554 if (fp == NULL) 00555 return; 00556 00557 init_from_stream(fp, 32); 00558 00559 fclose(fp); 00560 00561 counter = GUID_PERIOD; 00562 } 00563 00564 counter--; 00565 }
| 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 568 of file guid.c.
| const GUID* guid_null | ( | void | ) |
Returns a GUID which is guaranteed to never reference any entity.
Definition at line 151 of file guid.c.
00152 { 00153 static int null_inited = 0; 00154 static GUID null_guid; 00155 00156 if (!null_inited) { 00157 int i; 00158 00159 for (i = 0; i < GUID_DATA_SIZE; i++) 00160 null_guid.data[i] = '\0'; 00161 00162 null_inited = 1; 00163 } 00164 00165 return &null_guid; 00166 }
| 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 636 of file guid.c.
00637 { 00638 #ifdef G_THREADS_ENABLED 00639 static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT; 00640 gchar *string; 00641 00642 string = g_static_private_get (&guid_buffer_key); 00643 if (string == NULL) { 00644 string = malloc(GUID_ENCODING_LENGTH+1); 00645 g_static_private_set (&guid_buffer_key, string, g_free); 00646 } 00647 #else 00648 static char string[64]; 00649 #endif 00650 00651 encode_md5_data(guid->data, string); 00652 string[GUID_ENCODING_LENGTH] = '\0'; 00653 00654 return string; 00655 }
| 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.
1.5.2