dbus-internals.c revision 2f38c959212d98e2194139daa9120fda37415b4f
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* dbus-internals.c random utility stuff (internal to D-BUS implementation) 3 * 4 * Copyright (C) 2002 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 1.2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23#include "dbus-internals.h" 24#include "dbus-protocol.h" 25#include "dbus-test.h" 26#include <stdio.h> 27#include <stdarg.h> 28#include <string.h> 29#include <sys/types.h> 30#include <errno.h> 31#include <unistd.h> 32#include <fcntl.h> 33#include <stdlib.h> 34 35/** 36 * @defgroup DBusInternals D-BUS internal implementation details 37 * @brief Documentation useful when developing or debugging D-BUS itself. 38 * 39 */ 40 41/** 42 * @defgroup DBusInternalsUtils Utilities and portability 43 * @ingroup DBusInternals 44 * @brief Utility functions (_dbus_assert(), _dbus_warn(), etc.) 45 * @{ 46 */ 47 48/** 49 * @def _dbus_assert 50 * 51 * Aborts with an error message if the condition is false. 52 * 53 * @param condition condition which must be true. 54 */ 55 56/** 57 * @def _dbus_assert_not_reached 58 * 59 * Aborts with an error message if called. 60 * The given explanation will be printed. 61 * 62 * @param explanation explanation of what happened if the code was reached. 63 */ 64 65/** 66 * @def _DBUS_N_ELEMENTS 67 * 68 * Computes the number of elements in a fixed-size array using 69 * sizeof(). 70 * 71 * @param array the array to count elements in. 72 */ 73 74/** 75 * @def _DBUS_POINTER_TO_INT 76 * 77 * Safely casts a void* to an integer; should only be used on void* 78 * that actually contain integers, for example one created with 79 * _DBUS_INT_TO_POINTER. Only guaranteed to preserve 32 bits. 80 * (i.e. it's used to store 32-bit ints in pointers, but 81 * can't be used to store 64-bit pointers in ints.) 82 * 83 * @param pointer pointer to extract an integer from. 84 */ 85/** 86 * @def _DBUS_INT_TO_POINTER 87 * 88 * Safely stuffs an integer into a pointer, to be extracted later with 89 * _DBUS_POINTER_TO_INT. Only guaranteed to preserve 32 bits. 90 * 91 * @param integer the integer to stuff into a pointer. 92 */ 93/** 94 * @def _DBUS_ZERO 95 * 96 * Sets all bits in an object to zero. 97 * 98 * @param object the object to be zeroed. 99 */ 100/** 101 * @def _DBUS_INT_MIN 102 * 103 * Minimum value of type "int" 104 */ 105/** 106 * @def _DBUS_INT_MAX 107 * 108 * Maximum value of type "int" 109 */ 110/** 111 * @def _DBUS_MAX_SUN_PATH_LENGTH 112 * 113 * Maximum length of the path to a UNIX domain socket, 114 * sockaddr_un::sun_path member. POSIX requires that all systems 115 * support at least 100 bytes here, including the nul termination. 116 * We use 99 for the max value to allow for the nul. 117 * 118 * We could probably also do sizeof (addr.sun_path) 119 * but this way we are the same on all platforms 120 * which is probably a good idea. 121 */ 122 123/** 124 * @typedef DBusForeachFunction 125 * 126 * Used to iterate over each item in a collection, such as 127 * a DBusList. 128 */ 129 130/** 131 * Prints a warning message to stderr. 132 * 133 * @param format printf-style format string. 134 */ 135void 136_dbus_warn (const char *format, 137 ...) 138{ 139 /* FIXME not portable enough? */ 140 va_list args; 141 142 va_start (args, format); 143 vfprintf (stderr, format, args); 144 va_end (args); 145} 146 147/** 148 * Prints a warning message to stderr 149 * if the user has enabled verbose mode. 150 * This is the real function implementation, 151 * use _dbus_verbose() macro in code. 152 * 153 * @param format printf-style format string. 154 */ 155void 156_dbus_verbose_real (const char *format, 157 ...) 158{ 159 va_list args; 160 static dbus_bool_t verbose = TRUE; 161 static dbus_bool_t initted = FALSE; 162 163 /* things are written a bit oddly here so that 164 * in the non-verbose case we just have the one 165 * conditional and return immediately. 166 */ 167 if (!verbose) 168 return; 169 170 if (!initted) 171 { 172 verbose = _dbus_getenv ("DBUS_VERBOSE") != NULL; 173 initted = TRUE; 174 if (!verbose) 175 return; 176 } 177 178 va_start (args, format); 179 vfprintf (stderr, format, args); 180 va_end (args); 181} 182 183/** 184 * Converts a UNIX errno into a DBusResultCode. 185 * 186 * @todo should cover more errnos, specifically those 187 * from open(). 188 * 189 * @param error_number the errno. 190 * @returns the result code. 191 */ 192DBusResultCode 193_dbus_result_from_errno (int error_number) 194{ 195 switch (error_number) 196 { 197 case 0: 198 return DBUS_RESULT_SUCCESS; 199 200#ifdef EPROTONOSUPPORT 201 case EPROTONOSUPPORT: 202 return DBUS_RESULT_NOT_SUPPORTED; 203#endif 204#ifdef EAFNOSUPPORT 205 case EAFNOSUPPORT: 206 return DBUS_RESULT_NOT_SUPPORTED; 207#endif 208#ifdef ENFILE 209 case ENFILE: 210 return DBUS_RESULT_LIMITS_EXCEEDED; /* kernel out of memory */ 211#endif 212#ifdef EMFILE 213 case EMFILE: 214 return DBUS_RESULT_LIMITS_EXCEEDED; 215#endif 216#ifdef EACCES 217 case EACCES: 218 return DBUS_RESULT_ACCESS_DENIED; 219#endif 220#ifdef EPERM 221 case EPERM: 222 return DBUS_RESULT_ACCESS_DENIED; 223#endif 224#ifdef ENOBUFS 225 case ENOBUFS: 226 return DBUS_RESULT_NO_MEMORY; 227#endif 228#ifdef ENOMEM 229 case ENOMEM: 230 return DBUS_RESULT_NO_MEMORY; 231#endif 232#ifdef EINVAL 233 case EINVAL: 234 return DBUS_RESULT_FAILED; 235#endif 236#ifdef EBADF 237 case EBADF: 238 return DBUS_RESULT_FAILED; 239#endif 240#ifdef EFAULT 241 case EFAULT: 242 return DBUS_RESULT_FAILED; 243#endif 244#ifdef ENOTSOCK 245 case ENOTSOCK: 246 return DBUS_RESULT_FAILED; 247#endif 248#ifdef EISCONN 249 case EISCONN: 250 return DBUS_RESULT_FAILED; 251#endif 252#ifdef ECONNREFUSED 253 case ECONNREFUSED: 254 return DBUS_RESULT_NO_SERVER; 255#endif 256#ifdef ETIMEDOUT 257 case ETIMEDOUT: 258 return DBUS_RESULT_TIMEOUT; 259#endif 260#ifdef ENETUNREACH 261 case ENETUNREACH: 262 return DBUS_RESULT_NO_NETWORK; 263#endif 264#ifdef EADDRINUSE 265 case EADDRINUSE: 266 return DBUS_RESULT_ADDRESS_IN_USE; 267#endif 268#ifdef EEXIST 269 case EEXIST: 270 return DBUS_RESULT_FILE_NOT_FOUND; 271#endif 272#ifdef ENOENT 273 case ENOENT: 274 return DBUS_RESULT_FILE_NOT_FOUND; 275#endif 276 } 277 278 return DBUS_RESULT_FAILED; 279} 280 281/** 282 * Duplicates a string. Result must be freed with 283 * dbus_free(). Returns #NULL if memory allocation fails. 284 * If the string to be duplicated is #NULL, returns #NULL. 285 * 286 * @param str string to duplicate. 287 * @returns newly-allocated copy. 288 */ 289char* 290_dbus_strdup (const char *str) 291{ 292 int len; 293 char *copy; 294 295 if (str == NULL) 296 return NULL; 297 298 len = strlen (str); 299 300 copy = dbus_malloc (len + 1); 301 if (copy == NULL) 302 return NULL; 303 304 memcpy (copy, str, len + 1); 305 306 return copy; 307} 308 309/** 310 * Sets a file descriptor to be nonblocking. 311 * 312 * @param fd the file descriptor. 313 * @param result address of result code. 314 * @returns #TRUE on success. 315 */ 316dbus_bool_t 317_dbus_set_fd_nonblocking (int fd, 318 DBusResultCode *result) 319{ 320 int val; 321 322 val = fcntl (fd, F_GETFL, 0); 323 if (val < 0) 324 { 325 dbus_set_result (result, _dbus_result_from_errno (errno)); 326 _dbus_verbose ("Failed to get flags for fd %d: %s\n", fd, 327 _dbus_strerror (errno)); 328 return FALSE; 329 } 330 331 if (fcntl (fd, F_SETFL, val | O_NONBLOCK) < 0) 332 { 333 dbus_set_result (result, _dbus_result_from_errno (errno)); 334 _dbus_verbose ("Failed to set fd %d nonblocking: %s\n", 335 fd, _dbus_strerror (errno)); 336 337 return FALSE; 338 } 339 340 return TRUE; 341} 342 343/** 344 * Returns a string describing the given type. 345 * 346 * @param type the type to describe 347 * @returns a constant string describing the type 348 */ 349const char * 350_dbus_type_to_string (int type) 351{ 352 switch (type) 353 { 354 case DBUS_TYPE_INVALID: 355 return "invalid"; 356 case DBUS_TYPE_NIL: 357 return "nil"; 358 case DBUS_TYPE_INT32: 359 return "int32"; 360 case DBUS_TYPE_UINT32: 361 return "uint32"; 362 case DBUS_TYPE_DOUBLE: 363 return "double"; 364 case DBUS_TYPE_STRING: 365 return "string"; 366 case DBUS_TYPE_INT32_ARRAY: 367 return "int32 array"; 368 case DBUS_TYPE_UINT32_ARRAY: 369 return "uint32 array"; 370 case DBUS_TYPE_DOUBLE_ARRAY: 371 return "double array"; 372 case DBUS_TYPE_BYTE_ARRAY: 373 return "byte array"; 374 case DBUS_TYPE_STRING_ARRAY: 375 return "string array"; 376 default: 377 return "unknown"; 378 } 379} 380 381#ifdef DBUS_BUILD_TESTS 382static int fail_alloc_counter = _DBUS_INT_MAX; 383/** 384 * Sets the number of allocations until we simulate a failed 385 * allocation. If set to 0, the next allocation to run 386 * fails; if set to 1, one succeeds then the next fails; etc. 387 * Set to _DBUS_INT_MAX to not fail anything. 388 * 389 * @param until_next_fail number of successful allocs before one fails 390 */ 391void 392_dbus_set_fail_alloc_counter (int until_next_fail) 393{ 394 fail_alloc_counter = until_next_fail; 395} 396 397/** 398 * Gets the number of successful allocs until we'll simulate 399 * a failed alloc. 400 * 401 * @returns current counter value 402 */ 403int 404_dbus_get_fail_alloc_counter (void) 405{ 406 return fail_alloc_counter; 407} 408 409/** 410 * Called when about to alloc some memory; if 411 * it returns #TRUE, then the allocation should 412 * fail. If it returns #FALSE, then the allocation 413 * should not fail. 414 * 415 * @returns #TRUE if this alloc should fail 416 */ 417dbus_bool_t 418_dbus_decrement_fail_alloc_counter (void) 419{ 420 if (fail_alloc_counter <= 0) 421 { 422 fail_alloc_counter = _DBUS_INT_MAX; 423 return TRUE; 424 } 425 else 426 { 427 fail_alloc_counter -= 1; 428 return FALSE; 429 } 430} 431#endif /* DBUS_BUILD_TESTS */ 432 433/** @} */ 434