From 6c560a52fc22a10c65449aaa59d6c37c76e6e118 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 14 Sep 2008 04:18:44 +0200 Subject: [PATCH] Extend strerror to cover the added errno values. --- ChangeLog | 15 +++ doc/posix-functions/strerror.texi | 5 +- lib/strerror.c | 243 ++++++++++++++++++++++++++++++++++++-- m4/strerror.m4 | 61 ++++++---- modules/strerror | 1 + tests/test-strerror.c | 9 ++ 6 files changed, 304 insertions(+), 30 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5de740e51..ac10f0a78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ 2008-09-13 Bruno Haible + Extend strerror to cover the added errno values. + * lib/strerror.c: Include errno.h and winsock2.h if it exists. + (rpl_strerror): Provide error messages for the added errno values and + for the WSA* values. + * m4/strerror.m4 (gl_FUNC_STRERROR): Test REPLACE_STRERROR. + (gl_FUNC_STRERROR_SEPARATE): If errno.h is replaced, always replace + strerror. + (gl_PREREQ_STRERROR): Test whether winsock2.h exists. + * modules/strerror (Depends-on): Add errno. + * doc/posix-functions/strerror.texi: Document the change. + * tests/test-strerror.c (main): Check also the string for ETIMEDOUT + and EOVERFLOW. + +2008-09-13 Bruno Haible + * modules/EOVERFLOW: Remove file. * m4/eoverflow.m4: Remove file. * modules/EOVERFLOW-tests: Remove file. diff --git a/doc/posix-functions/strerror.texi b/doc/posix-functions/strerror.texi index 012b691ab..488d3e327 100644 --- a/doc/posix-functions/strerror.texi +++ b/doc/posix-functions/strerror.texi @@ -10,7 +10,10 @@ Portability problems fixed by Gnulib: @itemize @item This function is missing on some old platforms. - +@item +This function does not support the error values that are specified by POSIX +but not defined by the system, on some platforms: +OpenBSD 4.0, OSF/1 4.0, mingw. @item This function fails to return a string for out-of-range integers on some platforms: diff --git a/lib/strerror.c b/lib/strerror.c index 9fe437db7..2393c67d3 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -1,6 +1,6 @@ /* strerror.c --- POSIX compatible system error routine - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007-2008 Free Software Foundation, Inc. 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 @@ -21,8 +21,15 @@ #if REPLACE_STRERROR +# include # include +# if GNULIB_defined_ESOCK /* native Windows platforms */ +# if HAVE_WINSOCK2_H +# include +# endif +# endif + # include "intprops.h" # undef strerror @@ -33,17 +40,235 @@ char * rpl_strerror (int n) { - char *result = strerror (n); - - if (result == NULL || result[0] == '\0') + /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ + switch (n) { - static char const fmt[] = "Unknown error (%d)"; - static char mesg[sizeof fmt + INT_STRLEN_BOUND (n)]; - sprintf (mesg, fmt, n); - return mesg; +# if GNULIB_defined_ETXTBSY + case ETXTBSY: + return "Text file busy"; +# endif + +# if GNULIB_defined_ESOCK /* native Windows platforms */ + case EWOULDBLOCK: + return "Operation would block"; + case EINPROGRESS: + return "Operation now in progress"; + case EALREADY: + return "Operation already in progress"; + case ENOTSOCK: + return "Socket operation on non-socket"; + case EDESTADDRREQ: + return "Destination address required"; + case EMSGSIZE: + return "Message too long"; + case EPROTOTYPE: + return "Protocol wrong type for socket"; + case ENOPROTOOPT: + return "Protocol not available"; + case EPROTONOSUPPORT: + return "Protocol not supported"; + case ESOCKTNOSUPPORT: + return "Socket type not supported"; + case EOPNOTSUPP: + return "Operation not supported"; + case EPFNOSUPPORT: + return "Protocol family not supported"; + case EAFNOSUPPORT: + return "Address family not supported by protocol"; + case EADDRINUSE: + return "Address already in use"; + case EADDRNOTAVAIL: + return "Cannot assign requested address"; + case ENETDOWN: + return "Network is down"; + case ENETUNREACH: + return "Network is unreachable"; + case ENETRESET: + return "Network dropped connection on reset"; + case ECONNABORTED: + return "Software caused connection abort"; + case ECONNRESET: + return "Connection reset by peer"; + case ENOBUFS: + return "No buffer space available"; + case EISCONN: + return "Transport endpoint is already connected"; + case ENOTCONN: + return "Transport endpoint is not connected"; + case ESHUTDOWN: + return "Cannot send after transport endpoint shutdown"; + case ETOOMANYREFS: + return "Too many references: cannot splice"; + case ETIMEDOUT: + return "Connection timed out"; + case ECONNREFUSED: + return "Connection refused"; + case ELOOP: + return "Too many levels of symbolic links"; + case EHOSTDOWN: + return "Host is down"; + case EHOSTUNREACH: + return "No route to host"; + case EPROCLIM: + return "Too many processes"; + case EUSERS: + return "Too many users"; + case EDQUOT: + return "Disk quota exceeded"; + case ESTALE: + return "Stale NFS file handle"; + case EREMOTE: + return "Object is remote"; +# 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: + return "Overlapped operation aborted"; + case WSA_IO_INCOMPLETE: + return "Overlapped I/O event object not in signaled state"; + case WSA_IO_PENDING: + return "Overlapped operations will complete later"; + /* WSAEINTR maps to EINTR */ + /* WSAEBADF maps to EBADF */ + /* WSAEACCES maps to EACCES */ + /* WSAEFAULT maps to EFAULT */ + /* WSAEINVAL maps to EINVAL */ + /* WSAEMFILE maos to EMFILE */ + /* WSAEWOULDBLOCK is 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: + return "Network subsystem is unavailable"; + case WSAVERNOTSUPPORTED: + return "Winsock.dll version out of range"; + case WSANOTINITIALISED: + return "Successful WSAStartup not yet performed"; + case WSAEDISCON: + return "Graceful shutdown in progress"; + case WSAENOMORE: case WSA_E_NO_MORE: + return "No more results"; + case WSAECANCELLED: case WSA_E_CANCELLED: + return "Call was canceled"; + case WSAEINVALIDPROCTABLE: + return "Procedure call table is invalid"; + case WSAEINVALIDPROVIDER: + return "Service provider is invalid"; + case WSAEPROVIDERFAILEDINIT: + return "Service provider failed to initialize"; + case WSASYSCALLFAILURE: + return "System call failure"; + case WSASERVICE_NOT_FOUND: + return "Service not found"; + case WSATYPE_NOT_FOUND: + return "Class type not found"; + case WSAEREFUSED: + return "Database query was refused"; + case WSAHOST_NOT_FOUND: + return "Host not found"; + case WSATRY_AGAIN: + return "Nonauthoritative host not found"; + case WSANO_RECOVERY: + return "Nonrecoverable error"; + case WSANO_DATA: + return "Valid name, no data record of requested type"; + /* WSA_QOS_* omitted */ +# endif +# endif + +# if GNULIB_defined_ENOMSG + case ENOMSG: + return "No message of desired type"; +# endif + +# if GNULIB_defined_EIDRM + case EIDRM: + return "Identifier removed"; +# endif + +# if GNULIB_defined_ENOLINK + case ENOLINK: + return "Link has been severed"; +# endif + +# if GNULIB_defined_EPROTO + case EPROTO: + return "Protocol error"; +# endif + +# if GNULIB_defined_EMULTIHOP + case EMULTIHOP: + return "Multihop attempted"; +# endif + +# if GNULIB_defined_EBADMSG + case EBADMSG: + return "Bad message"; +# endif + +# if GNULIB_defined_EOVERFLOW + case EOVERFLOW: + return "Value too large for defined data type"; +# endif + +# if GNULIB_defined_ENOTSUP + case ENOTSUP: + return "Not supported"; +# endif + +# if GNULIB_defined_ + case ECANCELED: + return "Operation canceled"; +# endif } - return result; + { + char *result = strerror (n); + + if (result == NULL || result[0] == '\0') + { + static char const fmt[] = "Unknown error (%d)"; + static char mesg[sizeof fmt + INT_STRLEN_BOUND (n)]; + sprintf (mesg, fmt, n); + return mesg; + } + + return result; + } } #endif diff --git a/m4/strerror.m4 b/m4/strerror.m4 index 75d54621b..8c16ca9a8 100644 --- a/m4/strerror.m4 +++ b/m4/strerror.m4 @@ -1,4 +1,4 @@ -# strerror.m4 serial 8 +# strerror.m4 serial 9 dnl Copyright (C) 2002, 2007-2008 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -7,7 +7,7 @@ dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_FUNC_STRERROR], [ AC_REQUIRE([gl_FUNC_STRERROR_SEPARATE]) - if test $gl_cv_func_working_strerror = no; then + if test $REPLACE_STRERROR = 1; then AC_LIBOBJ([strerror]) AC_DEFINE_UNQUOTED([REPLACE_STRERROR], [$REPLACE_STRERROR], [Define this to 1 if strerror is broken.]) @@ -18,25 +18,38 @@ AC_DEFUN([gl_FUNC_STRERROR], AC_DEFUN([gl_FUNC_STRERROR_SEPARATE], [ AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) - AC_CACHE_CHECK([for working strerror function], - [gl_cv_func_working_strerror], - [AC_RUN_IFELSE( - [AC_LANG_PROGRAM( - [[#include - ]], - [[return !*strerror (-2);]])], - [gl_cv_func_working_strerror=yes], - [gl_cv_func_working_strerror=no], - [dnl Assume crossbuild works if it compiles. - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#include - ]], - [[return !*strerror (-2);]])], - [gl_cv_func_working_strerror=yes], - [gl_cv_func_working_strerror=no])])]) - if test $gl_cv_func_working_strerror = no ; then + AC_REQUIRE([gl_HEADER_ERRNO_H]) + if test -z "$ERRNO_H"; then + AC_CACHE_CHECK([for working strerror function], + [gl_cv_func_working_strerror], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[return !*strerror (-2);]])], + [gl_cv_func_working_strerror=yes], + [gl_cv_func_working_strerror=no], + [dnl Assume crossbuild works if it compiles. + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[return !*strerror (-2);]])], + [gl_cv_func_working_strerror=yes], + [gl_cv_func_working_strerror=no]) + ]) + ]) + if test $gl_cv_func_working_strerror = no; then + dnl The system's strerror() fails to return a string for out-of-range + dnl integers. Replace it. + REPLACE_STRERROR=1 + fi + else + dnl The system's strerror() cannot know about the new errno values we add + dnl to . Replace it. REPLACE_STRERROR=1 + fi + if test $REPLACE_STRERROR = 1; then gl_PREREQ_STRERROR fi ]) @@ -44,4 +57,12 @@ AC_DEFUN([gl_FUNC_STRERROR_SEPARATE], # Prerequisites of lib/strerror.c. AC_DEFUN([gl_PREREQ_STRERROR], [ AC_CHECK_DECLS([strerror]) + AC_CHECK_HEADERS_ONCE([sys/socket.h]) + if test $ac_cv_header_sys_socket_h != yes; then + dnl We cannot use AC_CHECK_HEADERS_ONCE here, because that would make + dnl the check for those headers unconditional; yet cygwin reports + dnl that the headers are present but cannot be compiled (since on + dnl cygwin, all socket information should come from sys/socket.h). + AC_CHECK_HEADERS([winsock2.h]) + fi ]) diff --git a/modules/strerror b/modules/strerror index 2e914b345..b662401c6 100644 --- a/modules/strerror +++ b/modules/strerror @@ -6,6 +6,7 @@ lib/strerror.c m4/strerror.m4 Depends-on: +errno intprops string diff --git a/tests/test-strerror.c b/tests/test-strerror.c index 752afe27e..3d9814d5d 100644 --- a/tests/test-strerror.c +++ b/tests/test-strerror.c @@ -40,10 +40,19 @@ int main (int argc, char **argv) { char *str; + str = strerror (EACCES); ASSERT (str); ASSERT (*str); + str = strerror (ETIMEDOUT); + ASSERT (str); + ASSERT (*str); + + str = strerror (EOVERFLOW); + ASSERT (str); + ASSERT (*str); + str = strerror (0); ASSERT (str); ASSERT (*str); -- 2.11.0