00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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 <fcntl.h>
00032 #include <stdlib.h>
00033
00194 const char _dbus_no_memory_message[] = "Not enough memory";
00195
00201 void
00202 _dbus_warn (const char *format,
00203 ...)
00204 {
00205
00206 va_list args;
00207
00208 va_start (args, format);
00209 vfprintf (stderr, format, args);
00210 va_end (args);
00211 }
00212
00213 #ifdef DBUS_ENABLE_VERBOSE_MODE
00214
00215 static dbus_bool_t verbose_initted = FALSE;
00216 static dbus_bool_t verbose = TRUE;
00217
00218 #define PTHREAD_IN_VERBOSE 0
00219 #if PTHREAD_IN_VERBOSE
00220 #include <pthread.h>
00221 #endif
00222
00223 static inline void
00224 _dbus_verbose_init (void)
00225 {
00226 if (!verbose_initted)
00227 {
00228 const char *p = _dbus_getenv ("DBUS_VERBOSE");
00229 verbose = p != NULL && *p == '1';
00230 verbose_initted = TRUE;
00231 }
00232 }
00233
00234 dbus_bool_t
00235 _dbus_is_verbose_real (void)
00236 {
00237 _dbus_verbose_init ();
00238 return verbose;
00239 }
00240
00249 void
00250 _dbus_verbose_real (const char *format,
00251 ...)
00252 {
00253 va_list args;
00254 static dbus_bool_t need_pid = TRUE;
00255 int len;
00256
00257
00258
00259
00260
00261 if (!_dbus_is_verbose_real())
00262 return;
00263
00264
00265 if (need_pid)
00266 {
00267 #if PTHREAD_IN_VERBOSE
00268 fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
00269 #else
00270 fprintf (stderr, "%lu: ", _dbus_getpid ());
00271 #endif
00272 }
00273
00274
00275
00276 len = strlen (format);
00277 if (format[len-1] == '\n')
00278 need_pid = TRUE;
00279 else
00280 need_pid = FALSE;
00281
00282 va_start (args, format);
00283 vfprintf (stderr, format, args);
00284 va_end (args);
00285
00286 fflush (stderr);
00287 }
00288
00295 void
00296 _dbus_verbose_reset_real (void)
00297 {
00298 verbose_initted = FALSE;
00299 }
00300
00301 #endif
00302
00311 char*
00312 _dbus_strdup (const char *str)
00313 {
00314 size_t len;
00315 char *copy;
00316
00317 if (str == NULL)
00318 return NULL;
00319
00320 len = strlen (str);
00321
00322 copy = dbus_malloc (len + 1);
00323 if (copy == NULL)
00324 return NULL;
00325
00326 memcpy (copy, str, len + 1);
00327
00328 return copy;
00329 }
00330
00339 void*
00340 _dbus_memdup (const void *mem,
00341 size_t n_bytes)
00342 {
00343 void *copy;
00344
00345 copy = dbus_malloc (n_bytes);
00346 if (copy == NULL)
00347 return NULL;
00348
00349 memcpy (copy, mem, n_bytes);
00350
00351 return copy;
00352 }
00353
00362 char**
00363 _dbus_dup_string_array (const char **array)
00364 {
00365 int len;
00366 int i;
00367 char **copy;
00368
00369 if (array == NULL)
00370 return NULL;
00371
00372 for (len = 0; array[len] != NULL; ++len)
00373 ;
00374
00375 copy = dbus_new0 (char*, len + 1);
00376 if (copy == NULL)
00377 return NULL;
00378
00379 i = 0;
00380 while (i < len)
00381 {
00382 copy[i] = _dbus_strdup (array[i]);
00383 if (copy[i] == NULL)
00384 {
00385 dbus_free_string_array (copy);
00386 return NULL;
00387 }
00388
00389 ++i;
00390 }
00391
00392 return copy;
00393 }
00394
00402 dbus_bool_t
00403 _dbus_string_array_contains (const char **array,
00404 const char *str)
00405 {
00406 int i;
00407
00408 i = 0;
00409 while (array[i] != NULL)
00410 {
00411 if (strcmp (array[i], str) == 0)
00412 return TRUE;
00413 ++i;
00414 }
00415
00416 return FALSE;
00417 }
00418
00419 #ifdef DBUS_BUILD_TESTS
00420
00426 const char *
00427 _dbus_header_field_to_string (int header_field)
00428 {
00429 switch (header_field)
00430 {
00431 case DBUS_HEADER_FIELD_INVALID:
00432 return "invalid";
00433 case DBUS_HEADER_FIELD_PATH:
00434 return "path";
00435 case DBUS_HEADER_FIELD_INTERFACE:
00436 return "interface";
00437 case DBUS_HEADER_FIELD_MEMBER:
00438 return "member";
00439 case DBUS_HEADER_FIELD_ERROR_NAME:
00440 return "error-name";
00441 case DBUS_HEADER_FIELD_REPLY_SERIAL:
00442 return "reply-serial";
00443 case DBUS_HEADER_FIELD_DESTINATION:
00444 return "destination";
00445 case DBUS_HEADER_FIELD_SENDER:
00446 return "sender";
00447 case DBUS_HEADER_FIELD_SIGNATURE:
00448 return "signature";
00449 default:
00450 return "unknown";
00451 }
00452 }
00453 #endif
00454
00455 #ifndef DBUS_DISABLE_CHECKS
00456
00457 const char _dbus_return_if_fail_warning_format[] =
00458 "%lu: arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
00459 "This is normally a bug in some application using the D-Bus library.\n";
00460 #endif
00461
00462 #ifndef DBUS_DISABLE_ASSERT
00463
00475 void
00476 _dbus_real_assert (dbus_bool_t condition,
00477 const char *condition_text,
00478 const char *file,
00479 int line,
00480 const char *func)
00481 {
00482 if (_DBUS_UNLIKELY (!condition))
00483 {
00484 _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
00485 _dbus_getpid (), condition_text, file, line, func);
00486 _dbus_abort ();
00487 }
00488 }
00489
00500 void
00501 _dbus_real_assert_not_reached (const char *explanation,
00502 const char *file,
00503 int line)
00504 {
00505 _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
00506 file, line, _dbus_getpid (), explanation);
00507 _dbus_abort ();
00508 }
00509 #endif
00510
00511 #ifdef DBUS_BUILD_TESTS
00512 static dbus_bool_t
00513 run_failing_each_malloc (int n_mallocs,
00514 const char *description,
00515 DBusTestMemoryFunction func,
00516 void *data)
00517 {
00518 n_mallocs += 10;
00519
00520 while (n_mallocs >= 0)
00521 {
00522 _dbus_set_fail_alloc_counter (n_mallocs);
00523
00524 _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
00525 description, n_mallocs,
00526 _dbus_get_fail_alloc_failures ());
00527
00528 if (!(* func) (data))
00529 return FALSE;
00530
00531 n_mallocs -= 1;
00532 }
00533
00534 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00535
00536 return TRUE;
00537 }
00538
00552 dbus_bool_t
00553 _dbus_test_oom_handling (const char *description,
00554 DBusTestMemoryFunction func,
00555 void *data)
00556 {
00557 int approx_mallocs;
00558 const char *setting;
00559 int max_failures_to_try;
00560 int i;
00561
00562
00563
00564 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00565
00566 _dbus_verbose ("Running once to count mallocs\n");
00567
00568 if (!(* func) (data))
00569 return FALSE;
00570
00571 approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
00572
00573 _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
00574 description, approx_mallocs);
00575
00576 setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
00577 if (setting != NULL)
00578 {
00579 DBusString str;
00580 long v;
00581 _dbus_string_init_const (&str, setting);
00582 v = 4;
00583 if (!_dbus_string_parse_int (&str, 0, &v, NULL))
00584 _dbus_warn ("couldn't parse '%s' as integer\n", setting);
00585 max_failures_to_try = v;
00586 }
00587 else
00588 {
00589 max_failures_to_try = 4;
00590 }
00591
00592 i = setting ? max_failures_to_try - 1 : 1;
00593 while (i < max_failures_to_try)
00594 {
00595 _dbus_set_fail_alloc_failures (i);
00596 if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00597 return FALSE;
00598 ++i;
00599 }
00600
00601 _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
00602 description);
00603
00604 return TRUE;
00605 }
00606 #endif
00607