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