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