D-Bus 1.14.8
dbus-internals.c
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-test-tap.h"
30#include "dbus-valgrind-internal.h"
31#include <stdio.h>
32#include <stdarg.h>
33#include <string.h>
34#include <stdlib.h>
35#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
36#include <windows.h>
37#include <mbstring.h>
38#endif
39
40
41#ifdef HAVE_PDPLINUX
42
43#include <setjmp.h>
44/*
45#define TRY do{ jmp_buf ex_buf__; if( !setjmp(ex_buf__) ){
46#define CATCH } else {
47#define ETRY } }while(0)
48#define THROW longjmp(ex_buf__, 1)
49*/
50
51 #ifdef DBUS_ENABLE_VERBOSE_MODE
52
53// Option used at debug and release modes with DBUS_ENABLE_VERBOSE_MODE ONLY!
54// TO force variable DBUS_VERBOSE=1 (if DBUS_ENABLE_VERBOSE_MODE => _dbus_verbose is only define)
55
56// This option send to config: HAVE_PDPLINUX_FORCE_ENABLE_DBUS_VERBOSE
57// NB Look at option --enable-pdplinux-force-verbose | on
58
59
60//option used only when DBUS_ENABLE_VERBOSE_MODE mode to use FILE LOGGING (also loves HAVE_PDPLINUX_FORCE_ENABLE_DBUS_VERBOSE)
61//#define PDPLINUX_USE_FILELOG
62
63 #ifdef PDPLINUX_USE_FILELOG
64
65//use special verbose command to close file log search => "!PDPLINUX_LOGCLOSE!"
66#define PDPLINUX_LOGCLOSE "!PDPLINUX_LOGCLOSE!"
67
68 #endif
69 #endif
70
71#endif
72
218const char *_dbus_no_memory_message = "Not enough memory";
219
220/* Not necessarily thread-safe, but if writes don't propagate between
221 * threads, the worst that will happen is that we duplicate work in more than
222 * one thread. */
223static dbus_bool_t warn_initted = FALSE;
224
225/* Not necessarily thread-safe, but if writes don't propagate between
226 * threads, the worst that will happen is that warnings get their default
227 * fatal/non-fatal nature. */
228static dbus_bool_t fatal_warnings = FALSE;
229static dbus_bool_t fatal_warnings_on_check_failed = TRUE;
230
231static void
232init_warnings(void)
233{
234 if (!warn_initted)
235 {
236 const char *s;
237 s = _dbus_getenv ("DBUS_FATAL_WARNINGS");
238 if (s && *s)
239 {
240 if (*s == '0')
241 {
242 fatal_warnings = FALSE;
243 fatal_warnings_on_check_failed = FALSE;
244 }
245 else if (*s == '1')
246 {
247 fatal_warnings = TRUE;
248 fatal_warnings_on_check_failed = TRUE;
249 }
250 else
251 {
252 fprintf(stderr, "DBUS_FATAL_WARNINGS should be set to 0 or 1 if set, not '%s'",
253 s);
254 }
255 }
256
257 warn_initted = TRUE;
258 }
259}
260
270void
271_dbus_warn (const char *format,
272 ...)
273{
274 DBusSystemLogSeverity severity = DBUS_SYSTEM_LOG_WARNING;
275 va_list args;
276
277 if (!warn_initted)
278 init_warnings ();
279
280 if (fatal_warnings)
281 severity = DBUS_SYSTEM_LOG_ERROR;
282
283 va_start (args, format);
284 _dbus_logv (severity, format, args);
285 va_end (args);
286
287 if (fatal_warnings)
288 {
289 fflush (stderr);
290 _dbus_abort ();
291 }
292}
293
302void
303_dbus_warn_check_failed(const char *format,
304 ...)
305{
306 DBusSystemLogSeverity severity = DBUS_SYSTEM_LOG_WARNING;
307 va_list args;
308
309 if (!warn_initted)
310 init_warnings ();
311
312 if (fatal_warnings_on_check_failed)
313 severity = DBUS_SYSTEM_LOG_ERROR;
314
315 va_start (args, format);
316 _dbus_logv (severity, format, args);
317 va_end (args);
318
319 if (fatal_warnings_on_check_failed)
320 {
321 fflush (stderr);
322 _dbus_abort ();
323 }
324}
325
326#ifdef DBUS_ENABLE_VERBOSE_MODE
327
328static dbus_bool_t verbose_initted = FALSE;
329static dbus_bool_t verbose = TRUE;
330
331#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
332static char module_name[1024];
333#endif
334
335#ifdef HAVE_PDPLINUX
336#include <time.h>
337#include <unistd.h>
338
339#ifdef PDPLINUX_USE_FILELOG
340static FILE* fdlog=0;
341static char namelog[1024];
342#endif
343#endif
344
345static inline void
346_dbus_verbose_init (void)
347{
348 if (!verbose_initted)
349 {
350 const char *p = _dbus_getenv ("DBUS_VERBOSE");
351
352 verbose = p != NULL && *p == '1';
353 verbose_initted = TRUE;
354
355#ifdef HAVE_PDPLINUX
356#ifdef HAVE_PDPLINUX_FORCE_ENABLE_DBUS_VERBOSE
357 verbose=TRUE;
358#endif
359
360#ifdef PDPLINUX_USE_FILELOG
361 if (!fdlog && verbose){
362 time_t rawtime;
363 PDPL_T* pdpl=NULL;
364 char* textlabel=NULL;
365 struct tm* timeinfo=NULL;
366 char sttime[80];
367
368 time(&rawtime);
369 timeinfo=localtime(&rawtime);
370
371 snprintf(sttime,sizeof(sttime),"notime");
372 if (timeinfo)
373 strftime (sttime,sizeof(sttime),"%F-%H%M%S",timeinfo);
374
375 pdpl=pdp_get_current();
376 if (pdpl){
377 textlabel=pdpl_get_text(pdpl,PDPL_FMT_NUM);
378 }
379 if (snprintf(namelog,sizeof(namelog),"/dbuslog/dbus-%s-(%s)-%ld",
380 sttime,
381 textlabel ? textlabel : "-",
382 (long)getpid())>0){
383 char* pos=namelog;
384 while ('\0' != *pos && pos <= namelog+sizeof(namelog)/sizeof(*namelog)){
385 if (*pos == ':') *pos='-';
386 pos++;
387 }
388
389 fdlog=fopen(namelog,"wt+");
390 }
391 if (textlabel) free(textlabel);
392 if (pdpl) pdpl_put(pdpl);
393 }
394#endif
395#endif
396
397#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
398 {
399 char *last_period, *last_slash;
400 GetModuleFileName(0,module_name,sizeof(module_name)-1);
401 last_period = _mbsrchr(module_name,'.');
402 if (last_period)
403 *last_period ='\0';
404 last_slash = _mbsrchr(module_name,'\\');
405 if (last_slash)
406 strcpy(module_name,last_slash+1);
407 strcat(module_name,": ");
408 }
409#endif
410 }
411}
412
418#ifdef DBUS_WIN
419#define DBUS_IS_DIR_SEPARATOR(c) (c == '\\' || c == '/')
420#else
421#define DBUS_IS_DIR_SEPARATOR(c) (c == '/')
422#endif
423
428static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level)
429{
430 int prefix = 0;
431 char *p = (char *)file + strlen(file);
432 int i = 0;
433
434 for (;p >= file;p--)
435 {
436 if (DBUS_IS_DIR_SEPARATOR(*p))
437 {
438 if (++i >= level)
439 {
440 prefix = p-file+1;
441 break;
442 }
443 }
444 }
445
446 return (char *)file+prefix;
447}
448
455_dbus_is_verbose_real (void)
456{
457 _dbus_verbose_init ();
458 return verbose;
459}
460
461void _dbus_set_verbose (dbus_bool_t state)
462{
463 verbose = state;
464}
465
466dbus_bool_t _dbus_get_verbose (void)
467{
468 return verbose;
469}
470
482void
483_dbus_verbose_raw (const char *s)
484{
485 if (!_dbus_is_verbose_real ())
486 return;
487#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
488 OutputDebugStringA (s);
489#else
490 fputs (s, stderr);
491 fflush (stderr);
492#endif
493}
494
503void
504_dbus_verbose_real (
505#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
506 const char *file,
507 const int line,
508 const char *function,
509#endif
510 const char *format,
511 ...)
512{
513 va_list args;
514 static dbus_bool_t need_pid = TRUE;
515 int len;
516 long sec, usec;
517 FILE* outfile=stderr;
518
519#ifdef HAVE_PDPLINUX
520#ifdef PDPLINUX_USE_FILELOG
521 if (fdlog) outfile=fdlog;
522 if (format){
523 if (strlen(format) == sizeof(PDPLINUX_LOGCLOSE)-1 ){
524 if (0 == memcmp(format,PDPLINUX_LOGCLOSE,sizeof(PDPLINUX_LOGCLOSE))){
525 if (fdlog) fclose(fdlog);
526 fdlog = NULL;
527 outfile = stderr;
528 return;
529 }
530 }
531 }
532#endif
533#endif
534
535 /* things are written a bit oddly here so that
536 * in the non-verbose case we just have the one
537 * conditional and return immediately.
538 */
539 if (!_dbus_is_verbose_real())
540 return;
541
542#ifndef DBUS_USE_OUTPUT_DEBUG_STRING
543 /* Print out pid before the line */
544 if (need_pid)
545 {
546 _dbus_print_thread ();
547 }
548 _dbus_get_real_time (&sec, &usec);
549 fprintf (outfile, "%ld.%06ld ", sec, usec);
550#endif
551
552 /* Only print pid again if the next line is a new line */
553 if (format){
554 len = strlen (format);
555 if (len > 0){
556 if (format[len-1] == '\n')
557 need_pid = TRUE;
558 else
559 need_pid = FALSE;
560 }
561
562 va_start (args, format);
563#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
564 {
565 DBusString out = _DBUS_STRING_INIT_INVALID;
566 const char *message = NULL;
567
568 if (!_dbus_string_init (&out))
569 goto out;
570
571 if (!_dbus_string_append (&out, module_name))
572 goto out;
573
574#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
575 if (!_dbus_string_append_printf (&out, "[%s(%d):%s] ", _dbus_file_path_extract_elements_from_tail (file, 2), line, function))
576 goto out;
577#endif
578 if (!_dbus_string_append_printf_valist (&out, format, args))
579 goto out;
580 message = _dbus_string_get_const_data (&out);
581out:
582 if (message == NULL)
583 {
584 OutputDebugStringA ("Out of memory while formatting verbose message: '''");
585 OutputDebugStringA (format);
586 OutputDebugStringA ("'''");
587 }
588 else
589 {
590 OutputDebugStringA (message);
591 }
592 _dbus_string_free (&out);
593 }
594#else
595#ifdef DBUS_CPP_SUPPORTS_VARIABLE_MACRO_ARGUMENTS
596 fprintf (outfile, "[%s(%d):%s] ",_dbus_file_path_extract_elements_from_tail(file,2),line,function);
597#endif
598
599 vfprintf (outfile, format, args);
600 va_end (args);
601#endif
602 }
603
604 fflush (outfile);
605}
606
613void
614_dbus_verbose_reset_real (void)
615{
616 verbose_initted = FALSE;
617}
618
619void
620_dbus_trace_ref (const char *obj_name,
621 void *obj,
622 int old_refcount,
623 int new_refcount,
624 const char *why,
625 const char *env_var,
626 int *enabled)
627{
628 _dbus_assert (obj_name != NULL);
629 _dbus_assert (obj != NULL);
630 _dbus_assert (old_refcount >= -1);
631 _dbus_assert (new_refcount >= -1);
632
633 if (old_refcount == -1)
634 {
635 _dbus_assert (new_refcount == -1);
636 }
637 else
638 {
639 _dbus_assert (new_refcount >= 0);
640 _dbus_assert (old_refcount >= 0);
641 _dbus_assert (old_refcount > 0 || new_refcount > 0);
642 }
643
644 _dbus_assert (why != NULL);
645 _dbus_assert (env_var != NULL);
646 _dbus_assert (enabled != NULL);
647
648 if (*enabled < 0)
649 {
650 const char *s = _dbus_getenv (env_var);
651
652 *enabled = FALSE;
653
654 if (s && *s)
655 {
656 if (*s == '0')
657 *enabled = FALSE;
658 else if (*s == '1')
659 *enabled = TRUE;
660 else
661 _dbus_warn ("%s should be 0 or 1 if set, not '%s'", env_var, s);
662 }
663 }
664
665 if (*enabled)
666 {
667 if (old_refcount == -1)
668 {
669 VALGRIND_PRINTF_BACKTRACE ("%s %p ref stolen (%s)",
670 obj_name, obj, why);
671 _dbus_verbose ("%s %p ref stolen (%s)\n",
672 obj_name, obj, why);
673 }
674 else
675 {
676 VALGRIND_PRINTF_BACKTRACE ("%s %p %d -> %d refs (%s)",
677 obj_name, obj,
678 old_refcount, new_refcount, why);
679 _dbus_verbose ("%s %p %d -> %d refs (%s)\n",
680 obj_name, obj, old_refcount, new_refcount, why);
681 }
682 }
683}
684
685#endif /* DBUS_ENABLE_VERBOSE_MODE */
686
695char*
696_dbus_strdup (const char *str)
697{
698 size_t len;
699 char *copy;
700
701 if (str == NULL)
702 return NULL;
703
704 len = strlen (str);
705
706 copy = dbus_malloc (len + 1);
707 if (copy == NULL)
708 return NULL;
709
710 memcpy (copy, str, len + 1);
711
712 return copy;
713}
714
723void*
724_dbus_memdup (const void *mem,
725 size_t n_bytes)
726{
727 void *copy;
728
729 copy = dbus_malloc (n_bytes);
730 if (copy == NULL)
731 return NULL;
732
733 memcpy (copy, mem, n_bytes);
734
735 return copy;
736}
737
746char**
747_dbus_dup_string_array (const char **array)
748{
749 int len;
750 int i;
751 char **copy;
752
753 if (array == NULL)
754 return NULL;
755
756 for (len = 0; array[len] != NULL; ++len)
757 ;
758
759 copy = dbus_new0 (char*, len + 1);
760 if (copy == NULL)
761 return NULL;
762
763 i = 0;
764 while (i < len)
765 {
766 copy[i] = _dbus_strdup (array[i]);
767 if (copy[i] == NULL)
768 {
770 return NULL;
771 }
772
773 ++i;
774 }
775
776 return copy;
777}
778
787_dbus_string_array_contains (const char **array,
788 const char *str)
789{
790 int i;
791
792 i = 0;
793 while (array[i] != NULL)
794 {
795 if (strcmp (array[i], str) == 0)
796 return TRUE;
797 ++i;
798 }
799
800 return FALSE;
801}
802
809size_t
810_dbus_string_array_length (const char **array)
811{
812 size_t i;
813 for (i = 0; array[i]; i++) {}
814 return i;
815}
816
817
828 DBusError *error)
829{
830 DBusError rand_error;
831 long now;
832
833 dbus_error_init (&rand_error);
834
835 /* don't use monotonic time because the UUID may be saved to disk, e.g.
836 * it may persist across reboots
837 */
839
840 uuid->as_uint32s[DBUS_UUID_LENGTH_WORDS - 1] = DBUS_UINT32_TO_BE (now);
841
843 DBUS_UUID_LENGTH_BYTES - 4,
844 &rand_error))
845 {
846 dbus_set_error (error, rand_error.name,
847 "Failed to generate UUID: %s", rand_error.message);
848 dbus_error_free (&rand_error);
849 return FALSE;
850 }
851
852 return TRUE;
853}
854
864 DBusString *encoded)
865{
866 DBusString binary;
867 _dbus_string_init_const_len (&binary, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
868 return _dbus_string_hex_encode (&binary, 0, encoded, _dbus_string_get_length (encoded));
869}
870
871static dbus_bool_t
872_dbus_read_uuid_file_without_creating (const DBusString *filename,
873 DBusGUID *uuid,
874 DBusError *error)
875{
876 DBusString contents;
877 DBusString decoded;
878 int end;
879
880 if (!_dbus_string_init (&contents))
881 {
882 _DBUS_SET_OOM (error);
883 return FALSE;
884 }
885
886 if (!_dbus_string_init (&decoded))
887 {
888 _dbus_string_free (&contents);
889 _DBUS_SET_OOM (error);
890 return FALSE;
891 }
892
893 if (!_dbus_file_get_contents (&contents, filename, error))
894 goto error;
895
896 _dbus_string_chop_white (&contents);
897
898 if (_dbus_string_get_length (&contents) != DBUS_UUID_LENGTH_HEX)
899 {
901 "UUID file '%s' should contain a hex string of length %d, not length %d, with no other text",
902 _dbus_string_get_const_data (filename),
903 DBUS_UUID_LENGTH_HEX,
904 _dbus_string_get_length (&contents));
905 goto error;
906 }
907
908 if (!_dbus_string_hex_decode (&contents, 0, &end, &decoded, 0))
909 {
910 _DBUS_SET_OOM (error);
911 goto error;
912 }
913
914 if (end == 0)
915 {
917 "UUID file '%s' contains invalid hex data",
918 _dbus_string_get_const_data (filename));
919 goto error;
920 }
921
922 if (_dbus_string_get_length (&decoded) != DBUS_UUID_LENGTH_BYTES)
923 {
925 "UUID file '%s' contains %d bytes of hex-encoded data instead of %d",
926 _dbus_string_get_const_data (filename),
927 _dbus_string_get_length (&decoded),
928 DBUS_UUID_LENGTH_BYTES);
929 goto error;
930 }
931
932 _dbus_string_copy_to_buffer (&decoded, uuid->as_bytes, DBUS_UUID_LENGTH_BYTES);
933
934 _dbus_string_free (&decoded);
935 _dbus_string_free (&contents);
936
937 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
938
939 return TRUE;
940
941 error:
942 _DBUS_ASSERT_ERROR_IS_SET (error);
943 _dbus_string_free (&contents);
944 _dbus_string_free (&decoded);
945 return FALSE;
946}
947
958 const DBusGUID *uuid,
959 DBusError *error)
960{
961 DBusString encoded;
962
963 if (!_dbus_string_init (&encoded))
964 {
965 _DBUS_SET_OOM (error);
966 return FALSE;
967 }
968
969 if (!_dbus_uuid_encode (uuid, &encoded))
970 {
971 _DBUS_SET_OOM (error);
972 goto error;
973 }
974
975 if (!_dbus_string_append_byte (&encoded, '\n'))
976 {
977 _DBUS_SET_OOM (error);
978 goto error;
979 }
980
981 if (!_dbus_string_save_to_file (&encoded, filename, TRUE, error))
982 goto error;
983
984 _dbus_string_free (&encoded);
985
986 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
987 return TRUE;
988
989 error:
990 _DBUS_ASSERT_ERROR_IS_SET (error);
991 _dbus_string_free (&encoded);
992 return FALSE;
993}
994
1007 DBusGUID *uuid,
1008 dbus_bool_t create_if_not_found,
1009 DBusError *error)
1010{
1011 DBusError read_error = DBUS_ERROR_INIT;
1012
1013 if (_dbus_read_uuid_file_without_creating (filename, uuid, &read_error))
1014 return TRUE;
1015
1016 if (!create_if_not_found)
1017 {
1018 dbus_move_error (&read_error, error);
1019 return FALSE;
1020 }
1021
1022 /* If the file exists and contains junk, we want to keep that error
1023 * message instead of overwriting it with a "file exists" error
1024 * message when we try to write
1025 */
1027 {
1028 dbus_move_error (&read_error, error);
1029 return FALSE;
1030 }
1031 else
1032 {
1033 dbus_error_free (&read_error);
1034
1035 if (!_dbus_generate_uuid (uuid, error))
1036 return FALSE;
1037
1038 return _dbus_write_uuid_file (filename, uuid, error);
1039 }
1040}
1041
1042/* Protected by _DBUS_LOCK (machine_uuid) */
1043static int machine_uuid_initialized_generation = 0;
1044static DBusGUID machine_uuid;
1045
1059 DBusError *error)
1060{
1061 dbus_bool_t ok = TRUE;
1062
1063 if (!_DBUS_LOCK (machine_uuid))
1064 {
1065 _DBUS_SET_OOM (error);
1066 return FALSE;
1067 }
1068
1069 if (machine_uuid_initialized_generation != _dbus_current_generation)
1070 {
1071 if (!_dbus_read_local_machine_uuid (&machine_uuid, FALSE, error))
1072 ok = FALSE;
1073 }
1074
1075 if (ok)
1076 {
1077 if (!_dbus_uuid_encode (&machine_uuid, uuid_str))
1078 {
1079 ok = FALSE;
1080 _DBUS_SET_OOM (error);
1081 }
1082 }
1083
1084 _DBUS_UNLOCK (machine_uuid);
1085
1086 return ok;
1087}
1088
1089#ifndef DBUS_DISABLE_CHECKS
1090void
1091_dbus_warn_return_if_fail (const char *function,
1092 const char *assertion,
1093 const char *file,
1094 int line)
1095{
1097 "arguments to %s() were incorrect, assertion \"%s\" failed in file %s line %d.\n"
1098 "This is normally a bug in some application using the D-Bus library.\n",
1099 function, assertion, file, line);
1100}
1101#endif
1102
1103#ifndef DBUS_DISABLE_ASSERT
1116void
1118 const char *condition_text,
1119 const char *file,
1120 int line,
1121 const char *func)
1122{
1123 if (_DBUS_UNLIKELY (!condition))
1124 {
1125 _dbus_warn ("assertion failed \"%s\" file \"%s\" line %d function %s",
1126 condition_text, file, line, func);
1127 _dbus_abort ();
1128 }
1129}
1130
1141void
1142_dbus_real_assert_not_reached (const char *explanation,
1143 const char *file,
1144 int line)
1145{
1146 _dbus_warn ("File \"%s\" line %d should not have been reached: %s",
1147 file, line, explanation);
1148 _dbus_abort ();
1149}
1150#endif /* DBUS_DISABLE_ASSERT */
1151
1152#ifdef DBUS_ENABLE_EMBEDDED_TESTS
1153static dbus_bool_t
1154run_failing_each_malloc (int n_mallocs,
1155 const char *description,
1156 DBusTestMemoryFunction func,
1157 void *data)
1158{
1159 n_mallocs += 10; /* fudge factor to ensure reallocs etc. are covered */
1160
1161 while (n_mallocs >= 0)
1162 {
1163 _dbus_set_fail_alloc_counter (n_mallocs);
1164
1165 _dbus_test_diag ("%s: will fail malloc %d and %d that follow",
1166 description, n_mallocs,
1167 _dbus_get_fail_alloc_failures () - 1);
1168
1169 if (!(* func) (data, FALSE))
1170 return FALSE;
1171
1172 n_mallocs -= 1;
1173 }
1174
1175 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
1176
1177 return TRUE;
1178}
1179
1194_dbus_test_oom_handling (const char *description,
1195 DBusTestMemoryFunction func,
1196 void *data)
1197{
1198 int approx_mallocs;
1199 const char *setting;
1200 int max_failures_to_try;
1201 int i;
1202
1203 /* Run once to see about how many mallocs are involved */
1204
1205 _dbus_set_fail_alloc_counter (_DBUS_INT_MAX);
1206
1207 _dbus_test_diag ("Running \"%s\" once to count mallocs", description);
1208
1209 if (!(* func) (data, TRUE))
1210 return FALSE;
1211
1212 approx_mallocs = _DBUS_INT_MAX - _dbus_get_fail_alloc_counter ();
1213
1214 _dbus_test_diag ("\"%s\" has about %d mallocs in total",
1215 description, approx_mallocs);
1216
1217 setting = _dbus_getenv ("DBUS_TEST_MALLOC_FAILURES");
1218
1219 if (setting != NULL)
1220 {
1221 DBusString str;
1222 long v;
1223 _dbus_string_init_const (&str, setting);
1224 v = 4;
1225 if (!_dbus_string_parse_int (&str, 0, &v, NULL))
1226 _dbus_warn ("couldn't parse '%s' as integer\n", setting);
1227 max_failures_to_try = v;
1228 }
1229 else
1230 {
1231 max_failures_to_try = 4;
1232 }
1233
1234 if (RUNNING_ON_VALGRIND && _dbus_getenv ("DBUS_TEST_SLOW") == NULL)
1235 {
1236 /* The full OOM testing is slow, valgrind is slow, so the
1237 * combination is just horrible. Only do this if the user
1238 * asked for extra-slow tests. */
1239 max_failures_to_try = 0;
1240 }
1241
1242 if (max_failures_to_try < 1)
1243 {
1244 _dbus_test_diag ("not testing OOM handling");
1245 return TRUE;
1246 }
1247
1248 _dbus_test_diag ("testing \"%s\" with up to %d consecutive malloc failures",
1249 description, max_failures_to_try);
1250
1251 i = setting ? max_failures_to_try - 1 : 1;
1252 while (i < max_failures_to_try)
1253 {
1254 _dbus_test_diag ("testing \"%s\" with %d consecutive malloc failures",
1255 description, i + 1);
1256
1257 _dbus_set_fail_alloc_failures (i);
1258 if (!run_failing_each_malloc (approx_mallocs, description, func, data))
1259 return FALSE;
1260 ++i;
1261 }
1262
1263 _dbus_verbose ("\"%s\" coped OK with malloc failures\n", description);
1264
1265 return TRUE;
1266}
1267#endif /* DBUS_ENABLE_EMBEDDED_TESTS */
1268
#define DBUS_ERROR_INIT
Expands to a suitable initializer for a DBusError on the stack.
Definition: dbus-errors.h:62
void dbus_move_error(DBusError *src, DBusError *dest)
Moves an error src into dest, freeing src and overwriting dest.
Definition: dbus-errors.c:279
dbus_bool_t dbus_error_has_name(const DBusError *error, const char *name)
Checks whether the error is set and has the given name.
Definition: dbus-errors.c:302
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition: dbus-errors.c:188
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
dbus_bool_t _dbus_string_save_to_file(const DBusString *str, const DBusString *filename, dbus_bool_t world_readable, DBusError *error)
Writes a string out to a file.
dbus_bool_t _dbus_file_get_contents(DBusString *str, const DBusString *filename, DBusError *error)
Appends the contents of the given file to the string, returning error code.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
void _dbus_real_assert_not_reached(const char *explanation, const char *file, int line)
Internals of _dbus_assert_not_reached(); it's a function rather than a macro with the inline code so ...
dbus_bool_t _dbus_generate_uuid(DBusGUID *uuid, DBusError *error)
Generates a new UUID.
#define _DBUS_INT_MAX
Maximum value of type "int".
void _dbus_warn_check_failed(const char *format,...)
Prints a "critical" warning to stderr when an assertion fails; differs from _dbus_warn primarily in t...
char * _dbus_strdup(const char *str)
Duplicates a string.
dbus_bool_t _dbus_read_uuid_file(const DBusString *filename, DBusGUID *uuid, dbus_bool_t create_if_not_found, DBusError *error)
Reads (and optionally writes) a uuid to a file.
dbus_bool_t _dbus_string_array_contains(const char **array, const char *str)
Checks whether a string array contains the given string.
dbus_bool_t _dbus_get_local_machine_uuid_encoded(DBusString *uuid_str, DBusError *error)
Gets the hex-encoded UUID of the machine this function is executed on.
void _dbus_real_assert(dbus_bool_t condition, const char *condition_text, const char *file, int line, const char *func)
Internals of _dbus_assert(); it's a function rather than a macro with the inline code so that the ass...
dbus_bool_t _dbus_write_uuid_file(const DBusString *filename, const DBusGUID *uuid, DBusError *error)
Write the give UUID to a file.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
size_t _dbus_string_array_length(const char **array)
Returns the size of a string array.
const char * _dbus_no_memory_message
Fixed "out of memory" error message, just to avoid making up a different string every time and wastin...
void * _dbus_memdup(const void *mem, size_t n_bytes)
Duplicates a block of memory.
dbus_bool_t _dbus_uuid_encode(const DBusGUID *uuid, DBusString *encoded)
Hex-encode a UUID.
char ** _dbus_dup_string_array(const char **array)
Duplicates a string array.
dbus_bool_t _dbus_generate_random_bytes_buffer(char *buffer, int n_bytes, DBusError *error)
Fills n_bytes of the given buffer with random bytes.
Definition: dbus-sysdeps.c:525
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called,...
Definition: dbus-memory.c:772
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:740
void * dbus_malloc(size_t bytes)
Allocates the given number of bytes, as with standard malloc().
Definition: dbus-memory.c:452
#define DBUS_ERROR_INVALID_FILE_CONTENT
A file contains invalid syntax or is otherwise broken.
dbus_bool_t _dbus_string_hex_decode(const DBusString *source, int start, int *end_return, DBusString *dest, int insert_at)
Decodes a string from hex encoding.
Definition: dbus-string.c:2395
dbus_bool_t _dbus_string_append(DBusString *str, const char *buffer)
Appends a nul-terminated C-style string to a DBusString.
Definition: dbus-string.c:966
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:197
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:217
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
dbus_bool_t _dbus_string_append_printf_valist(DBusString *str, const char *format, va_list args)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1103
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_string_parse_int(const DBusString *str, int start, long *value_return, int *end_return)
Parses an integer contained in a DBusString.
Definition: dbus-sysdeps.c:444
dbus_bool_t _dbus_string_append_byte(DBusString *str, unsigned char byte)
Appends a single byte to the string, returning FALSE if not enough memory.
Definition: dbus-string.c:1188
void _dbus_string_chop_white(DBusString *str)
Deletes leading and trailing whitespace.
Definition: dbus-string.c:2049
dbus_bool_t _dbus_string_hex_encode(const DBusString *source, int start, DBusString *dest, int insert_at)
Encodes a string in hex, the way MD5 and SHA-1 are usually encoded.
Definition: dbus-string.c:2345
dbus_bool_t _dbus_string_append_printf(DBusString *str, const char *format,...)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1145
void _dbus_string_copy_to_buffer(const DBusString *str, char *buffer, int avail_len)
Copies the contents of a DBusString into a different buffer.
Definition: dbus-string.c:728
void _dbus_logv(DBusSystemLogSeverity severity, const char *msg, va_list args)
Log a message to the system log file (e.g.
dbus_bool_t _dbus_read_local_machine_uuid(DBusGUID *machine_id, dbus_bool_t create_if_not_found, DBusError *error)
Reads the uuid of the machine we're running on from the dbus configuration.
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:195
void _dbus_get_real_time(long *tv_sec, long *tv_usec)
Get current time, as in gettimeofday().
void _dbus_abort(void)
Aborts the program with SIGABRT (dumping core).
Definition: dbus-sysdeps.c:87
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
Object representing an exception.
Definition: dbus-errors.h:49
const char * name
public error name field
Definition: dbus-errors.h:50
const char * message
public error message field
Definition: dbus-errors.h:51
A globally unique ID ; we have one for each DBusServer, and also one for each machine with libdbus in...
dbus_uint32_t as_uint32s[DBUS_UUID_LENGTH_WORDS]
guid as four uint32 values
char as_bytes[DBUS_UUID_LENGTH_BYTES]
guid as 16 single-byte values