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