This patch fixes two problems with MSVC 14 support in module 'strerror_r-posix':
1) The function local_snprintf uses va_list, va_start, va_end, without including the required header <stdarg.h>. 2) Test failures of strerror_r-posix and perror, reported in https://lists.gnu.org/archive/html/bug-gnulib/2016-12/msg00112.html The cause is that MSVC's <errno.h> now defines ETIMEDOUT and other errno values in the range 100..140, but without adding them to the _sys_errlist array. _sys_nerr still is = 43. 2017-04-29 Bruno Haible <br...@clisp.org> strerror_r-posix: Fixes for MSVC 14. * lib/strerror_r.c: Include <stdarg.h>. (strerror_r): Provide error messages for errno values 100...140. * doc/posix-functions/strerror_r.texi: Mention the MSVC 14 problem. diff --git a/doc/posix-functions/strerror_r.texi b/doc/posix-functions/strerror_r.texi index 06fdfd2..8554a29 100644 --- a/doc/posix-functions/strerror_r.texi +++ b/doc/posix-functions/strerror_r.texi @@ -39,6 +39,10 @@ glibc 2.12 with @code{-D_POSIX_C_SOURCE=200112L}, AIX 6.1, OSF/1 5.1. When this function fails, it corrupts @code{errno}, on some platforms: Solaris 10. @item +This function does not support many error values defined in @code{<errno.h>} on +some platforms: +MSVC 14. +@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 5.1, NonStop Kernel, Cygwin 1.5.x. diff --git a/lib/strerror_r.c b/lib/strerror_r.c index d7b0f77..650751f 100644 --- a/lib/strerror_r.c +++ b/lib/strerror_r.c @@ -28,6 +28,9 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> +#if !HAVE_SNPRINTF +# include <stdarg.h> +#endif #include "strerror-override.h" @@ -329,6 +332,115 @@ strerror_r (int errnum, char *buf, size_t buflen) #endif +#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ + /* MSVC 14 defines names for many error codes in the range 100..140, + but _sys_errlist contains strings only for the error codes + < _sys_nerr = 43. */ + if (ret == EINVAL) + { + const char *errmsg; + + switch (errnum) + { + case 100 /* EADDRINUSE */: + errmsg = "Address already in use"; + break; + case 101 /* EADDRNOTAVAIL */: + errmsg = "Cannot assign requested address"; + break; + case 102 /* EAFNOSUPPORT */: + errmsg = "Address family not supported by protocol"; + break; + case 103 /* EALREADY */: + errmsg = "Operation already in progress"; + break; + case 105 /* ECANCELED */: + errmsg = "Operation canceled"; + break; + case 106 /* ECONNABORTED */: + errmsg = "Software caused connection abort"; + break; + case 107 /* ECONNREFUSED */: + errmsg = "Connection refused"; + break; + case 108 /* ECONNRESET */: + errmsg = "Connection reset by peer"; + break; + case 109 /* EDESTADDRREQ */: + errmsg = "Destination address required"; + break; + case 110 /* EHOSTUNREACH */: + errmsg = "No route to host"; + break; + case 112 /* EINPROGRESS */: + errmsg = "Operation now in progress"; + break; + case 113 /* EISCONN */: + errmsg = "Transport endpoint is already connected"; + break; + case 114 /* ELOOP */: + errmsg = "Too many levels of symbolic links"; + break; + case 115 /* EMSGSIZE */: + errmsg = "Message too long"; + break; + case 116 /* ENETDOWN */: + errmsg = "Network is down"; + break; + case 117 /* ENETRESET */: + errmsg = "Network dropped connection on reset"; + break; + case 118 /* ENETUNREACH */: + errmsg = "Network is unreachable"; + break; + case 119 /* ENOBUFS */: + errmsg = "No buffer space available"; + break; + case 123 /* ENOPROTOOPT */: + errmsg = "Protocol not available"; + break; + case 126 /* ENOTCONN */: + errmsg = "Transport endpoint is not connected"; + break; + case 128 /* ENOTSOCK */: + errmsg = "Socket operation on non-socket"; + break; + case 129 /* ENOTSUP */: + errmsg = "Not supported"; + break; + case 130 /* EOPNOTSUPP */: + errmsg = "Operation not supported"; + break; + case 132 /* EOVERFLOW */: + errmsg = "Value too large for defined data type"; + break; + case 133 /* EOWNERDEAD */: + errmsg = "Owner died"; + break; + case 134 /* EPROTO */: + errmsg = "Protocol error"; + break; + case 135 /* EPROTONOSUPPORT */: + errmsg = "Protocol not supported"; + break; + case 136 /* EPROTOTYPE */: + errmsg = "Protocol wrong type for socket"; + break; + case 138 /* ETIMEDOUT */: + errmsg = "Connection timed out"; + break; + case 140 /* EWOULDBLOCK */: + errmsg = "Operation would block"; + break; + default: + errmsg = NULL; + break; + } + if (errmsg != NULL) + ret = safe_copy (buf, buflen, errmsg); + } +#endif + if (ret == EINVAL && !*buf) snprintf (buf, buflen, "Unknown error %d", errnum);