From d5d3e86d326de4aa7d661fde1ebb636f3efbffd5 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Tue, 25 Sep 2007 10:40:16 -0600 Subject: [PATCH] Fix strerror on Interix. * lib/string_.h (strerror): Declare replacement. * doc/functions/strerror.texi (strerror): Document the Interix shortcoming. * modules/string (Makefile.am): Support new hooks. * m4/string_h.m4 (gl_HEADER_STRING_H_DEFAULTS): Add new hooks. * m4/strerror.m4 (gl_FUNC_STRERROR): Defer to gl_FUNC_STRERROR_SEPARATE. (gl_FUNC_STRERROR_SEPARATE): Check for Interix bug. * lib/strerror.c (rpl_strerror): Provide replacement. * modules/strerror (Depends-on): Add string. (configure.ac): Detect use of module. * tests/test-strerror.c: New file. * modules/strerror-tests: New test module. * modules/argp (Depends-on): Add strerror. * modules/error (Depends-on): Likewise. Reported by Martin Koeppe. Signed-off-by: Eric Blake --- ChangeLog | 20 +++++++++++++++++ doc/functions/strerror.texi | 5 +++++ lib/strerror.c | 24 +++++++++++++++++++- lib/string_.h | 17 ++++++++++++++ m4/strerror.m4 | 31 +++++++++++++++++++++---- m4/string_h.m4 | 3 +++ modules/argp | 1 + modules/error | 1 + modules/strerror | 2 ++ modules/strerror-tests | 10 +++++++++ modules/string | 3 +++ tests/test-strerror.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 modules/strerror-tests create mode 100644 tests/test-strerror.c diff --git a/ChangeLog b/ChangeLog index 90c041432..78fa16cad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2007-09-25 Eric Blake + + Fix strerror on Interix. + * lib/string_.h (strerror): Declare replacement. + * doc/functions/strerror.texi (strerror): Document the Interix + shortcoming. + * modules/string (Makefile.am): Support new hooks. + * m4/string_h.m4 (gl_HEADER_STRING_H_DEFAULTS): Add new hooks. + * m4/strerror.m4 (gl_FUNC_STRERROR): Defer to + gl_FUNC_STRERROR_SEPARATE. + (gl_FUNC_STRERROR_SEPARATE): Check for Interix bug. + * lib/strerror.c (rpl_strerror): Provide replacement. + * modules/strerror (Depends-on): Add string. + (configure.ac): Detect use of module. + * tests/test-strerror.c: New file. + * modules/strerror-tests: New test module. + * modules/argp (Depends-on): Add strerror. + * modules/error (Depends-on): Likewise. + Reported by Martin Koeppe. + 2007-09-24 Bruno Haible * README: Update git instructions. diff --git a/doc/functions/strerror.texi b/doc/functions/strerror.texi index 9ac63e5a6..aad375497 100644 --- a/doc/functions/strerror.texi +++ b/doc/functions/strerror.texi @@ -10,6 +10,11 @@ Portability problems fixed by Gnulib: @itemize @item This function is missing on some old platforms. + +@item +This function fails to return a string for out-of-range integers on +some platforms: +Interix @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/strerror.c b/lib/strerror.c index 54b851bda..ef6234e4f 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -19,7 +19,29 @@ #include -#if !HAVE_STRERROR +#if REPLACE_STRERROR + +# include +# include + +# undef strerror + +char *rpl_strerror (int n) +{ + static char const fmt[] = "Unknown error (%d)"; + static char mesg[sizeof fmt + sizeof n * CHAR_BIT / 3]; + + char *result = strerror (n); + + if (! result) + { + sprintf (mesg, fmt, n); + return mesg; + } + return result; +} + +#elif !HAVE_STRERROR #include diff --git a/lib/string_.h b/lib/string_.h index bfb22b0eb..41e539f23 100644 --- a/lib/string_.h +++ b/lib/string_.h @@ -539,6 +539,23 @@ extern char * mbssep (char **stringp, const char *delim); extern char * mbstok_r (char *string, const char *delim, char **save_ptr); #endif +/* Map any int, typically from errno, into an error message. */ +#if @GNULIB_STRERROR@ +# if @REPLACE_STRERROR@ +# undef strerror +# define strerror rpl_strerror +# endif +# if !@HAVE_DECL_STRERROR@ || @REPLACE_STRERROR@ +extern char *strerror (int); +# endif +#elif defined GNULIB_POSIXCHECK +# undef strerror +# define strerror(e) \ + (GL_LINK_WARNING ("strerror is unportable - " \ + "use gnulib module strerror to guarantee non-NULL result"), \ + strerror (e)) +#endif + #ifdef __cplusplus } diff --git a/m4/strerror.m4 b/m4/strerror.m4 index bbcda3050..52f3e3fdc 100644 --- a/m4/strerror.m4 +++ b/m4/strerror.m4 @@ -1,4 +1,4 @@ -# strerror.m4 serial 3 +# strerror.m4 serial 4 dnl Copyright (C) 2002, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -6,10 +6,11 @@ dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_FUNC_STRERROR], [ - AC_CHECK_FUNCS_ONCE([strerror]) - if test $ac_cv_func_strerror = no; then + AC_REQUIRE([gl_FUNC_STRERROR_SEPARATE]) + if test $gl_cv_func_working_strerror = no; then AC_LIBOBJ([strerror]) - gl_PREREQ_STRERROR + AC_DEFINE_UNQUOTED([REPLACE_STRERROR], [$REPLACE_STRERROR], + [Define this to 1 if strerror is broken.]) fi ]) @@ -18,6 +19,28 @@ AC_DEFUN([gl_FUNC_STRERROR_SEPARATE], [ AC_CHECK_FUNCS_ONCE([strerror]) gl_PREREQ_STRERROR + if test $ac_cv_func_strerror = no; then + HAVE_DECL_STRERROR=0 + gl_cv_func_working_strerror=no + else + AC_CACHE_CHECK([for working strerror function], + [gl_cv_func_working_strerror], + [AC_RUN_IFELSE( + [AC_LANG_PROGRAM([ +#include + ], [return !*strerror (-2);])], + [gl_cv_func_working_strerror=yes], [gl_cv_func_working_strerror=no], + [dnl assume success except on Interix + AC_EGREP_CPP([assuming success], [ +#ifndef __INTERIX + assuming success +#endif + ], [gl_cv_func_working_strerror=yes], + [gl_cv_func_working_strerror=no])])]) + if test $gl_cv_func_working_strerror = no ; then + REPLACE_STRERROR=1 + fi + fi ]) # Prerequisites of lib/strerror.c. diff --git a/m4/string_h.m4 b/m4/string_h.m4 index ec51e9a01..d811e26b8 100644 --- a/m4/string_h.m4 +++ b/m4/string_h.m4 @@ -57,6 +57,7 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS], GNULIB_MBSSPN=0; AC_SUBST([GNULIB_MBSSPN]) GNULIB_MBSSEP=0; AC_SUBST([GNULIB_MBSSEP]) GNULIB_MBSTOK_R=0; AC_SUBST([GNULIB_MBSTOK_R]) + GNULIB_STRERROR=0; AC_SUBST([GNULIB_STRERROR]) dnl Assume proper GNU behavior unless another module says otherwise. HAVE_DECL_MEMMEM=1; AC_SUBST([HAVE_DECL_MEMMEM]) HAVE_MEMPCPY=1; AC_SUBST([HAVE_MEMPCPY]) @@ -74,4 +75,6 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS], HAVE_STRSEP=1; AC_SUBST([HAVE_STRSEP]) HAVE_STRCASESTR=1; AC_SUBST([HAVE_STRCASESTR]) HAVE_DECL_STRTOK_R=1; AC_SUBST([HAVE_DECL_STRTOK_R]) + HAVE_DECL_STRERROR=1; AC_SUBST([HAVE_DECL_STRERROR]) + REPLACE_STRERROR=0; AC_SUBST([REPLACE_STRERROR]) ]) diff --git a/modules/argp b/modules/argp index b188e8ac5..da65d4f3c 100644 --- a/modules/argp +++ b/modules/argp @@ -30,6 +30,7 @@ strcase extensions vsnprintf sleep +strerror configure.ac: gl_ARGP diff --git a/modules/error b/modules/error index 4e999ca88..cdf57f07d 100644 --- a/modules/error +++ b/modules/error @@ -7,6 +7,7 @@ lib/error.c m4/error.m4 Depends-on: +strerror configure.ac: gl_ERROR diff --git a/modules/strerror b/modules/strerror index f86dd709f..24dacabe1 100644 --- a/modules/strerror +++ b/modules/strerror @@ -6,9 +6,11 @@ lib/strerror.c m4/strerror.m4 Depends-on: +string configure.ac: gl_FUNC_STRERROR +gl_STRING_MODULE_INDICATOR([strerror]) Makefile.am: diff --git a/modules/strerror-tests b/modules/strerror-tests new file mode 100644 index 000000000..0341c12c5 --- /dev/null +++ b/modules/strerror-tests @@ -0,0 +1,10 @@ +Files: +tests/test-strerror.c + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-strerror +check_PROGRAMS += test-strerror diff --git a/modules/string b/modules/string index e6d576202..c4e9f2f9b 100644 --- a/modules/string +++ b/modules/string @@ -50,6 +50,7 @@ string.h: string_.h -e 's|@''GNULIB_STRSEP''@|$(GNULIB_STRSEP)|g' \ -e 's|@''GNULIB_STRCASESTR''@|$(GNULIB_STRCASESTR)|g' \ -e 's|@''GNULIB_STRTOK_R''@|$(GNULIB_STRTOK_R)|g' \ + -e 's|@''GNULIB_STRERROR''@|$(GNULIB_STRERROR)|g' \ -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ @@ -66,6 +67,8 @@ string.h: string_.h -e 's|@''HAVE_STRSEP''@|$(HAVE_STRSEP)|g' \ -e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \ -e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \ + -e 's|@''HAVE_DECL_STRERROR''@|$(HAVE_DECL_STRERROR)|g' \ + -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \ -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \ < $(srcdir)/string_.h; \ } > $@-t diff --git a/tests/test-strerror.c b/tests/test-strerror.c new file mode 100644 index 000000000..036ce458c --- /dev/null +++ b/tests/test-strerror.c @@ -0,0 +1,55 @@ +/* Test of strerror() function. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Eric Blake , 2007. */ + +#include + +#include +#include +#include +#include + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + abort (); \ + } \ + } \ + while (0) + +int +main (int argc, char **argv) +{ + char *str; + str = strerror (EACCES); + ASSERT (str); + ASSERT (*str); + + str = strerror (0); + ASSERT (str); + ASSERT (*str); + + str = strerror (-3); + ASSERT (str); + ASSERT (*str); + + return 0; +} -- 2.11.0