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