26 #ifdef HAVE_SYS_TYPES_H
27 # include <sys/types.h>
36 #ifdef HAVE_SYS_TIMES_H
37 # include <sys/times.h>
45 # define P_tmpdir "/tmp"
50 #define BLOCKSIZE 4096
51 #define THRESHOLD (2 * BLOCKSIZE)
55 static gboolean guid_initialized = FALSE;
56 static struct md5_ctx guid_context;
58 static GMemChunk *guid_memchunk = NULL;
69 return g_slice_new (
GUID);
73 guid_free (
GUID * guid)
78 g_slice_free (
GUID, guid);
83 guid_memchunk_init (
void)
86 guid_memchunk = g_mem_chunk_create (
GUID, 512, G_ALLOC_AND_FREE);
90 guid_memchunk_shutdown (
void)
94 g_mem_chunk_destroy (guid_memchunk);
103 guid_memchunk_init ();
104 return g_chunk_new (
GUID, guid_memchunk);
108 guid_free (
GUID * guid)
113 g_chunk_free (guid, guid_memchunk);
121 static int null_inited = 0;
122 static GUID null_guid;
127 char *tmp =
"NULLGUID.EMPTY.";
131 null_guid.data[i] = tmp[i];
143 init_from_stream (FILE * stream,
size_t max_size)
145 char buffer[BLOCKSIZE + 72];
146 size_t sum, block_size, total;
162 if (max_size < BLOCKSIZE)
163 block_size = max_size;
165 block_size = BLOCKSIZE;
170 n = fread (buffer + sum, 1, block_size - sum, stream);
174 while (sum < block_size && n != 0);
178 if (n == 0 && ferror (stream))
182 if ((n == 0) || (max_size == 0))
187 md5_process_block (buffer, BLOCKSIZE, &guid_context);
195 md5_process_bytes (buffer, sum, &guid_context);
203 init_from_file (
const char *filename,
size_t max_size)
210 memset (&stats, 0,
sizeof (stats));
211 if (stat (filename, &stats) != 0)
214 md5_process_bytes (&stats,
sizeof (stats), &guid_context);
215 total +=
sizeof (stats);
220 fp = fopen (filename,
"r");
224 file_bytes = init_from_stream (fp, max_size);
226 PINFO (
"guid_init got %llu bytes from %s",
227 (
unsigned long long int) file_bytes, filename);
237 init_from_dir (
const char *dirname,
unsigned int max_files)
249 dir = opendir (dirname);
261 md5_process_bytes (de->d_name, strlen (de->d_name), &guid_context);
262 total += strlen (de->d_name);
264 result = snprintf (filename,
sizeof (filename),
265 "%s/%s", dirname, de->d_name);
266 if ((result < 0) || (result >= (
int)
sizeof (filename)))
269 memset (&stats, 0,
sizeof (stats));
270 if (stat (filename, &stats) != 0)
272 md5_process_bytes (&stats,
sizeof (stats), &guid_context);
273 total +=
sizeof (stats);
277 while (max_files > 0);
285 init_from_time (
void)
289 #ifdef HAVE_SYS_TIMES_H
296 t_time = time (NULL);
297 md5_process_bytes (&t_time,
sizeof (t_time), &guid_context);
298 total +=
sizeof (t_time);
300 #ifdef HAVE_SYS_TIMES_H
301 clocks = times (&tms_buf);
302 md5_process_bytes (&clocks,
sizeof (clocks), &guid_context);
303 md5_process_bytes (&tms_buf,
sizeof (tms_buf), &guid_context);
304 total +=
sizeof (clocks) +
sizeof (tms_buf);
311 init_from_int (
int val)
313 md5_process_bytes (&val,
sizeof (val), &guid_context);
318 init_from_buff (
unsigned char *buf,
size_t buflen)
320 md5_process_bytes (buf, buflen, &guid_context);
332 md5_init_ctx (&guid_context);
335 bytes += init_from_file (
"/dev/urandom", 512);
339 const char *files[] = {
"/etc/passwd",
344 "/proc/self/environ",
352 for (i = 0; files[i] != NULL; i++)
353 bytes += init_from_file (files[i], BLOCKSIZE);
359 const char *dirs[] = {
371 for (i = 0; dirs[i] != NULL; i++)
372 bytes += init_from_dir (dirs[i], 32);
374 dirname = g_get_home_dir ();
376 bytes += init_from_dir (dirname, 32);
384 md5_process_bytes (&pid,
sizeof (pid), &guid_context);
385 bytes +=
sizeof (pid);
389 md5_process_bytes (&pid,
sizeof (pid), &guid_context);
390 bytes +=
sizeof (pid);
404 md5_process_bytes (s, strlen (s), &guid_context);
409 md5_process_bytes (&uid,
sizeof (uid), &guid_context);
410 bytes +=
sizeof (uid);
413 md5_process_bytes (&gid,
sizeof (gid), &guid_context);
414 bytes +=
sizeof (gid);
420 #ifdef HAVE_GETHOSTNAME
423 memset (
string, 0,
sizeof (
string));
424 gethostname (
string,
sizeof (
string));
425 md5_process_bytes (
string,
sizeof (
string), &guid_context);
426 bytes +=
sizeof (string);
434 srand ((
unsigned int) time (NULL));
436 for (i = 0; i < 32; i++)
440 md5_process_bytes (&n,
sizeof (n), &guid_context);
446 bytes += init_from_time ();
448 PINFO (
"got %llu bytes", (
unsigned long long int) bytes);
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);
455 guid_initialized = TRUE;
463 md5_process_bytes (salt, salt_len, &guid_context);
469 md5_init_ctx (&guid_context);
471 md5_process_bytes (salt, salt_len, &guid_context);
473 guid_initialized = TRUE;
480 guid_memchunk_shutdown ();
484 #define GUID_PERIOD 5000
489 static int counter = 0;
495 if (!guid_initialized)
500 md5_finish_ctx (&ctx, guid->data);
516 init_from_int (433781 * counter);
523 fp = fopen (
"/dev/urandom",
"r");
527 init_from_stream (fp, 32);
531 counter = GUID_PERIOD;
549 encode_md5_data (
const unsigned char *data,
char *buffer)
554 sprintf (buffer,
"%02x", data[count]);
561 decode_md5_string (
const unsigned char *
string,
unsigned char *data)
563 unsigned char n1, n2;
565 unsigned char c1, c2;
575 if ((0 ==
string[2 * count]) || (0 ==
string[2 * count + 1]))
578 c1 = tolower (
string[2 * count]);
582 c2 = tolower (
string[2 * count + 1]);
596 data[count] = (n1 << 4) | n2;
613 #ifdef G_THREADS_ENABLED
614 static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT;
617 string = g_static_private_get (&guid_buffer_key);
621 g_static_private_set (&guid_buffer_key,
string, g_free);
624 static char string[64];
627 encode_md5_data (guid->data,
string);
636 if (!
string || !guid)
639 encode_md5_data (guid->data,
string);
648 return decode_md5_string (
string, (guid != NULL) ? guid->data : NULL);
654 if (guid_1 && guid_2)
655 return (memcmp (guid_1, guid_2, GUID_DATA_SIZE) == 0);
661 guid_compare (
const GUID * guid_1,
const GUID * guid_2)
663 if (guid_1 == guid_2)
667 if (!guid_1 && guid_2)
670 if (guid_1 && !guid_2)
673 return memcmp (guid_1, guid_2, GUID_DATA_SIZE);
679 const GUID *guid = ptr;
683 PERR (
"received NULL guid pointer.");
687 if (
sizeof (guint) <=
sizeof (guid->data))
689 return (*((guint *) guid->data));
696 for (i = 0, j = 0; i <
sizeof (guint); i++, j++)
698 if (j == GUID_DATA_SIZE)
702 hash |= guid->data[j];
710 guid_g_hash_table_equal (gconstpointer guid_a, gconstpointer guid_b)
716 guid_hash_table_new (
void)