strerror_r: fix includes for FreeBSD
[gnulib.git] / lib / strerror_r.c
1 /* strerror_r.c --- POSIX compatible system error routine
2
3    Copyright (C) 2010-2011 Free Software Foundation, Inc.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 /* Written by Bruno Haible <bruno@clisp.org>, 2010.  */
19
20 #include <config.h>
21
22 /* Enable declaration of sys_nerr and sys_errlist in <errno.h> on NetBSD.  */
23 #define _NETBSD_SOURCE 1
24
25 /* Specification.  */
26 #include <string.h>
27
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #if GNULIB_defined_ESOCK /* native Windows platforms */
33 # if HAVE_WINSOCK2_H
34 #  include <winsock2.h>
35 # endif
36 #endif
37
38 /* Reasonable buffer size that should never trigger ERANGE; if this
39    proves too small, we intentionally abort(), to remind us to fix
40    this value as well as strerror-impl.h.  */
41 #define STACKBUF_LEN 256
42
43 #if (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__) && HAVE___XPG_STRERROR_R /* glibc >= 2.3.4, cygwin >= 1.7.9 */
44
45 # define USE_XPG_STRERROR_R 1
46
47 #elif HAVE_DECL_STRERROR_R && !(__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__)
48
49 /* The system's strerror_r function is OK, except that its third argument
50    is 'int', not 'size_t', or its return type is wrong.  */
51
52 # include <limits.h>
53
54 # define USE_SYSTEM_STRERROR_R 1
55
56 #else /* (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__ ? !HAVE___XPG_STRERROR_R : !HAVE_DECL_STRERROR_R) */
57
58 /* Use the system's strerror().  Exclude glibc and cygwin because the
59    system strerror_r has the wrong return type, and cygwin 1.7.9
60    strerror_r clobbers strerror.  */
61 # undef strerror
62
63 # define USE_SYSTEM_STRERROR 1
64
65 # if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __sgi || (defined __sun && !defined _LP64) || defined __CYGWIN__
66
67 /* No locking needed.  */
68
69 /* Get catgets internationalization functions.  */
70 #  if HAVE_CATGETS
71 #   include <nl_types.h>
72 #  endif
73
74 /* Get sys_nerr, sys_errlist on HP-UX (otherwise only declared in C++ mode).
75    Get sys_nerr, sys_errlist on IRIX (otherwise only declared with _SGIAPI).  */
76 #  if defined __hpux || defined __sgi
77 extern int sys_nerr;
78 extern char *sys_errlist[];
79 #  endif
80
81 /* Get sys_nerr on Solaris.  */
82 #  if defined __sun && !defined _LP64
83 extern int sys_nerr;
84 #  endif
85
86 # else
87
88 #  include "glthread/lock.h"
89
90 /* This lock protects the buffer returned by strerror().  We assume that
91    no other uses of strerror() exist in the program.  */
92 gl_lock_define_initialized(static, strerror_lock)
93
94 # endif
95
96 #endif
97
98 /* Copy as much of MSG into BUF as possible, without corrupting errno.
99    Return 0 if MSG fit in BUFLEN, otherwise return ERANGE.  */
100 static int
101 safe_copy (char *buf, size_t buflen, const char *msg)
102 {
103   size_t len = strlen (msg);
104   int ret;
105
106   if (len < buflen)
107     {
108       /* Although POSIX allows memcpy() to corrupt errno, we don't
109          know of any implementation where this is a real problem.  */
110       memcpy (buf, msg, len + 1);
111       ret = 0;
112     }
113   else
114     {
115       memcpy (buf, msg, buflen - 1);
116       buf[buflen - 1] = '\0';
117       ret = ERANGE;
118     }
119   return ret;
120 }
121
122
123 int
124 strerror_r (int errnum, char *buf, size_t buflen)
125 #undef strerror_r
126 {
127   /* Filter this out now, so that rest of this replacement knows that
128      there is room for a non-empty message and trailing NUL.  */
129   if (buflen <= 1)
130     {
131       if (buflen)
132         *buf = '\0';
133       return ERANGE;
134     }
135   *buf = '\0';
136
137 #if GNULIB_defined_ETXTBSY \
138     || GNULIB_defined_ESOCK \
139     || GNULIB_defined_ENOMSG \
140     || GNULIB_defined_EIDRM \
141     || GNULIB_defined_ENOLINK \
142     || GNULIB_defined_EPROTO \
143     || GNULIB_defined_EMULTIHOP \
144     || GNULIB_defined_EBADMSG \
145     || GNULIB_defined_EOVERFLOW \
146     || GNULIB_defined_ENOTSUP \
147     || GNULIB_defined_ESTALE \
148     || GNULIB_defined_EDQUOT \
149     || GNULIB_defined_ECANCELED
150   {
151     char const *msg = NULL;
152     /* These error messages are taken from glibc/sysdeps/gnu/errlist.c.  */
153     switch (errnum)
154       {
155 # if GNULIB_defined_ETXTBSY
156       case ETXTBSY:
157         msg = "Text file busy";
158         break;
159 # endif
160
161 # if GNULIB_defined_ESOCK /* native Windows platforms */
162       /* EWOULDBLOCK is the same as EAGAIN.  */
163       case EINPROGRESS:
164         msg = "Operation now in progress";
165         break;
166       case EALREADY:
167         msg = "Operation already in progress";
168         break;
169       case ENOTSOCK:
170         msg = "Socket operation on non-socket";
171         break;
172       case EDESTADDRREQ:
173         msg = "Destination address required";
174         break;
175       case EMSGSIZE:
176         msg = "Message too long";
177         break;
178       case EPROTOTYPE:
179         msg = "Protocol wrong type for socket";
180         break;
181       case ENOPROTOOPT:
182         msg = "Protocol not available";
183         break;
184       case EPROTONOSUPPORT:
185         msg = "Protocol not supported";
186         break;
187       case ESOCKTNOSUPPORT:
188         msg = "Socket type not supported";
189         break;
190       case EOPNOTSUPP:
191         msg = "Operation not supported";
192         break;
193       case EPFNOSUPPORT:
194         msg = "Protocol family not supported";
195         break;
196       case EAFNOSUPPORT:
197         msg = "Address family not supported by protocol";
198         break;
199       case EADDRINUSE:
200         msg = "Address already in use";
201         break;
202       case EADDRNOTAVAIL:
203         msg = "Cannot assign requested address";
204         break;
205       case ENETDOWN:
206         msg = "Network is down";
207         break;
208       case ENETUNREACH:
209         msg = "Network is unreachable";
210         break;
211       case ENETRESET:
212         msg = "Network dropped connection on reset";
213         break;
214       case ECONNABORTED:
215         msg = "Software caused connection abort";
216         break;
217       case ECONNRESET:
218         msg = "Connection reset by peer";
219         break;
220       case ENOBUFS:
221         msg = "No buffer space available";
222         break;
223       case EISCONN:
224         msg = "Transport endpoint is already connected";
225         break;
226       case ENOTCONN:
227         msg = "Transport endpoint is not connected";
228         break;
229       case ESHUTDOWN:
230         msg = "Cannot send after transport endpoint shutdown";
231         break;
232       case ETOOMANYREFS:
233         msg = "Too many references: cannot splice";
234         break;
235       case ETIMEDOUT:
236         msg = "Connection timed out";
237         break;
238       case ECONNREFUSED:
239         msg = "Connection refused";
240         break;
241       case ELOOP:
242         msg = "Too many levels of symbolic links";
243         break;
244       case EHOSTDOWN:
245         msg = "Host is down";
246         break;
247       case EHOSTUNREACH:
248         msg = "No route to host";
249         break;
250       case EPROCLIM:
251         msg = "Too many processes";
252         break;
253       case EUSERS:
254         msg = "Too many users";
255         break;
256       case EDQUOT:
257         msg = "Disk quota exceeded";
258         break;
259       case ESTALE:
260         msg = "Stale NFS file handle";
261         break;
262       case EREMOTE:
263         msg = "Object is remote";
264         break;
265 #  if HAVE_WINSOCK2_H
266       /* WSA_INVALID_HANDLE maps to EBADF */
267       /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */
268       /* WSA_INVALID_PARAMETER maps to EINVAL */
269       case WSA_OPERATION_ABORTED:
270         msg = "Overlapped operation aborted";
271         break;
272       case WSA_IO_INCOMPLETE:
273         msg = "Overlapped I/O event object not in signaled state";
274         break;
275       case WSA_IO_PENDING:
276         msg = "Overlapped operations will complete later";
277         break;
278       /* WSAEINTR maps to EINTR */
279       /* WSAEBADF maps to EBADF */
280       /* WSAEACCES maps to EACCES */
281       /* WSAEFAULT maps to EFAULT */
282       /* WSAEINVAL maps to EINVAL */
283       /* WSAEMFILE maps to EMFILE */
284       /* WSAEWOULDBLOCK maps to EWOULDBLOCK */
285       /* WSAEINPROGRESS is EINPROGRESS */
286       /* WSAEALREADY is EALREADY */
287       /* WSAENOTSOCK is ENOTSOCK */
288       /* WSAEDESTADDRREQ is EDESTADDRREQ */
289       /* WSAEMSGSIZE is EMSGSIZE */
290       /* WSAEPROTOTYPE is EPROTOTYPE */
291       /* WSAENOPROTOOPT is ENOPROTOOPT */
292       /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */
293       /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */
294       /* WSAEOPNOTSUPP is EOPNOTSUPP */
295       /* WSAEPFNOSUPPORT is EPFNOSUPPORT */
296       /* WSAEAFNOSUPPORT is EAFNOSUPPORT */
297       /* WSAEADDRINUSE is EADDRINUSE */
298       /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */
299       /* WSAENETDOWN is ENETDOWN */
300       /* WSAENETUNREACH is ENETUNREACH */
301       /* WSAENETRESET is ENETRESET */
302       /* WSAECONNABORTED is ECONNABORTED */
303       /* WSAECONNRESET is ECONNRESET */
304       /* WSAENOBUFS is ENOBUFS */
305       /* WSAEISCONN is EISCONN */
306       /* WSAENOTCONN is ENOTCONN */
307       /* WSAESHUTDOWN is ESHUTDOWN */
308       /* WSAETOOMANYREFS is ETOOMANYREFS */
309       /* WSAETIMEDOUT is ETIMEDOUT */
310       /* WSAECONNREFUSED is ECONNREFUSED */
311       /* WSAELOOP is ELOOP */
312       /* WSAENAMETOOLONG maps to ENAMETOOLONG */
313       /* WSAEHOSTDOWN is EHOSTDOWN */
314       /* WSAEHOSTUNREACH is EHOSTUNREACH */
315       /* WSAENOTEMPTY maps to ENOTEMPTY */
316       /* WSAEPROCLIM is EPROCLIM */
317       /* WSAEUSERS is EUSERS */
318       /* WSAEDQUOT is EDQUOT */
319       /* WSAESTALE is ESTALE */
320       /* WSAEREMOTE is EREMOTE */
321       case WSASYSNOTREADY:
322         msg = "Network subsystem is unavailable";
323         break;
324       case WSAVERNOTSUPPORTED:
325         msg = "Winsock.dll version out of range";
326         break;
327       case WSANOTINITIALISED:
328         msg = "Successful WSAStartup not yet performed";
329         break;
330       case WSAEDISCON:
331         msg = "Graceful shutdown in progress";
332         break;
333       case WSAENOMORE: case WSA_E_NO_MORE:
334         msg = "No more results";
335         break;
336       case WSAECANCELLED: case WSA_E_CANCELLED:
337         msg = "Call was canceled";
338         break;
339       case WSAEINVALIDPROCTABLE:
340         msg = "Procedure call table is invalid";
341         break;
342       case WSAEINVALIDPROVIDER:
343         msg = "Service provider is invalid";
344         break;
345       case WSAEPROVIDERFAILEDINIT:
346         msg = "Service provider failed to initialize";
347         break;
348       case WSASYSCALLFAILURE:
349         msg = "System call failure";
350         break;
351       case WSASERVICE_NOT_FOUND:
352         msg = "Service not found";
353         break;
354       case WSATYPE_NOT_FOUND:
355         msg = "Class type not found";
356         break;
357       case WSAEREFUSED:
358         msg = "Database query was refused";
359         break;
360       case WSAHOST_NOT_FOUND:
361         msg = "Host not found";
362         break;
363       case WSATRY_AGAIN:
364         msg = "Nonauthoritative host not found";
365         break;
366       case WSANO_RECOVERY:
367         msg = "Nonrecoverable error";
368         break;
369       case WSANO_DATA:
370         msg = "Valid name, no data record of requested type";
371         break;
372       /* WSA_QOS_* omitted */
373 #  endif
374 # endif
375
376 # if GNULIB_defined_ENOMSG
377       case ENOMSG:
378         msg = "No message of desired type";
379         break;
380 # endif
381
382 # if GNULIB_defined_EIDRM
383       case EIDRM:
384         msg = "Identifier removed";
385         break;
386 # endif
387
388 # if GNULIB_defined_ENOLINK
389       case ENOLINK:
390         msg = "Link has been severed";
391         break;
392 # endif
393
394 # if GNULIB_defined_EPROTO
395       case EPROTO:
396         msg = "Protocol error";
397         break;
398 # endif
399
400 # if GNULIB_defined_EMULTIHOP
401       case EMULTIHOP:
402         msg = "Multihop attempted";
403         break;
404 # endif
405
406 # if GNULIB_defined_EBADMSG
407       case EBADMSG:
408         msg = "Bad message";
409         break;
410 # endif
411
412 # if GNULIB_defined_EOVERFLOW
413       case EOVERFLOW:
414         msg = "Value too large for defined data type";
415         break;
416 # endif
417
418 # if GNULIB_defined_ENOTSUP
419       case ENOTSUP:
420         msg = "Not supported";
421         break;
422 # endif
423
424 # if GNULIB_defined_ESTALE
425       case ESTALE:
426         msg = "Stale NFS file handle";
427         break;
428 # endif
429
430 # if GNULIB_defined_EDQUOT
431       case EDQUOT:
432         msg = "Disk quota exceeded";
433         break;
434 # endif
435
436 # if GNULIB_defined_ECANCELED
437       case ECANCELED:
438         msg = "Operation canceled";
439         break;
440 # endif
441       }
442
443     if (msg)
444       return safe_copy (buf, buflen, msg);
445   }
446 #endif
447
448   {
449     int ret;
450     int saved_errno = errno;
451
452 #if USE_XPG_STRERROR_R
453
454     {
455       extern int __xpg_strerror_r (int errnum, char *buf, size_t buflen);
456
457       ret = __xpg_strerror_r (errnum, buf, buflen);
458       if (ret < 0)
459         ret = errno;
460       if (!*buf)
461         {
462           /* glibc 2.13 would not touch buf on err, so we have to fall
463              back to GNU strerror_r which always returns a thread-safe
464              untruncated string to (partially) copy into our buf.  */
465           safe_copy (buf, buflen, strerror_r (errnum, buf, buflen));
466         }
467     }
468
469 #elif USE_SYSTEM_STRERROR_R
470
471     if (buflen > INT_MAX)
472       buflen = INT_MAX;
473
474 # ifdef __hpux
475     /* On HP-UX 11.31, strerror_r always fails when buflen < 80; it
476        also fails to change buf on EINVAL.  */
477     {
478       char stackbuf[80];
479
480       if (buflen < sizeof stackbuf)
481         {
482           ret = strerror_r (errnum, stackbuf, sizeof stackbuf);
483           if (ret == 0)
484             ret = safe_copy (buf, buflen, stackbuf);
485         }
486       else
487         ret = strerror_r (errnum, buf, buflen);
488     }
489 # else
490     /* Solaris 10 does not populate buf on ERANGE.  */
491     ret = strerror_r (errnum, buf, buflen);
492     if (ret == ERANGE && !*buf)
493       {
494         char stackbuf[STACKBUF_LEN];
495
496         /* strerror-impl.h is also affected if our choice of stackbuf
497            size is not large enough.  */
498         if (strerror_r (errnum, stackbuf, sizeof stackbuf) == ERANGE)
499           abort ();
500         safe_copy (buf, buflen, stackbuf);
501       }
502 # endif
503
504 # ifdef _AIX
505     /* AIX returns 0 rather than ERANGE when truncating strings; try
506        again until we are sure we got the entire string.  */
507     if (!ret && strlen (buf) == buflen - 1)
508       {
509         char stackbuf[STACKBUF_LEN];
510         size_t len;
511         strerror_r (errnum, stackbuf, sizeof stackbuf);
512         len = strlen (stackbuf);
513         /* stackbuf should have been large enough.  */
514         if (len + 1 == sizeof stackbuf)
515           abort ();
516         if (buflen <= len)
517           ret = ERANGE;
518       }
519 # endif
520
521     /* Some old implementations may return (-1, EINVAL) instead of EINVAL.  */
522     if (ret < 0)
523       ret = errno;
524
525     /* FreeBSD rejects 0; see http://austingroupbugs.net/view.php?id=382.  */
526     if (errnum == 0 && ret == EINVAL)
527       ret = safe_copy (buf, buflen, "Success");
528
529 #else /* USE_SYSTEM_STRERROR */
530
531     /* Try to do what strerror (errnum) does, but without clobbering the
532        buffer used by strerror().  */
533
534 # if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __CYGWIN__ /* NetBSD, HP-UX, native Win32, Cygwin */
535
536     /* NetBSD:        sys_nerr, sys_errlist are declared through _NETBSD_SOURCE
537                       and <errno.h> above.
538        HP-UX:         sys_nerr, sys_errlist are declared explicitly above.
539        native Win32:  sys_nerr, sys_errlist are declared in <stdlib.h>.
540        Cygwin:        sys_nerr, sys_errlist are declared in <errno.h>.  */
541     if (errnum >= 0 && errnum < sys_nerr)
542       {
543 #  if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux)
544 #   if defined __NetBSD__
545         nl_catd catd = catopen ("libc", NL_CAT_LOCALE);
546         const char *errmsg =
547           (catd != (nl_catd)-1
548            ? catgets (catd, 1, errnum, sys_errlist[errnum])
549            : sys_errlist[errnum]);
550 #   endif
551 #   if defined __hpux
552         nl_catd catd = catopen ("perror", NL_CAT_LOCALE);
553         const char *errmsg =
554           (catd != (nl_catd)-1
555            ? catgets (catd, 1, 1 + errnum, sys_errlist[errnum])
556            : sys_errlist[errnum]);
557 #   endif
558 #  else
559         const char *errmsg = sys_errlist[errnum];
560 #  endif
561         if (errmsg == NULL || *errmsg == '\0')
562           ret = EINVAL;
563         else
564           ret = safe_copy (buf, buflen, errmsg);
565 #  if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux)
566         if (catd != (nl_catd)-1)
567           catclose (catd);
568 #  endif
569       }
570     else
571       ret = EINVAL;
572
573 # elif defined __sgi || (defined __sun && !defined _LP64) /* IRIX, Solaris <= 9 32-bit */
574
575     /* For a valid error number, the system's strerror() function returns
576        a pointer to a not copied string, not to a buffer.  */
577     if (errnum >= 0 && errnum < sys_nerr)
578       {
579         char *errmsg = strerror (errnum);
580
581         if (errmsg == NULL || *errmsg == '\0')
582           ret = EINVAL;
583         else
584           ret = safe_copy (buf, buflen, errmsg);
585       }
586     else
587       ret = EINVAL;
588
589 # else
590
591     gl_lock_lock (strerror_lock);
592
593     {
594       char *errmsg = strerror (errnum);
595
596       /* For invalid error numbers, strerror() on
597            - IRIX 6.5 returns NULL,
598            - HP-UX 11 returns an empty string.  */
599       if (errmsg == NULL || *errmsg == '\0')
600         ret = EINVAL;
601       else
602         ret = safe_copy (buf, buflen, errmsg);
603     }
604
605     gl_lock_unlock (strerror_lock);
606
607 # endif
608
609 #endif
610
611     if (ret == EINVAL && !*buf)
612       snprintf (buf, buflen, "Unknown error %d", errnum);
613
614     errno = saved_errno;
615     return ret;
616   }
617 }