[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: perror bug
From: |
Bruno Haible |
Subject: |
Re: perror bug |
Date: |
Thu, 19 May 2011 05:27:23 +0200 |
User-agent: |
KMail/1.9.9 |
On 2011-14-03 I wrote in
<http://lists.gnu.org/archive/html/bug-gnulib/2011-03/msg00117.html>:
> With gnulib, there are three problems
> in toto:
> 1) The strerror_r replacement, when EXTEND_STRERROR_R is defined,
> clobbers the strerror function's buffer, which it shouldn't.
> 2) The perror replacement uses strerror, thus clobbering the strerror
> buffer.
> 3) On Cygwin, perror clobbers the strerror buffer.
>
> The fix for 1) should be to move most of lib/strerror.c to lib/strerror_r.c.
> The fix for 2) should be to change lib/perror.c to call strerror_r.
> The fix for 3) should be to change m4/perror.m4 to enable the replacement
> on Cygwin.
Here comes the fix for 1). Tested on
glibc 2.8
glibc 2.8 with -D_POSIX_C_SOURCE=200112L
MacOS X 10.5
OpenBSD 4.4
AIX 5.1
AIX 6.1
HP-UX 11.23
HP-UX 11.31
IRIX 6.5
OSF/1 5.1
Solaris 9
Solaris 10
mingw
Cygwin 1.5.x
2011-05-18 Bruno Haible <address@hidden>
strerror_r: Avoid clobbering the strerror buffer when possible.
* lib/strerror_r.c (strerror_r): Merge the three implementations.
Handle gnulib defined errno values here. When strerror() returns NULL
or an empty string, return EINVAL.
* lib/strerror.c (strerror): Always call strerror_r. Don't handle
gnulib defined errno values here.
* modules/strerror (Depends-on): Add verify, strerror_r-posix.
*** lib/strerror.c.orig Thu May 19 05:17:36 2011
--- lib/strerror.c Thu May 19 04:47:44 2011
***************
*** 17,355 ****
#include <config.h>
#include <string.h>
#if REPLACE_STRERROR
# include <errno.h>
# include <stdio.h>
!
! # if GNULIB_defined_ESOCK /* native Windows platforms */
! # if HAVE_WINSOCK2_H
! # include <winsock2.h>
! # endif
! # endif
# include "intprops.h"
/* Use the system functions, not the gnulib overrides in this file. */
# undef sprintf
- # undef strerror
- # if ! HAVE_DECL_STRERROR
- # define strerror(n) NULL
- # endif
-
char *
! rpl_strerror (int n)
{
! char const *msg = NULL;
! /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */
! switch (n)
! {
! # if GNULIB_defined_ETXTBSY
! case ETXTBSY:
! msg = "Text file busy";
! break;
! # endif
!
! # if GNULIB_defined_ESOCK /* native Windows platforms */
! /* EWOULDBLOCK is the same as EAGAIN. */
! case EINPROGRESS:
! 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_EDQUOT
! case EDQUOT:
! msg = "Disk quota exceeded";
! break;
! # endif
!
! # if GNULIB_defined_ECANCELED
! case ECANCELED:
! msg = "Operation canceled";
! break;
! # endif
! }
! if (msg)
! return (char *) msg;
! {
! char *result = strerror (n);
! if (result == NULL || result[0] == '\0')
! {
! static char const fmt[] = "Unknown error (%d)";
! static char msg_buf[sizeof fmt + INT_STRLEN_BOUND (n)];
! sprintf (msg_buf, fmt, n);
! return msg_buf;
! }
! return result;
}
}
--- 17,56 ----
#include <config.h>
+ /* Specification. */
#include <string.h>
#if REPLACE_STRERROR
# include <errno.h>
# include <stdio.h>
! # include <stdlib.h>
# include "intprops.h"
+ # include "verify.h"
/* Use the system functions, not the gnulib overrides in this file. */
# undef sprintf
char *
! strerror (int n)
{
! static char buf[256];
! int ret = strerror_r (n, buf, sizeof (buf));
! if (ret == 0)
! return buf;
! if (ret == ERANGE)
! /* If this happens, increase the size of buf. */
! abort ();
! {
! static char const fmt[] = "Unknown error (%d)";
! verify (sizeof (buf) >= sizeof (fmt) + INT_STRLEN_BOUND (n));
! sprintf (buf, fmt, n);
! return buf;
}
}
*** lib/strerror_r.c.orig Thu May 19 05:17:36 2011
--- lib/strerror_r.c Thu May 19 05:04:39 2011
***************
*** 24,143 ****
#include <errno.h>
! #if HAVE_DECL_STRERROR_R && !(__GLIBC__ >= 2 || defined __UCLIBC__) &&
!EXTEND_STRERROR_R
/* The system's strerror_r function is OK, except that its third argument
is 'int', not 'size_t', or its return type is wrong. */
# include <limits.h>
int
strerror_r (int errnum, char *buf, size_t buflen)
! # undef strerror_r
{
! int ret;
! if (buflen > INT_MAX)
! buflen = INT_MAX;
! # ifdef __hpux
! /* On HP-UX 11.31, strerror_r always fails when buflen < 80. */
! {
! char stackbuf[80];
! if (buflen < sizeof (stackbuf))
{
! ret = strerror_r (errnum, stackbuf, sizeof (stackbuf));
! if (ret == 0)
! {
! size_t len = strlen (stackbuf);
! if (len < buflen)
! memcpy (buf, stackbuf, len + 1);
! else
! ret = ERANGE;
}
}
- else
- ret = strerror_r (errnum, buf, buflen);
}
! # elif defined __CYGWIN__
! /* Cygwin only provides the glibc interface, is thread-safe, and
! always succeeds (although it may truncate). */
! strerror_r (errnum, buf, buflen);
! ret = 0;
! # else
! ret = strerror_r (errnum, buf, buflen);
! # endif
! # ifdef _AIX
! /* On AIX 6.1, strerror_r returns -1 and sets errno to EINVAL
! if buflen <= 1. */
! if (ret < 0 && errno == EINVAL && buflen <= 1)
{
! /* Retry with a larger buffer. */
! char largerbuf[10];
! ret = strerror_r (errnum, largerbuf, sizeof (largerbuf));
! if (ret < 0 && errno == EINVAL)
{
! /* errnum was out of range. */
! return EINVAL;
}
else
! {
! /* buf was too small. */
! return ERANGE;
! }
}
# endif
! /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */
! return (ret < 0 ? errno : ret);
! }
!
! #elif (__GLIBC__ >= 2 || defined __UCLIBC__) && HAVE___XPG_STRERROR_R /*
glibc >= 2.3.4 */ && !EXTEND_STRERROR_R
! int
! strerror_r (int errnum, char *buf, size_t buflen)
! {
! extern int __xpg_strerror_r (int errnum, char *buf, size_t buflen);
! int ret = __xpg_strerror_r (errnum, buf, buflen);
! return (ret < 0 ? errno : ret);
! }
! #else /* (__GLIBC__ >= 2 || defined __UCLIBC__ ? !HAVE___XPG_STRERROR_R :
!HAVE_DECL_STRERROR_R) || EXTEND_STRERROR_R */
! # include "glthread/lock.h"
! /* Use strerror(), with locking. */
! /* This lock protects the buffer returned by strerror(). We assume that
! no other uses of strerror() exist in the program. */
! gl_lock_define_initialized(static, strerror_lock)
! int
! strerror_r (int errnum, char *buf, size_t buflen)
! {
! gl_lock_lock (strerror_lock);
! {
! char *errmsg = strerror (errnum);
! size_t len = strlen (errmsg);
! int ret;
! if (len < buflen)
! {
! memcpy (buf, errmsg, len + 1);
! ret = 0;
! }
! else
! ret = ERANGE;
gl_lock_unlock (strerror_lock);
return ret;
}
}
-
- #endif
--- 24,481 ----
#include <errno.h>
! # if GNULIB_defined_ESOCK /* native Windows platforms */
! # if HAVE_WINSOCK2_H
! # include <winsock2.h>
! # endif
! # endif
!
!
! #if HAVE_DECL_STRERROR_R && !(__GLIBC__ >= 2 || defined __UCLIBC__)
/* The system's strerror_r function is OK, except that its third argument
is 'int', not 'size_t', or its return type is wrong. */
# include <limits.h>
+ # define USE_SYSTEM_STRERROR_R 1
+
+ #elif (__GLIBC__ >= 2 || defined __UCLIBC__) && HAVE___XPG_STRERROR_R /*
glibc >= 2.3.4 */
+
+ # define USE_XPG_STRERROR_R 1
+
+ #else /* (__GLIBC__ >= 2 || defined __UCLIBC__ ? !HAVE___XPG_STRERROR_R :
!HAVE_DECL_STRERROR_R) */
+
+ # include "glthread/lock.h"
+
+ /* Use strerror(), with locking. */
+ # undef strerror
+
+ # define USE_SYSTEM_STRERROR 1
+
+ /* This lock protects the buffer returned by strerror(). We assume that
+ no other uses of strerror() exist in the program. */
+ gl_lock_define_initialized(static, strerror_lock)
+
+ #endif
+
+
int
strerror_r (int errnum, char *buf, size_t buflen)
! #undef strerror_r
{
! #if EXTEND_STRERROR_R
! {
! char const *msg = NULL;
! /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */
! switch (errnum)
! {
! # if GNULIB_defined_ETXTBSY
! case ETXTBSY:
! msg = "Text file busy";
! break;
! # endif
! # if GNULIB_defined_ESOCK /* native Windows platforms */
! /* EWOULDBLOCK is the same as EAGAIN. */
! case EINPROGRESS:
! 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_EDQUOT
! case EDQUOT:
! msg = "Disk quota exceeded";
! break;
! # endif
!
! # if GNULIB_defined_ECANCELED
! case ECANCELED:
! msg = "Operation canceled";
! break;
! # endif
! }
!
! if (msg)
{
! size_t len = strlen (msg);
! if (len < buflen)
! {
! memcpy (buf, msg, len + 1);
! return 0;
}
+ else
+ return ERANGE;
}
}
! #endif
! {
! int ret;
!
! #if USE_SYSTEM_STRERROR_R
!
! if (buflen > INT_MAX)
! buflen = INT_MAX;
!
! # ifdef __hpux
! /* On HP-UX 11.31, strerror_r always fails when buflen < 80. */
{
! char stackbuf[80];
!
! if (buflen < sizeof (stackbuf))
{
! ret = strerror_r (errnum, stackbuf, sizeof (stackbuf));
! if (ret == 0)
! {
! size_t len = strlen (stackbuf);
!
! if (len < buflen)
! memcpy (buf, stackbuf, len + 1);
! else
! ret = ERANGE;
! }
}
else
! ret = strerror_r (errnum, buf, buflen);
}
+ # elif defined __CYGWIN__
+ /* Cygwin only provides the glibc interface, is thread-safe, and
+ always succeeds (although it may truncate). */
+ strerror_r (errnum, buf, buflen);
+ ret = 0;
+ # else
+ ret = strerror_r (errnum, buf, buflen);
# endif
! # ifdef _AIX
! /* On AIX 6.1, strerror_r returns -1 and sets errno to EINVAL
! if buflen <= 1. */
! if (ret < 0 && errno == EINVAL && buflen <= 1)
! {
! /* Retry with a larger buffer. */
! char largerbuf[10];
! ret = strerror_r (errnum, largerbuf, sizeof (largerbuf));
! if (ret < 0 && errno == EINVAL)
! {
! /* errnum was out of range. */
! ret = EINVAL;
! }
! else
! {
! /* buf was too small. */
! ret = ERANGE;
! }
! }
! # endif
! /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */
! if (ret < 0)
! ret = errno;
! #elif USE_XPG_STRERROR_R
! {
! extern int __xpg_strerror_r (int errnum, char *buf, size_t buflen);
! ret = __xpg_strerror_r (errnum, buf, buflen);
! if (ret < 0)
! ret = errno;
! }
! #else /* USE_SYSTEM_STRERROR */
! gl_lock_lock (strerror_lock);
! {
! char *errmsg = strerror (errnum);
! /* For invalid error numbers, strerror() on
! - IRIX 6.5 returns NULL,
! - HP-UX 11 returns an empty string. */
! if (errmsg == NULL || *errmsg == '\0')
! ret = EINVAL;
! else
! {
! size_t len = strlen (errmsg);
! if (len < buflen)
! {
! memcpy (buf, errmsg, len + 1);
! ret = 0;
! }
! else
! ret = ERANGE;
! }
! }
gl_lock_unlock (strerror_lock);
+ #endif
+
return ret;
}
}
*** modules/strerror.orig Thu May 19 05:17:36 2011
--- modules/strerror Thu May 19 04:13:54 2011
***************
*** 7,14 ****
Depends-on:
string
! errno [test $REPLACE_STRERROR = 1]
! intprops [test $REPLACE_STRERROR = 1]
configure.ac:
gl_FUNC_STRERROR
--- 7,16 ----
Depends-on:
string
! errno [test $REPLACE_STRERROR = 1]
! intprops [test $REPLACE_STRERROR = 1]
! verify [test $REPLACE_STRERROR = 1]
! strerror_r-posix [test $REPLACE_STRERROR = 1]
configure.ac:
gl_FUNC_STRERROR
--
In memoriam Eli Cohen <http://en.wikipedia.org/wiki/Eli_Cohen>
- Re: perror bug,
Bruno Haible <=