D-Bus
1.10.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-internals.c random utility stuff (internal to D-Bus implementation) 00003 * 00004 * Copyright (C) 2002, 2003 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 00024 #include <config.h> 00025 #include "dbus-internals.h" 00026 #include "dbus-protocol.h" 00027 #include "dbus-marshal-basic.h" 00028 #include "dbus-test.h" 00029 #include "dbus-valgrind-internal.h" 00030 #include <stdio.h> 00031 #include <stdarg.h> 00032 #include <string.h> 00033 #include <stdlib.h> 00034 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING 00035 #include <windows.h> 00036 #include <mbstring.h> 00037 #endif 00038 00184 const char *_dbus_no_memory_message = "Not enough memory"; 00185 00186 static dbus_bool_t warn_initted = FALSE; 00187 static dbus_bool_t fatal_warnings = FALSE; 00188 static dbus_bool_t fatal_warnings_on_check_failed = TRUE; 00189 00190 static void 00191 init_warnings(void) 00192 { 00193 if (!warn_initted) 00194 { 00195 const char *s; 00196 s = _dbus_getenv ("DBUS_FATAL_WARNINGS"); 00197 if (s && *s) 00198 { 00199 if (*s == '0') 00200 { 00201 fatal_warnings = FALSE; 00202 fatal_warnings_on_check_failed = FALSE; 00203 } 00204 else if (*s == '1') 00205 { 00206 fatal_warnings = TRUE; 00207 fatal_warnings_on_check_failed = TRUE; 00208 } 00209 else 00210 { 00211 fprintf(stderr, "DBUS_FATAL_WARNINGS should be set to 0 or 1 if set, not '%s'", 00212 s); 00213 } 00214 } 00215 00216 warn_initted = TRUE; 00217 } 00218 } 00219 00229 void 00230 _dbus_warn (const char *format, 00231 ...) 00232 { 00233 va_list args; 00234 00235 if (!warn_initted) 00236 init_warnings (); 00237 00238 va_start (args, format); 00239 vfprintf (stderr, format, args); 00240 va_end (args); 00241 00242 if (fatal_warnings) 00243 { 00244 fflush (stderr); 00245 _dbus_abort (); 00246 } 00247 } 00248 00257 void 00258 _dbus_warn_check_failed(const char *format, 00259 ...) 00260 { 00261 va_list args; 00262 00263 if (!warn_initted) 00264 init_warnings (); 00265 00266 fprintf (stderr, "process %lu: ", _dbus_pid_for_log ()); 00267 00268 va_start (args, format); 00269 vfprintf (stderr, format, args); 00270 va_end (args); 00271 00272 if (fatal_warnings_on_check_failed) 00273 { 00274 fflush (stderr); 00275 _dbus_abort (); 00276 } 00277 } 00278 00279 #ifdef DBUS_ENABLE_VERBOSE_MODE 00280 00281 static dbus_bool_t verbose_initted = FALSE; 00282 static dbus_bool_t verbose = TRUE; 00283 00285 #define PTHREAD_IN_VERBOSE 0 00286 #if PTHREAD_IN_VERBOSE 00287 #include <pthread.h> 00288 #endif 00289 00290 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING 00291 static char module_name[1024]; 00292 #endif 00293 00294 static inline void 00295 _dbus_verbose_init (void) 00296 { 00297 if (!verbose_initted) 00298 { 00299 const char *p = _dbus_getenv ("DBUS_VERBOSE"); 00300 verbose = p != NULL && *p == '1'; 00301 verbose_initted = TRUE; 00302 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING 00303 { 00304 char *last_period, *last_slash; 00305 GetModuleFileName(0,module_name,sizeof(module_name)-1); 00306 last_period = _mbsrchr(module_name,'.'); 00307 if (last_period) 00308 *last_period ='\0'; 00309 last_slash = _mbsrchr(module_name,'\\'); 00310 if (last_slash) 00311 strcpy(module_name,last_slash+1); 00312 strcat(module_name,": "); 00313 } 00314 #endif 00315 } 00316 } 00317 00323 #ifdef DBUS_WIN 00324 #define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/') 00325 #else 00326 #define DBUS_IS_DIR_SEPARATOR(c) (c == '/') 00327 #endif 00328 00333 static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level) 00334 { 00335 int prefix = 0; 00336 char *p = (char *)file + strlen(file); 00337 int i = 0; 00338 00339 for (;p >= file;p--) 00340 { 00341 if (DBUS_IS_DIR_SEPARATOR(*p)) 00342 { 00343 if (++i >= level) 00344 { 00345 prefix = p-file+1; 00346 break; 00347 } 00348 } 00349 } 00350 00351 return (char *)file+prefix; 00352 } 00353 00359 dbus_bool_t 00360 _dbus_is_verbose_real (void) 00361 { 00362 _dbus_verbose_init (); 00363 return verbose; 00364 } 00365 00366 void _dbus_set_verbose (dbus_bool_t state) 00367 { 00368 verbose = state; 00369 } 00370 00371 dbus_bool_t _dbus_get_verbose (void) 00372 { 00373 return verbose; 00374 } 00375 00384 void 00385 _dbus_verbose_real ( 00386 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS 00387 const char *file, 00388 const int line, 00389 const char *function, 00390 #endif 00391 const char *format, 00392 ...) 00393 { 00394 va_list args; 00395 static dbus_bool_t need_pid = TRUE; 00396 int len; 00397 00398 /* things are written a bit oddly here so that 00399 * in the non-verbose case we just have the one 00400 * conditional and return immediately. 00401 */ 00402 if (!_dbus_is_verbose_real()) 00403 return; 00404 00405 #ifndef DBUS_USE_OUTPUT_DEBUG_STRING 00406 /* Print out pid before the line */ 00407 if (need_pid) 00408 { 00409 #if PTHREAD_IN_VERBOSE 00410 fprintf (stderr, "%lu: 0x%lx: ", _dbus_pid_for_log (), pthread_self ()); 00411 #else 00412 fprintf (stderr, "%lu: ", _dbus_pid_for_log ()); 00413 #endif 00414 } 00415 #endif 00416 00417 /* Only print pid again if the next line is a new line */ 00418 len = strlen (format); 00419 if (format[len-1] == '\n') 00420 need_pid = TRUE; 00421 else 00422 need_pid = FALSE; 00423 00424 va_start (args, format); 00425 #ifdef DBUS_USE_OUTPUT_DEBUG_STRING 00426 { 00427 char buf[1024]; 00428 strcpy(buf,module_name); 00429 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS 00430 sprintf (buf+strlen(buf), "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function); 00431 #endif 00432 vsprintf (buf+strlen(buf),format, args); 00433 va_end (args); 00434 OutputDebugStringA(buf); 00435 } 00436 #else 00437 #ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS 00438 fprintf (stderr, "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function); 00439 #endif 00440 00441 vfprintf (stderr, format, args); 00442 va_end (args); 00443 00444 fflush (stderr); 00445 #endif 00446 } 00447 00454 void 00455 _dbus_verbose_reset_real (void) 00456 { 00457 verbose_initted = FALSE; 00458 } 00459 00460 void 00461 _dbus_trace_ref (const char *obj_name, 00462 void *obj, 00463 int old_refcount, 00464 int new_refcount, 00465 const char *why, 00466 const char *env_var, 00467 int *enabled) 00468 { 00469 _dbus_assert (obj_name != NULL); 00470 _dbus_assert (obj != NULL); 00471 _dbus_assert (old_refcount >= -1); 00472 _dbus_assert (new_refcount >= -1); 00473 00474 if (old_refcount == -1) 00475 { 00476 _dbus_assert (new_refcount == -1); 00477 } 00478 else 00479 { 00480 _dbus_assert (new_refcount >= 0); 00481 _dbus_assert (old_refcount >= 0); 00482 _dbus_assert (old_refcount > 0 || new_refcount > 0); 00483 } 00484 00485 _dbus_assert (why != NULL); 00486 _dbus_assert (env_var != NULL); 00487 _dbus_assert (enabled != NULL); 00488 00489 if (*enabled < 0) 00490 { 00491 const char *s = _dbus_getenv (env_var); 00492 00493 *enabled = FALSE; 00494 00495 if (s && *s) 00496 { 00497 if (*s == '0') 00498 *enabled = FALSE; 00499 else if (*s == '1') 00500 *enabled = TRUE; 00501 else 00502 _dbus_warn ("%s should be 0 or 1 if set, not '%s'", env_var, s); 00503 } 00504 } 00505 00506 if (*enabled) 00507 { 00508 if (old_refcount == -1) 00509 { 00510 VALGRIND_PRINTF_BACKTRACE ("%s %p ref stolen (%s)", 00511 obj_name, obj, why); 00512 _dbus_verbose ("%s %p ref stolen (%s)\n", 00513 obj_name, obj, why); 00514 } 00515 else 00516 { 00517 VALGRIND_PRINTF_BACKTRACE ("%s %p %d -> %d refs (%s)", 00518 obj_name, obj, 00519 old_refcount, new_refcount, why); 00520 _dbus_verbose ("%s %p %d -> %d refs (%s)\n", 00521 obj_name, obj, old_refcount, new_refcount, why); 00522 } 00523 } 00524 } 00525 00526 #endif /* DBUS_ENABLE_VERBOSE_MODE */ 00527 00536 char* 00537 _dbus_strdup (const char *str) 00538 { 00539 size_t len; 00540 char *copy; 00541 00542 if (str == NULL) 00543 return NULL; 00544 00545 len = strlen (str); 00546 00547 copy = dbus_malloc (len + 1); 00548 if (copy == NULL) 00549 return NULL; 00550 00551 memcpy (copy, str, len + 1); 00552 00553 return copy; 00554 } 00555 00564 void* 00565 _dbus_memdup (const void *mem, 00566 size_t n_bytes) 00567 { 00568 void *copy; 00569 00570 copy = dbus_malloc (n_bytes); 00571 if (copy == NULL) 00572 return NULL; 00573 00574 memcpy (copy, mem, n_bytes); 00575 00576 return copy; 00577 } 00578 00587 char** 00588 _dbus_dup_string_array (const char **array) 00589 { 00590 int len; 00591 int i; 00592 char **copy; 00593 00594 if (array == NULL) 00595 return NULL; 00596 00597 for (len = 0; array[len] != NULL; ++len) 00598 ; 00599 00600 copy = dbus_new0 (char*, len + 1); 00601 if (copy == NULL) 00602 return NULL; 00603 00604 i = 0; 00605 while (i < len) 00606 { 00607 copy[i] = _dbus_strdup (array[i]); 00608 if (copy[i] == NULL) 00609 { 00610 dbus_free_string_array (copy); 00611 return NULL; 00612 } 00613 00614 ++i; 00615 } 00616 00617 return copy; 00618 } 00619 00627 dbus_bool_t 00628 _dbus_string_array_contains (const char **array, 00629 const char *str) 00630 { 00631 int i; 00632 00633 i = 0; 00634 while (array[i] != NULL) 00635 { 00636 if (strcmp (array[i], str) == 0) 00637 return TRUE; 00638 ++i; 00639 } 00640 00641 return FALSE; 00642 } 00643 00652 dbus_bool_t 00653 _dbus_generate_uuid (DBusGUID *uuid, 00654 DBusError *error) 00655 { 00656 DBusError rand_error; 00657 long now; 00658 00659 dbus_error_init (&rand_error); 00660 00661 /* don't use monotonic time because the UUID may be saved to disk, e.g. 00662 * it may persist across reboots 00663 */ 00664 _dbus_get_real_time (&now, NULL); 00665 00666 uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now); 00667 00668 if (!_dbus_generate_random_bytes_buffer (uuid->as_bytes, 00669 DBUS_UUID_LENGTH_BYTES - 4, 00670 &rand_error)) 00671 { 00672 dbus_set_error (error, rand_error.name, 00673 "Failed to generate UUID: %s", rand_error.message); 00674 dbus_error_free (&rand_error); 00675 return FALSE; 00676 } 00677 00678 return TRUE; 00679 } 00680 00688 dbus_bool_t 00689 _dbus_uuid_encode (const DBusGUID *uuid, 00690 DBusString *encoded) 00691 { 00692 DBusString binary; 00693 _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES); 00694 return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded)); 00695 } 00696 00697 static dbus_bool_t 00698 _dbus_read_uuid_file_without_creating (const DBusString *filename, 00699 DBusGUID *uuid, 00700 DBusError *error) 00701 { 00702 DBusString contents; 00703 DBusString decoded; 00704 int end; 00705 00706 if (!_dbus_string_init (&contents)) 00707 { 00708 _DBUS_SET_OOM (error); 00709 return FALSE; 00710 } 00711 00712 if (!_dbus_string_init (&decoded)) 00713 { 00714 _dbus_string_free (&contents); 00715 _DBUS_SET_OOM (error); 00716 return FALSE; 00717 } 00718 00719 if (!_dbus_file_get_contents (&contents, filename, error)) 00720 goto error; 00721 00722 _dbus_string_chop_white (&contents); 00723 00724 if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX) 00725 { 00726 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT, 00727 "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text", 00728 _dbus_string_get_const_data (filename), 00729 DBUS_UUID_LENGTH_HEX, 00730 _dbus_string_get_length (&contents)); 00731 goto error; 00732 } 00733 00734 if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0)) 00735 { 00736 _DBUS_SET_OOM (error); 00737 goto error; 00738 } 00739 00740 if (end == 0) 00741 { 00742 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT, 00743 "UUID file '%s' contains invalid hex data", 00744 _dbus_string_get_const_data (filename)); 00745 goto error; 00746 } 00747 00748 if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES) 00749 { 00750 dbus_set_error (error, DBUS_ERROR_INVALID_FILE_CONTENT, 00751 "UUID file '%s' contains %d bytes of hex-encoded data instead of %d", 00752 _dbus_string_get_const_data (filename), 00753 _dbus_string_get_length (&decoded), 00754 DBUS_UUID_LENGTH_BYTES); 00755 goto error; 00756 } 00757 00758 _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES); 00759 00760 _dbus_string_free (&decoded); 00761 _dbus_string_free (&contents); 00762 00763 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00764 00765 return TRUE; 00766 00767 error: 00768 _DBUS_ASSERT_ERROR_IS_SET (error); 00769 _dbus_string_free (&contents); 00770 _dbus_string_free (&decoded); 00771 return FALSE; 00772 } 00773 00782 dbus_bool_t 00783 _dbus_write_uuid_file (const DBusString *filename, 00784 const DBusGUID *uuid, 00785 DBusError *error) 00786 { 00787 DBusString encoded; 00788 00789 if (!_dbus_string_init (&encoded)) 00790 { 00791 _DBUS_SET_OOM (error); 00792 return FALSE; 00793 } 00794 00795 if (!_dbus_uuid_encode (uuid, &encoded)) 00796 { 00797 _DBUS_SET_OOM (error); 00798 goto error; 00799 } 00800 00801 if (!_dbus_string_append_byte (&encoded, '\n')) 00802 { 00803 _DBUS_SET_OOM (error); 00804 goto error; 00805 } 00806 00807 if (!_dbus_string_save_to_file (&encoded, filename, TRUE, error)) 00808 goto error; 00809 00810 _dbus_string_free (&encoded); 00811 00812 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00813 return TRUE; 00814 00815 error: 00816 _DBUS_ASSERT_ERROR_IS_SET (error); 00817 _dbus_string_free (&encoded); 00818 return FALSE; 00819 } 00820 00831 dbus_bool_t 00832 _dbus_read_uuid_file (const DBusString *filename, 00833 DBusGUID *uuid, 00834 dbus_bool_t create_if_not_found, 00835 DBusError *error) 00836 { 00837 DBusError read_error = DBUS_ERROR_INIT; 00838 00839 if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error)) 00840 return TRUE; 00841 00842 if (!create_if_not_found) 00843 { 00844 dbus_move_error (&read_error, error); 00845 return FALSE; 00846 } 00847 00848 /* If the file exists and contains junk, we want to keep that error 00849 * message instead of overwriting it with a "file exists" error 00850 * message when we try to write 00851 */ 00852 if (dbus_error_has_name (&read_error, DBUS_ERROR_INVALID_FILE_CONTENT)) 00853 { 00854 dbus_move_error (&read_error, error); 00855 return FALSE; 00856 } 00857 else 00858 { 00859 dbus_error_free (&read_error); 00860 00861 if (!_dbus_generate_uuid (uuid, error)) 00862 return FALSE; 00863 00864 return _dbus_write_uuid_file (filename, uuid, error); 00865 } 00866 } 00867 00868 /* Protected by _DBUS_LOCK (machine_uuid) */ 00869 static int machine_uuid_initialized_generation = 0; 00870 static DBusGUID machine_uuid; 00871 00883 dbus_bool_t 00884 _dbus_get_local_machine_uuid_encoded (DBusString *uuid_str, 00885 DBusError *error) 00886 { 00887 dbus_bool_t ok = TRUE; 00888 00889 if (!_DBUS_LOCK (machine_uuid)) 00890 { 00891 _DBUS_SET_OOM (error); 00892 return FALSE; 00893 } 00894 00895 if (machine_uuid_initialized_generation != _dbus_current_generation) 00896 { 00897 DBusError local_error = DBUS_ERROR_INIT; 00898 00899 if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE, 00900 &local_error)) 00901 { 00902 #ifndef DBUS_ENABLE_EMBEDDED_TESTS 00903 /* For the test suite, we may not be installed so just continue silently 00904 * here. But in a production build, we want to be nice and loud about 00905 * this. 00906 */ 00907 _dbus_warn_check_failed ("D-Bus library appears to be incorrectly set up; failed to read machine uuid: %s\n" 00908 "See the manual page for dbus-uuidgen to correct this issue.\n", 00909 local_error.message); 00910 #endif 00911 00912 dbus_error_free (&local_error); 00913 00914 ok = _dbus_generate_uuid (&machine_uuid, error); 00915 } 00916 } 00917 00918 if (ok) 00919 { 00920 if (!_dbus_uuid_encode (&machine_uuid, uuid_str)) 00921 { 00922 ok = FALSE; 00923 _DBUS_SET_OOM (error); 00924 } 00925 } 00926 00927 _DBUS_UNLOCK (machine_uuid); 00928 00929 return ok; 00930 } 00931 00932 #ifndef DBUS_DISABLE_CHECKS 00933 00934 const char *_dbus_return_if_fail_warning_format = 00935 "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n" 00936 "This is normally a bug in some application using the D-Bus library.\n"; 00937 #endif 00938 00939 #ifndef DBUS_DISABLE_ASSERT 00940 00952 void 00953 _dbus_real_assert (dbus_bool_t condition, 00954 const char *condition_text, 00955 const char *file, 00956 int line, 00957 const char *func) 00958 { 00959 if (_DBUS_UNLIKELY (!condition)) 00960 { 00961 _dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n", 00962 _dbus_pid_for_log (), condition_text, file, line, func); 00963 _dbus_abort (); 00964 } 00965 } 00966 00977 void 00978 _dbus_real_assert_not_reached (const char *explanation, 00979 const char *file, 00980 int line) 00981 { 00982 _dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n", 00983 file, line, _dbus_pid_for_log (), explanation); 00984 _dbus_abort (); 00985 } 00986 #endif /* DBUS_DISABLE_ASSERT */ 00987 00988 #ifdef DBUS_ENABLE_EMBEDDED_TESTS 00989 static dbus_bool_t 00990 run_failing_each_malloc (int n_mallocs, 00991 const char *description, 00992 DBusTestMemoryFunction func, 00993 void *data) 00994 { 00995 n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */ 00996 00997 while (n_mallocs >= 0) 00998 { 00999 _dbus_set_fail_alloc_counter (n_mallocs); 01000 01001 _dbus_verbose ("\n===\n%s: (will fail malloc %d with %d failures)\n===\n", 01002 description, n_mallocs, 01003 _dbus_get_fail_alloc_failures ()); 01004 01005 if (!(* func) (data)) 01006 return FALSE; 01007 01008 n_mallocs -= 1; 01009 } 01010 01011 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); 01012 01013 return TRUE; 01014 } 01015 01029 dbus_bool_t 01030 _dbus_test_oom_handling (const char *description, 01031 DBusTestMemoryFunction func, 01032 void *data) 01033 { 01034 int approx_mallocs; 01035 const char *setting; 01036 int max_failures_to_try; 01037 int i; 01038 01039 /* Run once to see about how many mallocs are involved */ 01040 01041 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX); 01042 01043 _dbus_verbose ("Running once to count mallocs\n"); 01044 01045 if (!(* func) (data)) 01046 return FALSE; 01047 01048 approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter (); 01049 01050 _dbus_verbose ("\n=================\n%s: about %d mallocs total\n=================\n", 01051 description, approx_mallocs); 01052 01053 setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES"); 01054 if (setting != NULL) 01055 { 01056 DBusString str; 01057 long v; 01058 _dbus_string_init_const (&str, setting); 01059 v = 4; 01060 if (!_dbus_string_parse_int (&str, 0, &v, NULL)) 01061 _dbus_warn ("couldn't parse '%s' as integer\n", setting); 01062 max_failures_to_try = v; 01063 } 01064 else 01065 { 01066 max_failures_to_try = 4; 01067 } 01068 01069 if (max_failures_to_try < 1) 01070 { 01071 _dbus_verbose ("not testing OOM handling\n"); 01072 return TRUE; 01073 } 01074 01075 i = setting ? max_failures_to_try - 1 : 1; 01076 while (i < max_failures_to_try) 01077 { 01078 _dbus_set_fail_alloc_failures (i); 01079 if (!run_failing_each_malloc (approx_mallocs, description, func, data)) 01080 return FALSE; 01081 ++i; 01082 } 01083 01084 _dbus_verbose ("\n=================\n%s: all iterations passed\n=================\n", 01085 description); 01086 01087 return TRUE; 01088 } 01089 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */ 01090