1 /* -*- mode: C; c-file-style: "gnu" -*- */ 2 /* dbus-sysdeps.c Wrappers around system/libc features shared between UNIX and Windows (internal to D-Bus implementation) 3 * 4 * Copyright (C) 2002, 2003, 2006 Red Hat, Inc. 5 * Copyright (C) 2003 CodeFactory AB 6 * 7 * Licensed under the Academic Free License version 2.1 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 */ 24 25 #include "dbus-internals.h" 26 #include "dbus-sysdeps.h" 27 #include "dbus-threads.h" 28 #include "dbus-protocol.h" 29 #include "dbus-string.h" 30 31 /* NOTE: If you include any unix/windows-specific headers here, you are probably doing something 32 * wrong and should be putting some code in dbus-sysdeps-unix.c or dbus-sysdeps-win.c. 33 * 34 * These are the standard ANSI C headers... 35 */ 36 #include <locale.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <stdio.h> 40 41 /* This is UNIX-specific (on windows it's just in stdlib.h I believe) 42 * but OK since the same stuff does exist on Windows in stdlib.h 43 * and covered by a configure check. 44 */ 45 #ifdef HAVE_ERRNO_H 46 #include <errno.h> 47 #endif 48 49 _DBUS_DEFINE_GLOBAL_LOCK (win_fds); 50 _DBUS_DEFINE_GLOBAL_LOCK (sid_atom_cache); 51 52 /** 53 * @defgroup DBusSysdeps Internal system-dependent API 54 * @ingroup DBusInternals 55 * @brief Internal system-dependent API available on UNIX and Windows 56 * 57 * The system-dependent API has a dual purpose. First, it encapsulates 58 * all usage of operating system APIs for ease of auditing and to 59 * avoid cluttering the rest of the code with bizarre OS quirks and 60 * headers. Second, it abstracts different operating system APIs for 61 * portability. 62 * 63 * @{ 64 */ 65 66 /** 67 * Aborts the program with SIGABRT (dumping core). 68 */ 69 void 70 _dbus_abort (void) 71 { 72 const char *s; 73 74 _dbus_print_backtrace (); 75 76 s = _dbus_getenv ("DBUS_BLOCK_ON_ABORT"); 77 if (s && *s) 78 { 79 /* don't use _dbus_warn here since it can _dbus_abort() */ 80 fprintf (stderr, " Process %lu sleeping for gdb attach\n", (unsigned long) _dbus_getpid()); 81 _dbus_sleep_milliseconds (1000 * 180); 82 } 83 84 abort (); 85 _dbus_exit (1); /* in case someone manages to ignore SIGABRT ? */ 86 } 87 88 /** 89 * Wrapper for setenv(). If the value is #NULL, unsets 90 * the environment variable. 91 * 92 * There is an unfixable memleak in that it is unsafe to 93 * free memory malloced for use with setenv. This is because 94 * we can not rely on internal implementation details of 95 * the underlying libc library. 96 * 97 * @param varname name of environment variable 98 * @param value value of environment variable 99 * @returns #TRUE on success. 100 */ 101 dbus_bool_t 102 _dbus_setenv (const char *varname, 103 const char *value) 104 { 105 _dbus_assert (varname != NULL); 106 107 if (value == NULL) 108 { 109 #ifdef HAVE_UNSETENV 110 unsetenv (varname); 111 return TRUE; 112 #else 113 char *putenv_value; 114 size_t len; 115 116 len = strlen (varname); 117 118 /* Use system malloc to avoid memleaks that dbus_malloc 119 * will get upset about. 120 */ 121 122 putenv_value = malloc (len + 1); 123 if (putenv_value == NULL) 124 return FALSE; 125 126 strcpy (putenv_value, varname); 127 128 return (putenv (putenv_value) == 0); 129 #endif 130 } 131 else 132 { 133 #ifdef HAVE_SETENV 134 return (setenv (varname, value, TRUE) == 0); 135 #else 136 char *putenv_value; 137 size_t len; 138 size_t varname_len; 139 size_t value_len; 140 141 varname_len = strlen (varname); 142 value_len = strlen (value); 143 144 len = varname_len + value_len + 1 /* '=' */ ; 145 146 /* Use system malloc to avoid memleaks that dbus_malloc 147 * will get upset about. 148 */ 149 150 putenv_value = malloc (len + 1); 151 if (putenv_value == NULL) 152 return FALSE; 153 154 strcpy (putenv_value, varname); 155 strcpy (putenv_value + varname_len, "="); 156 strcpy (putenv_value + varname_len + 1, value); 157 158 return (putenv (putenv_value) == 0); 159 #endif 160 } 161 } 162 163 /** 164 * Wrapper for getenv(). 165 * 166 * @param varname name of environment variable 167 * @returns value of environment variable or #NULL if unset 168 */ 169 const char* 170 _dbus_getenv (const char *varname) 171 { 172 return getenv (varname); 173 } 174 175 /** @} */ 176 177 /** 178 * @addtogroup DBusString 179 * 180 * @{ 181 */ 182 /** 183 * Appends an integer to a DBusString. 184 * 185 * @param str the string 186 * @param value the integer value 187 * @returns #FALSE if not enough memory or other failure. 188 */ 189 dbus_bool_t 190 _dbus_string_append_int (DBusString *str, 191 long value) 192 { 193 /* this calculation is from comp.lang.c faq */ 194 #define MAX_LONG_LEN ((sizeof (long) * 8 + 2) / 3 + 1) /* +1 for '-' */ 195 int orig_len; 196 int i; 197 char *buf; 198 199 orig_len = _dbus_string_get_length (str); 200 201 if (!_dbus_string_lengthen (str, MAX_LONG_LEN)) 202 return FALSE; 203 204 buf = _dbus_string_get_data_len (str, orig_len, MAX_LONG_LEN); 205 206 snprintf (buf, MAX_LONG_LEN, "%ld", value); 207 208 i = 0; 209 while (*buf) 210 { 211 ++buf; 212 ++i; 213 } 214 215 _dbus_string_shorten (str, MAX_LONG_LEN - i); 216 217 return TRUE; 218 } 219 220 /** 221 * Appends an unsigned integer to a DBusString. 222 * 223 * @param str the string 224 * @param value the integer value 225 * @returns #FALSE if not enough memory or other failure. 226 */ 227 dbus_bool_t 228 _dbus_string_append_uint (DBusString *str, 229 unsigned long value) 230 { 231 /* this is wrong, but definitely on the high side. */ 232 #define MAX_ULONG_LEN (MAX_LONG_LEN * 2) 233 int orig_len; 234 int i; 235 char *buf; 236 237 orig_len = _dbus_string_get_length (str); 238 239 if (!_dbus_string_lengthen (str, MAX_ULONG_LEN)) 240 return FALSE; 241 242 buf = _dbus_string_get_data_len (str, orig_len, MAX_ULONG_LEN); 243 244 snprintf (buf, MAX_ULONG_LEN, "%lu", value); 245 246 i = 0; 247 while (*buf) 248 { 249 ++buf; 250 ++i; 251 } 252 253 _dbus_string_shorten (str, MAX_ULONG_LEN - i); 254 255 return TRUE; 256 } 257 258 #ifdef DBUS_BUILD_TESTS 259 /** 260 * Appends a double to a DBusString. 261 * 262 * @param str the string 263 * @param value the floating point value 264 * @returns #FALSE if not enough memory or other failure. 265 */ 266 dbus_bool_t 267 _dbus_string_append_double (DBusString *str, 268 double value) 269 { 270 #define MAX_DOUBLE_LEN 64 /* this is completely made up :-/ */ 271 int orig_len; 272 char *buf; 273 int i; 274 275 orig_len = _dbus_string_get_length (str); 276 277 if (!_dbus_string_lengthen (str, MAX_DOUBLE_LEN)) 278 return FALSE; 279 280 buf = _dbus_string_get_data_len (str, orig_len, MAX_DOUBLE_LEN); 281 282 snprintf (buf, MAX_LONG_LEN, "%g", value); 283 284 i = 0; 285 while (*buf) 286 { 287 ++buf; 288 ++i; 289 } 290 291 _dbus_string_shorten (str, MAX_DOUBLE_LEN - i); 292 293 return TRUE; 294 } 295 #endif /* DBUS_BUILD_TESTS */ 296 297 /** 298 * Parses an integer contained in a DBusString. Either return parameter 299 * may be #NULL if you aren't interested in it. The integer is parsed 300 * and stored in value_return. Return parameters are not initialized 301 * if the function returns #FALSE. 302 * 303 * @param str the string 304 * @param start the byte index of the start of the integer 305 * @param value_return return location of the integer value or #NULL 306 * @param end_return return location of the end of the integer, or #NULL 307 * @returns #TRUE on success 308 */ 309 dbus_bool_t 310 _dbus_string_parse_int (const DBusString *str, 311 int start, 312 long *value_return, 313 int *end_return) 314 { 315 long v; 316 const char *p; 317 char *end; 318 319 p = _dbus_string_get_const_data_len (str, start, 320 _dbus_string_get_length (str) - start); 321 322 end = NULL; 323 errno = 0; 324 v = strtol (p, &end, 0); 325 if (end == NULL || end == p || errno != 0) 326 return FALSE; 327 328 if (value_return) 329 *value_return = v; 330 if (end_return) 331 *end_return = start + (end - p); 332 333 return TRUE; 334 } 335 336 /** 337 * Parses an unsigned integer contained in a DBusString. Either return 338 * parameter may be #NULL if you aren't interested in it. The integer 339 * is parsed and stored in value_return. Return parameters are not 340 * initialized if the function returns #FALSE. 341 * 342 * @param str the string 343 * @param start the byte index of the start of the integer 344 * @param value_return return location of the integer value or #NULL 345 * @param end_return return location of the end of the integer, or #NULL 346 * @returns #TRUE on success 347 */ 348 dbus_bool_t 349 _dbus_string_parse_uint (const DBusString *str, 350 int start, 351 unsigned long *value_return, 352 int *end_return) 353 { 354 unsigned long v; 355 const char *p; 356 char *end; 357 358 p = _dbus_string_get_const_data_len (str, start, 359 _dbus_string_get_length (str) - start); 360 361 end = NULL; 362 errno = 0; 363 v = strtoul (p, &end, 0); 364 if (end == NULL || end == p || errno != 0) 365 return FALSE; 366 367 if (value_return) 368 *value_return = v; 369 if (end_return) 370 *end_return = start + (end - p); 371 372 return TRUE; 373 } 374 375 #ifdef DBUS_BUILD_TESTS 376 static dbus_bool_t 377 ascii_isspace (char c) 378 { 379 return (c == ' ' || 380 c == '\f' || 381 c == '\n' || 382 c == '\r' || 383 c == '\t' || 384 c == '\v'); 385 } 386 #endif /* DBUS_BUILD_TESTS */ 387 388 #ifdef DBUS_BUILD_TESTS 389 static dbus_bool_t 390 ascii_isdigit (char c) 391 { 392 return c >= '0' && c <= '9'; 393 } 394 #endif /* DBUS_BUILD_TESTS */ 395 396 #ifdef DBUS_BUILD_TESTS 397 static dbus_bool_t 398 ascii_isxdigit (char c) 399 { 400 return (ascii_isdigit (c) || 401 (c >= 'a' && c <= 'f') || 402 (c >= 'A' && c <= 'F')); 403 } 404 #endif /* DBUS_BUILD_TESTS */ 405 406 #ifdef DBUS_BUILD_TESTS 407 /* Calls strtod in a locale-independent fashion, by looking at 408 * the locale data and patching the decimal comma to a point. 409 * 410 * Relicensed from glib. 411 */ 412 static double 413 ascii_strtod (const char *nptr, 414 char **endptr) 415 { 416 char *fail_pos; 417 double val; 418 struct lconv *locale_data; 419 const char *decimal_point; 420 int decimal_point_len; 421 const char *p, *decimal_point_pos; 422 const char *end = NULL; /* Silence gcc */ 423 424 fail_pos = NULL; 425 426 locale_data = localeconv (); 427 decimal_point = locale_data->decimal_point; 428 decimal_point_len = strlen (decimal_point); 429 430 _dbus_assert (decimal_point_len != 0); 431 432 decimal_point_pos = NULL; 433 if (decimal_point[0] != '.' || 434 decimal_point[1] != 0) 435 { 436 p = nptr; 437 /* Skip leading space */ 438 while (ascii_isspace (*p)) 439 p++; 440 441 /* Skip leading optional sign */ 442 if (*p == '+' || *p == '-') 443 p++; 444 445 if (p[0] == '0' && 446 (p[1] == 'x' || p[1] == 'X')) 447 { 448 p += 2; 449 /* HEX - find the (optional) decimal point */ 450 451 while (ascii_isxdigit (*p)) 452 p++; 453 454 if (*p == '.') 455 { 456 decimal_point_pos = p++; 457 458 while (ascii_isxdigit (*p)) 459 p++; 460 461 if (*p == 'p' || *p == 'P') 462 p++; 463 if (*p == '+' || *p == '-') 464 p++; 465 while (ascii_isdigit (*p)) 466 p++; 467 end = p; 468 } 469 } 470 else 471 { 472 while (ascii_isdigit (*p)) 473 p++; 474 475 if (*p == '.') 476 { 477 decimal_point_pos = p++; 478 479 while (ascii_isdigit (*p)) 480 p++; 481 482 if (*p == 'e' || *p == 'E') 483 p++; 484 if (*p == '+' || *p == '-') 485 p++; 486 while (ascii_isdigit (*p)) 487 p++; 488 end = p; 489 } 490 } 491 /* For the other cases, we need not convert the decimal point */ 492 } 493 494 /* Set errno to zero, so that we can distinguish zero results 495 and underflows */ 496 errno = 0; 497 498 if (decimal_point_pos) 499 { 500 char *copy, *c; 501 502 /* We need to convert the '.' to the locale specific decimal point */ 503 copy = dbus_malloc (end - nptr + 1 + decimal_point_len); 504 505 c = copy; 506 memcpy (c, nptr, decimal_point_pos - nptr); 507 c += decimal_point_pos - nptr; 508 memcpy (c, decimal_point, decimal_point_len); 509 c += decimal_point_len; 510 memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1)); 511 c += end - (decimal_point_pos + 1); 512 *c = 0; 513 514 val = strtod (copy, &fail_pos); 515 516 if (fail_pos) 517 { 518 if (fail_pos > decimal_point_pos) 519 fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1); 520 else 521 fail_pos = (char *)nptr + (fail_pos - copy); 522 } 523 524 dbus_free (copy); 525 526 } 527 else 528 val = strtod (nptr, &fail_pos); 529 530 if (endptr) 531 *endptr = fail_pos; 532 533 return val; 534 } 535 #endif /* DBUS_BUILD_TESTS */ 536 537 #ifdef DBUS_BUILD_TESTS 538 /** 539 * Parses a floating point number contained in a DBusString. Either 540 * return parameter may be #NULL if you aren't interested in it. The 541 * integer is parsed and stored in value_return. Return parameters are 542 * not initialized if the function returns #FALSE. 543 * 544 * @param str the string 545 * @param start the byte index of the start of the float 546 * @param value_return return location of the float value or #NULL 547 * @param end_return return location of the end of the float, or #NULL 548 * @returns #TRUE on success 549 */ 550 dbus_bool_t 551 _dbus_string_parse_double (const DBusString *str, 552 int start, 553 double *value_return, 554 int *end_return) 555 { 556 double v; 557 const char *p; 558 char *end; 559 560 p = _dbus_string_get_const_data_len (str, start, 561 _dbus_string_get_length (str) - start); 562 563 end = NULL; 564 errno = 0; 565 v = ascii_strtod (p, &end); 566 if (end == NULL || end == p || errno != 0) 567 return FALSE; 568 569 if (value_return) 570 *value_return = v; 571 if (end_return) 572 *end_return = start + (end - p); 573 574 return TRUE; 575 } 576 #endif /* DBUS_BUILD_TESTS */ 577 578 /** @} */ /* DBusString group */ 579 580 /** 581 * @addtogroup DBusInternalsUtils 582 * @{ 583 */ 584 585 /** 586 * Frees the members of info 587 * (but not info itself) 588 * @param info the user info struct 589 */ 590 void 591 _dbus_user_info_free (DBusUserInfo *info) 592 { 593 dbus_free (info->group_ids); 594 dbus_free (info->username); 595 dbus_free (info->homedir); 596 } 597 598 /** 599 * Frees the members of info (but not info itself). 600 * 601 * @param info the group info 602 */ 603 void 604 _dbus_group_info_free (DBusGroupInfo *info) 605 { 606 dbus_free (info->groupname); 607 } 608 609 /** 610 * Sets fields in DBusCredentials to DBUS_PID_UNSET, 611 * DBUS_UID_UNSET, DBUS_GID_UNSET. 612 * 613 * @param credentials the credentials object to fill in 614 */ 615 void 616 _dbus_credentials_clear (DBusCredentials *credentials) 617 { 618 credentials->pid = DBUS_PID_UNSET; 619 credentials->uid = DBUS_UID_UNSET; 620 credentials->gid = DBUS_GID_UNSET; 621 } 622 623 /** 624 * Checks whether the provided_credentials are allowed to log in 625 * as the expected_credentials. 626 * 627 * @param expected_credentials credentials we're trying to log in as 628 * @param provided_credentials credentials we have 629 * @returns #TRUE if we can log in 630 */ 631 dbus_bool_t 632 _dbus_credentials_match (const DBusCredentials *expected_credentials, 633 const DBusCredentials *provided_credentials) 634 { 635 if (provided_credentials->uid == DBUS_UID_UNSET) 636 return FALSE; 637 else if (expected_credentials->uid == DBUS_UID_UNSET) 638 return FALSE; 639 else if (provided_credentials->uid == 0) 640 return TRUE; 641 else if (provided_credentials->uid == expected_credentials->uid) 642 return TRUE; 643 else 644 return FALSE; 645 } 646 647 _DBUS_DEFINE_GLOBAL_LOCK (atomic); 648 649 #ifdef DBUS_USE_ATOMIC_INT_486 650 /* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */ 651 /* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */ 652 static inline dbus_int32_t 653 atomic_exchange_and_add (DBusAtomic *atomic, 654 volatile dbus_int32_t val) 655 { 656 register dbus_int32_t result; 657 658 __asm__ __volatile__ ("lock; xaddl %0,%1" 659 : "=r" (result), "=m" (atomic->value) 660 : "0" (val), "m" (atomic->value)); 661 return result; 662 } 663 #endif 664 665 /** 666 * Atomically increments an integer 667 * 668 * @param atomic pointer to the integer to increment 669 * @returns the value before incrementing 670 * 671 * @todo implement arch-specific faster atomic ops 672 */ 673 dbus_int32_t 674 _dbus_atomic_inc (DBusAtomic *atomic) 675 { 676 #ifdef DBUS_USE_ATOMIC_INT_486 677 return atomic_exchange_and_add (atomic, 1); 678 #else 679 dbus_int32_t res; 680 _DBUS_LOCK (atomic); 681 res = atomic->value; 682 atomic->value += 1; 683 _DBUS_UNLOCK (atomic); 684 return res; 685 #endif 686 } 687 688 /** 689 * Atomically decrement an integer 690 * 691 * @param atomic pointer to the integer to decrement 692 * @returns the value before decrementing 693 * 694 * @todo implement arch-specific faster atomic ops 695 */ 696 dbus_int32_t 697 _dbus_atomic_dec (DBusAtomic *atomic) 698 { 699 #ifdef DBUS_USE_ATOMIC_INT_486 700 return atomic_exchange_and_add (atomic, -1); 701 #else 702 dbus_int32_t res; 703 704 _DBUS_LOCK (atomic); 705 res = atomic->value; 706 atomic->value -= 1; 707 _DBUS_UNLOCK (atomic); 708 return res; 709 #endif 710 } 711 712 void 713 _dbus_generate_pseudorandom_bytes_buffer (char *buffer, 714 int n_bytes) 715 { 716 long tv_usec; 717 int i; 718 719 /* fall back to pseudorandom */ 720 _dbus_verbose ("Falling back to pseudorandom for %d bytes\n", 721 n_bytes); 722 723 _dbus_get_current_time (NULL, &tv_usec); 724 srand (tv_usec); 725 726 i = 0; 727 while (i < n_bytes) 728 { 729 double r; 730 unsigned int b; 731 732 r = rand (); 733 b = (r / (double) RAND_MAX) * 255.0; 734 735 buffer[i] = b; 736 737 ++i; 738 } 739 } 740 741 /** 742 * Fills n_bytes of the given buffer with random bytes. 743 * 744 * @param buffer an allocated buffer 745 * @param n_bytes the number of bytes in buffer to write to 746 */ 747 void 748 _dbus_generate_random_bytes_buffer (char *buffer, 749 int n_bytes) 750 { 751 DBusString str; 752 753 if (!_dbus_string_init (&str)) 754 { 755 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes); 756 return; 757 } 758 759 if (!_dbus_generate_random_bytes (&str, n_bytes)) 760 { 761 _dbus_string_free (&str); 762 _dbus_generate_pseudorandom_bytes_buffer (buffer, n_bytes); 763 return; 764 } 765 766 _dbus_string_copy_to_buffer (&str, buffer, n_bytes); 767 768 _dbus_string_free (&str); 769 } 770 771 /** 772 * Generates the given number of random bytes, where the bytes are 773 * chosen from the alphanumeric ASCII subset. 774 * 775 * @param str the string 776 * @param n_bytes the number of random ASCII bytes to append to string 777 * @returns #TRUE on success, #FALSE if no memory or other failure 778 */ 779 dbus_bool_t 780 _dbus_generate_random_ascii (DBusString *str, 781 int n_bytes) 782 { 783 static const char letters[] = 784 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 785 int i; 786 int len; 787 788 if (!_dbus_generate_random_bytes (str, n_bytes)) 789 return FALSE; 790 791 len = _dbus_string_get_length (str); 792 i = len - n_bytes; 793 while (i < len) 794 { 795 _dbus_string_set_byte (str, i, 796 letters[_dbus_string_get_byte (str, i) % 797 (sizeof (letters) - 1)]); 798 799 ++i; 800 } 801 802 _dbus_assert (_dbus_string_validate_ascii (str, len - n_bytes, 803 n_bytes)); 804 805 return TRUE; 806 } 807 808 /** 809 * Gets a UID from a UID string. 810 * 811 * @param uid_str the UID in string form 812 * @param uid UID to fill in 813 * @returns #TRUE if successfully filled in UID 814 */ 815 dbus_bool_t 816 _dbus_parse_uid (const DBusString *uid_str, 817 dbus_uid_t *uid) 818 { 819 int end; 820 long val; 821 822 if (_dbus_string_get_length (uid_str) == 0) 823 { 824 _dbus_verbose ("UID string was zero length\n"); 825 return FALSE; 826 } 827 828 val = -1; 829 end = 0; 830 if (!_dbus_string_parse_int (uid_str, 0, &val, 831 &end)) 832 { 833 _dbus_verbose ("could not parse string as a UID\n"); 834 return FALSE; 835 } 836 837 if (end != _dbus_string_get_length (uid_str)) 838 { 839 _dbus_verbose ("string contained trailing stuff after UID\n"); 840 return FALSE; 841 } 842 843 *uid = val; 844 845 return TRUE; 846 } 847 848 /** 849 * Converts a UNIX or Windows errno 850 * into a #DBusError name. 851 * 852 * @todo should cover more errnos, specifically those 853 * from open(). 854 * 855 * @param error_number the errno. 856 * @returns an error name 857 */ 858 const char* 859 _dbus_error_from_errno (int error_number) 860 { 861 switch (error_number) 862 { 863 case 0: 864 return DBUS_ERROR_FAILED; 865 866 #ifdef EPROTONOSUPPORT 867 case EPROTONOSUPPORT: 868 return DBUS_ERROR_NOT_SUPPORTED; 869 #endif 870 #ifdef EAFNOSUPPORT 871 case EAFNOSUPPORT: 872 return DBUS_ERROR_NOT_SUPPORTED; 873 #endif 874 #ifdef ENFILE 875 case ENFILE: 876 return DBUS_ERROR_LIMITS_EXCEEDED; /* kernel out of memory */ 877 #endif 878 #ifdef EMFILE 879 case EMFILE: 880 return DBUS_ERROR_LIMITS_EXCEEDED; 881 #endif 882 #ifdef EACCES 883 case EACCES: 884 return DBUS_ERROR_ACCESS_DENIED; 885 #endif 886 #ifdef EPERM 887 case EPERM: 888 return DBUS_ERROR_ACCESS_DENIED; 889 #endif 890 #ifdef ENOBUFS 891 case ENOBUFS: 892 return DBUS_ERROR_NO_MEMORY; 893 #endif 894 #ifdef ENOMEM 895 case ENOMEM: 896 return DBUS_ERROR_NO_MEMORY; 897 #endif 898 #ifdef EINVAL 899 case EINVAL: 900 return DBUS_ERROR_FAILED; 901 #endif 902 #ifdef EBADF 903 case EBADF: 904 return DBUS_ERROR_FAILED; 905 #endif 906 #ifdef EFAULT 907 case EFAULT: 908 return DBUS_ERROR_FAILED; 909 #endif 910 #ifdef ENOTSOCK 911 case ENOTSOCK: 912 return DBUS_ERROR_FAILED; 913 #endif 914 #ifdef EISCONN 915 case EISCONN: 916 return DBUS_ERROR_FAILED; 917 #endif 918 #ifdef ECONNREFUSED 919 case ECONNREFUSED: 920 return DBUS_ERROR_NO_SERVER; 921 #endif 922 #ifdef ETIMEDOUT 923 case ETIMEDOUT: 924 return DBUS_ERROR_TIMEOUT; 925 #endif 926 #ifdef ENETUNREACH 927 case ENETUNREACH: 928 return DBUS_ERROR_NO_NETWORK; 929 #endif 930 #ifdef EADDRINUSE 931 case EADDRINUSE: 932 return DBUS_ERROR_ADDRESS_IN_USE; 933 #endif 934 #ifdef EEXIST 935 case EEXIST: 936 return DBUS_ERROR_FILE_EXISTS; 937 #endif 938 #ifdef ENOENT 939 case ENOENT: 940 return DBUS_ERROR_FILE_NOT_FOUND; 941 #endif 942 } 943 944 return DBUS_ERROR_FAILED; 945 } 946 947 /** @} end of sysdeps */ 948 949 /* tests in dbus-sysdeps-util.c */ 950