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-marshal-basic.h"
00026 #include "dbus-test.h"
00027 #include <stdio.h>
00028 #include <stdarg.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031
00192 const char _dbus_no_memory_message[] = "Not enough memory";
00193
00194 static dbus_bool_t warn_initted = FALSE;
00195 static dbus_bool_t fatal_warnings = FALSE;
00196 static dbus_bool_t fatal_warnings_on_check_failed = TRUE;
00197
00198 static void
00199 init_warnings(void)
00200 {
00201 if (!warn_initted)
00202 {
00203 const char *s;
00204 s = _dbus_getenv ("DBUS_FATAL_WARNINGS");
00205 if (s && *s)
00206 {
00207 if (*s == '0')
00208 {
00209 fatal_warnings = FALSE;
00210 fatal_warnings_on_check_failed = FALSE;
00211 }
00212 else if (*s == '1')
00213 {
00214 fatal_warnings = TRUE;
00215 fatal_warnings_on_check_failed = TRUE;
00216 }
00217 else
00218 {
00219 fprintf(stderr, "DBUS_FATAL_WARNINGS should be set to 0 or 1 if set, not '%s'",
00220 s);
00221 }
00222 }
00223
00224 warn_initted = TRUE;
00225 }
00226 }
00227
00237 void
00238 _dbus_warn (const char *format,
00239 ...)
00240 {
00241 va_list args;
00242
00243 if (!warn_initted)
00244 init_warnings ();
00245
00246 va_start (args, format);
00247 vfprintf (stderr, format, args);
00248 va_end (args);
00249
00250 if (fatal_warnings)
00251 {
00252 fflush (stderr);
00253 _dbus_abort ();
00254 }
00255 }
00256
00265 void
00266 _dbus_warn_check_failed(const char *format,
00267 ...)
00268 {
00269 va_list args;
00270
00271 if (!warn_initted)
00272 init_warnings ();
00273
00274 fprintf (stderr, "process %lu: ", _dbus_getpid ());
00275
00276 va_start (args, format);
00277 vfprintf (stderr, format, args);
00278 va_end (args);
00279
00280 if (fatal_warnings_on_check_failed)
00281 {
00282 fflush (stderr);
00283 _dbus_abort ();
00284 }
00285 }
00286
00287 #ifdef DBUS_ENABLE_VERBOSE_MODE
00288
00289 static dbus_bool_t verbose_initted = FALSE;
00290 static dbus_bool_t verbose = TRUE;
00291
00293 #define PTHREAD_IN_VERBOSE 0
00294 #if PTHREAD_IN_VERBOSE
00295 #include <pthread.h>
00296 #endif
00297
00298 static inline void
00299 _dbus_verbose_init (void)
00300 {
00301 if (!verbose_initted)
00302 {
00303 const char *p = _dbus_getenv ("DBUS_VERBOSE");
00304 verbose = p != NULL && *p == '1';
00305 verbose_initted = TRUE;
00306 }
00307 }
00308
00314 dbus_bool_t
00315 _dbus_is_verbose_real (void)
00316 {
00317 _dbus_verbose_init ();
00318 return verbose;
00319 }
00320
00329 void
00330 _dbus_verbose_real (const char *format,
00331 ...)
00332 {
00333 va_list args;
00334 static dbus_bool_t need_pid = TRUE;
00335 int len;
00336
00337
00338
00339
00340
00341 if (!_dbus_is_verbose_real())
00342 return;
00343
00344
00345 if (need_pid)
00346 {
00347 #if PTHREAD_IN_VERBOSE
00348 fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
00349 #else
00350 fprintf (stderr, "%lu: ", _dbus_getpid ());
00351 #endif
00352 }
00353
00354
00355
00356 len = strlen (format);
00357 if (format[len-1] == '\n')
00358 need_pid = TRUE;
00359 else
00360 need_pid = FALSE;
00361
00362 va_start (args, format);
00363 vfprintf (stderr, format, args);
00364 va_end (args);
00365
00366 fflush (stderr);
00367 }
00368
00375 void
00376 _dbus_verbose_reset_real (void)
00377 {
00378 verbose_initted = FALSE;
00379 }
00380
00381 #endif
00382
00391 char*
00392 _dbus_strdup (const char *str)
00393 {
00394 size_t len;
00395 char *copy;
00396
00397 if (str == NULL)
00398 return NULL;
00399
00400 len = strlen (str);
00401
00402 copy = dbus_malloc (len + 1);
00403 if (copy == NULL)
00404 return NULL;
00405
00406 memcpy (copy, str, len + 1);
00407
00408 return copy;
00409 }
00410
00419 void*
00420 _dbus_memdup (const void *mem,
00421 size_t n_bytes)
00422 {
00423 void *copy;
00424
00425 copy = dbus_malloc (n_bytes);
00426 if (copy == NULL)
00427 return NULL;
00428
00429 memcpy (copy, mem, n_bytes);
00430
00431 return copy;
00432 }
00433
00442 char**
00443 _dbus_dup_string_array (const char **array)
00444 {
00445 int len;
00446 int i;
00447 char **copy;
00448
00449 if (array == NULL)
00450 return NULL;
00451
00452 for (len = 0; array[len] != NULL; ++len)
00453 ;
00454
00455 copy = dbus_new0 (char*, len + 1);
00456 if (copy == NULL)
00457 return NULL;
00458
00459 i = 0;
00460 while (i < len)
00461 {
00462 copy[i] = _dbus_strdup (array[i]);
00463 if (copy[i] == NULL)
00464 {
00465 dbus_free_string_array (copy);
00466 return NULL;
00467 }
00468
00469 ++i;
00470 }
00471
00472 return copy;
00473 }
00474
00482 dbus_bool_t
00483 _dbus_string_array_contains (const char **array,
00484 const char *str)
00485 {
00486 int i;
00487
00488 i = 0;
00489 while (array[i] != NULL)
00490 {
00491 if (strcmp (array[i], str) == 0)
00492 return TRUE;
00493 ++i;
00494 }
00495
00496 return FALSE;
00497 }
00498
00505 void
00506 _dbus_generate_uuid (DBusGUID *uuid)
00507 {
00508 long now;
00509
00510 _dbus_get_current_time (&now, NULL);
00511
00512 uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
00513
00514 _dbus_generate_random_bytes_buffer (uuid->as_bytes, DBUS_UUID_LENGTH_BYTES - 4);
00515 }
00516
00524 dbus_bool_t
00525 _dbus_uuid_encode (const DBusGUID *uuid,
00526 DBusString *encoded)
00527 {
00528 DBusString binary;
00529 _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
00530 return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
00531 }
00532
00533 static dbus_bool_t
00534 _dbus_read_uuid_file_without_creating (const DBusString *filename,
00535 DBusGUID *uuid,
00536 DBusError *error)
00537 {
00538 DBusString contents;
00539 DBusString decoded;
00540 int end;
00541
00542 if (!_dbus_string_init (&contents))
00543 {
00544 _DBUS_SET_OOM (error);
00545 return FALSE;
00546 }
00547
00548 if (!_dbus_string_init (&decoded))
00549 {
00550 _dbus_string_free (&contents);
00551 _DBUS_SET_OOM (error);
00552 return FALSE;
00553 }
00554
00555 if (!_dbus_file_get_contents (&contents, filename, error))
00556 goto error;
00557
00558 _dbus_string_chop_white (&contents);
00559
00560 if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
00561 {
00562 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
00563 "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
00564 _dbus_string_get_const_data (filename),
00565 DBUS_UUID_LENGTH_HEX,
00566 _dbus_string_get_length (&contents));
00567 goto error;
00568 }
00569
00570 if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
00571 {
00572 _DBUS_SET_OOM (error);
00573 goto error;
00574 }
00575
00576 if (end == 0)
00577 {
00578 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
00579 "UUID file '%s' contains invalid hex data",
00580 _dbus_string_get_const_data (filename));
00581 goto error;
00582 }
00583
00584 if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
00585 {
00586 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
00587 "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
00588 _dbus_string_get_const_data (filename),
00589 _dbus_string_get_length (&decoded),
00590 DBUS_UUID_LENGTH_BYTES);
00591 goto error;
00592 }
00593
00594 _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
00595
00596 _dbus_string_free (&decoded);
00597 _dbus_string_free (&contents);
00598
00599 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00600
00601 return TRUE;
00602
00603 error:
00604 _DBUS_ASSERT_ERROR_IS_SET (error);
00605 _dbus_string_free (&contents);
00606 _dbus_string_free (&decoded);
00607 return FALSE;
00608 }
00609
00610 static dbus_bool_t
00611 _dbus_create_uuid_file_exclusively (const DBusString *filename,
00612 DBusGUID *uuid,
00613 DBusError *error)
00614 {
00615 DBusString encoded;
00616
00617 if (!_dbus_string_init (&encoded))
00618 {
00619 _DBUS_SET_OOM (error);
00620 return FALSE;
00621 }
00622
00623 _dbus_generate_uuid (uuid);
00624
00625 if (!_dbus_uuid_encode (uuid, &encoded))
00626 {
00627 _DBUS_SET_OOM (error);
00628 goto error;
00629 }
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 if (!_dbus_create_file_exclusively (filename, error))
00640 goto error;
00641
00642 if (!_dbus_string_append_byte (&encoded, '\n'))
00643 {
00644 _DBUS_SET_OOM (error);
00645 goto error;
00646 }
00647
00648 if (!_dbus_string_save_to_file (&encoded, filename, error))
00649 goto error;
00650
00651 if (!_dbus_make_file_world_readable (filename, error))
00652 goto error;
00653
00654 _dbus_string_free (&encoded);
00655
00656 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00657 return TRUE;
00658
00659 error:
00660 _DBUS_ASSERT_ERROR_IS_SET (error);
00661 _dbus_string_free (&encoded);
00662 return FALSE;
00663 }
00664
00675 dbus_bool_t
00676 _dbus_read_uuid_file (const DBusString *filename,
00677 DBusGUID *uuid,
00678 dbus_bool_t create_if_not_found,
00679 DBusError *error)
00680 {
00681 DBusError read_error;
00682
00683 dbus_error_init (&read_error);
00684
00685 if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
00686 return TRUE;
00687
00688 if (!create_if_not_found)
00689 {
00690 dbus_move_error (&read_error, error);
00691 return FALSE;
00692 }
00693
00694
00695
00696
00697
00698 if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT))
00699 {
00700 dbus_move_error (&read_error, error);
00701 return FALSE;
00702 }
00703 else
00704 {
00705 dbus_error_free (&read_error);
00706 return _dbus_create_uuid_file_exclusively (filename, uuid, error);
00707 }
00708 }
00709
00710 _DBUS_DEFINE_GLOBAL_LOCK (machine_uuid);
00711 static int machine_uuid_initialized_generation = 0;
00712 static DBusGUID machine_uuid;
00713
00724 dbus_bool_t
00725 _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
00726 {
00727 dbus_bool_t ok;
00728
00729 _DBUS_LOCK (machine_uuid);
00730 if (machine_uuid_initialized_generation != _dbus_current_generation)
00731 {
00732 DBusError error;
00733 dbus_error_init (&error);
00734 if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
00735 &error))
00736 {
00737 #ifndef DBUS_BUILD_TESTS
00738
00739
00740
00741
00742 _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n"
00743 "See the manual page for dbus-uuidgen to correct this issue.\n",
00744 error.message);
00745 #endif
00746
00747 dbus_error_free (&error);
00748
00749 _dbus_generate_uuid (&machine_uuid);
00750 }
00751 }
00752
00753 ok = _dbus_uuid_encode (&machine_uuid, uuid_str);
00754
00755 _DBUS_UNLOCK (machine_uuid);
00756
00757 return ok;
00758 }
00759
00760 #ifdef DBUS_BUILD_TESTS
00761
00767 const char *
00768 _dbus_header_field_to_string (int header_field)
00769 {
00770 switch (header_field)
00771 {
00772 case DBUS_HEADER_FIELD_INVALID:
00773 return "invalid";
00774 case DBUS_HEADER_FIELD_PATH:
00775 return "path";
00776 case DBUS_HEADER_FIELD_INTERFACE:
00777 return "interface";
00778 case DBUS_HEADER_FIELD_MEMBER:
00779 return "member";
00780 case DBUS_HEADER_FIELD_ERROR_NAME:
00781 return "error-name";
00782 case DBUS_HEADER_FIELD_REPLY_SERIAL:
00783 return "reply-serial";
00784 case DBUS_HEADER_FIELD_DESTINATION:
00785 return "destination";
00786 case DBUS_HEADER_FIELD_SENDER:
00787 return "sender";
00788 case DBUS_HEADER_FIELD_SIGNATURE:
00789 return "signature";
00790 default:
00791 return "unknown";
00792 }
00793 }
00794 #endif
00795
00796 #ifndef DBUS_DISABLE_CHECKS
00797
00798 const char _dbus_return_if_fail_warning_format[] =
00799 "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
00800 "This is normally a bug in some application using the D-Bus library.\n";
00801 #endif
00802
00803 #ifndef DBUS_DISABLE_ASSERT
00804
00816 void
00817 _dbus_real_assert (dbus_bool_t condition,
00818 const char *condition_text,
00819 const char *file,
00820 int line,
00821 const char *func)
00822 {
00823 if (_DBUS_UNLIKELY (!condition))
00824 {
00825 _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
00826 _dbus_getpid (), condition_text, file, line, func);
00827 _dbus_abort ();
00828 }
00829 }
00830
00841 void
00842 _dbus_real_assert_not_reached (const char *explanation,
00843 const char *file,
00844 int line)
00845 {
00846 _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
00847 file, line, _dbus_getpid (), explanation);
00848 _dbus_abort ();
00849 }
00850 #endif
00851
00852 #ifdef DBUS_BUILD_TESTS
00853 static dbus_bool_t
00854 run_failing_each_malloc (int n_mallocs,
00855 const char *description,
00856 DBusTestMemoryFunction func,
00857 void *data)
00858 {
00859 n_mallocs += 10;
00860
00861 while (n_mallocs >= 0)
00862 {
00863 _dbus_set_fail_alloc_counter (n_mallocs);
00864
00865 _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
00866 description, n_mallocs,
00867 _dbus_get_fail_alloc_failures ());
00868
00869 if (!(* func) (data))
00870 return FALSE;
00871
00872 n_mallocs -= 1;
00873 }
00874
00875 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00876
00877 return TRUE;
00878 }
00879
00893 dbus_bool_t
00894 _dbus_test_oom_handling (const char *description,
00895 DBusTestMemoryFunction func,
00896 void *data)
00897 {
00898 int approx_mallocs;
00899 const char *setting;
00900 int max_failures_to_try;
00901 int i;
00902
00903
00904
00905 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00906
00907 _dbus_verbose ("Running once to count mallocs\n");
00908
00909 if (!(* func) (data))
00910 return FALSE;
00911
00912 approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
00913
00914 _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
00915 description, approx_mallocs);
00916
00917 setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
00918 if (setting != NULL)
00919 {
00920 DBusString str;
00921 long v;
00922 _dbus_string_init_const (&str, setting);
00923 v = 4;
00924 if (!_dbus_string_parse_int (&str, 0, &v, NULL))
00925 _dbus_warn ("couldn't parse '%s' as integer\n", setting);
00926 max_failures_to_try = v;
00927 }
00928 else
00929 {
00930 max_failures_to_try = 4;
00931 }
00932
00933 i = setting ? max_failures_to_try - 1 : 1;
00934 while (i < max_failures_to_try)
00935 {
00936 _dbus_set_fail_alloc_failures (i);
00937 if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00938 return FALSE;
00939 ++i;
00940 }
00941
00942 _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
00943 description);
00944
00945 return TRUE;
00946 }
00947 #endif
00948