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