Merge branch 'dbus-1.6'
[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   static int prefix = -1;
336
337   if (prefix == -1) 
338     {
339       char *p = (char *)file + strlen(file);
340       int i = 0;
341       prefix = 0;
342       for (;p >= file;p--)
343         {
344           if (DBUS_IS_DIR_SEPARATOR(*p))
345             {
346               if (++i >= level) 
347                 {
348                   prefix = p-file+1;
349                   break;
350                 }
351            }
352         }
353     }
354   return (char *)file+prefix;
355 }
356
357 /**
358  * Implementation of dbus_is_verbose() macro if built with verbose logging
359  * enabled.
360  * @returns whether verbose logging is active.
361  */
362 dbus_bool_t
363 _dbus_is_verbose_real (void)
364 {
365   _dbus_verbose_init ();
366   return verbose;
367 }
368
369 /**
370  * Prints a warning message to stderr
371  * if the user has enabled verbose mode.
372  * This is the real function implementation,
373  * use _dbus_verbose() macro in code.
374  *
375  * @param format printf-style format string.
376  */
377 void
378 _dbus_verbose_real (
379 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
380                     const char *file,
381                     const int line, 
382                     const char *function, 
383 #endif
384                     const char *format,
385                     ...)
386 {
387   va_list args;
388   static dbus_bool_t need_pid = TRUE;
389   int len;
390   
391   /* things are written a bit oddly here so that
392    * in the non-verbose case we just have the one
393    * conditional and return immediately.
394    */
395   if (!_dbus_is_verbose_real())
396     return;
397
398 #ifndef DBUS_USE_OUTPUT_DEBUG_STRING
399   /* Print out pid before the line */
400   if (need_pid)
401     {
402 #if PTHREAD_IN_VERBOSE
403       fprintf (stderr, "%lu: 0x%lx: ", _dbus_pid_for_log (), pthread_self ());
404 #else
405       fprintf (stderr, "%lu: ", _dbus_pid_for_log ());
406 #endif
407     }
408 #endif
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)",
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)",
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  * Generates a new UUID. If you change how this is done,
639  * there's some text about it in the spec that should also change.
640  *
641  * @param uuid the uuid to initialize
642  */
643 void
644 _dbus_generate_uuid (DBusGUID *uuid)
645 {
646   long now;
647
648   /* don't use monotonic time because the UUID may be saved to disk, e.g.
649    * it may persist across reboots
650    */
651   _dbus_get_real_time (&now, NULL);
652
653   uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
654   
655   _dbus_generate_random_bytes_buffer (uuid->as_bytes, DBUS_UUID_LENGTH_BYTES - 4);
656 }
657
658 /**
659  * Hex-encode a UUID.
660  *
661  * @param uuid the uuid
662  * @param encoded string to append hex uuid to
663  * @returns #FALSE if no memory
664  */
665 dbus_bool_t
666 _dbus_uuid_encode (const DBusGUID *uuid,
667                    DBusString     *encoded)
668 {
669   DBusString binary;
670   _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
671   return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
672 }
673
674 static dbus_bool_t
675 _dbus_read_uuid_file_without_creating (const DBusString *filename,
676                                        DBusGUID         *uuid,
677                                        DBusError        *error)
678 {
679   DBusString contents;
680   DBusString decoded;
681   int end;
682   
683   if (!_dbus_string_init (&contents))
684     {
685       _DBUS_SET_OOM (error);
686       return FALSE;
687     }
688
689   if (!_dbus_string_init (&decoded))
690     {
691       _dbus_string_free (&contents);
692       _DBUS_SET_OOM (error);
693       return FALSE;
694     }
695   
696   if (!_dbus_file_get_contents (&contents, filename, error))
697     goto error;
698
699   _dbus_string_chop_white (&contents);
700
701   if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
702     {
703       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
704                       "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
705                       _dbus_string_get_const_data (filename),
706                       DBUS_UUID_LENGTH_HEX,
707                       _dbus_string_get_length (&contents));
708       goto error;
709     }
710
711   if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
712     {
713       _DBUS_SET_OOM (error);
714       goto error;
715     }
716
717   if (end == 0)
718     {
719       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
720                       "UUID file '%s' contains invalid hex data",
721                       _dbus_string_get_const_data (filename));
722       goto error;
723     }
724
725   if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
726     {
727       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
728                       "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
729                       _dbus_string_get_const_data (filename),
730                       _dbus_string_get_length (&decoded),
731                       DBUS_UUID_LENGTH_BYTES);
732       goto error;
733     }
734
735   _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
736
737   _dbus_string_free (&decoded);
738   _dbus_string_free (&contents);
739
740   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
741
742   return TRUE;
743   
744  error:
745   _DBUS_ASSERT_ERROR_IS_SET (error);
746   _dbus_string_free (&contents);
747   _dbus_string_free (&decoded);
748   return FALSE;
749 }
750
751 static dbus_bool_t
752 _dbus_create_uuid_file_exclusively (const DBusString *filename,
753                                     DBusGUID         *uuid,
754                                     DBusError        *error)
755 {
756   DBusString encoded;
757
758   if (!_dbus_string_init (&encoded))
759     {
760       _DBUS_SET_OOM (error);
761       return FALSE;
762     }
763
764   _dbus_generate_uuid (uuid);
765   
766   if (!_dbus_uuid_encode (uuid, &encoded))
767     {
768       _DBUS_SET_OOM (error);
769       goto error;
770     }
771   
772   if (!_dbus_string_append_byte (&encoded, '\n'))
773     {
774       _DBUS_SET_OOM (error);
775       goto error;
776     }
777   
778   if (!_dbus_string_save_to_file (&encoded, filename, TRUE, error))
779     goto error;
780
781   _dbus_string_free (&encoded);
782
783   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
784   return TRUE;
785   
786  error:
787   _DBUS_ASSERT_ERROR_IS_SET (error);
788   _dbus_string_free (&encoded);
789   return FALSE;        
790 }
791
792 /**
793  * Reads (and optionally writes) a uuid to a file. Initializes the uuid
794  * unless an error is returned.
795  *
796  * @param filename the name of the file
797  * @param uuid uuid to be initialized with the loaded uuid
798  * @param create_if_not_found #TRUE to create a new uuid and save it if the file doesn't exist
799  * @param error the error return
800  * @returns #FALSE if the error is set
801  */
802 dbus_bool_t
803 _dbus_read_uuid_file (const DBusString *filename,
804                       DBusGUID         *uuid,
805                       dbus_bool_t       create_if_not_found,
806                       DBusError        *error)
807 {
808   DBusError read_error = DBUS_ERROR_INIT;
809
810   if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
811     return TRUE;
812
813   if (!create_if_not_found)
814     {
815       dbus_move_error (&read_error, error);
816       return FALSE;
817     }
818
819   /* If the file exists and contains junk, we want to keep that error
820    * message instead of overwriting it with a "file exists" error
821    * message when we try to write
822    */
823   if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT))
824     {
825       dbus_move_error (&read_error, error);
826       return FALSE;
827     }
828   else
829     {
830       dbus_error_free (&read_error);
831       return _dbus_create_uuid_file_exclusively (filename, uuid, error);
832     }
833 }
834
835 /* Protected by _DBUS_LOCK (machine_uuid) */
836 static int machine_uuid_initialized_generation = 0;
837 static DBusGUID machine_uuid;
838
839 /**
840  * Gets the hex-encoded UUID of the machine this function is
841  * executed on. This UUID is guaranteed to be the same for a given
842  * machine at least until it next reboots, though it also
843  * makes some effort to be the same forever, it may change if the
844  * machine is reconfigured or its hardware is modified.
845  * 
846  * @param uuid_str string to append hex-encoded machine uuid to
847  * @returns #FALSE if no memory
848  */
849 dbus_bool_t
850 _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
851 {
852   dbus_bool_t ok;
853   
854   if (!_DBUS_LOCK (machine_uuid))
855     return FALSE;
856
857   if (machine_uuid_initialized_generation != _dbus_current_generation)
858     {
859       DBusError error = DBUS_ERROR_INIT;
860
861       if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
862                                           &error))
863         {          
864 #ifndef DBUS_ENABLE_EMBEDDED_TESTS
865           /* For the test suite, we may not be installed so just continue silently
866            * here. But in a production build, we want to be nice and loud about
867            * this.
868            */
869           _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n"
870                                    "See the manual page for dbus-uuidgen to correct this issue.\n",
871                                    error.message);
872 #endif
873           
874           dbus_error_free (&error);
875           
876           _dbus_generate_uuid (&machine_uuid);
877         }
878     }
879
880   ok = _dbus_uuid_encode (&machine_uuid, uuid_str);
881
882   _DBUS_UNLOCK (machine_uuid);
883
884   return ok;
885 }
886
887 #ifndef DBUS_DISABLE_CHECKS
888 /** String used in _dbus_return_if_fail macro */
889 const char *_dbus_return_if_fail_warning_format =
890 "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
891 "This is normally a bug in some application using the D-Bus library.\n";
892 #endif
893
894 #ifndef DBUS_DISABLE_ASSERT
895 /**
896  * Internals of _dbus_assert(); it's a function
897  * rather than a macro with the inline code so
898  * that the assertion failure blocks don't show up
899  * in test suite coverage, and to shrink code size.
900  *
901  * @param condition TRUE if assertion succeeded
902  * @param condition_text condition as a string
903  * @param file file the assertion is in
904  * @param line line the assertion is in
905  * @param func function the assertion is in
906  */
907 void
908 _dbus_real_assert (dbus_bool_t  condition,
909                    const char  *condition_text,
910                    const char  *file,
911                    int          line,
912                    const char  *func)
913 {
914   if (_DBUS_UNLIKELY (!condition))
915     {
916       _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
917                   _dbus_pid_for_log (), condition_text, file, line, func);
918       _dbus_abort ();
919     }
920 }
921
922 /**
923  * Internals of _dbus_assert_not_reached(); it's a function
924  * rather than a macro with the inline code so
925  * that the assertion failure blocks don't show up
926  * in test suite coverage, and to shrink code size.
927  *
928  * @param explanation what was reached that shouldn't have been
929  * @param file file the assertion is in
930  * @param line line the assertion is in
931  */
932 void
933 _dbus_real_assert_not_reached (const char *explanation,
934                                const char *file,
935                                int         line)
936 {
937   _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
938               file, line, _dbus_pid_for_log (), explanation);
939   _dbus_abort ();
940 }
941 #endif /* DBUS_DISABLE_ASSERT */
942   
943 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
944 static dbus_bool_t
945 run_failing_each_malloc (int                    n_mallocs,
946                          const char            *description,
947                          DBusTestMemoryFunction func,
948                          void                  *data)
949 {
950   n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
951   
952   while (n_mallocs >= 0)
953     {      
954       _dbus_set_fail_alloc_counter (n_mallocs);
955
956       _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
957                      description, n_mallocs,
958                      _dbus_get_fail_alloc_failures ());
959
960       if (!(* func) (data))
961         return FALSE;
962       
963       n_mallocs -= 1;
964     }
965
966   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
967
968   return TRUE;
969 }                        
970
971 /**
972  * Tests how well the given function responds to out-of-memory
973  * situations. Calls the function repeatedly, failing a different
974  * call to malloc() each time. If the function ever returns #FALSE,
975  * the test fails. The function should return #TRUE whenever something
976  * valid (such as returning an error, or succeeding) occurs, and #FALSE
977  * if it gets confused in some way.
978  *
979  * @param description description of the test used in verbose output
980  * @param func function to call
981  * @param data data to pass to function
982  * @returns #TRUE if the function never returns FALSE
983  */
984 dbus_bool_t
985 _dbus_test_oom_handling (const char             *description,
986                          DBusTestMemoryFunction  func,
987                          void                   *data)
988 {
989   int approx_mallocs;
990   const char *setting;
991   int max_failures_to_try;
992   int i;
993
994   /* Run once to see about how many mallocs are involved */
995   
996   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
997
998   _dbus_verbose ("Running once to count mallocs\n");
999   
1000   if (!(* func) (data))
1001     return FALSE;
1002   
1003   approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
1004
1005   _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
1006                  description, approx_mallocs);
1007
1008   setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
1009   if (setting != NULL)
1010     {
1011       DBusString str;
1012       long v;
1013       _dbus_string_init_const (&str, setting);
1014       v = 4;
1015       if (!_dbus_string_parse_int (&str, 0, &v, NULL))
1016         _dbus_warn ("couldn't parse '%s' as integer\n", setting);
1017       max_failures_to_try = v;
1018     }
1019   else
1020     {
1021       max_failures_to_try = 4;
1022     }
1023
1024   i = setting ? max_failures_to_try - 1 : 1;
1025   while (i < max_failures_to_try)
1026     {
1027       _dbus_set_fail_alloc_failures (i);
1028       if (!run_failing_each_malloc (approx_mallocs, description, func, data))
1029         return FALSE;
1030       ++i;
1031     }
1032   
1033   _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
1034                  description);
1035
1036   return TRUE;
1037 }
1038 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */
1039
1040 /** @} */