Discussion:
strerror_r-posix: fixes for MSVC 14
Bruno Haible
2017-04-29 11:30:34 UTC
Permalink
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 <***@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);

Loading...