summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2011-05-20 11:09:53 -0600
committerEric Blake <eblake@redhat.com>2011-05-20 12:01:05 -0600
commit88dabde472b81a034a72484a32ef51d0fd549db8 (patch)
tree8bacd95a16e20782e3974205b567e89a9a3d1560
parentc0fb797b4075b0e5f93207d4df1704aa6615cac0 (diff)
downloadgnulib-88dabde472b81a034a72484a32ef51d0fd549db8.tar.gz
perror: work around FreeBSD bug
POSIX requires that 'errno = 0; perror ("")' print the same message as strerror(0), but this failed if we were replacing strerror to work around the FreeBSD bug of treating 0 as a failure. The goal here is to _not_ replace perror on glibc, even though strerror_r has to be replaced, because the strerror_r replacement is only for the sake of correcting the signature rather than working around bugs in the handling of any particular errnum value. Recall that $gl_cv_func_strerror_r_works is only set if the POSIX signature was detected in the first place. * m4/perror.m4 (gl_FUNC_PERROR): Also replace perror if strerror_r is broken. Move AC_LIBOBJ... * modules/perror (configure.ac): Here. * doc/posix-functions/perror.texi (perror): Document this. * tests/test-perror2.c (main): Enhance test. Signed-off-by: Eric Blake <eblake@redhat.com>
-rw-r--r--ChangeLog7
-rw-r--r--doc/posix-functions/perror.texi4
-rw-r--r--m4/perror.m410
-rw-r--r--modules/perror3
-rw-r--r--tests/test-perror2.c22
5 files changed, 44 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 5001637a60..e1f9b6773d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2011-05-20 Eric Blake <eblake@redhat.com>
+ perror: work around FreeBSD bug
+ * m4/perror.m4 (gl_FUNC_PERROR): Also replace perror if strerror_r
+ is broken. Move AC_LIBOBJ...
+ * modules/perror (configure.ac): Here.
+ * doc/posix-functions/perror.texi (perror): Document this.
+ * tests/test-perror2.c (main): Enhance test.
+
test-perror: check for strerror interactions
* tests/macros.h (STREQ) Add macro.
* modules/perror-tests (Files): Add second test.
diff --git a/doc/posix-functions/perror.texi b/doc/posix-functions/perror.texi
index 29231064b3..cf6ac79d1c 100644
--- a/doc/posix-functions/perror.texi
+++ b/doc/posix-functions/perror.texi
@@ -12,6 +12,10 @@ Portability problems fixed by Gnulib:
This function does not support the error values that are specified by POSIX
but not defined by the system, on some platforms:
OpenBSD 4.0, OSF/1 5.1, Cygwin 1.5.x, mingw.
+@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
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/m4/perror.m4 b/m4/perror.m4
index 2a03e0809d..d08f365e07 100644
--- a/m4/perror.m4
+++ b/m4/perror.m4
@@ -1,4 +1,4 @@
-# perror.m4 serial 1
+# perror.m4 serial 2
dnl Copyright (C) 2008-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,
@@ -8,10 +8,16 @@ AC_DEFUN([gl_FUNC_PERROR],
[
AC_REQUIRE([gl_STDIO_H_DEFAULTS])
AC_REQUIRE([gl_HEADER_ERRNO_H])
+ AC_REQUIRE([gl_FUNC_STRERROR_R])
if test -n "$ERRNO_H"; then
dnl The system's perror() cannot know about the new errno values we add
dnl to <errno.h>. Replace it.
REPLACE_PERROR=1
- AC_LIBOBJ([perror])
fi
+ case ${gl_cv_func_strerror_r_works-unset} in
+ unset|*yes) ;;
+ *) dnl The system's perror() probably inherits the bugs in the
+ dnl system's strerror_r(). Replace it.
+ REPLACE_PERROR=1 ;;
+ esac
])
diff --git a/modules/perror b/modules/perror
index af79a0d8e7..1ff9ec27e5 100644
--- a/modules/perror
+++ b/modules/perror
@@ -16,6 +16,9 @@ strerror_r-posix [test $REPLACE_PERROR = 1]
configure.ac:
gl_FUNC_PERROR
gl_STRING_MODULE_INDICATOR([perror])
+if test $REPLACE_PERROR = 1; then
+ AC_LIBOBJ([perror])
+fi
Makefile.am:
diff --git a/tests/test-perror2.c b/tests/test-perror2.c
index dfcabb4fb7..fe5e33eba0 100644
--- a/tests/test-perror2.c
+++ b/tests/test-perror2.c
@@ -88,6 +88,28 @@ main (void)
ASSERT (STREQ (msg4, str4));
}
+ /* Test that perror uses the same message as strerror. */
+ {
+ int errs[] = { EACCES, 0, -3, };
+ int i;
+ for (i = 0; i < SIZEOF (errs); i++)
+ {
+ char buf[256];
+ char *err = strerror (errs[i]);
+
+ ASSERT (err);
+ ASSERT (strlen (err) < sizeof buf);
+ rewind (stderr);
+ ASSERT (ftruncate (fileno (stderr), 0) == 0);
+ errno = errs[i];
+ perror (NULL);
+ ASSERT (!ferror (stderr));
+ rewind (stderr);
+ ASSERT (fgets (buf, sizeof buf, stderr) == buf);
+ ASSERT (strstr (buf, err));
+ }
+ }
+
/* Test that perror reports write failure. */
{
ASSERT (freopen (BASE ".tmp", "r", stderr) == stderr);