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