On OpenBSD, strerror_r(1000,buf,19) gives "Unknown error: " rather than "Unknown error: 100" while failing with ERANGE. Admittedly, this behavior is nice, since a truncated integer is misleading, but all other platforms use maximal strings on ERANGE and we are already replacing strerror_r for other reasons, so it is easier to work around this behavior than to adjust the testsuite (how do you quickly decide if the only reason that the ERANGE string was shorter than maximal was because the implementation avoided truncating an integer?).
* lib/strerror_r.c (strerror_r): Always use maximal string. * doc/posix-functions/strerror_r.texi (strerror_r): Document it. Signed-off-by: Eric Blake <ebl...@redhat.com> --- I'm not sure whether to push this one as-is, or whether we should instead modify the testsuite to allow OpenBSD behavior. Thoughts? ChangeLog | 6 ++++++ doc/posix-functions/strerror_r.texi | 5 +++++ lib/strerror_r.c | 12 ++++++++++++ 3 files changed, 23 insertions(+), 0 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6e5eaf4..ec3e115 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2011-06-21 Eric Blake <ebl...@redhat.com> + strerror_r: fix OpenBSD behavior on out-of-range + * lib/strerror_r.c (strerror_r): Always use maximal string. + * doc/posix-functions/strerror_r.texi (strerror_r): Document it. + +2011-06-21 Eric Blake <ebl...@redhat.com> + strerror_r: fix OpenBSD behavior on 0 * lib/strerror-override.c (strerror_override): Also override 0 when needed. diff --git a/doc/posix-functions/strerror_r.texi b/doc/posix-functions/strerror_r.texi index 5aaa1c6..08b59ec 100644 --- a/doc/posix-functions/strerror_r.texi +++ b/doc/posix-functions/strerror_r.texi @@ -64,6 +64,11 @@ strerror_r function fails to leave a NUL-terminated string in the buffer on some platforms: glibc 2.13, FreeBSD 8.2, Solaris 10. +@item +When the value is out of range but the buffer is too small, this +function does not always return the longest possible string on some +platforms: +OpenBSD 4.7. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/strerror_r.c b/lib/strerror_r.c index 0da9ba2..7c4214c 100644 --- a/lib/strerror_r.c +++ b/lib/strerror_r.c @@ -209,6 +209,18 @@ strerror_r (int errnum, char *buf, size_t buflen) if (ret < 0) ret = errno; + /* OpenBSD 4.7 truncates early on ERANGE rather than return a + partial integer, but we prefer the maximal string. */ + if (ret == ERANGE && strlen (buf) < buflen - 1) + { + char stackbuf[STACKBUF_LEN]; + ret = strerror_r (errnum, stackbuf, sizeof stackbuf); + /* STACKBUF_LEN should have been large enough. */ + if (ret == ERANGE) + abort (); + ret = safe_copy (buf, buflen, stackbuf); + } + #else /* USE_SYSTEM_STRERROR */ /* Try to do what strerror (errnum) does, but without clobbering the -- 1.7.4.4