Main Page   Modules   Data Structures   File List   Data Fields   Related Pages  

dbus-internals.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-internals.c  random utility stuff (internal to D-BUS implementation)
00003  *
00004  * Copyright (C) 2002, 2003  Red Hat, Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.0
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 #include "dbus-internals.h"
00024 #include "dbus-protocol.h"
00025 #include "dbus-test.h"
00026 #include <stdio.h>
00027 #include <stdarg.h>
00028 #include <string.h>
00029 #include <sys/types.h>
00030 #include <errno.h>
00031 #include <unistd.h>
00032 #include <fcntl.h>
00033 #include <stdlib.h>
00034 
00158 const char _dbus_no_memory_message[] = "Not enough memory";
00159 
00165 void
00166 _dbus_warn (const char *format,
00167             ...)
00168 {
00169   /* FIXME not portable enough? */
00170   va_list args;
00171 
00172   va_start (args, format);
00173   vfprintf (stderr, format, args);
00174   va_end (args);
00175 }
00176 
00177 static dbus_bool_t verbose_initted = FALSE;
00178 
00187 void
00188 _dbus_verbose_real (const char *format,
00189                     ...)
00190 {
00191   va_list args;
00192   static dbus_bool_t verbose = TRUE;
00193   static dbus_bool_t need_pid = TRUE;
00194   
00195   /* things are written a bit oddly here so that
00196    * in the non-verbose case we just have the one
00197    * conditional and return immediately.
00198    */
00199   if (!verbose)
00200     return;
00201   
00202   if (!verbose_initted)
00203     {
00204       verbose = _dbus_getenv ("DBUS_VERBOSE") != NULL;
00205       verbose_initted = TRUE;
00206       if (!verbose)
00207         return;
00208     }
00209 
00210   if (need_pid)
00211     {
00212       int len;
00213       
00214       fprintf (stderr, "%lu: ", _dbus_getpid ());
00215 
00216       len = strlen (format);
00217       if (format[len-1] == '\n')
00218         need_pid = TRUE;
00219       else
00220         need_pid = FALSE;
00221     }
00222   
00223   va_start (args, format);
00224   vfprintf (stderr, format, args);
00225   va_end (args);
00226 
00227   fflush (stderr);
00228 }
00229 
00236 void
00237 _dbus_verbose_reset_real (void)
00238 {
00239   verbose_initted = FALSE;
00240 }
00241 
00250 char*
00251 _dbus_strdup (const char *str)
00252 {
00253   size_t len;
00254   char *copy;
00255   
00256   if (str == NULL)
00257     return NULL;
00258   
00259   len = strlen (str);
00260 
00261   copy = dbus_malloc (len + 1);
00262   if (copy == NULL)
00263     return NULL;
00264 
00265   memcpy (copy, str, len + 1);
00266   
00267   return copy;
00268 }
00269 
00278 void*
00279 _dbus_memdup (const void  *mem,
00280               size_t       n_bytes)
00281 {
00282   void *copy;
00283 
00284   copy = dbus_malloc (n_bytes);
00285   if (copy == NULL)
00286     return NULL;
00287 
00288   memcpy (copy, mem, n_bytes);
00289   
00290   return copy;
00291 }
00292 
00301 char**
00302 _dbus_dup_string_array (const char **array)
00303 {
00304   int len;
00305   int i;
00306   char **copy;
00307   
00308   if (array == NULL)
00309     return NULL;
00310 
00311   for (len = 0; array[len] != NULL; ++len)
00312     ;
00313 
00314   copy = dbus_new0 (char*, len + 1);
00315   if (copy == NULL)
00316     return NULL;
00317 
00318   i = 0;
00319   while (i < len)
00320     {
00321       copy[i] = _dbus_strdup (array[i]);
00322       if (copy[i] == NULL)
00323         {
00324           dbus_free_string_array (copy);
00325           return NULL;
00326         }
00327 
00328       ++i;
00329     }
00330 
00331   return copy;
00332 }
00333 
00341 dbus_bool_t
00342 _dbus_string_array_contains (const char **array,
00343                              const char  *str)
00344 {
00345   int i;
00346 
00347   i = 0;
00348   while (array[i] != NULL)
00349     {
00350       if (strcmp (array[i], str) == 0)
00351         return TRUE;
00352       ++i;
00353     }
00354 
00355   return FALSE;
00356 }
00357 
00364 const char *
00365 _dbus_type_to_string (int type)
00366 {
00367   switch (type)
00368     {
00369     case DBUS_TYPE_INVALID:
00370       return "invalid";
00371     case DBUS_TYPE_NIL:
00372       return "nil";
00373     case DBUS_TYPE_BOOLEAN:
00374       return "boolean";
00375     case DBUS_TYPE_INT32:
00376       return "int32";
00377     case DBUS_TYPE_UINT32:
00378       return "uint32";
00379     case DBUS_TYPE_DOUBLE:
00380       return "double";
00381     case DBUS_TYPE_STRING:
00382       return "string";
00383     case DBUS_TYPE_CUSTOM:
00384       return "custom";
00385     case DBUS_TYPE_ARRAY:
00386       return "array";
00387     case DBUS_TYPE_DICT:
00388       return "dict";
00389     default:
00390       return "unknown";
00391     }
00392 }
00393 
00400 const char *
00401 _dbus_header_field_to_string (int header_field)
00402 {
00403   switch (header_field)
00404     {
00405     case DBUS_HEADER_FIELD_INVALID:
00406       return "invalid";
00407     case DBUS_HEADER_FIELD_PATH:
00408       return "path";
00409     case DBUS_HEADER_FIELD_INTERFACE:
00410       return "interface";
00411     case DBUS_HEADER_FIELD_MEMBER:
00412       return "member";
00413     case DBUS_HEADER_FIELD_ERROR_NAME:
00414       return "error-name";
00415     case DBUS_HEADER_FIELD_REPLY_SERIAL:
00416       return "reply-serial";
00417     case DBUS_HEADER_FIELD_DESTINATION:
00418       return "destination";
00419     case DBUS_HEADER_FIELD_SENDER:
00420       return "sender";
00421     default:
00422       return "unknown";
00423     }
00424 }
00425 
00426 #ifndef DBUS_DISABLE_CHECKS
00427 
00428 const char _dbus_return_if_fail_warning_format[] =
00429 "%lu: arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
00430 "This is normally a bug in some application using the D-BUS library.\n";
00431 #endif
00432 
00433 #ifndef DBUS_DISABLE_ASSERT
00434 
00445 void
00446 _dbus_real_assert (dbus_bool_t  condition,
00447                    const char  *condition_text,
00448                    const char  *file,
00449                    int          line)
00450 {
00451   if (_DBUS_UNLIKELY (!condition))
00452     {
00453       _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d\n",
00454                   _dbus_getpid (), condition_text, file, line);
00455       _dbus_abort ();
00456     }
00457 }
00458 
00469 void
00470 _dbus_real_assert_not_reached (const char *explanation,
00471                                const char *file,
00472                                int         line)
00473 {
00474   _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
00475               file, line, _dbus_getpid (), explanation);
00476   _dbus_abort ();
00477 }
00478 #endif /* DBUS_DISABLE_ASSERT */
00479   
00480 #ifdef DBUS_BUILD_TESTS
00481 static dbus_bool_t
00482 run_failing_each_malloc (int                    n_mallocs,
00483                          const char            *description,
00484                          DBusTestMemoryFunction func,
00485                          void                  *data)
00486 {
00487   n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
00488   
00489   while (n_mallocs >= 0)
00490     {      
00491       _dbus_set_fail_alloc_counter (n_mallocs);
00492 
00493       _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
00494                      description, n_mallocs,
00495                      _dbus_get_fail_alloc_failures ());
00496 
00497       if (!(* func) (data))
00498         return FALSE;
00499       
00500       n_mallocs -= 1;
00501     }
00502 
00503   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00504 
00505   return TRUE;
00506 }                        
00507 
00521 dbus_bool_t
00522 _dbus_test_oom_handling (const char             *description,
00523                          DBusTestMemoryFunction  func,
00524                          void                   *data)
00525 {
00526   int approx_mallocs;
00527 
00528   /* Run once to see about how many mallocs are involved */
00529   
00530   _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00531 
00532   _dbus_verbose ("Running once to count mallocs\n");
00533   
00534   if (!(* func) (data))
00535     return FALSE;
00536   
00537   approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
00538 
00539   _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
00540                  description, approx_mallocs);
00541 
00542   _dbus_set_fail_alloc_failures (1);
00543   if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00544     return FALSE;
00545 
00546   _dbus_set_fail_alloc_failures (2);
00547   if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00548     return FALSE;
00549   
00550   _dbus_set_fail_alloc_failures (3);
00551   if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00552     return FALSE;
00553 
00554   _dbus_set_fail_alloc_failures (4);
00555   if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00556     return FALSE;
00557   
00558   _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
00559                  description);
00560 
00561   return TRUE;
00562 }
00563 #endif /* DBUS_BUILD_TESTS */
00564 

Generated on Wed Jun 9 05:01:25 2004 for D-BUS by doxygen1.2.15