(linenum→info "unix/slp.c:2238")

dbus/1.0.2/dbus/dbus-internals.c

    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: /**
   33:  * @defgroup DBusInternals D-Bus secret internal implementation details
   34:  * @brief Documentation useful when developing or debugging D-Bus itself.
   35:  * 
   36:  */
   37: 
   38: /**
   39:  * @defgroup DBusInternalsUtils Utilities and portability
   40:  * @ingroup DBusInternals
   41:  * @brief Utility functions (_dbus_assert(), _dbus_warn(), etc.)
   42:  * @{
   43:  */
   44: 
   45: /**
   46:  * @def _dbus_assert
   47:  *
   48:  * Aborts with an error message if the condition is false.
   49:  * 
   50:  * @param condition condition which must be true.
   51:  */
   52: 
   53: /**
   54:  * @def _dbus_assert_not_reached
   55:  *
   56:  * Aborts with an error message if called.
   57:  * The given explanation will be printed.
   58:  * 
   59:  * @param explanation explanation of what happened if the code was reached.
   60:  */
   61: 
   62: /**
   63:  * @def _DBUS_N_ELEMENTS
   64:  *
   65:  * Computes the number of elements in a fixed-size array using
   66:  * sizeof().
   67:  *
   68:  * @param array the array to count elements in.
   69:  */
   70: 
   71: /**
   72:  * @def _DBUS_POINTER_TO_INT
   73:  *
   74:  * Safely casts a void* to an integer; should only be used on void*
   75:  * that actually contain integers, for example one created with
   76:  * _DBUS_INT_TO_POINTER.  Only guaranteed to preserve 32 bits.
   77:  * (i.e. it's used to store 32-bit ints in pointers, but
   78:  * can't be used to store 64-bit pointers in ints.)
   79:  *
   80:  * @param pointer pointer to extract an integer from.
   81:  */
   82: /**
   83:  * @def _DBUS_INT_TO_POINTER
   84:  *
   85:  * Safely stuffs an integer into a pointer, to be extracted later with
   86:  * _DBUS_POINTER_TO_INT. Only guaranteed to preserve 32 bits.
   87:  *
   88:  * @param integer the integer to stuff into a pointer.
   89:  */
   90: /**
   91:  * @def _DBUS_ZERO
   92:  *
   93:  * Sets all bits in an object to zero.
   94:  *
   95:  * @param object the object to be zeroed.
   96:  */
   97: /**
   98:  * @def _DBUS_INT16_MIN
   99:  *
  100:  * Minimum value of type "int16"
  101:  */
  102: /**
  103:  * @def _DBUS_INT16_MAX
  104:  *
  105:  * Maximum value of type "int16"
  106:  */
  107: /**
  108:  * @def _DBUS_UINT16_MAX
  109:  *
  110:  * Maximum value of type "uint16"
  111:  */
  112: 
  113: /**
  114:  * @def _DBUS_INT32_MIN
  115:  *
  116:  * Minimum value of type "int32"
  117:  */
  118: /**
  119:  * @def _DBUS_INT32_MAX
  120:  *
  121:  * Maximum value of type "int32"
  122:  */
  123: /**
  124:  * @def _DBUS_UINT32_MAX
  125:  *
  126:  * Maximum value of type "uint32"
  127:  */
  128: 
  129: /**
  130:  * @def _DBUS_INT_MIN
  131:  *
  132:  * Minimum value of type "int"
  133:  */
  134: /**
  135:  * @def _DBUS_INT_MAX
  136:  *
  137:  * Maximum value of type "int"
  138:  */
  139: /**
  140:  * @def _DBUS_UINT_MAX
  141:  *
  142:  * Maximum value of type "uint"
  143:  */
  144: 
  145: /**
  146:  * @typedef DBusForeachFunction
  147:  * 
  148:  * Used to iterate over each item in a collection, such as
  149:  * a DBusList.
  150:  */
  151: 
  152: /**
  153:  * @def _DBUS_LOCK_NAME
  154:  *
  155:  * Expands to name of a global lock variable.
  156:  */
  157: 
  158: /**
  159:  * @def _DBUS_DEFINE_GLOBAL_LOCK
  160:  *
  161:  * Defines a global lock variable with the given name.
  162:  * The lock must be added to the list to initialize
  163:  * in dbus_threads_init().
  164:  */
  165: 
  166: /**
  167:  * @def _DBUS_DECLARE_GLOBAL_LOCK
  168:  *
  169:  * Expands to declaration of a global lock defined
  170:  * with _DBUS_DEFINE_GLOBAL_LOCK.
  171:  * The lock must be added to the list to initialize
  172:  * in dbus_threads_init().
  173:  */
  174: 
  175: /**
  176:  * @def _DBUS_LOCK
  177:  *
  178:  * Locks a global lock
  179:  */
  180: 
  181: /**
  182:  * @def _DBUS_UNLOCK
  183:  *
  184:  * Unlocks a global lock
  185:  */
  186: 
  187: /**
  188:  * Fixed "out of memory" error message, just to avoid
  189:  * making up a different string every time and wasting
  190:  * space.
  191:  */
  192: const char _dbus_no_memory_message[] = "Not enough memory";
  193: 
  194: static dbus_bool_t warn_initted = FALSE;
  195: static dbus_bool_t fatal_warnings = FALSE;
  196: static dbus_bool_t fatal_warnings_on_check_failed = TRUE;
  197: 
  198: static void
  199: init_warnings(void)
  200: {
  201:   if (!warn_initted)
  202:     {
  203:       const char *s;
  204:       s = _dbus_getenv ("DBUS_FATAL_WARNINGS");
  205:       if (s && *s)
  206:         {
  207:           if (*s == '0')
  208:             {
  209:               fatal_warnings = FALSE;
  210:               fatal_warnings_on_check_failed = FALSE;
  211:             }
  212:           else if (*s == '1')
  213:             {
  214:               fatal_warnings = TRUE;
  215:               fatal_warnings_on_check_failed = TRUE;
  216:             }
  217:           else
  218:             {
  219:               fprintf(stderr, "DBUS_FATAL_WARNINGS should be set to 0 or 1 if set, not '%s'",
  220:                       s);
  221:             }
  222:         }
  223: 
  224:       warn_initted = TRUE;
  225:     }
  226: }
  227: 
  228: /**
  229:  * Prints a warning message to stderr. Can optionally be made to exit
  230:  * fatally by setting DBUS_FATAL_WARNINGS, but this is rarely
  231:  * used. This function should be considered pretty much equivalent to
  232:  * fprintf(stderr). _dbus_warn_check_failed() on the other hand is
  233:  * suitable for use when a programming mistake has been made.
  234:  *
  235:  * @param format printf-style format string.
  236:  */
  237: void
  238: _dbus_warn (const char *format,
  239:             ...)
  240: {
  241:   va_list args;
  242: 
  243:   if (!warn_initted)
  244:     init_warnings ();
  245:   
  246:   va_start (args, format);
  247:   vfprintf (stderr, format, args);
  248:   va_end (args);
  249: 
  250:   if (fatal_warnings)
  251:     {
  252:       fflush (stderr);
  253:       _dbus_abort ();
  254:     }
  255: }
  256: 
  257: /**
  258:  * Prints a "critical" warning to stderr when an assertion fails;
  259:  * differs from _dbus_warn primarily in that it prefixes the pid and
  260:  * defaults to fatal. This should be used only when a programming
  261:  * error has been detected. (NOT for unavoidable errors that an app
  262:  * might handle - those should be returned as DBusError.) Calling this
  263:  * means "there is a bug"
  264:  */
  265: void
  266: _dbus_warn_check_failed(const char *format,
  267:                         ...)
  268: {
  269:   va_list args;
  270:   
  271:   if (!warn_initted)
  272:     init_warnings ();
  273: 
  274:   fprintf (stderr, "process %lu: ", _dbus_getpid ());
  275:   
  276:   va_start (args, format);
  277:   vfprintf (stderr, format, args);
  278:   va_end (args);
  279: 
  280:   if (fatal_warnings_on_check_failed)
  281:     {
  282:       fflush (stderr);
  283:       _dbus_abort ();
  284:     }
  285: }
  286: 
  287: #ifdef DBUS_ENABLE_VERBOSE_MODE
  288: 
  289: static dbus_bool_t verbose_initted = FALSE;
  290: static dbus_bool_t verbose = TRUE;
  291: 
  292: /** Whether to show the current thread in verbose messages */
  293: #define PTHREAD_IN_VERBOSE 0
  294: #if PTHREAD_IN_VERBOSE
  295: #include <pthread.h>
  296: #endif
  297: 
  298: static inline void
  299: _dbus_verbose_init (void)
  300: {
  301:   if (!verbose_initted)
  302:     {
  303:       const char *p = _dbus_getenv ("DBUS_VERBOSE"); 
  304:       verbose = p != NULL && *p == '1';
  305:       verbose_initted = TRUE;
  306:     }
  307: }
  308: 
  309: /**
  310:  * Implementation of dbus_is_verbose() macro if built with verbose logging
  311:  * enabled.
  312:  * @returns whether verbose logging is active.
  313:  */
  314: dbus_bool_t
  315: _dbus_is_verbose_real (void)
  316: {
  317:   _dbus_verbose_init ();
  318:   return verbose;
  319: }
  320: 
  321: /**
  322:  * Prints a warning message to stderr
  323:  * if the user has enabled verbose mode.
  324:  * This is the real function implementation,
  325:  * use _dbus_verbose() macro in code.
  326:  *
  327:  * @param format printf-style format string.
  328:  */
  329: void
  330: _dbus_verbose_real (const char *format,
  331:                     ...)
  332: {
  333:   va_list args;
  334:   static dbus_bool_t need_pid = TRUE;
  335:   int len;
  336:   
  337:   /* things are written a bit oddly here so that
  338:    * in the non-verbose case we just have the one
  339:    * conditional and return immediately.
  340:    */
  341:   if (!_dbus_is_verbose_real())
  342:     return;
  343: 
  344:   /* Print out pid before the line */
  345:   if (need_pid)
  346:     {
  347: #if PTHREAD_IN_VERBOSE
  348:       fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
  349: #else
  350:       fprintf (stderr, "%lu: ", _dbus_getpid ());
  351: #endif
  352:     }
  353:       
  354: 
  355:   /* Only print pid again if the next line is a new line */
  356:   len = strlen (format);
  357:   if (format[len-1] == '\n')
  358:     need_pid = TRUE;
  359:   else
  360:     need_pid = FALSE;
  361:   
  362:   va_start (args, format);
  363:   vfprintf (stderr, format, args);
  364:   va_end (args);
  365: 
  366:   fflush (stderr);
  367: }
  368: 
  369: /**
  370:  * Reinitializes the verbose logging code, used
  371:  * as a hack in dbus-spawn.c so that a child
  372:  * process re-reads its pid
  373:  *
  374:  */
  375: void
  376: _dbus_verbose_reset_real (void)
  377: {
  378:   verbose_initted = FALSE;
  379: }
  380: 
  381: #endif /* DBUS_ENABLE_VERBOSE_MODE */
  382: 
  383: /**
  384:  * Duplicates a string. Result must be freed with
  385:  * dbus_free(). Returns #NULL if memory allocation fails.
  386:  * If the string to be duplicated is #NULL, returns #NULL.
  387:  * 
  388:  * @param str string to duplicate.
  389:  * @returns newly-allocated copy.
  390:  */
  391: char*
  392: _dbus_strdup (const char *str)
  393: {
  394:   size_t len;
  395:   char *copy;
  396:   
  397:   if (str == NULL)
  398:     return NULL;
  399:   
  400:   len = strlen (str);
  401: 
  402:   copy = dbus_malloc (len + 1);
  403:   if (copy == NULL)
  404:     return NULL;
  405: 
  406:   memcpy (copy, str, len + 1);
  407:   
  408:   return copy;
  409: }
  410: 
  411: /**
  412:  * Duplicates a block of memory. Returns
  413:  * #NULL on failure.
  414:  *
  415:  * @param mem memory to copy
  416:  * @param n_bytes number of bytes to copy
  417:  * @returns the copy
  418:  */
  419: void*
  420: _dbus_memdup (const void  *mem,
  421:               size_t       n_bytes)
  422: {
  423:   void *copy;
  424: 
  425:   copy = dbus_malloc (n_bytes);
  426:   if (copy == NULL)
  427:     return NULL;
  428: 
  429:   memcpy (copy, mem, n_bytes);
  430:   
  431:   return copy;
  432: }
  433: 
  434: /**
  435:  * Duplicates a string array. Result may be freed with
  436:  * dbus_free_string_array(). Returns #NULL if memory allocation fails.
  437:  * If the array to be duplicated is #NULL, returns #NULL.
  438:  * 
  439:  * @param array array to duplicate.
  440:  * @returns newly-allocated copy.
  441:  */
  442: char**
  443: _dbus_dup_string_array (const char **array)
  444: {
  445:   int len;
  446:   int i;
  447:   char **copy;
  448:   
  449:   if (array == NULL)
  450:     return NULL;
  451: 
  452:   for (len = 0; array[len] != NULL; ++len)
  453:     ;
  454: 
  455:   copy = dbus_new0 (char*, len + 1);
  456:   if (copy == NULL)
  457:     return NULL;
  458: 
  459:   i = 0;
  460:   while (i < len)
  461:     {
  462:       copy[i] = _dbus_strdup (array[i]);
  463:       if (copy[i] == NULL)
  464:         {
  465:           dbus_free_string_array (copy);
  466:           return NULL;
  467:         }
  468: 
  469:       ++i;
  470:     }
  471: 
  472:   return copy;
  473: }
  474: 
  475: /**
  476:  * Checks whether a string array contains the given string.
  477:  * 
  478:  * @param array array to search.
  479:  * @param str string to look for
  480:  * @returns #TRUE if array contains string
  481:  */
  482: dbus_bool_t
  483: _dbus_string_array_contains (const char **array,
  484:                              const char  *str)
  485: {
  486:   int i;
  487: 
  488:   i = 0;
  489:   while (array[i] != NULL)
  490:     {
  491:       if (strcmp (array[i], str) == 0)
  492:         return TRUE;
  493:       ++i;
  494:     }
  495: 
  496:   return FALSE;
  497: }
  498: 
  499: /**
  500:  * Generates a new UUID. If you change how this is done,
  501:  * there's some text about it in the spec that should also change.
  502:  *
  503:  * @param uuid the uuid to initialize
  504:  */
  505: void
  506: _dbus_generate_uuid (DBusGUID *uuid)
  507: {
  508:   long now;
  509: 
  510:   _dbus_get_current_time (&now, NULL);
  511: 
  512:   uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
  513:   
  514:   _dbus_generate_random_bytes_buffer (uuid->as_bytes, DBUS_UUID_LENGTH_BYTES - 4);
  515: }
  516: 
  517: /**
  518:  * Hex-encode a UUID.
  519:  *
  520:  * @param uuid the uuid
  521:  * @param encoded string to append hex uuid to
  522:  * @returns #FALSE if no memory
  523:  */
  524: dbus_bool_t
  525: _dbus_uuid_encode (const DBusGUID *uuid,
  526:                    DBusString     *encoded)
  527: {
  528:   DBusString binary;
  529:   _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
  530:   return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
  531: }
  532: 
  533: static dbus_bool_t
  534: _dbus_read_uuid_file_without_creating (const DBusString *filename,
  535:                                        DBusGUID         *uuid,
  536:                                        DBusError        *error)
  537: {
  538:   DBusString contents;
  539:   DBusString decoded;
  540:   int end;
  541:   
  542:   _dbus_string_init (&contents);
  543:   _dbus_string_init (&decoded);
  544:   
  545:   if (!_dbus_file_get_contents (&contents, filename, error))
  546:     goto error;
  547: 
  548:   _dbus_string_chop_white (&contents);
  549: 
  550:   if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
  551:     {
  552:       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
  553:                       "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
  554:                       _dbus_string_get_const_data (filename),
  555:                       DBUS_UUID_LENGTH_HEX,
  556:                       _dbus_string_get_length (&contents));
  557:       goto error;
  558:     }
  559: 
  560:   if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
  561:     {
  562:       _DBUS_SET_OOM (error);
  563:       goto error;
  564:     }
  565: 
  566:   if (end == 0)
  567:     {
  568:       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
  569:                       "UUID file '%s' contains invalid hex data",
  570:                       _dbus_string_get_const_data (filename));
  571:       goto error;
  572:     }
  573: 
  574:   if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
  575:     {
  576:       dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
  577:                       "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
  578:                       _dbus_string_get_const_data (filename),
  579:                       _dbus_string_get_length (&decoded),
  580:                       DBUS_UUID_LENGTH_BYTES);
  581:       goto error;
  582:     }
  583: 
  584:   _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
  585: 
  586:   _dbus_string_free (&decoded);
  587:   _dbus_string_free (&contents);
  588: 
  589:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  590: 
  591:   return TRUE;
  592:   
  593:  error:
  594:   _DBUS_ASSERT_ERROR_IS_SET (error);
  595:   _dbus_string_free (&contents);
  596:   _dbus_string_free (&decoded);
  597:   return FALSE;
  598: }
  599: 
  600: static dbus_bool_t
  601: _dbus_create_uuid_file_exclusively (const DBusString *filename,
  602:                                     DBusGUID         *uuid,
  603:                                     DBusError        *error)
  604: {
  605:   DBusString encoded;
  606: 
  607:   _dbus_string_init (&encoded);
  608: 
  609:   _dbus_generate_uuid (uuid);
  610:   
  611:   if (!_dbus_uuid_encode (uuid, &encoded))
  612:     {
  613:       _DBUS_SET_OOM (error);
  614:       goto error;
  615:     }
  616:   
  617:   /* FIXME this is racy; we need a save_file_exclusively
  618:    * function. But in practice this should be fine for now.
  619:    *
  620:    * - first be sure we can create the file and it
  621:    *   doesn't exist by creating it empty with O_EXCL
  622:    * - then create it by creating a temporary file and
  623:    *   overwriting atomically with rename()
  624:    */
  625:   if (!_dbus_create_file_exclusively (filename, error))
  626:     goto error;
  627: 
  628:   if (!_dbus_string_append_byte (&encoded, '\n'))
  629:     {
  630:       _DBUS_SET_OOM (error);
  631:       goto error;
  632:     }
  633:   
  634:   if (!_dbus_string_save_to_file (&encoded, filename, error))
  635:     goto error;
  636: 
  637:   if (!_dbus_make_file_world_readable (filename, error))
  638:     goto error;
  639: 
  640:   _dbus_string_free (&encoded);
  641: 
  642:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  643:   return TRUE;
  644:   
  645:  error:
  646:   _DBUS_ASSERT_ERROR_IS_SET (error);
  647:   _dbus_string_free (&encoded);
  648:   return FALSE;        
  649: }
  650: 
  651: /**
  652:  * Reads (and optionally writes) a uuid to a file. Initializes the uuid
  653:  * unless an error is returned.
  654:  *
  655:  * @param filename the name of the file