strerror_r: fix Solaris test failures
authorEric Blake <eblake@redhat.com>
Tue, 24 May 2011 03:05:07 +0000 (21:05 -0600)
committerEric Blake <eblake@redhat.com>
Tue, 24 May 2011 19:42:46 +0000 (13:42 -0600)
Solaris 10 populates buf on EINVAL, but not on ERANGE.

* lib/strerror_r.c (strerror_r): Partially populate buf on ERANGE
failures.
* doc/posix-functions/strerror_r.texi (strerror_r): Document this.

Signed-off-by: Eric Blake <eblake@redhat.com>
ChangeLog
doc/posix-functions/strerror_r.texi
lib/strerror_r.c

index bc838bd..80e9369 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2011-05-24  Eric Blake  <eblake@redhat.com>
 
+       strerror_r: fix Solaris test failures
+       * lib/strerror_r.c (strerror_r): Partially populate buf on ERANGE
+       failures.
+       * doc/posix-functions/strerror_r.texi (strerror_r): Document this.
+
        strerror_r: enforce POSIX recommendations
        * lib/strerror_r.c (safe_copy): New helper method.
        (strerror_r): Guarantee a non-empty string.
index 91026ef..e0f19c0 100644 (file)
@@ -59,7 +59,7 @@ AIX 6.1, OSF/1 5.1.
 When the value is not in range or the buffer is too small, this
 function fails to leave a NUL-terminated string in the buffer on some
 platforms:
-glibc 2.13, FreeBSD 8.2.
+glibc 2.13, FreeBSD 8.2, Solaris 10.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 40ebc59..f6ce8a3 100644 (file)
 
 #include <errno.h>
 
-# if GNULIB_defined_ESOCK /* native Windows platforms */
-#  if HAVE_WINSOCK2_H
-#   include <winsock2.h>
-#  endif
+#if GNULIB_defined_ESOCK /* native Windows platforms */
+# if HAVE_WINSOCK2_H
+#  include <winsock2.h>
 # endif
+#endif
 
+/* Reasonable buffer size that should never trigger ERANGE; if this
+   proves too small, we intentionally abort(), to remind us to fix
+   this value as well as strerror-impl.h.  */
+#define STACKBUF_LEN 256
 
 #if (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__) && HAVE___XPG_STRERROR_R /* glibc >= 2.3.4, cygwin >= 1.7.9 */
 
@@ -483,7 +487,18 @@ strerror_r (int errnum, char *buf, size_t buflen)
         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);
+      }
 # endif
 
     /* Some old implementations may return (-1, EINVAL) instead of EINVAL.  */