> With this, the conversion function from a WSAGetLastError() value to an > errno value is > e -> (e < 10025 ? e - 10000 : > e == WSAENAMETOOLONG ? ENAMETOOLONG : > e == WSAENOTEMPTY ; ENOTEMPTY : > e);
That's still not enough. Looking at [1], I think it should also map WSA_INVALID_HANDLE -> EBADF WSA_NOT_ENOUGH_MEMORY -> ENOMEM WSA_INVALID_PARAMETER -> EINVAL [1] http://msdn.microsoft.com/en-us/library/ms740668(VS.85).aspx I'm extending the strerror function to cover these E* and WSAE* values. 2008-09-13 Bruno Haible <[EMAIL PROTECTED]> 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. *** doc/posix-functions/strerror.texi.orig 2008-09-14 04:10:20.000000000 +0200 --- doc/posix-functions/strerror.texi 2008-09-14 01:13:45.000000000 +0200 *************** *** 10,16 **** @itemize @item This function is missing on some old platforms. ! @item This function fails to return a string for out-of-range integers on some platforms: --- 10,19 ---- @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: *** lib/strerror.c.orig 2008-09-14 04:10:20.000000000 +0200 --- lib/strerror.c 2008-09-14 04:07:28.000000000 +0200 *************** *** 1,6 **** /* strerror.c --- POSIX compatible system error routine ! Copyright (C) 2007 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 --- 1,6 ---- /* strerror.c --- POSIX compatible system error routine ! 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,28 **** --- 21,35 ---- #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" # undef strerror *************** *** 33,49 **** char * rpl_strerror (int n) { ! 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 --- 40,274 ---- char * rpl_strerror (int n) { ! /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ ! switch (n) { ! # 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 } ! { ! 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 *** m4/strerror.m4.orig 2008-09-14 04:10:20.000000000 +0200 --- m4/strerror.m4 2008-09-14 04:00:52.000000000 +0200 *************** *** 1,4 **** ! # strerror.m4 serial 8 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, --- 1,4 ---- ! # 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,13 **** AC_DEFUN([gl_FUNC_STRERROR], [ AC_REQUIRE([gl_FUNC_STRERROR_SEPARATE]) ! if test $gl_cv_func_working_strerror = no; then AC_LIBOBJ([strerror]) AC_DEFINE_UNQUOTED([REPLACE_STRERROR], [$REPLACE_STRERROR], [Define this to 1 if strerror is broken.]) --- 7,13 ---- AC_DEFUN([gl_FUNC_STRERROR], [ AC_REQUIRE([gl_FUNC_STRERROR_SEPARATE]) ! 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,42 **** 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 <string.h> ! ]], ! [[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 <string.h> ! ]], ! [[return !*strerror (-2);]])], ! [gl_cv_func_working_strerror=yes], ! [gl_cv_func_working_strerror=no])])]) ! if test $gl_cv_func_working_strerror = no ; then REPLACE_STRERROR=1 gl_PREREQ_STRERROR fi ]) --- 18,55 ---- AC_DEFUN([gl_FUNC_STRERROR_SEPARATE], [ AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS]) ! 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 <string.h> ! ]], ! [[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 <string.h> ! ]], ! [[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 <errno.h>. Replace it. REPLACE_STRERROR=1 + fi + if test $REPLACE_STRERROR = 1; then gl_PREREQ_STRERROR fi ]) *************** *** 44,47 **** --- 57,68 ---- # 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 ]) *** modules/strerror.orig 2008-09-14 04:10:20.000000000 +0200 --- modules/strerror 2008-09-14 02:00:21.000000000 +0200 *************** *** 6,11 **** --- 6,12 ---- m4/strerror.m4 Depends-on: + errno intprops string *** tests/test-strerror.c.orig 2008-09-14 04:10:20.000000000 +0200 --- tests/test-strerror.c 2008-09-14 01:15:18.000000000 +0200 *************** *** 40,49 **** --- 40,58 ---- 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);