|
version 1.1, 2012/02/21 22:57:48
|
version 1.1.1.3, 2021/03/17 13:38:46
|
|
Line 1
|
Line 1
|
| /* strerror.c --- POSIX compatible system error routine |
/* strerror.c --- POSIX compatible system error routine |
| |
|
| Copyright (C) 2007-2009 Free Software Foundation, Inc. | Copyright (C) 2007-2019 Free Software Foundation, Inc. |
| |
|
| This program is free software: you can redistribute it and/or modify |
This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
|
Line 13
|
Line 13
|
| GNU General Public License for more details. |
GNU General Public License for more details. |
| |
|
| You should have received a copy of the GNU General Public License |
You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
| |
|
| #include <config.h> |
#include <config.h> |
| |
|
| |
/* Specification. */ |
| #include <string.h> |
#include <string.h> |
| |
|
| #if REPLACE_STRERROR | #include <errno.h> |
| | #include <stdio.h> |
| | #include <stdlib.h> |
| | #include <string.h> |
| |
|
| # include <errno.h> | #include "intprops.h" |
| # include <stdio.h> | #include "strerror-override.h" |
| | #include "verify.h" |
| |
|
| # if GNULIB_defined_ESOCK /* native Windows platforms */ | /* Use the system functions, not the gnulib overrides in this file. */ |
| # if HAVE_WINSOCK2_H | #undef sprintf |
| # include <winsock2.h> | |
| # endif | |
| # endif | |
| |
|
| # include "intprops.h" |
|
| |
|
| # undef strerror |
|
| # if ! HAVE_DECL_STRERROR |
|
| # define strerror(n) NULL |
|
| # endif |
|
| |
|
| char * |
char * |
| rpl_strerror (int n) | strerror (int n) |
| | #undef strerror |
| { |
{ |
| char const *msg = NULL; | static char buf[STACKBUF_LEN]; |
| /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ | size_t len; |
| switch (n) | |
| { | |
| # if GNULIB_defined_ETXTBSY | |
| case ETXTBSY: | |
| msg = "Text file busy"; | |
| break; | |
| # endif | |
| |
|
| # if GNULIB_defined_ESOCK /* native Windows platforms */ | /* Cast away const, due to the historical signature of strerror; |
| /* EWOULDBLOCK is the same as EAGAIN. */ | callers should not be modifying the string. */ |
| case EINPROGRESS: | const char *msg = strerror_override (n); |
| msg = "Operation now in progress"; | |
| break; | |
| case EALREADY: | |
| msg = "Operation already in progress"; | |
| break; | |
| case ENOTSOCK: | |
| msg = "Socket operation on non-socket"; | |
| break; | |
| case EDESTADDRREQ: | |
| msg = "Destination address required"; | |
| break; | |
| case EMSGSIZE: | |
| msg = "Message too long"; | |
| break; | |
| case EPROTOTYPE: | |
| msg = "Protocol wrong type for socket"; | |
| break; | |
| case ENOPROTOOPT: | |
| msg = "Protocol not available"; | |
| break; | |
| case EPROTONOSUPPORT: | |
| msg = "Protocol not supported"; | |
| break; | |
| case ESOCKTNOSUPPORT: | |
| msg = "Socket type not supported"; | |
| break; | |
| case EOPNOTSUPP: | |
| msg = "Operation not supported"; | |
| break; | |
| case EPFNOSUPPORT: | |
| msg = "Protocol family not supported"; | |
| break; | |
| case EAFNOSUPPORT: | |
| msg = "Address family not supported by protocol"; | |
| break; | |
| case EADDRINUSE: | |
| msg = "Address already in use"; | |
| break; | |
| case EADDRNOTAVAIL: | |
| msg = "Cannot assign requested address"; | |
| break; | |
| case ENETDOWN: | |
| msg = "Network is down"; | |
| break; | |
| case ENETUNREACH: | |
| msg = "Network is unreachable"; | |
| break; | |
| case ENETRESET: | |
| msg = "Network dropped connection on reset"; | |
| break; | |
| case ECONNABORTED: | |
| msg = "Software caused connection abort"; | |
| break; | |
| case ECONNRESET: | |
| msg = "Connection reset by peer"; | |
| break; | |
| case ENOBUFS: | |
| msg = "No buffer space available"; | |
| break; | |
| case EISCONN: | |
| msg = "Transport endpoint is already connected"; | |
| break; | |
| case ENOTCONN: | |
| msg = "Transport endpoint is not connected"; | |
| break; | |
| case ESHUTDOWN: | |
| msg = "Cannot send after transport endpoint shutdown"; | |
| break; | |
| case ETOOMANYREFS: | |
| msg = "Too many references: cannot splice"; | |
| break; | |
| case ETIMEDOUT: | |
| msg = "Connection timed out"; | |
| break; | |
| case ECONNREFUSED: | |
| msg = "Connection refused"; | |
| break; | |
| case ELOOP: | |
| msg = "Too many levels of symbolic links"; | |
| break; | |
| case EHOSTDOWN: | |
| msg = "Host is down"; | |
| break; | |
| case EHOSTUNREACH: | |
| msg = "No route to host"; | |
| break; | |
| case EPROCLIM: | |
| msg = "Too many processes"; | |
| break; | |
| case EUSERS: | |
| msg = "Too many users"; | |
| break; | |
| case EDQUOT: | |
| msg = "Disk quota exceeded"; | |
| break; | |
| case ESTALE: | |
| msg = "Stale NFS file handle"; | |
| break; | |
| case EREMOTE: | |
| msg = "Object is remote"; | |
| break; | |
| # if HAVE_WINSOCK2_H | |
| /* WSA_INVALID_HANDLE maps to EBADF */ | |
| /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */ | |
| /* WSA_INVALID_PARAMETER maps to EINVAL */ | |
| case WSA_OPERATION_ABORTED: | |
| msg = "Overlapped operation aborted"; | |
| break; | |
| case WSA_IO_INCOMPLETE: | |
| msg = "Overlapped I/O event object not in signaled state"; | |
| break; | |
| case WSA_IO_PENDING: | |
| msg = "Overlapped operations will complete later"; | |
| break; | |
| /* WSAEINTR maps to EINTR */ | |
| /* WSAEBADF maps to EBADF */ | |
| /* WSAEACCES maps to EACCES */ | |
| /* WSAEFAULT maps to EFAULT */ | |
| /* WSAEINVAL maps to EINVAL */ | |
| /* WSAEMFILE maps to EMFILE */ | |
| /* WSAEWOULDBLOCK maps to EWOULDBLOCK */ | |
| /* WSAEINPROGRESS is EINPROGRESS */ | |
| /* WSAEALREADY is EALREADY */ | |
| /* WSAENOTSOCK is ENOTSOCK */ | |
| /* WSAEDESTADDRREQ is EDESTADDRREQ */ | |
| /* WSAEMSGSIZE is EMSGSIZE */ | |
| /* WSAEPROTOTYPE is EPROTOTYPE */ | |
| /* WSAENOPROTOOPT is ENOPROTOOPT */ | |
| /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */ | |
| /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */ | |
| /* WSAEOPNOTSUPP is EOPNOTSUPP */ | |
| /* WSAEPFNOSUPPORT is EPFNOSUPPORT */ | |
| /* WSAEAFNOSUPPORT is EAFNOSUPPORT */ | |
| /* WSAEADDRINUSE is EADDRINUSE */ | |
| /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */ | |
| /* WSAENETDOWN is ENETDOWN */ | |
| /* WSAENETUNREACH is ENETUNREACH */ | |
| /* WSAENETRESET is ENETRESET */ | |
| /* WSAECONNABORTED is ECONNABORTED */ | |
| /* WSAECONNRESET is ECONNRESET */ | |
| /* WSAENOBUFS is ENOBUFS */ | |
| /* WSAEISCONN is EISCONN */ | |
| /* WSAENOTCONN is ENOTCONN */ | |
| /* WSAESHUTDOWN is ESHUTDOWN */ | |
| /* WSAETOOMANYREFS is ETOOMANYREFS */ | |
| /* WSAETIMEDOUT is ETIMEDOUT */ | |
| /* WSAECONNREFUSED is ECONNREFUSED */ | |
| /* WSAELOOP is ELOOP */ | |
| /* WSAENAMETOOLONG maps to ENAMETOOLONG */ | |
| /* WSAEHOSTDOWN is EHOSTDOWN */ | |
| /* WSAEHOSTUNREACH is EHOSTUNREACH */ | |
| /* WSAENOTEMPTY maps to ENOTEMPTY */ | |
| /* WSAEPROCLIM is EPROCLIM */ | |
| /* WSAEUSERS is EUSERS */ | |
| /* WSAEDQUOT is EDQUOT */ | |
| /* WSAESTALE is ESTALE */ | |
| /* WSAEREMOTE is EREMOTE */ | |
| case WSASYSNOTREADY: | |
| msg = "Network subsystem is unavailable"; | |
| break; | |
| case WSAVERNOTSUPPORTED: | |
| msg = "Winsock.dll version out of range"; | |
| break; | |
| case WSANOTINITIALISED: | |
| msg = "Successful WSAStartup not yet performed"; | |
| break; | |
| case WSAEDISCON: | |
| msg = "Graceful shutdown in progress"; | |
| break; | |
| case WSAENOMORE: case WSA_E_NO_MORE: | |
| msg = "No more results"; | |
| break; | |
| case WSAECANCELLED: case WSA_E_CANCELLED: | |
| msg = "Call was canceled"; | |
| break; | |
| case WSAEINVALIDPROCTABLE: | |
| msg = "Procedure call table is invalid"; | |
| break; | |
| case WSAEINVALIDPROVIDER: | |
| msg = "Service provider is invalid"; | |
| break; | |
| case WSAEPROVIDERFAILEDINIT: | |
| msg = "Service provider failed to initialize"; | |
| break; | |
| case WSASYSCALLFAILURE: | |
| msg = "System call failure"; | |
| break; | |
| case WSASERVICE_NOT_FOUND: | |
| msg = "Service not found"; | |
| break; | |
| case WSATYPE_NOT_FOUND: | |
| msg = "Class type not found"; | |
| break; | |
| case WSAEREFUSED: | |
| msg = "Database query was refused"; | |
| break; | |
| case WSAHOST_NOT_FOUND: | |
| msg = "Host not found"; | |
| break; | |
| case WSATRY_AGAIN: | |
| msg = "Nonauthoritative host not found"; | |
| break; | |
| case WSANO_RECOVERY: | |
| msg = "Nonrecoverable error"; | |
| break; | |
| case WSANO_DATA: | |
| msg = "Valid name, no data record of requested type"; | |
| break; | |
| /* WSA_QOS_* omitted */ | |
| # endif | |
| # endif | |
| |
| # if GNULIB_defined_ENOMSG | |
| case ENOMSG: | |
| msg = "No message of desired type"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_EIDRM | |
| case EIDRM: | |
| msg = "Identifier removed"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_ENOLINK | |
| case ENOLINK: | |
| msg = "Link has been severed"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_EPROTO | |
| case EPROTO: | |
| msg = "Protocol error"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_EMULTIHOP | |
| case EMULTIHOP: | |
| msg = "Multihop attempted"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_EBADMSG | |
| case EBADMSG: | |
| msg = "Bad message"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_EOVERFLOW | |
| case EOVERFLOW: | |
| msg = "Value too large for defined data type"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_ENOTSUP | |
| case ENOTSUP: | |
| msg = "Not supported"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_ESTALE | |
| case ESTALE: | |
| msg = "Stale NFS file handle"; | |
| break; | |
| # endif | |
| |
| # if GNULIB_defined_ECANCELED | |
| case ECANCELED: | |
| msg = "Operation canceled"; | |
| break; | |
| # endif | |
| } | |
| |
| if (msg) |
if (msg) |
| return (char *) msg; |
return (char *) msg; |
| |
|
| { | msg = strerror (n); |
| char *result = strerror (n); | |
| |
|
| if (result == NULL || result[0] == '\0') | /* Our strerror_r implementation might use the system's strerror |
| { | buffer, so all other clients of strerror have to see the error |
| static char const fmt[] = "Unknown error (%d)"; | copied into a buffer that we manage. This is not thread-safe, |
| static char msg_buf[sizeof fmt + INT_STRLEN_BOUND (n)]; | even if the system strerror is, but portable programs shouldn't |
| sprintf (msg_buf, fmt, n); | be using strerror if they care about thread-safety. */ |
| return msg_buf; | if (!msg || !*msg) |
| } | { |
| | static char const fmt[] = "Unknown error %d"; |
| | verify (sizeof buf >= sizeof (fmt) + INT_STRLEN_BOUND (n)); |
| | sprintf (buf, fmt, n); |
| | errno = EINVAL; |
| | return buf; |
| | } |
| |
|
| return result; | /* Fix STACKBUF_LEN if this ever aborts. */ |
| } | len = strlen (msg); |
| } | if (sizeof buf <= len) |
| | abort (); |
| |
|
| #endif | memcpy (buf, msg, len + 1); |
| | return buf; |
| | } |