1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 2 /* dbus-internals.c random utility stuff (internal to D-Bus implementation) 3 * 4 * Copyright (C) 2002, 2003 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 2.1 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 #include <config.h> 25 #include "dbus-internals.h" 26 #include "dbus-protocol.h" 27 #include "dbus-marshal-basic.h" 28 #include "dbus-test.h" 29 #include "dbus-valgrind-internal.h" 30 #include <stdio.h> 31 #include <stdarg.h> 32 #include <string.h> 33 #include <stdlib.h> 34 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING 35 #include <windows.h> 36 #include <mbstring.h> 37 #endif 38 39 #ifdef DBUS_ANDROID_LOG 40 #define LOG_TAG "libdbus" 41 #include <cutils/log.h> 42 #endif /* DBUS_ANDROID_LOG */ 43 44 /** 45 * @defgroup DBusInternals D-Bus secret internal implementation details 46 * @brief Documentation useful when developing or debugging D-Bus itself. 47 * 48 */ 49 50 /** 51 * @defgroup DBusInternalsUtils Utilities and portability 52 * @ingroup DBusInternals 53 * @brief Utility functions (_dbus_assert(), _dbus_warn(), etc.) 54 * @{ 55 */ 56 57 /** 58 * @def _dbus_assert 59 * 60 * Aborts with an error message if the condition is false. 61 * 62 * @param condition condition which must be true. 63 */ 64 65 /** 66 * @def _dbus_assert_not_reached 67 * 68 * Aborts with an error message if called. 69 * The given explanation will be printed. 70 * 71 * @param explanation explanation of what happened if the code was reached. 72 */ 73 74 /** 75 * @def _DBUS_N_ELEMENTS 76 * 77 * Computes the number of elements in a fixed-size array using 78 * sizeof(). 79 * 80 * @param array the array to count elements in. 81 */ 82 83 /** 84 * @def _DBUS_POINTER_TO_INT 85 * 86 * Safely casts a void* to an integer; should only be used on void* 87 * that actually contain integers, for example one created with 88 * _DBUS_INT_TO_POINTER. Only guaranteed to preserve 32 bits. 89 * (i.e. it's used to store 32-bit ints in pointers, but 90 * can't be used to store 64-bit pointers in ints.) 91 * 92 * @param pointer pointer to extract an integer from. 93 */ 94 /** 95 * @def _DBUS_INT_TO_POINTER 96 * 97 * Safely stuffs an integer into a pointer, to be extracted later with 98 * _DBUS_POINTER_TO_INT. Only guaranteed to preserve 32 bits. 99 * 100 * @param integer the integer to stuff into a pointer. 101 */ 102 /** 103 * @def _DBUS_ZERO 104 * 105 * Sets all bits in an object to zero. 106 * 107 * @param object the object to be zeroed. 108 */ 109 /** 110 * @def _DBUS_INT16_MIN 111 * 112 * Minimum value of type "int16" 113 */ 114 /** 115 * @def _DBUS_INT16_MAX 116 * 117 * Maximum value of type "int16" 118 */ 119 /** 120 * @def _DBUS_UINT16_MAX 121 * 122 * Maximum value of type "uint16" 123 */ 124 125 /** 126 * @def _DBUS_INT32_MIN 127 * 128 * Minimum value of type "int32" 129 */ 130 /** 131 * @def _DBUS_INT32_MAX 132 * 133 * Maximum value of type "int32" 134 */ 135 /** 136 * @def _DBUS_UINT32_MAX 137 * 138 * Maximum value of type "uint32" 139 */ 140 141 /** 142 * @def _DBUS_INT_MIN 143 * 144 * Minimum value of type "int" 145 */ 146 /** 147 * @def _DBUS_INT_MAX 148 * 149 * Maximum value of type "int" 150 */ 151 /** 152 * @def _DBUS_UINT_MAX 153 * 154 * Maximum value of type "uint" 155 */ 156 157 /** 158 * @typedef DBusForeachFunction 159 * 160 * Used to iterate over each item in a collection, such as 161 * a DBusList. 162 */ 163 164 /** 165 * @def _DBUS_LOCK_NAME 166 * 167 * Expands to name of a global lock variable. 168 */ 169 170 /** 171 * @def _DBUS_DEFINE_GLOBAL_LOCK 172 * 173 * Defines a global lock variable with the given name. 174 * The lock must be added to the list to initialize 175 * in dbus_threads_init(). 176 */ 177 178 /** 179 * @def _DBUS_DECLARE_GLOBAL_LOCK 180 * 181 * Expands to declaration of a global lock defined 182 * with _DBUS_DEFINE_GLOBAL_LOCK. 183 * The lock must be added to the list to initialize 184 * in dbus_threads_init(). 185 */ 186 187 /** 188 * @def _DBUS_LOCK 189 * 190 * Locks a global lock 191 */ 192 193 /** 194 * @def _DBUS_UNLOCK 195 * 196 * Unlocks a global lock 197 */ 198 199 /** 200 * Fixed "out of memory" error message, just to avoid 201 * making up a different string every time and wasting 202 * space. 203 */ 204 const char *_dbus_no_memory_message = "Not enough memory"; 205 206 static dbus_bool_t warn_initted = FALSE; 207 static dbus_bool_t fatal_warnings = FALSE; 208 static dbus_bool_t fatal_warnings_on_check_failed = TRUE; 209 210 static void 211 init_warnings(void) 212 { 213 if (!warn_initted) 214 { 215 const char *s; 216 s = _dbus_getenv ("DBUS_FATAL_WARNINGS"); 217 if (s && *s) 218 { 219 if (*s == '0') 220 { 221 fatal_warnings = FALSE; 222 fatal_warnings_on_check_failed = FALSE; 223 } 224 else if (*s == '1') 225 { 226 fatal_warnings = TRUE; 227 fatal_warnings_on_check_failed = TRUE; 228 } 229 else 230 { 231 fprintf(stderr, "DBUS_FATAL_WARNINGS should be set to 0 or 1 if set, not '%s'", 232 s); 233 } 234 } 235 236 warn_initted = TRUE; 237 } 238 } 239 240 /** 241 * Prints a warning message to stderr. Can optionally be made to exit 242 * fatally by setting DBUS_FATAL_WARNINGS, but this is rarely 243 * used. This function should be considered pretty much equivalent to 244 * fprintf(stderr). _dbus_warn_check_failed() on the other hand is 245 * suitable for use when a programming mistake has been made. 246 * 247 * @param format printf-style format string. 248 */ 249 void 250 _dbus_warn (const char *format, 251 ...) 252 { 253 va_list args; 254 255 if (!warn_initted) 256 init_warnings (); 257 258 va_start (args, format); 259 #ifdef DBUS_ANDROID_LOG 260 LOG_PRI_VA(ANDROID_LOG_WARN, LOG_TAG, format, args); 261 #else 262 vfprintf (stderr, format, args); 263 #endif /* DBUS_ANDROID_LOG */ 264 va_end (args); 265 266 if (fatal_warnings) 267 { 268 fflush (stderr); 269 _dbus_abort (); 270 } 271 } 272 273 /** 274 * Prints a "critical" warning to stderr when an assertion fails; 275 * differs from _dbus_warn primarily in that it prefixes the pid and 276 * defaults to fatal. This should be used only when a programming 277 * error has been detected. (NOT for unavoidable errors that an app 278 * might handle - those should be returned as DBusError.) Calling this 279 * means "there is a bug" 280 */ 281 void 282 _dbus_warn_check_failed(const char *format, 283 ...) 284 { 285 va_list args; 286 287 if (!warn_initted) 288 init_warnings (); 289 290 fprintf (stderr, "process %lu: ", _dbus_pid_for_log ()); 291 292 va_start (args, format); 293 #ifdef DBUS_ANDROID_LOG 294 LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args); 295 #else 296 vfprintf (stderr, format, args); 297 #endif /* DBUS_ANDROID_LOG */ 298 va_end (args); 299 300 if (fatal_warnings_on_check_failed) 301 { 302 fflush (stderr); 303 _dbus_abort (); 304 } 305 } 306 307 #ifdef DBUS_ENABLE_VERBOSE_MODE 308 309 static dbus_bool_t verbose_initted = FALSE; 310 static dbus_bool_t verbose = TRUE; 311 312 /** Whether to show the current thread in verbose messages */ 313 #define PTHREAD_IN_VERBOSE 0 314 #if PTHREAD_IN_VERBOSE 315 #include <pthread.h> 316 #endif 317 318 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING 319 static char module_name[1024]; 320 #endif 321 322 static inline void 323 _dbus_verbose_init (void) 324 { 325 if (!verbose_initted) 326 { 327 #ifdef DBUS_ANDROID_LOG 328 /* Don't bother checking environment variable - just print the 329 verbose logs (can still be disabled with DBUS_ENABLE_VERBOSE_MODE) */ 330 verbose = TRUE; 331 #else 332 const char *p = _dbus_getenv ("DBUS_VERBOSE"); 333 verbose = p != NULL && *p == '1'; 334 #endif 335 verbose_initted = TRUE; 336 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING 337 { 338 char *last_period, *last_slash; 339 GetModuleFileName(0,module_name,sizeof(module_name)-1); 340 last_period = _mbsrchr(module_name,'.'); 341 if (last_period) 342 *last_period ='\0'; 343 last_slash = _mbsrchr(module_name,'\\'); 344 if (last_slash) 345 strcpy(module_name,last_slash+1); 346 strcat(module_name,": "); 347 } 348 #endif 349 } 350 } 351 352 /** @def DBUS_IS_DIR_SEPARATOR(c) 353 * macro for checking if character c is a patch separator 354 * 355 * @todo move to a header file so that others can use this too 356 */ 357 #ifdef DBUS_WIN 358 #define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/') 359 #else 360 #define DBUS_IS_DIR_SEPARATOR(c) (c == '/') 361 #endif 362 363 /** 364 remove source root from file path 365 the source root is determined by 366 */ 367 static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level) 368 { 369 static int prefix = -1; 370 371 if (prefix == -1) 372 { 373 char *p = (char *)file + strlen(file); 374 int i = 0; 375 prefix = 0; 376 for (;p >= file;p--) 377 { 378 if (DBUS_IS_DIR_SEPARATOR(*p)) 379 { 380 if (++i >= level) 381 { 382 prefix = p-file+1; 383 break; 384 } 385 } 386 } 387 } 388 return (char *)file+prefix; 389 } 390 391 /** 392 * Implementation of dbus_is_verbose() macro if built with verbose logging 393 * enabled. 394 * @returns whether verbose logging is active. 395 */ 396 dbus_bool_t 397 _dbus_is_verbose_real (void) 398 { 399 _dbus_verbose_init (); 400 return verbose; 401 } 402 403 /** 404 * Prints a warning message to stderr 405 * if the user has enabled verbose mode. 406 * This is the real function implementation, 407 * use _dbus_verbose() macro in code. 408 * 409 * @param format printf-style format string. 410 */ 411 void 412 _dbus_verbose_real ( 413 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS 414 const char *file, 415 const int line, 416 const char *function, 417 #endif 418 const char *format, 419 ...) 420 { 421 va_list args; 422 static dbus_bool_t need_pid = TRUE; 423 int len; 424 425 /* things are written a bit oddly here so that 426 * in the non-verbose case we just have the one 427 * conditional and return immediately. 428 */ 429 if (!_dbus_is_verbose_real()) 430 return; 431 432 #ifndef DBUS_USE_OUTPUT_DEBUG_STRING 433 /* Print out pid before the line */ 434 if (need_pid) 435 { 436 #if PTHREAD_IN_VERBOSE 437 fprintf (stderr, "%lu: 0x%lx: ", _dbus_pid_for_log (), pthread_self ()); 438 #else 439 fprintf (stderr, "%lu: ", _dbus_pid_for_log ()); 440 #endif 441 } 442 #endif 443 444 /* Only print pid again if the next line is a new line */ 445 len = strlen (format); 446 if (format[len-1] == '\n') 447 need_pid = TRUE; 448 else 449 need_pid = FALSE; 450 451 va_start (args, format); 452 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING 453 { 454 char buf[1024]; 455 strcpy(buf,module_name); 456 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS 457 sprintf (buf+strlen(buf), "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function); 458 #endif 459 vsprintf (buf+strlen(buf),format, args); 460 va_end (args); 461 OutputDebugStringA(buf); 462 } 463 #else 464 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS 465 fprintf (stderr, "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function); 466 #endif 467 468 #ifdef DBUS_ANDROID_LOG 469 LOG_PRI_VA(ANDROID_LOG_DEBUG, LOG_TAG, format, args); 470 #else 471 vfprintf (stderr, format, args); 472 #endif /* DBUS_ANDROID_LOG */ 473 va_end (args); 474 475 fflush (stderr); 476 #endif 477 } 478 479 /** 480 * Reinitializes the verbose logging code, used 481 * as a hack in dbus-spawn.c so that a child 482 * process re-reads its pid 483 * 484 */ 485 void 486 _dbus_verbose_reset_real (void) 487 { 488 verbose_initted = FALSE; 489 } 490 491 void 492 _dbus_trace_ref (const char *obj_name, 493 void *obj, 494 int old_refcount, 495 int new_refcount, 496 const char *why, 497 const char *env_var, 498 int *enabled) 499 { 500 _dbus_assert (obj_name != NULL); 501 _dbus_assert (obj != NULL); 502 _dbus_assert (old_refcount >= -1); 503 _dbus_assert (new_refcount >= -1); 504 505 if (old_refcount == -1) 506 { 507 _dbus_assert (new_refcount == -1); 508 } 509 else 510 { 511 _dbus_assert (new_refcount >= 0); 512 _dbus_assert (old_refcount >= 0); 513 _dbus_assert (old_refcount > 0 || new_refcount > 0); 514 } 515 516 _dbus_assert (why != NULL); 517 _dbus_assert (env_var != NULL); 518 _dbus_assert (enabled != NULL); 519 520 if (*enabled < 0) 521 { 522 const char *s = _dbus_getenv (env_var); 523 524 *enabled = FALSE; 525 526 if (s && *s) 527 { 528 if (*s == '0') 529 *enabled = FALSE; 530 else if (*s == '1') 531 *enabled = TRUE; 532 else 533 _dbus_warn ("%s should be 0 or 1 if set, not '%s'", env_var, s); 534 } 535 } 536 537 if (*enabled) 538 { 539 if (old_refcount == -1) 540 { 541 VALGRIND_PRINTF_BACKTRACE ("%s %p ref stolen (%s)", 542 obj_name, obj, why); 543 _dbus_verbose ("%s %p ref stolen (%s)", 544 obj_name, obj, why); 545 } 546 else 547 { 548 VALGRIND_PRINTF_BACKTRACE ("%s %p %d -> %d refs (%s)", 549 obj_name, obj, 550 old_refcount, new_refcount, why); 551 _dbus_verbose ("%s %p %d -> %d refs (%s)", 552 obj_name, obj, old_refcount, new_refcount, why); 553 } 554 } 555 } 556 557 #endif /* DBUS_ENABLE_VERBOSE_MODE */ 558 559 /** 560 * Duplicates a string. Result must be freed with 561 * dbus_free(). Returns #NULL if memory allocation fails. 562 * If the string to be duplicated is #NULL, returns #NULL. 563 * 564 * @param str string to duplicate. 565 * @returns newly-allocated copy. 566 */ 567 char* 568 _dbus_strdup (const char *str) 569 { 570 size_t len; 571 char *copy; 572 573 if (str == NULL) 574 return NULL; 575 576 len = strlen (str); 577 578 copy = dbus_malloc (len + 1); 579 if (copy == NULL) 580 return NULL; 581 582 memcpy (copy, str, len + 1); 583 584 return copy; 585 } 586 587 /** 588 * Duplicates a block of memory. Returns 589 * #NULL on failure. 590 * 591 * @param mem memory to copy 592 * @param n_bytes number of bytes to copy 593 * @returns the copy 594 */ 595 void* 596 _dbus_memdup (const void *mem, 597 size_t n_bytes) 598 { 599 void *copy; 600 601 copy = dbus_malloc (n_bytes); 602 if (copy == NULL) 603 return NULL; 604 605 memcpy (copy, mem, n_bytes); 606 607 return copy; 608 } 609 610 /** 611 * Duplicates a string array. Result may be freed with 612 * dbus_free_string_array(). Returns #NULL if memory allocation fails. 613 * If the array to be duplicated is #NULL, returns #NULL. 614 * 615 * @param array array to duplicate. 616 * @returns newly-allocated copy. 617 */ 618 char** 619 _dbus_dup_string_array (const char **array) 620 { 621 int len; 622 int i; 623 char **copy; 624 625 if (array == NULL) 626 return NULL; 627 628 for (len = 0; array[len] != NULL; ++len) 629 ; 630 631 copy = dbus_new0 (char*, len + 1); 632 if (copy == NULL) 633 return NULL; 634 635 i = 0; 636 while (i < len) 637 { 638 copy[i] = _dbus_strdup (array[i]); 639 if (copy[i] == NULL) 640 { 641 dbus_free_string_array (copy); 642 return NULL; 643 } 644 645 ++i; 646 } 647 648 return copy; 649 } 650 651 /** 652 * Checks whether a string array contains the given string. 653 * 654 * @param array array to search. 655 * @param str string to look for 656 * @returns #TRUE if array contains string 657 */ 658 dbus_bool_t 659 _dbus_string_array_contains (const char **array, 660 const char *str) 661 { 662 int i; 663 664 i = 0; 665 while (array[i] != NULL) 666 { 667 if (strcmp (array[i], str) == 0) 668 return TRUE; 669 ++i; 670 } 671 672 return FALSE; 673 } 674 675 /** 676 * Generates a new UUID. If you change how this is done, 677 * there's some text about it in the spec that should also change. 678 * 679 * @param uuid the uuid to initialize 680 */ 681 void 682 _dbus_generate_uuid (DBusGUID *uuid) 683 { 684 long now; 685 686 /* don't use monotonic time because the UUID may be saved to disk, e.g. 687 * it may persist across reboots 688 */ 689 _dbus_get_real_time (&now, NULL); 690 691 uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now); 692 693 _dbus_generate_random_bytes_buffer (uuid->as_bytes, DBUS_UUID_LENGTH_BYTES - 4); 694 } 695 696 /** 697 * Hex-encode a UUID. 698 * 699 * @param uuid the uuid 700 * @param encoded string to append hex uuid to 701 * @returns #FALSE if no memory 702 */ 703 dbus_bool_t 704 _dbus_uuid_encode (const DBusGUID *uuid, 705 DBusString *encoded) 706 { 707 DBusString binary; 708 _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES); 709 return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded)); 710 } 711 712 static dbus_bool_t 713 _dbus_read_uuid_file_without_creating (const DBusString *filename, 714 DBusGUID *uuid, 715 DBusError *error) 716 { 717 DBusString contents; 718 DBusString decoded; 719 int end; 720 721 if (!_dbus_string_init (&contents)) 722 { 723 _DBUS_SET_OOM (error); 724 return FALSE; 725 } 726 727 if (!_dbus_string_init (&decoded)) 728 { 729 _dbus_string_free (&contents); 730 _DBUS_SET_OOM (error); 731 return FALSE; 732 } 733 734 if (!_dbus_file_get_contents (&contents, filename, error)) 735 goto error; 736 737 _dbus_string_chop_white (&contents); 738 739 if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX) 740 { 741 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT, 742 "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text", 743 _dbus_string_get_const_data (filename), 744 DBUS_UUID_LENGTH_HEX, 745 _dbus_string_get_length (&contents)); 746 goto error; 747 } 748 749 if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0)) 750 { 751 _DBUS_SET_OOM (error); 752 goto error; 753 } 754 755 if (end == 0) 756 { 757 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT, 758 "UUID file '%s' contains invalid hex data", 759 _dbus_string_get_const_data (filename)); 760 goto error; 761 } 762 763 if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES) 764 { 765 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT, 766 "UUID file '%s' contains %d bytes of hex-encoded data instead of %d", 767 _dbus_string_get_const_data (filename), 768 _dbus_string_get_length (&decoded), 769 DBUS_UUID_LENGTH_BYTES); 770 goto error; 771 } 772 773 _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES); 774 775 _dbus_string_free (&decoded); 776 _dbus_string_free (&contents); 777 778 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 779 780 return TRUE; 781 782 error: 783 _DBUS_ASSERT_ERROR_IS_SET (error); 784 _dbus_string_free (&contents); 785 _dbus_string_free (&decoded); 786 return FALSE; 787 } 788 789 static dbus_bool_t 790 _dbus_create_uuid_file_exclusively (const DBusString *filename, 791 DBusGUID *uuid, 792 DBusError *error) 793 { 794 DBusString encoded; 795 796 if (!_dbus_string_init (&encoded)) 797 { 798 _DBUS_SET_OOM (error); 799 return FALSE; 800 } 801 802 _dbus_generate_uuid (uuid); 803 804 if (!_dbus_uuid_encode (uuid, &encoded)) 805 { 806 _DBUS_SET_OOM (error); 807 goto error; 808 } 809 810 if (!_dbus_string_append_byte (&encoded, '\n')) 811 { 812 _DBUS_SET_OOM (error); 813 goto error; 814 } 815 816 if (!_dbus_string_save_to_file (&encoded, filename, TRUE, error)) 817 goto error; 818 819 _dbus_string_free (&encoded); 820 821 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 822 return TRUE; 823 824 error: 825 _DBUS_ASSERT_ERROR_IS_SET (error); 826 _dbus_string_free (&encoded); 827 return FALSE; 828 } 829 830 /** 831 * Reads (and optionally writes) a uuid to a file. Initializes the uuid 832 * unless an error is returned. 833 * 834 * @param filename the name of the file 835 * @param uuid uuid to be initialized with the loaded uuid 836 * @param create_if_not_found #TRUE to create a new uuid and save it if the file doesn't exist 837 * @param error the error return 838 * @returns #FALSE if the error is set 839 */ 840 dbus_bool_t 841 _dbus_read_uuid_file (const DBusString *filename, 842 DBusGUID *uuid, 843 dbus_bool_t create_if_not_found, 844 DBusError *error) 845 { 846 DBusError read_error = DBUS_ERROR_INIT; 847 848 if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error)) 849 return TRUE; 850 851 if (!create_if_not_found) 852 { 853 dbus_move_error (&read_error, error); 854 return FALSE; 855 } 856 857 /* If the file exists and contains junk, we want to keep that error 858 * message instead of overwriting it with a "file exists" error 859 * message when we try to write 860 */ 861 if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT)) 862 { 863 dbus_move_error (&read_error, error); 864 return FALSE; 865 } 866 else 867 { 868 dbus_error_free (&read_error); 869 return _dbus_create_uuid_file_exclusively (filename, uuid, error); 870 } 871 } 872 873 _DBUS_DEFINE_GLOBAL_LOCK (machine_uuid); 874 static int machine_uuid_initialized_generation = 0; 875 static DBusGUID machine_uuid; 876 877 /** 878 * Gets the hex-encoded UUID of the machine this function is 879 * executed on. This UUID is guaranteed to be the same for a given 880 * machine at least until it next reboots, though it also 881 * makes some effort to be the same forever, it may change if the 882 * machine is reconfigured or its hardware is modified. 883 * 884 * @param uuid_str string to append hex-encoded machine uuid to 885 * @returns #FALSE if no memory 886 */ 887 dbus_bool_t 888 _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str) 889 { 890 dbus_bool_t ok; 891 892 _DBUS_LOCK (machine_uuid); 893 if (machine_uuid_initialized_generation != _dbus_current_generation) 894 { 895 DBusError error = DBUS_ERROR_INIT; 896 897 if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE, 898 &error)) 899 { 900 #ifndef DBUS_BUILD_TESTS 901 /* For the test suite, we may not be installed so just continue silently 902 * here. But in a production build, we want to be nice and loud about 903 * this. 904 */ 905 _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n" 906 "See the manual page for dbus-uuidgen to correct this issue.\n", 907 error.message); 908 #endif 909 910 dbus_error_free (&error); 911 912 _dbus_generate_uuid (&machine_uuid); 913 } 914 } 915 916 ok = _dbus_uuid_encode (&machine_uuid, uuid_str); 917 918 _DBUS_UNLOCK (machine_uuid); 919 920 return ok; 921 } 922 923 #ifndef DBUS_DISABLE_CHECKS 924 /** String used in _dbus_return_if_fail macro */ 925 const char *_dbus_return_if_fail_warning_format = 926 "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n" 927 "This is normally a bug in some application using the D-Bus library.\n"; 928 #endif 929 930 #ifndef DBUS_DISABLE_ASSERT 931 /** 932 * Internals of _dbus_assert(); it's a function 933 * rather than a macro with the inline code so 934 * that the assertion failure blocks don't show up 935 * in test suite coverage, and to shrink code size. 936 * 937 * @param condition TRUE if assertion succeeded 938 * @param condition_text condition as a string 939 * @param file file the assertion is in 940 * @param line line the assertion is in 941 * @param func function the assertion is in 942 */ 943 void 944 _dbus_real_assert (dbus_bool_t condition, 945 const char *condition_text, 946 const char *file, 947 int line, 948 const char *func) 949 { 950 if (_DBUS_UNLIKELY (!condition)) 951 { 952 _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n", 953 _dbus_pid_for_log (), condition_text, file, line, func); 954 _dbus_abort (); 955 } 956 } 957 958 /** 959 * Internals of _dbus_assert_not_reached(); it's a function 960 * rather than a macro with the inline code so 961 * that the assertion failure blocks don't show up 962 * in test suite coverage, and to shrink code size. 963 * 964 * @param explanation what was reached that shouldn't have been 965 * @param file file the assertion is in 966 * @param line line the assertion is in 967 */ 968 void 969 _dbus_real_assert_not_reached (const char *explanation, 970 const char *file, 971 int line) 972 { 973 _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n", 974 file, line, _dbus_pid_for_log (), explanation); 975 _dbus_abort (); 976 } 977 #endif /* DBUS_DISABLE_ASSERT */ 978 979 #ifdef DBUS_BUILD_TESTS 980 static dbus_bool_t 981 run_failing_each_malloc (int n_mallocs, 982 const char *description, 983 DBusTestMemoryFunction func, 984 void *data) 985 { 986 n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */ 987 988 while (n_mallocs >= 0) 989 { 990 _dbus_set_fail_alloc_counter (n_mallocs); 991 992 _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n", 993 description, n_mallocs, 994 _dbus_get_fail_alloc_failures ()); 995 996 if (!(* func) (data)) 997 return FALSE; 998 999 n_mallocs -= 1; 1000 } 1001 1002 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); 1003 1004 return TRUE; 1005 } 1006 1007 /** 1008 * Tests how well the given function responds to out-of-memory 1009 * situations. Calls the function repeatedly, failing a different 1010 * call to malloc() each time. If the function ever returns #FALSE, 1011 * the test fails. The function should return #TRUE whenever something 1012 * valid (such as returning an error, or succeeding) occurs, and #FALSE 1013 * if it gets confused in some way. 1014 * 1015 * @param description description of the test used in verbose output 1016 * @param func function to call 1017 * @param data data to pass to function 1018 * @returns #TRUE if the function never returns FALSE 1019 */ 1020 dbus_bool_t 1021 _dbus_test_oom_handling (const char *description, 1022 DBusTestMemoryFunction func, 1023 void *data) 1024 { 1025 int approx_mallocs; 1026 const char *setting; 1027 int max_failures_to_try; 1028 int i; 1029 1030 /* Run once to see about how many mallocs are involved */ 1031 1032 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); 1033 1034 _dbus_verbose ("Running once to count mallocs\n"); 1035 1036 if (!(* func) (data)) 1037 return FALSE; 1038 1039 approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter (); 1040 1041 _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n", 1042 description, approx_mallocs); 1043 1044 setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES"); 1045 if (setting != NULL) 1046 { 1047 DBusString str; 1048 long v; 1049 _dbus_string_init_const (&str, setting); 1050 v = 4; 1051 if (!_dbus_string_parse_int (&str, 0, &v, NULL)) 1052 _dbus_warn ("couldn't parse '%s' as integer\n", setting); 1053 max_failures_to_try = v; 1054 } 1055 else 1056 { 1057 max_failures_to_try = 4; 1058 } 1059 1060 i = setting ? max_failures_to_try - 1 : 1; 1061 while (i < max_failures_to_try) 1062 { 1063 _dbus_set_fail_alloc_failures (i); 1064 if (!run_failing_each_malloc (approx_mallocs, description, func, data)) 1065 return FALSE; 1066 ++i; 1067 } 1068 1069 _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n", 1070 description); 1071 1072 return TRUE; 1073 } 1074 #endif /* DBUS_BUILD_TESTS */ 1075 1076 /** @} */ 1077