#endif
+/* On MSVC, there is no snprintf() function, just a _snprintf().
+ It is of lower quality, but sufficient for the simple use here.
+ We only have to make sure to NUL terminate the result (_snprintf
+ does not NUL terminate, like strncpy). */
+#if !HAVE_SNPRINTF
+static int
+local_snprintf (char *buf, size_t buflen, const char *format, ...)
+{
+ va_list args;
+ int result;
+
+ va_start (args, format);
+ result = _vsnprintf (buf, buflen, format, args);
+ va_end (args);
+ if (buflen > 0 && (result < 0 || result >= buflen))
+ buf[buflen - 1] = '\0';
+ return result;
+}
+# define snprintf local_snprintf
+#endif
+
/* Copy as much of MSG into BUF as possible, without corrupting errno.
Return 0 if MSG fit in BUFLEN, otherwise return ERANGE. */
static int
ret = strerror_r (errnum, buf, buflen);
}
# else
- /* Solaris 10 does not populate buf on ERANGE. */
ret = strerror_r (errnum, buf, buflen);
- if (ret == ERANGE && !*buf)
- {
- char stackbuf[STACKBUF_LEN];
- /* strerror-impl.h is also affected if our choice of stackbuf
- size is not large enough. */
- if (strerror_r (errnum, stackbuf, sizeof stackbuf) == ERANGE)
- abort ();
- safe_copy (buf, buflen, stackbuf);
- }
+ /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */
+ if (ret < 0)
+ ret = errno;
# endif
# ifdef _AIX
size_t len;
strerror_r (errnum, stackbuf, sizeof stackbuf);
len = strlen (stackbuf);
- /* stackbuf should have been large enough. */
+ /* STACKBUF_LEN should have been large enough. */
if (len + 1 == sizeof stackbuf)
abort ();
if (buflen <= len)
ret = ERANGE;
}
-# endif
-
- /* Some old implementations may return (-1, EINVAL) instead of EINVAL. */
- if (ret < 0)
- ret = errno;
+# else
+ /* Solaris 10 does not populate buf on ERANGE. OpenBSD 4.7
+ truncates early on ERANGE rather than return a partial integer.
+ We prefer the maximal string. We set buf[0] earlier, and we
+ know of no implementation that modifies buf to be an
+ unterminated string, so this strlen should be portable in
+ practice (rather than pulling in a safer strnlen). */
+ if (ret == ERANGE && strlen (buf) < buflen - 1)
+ {
+ char stackbuf[STACKBUF_LEN];
- /* FreeBSD rejects 0; see http://austingroupbugs.net/view.php?id=382. */
- if (errnum == 0 && ret == EINVAL)
- ret = safe_copy (buf, buflen, "Success");
+ /* STACKBUF_LEN should have been large enough. */
+ if (strerror_r (errnum, stackbuf, sizeof stackbuf) == ERANGE)
+ abort ();
+ safe_copy (buf, buflen, stackbuf);
+ }
+# endif
#else /* USE_SYSTEM_STRERROR */