changeset 14770:edc214f40f31

strerror_r: Work around strerror_r() change in Cygwin 1.7.8. * lib/strerror_r.c (strerror_r) [CYGWIN]: Recognize when the system's strerror_r() returned without filling the buffer. Reported by Eric Blake.
author Bruno Haible <bruno@clisp.org>
date Fri, 20 May 2011 04:01:43 +0200
parents 8e815ef27998
children 05ca371c9c6e
files ChangeLog lib/strerror_r.c
diffstat 2 files changed, 36 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-05-19  Bruno Haible  <bruno@clisp.org>
+
+	strerror_r: Work around strerror_r() change in Cygwin 1.7.8.
+	* lib/strerror_r.c (strerror_r) [CYGWIN]: Recognize when the system's
+	strerror_r() returned without filling the buffer.
+	Reported by Eric Blake.
+
 2011-05-19  Eric Blake  <eblake@redhat.com>
 
 	strerror_r: guarantee unchanged errno
--- a/lib/strerror_r.c
+++ b/lib/strerror_r.c
@@ -459,10 +459,35 @@
         ret = strerror_r (errnum, buf, buflen);
     }
 # elif defined __CYGWIN__
-    /* Cygwin 1.7.8 only provides the glibc interface, is thread-safe, and
-       always succeeds (although it may truncate). */
-    strerror_r (errnum, buf, buflen);
-    ret = 0;
+    /* Cygwin <= 1.7.7 only provides the glibc interface, is thread-safe, and
+       always succeeds (although it may truncate).  In Cygwin >= 1.7.8, for
+       valid errnum values, instead of truncating, it leaves the buffer
+       untouched.  */
+    {
+      char stackbuf[256];
+
+      if (buflen < sizeof (stackbuf))
+        {
+          size_t len;
+
+          stackbuf[0] = '\0'; /* in case strerror_r does nothing */
+          strerror_r (errnum, stackbuf, sizeof (stackbuf));
+          len = strlen (stackbuf);
+          if (len < buflen)
+            {
+              memcpy (buf, stackbuf, len + 1);
+              ret = 0;
+            }
+          else
+            ret = ERANGE;
+        }
+      else
+        {
+          buf[0] = '\0'; /* in case strerror_r does nothing */
+          strerror_r (errnum, buf, buflen);
+          ret = 0;
+        }
+    }
 # else
     ret = strerror_r (errnum, buf, buflen);
 # endif