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