Merge branch 'dbus-1.10'
[platform/upstream/dbus.git] / dbus / dbus-internals.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-internals.c  random utility stuff (internal to D-Bus implementation)
3  *
4  * Copyright (C) 2002, 2003  Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #include <config.h>
25 #include "dbus-internals.h"
26 #include "dbus-protocol.h"
27 #include "dbus-marshal-basic.h"
28 #include "dbus-test.h"
29 #include "dbus-valgrind-internal.h"
30 #include <stdio.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING
35 #include <windows.h>
36 #include <mbstring.h>
37 #endif
38
39 /**
40  * @defgroup DBusInternals D-Bus secret internal implementation details
41  * @brief Documentation useful when developing or debugging D-Bus itself.
42  * 
43  */
44
45 /**
46  * @defgroup DBusInternalsUtils Utilities and portability
47  * @ingroup DBusInternals
48  * @brief Utility functions (_dbus_assert(), _dbus_warn(), etc.)
49  * @{
50  */
51
52 /**
53  * @def _dbus_assert
54  *
55  * Aborts with an error message if the condition is false.
56  * 
57  * @param condition condition which must be true.
58  */
59
60 /**
61  * @def _dbus_assert_not_reached
62  *
63  * Aborts with an error message if called.
64  * The given explanation will be printed.
65  * 
66  * @param explanation explanation of what happened if the code was reached.
67  */
68
69 /**
70  * @def _DBUS_N_ELEMENTS
71  *
72  * Computes the number of elements in a fixed-size array using
73  * sizeof().
74  *
75  * @param array the array to count elements in.
76  */
77
78 /**
79  * @def _DBUS_POINTER_TO_INT
80  *
81  * Safely casts a void* to an integer; should only be used on void*
82  * that actually contain integers, for example one created with
83  * _DBUS_INT_TO_POINTER.  Only guaranteed to preserve 32 bits.
84  * (i.e. it's used to store 32-bit ints in pointers, but
85  * can't be used to store 64-bit pointers in ints.)
86  *
87  * @param pointer pointer to extract an integer from.
88  */
89 /**
90  * @def _DBUS_INT_TO_POINTER
91  *
92  * Safely stuffs an integer into a pointer, to be extracted later with
93  * _DBUS_POINTER_TO_INT. Only guaranteed to preserve 32 bits.
94  *
95  * @param integer the integer to stuff into a pointer.
96  */
97 /**
98  * @def _DBUS_ZERO
99  *
100  * Sets all bits in an object to zero.
101  *
102  * @param object the object to be zeroed.
103  */
104 /**
105  * @def _DBUS_INT16_MIN
106  *
107  * Minimum value of type "int16"
108  */
109 /**
110  * @def _DBUS_INT16_MAX
111  *
112  * Maximum value of type "int16"
113  */
114 /**
115  * @def _DBUS_UINT16_MAX
116  *
117  * Maximum value of type "uint16"
118  */
119
120 /**
121  * @def _DBUS_INT32_MIN
122  *
123  * Minimum value of type "int32"
124  */
125 /**
126  * @def _DBUS_INT32_MAX
127  *
128  * Maximum value of type "int32"
129  */
130 /**
131  * @def _DBUS_UINT32_MAX
132  *
133  * Maximum value of type "uint32"
134  */
135
136 /**
137  * @def _DBUS_INT_MIN
138  *
139  * Minimum value of type "int"
140  */
141 /**
142  * @def _DBUS_INT_MAX
143  *
144  * Maximum value of type "int"
145  */
146 /**
147  * @def _DBUS_UINT_MAX
148  *
149  * Maximum value of type "uint"
150  */
151
152 /**
153  * @typedef DBusForeachFunction
154  * 
155  * Used to iterate over each item in a collection, such as
156  * a DBusList.
157  */
158
159 /**
160  * @def _DBUS_LOCK_NAME
161  *
162  * Expands to name of a global lock variable.
163  */
164
165 /**
166  * @def _DBUS_LOCK
167  *
168  * Locks a global lock, initializing it first if necessary.
169  *
170  * @returns #FALSE if not enough memory
171  */
172
173 /**
174  * @def _DBUS_UNLOCK
175  *
176  * Unlocks a global lock
177  */
178
179 /**
180  * Fixed "out of memory" error message, just to avoid
181  * making up a different string every time and wasting
182  * space.
183  */
184 const char *_dbus_no_memory_message = "Not enough memory";
185
186 static dbus_bool_t warn_initted = FALSE;
187 static dbus_bool_t fatal_warnings = FALSE;
188 static dbus_bool_t fatal_warnings_on_check_failed = TRUE;
189
190 static void
191 init_warnings(void)
192 {
193   if (!warn_initted)
194     {
195       const char *s;
196       s = _dbus_getenv ("DBUS_FATAL_WARNINGS");
197       if (s && *s)
198         {
199           if (*s == '0')
200             {
201               fatal_warnings = FALSE;
202               fatal_warnings_on_check_failed = FALSE;
203             }
204           else if (*s == '1')
205             {
206               fatal_warnings = TRUE;
207               fatal_warnings_on_check_failed = TRUE;
208             }
209           else
210             {
211               fprintf(stderr, "DBUS_FATAL_WARNINGS should be set to 0 or 1 if set, not '%s'",
212                       s);
213             }
214         }
215
216       warn_initted = TRUE;
217     }
218 }
219
220 /**
221  * Prints a warning message to stderr. Can optionally be made to exit
222  * fatally by setting DBUS_FATAL_WARNINGS, but this is rarely
223  * used. This function should be considered pretty much equivalent to
224  * fprintf(stderr). _dbus_warn_check_failed() on the other hand is
225  * suitable for use when a programming mistake has been made.
226  *
227  * @param format printf-style format string.
228  */
229 void
230 _dbus_warn (const char *format,
231             ...)
232 {
233   va_list args;
234
235   if (!warn_initted)
236     init_warnings ();
237   
238   va_start (args, format);
239   vfprintf (stderr, format, args);
240   va_end (args);
241
242   if (fatal_warnings)
243     {
244       fflush (stderr);
245       _dbus_abort ();
246     }
247 }
248
249 /**
250  * Prints a "critical" warning to stderr when an assertion fails;
251  * differs from _dbus_warn primarily in that it prefixes the pid and
252  * defaults to fatal. This should be used only when a programming
253  * error has been detected. (NOT for unavoidable errors that an app
254  * might handle - those should be returned as DBusError.) Calling this
255  * means "there is a bug"
256  */
257 void
258 _dbus_warn_check_failed(const char *format,
259                         ...)
260 {
261   va_list args;
262   
263   if (!warn_initted)
264     init_warnings ();
265
266   fprintf (stderr, "process %lu: ", _dbus_pid_for_log ());
267   
268   va_start (args, format);
269   vfprintf (stderr, format, args);
270   va_end (args);
271
272   if (fatal_warnings_on_check_failed)
273     {
274       fflush (stderr);
275       _dbus_abort ();
276     }
277 }
278
279 #ifdef DBUS_ENABLE_VERBOSE_MODE
280
281 static dbus_bool_t verbose_initted = FALSE;
282 static dbus_bool_t verbose = TRUE;
283
284 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING
285 static char module_name[1024];
286 #endif
287
288 static inline void
289 _dbus_verbose_init (void)
290 {
291   if (!verbose_initted)
292     {
293       const char *p = _dbus_getenv ("DBUS_VERBOSE");
294       verbose = p != NULL && *p == '1';
295       verbose_initted = TRUE;
296 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING
297       {
298         char *last_period, *last_slash;
299         GetModuleFileName(0,module_name,sizeof(module_name)-1);
300         last_period = _mbsrchr(module_name,'.');
301         if (last_period)
302           *last_period ='\0';
303         last_slash = _mbsrchr(module_name,'\\');
304         if (last_slash)
305           strcpy(module_name,last_slash+1);
306         strcat(module_name,": ");
307       }
308 #endif
309     }
310 }
311
312 /** @def DBUS_IS_DIR_SEPARATOR(c)
313  * macro for checking if character c is a patch separator
314  * 
315  * @todo move to a header file so that others can use this too
316  */
317 #ifdef DBUS_WIN 
318 #define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/')
319 #else
320 #define DBUS_IS_DIR_SEPARATOR(c) (c == '/')
321 #endif
322
323 /** 
324  remove source root from file path 
325  the source root is determined by 
326 */ 
327 static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level)
328 {
329   int prefix = 0;
330   char *p = (char *)file + strlen(file);
331   int i = 0;
332
333   for (;p >= file;p--)
334     {
335       if (DBUS_IS_DIR_SEPARATOR(*p))
336         {
337           if (++i >= level)
338             {
339               prefix = p-file+1;
340               break;
341             }
342        }
343     }
344
345   return (char *)file+prefix;
346 }
347
348 /**
349  * Implementation of dbus_is_verbose() macro if built with verbose logging
350  * enabled.
351  * @returns whether verbose logging is active.
352  */
353 dbus_bool_t
354 _dbus_is_verbose_real (void)
355 {
356   _dbus_verbose_init ();
357   return verbose;
358 }
359
360 void _dbus_set_verbose (dbus_bool_t state)
361 {
362     verbose = state;
363 }
364
365 dbus_bool_t _dbus_get_verbose (void)
366 {
367     return verbose;
368 }
369
370 /**
371  * Prints a warning message to stderr
372  * if the user has enabled verbose mode.
373  * This is the real function implementation,
374  * use _dbus_verbose() macro in code.
375  *
376  * @param format printf-style format string.
377  */
378 void
379 _dbus_verbose_real (
380 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
381                     const char *file,
382                     const int line, 
383                     const char *function, 
384 #endif
385                     const char *format,
386                     ...)
387 {
388   va_list args;
389   static dbus_bool_t need_pid = TRUE;
390   int len;
391   long sec, usec;
392   _dbus_get_real_time (&sec, &usec);
393   
394   /* things are written a bit oddly here so that
395    * in the non-verbose case we just have the one
396    * conditional and return immediately.
397    */
398   if (!_dbus_is_verbose_real())
399     return;
400
401 #ifndef DBUS_USE_OUTPUT_DEBUG_STRING
402   /* Print out pid before the line */
403   if (need_pid)
404     {
405       _dbus_print_thread ();
406     }
407 #endif
408   fprintf (stderr, "%ld.%06ld ", sec, usec);
409
410   /* Only print pid again if the next line is a new line */
411   len = strlen (format);
412   if (format[len-1] == '\n')
413     need_pid = TRUE;
414   else
415     need_pid = FALSE;
416
417   va_start (args, format);
418 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING
419   {
420   char buf[1024];
421   strcpy(buf,module_name);
422 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
423   sprintf (buf+strlen(buf), "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
424 #endif
425   vsprintf (buf+strlen(buf),format, args);
426   va_end (args);
427   OutputDebugStringA(buf);
428   }
429 #else
430 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
431   fprintf (stderr, "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
432 #endif
433
434   vfprintf (stderr, format, args);
435   va_end (args);
436
437   fflush (stderr);
438 #endif
439 }
440
441 /**
442  * Reinitializes the verbose logging code, used
443  * as a hack in dbus-spawn.c so that a child
444  * process re-reads its pid
445  *
446  */
447 void
448 _dbus_verbose_reset_real (void)
449 {
450   verbose_initted = FALSE;
451 }
452
453 void
454 _dbus_trace_ref (const char *obj_name,
455                  void       *obj,
456                  int         old_refcount,
457                  int         new_refcount,
458                  const char *why,
459                  const char *env_var,
460                  int        *enabled)
461 {
462   _dbus_assert (obj_name != NULL);
463   _dbus_assert (obj != NULL);
464   _dbus_assert (old_refcount >= -1);
465   _dbus_assert (new_refcount >= -1);
466
467   if (old_refcount == -1)
468     {
469       _dbus_assert (new_refcount == -1);
470     }
471   else
472     {
473       _dbus_assert (new_refcount >= 0);
474       _dbus_assert (old_refcount >= 0);
475       _dbus_assert (old_refcount > 0 || new_refcount > 0);
476     }
477
478   _dbus_assert (why != NULL);
479   _dbus_assert (env_var != NULL);
480   _dbus_assert (enabled != NULL);
481
482   if (*enabled < 0)
483     {
484       const char *s = _dbus_getenv (env_var);
485
486       *enabled = FALSE;
487
488       if (s && *s)
489         {
490           if (*s == '0')
491             *enabled = FALSE;
492           else if (*s == '1')
493             *enabled = TRUE;
494           else
495             _dbus_warn ("%s should be 0 or 1 if set, not '%s'", env_var, s);
496         }
497     }
498
499   if (*enabled)
500     {
501       if (old_refcount == -1)
502         {
503           VALGRIND_PRINTF_BACKTRACE ("%s %p ref stolen (%s)",
504                                      obj_name, obj, why);
505           _dbus_verbose ("%s %p ref stolen (%s)\n",
506                          obj_name, obj, why);
507         }
508       else
509         {
510           VALGRIND_PRINTF_BACKTRACE ("%s %p %d -> %d refs (%s)",
511                                      obj_name, obj,
512                                      old_refcount, new_refcount, why);
513           _dbus_verbose ("%s %p %d -> %d refs (%s)\n",
514                          obj_name, obj, old_refcount, new_refcount, why);
515         }
516     }
517 }
518
519 #endif /* DBUS_ENABLE_VERBOSE_MODE */
520
521 /**
522  * Duplicates a string. Result must be freed with
523  * dbus_free(). Returns #NULL if memory allocation fails.
524  * If the string to be duplicated is #NULL, returns #NULL.
525  * 
526  * @param str string to duplicate.
527  * @returns newly-allocated copy.
528  */
529 char*
530 _dbus_strdup (const char *str)
531 {
532   size_t len;
533   char *copy;
534   
535   if (str == NULL)
536     return NULL;
537   
538   len = strlen (str);
539
540   copy = dbus_malloc (len + 1);
541   if (copy == NULL)
542     return NULL;
543
544   memcpy (copy, str, len + 1);
545   
546   return copy;
547 }
548
549 /**
550  * Duplicates a block of memory. Returns
551  * #NULL on failure.
552  *
553  * @param mem memory to copy
554  * @param n_bytes number of bytes to copy
555  * @returns the copy
556  */
557 void*
558 _dbus_memdup (const void  *mem,
559               size_t       n_bytes)
560 {
561   void *copy;
562
563   copy = dbus_malloc (n_bytes);
564   if (copy == NULL)
565     return NULL;
566
567   memcpy (copy, mem, n_bytes);
568   
569   return copy;
570 }
571
572 /**
573  * Duplicates a string array. Result may be freed with
574  * dbus_free_string_array(). Returns #NULL if memory allocation fails.
575  * If the array to be duplicated is #NULL, returns #NULL.
576  * 
577  * @param array array to duplicate.
578  * @returns newly-allocated copy.
579  */
580 char**
581 _dbus_dup_string_array (const char **array)
582 {
583   int len;
584   int i;
585   char **copy;
586   
587   if (array == NULL)
588     return NULL;
589
590   for (len = 0; array[len] != NULL; ++len)
591     ;
592
593   copy = dbus_new0 (char*, len + 1);
594   if (copy == NULL)
595     return NULL;
596
597   i = 0;
598   while (i < len)
599     {
600       copy[i] = _dbus_strdup (array[i]);
601       if (copy[i] == NULL)
602         {
603           dbus_free_string_array (copy);
604           return NULL;
605         }
606
607       ++i;
608     }
609
610   return copy;
611 }
612
613 /**
614  * Checks whether a string array contains the given string.
615  * 
616  * @param array array to search.
617  * @param str string to look for
618  * @returns #TRUE if array contains string
619  */
620 dbus_bool_t
621 _dbus_string_array_contains (const char **array,
622                              const char  *str)
623 {
624   int i;
625
626   i = 0;
627   while (array[i] != NULL)
628     {
629       if (strcmp (array[i], str) == 0)
630         return TRUE;
631       ++i;
632     }
633
634   return FALSE;
635 }
636
637 /**
638  * Returns the size of a string array
639  *
640  * @param array array to search.
641  * @returns size of array
642  */
643 size_t
644 _dbus_string_array_length (const char **array)
645 {
646   size_t i;
647   for (i = 0; array[i]; i++) {}
648   return i;
649 }
650
651
652 /**
653  * Generates a new UUID. If you change how this is done,
654  * there's some text about it in the spec that should also change.
655  *
656  * @param uuid the uuid to initialize
657  * @param error location to store reason for failure
658  * @returns #TRUE on success
659  */
660 dbus_bool_t
661 _dbus_generate_uuid (DBusGUID  *uuid,
662                      DBusError *error)
663 {
664   DBusError rand_error;
665   long now;
666
667   dbus_error_init (&rand_error);
668
669   /* don't use monotonic time because the UUID may be saved to disk, e.g.
670    * it may persist across reboots
671    */
672   _dbus_get_real_time (&now, NULL);
673
674   uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
675   
676   if (!_dbus_generate_random_bytes_buffer (uuid->as_bytes,
677                                            DBUS_UUID_LENGTH_BYTES - 4,
678                                            &rand_error))
679     {
680       dbus_set_error (error, rand_error.name,
681                       "Failed to generate UUID: %s", rand_error.message);
682       dbus_error_free (&rand_error);
683       return FALSE;
684     }
685
686   return TRUE;
687 }
688
689 /**
690  * Hex-encode a UUID.
691  *
692  * @param uuid the uuid
693  * @param encoded string to append hex uuid to
694  * @returns #FALSE if no memory
695  */
696 dbus_bool_t
697 _dbus_uuid_encode (const DBusGUID *uuid,
698                    DBusString     *encoded)
699 {
700   DBusString binary;
701   _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
702   return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
703 }
704
705 static dbus_bool_t
706 _dbus_read_uuid_file_without_creating (const DBusString *filename,
707                                        DBusGUID         *uuid,
708                                        DBusError        *error)
709 {
710   DBusString contents;
711   DBusString decoded;
712   int end;
713   
714   if (!_dbus_string_init (&contents))
715     {
716       _DBUS_SET_OOM (error);
717       return FALSE;
718     }
719
720   if (!_dbus_string_init (&decoded))
721     {
722       _dbus_string_free (&contents);
723       _DBUS_SET_OOM (error);
724       return FALSE;
725     }
726   
727   if (!_dbus_file_get_contents (&contents, filename, error))
728     goto error;
729
730   _dbus_string_chop_white (&contents);
731
732   if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
733     {
734       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
735                       "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
736                       _dbus_string_get_const_data (filename),
737                       DBUS_UUID_LENGTH_HEX,
738                       _dbus_string_get_length (&contents));
739       goto error;
740     }
741
742   if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
743     {
744       _DBUS_SET_OOM (error);
745       goto error;
746     }
747
748   if (end == 0)
749     {
750       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
751                       "UUID file '%s' contains invalid hex data",
752                       _dbus_string_get_const_data (filename));
753       goto error;
754     }
755
756   if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
757     {
758       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
759                       "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
760                       _dbus_string_get_const_data (filename),
761                       _dbus_string_get_length (&decoded),
762                       DBUS_UUID_LENGTH_BYTES);
763       goto error;
764     }
765
766   _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
767
768   _dbus_string_free (&decoded);
769   _dbus_string_free (&contents);
770
771   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
772
773   return TRUE;
774   
775  error:
776   _DBUS_ASSERT_ERROR_IS_SET (error);
777   _dbus_string_free (&contents);
778   _dbus_string_free (&decoded);
779   return FALSE;
780 }
781
782 /**
783  * Write the give UUID to a file.
784  *
785  * @param filename the file to write
786  * @param uuid the UUID to save
787  * @param error used to raise an error
788  * @returns #FALSE on error
789  */
790 dbus_bool_t
791 _dbus_write_uuid_file (const DBusString *filename,
792                        const DBusGUID   *uuid,
793                        DBusError        *error)
794 {
795   DBusString encoded;
796
797   if (!_dbus_string_init (&encoded))
798     {
799       _DBUS_SET_OOM (error);
800       return FALSE;
801     }
802   
803   if (!_dbus_uuid_encode (uuid, &encoded))
804     {
805       _DBUS_SET_OOM (error);
806       goto error;
807     }
808   
809   if (!_dbus_string_append_byte (&encoded, '\n'))
810     {
811       _DBUS_SET_OOM (error);
812       goto error;
813     }
814   
815   if (!_dbus_string_save_to_file (&encoded, filename, TRUE, error))
816     goto error;
817
818   _dbus_string_free (&encoded);
819
820   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
821   return TRUE;
822   
823  error:
824   _DBUS_ASSERT_ERROR_IS_SET (error);
825   _dbus_string_free (&encoded);
826   return FALSE;        
827 }
828
829 /**
830  * Reads (and optionally writes) a uuid to a file. Initializes the uuid
831  * unless an error is returned.
832  *
833  * @param filename the name of the file
834  * @param uuid uuid to be initialized with the loaded uuid
835  * @param create_if_not_found #TRUE to create a new uuid and save it if the file doesn't exist
836  * @param error the error return
837  * @returns #FALSE if the error is set
838  */
839 dbus_bool_t
840 _dbus_read_uuid_file (const DBusString *filename,
841                       DBusGUID         *uuid,
842                       dbus_bool_t       create_if_not_found,
843                       DBusError        *error)
844 {
845   DBusError read_error = DBUS_ERROR_INIT;
846
847   if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
848     return TRUE;
849
850   if (!create_if_not_found)
851     {
852       dbus_move_error (&read_error, error);
853       return FALSE;
854     }
855
856   /* If the file exists and contains junk, we want to keep that error
857    * message instead of overwriting it with a "file exists" error
858    * message when we try to write
859    */
860   if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT))
861     {
862       dbus_move_error (&read_error, error);
863       return FALSE;
864     }
865   else
866     {
867       dbus_error_free (&read_error);
868
869       if (!_dbus_generate_uuid (uuid, error))
870         return FALSE;
871
872       return _dbus_write_uuid_file (filename, uuid, error);
873     }
874 }
875
876 /* Protected by _DBUS_LOCK (machine_uuid) */
877 static int machine_uuid_initialized_generation = 0;
878 static DBusGUID machine_uuid;
879
880 /**
881  * Gets the hex-encoded UUID of the machine this function is
882  * executed on. This UUID is guaranteed to be the same for a given
883  * machine at least until it next reboots, though it also
884  * makes some effort to be the same forever, it may change if the
885  * machine is reconfigured or its hardware is modified.
886  * 
887  * @param uuid_str string to append hex-encoded machine uuid to
888  * @param error location to store reason for failure
889  * @returns #TRUE if successful
890  */
891 dbus_bool_t
892 _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str,
893                                       DBusError  *error)
894 {
895   dbus_bool_t ok = TRUE;
896   
897   if (!_DBUS_LOCK (machine_uuid))
898     {
899       _DBUS_SET_OOM (error);
900       return FALSE;
901     }
902
903   if (machine_uuid_initialized_generation != _dbus_current_generation)
904     {
905       DBusError local_error = DBUS_ERROR_INIT;
906
907       if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
908                                           &local_error))
909         {          
910 #ifndef DBUS_ENABLE_EMBEDDED_TESTS
911           /* For the test suite, we may not be installed so just continue silently
912            * here. But in a production build, we want to be nice and loud about
913            * this.
914            */
915           _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n"
916                                    "See the manual page for dbus-uuidgen to correct this issue.\n",
917                                    local_error.message);
918 #endif
919           
920           dbus_error_free (&local_error);
921           
922           ok = _dbus_generate_uuid (&machine_uuid, error);
923         }
924     }
925
926   if (ok)
927     {
928       if (!_dbus_uuid_encode (&machine_uuid, uuid_str))
929         {
930           ok = FALSE;
931           _DBUS_SET_OOM (error);
932         }
933     }
934
935   _DBUS_UNLOCK (machine_uuid);
936
937   return ok;
938 }
939
940 #ifndef DBUS_DISABLE_CHECKS
941 /** String used in _dbus_return_if_fail macro */
942 const char *_dbus_return_if_fail_warning_format =
943 "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
944 "This is normally a bug in some application using the D-Bus library.\n";
945 #endif
946
947 #ifndef DBUS_DISABLE_ASSERT
948 /**
949  * Internals of _dbus_assert(); it's a function
950  * rather than a macro with the inline code so
951  * that the assertion failure blocks don't show up
952  * in test suite coverage, and to shrink code size.
953  *
954  * @param condition TRUE if assertion succeeded
955  * @param condition_text condition as a string
956  * @param file file the assertion is in
957  * @param line line the assertion is in
958  * @param func function the assertion is in
959  */
960 void
961 _dbus_real_assert (dbus_bool_t  condition,
962                    const char  *condition_text,
963                    const char  *file,
964                    int          line,
965                    const char  *func)
966 {
967   if (_DBUS_UNLIKELY (!condition))
968     {
969       _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
970                   _dbus_pid_for_log (), condition_text, file, line, func);
971       _dbus_abort ();
972     }
973 }
974
975 /**
976  * Internals of _dbus_assert_not_reached(); it's a function
977  * rather than a macro with the inline code so
978  * that the assertion failure blocks don't show up
979  * in test suite coverage, and to shrink code size.
980  *
981  * @param explanation what was reached that shouldn't have been
982  * @param file file the assertion is in
983  * @param line line the assertion is in
984  */
985 void
986 _dbus_real_assert_not_reached (const char *explanation,
987                                const char *file,
988                                int         line)
989 {
990   _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
991               file, line, _dbus_pid_for_log (), explanation);
992   _dbus_abort ();
993 }
994 #endif /* DBUS_DISABLE_ASSERT */
995   
996 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
997 static dbus_bool_t
998 run_failing_each_malloc (int                    n_mallocs,
999                          const char            *description,
1000                          DBusTestMemoryFunction func,
1001                          void                  *data)
1002 {
1003   n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
1004   
1005   while (n_mallocs >= 0)
1006     {      
1007       _dbus_set_fail_alloc_counter (n_mallocs);
1008
1009       _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
1010                      description, n_mallocs,
1011                      _dbus_get_fail_alloc_failures ());
1012
1013       if (!(* func) (data))
1014         return FALSE;
1015       
1016       n_mallocs -= 1;
1017     }
1018
1019   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
1020
1021   return TRUE;
1022 }                        
1023
1024 /**
1025  * Tests how well the given function responds to out-of-memory
1026  * situations. Calls the function repeatedly, failing a different
1027  * call to malloc() each time. If the function ever returns #FALSE,
1028  * the test fails. The function should return #TRUE whenever something
1029  * valid (such as returning an error, or succeeding) occurs, and #FALSE
1030  * if it gets confused in some way.
1031  *
1032  * @param description description of the test used in verbose output
1033  * @param func function to call
1034  * @param data data to pass to function
1035  * @returns #TRUE if the function never returns FALSE
1036  */
1037 dbus_bool_t
1038 _dbus_test_oom_handling (const char             *description,
1039                          DBusTestMemoryFunction  func,
1040                          void                   *data)
1041 {
1042   int approx_mallocs;
1043   const char *setting;
1044   int max_failures_to_try;
1045   int i;
1046
1047   /* Run once to see about how many mallocs are involved */
1048   
1049   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
1050
1051   _dbus_verbose ("Running once to count mallocs\n");
1052   
1053   if (!(* func) (data))
1054     return FALSE;
1055   
1056   approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
1057
1058   _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
1059                  description, approx_mallocs);
1060
1061   setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
1062   if (setting != NULL)
1063     {
1064       DBusString str;
1065       long v;
1066       _dbus_string_init_const (&str, setting);
1067       v = 4;
1068       if (!_dbus_string_parse_int (&str, 0, &v, NULL))
1069         _dbus_warn ("couldn't parse '%s' as integer\n", setting);
1070       max_failures_to_try = v;
1071     }
1072   else
1073     {
1074       max_failures_to_try = 4;
1075     }
1076
1077   if (max_failures_to_try < 1)
1078     {
1079       _dbus_verbose ("not testing OOM handling\n");
1080       return TRUE;
1081     }
1082
1083   i = setting ? max_failures_to_try - 1 : 1;
1084   while (i < max_failures_to_try)
1085     {
1086       _dbus_set_fail_alloc_failures (i);
1087       if (!run_failing_each_malloc (approx_mallocs, description, func, data))
1088         return FALSE;
1089       ++i;
1090     }
1091   
1092   _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
1093                  description);
1094
1095   return TRUE;
1096 }
1097 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
1098
1099 /** @} */