summaryrefslogtreecommitdiff
path: root/lib/strerror_r.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/strerror_r.c')
-rw-r--r--lib/strerror_r.c35
1 files changed, 17 insertions, 18 deletions
diff --git a/lib/strerror_r.c b/lib/strerror_r.c
index f0244520b1..90043c2237 100644
--- a/lib/strerror_r.c
+++ b/lib/strerror_r.c
@@ -34,33 +34,26 @@
#include "strerror-override.h"
-#if (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__) && HAVE___XPG_STRERROR_R /* glibc >= 2.3.4, cygwin >= 1.7.9 */
+#if STRERROR_R_CHAR_P
-# define USE_XPG_STRERROR_R 1
-extern
-#ifdef __cplusplus
-"C"
-#endif
-int __xpg_strerror_r (int errnum, char *buf, size_t buflen);
+# if HAVE___XPG_STRERROR_R
+_GL_EXTERN_C int __xpg_strerror_r (int errnum, char *buf, size_t buflen);
+# endif
-#elif HAVE_DECL_STRERROR_R && !(__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__)
+#elif HAVE_DECL_STRERROR_R
-/* The system's strerror_r function is OK, except that its third argument
+/* The system's strerror_r function's API is OK, except that its third argument
is 'int', not 'size_t', or its return type is wrong. */
# include <limits.h>
-# define USE_SYSTEM_STRERROR_R 1
-
-#else /* (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__ ? !HAVE___XPG_STRERROR_R : !HAVE_DECL_STRERROR_R) */
+#else
/* Use the system's strerror(). Exclude glibc and cygwin because the
system strerror_r has the wrong return type, and cygwin 1.7.9
strerror_r clobbers strerror. */
# undef strerror
-# define USE_SYSTEM_STRERROR 1
-
# if defined __NetBSD__ || defined __hpux || (defined _WIN32 && !defined __CYGWIN__) || defined __sgi || (defined __sun && !defined _LP64) || defined __CYGWIN__
/* No locking needed. */
@@ -166,22 +159,28 @@ strerror_r (int errnum, char *buf, size_t buflen)
int ret;
int saved_errno = errno;
-#if USE_XPG_STRERROR_R
+#if STRERROR_R_CHAR_P
{
+ ret = 0;
+
+# if HAVE___XPG_STRERROR_R
ret = __xpg_strerror_r (errnum, buf, buflen);
if (ret < 0)
ret = errno;
+# endif
+
if (!*buf)
{
/* glibc 2.13 would not touch buf on err, so we have to fall
back to GNU strerror_r which always returns a thread-safe
untruncated string to (partially) copy into our buf. */
- safe_copy (buf, buflen, strerror_r (errnum, buf, buflen));
+ char *errstring = strerror_r (errnum, buf, buflen);
+ ret = errstring ? safe_copy (buf, buflen, errstring) : errno;
}
}
-#elif USE_SYSTEM_STRERROR_R
+#elif HAVE_DECL_STRERROR_R
if (buflen > INT_MAX)
buflen = INT_MAX;
@@ -245,7 +244,7 @@ strerror_r (int errnum, char *buf, size_t buflen)
}
# endif
-#else /* USE_SYSTEM_STRERROR */
+#else /* strerror_r is not declared. */
/* Try to do what strerror (errnum) does, but without clobbering the
buffer used by strerror(). */