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 <unistd.h>
00032 #include <fcntl.h>
00033 #include <stdlib.h>
00034
00195 const char _dbus_no_memory_message[] = "Not enough memory";
00196
00202 void
00203 _dbus_warn (const char *format,
00204 ...)
00205 {
00206
00207 va_list args;
00208
00209 va_start (args, format);
00210 vfprintf (stderr, format, args);
00211 va_end (args);
00212 }
00213
00214 #ifdef DBUS_ENABLE_VERBOSE_MODE
00215
00216 static dbus_bool_t verbose_initted = FALSE;
00217
00218 #define PTHREAD_IN_VERBOSE 0
00219 #if PTHREAD_IN_VERBOSE
00220 #include <pthread.h>
00221 #endif
00222
00231 void
00232 _dbus_verbose_real (const char *format,
00233 ...)
00234 {
00235 va_list args;
00236 static dbus_bool_t verbose = TRUE;
00237 static dbus_bool_t need_pid = TRUE;
00238 int len;
00239
00240
00241
00242
00243
00244 if (!verbose)
00245 return;
00246
00247 if (!verbose_initted)
00248 {
00249 verbose = _dbus_getenv ("DBUS_VERBOSE") != NULL;
00250 verbose_initted = TRUE;
00251 if (!verbose)
00252 return;
00253 }
00254
00255
00256 if (need_pid)
00257 {
00258 #if PTHREAD_IN_VERBOSE
00259 fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
00260 #else
00261 fprintf (stderr, "%lu: ", _dbus_getpid ());
00262 #endif
00263 }
00264
00265
00266
00267 len = strlen (format);
00268 if (format[len-1] == '\n')
00269 need_pid = TRUE;
00270 else
00271 need_pid = FALSE;
00272
00273 va_start (args, format);
00274 vfprintf (stderr, format, args);
00275 va_end (args);
00276
00277 fflush (stderr);
00278 }
00279
00286 void
00287 _dbus_verbose_reset_real (void)
00288 {
00289 verbose_initted = FALSE;
00290 }
00291
00292 #endif
00293
00302 char*
00303 _dbus_strdup (const char *str)
00304 {
00305 size_t len;
00306 char *copy;
00307
00308 if (str == NULL)
00309 return NULL;
00310
00311 len = strlen (str);
00312
00313 copy = dbus_malloc (len + 1);
00314 if (copy == NULL)
00315 return NULL;
00316
00317 memcpy (copy, str, len + 1);
00318
00319 return copy;
00320 }
00321
00330 void*
00331 _dbus_memdup (const void *mem,
00332 size_t n_bytes)
00333 {
00334 void *copy;
00335
00336 copy = dbus_malloc (n_bytes);
00337 if (copy == NULL)
00338 return NULL;
00339
00340 memcpy (copy, mem, n_bytes);
00341
00342 return copy;
00343 }
00344
00353 char**
00354 _dbus_dup_string_array (const char **array)
00355 {
00356 int len;
00357 int i;
00358 char **copy;
00359
00360 if (array == NULL)
00361 return NULL;
00362
00363 for (len = 0; array[len] != NULL; ++len)
00364 ;
00365
00366 copy = dbus_new0 (char*, len + 1);
00367 if (copy == NULL)
00368 return NULL;
00369
00370 i = 0;
00371 while (i < len)
00372 {
00373 copy[i] = _dbus_strdup (array[i]);
00374 if (copy[i] == NULL)
00375 {
00376 dbus_free_string_array (copy);
00377 return NULL;
00378 }
00379
00380 ++i;
00381 }
00382
00383 return copy;
00384 }
00385
00393 dbus_bool_t
00394 _dbus_string_array_contains (const char **array,
00395 const char *str)
00396 {
00397 int i;
00398
00399 i = 0;
00400 while (array[i] != NULL)
00401 {
00402 if (strcmp (array[i], str) == 0)
00403 return TRUE;
00404 ++i;
00405 }
00406
00407 return FALSE;
00408 }
00409
00410 #ifdef DBUS_BUILD_TESTS
00411
00417 const char *
00418 _dbus_header_field_to_string (int header_field)
00419 {
00420 switch (header_field)
00421 {
00422 case DBUS_HEADER_FIELD_INVALID:
00423 return "invalid";
00424 case DBUS_HEADER_FIELD_PATH:
00425 return "path";
00426 case DBUS_HEADER_FIELD_INTERFACE:
00427 return "interface";
00428 case DBUS_HEADER_FIELD_MEMBER:
00429 return "member";
00430 case DBUS_HEADER_FIELD_ERROR_NAME:
00431 return "error-name";
00432 case DBUS_HEADER_FIELD_REPLY_SERIAL:
00433 return "reply-serial";
00434 case DBUS_HEADER_FIELD_DESTINATION:
00435 return "destination";
00436 case DBUS_HEADER_FIELD_SENDER:
00437 return "sender";
00438 case DBUS_HEADER_FIELD_SIGNATURE:
00439 return "signature";
00440 default:
00441 return "unknown";
00442 }
00443 }
00444 #endif
00445
00446 #ifndef DBUS_DISABLE_CHECKS
00447
00448 const char _dbus_return_if_fail_warning_format[] =
00449 "%lu: arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
00450 "This is normally a bug in some application using the D-BUS library.\n";
00451 #endif
00452
00453 #ifndef DBUS_DISABLE_ASSERT
00454
00466 void
00467 _dbus_real_assert (dbus_bool_t condition,
00468 const char *condition_text,
00469 const char *file,
00470 int line,
00471 const char *func)
00472 {
00473 if (_DBUS_UNLIKELY (!condition))
00474 {
00475 _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
00476 _dbus_getpid (), condition_text, file, line, func);
00477 _dbus_abort ();
00478 }
00479 }
00480
00491 void
00492 _dbus_real_assert_not_reached (const char *explanation,
00493 const char *file,
00494 int line)
00495 {
00496 _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
00497 file, line, _dbus_getpid (), explanation);
00498 _dbus_abort ();
00499 }
00500 #endif
00501
00502 #ifdef DBUS_BUILD_TESTS
00503 static dbus_bool_t
00504 run_failing_each_malloc (int n_mallocs,
00505 const char *description,
00506 DBusTestMemoryFunction func,
00507 void *data)
00508 {
00509 n_mallocs += 10;
00510
00511 while (n_mallocs >= 0)
00512 {
00513 _dbus_set_fail_alloc_counter (n_mallocs);
00514
00515 _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
00516 description, n_mallocs,
00517 _dbus_get_fail_alloc_failures ());
00518
00519 if (!(* func) (data))
00520 return FALSE;
00521
00522 n_mallocs -= 1;
00523 }
00524
00525 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00526
00527 return TRUE;
00528 }
00529
00543 dbus_bool_t
00544 _dbus_test_oom_handling (const char *description,
00545 DBusTestMemoryFunction func,
00546 void *data)
00547 {
00548 int approx_mallocs;
00549 const char *setting;
00550 int max_failures_to_try;
00551 int i;
00552
00553
00554
00555 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00556
00557 _dbus_verbose ("Running once to count mallocs\n");
00558
00559 if (!(* func) (data))
00560 return FALSE;
00561
00562 approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
00563
00564 _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
00565 description, approx_mallocs);
00566
00567 setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
00568 if (setting != NULL)
00569 {
00570 DBusString str;
00571 long v;
00572 _dbus_string_init_const (&str, setting);
00573 v = 4;
00574 if (!_dbus_string_parse_int (&str, 0, &v, NULL))
00575 _dbus_warn ("couldn't parse '%s' as integer\n", setting);
00576 max_failures_to_try = v;
00577 }
00578 else
00579 {
00580 max_failures_to_try = 4;
00581 }
00582
00583 i = setting ? max_failures_to_try - 1 : 1;
00584 while (i < max_failures_to_try)
00585 {
00586 _dbus_set_fail_alloc_failures (i);
00587 if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00588 return FALSE;
00589 ++i;
00590 }
00591
00592 _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
00593 description);
00594
00595 return TRUE;
00596 }
00597 #endif
00598