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 <ebl...@redhat.com> --- ChangeLog | 5 +++++ doc/posix-functions/strerror_r.texi | 2 +- lib/strerror_r.c | 23 +++++++++++++++++++---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index bc838bd..80e9369 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2011-05-24 Eric Blake <ebl...@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. diff --git a/doc/posix-functions/strerror_r.texi b/doc/posix-functions/strerror_r.texi index 91026ef..e0f19c0 100644 --- a/doc/posix-functions/strerror_r.texi +++ b/doc/posix-functions/strerror_r.texi @@ -59,7 +59,7 @@ strerror_r 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: diff --git a/lib/strerror_r.c b/lib/strerror_r.c index 40ebc59..f6ce8a3 100644 --- a/lib/strerror_r.c +++ b/lib/strerror_r.c @@ -27,12 +27,16 @@ #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. */ -- 1.7.4.4