2011-06-21 Eric Blake <eblake@redhat.com>
+ strerror_r: fix OpenBSD behavior on 0
+ * lib/strerror-override.c (strerror_override): Also override 0
+ when needed.
+ * lib/strerror-override.h (strerror_override): Likewise.
+ * lib/strerror.c (strerror): Simplify, now that 0 override is done
+ earlier.
+ * lib/strerror_r.c (strerror_r): Likewise.
+ * m4/strerror.m4 (gl_FUNC_STRERROR): Split detection of 0
+ behavior...
+ (gl_FUNC_STRERROR_0): ...into new macro.
+ * m4/strerror_r.m4 (gl_FUNC_STRERROR_R): Replace strerror_r if 0
+ is overridden.
+ (gl_FUNC_STRERROR_R_WORKS): Avoid extra tests if 0 is broken.
+ * modules/strerror-override (Files): Add strerror.m4.
+ (configure.ac): Also provide override for 0 when needed.
+ * doc/posix-functions/strerror.texi (strerror): Document this.
+ * doc/posix-functions/perror.texi (perror): Likewise.
+
perror: adjust array size
* modules/perror (Depends-on): Add strerror-override.
* lib/perror.c (perror): Use it to avoid magic number.
@item
This function treats @code{errno} of 0 like failure, although POSIX
requires that the message declare it as a success, on some platforms:
-FreeBSD 8.2, MacOS X 10.5.
+FreeBSD 8.2, OpenBSD 4.7, MacOS X 10.5.
@item
This function clobbers the @code{strerror} buffer on some platforms:
Cygwin 1.7.9.
@code{errno} or using a string similar to out-of-range values),
although POSIX requires this to leave @code{errno} unchanged and
report success, on some platforms:
-FreeBSD 8.2, MacOS X 10.5.
+FreeBSD 8.2, OpenBSD 4.7, MacOS X 10.5.
@item
This function fails to return a string for out-of-range integers on
some platforms:
/* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */
switch (errnum)
{
+#if REPLACE_STRERROR_0
+ case 0:
+ return "Success";
+#endif
+
#if GNULIB_defined_ETXTBSY
case ETXTBSY:
return "Text file busy";
|| GNULIB_defined_ENOTSUP \
|| GNULIB_defined_ESTALE \
|| GNULIB_defined_EDQUOT \
- || GNULIB_defined_ECANCELED
+ || GNULIB_defined_ECANCELED \
+ || REPLACE_STRERROR_0
extern const char *strerror_override (int errnum);
# else
# define strerror_override(ignored) NULL
if (msg)
return (char *) msg;
- /* FreeBSD rejects 0; see http://austingroupbugs.net/view.php?id=382.
- MacOS X 10.5 does not distinguish 0 from -1. */
- if (n)
- msg = strerror (n);
- else
- {
- int saved_errno = errno;
- errno = 0;
- msg = strerror (n);
- if (errno || (msg &&
- (strstr (msg, "nknown") || strstr (msg, "ndefined"))))
- msg = "Success";
- errno = saved_errno;
- }
+ msg = strerror (n);
/* Our strerror_r implementation might use the system's strerror
buffer, so all other clients of strerror have to see the error
if (ret < 0)
ret = errno;
- /* FreeBSD rejects 0; see http://austingroupbugs.net/view.php?id=382.
- MacOS X 10.5 strerror_r differs from the strerror string for 0. */
- if (errnum == 0)
- {
-# if defined __APPLE__ && defined __MACH__
- ret = EINVAL;
-# endif
- if (ret == EINVAL)
- ret = safe_copy (buf, buflen, "Success");
- }
-
#else /* USE_SYSTEM_STRERROR */
/* Try to do what strerror (errnum) does, but without clobbering the
-# strerror.m4 serial 15
+# strerror.m4 serial 16
dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
[
AC_REQUIRE([gl_HEADER_STRING_H_DEFAULTS])
AC_REQUIRE([gl_HEADER_ERRNO_H])
+ AC_REQUIRE([gl_FUNC_STRERROR_0])
m4_ifdef([gl_FUNC_STRERROR_R_WORKS], [
AC_REQUIRE([gl_FUNC_STRERROR_R_WORKS])
])
- if test -z "$ERRNO_H"; then
+ if test "$ERRNO_H:$REPLACE_STRERROR_0" = :0; then
AC_CACHE_CHECK([for working strerror function],
[gl_cv_func_working_strerror],
[AC_RUN_IFELSE(
[AC_LANG_PROGRAM(
[[#include <string.h>
- #include <errno.h>
]],
- [[int result = 0;
- char *str;
- if (!*strerror (-2)) result |= 1;
- errno = 0;
- str = strerror (0);
- if (!*str) result |= 2;
- if (errno) result |= 4;
- if (strstr (str, "nknown") || strstr (str, "ndefined"))
- result |= 8;
- return result;]])],
+ [[if (!*strerror (-2)) return 1;]])],
[gl_cv_func_working_strerror=yes],
[gl_cv_func_working_strerror=no],
[dnl Be pessimistic on cross-compiles for now.
- gl_cv_func_working_strerror=no])
+ gl_cv_func_working_strerror="guessing no"])
])
- if test $gl_cv_func_working_strerror = no; then
+ if test "$gl_cv_func_working_strerror" != yes; then
dnl The system's strerror() fails to return a string for out-of-range
dnl integers. Replace it.
REPLACE_STRERROR=1
])
else
dnl The system's strerror() cannot know about the new errno values we add
- dnl to <errno.h>. Replace it.
+ dnl to <errno.h>, or any fix for strerror(0). Replace it.
REPLACE_STRERROR=1
fi
])
+
+dnl Detect if strerror(0) passes (that is, does not set errno, and does not
+dnl return a string that matches strerror(-1)).
+AC_DEFUN([gl_FUNC_STRERROR_0],
+[
+ REPLACE_STRERROR_0=0
+ AC_CACHE_CHECK([whether strerror(0) succeeds],
+ [gl_cv_func_strerror_0_works],
+ [AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <string.h>
+ #include <errno.h>
+ ]],
+ [[int result = 0;
+ char *str;
+ errno = 0;
+ str = strerror (0);
+ if (!*str) result |= 1;
+ if (errno) result |= 2;
+ if (strstr (str, "nknown") || strstr (str, "ndefined"))
+ result |= 4;
+ return result;]])],
+ [gl_cv_func_strerror_0_works=yes],
+ [gl_cv_func_strerror_0_works=no],
+ [dnl Be pessimistic on cross-compiles for now.
+ gl_cv_func_strerror_0_works="guessing no"])
+ ])
+ if test "$gl_cv_func_strerror_0_works" != yes; then
+ REPLACE_STRERROR_0=1
+ AC_DEFINE([REPLACE_STRERROR_0], [1], [Define to 1 if strerror(0)
+ does not return a message implying success.])
+ fi
+])
-# strerror_r.m4 serial 11
+# strerror_r.m4 serial 12
dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
fi
if test $ac_cv_func_strerror_r = yes; then
- if test -z "$ERRNO_H"; then
+ if test "$ERRNO_H:$REPLACE_STRERROR_0" = :0; then
if test $gl_cv_func_strerror_r_posix_signature = yes; then
case "$gl_cv_func_strerror_r_works" in
dnl The system's strerror_r has bugs. Replace it.
fi
else
dnl The system's strerror_r() cannot know about the new errno values we
- dnl add to <errno.h>. Replace it.
+ dnl add to <errno.h>, or any fix for strerror(0). Replace it.
REPLACE_STRERROR_R=1
fi
fi
# Prerequisites of lib/strerror_r.c.
AC_DEFUN([gl_PREREQ_STRERROR_R], [
dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r.
- AC_CHECK_FUNCS([__xpg_strerror_r])
+ AC_CHECK_FUNCS_ONCE([__xpg_strerror_r])
AC_CHECK_FUNCS_ONCE([catgets])
])
[
AC_REQUIRE([gl_HEADER_ERRNO_H])
AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_REQUIRE([gl_FUNC_STRERROR_0])
AC_CHECK_FUNCS_ONCE([strerror_r])
if test $ac_cv_func_strerror_r = yes; then
- if test -z "$ERRNO_H"; then
+ if test "$ERRNO_H:$REPLACE_STRERROR_0" = :0; then
dnl The POSIX prototype is: int strerror_r (int, char *, size_t);
dnl glibc, Cygwin: char *strerror_r (int, char *, size_t);
dnl AIX 5.1, OSF/1 5.1: int strerror_r (int, char *, int);
aix*) gl_cv_func_strerror_r_works="guessing no";;
# Guess no on HP-UX.
hpux*) gl_cv_func_strerror_r_works="guessing no";;
- # Guess no on FreeBSD.
- freebsd*) gl_cv_func_strerror_r_works="guessing no";;
+ # Guess no on BSD variants.
+ *bsd*) gl_cv_func_strerror_r_works="guessing no";;
# Guess yes otherwise.
*) gl_cv_func_strerror_r_works="guessing yes";;
esac
else
dnl The system's strerror() has a wrong signature.
dnl glibc >= 2.3.4 and cygwin 1.7.9 have a function __xpg_strerror_r.
- AC_CHECK_FUNCS([__xpg_strerror_r])
+ AC_CHECK_FUNCS_ONCE([__xpg_strerror_r])
dnl In glibc < 2.14, __xpg_strerror_r does not populate buf on failure.
dnl In cygwin < 1.7.10, __xpg_strerror_r clobbers strerror's buffer.
if test $ac_cv_func___xpg_strerror_r = yes; then
lib/strerror-override.h
lib/strerror-override.c
m4/sys_socket_h.m4
+m4/strerror.m4
Depends-on:
errno
configure.ac:
AC_REQUIRE([gl_HEADER_ERRNO_H])
-if test -n "$ERRNO_H"; then
+AC_REQUIRE([gl_FUNC_STRERROR_0])
+if test -n "$ERRNO_H" || test $REPLACE_STRERROR_0 = 1; then
AC_LIBOBJ([strerror-override])
gl_PREREQ_SYS_H_WINSOCK2
fi