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_pid_for_log ());
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 #ifdef DBUS_WIN
00299 #define inline
00300 #endif
00301
00302 static inline void
00303 _dbus_verbose_init (void)
00304 {
00305 if (!verbose_initted)
00306 {
00307 const char *p = _dbus_getenv ("DBUS_VERBOSE");
00308 verbose = p != NULL && *p == '1';
00309 verbose_initted = TRUE;
00310 }
00311 }
00312
00318 dbus_bool_t
00319 _dbus_is_verbose_real (void)
00320 {
00321 _dbus_verbose_init ();
00322 return verbose;
00323 }
00324
00333 void
00334 _dbus_verbose_real (const char *format,
00335 ...)
00336 {
00337 va_list args;
00338 static dbus_bool_t need_pid = TRUE;
00339 int len;
00340
00341
00342
00343
00344
00345 if (!_dbus_is_verbose_real())
00346 return;
00347
00348
00349 if (need_pid)
00350 {
00351 #if PTHREAD_IN_VERBOSE
00352 fprintf (stderr, "%lu: 0x%lx: ", _dbus_pid_for_log (), pthread_self ());
00353 #else
00354 fprintf (stderr, "%lu: ", _dbus_pid_for_log ());
00355 #endif
00356 }
00357
00358
00359
00360 len = strlen (format);
00361 if (format[len-1] == '\n')
00362 need_pid = TRUE;
00363 else
00364 need_pid = FALSE;
00365
00366 va_start (args, format);
00367 vfprintf (stderr, format, args);
00368 va_end (args);
00369
00370 fflush (stderr);
00371 }
00372
00379 void
00380 _dbus_verbose_reset_real (void)
00381 {
00382 verbose_initted = FALSE;
00383 }
00384
00385 #endif
00386
00395 char*
00396 _dbus_strdup (const char *str)
00397 {
00398 size_t len;
00399 char *copy;
00400
00401 if (str == NULL)
00402 return NULL;
00403
00404 len = strlen (str);
00405
00406 copy = dbus_malloc (len + 1);
00407 if (copy == NULL)
00408 return NULL;
00409
00410 memcpy (copy, str, len + 1);
00411
00412 return copy;
00413 }
00414
00423 void*
00424 _dbus_memdup (const void *mem,
00425 size_t n_bytes)
00426 {
00427 void *copy;
00428
00429 copy = dbus_malloc (n_bytes);
00430 if (copy == NULL)
00431 return NULL;
00432
00433 memcpy (copy, mem, n_bytes);
00434
00435 return copy;
00436 }
00437
00446 char**
00447 _dbus_dup_string_array (const char **array)
00448 {
00449 int len;
00450 int i;
00451 char **copy;
00452
00453 if (array == NULL)
00454 return NULL;
00455
00456 for (len = 0; array[len] != NULL; ++len)
00457 ;
00458
00459 copy = dbus_new0 (char*, len + 1);
00460 if (copy == NULL)
00461 return NULL;
00462
00463 i = 0;
00464 while (i < len)
00465 {
00466 copy[i] = _dbus_strdup (array[i]);
00467 if (copy[i] == NULL)
00468 {
00469 dbus_free_string_array (copy);
00470 return NULL;
00471 }
00472
00473 ++i;
00474 }
00475
00476 return copy;
00477 }
00478
00486 dbus_bool_t
00487 _dbus_string_array_contains (const char **array,
00488 const char *str)
00489 {
00490 int i;
00491
00492 i = 0;
00493 while (array[i] != NULL)
00494 {
00495 if (strcmp (array[i], str) == 0)
00496 return TRUE;
00497 ++i;
00498 }
00499
00500 return FALSE;
00501 }
00502
00509 void
00510 _dbus_generate_uuid (DBusGUID *uuid)
00511 {
00512 long now;
00513
00514 _dbus_get_current_time (&now, NULL);
00515
00516 uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
00517
00518 _dbus_generate_random_bytes_buffer (uuid->as_bytes, DBUS_UUID_LENGTH_BYTES - 4);
00519 }
00520
00528 dbus_bool_t
00529 _dbus_uuid_encode (const DBusGUID *uuid,
00530 DBusString *encoded)
00531 {
00532 DBusString binary;
00533 _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
00534 return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
00535 }
00536
00537 static dbus_bool_t
00538 _dbus_read_uuid_file_without_creating (const DBusString *filename,
00539 DBusGUID *uuid,
00540 DBusError *error)
00541 {
00542 DBusString contents;
00543 DBusString decoded;
00544 int end;
00545
00546 if (!_dbus_string_init (&contents))
00547 {
00548 _DBUS_SET_OOM (error);
00549 return FALSE;
00550 }
00551
00552 if (!_dbus_string_init (&decoded))
00553 {
00554 _dbus_string_free (&contents);
00555 _DBUS_SET_OOM (error);
00556 return FALSE;
00557 }
00558
00559 if (!_dbus_file_get_contents (&contents, filename, error))
00560 goto error;
00561
00562 _dbus_string_chop_white (&contents);
00563
00564 if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
00565 {
00566 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
00567 "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
00568 _dbus_string_get_const_data (filename),
00569 DBUS_UUID_LENGTH_HEX,
00570 _dbus_string_get_length (&contents));
00571 goto error;
00572 }
00573
00574 if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
00575 {
00576 _DBUS_SET_OOM (error);
00577 goto error;
00578 }
00579
00580 if (end == 0)
00581 {
00582 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
00583 "UUID file '%s' contains invalid hex data",
00584 _dbus_string_get_const_data (filename));
00585 goto error;
00586 }
00587
00588 if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
00589 {
00590 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT,
00591 "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
00592 _dbus_string_get_const_data (filename),
00593 _dbus_string_get_length (&decoded),
00594 DBUS_UUID_LENGTH_BYTES);
00595 goto error;
00596 }
00597
00598 _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
00599
00600 _dbus_string_free (&decoded);
00601 _dbus_string_free (&contents);
00602
00603 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00604
00605 return TRUE;
00606
00607 error:
00608 _DBUS_ASSERT_ERROR_IS_SET (error);
00609 _dbus_string_free (&contents);
00610 _dbus_string_free (&decoded);
00611 return FALSE;
00612 }
00613
00614 static dbus_bool_t
00615 _dbus_create_uuid_file_exclusively (const DBusString *filename,
00616 DBusGUID *uuid,
00617 DBusError *error)
00618 {
00619 DBusString encoded;
00620
00621 if (!_dbus_string_init (&encoded))
00622 {
00623 _DBUS_SET_OOM (error);
00624 return FALSE;
00625 }
00626
00627 _dbus_generate_uuid (uuid);
00628
00629 if (!_dbus_uuid_encode (uuid, &encoded))
00630 {
00631 _DBUS_SET_OOM (error);
00632 goto error;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 if (!_dbus_create_file_exclusively (filename, error))
00644 goto error;
00645
00646 if (!_dbus_string_append_byte (&encoded, '\n'))
00647 {
00648 _DBUS_SET_OOM (error);
00649 goto error;
00650 }
00651
00652 if (!_dbus_string_save_to_file (&encoded, filename, error))
00653 goto error;
00654
00655 if (!_dbus_make_file_world_readable (filename, error))
00656 goto error;
00657
00658 _dbus_string_free (&encoded);
00659
00660 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00661 return TRUE;
00662
00663 error:
00664 _DBUS_ASSERT_ERROR_IS_SET (error);
00665 _dbus_string_free (&encoded);
00666 return FALSE;
00667 }
00668
00679 dbus_bool_t
00680 _dbus_read_uuid_file (const DBusString *filename,
00681 DBusGUID *uuid,
00682 dbus_bool_t create_if_not_found,
00683 DBusError *error)
00684 {
00685 DBusError read_error = DBUS_ERROR_INIT;
00686
00687 if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
00688 return TRUE;
00689
00690 if (!create_if_not_found)
00691 {
00692 dbus_move_error (&read_error, error);
00693 return FALSE;
00694 }
00695
00696
00697
00698
00699
00700 if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT))
00701 {
00702 dbus_move_error (&read_error, error);
00703 return FALSE;
00704 }
00705 else
00706 {
00707 dbus_error_free (&read_error);
00708 return _dbus_create_uuid_file_exclusively (filename, uuid, error);
00709 }
00710 }
00711
00712 _DBUS_DEFINE_GLOBAL_LOCK (machine_uuid);
00713 static int machine_uuid_initialized_generation = 0;
00714 static DBusGUID machine_uuid;
00715
00726 dbus_bool_t
00727 _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str)
00728 {
00729 dbus_bool_t ok;
00730
00731 _DBUS_LOCK (machine_uuid);
00732 if (machine_uuid_initialized_generation != _dbus_current_generation)
00733 {
00734 DBusError error = DBUS_ERROR_INIT;
00735
00736 if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE,
00737 &error))
00738 {
00739 #ifndef DBUS_BUILD_TESTS
00740
00741
00742
00743
00744 _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n"
00745 "See the manual page for dbus-uuidgen to correct this issue.\n",
00746 error.message);
00747 #endif
00748
00749 dbus_error_free (&error);
00750
00751 _dbus_generate_uuid (&machine_uuid);
00752 }
00753 }
00754
00755 ok = _dbus_uuid_encode (&machine_uuid, uuid_str);
00756
00757 _DBUS_UNLOCK (machine_uuid);
00758
00759 return ok;
00760 }
00761
00762 #ifdef DBUS_BUILD_TESTS
00763
00769 const char *
00770 _dbus_header_field_to_string (int header_field)
00771 {
00772 switch (header_field)
00773 {
00774 case DBUS_HEADER_FIELD_INVALID:
00775 return "invalid";
00776 case DBUS_HEADER_FIELD_PATH:
00777 return "path";
00778 case DBUS_HEADER_FIELD_INTERFACE:
00779 return "interface";
00780 case DBUS_HEADER_FIELD_MEMBER:
00781 return "member";
00782 case DBUS_HEADER_FIELD_ERROR_NAME:
00783 return "error-name";
00784 case DBUS_HEADER_FIELD_REPLY_SERIAL:
00785 return "reply-serial";
00786 case DBUS_HEADER_FIELD_DESTINATION:
00787 return "destination";
00788 case DBUS_HEADER_FIELD_SENDER:
00789 return "sender";
00790 case DBUS_HEADER_FIELD_SIGNATURE:
00791 return "signature";
00792 default:
00793 return "unknown";
00794 }
00795 }
00796 #endif
00797
00798 #ifndef DBUS_DISABLE_CHECKS
00799
00800 const char _dbus_return_if_fail_warning_format[] =
00801 "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
00802 "This is normally a bug in some application using the D-Bus library.\n";
00803 #endif
00804
00805 #ifndef DBUS_DISABLE_ASSERT
00806
00818 void
00819 _dbus_real_assert (dbus_bool_t condition,
00820 const char *condition_text,
00821 const char *file,
00822 int line,
00823 const char *func)
00824 {
00825 if (_DBUS_UNLIKELY (!condition))
00826 {
00827 _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
00828 _dbus_pid_for_log (), condition_text, file, line, func);
00829 _dbus_abort ();
00830 }
00831 }
00832
00843 void
00844 _dbus_real_assert_not_reached (const char *explanation,
00845 const char *file,
00846 int line)
00847 {
00848 _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
00849 file, line, _dbus_pid_for_log (), explanation);
00850 _dbus_abort ();
00851 }
00852 #endif
00853
00854 #ifdef DBUS_BUILD_TESTS
00855 static dbus_bool_t
00856 run_failing_each_malloc (int n_mallocs,
00857 const char *description,
00858 DBusTestMemoryFunction func,
00859 void *data)
00860 {
00861 n_mallocs += 10;
00862
00863 while (n_mallocs >= 0)
00864 {
00865 _dbus_set_fail_alloc_counter (n_mallocs);
00866
00867 _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n",
00868 description, n_mallocs,
00869 _dbus_get_fail_alloc_failures ());
00870
00871 if (!(* func) (data))
00872 return FALSE;
00873
00874 n_mallocs -= 1;
00875 }
00876
00877 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00878
00879 return TRUE;
00880 }
00881
00895 dbus_bool_t
00896 _dbus_test_oom_handling (const char *description,
00897 DBusTestMemoryFunction func,
00898 void *data)
00899 {
00900 int approx_mallocs;
00901 const char *setting;
00902 int max_failures_to_try;
00903 int i;
00904
00905
00906
00907 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
00908
00909 _dbus_verbose ("Running once to count mallocs\n");
00910
00911 if (!(* func) (data))
00912 return FALSE;
00913
00914 approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
00915
00916 _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n",
00917 description, approx_mallocs);
00918
00919 setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
00920 if (setting != NULL)
00921 {
00922 DBusString str;
00923 long v;
00924 _dbus_string_init_const (&str, setting);
00925 v = 4;
00926 if (!_dbus_string_parse_int (&str, 0, &v, NULL))
00927 _dbus_warn ("couldn't parse '%s' as integer\n", setting);
00928 max_failures_to_try = v;
00929 }
00930 else
00931 {
00932 max_failures_to_try = 4;
00933 }
00934
00935 i = setting ? max_failures_to_try - 1 : 1;
00936 while (i < max_failures_to_try)
00937 {
00938 _dbus_set_fail_alloc_failures (i);
00939 if (!run_failing_each_malloc (approx_mallocs, description, func, data))
00940 return FALSE;
00941 ++i;
00942 }
00943
00944 _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n",
00945 description);
00946
00947 return TRUE;
00948 }
00949 #endif
00950