Merge remote-tracking branch 'freedesktop/master'
[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 /** Whether to show the current thread in verbose messages */
285 #define PTHREAD_IN_VERBOSE 0
286 #if PTHREAD_IN_VERBOSE
287 #include <pthread.h>
288 #endif
289
290 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING
291 static char module_name[1024];
292 #endif
293
294 static inline void
295 _dbus_verbose_init (void)
296 {
297   if (!verbose_initted)
298     {
299       const char *p = _dbus_getenv ("DBUS_VERBOSE");
300       verbose = p != NULL && *p == '1';
301       verbose_initted = TRUE;
302 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING
303       {
304         char *last_period, *last_slash;
305         GetModuleFileName(0,module_name,sizeof(module_name)-1);
306         last_period = _mbsrchr(module_name,'.');
307         if (last_period)
308           *last_period ='\0';
309         last_slash = _mbsrchr(module_name,'\\');
310         if (last_slash)
311           strcpy(module_name,last_slash+1);
312         strcat(module_name,": ");
313       }
314 #endif
315     }
316 }
317
318 /** @def DBUS_IS_DIR_SEPARATOR(c)
319  * macro for checking if character c is a patch separator
320  * 
321  * @todo move to a header file so that others can use this too
322  */
323 #ifdef DBUS_WIN 
324 #define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/')
325 #else
326 #define DBUS_IS_DIR_SEPARATOR(c) (c == '/')
327 #endif
328
329 /** 
330  remove source root from file path 
331  the source root is determined by 
332 */ 
333 static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level)
334 {
335   int prefix = 0;
336   char *p = (char *)file + strlen(file);
337   int i = 0;
338
339   for (;p >= file;p--)
340     {
341       if (DBUS_IS_DIR_SEPARATOR(*p))
342         {
343           if (++i >= level)
344             {
345               prefix = p-file+1;
346               break;
347             }
348        }
349     }
350
351   return (char *)file+prefix;
352 }
353
354 /**
355  * Implementation of dbus_is_verbose() macro if built with verbose logging
356  * enabled.
357  * @returns whether verbose logging is active.
358  */
359 dbus_bool_t
360 _dbus_is_verbose_real (void)
361 {
362   _dbus_verbose_init ();
363   return verbose;
364 }
365
366 /**
367  * Prints a warning message to stderr
368  * if the user has enabled verbose mode.
369  * This is the real function implementation,
370  * use _dbus_verbose() macro in code.
371  *
372  * @param format printf-style format string.
373  */
374 void
375 _dbus_verbose_real (
376 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
377                     const char *file,
378                     const int line, 
379                     const char *function, 
380 #endif
381                     const char *format,
382                     ...)
383 {
384   va_list args;
385   static dbus_bool_t need_pid = TRUE;
386   int len;
387   
388   /* things are written a bit oddly here so that
389    * in the non-verbose case we just have the one
390    * conditional and return immediately.
391    */
392   if (!_dbus_is_verbose_real())
393     return;
394
395 #ifndef DBUS_USE_OUTPUT_DEBUG_STRING
396   /* Print out pid before the line */
397   if (need_pid)
398     {
399 #if PTHREAD_IN_VERBOSE
400       fprintf (stderr, "%lu: 0x%lx: ", _dbus_pid_for_log (), pthread_self ());
401 #else
402       fprintf (stderr, "%lu: ", _dbus_pid_for_log ());
403 #endif
404     }
405 #endif
406
407   /* Only print pid again if the next line is a new line */
408   len = strlen (format);
409   if (format[len-1] == '\n')
410     need_pid = TRUE;
411   else
412     need_pid = FALSE;
413
414   va_start (args, format);
415 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING
416   {
417   char buf[1024];
418   strcpy(buf,module_name);
419 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
420   sprintf (buf+strlen(buf), "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
421 #endif
422   vsprintf (buf+strlen(buf),format, args);
423   va_end (args);
424   OutputDebugStringA(buf);
425   }
426 #else
427 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
428   fprintf (stderr, "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
429 #endif
430
431   vfprintf (stderr, format, args);
432   va_end (args);
433
434   fflush (stderr);
435 #endif
436 }
437
438 /**
439  * Reinitializes the verbose logging code, used
440  * as a hack in dbus-spawn.c so that a child
441  * process re-reads its pid
442  *
443  */
444 void
445 _dbus_verbose_reset_real (void)
446 {
447   verbose_initted = FALSE;
448 }
449
450 void
451 _dbus_trace_ref (const char *obj_name,
452                  void       *obj,
453                  int         old_refcount,
454                  int         new_refcount,
455                  const char *why,
456                  const char *env_var,
457                  int        *enabled)
458 {
459   _dbus_assert (obj_name != NULL);
460   _dbus_assert (obj != NULL);
461   _dbus_assert (old_refcount >= -1);
462   _dbus_assert (new_refcount >= -1);
463
464   if (old_refcount == -1)
465     {
466       _dbus_assert (new_refcount == -1);
467     }
468   else
469     {
470       _dbus_assert (new_refcount >= 0);
471       _dbus_assert (old_refcount >= 0);
472       _dbus_assert (old_refcount > 0 || new_refcount > 0);
473     }
474
475   _dbus_assert (why != NULL);
476   _dbus_assert (env_var != NULL);
477   _dbus_assert (enabled != NULL);
478
479   if (*enabled < 0)
480     {
481       const char *s = _dbus_getenv (env_var);
482
483       *enabled = FALSE;
484
485       if (s && *s)
486         {
487           if (*s == '0')
488             *enabled = FALSE;
489           else if (*s == '1')
490             *enabled = TRUE;
491           else
492             _dbus_warn ("%s should be 0 or 1 if set, not '%s'", env_var, s);
493         }
494     }
495
496   if (*enabled)
497     {
498       if (old_refcount == -1)
499         {
500           VALGRIND_PRINTF_BACKTRACE ("%s %p ref stolen (%s)",
501                                      obj_name, obj, why);
502           _dbus_verbose ("%s %p ref stolen (%s)",
503                          obj_name, obj, why);
504         }
505       else
506         {
507           VALGRIND_PRINTF_BACKTRACE ("%s %p %d -> %d refs (%s)",
508                                      obj_name, obj,
509                                      old_refcount, new_refcount, why);
510           _dbus_verbose ("%s %p %d -> %d refs (%s)",
511                          obj_name, obj, old_refcount, new_refcount, why);
512         }
513     }
514 }
515
516 #endif /* DBUS_ENABLE_VERBOSE_MODE */
517
518 /**
519  * Duplicates a string. Result must be freed with
520  * dbus_free(). Returns #NULL if memory allocation fails.
521  * If the string to be duplicated is #NULL, returns #NULL.
522  * 
523  * @param str string to duplicate.
524  * @returns newly-allocated copy.
525  */
526 char*
527 _dbus_strdup (const char *str)
528 {
529   size_t len;
530   char *copy;
531   
532   if (str == NULL)
533     return NULL;
534   
535   len = strlen (str);
536
537   copy = dbus_malloc (len + 1);
538   if (copy == NULL)
539     return NULL;
540
541   memcpy (copy, str, len + 1);
542   
543   return copy;
544 }
545
546 /**
547  * Duplicates a block of memory. Returns
548  * #NULL on failure.
549  *
550  * @param mem memory to copy
551  * @param n_bytes number of bytes to copy
552  * @returns the copy
553  */
554 void*
555 _dbus_memdup (const void  *mem,
556               size_t       n_bytes)
557 {
558   void *copy;
559
560   copy = dbus_malloc (n_bytes);
561   if (copy == NULL)
562     return NULL;
563
564   memcpy (copy, mem, n_bytes);
565   
566   return copy;
567 }
568
569 /**
570  * Duplicates a string array. Result may be freed with
571  * dbus_free_string_array(). Returns #NULL if memory allocation fails.
572  * If the array to be duplicated is #NULL, returns #NULL.
573  * 
574  * @param array array to duplicate.
575  * @returns newly-allocated copy.
576  */
577 char**
578 _dbus_dup_string_array (const char **array)
579 {
580   int len;
581   int i;
582   char **copy;
583   
584   if (array == NULL)
585     return NULL;
586
587   for (len = 0; array[len] != NULL; ++len)
588     ;
589
590   copy = dbus_new0 (char*, len + 1);
591   if (copy == NULL)
592     return NULL;
593
594   i = 0;
595   while (i < len)
596     {
597       copy[i] = _dbus_strdup (array[i]);
598       if (copy[i] == NULL)
599         {
600           dbus_free_string_array (copy);
601           return NULL;
602         }
603
604       ++i;
605     }
606
607   return copy;
608 }
609
610 /**
611  * Checks whether a string array contains the given string.
612  * 
613  * @param array array to search.
614  * @param str string to look for
615  * @returns #TRUE if array contains string
616  */
617 dbus_bool_t
618 _dbus_string_array_contains (const char **array,
619                              const char  *str)
620 {
621   int i;
622
623   i = 0;
624   while (array[i] != NULL)
625     {
626       if (strcmp (array[i], str) == 0)
627         return TRUE;
628       ++i;
629     }
630
631   return FALSE;
632 }
633
634 /**
635  * Generates a new UUID. If you change how this is done,
636  * there's some text about it in the spec that should also change.
637  *
638  * @param uuid the uuid to initialize
639  */
640 void
641 _dbus_generate_uuid (DBusGUID *uuid)
642 {
643   long now;
644
645   /* don't use monotonic time because the UUID may be saved to disk, e.g.
646    * it may persist across reboots
647    */
648   _dbus_get_real_time (&now, NULL);
649
650   uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
651   
652   _dbus_generate_random_bytes_buffer (uuid->as_bytes, DBUS_UUID_LENGTH_BYTES - 4);
653 }
654
655 /**
656  * Hex-encode a UUID.
657  *
658  * @param uuid the uuid
659  * @param encoded string to append hex uuid to
660  * @returns #FALSE if no memory
661  */
662 dbus_bool_t
663 _dbus_uuid_encode (const DBusGUID *uuid,
664                    DBusString     *encoded)
665 {
666   DBusString binary;
667   _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
668   return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
669 }
670
671 static dbus_bool_t
672 _dbus_read_uuid_file_without_creating (const DBusString *filename,
673                                        DBusGUID         *uuid,
674                                        DBusError        *error)
675 {
676   DBusString contents;
677   DBusString decoded;
678   int end;
679   
680   if (!_dbus_string_init (&contents))
681     {
682       _DBUS_SET_OOM (error);
683       return FALSE;
684     }
685
686   if (!_dbus_string_init (&decoded))
687     {
688       _dbus_string_free (&contents);
689       _DBUS_SET_OOM (error);
690       return FALSE;
691     }
692   
693   if (!_dbus_file_get_contents (&contents, filename, error))
694     goto error;
695
696   _dbus_string_chop_white (&contents);
697
698   if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
699     {
700       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
701                       "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
702                       _dbus_string_get_const_data (filename),
703                       DBUS_UUID_LENGTH_HEX,
704                       _dbus_string_get_length (&contents));
705       goto error;
706     }
707
708   if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
709     {
710       _DBUS_SET_OOM (error);
711       goto error;
712     }
713
714   if (end == 0)
715     {
716       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
717                       "UUID file '%s' contains invalid hex data",
718                       _dbus_string_get_const_data (filename));
719       goto error;
720     }
721
722   if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
723     {
724       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
725                       "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
726                       _dbus_string_get_const_data (filename),
727                       _dbus_string_get_length (&decoded),
728                       DBUS_UUID_LENGTH_BYTES);
729       goto error;
730     }
731
732   _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
733
734   _dbus_string_free (&decoded);
735   _dbus_string_free (&contents);
736
737   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
738
739   return TRUE;
740   
741  error:
742   _DBUS_ASSERT_ERROR_IS_SET (error);
743   _dbus_string_free (&contents);
744   _dbus_string_free (&decoded);
745   return FALSE;
746 }
747
748 static dbus_bool_t
749 _dbus_create_uuid_file_exclusively (const DBusString *filename,
750                                     DBusGUID         *uuid,
751                                     DBusError        *error)
752 {
753   DBusString encoded;
754
755   if (!_dbus_string_init (&encoded))
756     {
757       _DBUS_SET_OOM (error);
758       return FALSE;
759     }
760
761   _dbus_generate_uuid (uuid);
762   
763   if (!_dbus_uuid_encode (uuid, &encoded))
764     {
765       _DBUS_SET_OOM (error);
766       goto error;
767     }
768   
769   if (!_dbus_string_append_byte (&encoded, '\n'))
770     {
771       _DBUS_SET_OOM (error);
772       goto error;
773     }
774   
775   if (!_dbus_string_save_to_file (&encoded, filename, TRUE, error))
776     goto error;
777
778   _dbus_string_free (&encoded);
779
780   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
781   return TRUE;
782   
783  error:
784   _DBUS_ASSERT_ERROR_IS_SET (error);
785   _dbus_string_free (&encoded);
786   return FALSE;        
787 }
788
789 /**
790  * Reads (and optionally writes) a uuid to a file. Initializes the uuid
791  * unless an error is returned.
792  *
793  * @param filename the name of the file
794  * @param uuid uuid to be initialized with the loaded uuid
795  * @param create_if_not_found #TRUE to create a new uuid and save it if the file doesn't exist
796  * @param error the error return
797  * @returns #FALSE if the error is set
798  */
799 dbus_bool_t
800 _dbus_read_uuid_file (const DBusString *filename,
801                       DBusGUID         *uuid,
802                       dbus_bool_t       create_if_not_found,
803                       DBusError        *error)
804 {
805   DBusError read_error = DBUS_ERROR_INIT;
806
807   if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
808     return TRUE;
809
810   if (!create_if_not_found)
811     {
812       dbus_move_error (&read_error, error);
813       return FALSE;
814     }
815
816   /* If the file exists and contains junk, we want to keep that error
817    * message instead of overwriting it with a "file exists" error
818    * message when we try to write
819    */
820   if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT))
821     {
822       dbus_move_error (&read_error, error);
823       return FALSE;
824     }
825   else
826     {
827       dbus_error_free (&read_error);
828       return _dbus_create_uuid_file_exclusively (filename, uuid, error);
829     }
830 }
831
832 /* Protected by _DBUS_LOCK (machine_uuid) */
833 static int machine_uuid_initialized_generation = 0;
834 static DBusGUID machine_uuid;
835
836 /**
837  * Gets the hex-encoded UUID of the machine this function is
838  * executed on. This UUID is guaranteed to be the same for a given
839  * machine at least until it next reboots, though it also
840  * makes some effort to be the same forever, it may change if the
841  * machine is reconfigured or its hardware is modified.
842  * 
843  * @param uuid_str string to append hex-encoded machine uuid to
844  * @returns #FALSE if no memory
845  */
846 dbus_bool_t
847 _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
848 {
849   dbus_bool_t ok;
850   
851   if (!_DBUS_LOCK (machine_uuid))
852     return FALSE;
853
854   if (machine_uuid_initialized_generation != _dbus_current_generation)
855     {
856       DBusError error = DBUS_ERROR_INIT;
857
858       if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
859                                           &error))
860         {          
861 #ifndef DBUS_ENABLE_EMBEDDED_TESTS
862           /* For the test suite, we may not be installed so just continue silently
863            * here. But in a production build, we want to be nice and loud about
864            * this.
865            */
866           _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n"
867                                    "See the manual page for dbus-uuidgen to correct this issue.\n",
868                                    error.message);
869 #endif
870           
871           dbus_error_free (&error);
872           
873           _dbus_generate_uuid (&machine_uuid);
874         }
875     }
876
877   ok = _dbus_uuid_encode (&machine_uuid, uuid_str);
878
879   _DBUS_UNLOCK (machine_uuid);
880
881   return ok;
882 }
883
884 #ifndef DBUS_DISABLE_CHECKS
885 /** String used in _dbus_return_if_fail macro */
886 const char *_dbus_return_if_fail_warning_format =
887 "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
888 "This is normally a bug in some application using the D-Bus library.\n";
889 #endif
890
891 #ifndef DBUS_DISABLE_ASSERT
892 /**
893  * Internals of _dbus_assert(); it's a function
894  * rather than a macro with the inline code so
895  * that the assertion failure blocks don't show up
896  * in test suite coverage, and to shrink code size.
897  *
898  * @param condition TRUE if assertion succeeded
899  * @param condition_text condition as a string
900  * @param file file the assertion is in
901  * @param line line the assertion is in
902  * @param func function the assertion is in
903  */
904 void
905 _dbus_real_assert (dbus_bool_t  condition,
906                    const char  *condition_text,
907                    const char  *file,
908                    int          line,
909                    const char  *func)
910 {
911   if (_DBUS_UNLIKELY (!condition))
912     {
913       _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
914                   _dbus_pid_for_log (), condition_text, file, line, func);
915       _dbus_abort ();
916     }
917 }
918
919 /**
920  * Internals of _dbus_assert_not_reached(); it's a function
921  * rather than a macro with the inline code so
922  * that the assertion failure blocks don't show up
923  * in test suite coverage, and to shrink code size.
924  *
925  * @param explanation what was reached that shouldn't have been
926  * @param file file the assertion is in
927  * @param line line the assertion is in
928  */
929 void
930 _dbus_real_assert_not_reached (const char *explanation,
931                                const char *file,
932                                int         line)
933 {
934   _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
935               file, line, _dbus_pid_for_log (), explanation);
936   _dbus_abort ();
937 }
938 #endif /* DBUS_DISABLE_ASSERT */
939   
940 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
941 static dbus_bool_t
942 run_failing_each_malloc (int                    n_mallocs,
943                          const char            *description,
944                          DBusTestMemoryFunction func,
945                          void                  *data)
946 {
947   n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
948   
949   while (n_mallocs >= 0)
950     {      
951       _dbus_set_fail_alloc_counter (n_mallocs);
952
953       _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
954                      description, n_mallocs,
955                      _dbus_get_fail_alloc_failures ());
956
957       if (!(* func) (data))
958         return FALSE;
959       
960       n_mallocs -= 1;
961     }
962
963   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
964
965   return TRUE;
966 }                        
967
968 /**
969  * Tests how well the given function responds to out-of-memory
970  * situations. Calls the function repeatedly, failing a different
971  * call to malloc() each time. If the function ever returns #FALSE,
972  * the test fails. The function should return #TRUE whenever something
973  * valid (such as returning an error, or succeeding) occurs, and #FALSE
974  * if it gets confused in some way.
975  *
976  * @param description description of the test used in verbose output
977  * @param func function to call
978  * @param data data to pass to function
979  * @returns #TRUE if the function never returns FALSE
980  */
981 dbus_bool_t
982 _dbus_test_oom_handling (const char             *description,
983                          DBusTestMemoryFunction  func,
984                          void                   *data)
985 {
986   int approx_mallocs;
987   const char *setting;
988   int max_failures_to_try;
989   int i;
990
991   /* Run once to see about how many mallocs are involved */
992   
993   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
994
995   _dbus_verbose ("Running once to count mallocs\n");
996   
997   if (!(* func) (data))
998     return FALSE;
999   
1000   approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
1001
1002   _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
1003                  description, approx_mallocs);
1004
1005   setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
1006   if (setting != NULL)
1007     {
1008       DBusString str;
1009       long v;
1010       _dbus_string_init_const (&str, setting);
1011       v = 4;
1012       if (!_dbus_string_parse_int (&str, 0, &v, NULL))
1013         _dbus_warn ("couldn't parse '%s' as integer\n", setting);
1014       max_failures_to_try = v;
1015     }
1016   else
1017     {
1018       max_failures_to_try = 4;
1019     }
1020
1021   i = setting ? max_failures_to_try - 1 : 1;
1022   while (i < max_failures_to_try)
1023     {
1024       _dbus_set_fail_alloc_failures (i);
1025       if (!run_failing_each_malloc (approx_mallocs, description, func, data))
1026         return FALSE;
1027       ++i;
1028     }
1029   
1030   _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
1031                  description);
1032
1033   return TRUE;
1034 }
1035 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
1036
1037 /** @} */