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