autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Diagnose write errors in config.status


From: Ralf Wildenhues
Subject: Diagnose write errors in config.status
Date: Thu, 15 Nov 2007 22:37:20 +0100
User-agent: Mutt/1.5.13 (2006-08-11)

Plowing my way through Bruno's bug reports and suggestions from:
<http://thread.gmane.org/gmane.comp.lib.gnulib.bugs/11571/focus=11850>.
Let's make write errors fail config.status.

First off, writing a test that exercises all possible code paths is
rather difficult.  I left it at a reasonably primitive addition to an
existing test, where most of the write errors will just trigger at the
`mkdir "$tmp"' near the beginning.  And a couple of tests using
/dev/full which I guess is not portable; however, on systems without it,
the redirection will just fail, so we should at least degrade gracefully.

I just went through status.m4 once, searching for all failure spots.
I deliberately left out checking all the
  cat >$CONFIG_STATUS <<...

for now, my (weak) rationale being that with a write error, the
config.status file will likely be completely unusable anyway (and my
other one being laziness for now).  Do you think each one of them should
be checked as well?  I can try fixing that then.

I believe to have found all other spots, but would of course appreciate
a second pair of eyes.

OK to apply?

Cheers,
Ralf

    Diagnose write errors in config.status instantiations.
    
    * lib/autoconf/status.m4 (_AC_OUTPUT_FILE)
    (_AC_OUTPUT_HEADER, _AC_OUTPUT_MAIN_LOOP): Bail out
    on write errors.
    * tests/torture.at (AC_CONFIG_FILES, HEADERS, LINKS and COMMANDS):
    Extend test to also check for some write error failures, using...
    <AT_CHECK_CONFIG_CREATION_NOWRITE>: ...this new macro.
    Report by Bruno Haible.

diff --git a/lib/autoconf/status.m4 b/lib/autoconf/status.m4
index 0d1d93e..4a617a6 100644
--- a/lib/autoconf/status.m4
+++ b/lib/autoconf/status.m4
@@ -636,7 +636,8 @@ m4_foreach([_AC_Var], [srcdir, abs_srcdir, top_srcdir, 
abs_top_srcdir,
 ])dnl
 m4_ifndef([AC_DATAROOTDIR_CHECKED], [$ac_datarootdir_hack
 ])dnl
-" $ac_file_inputs m4_defn([_AC_SUBST_CMDS]) >$tmp/out
+" $ac_file_inputs m4_defn([_AC_SUBST_CMDS]) >$tmp/out \
+  || AC_MSG_ERROR([could not create $ac_file])
 
 m4_ifndef([AC_DATAROOTDIR_CHECKED],
 [test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
@@ -648,9 +649,10 @@ which seems to be undefined.  Please make sure it is 
defined.])
 
   rm -f "$tmp/stdin"
   case $ac_file in
-  -) cat "$tmp/out"; rm -f "$tmp/out";;
-  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;
-  esac
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" $ac_file;;
+  esac \
+  || AC_MSG_ERROR([could not create $ac_file])
 dnl This would break Makefile dependencies:
 dnl  if diff $ac_file "$tmp/out" >/dev/null 2>&1; then
 dnl    echo "$ac_file is unchanged"
@@ -838,17 +840,22 @@ m4_define([_AC_OUTPUT_HEADER],
   # CONFIG_HEADER
   #
   if test x"$ac_file" != x-; then
-    AS_ECHO(["/* $configure_input  */"]) >"$tmp/config.h"
-    $AWK -f "$tmp/defines.awk" $ac_file_inputs >>"$tmp/config.h"
+    {
+      AS_ECHO(["/* $configure_input  */"]) \
+      && $AWK -f "$tmp/defines.awk" $ac_file_inputs
+    } >"$tmp/config.h" \
+      || AC_MSG_ERROR([could not create $ac_file])
     if diff $ac_file "$tmp/config.h" >/dev/null 2>&1; then
       AC_MSG_NOTICE([$ac_file is unchanged])
     else
       rm -f $ac_file
-      mv "$tmp/config.h" $ac_file
+      mv "$tmp/config.h" $ac_file \
+       || AC_MSG_ERROR([could not create $ac_file])
     fi
   else
-    AS_ECHO(["/* $configure_input  */"])
-    $AWK -f "$tmp/defines.awk" $ac_file_inputs
+    AS_ECHO(["/* $configure_input  */"]) \
+      && $AWK -f "$tmp/defines.awk" $ac_file_inputs \
+      || AC_MSG_ERROR([could not create -])
   fi
 dnl If running for Automake, be ready to perform additional
 dnl commands to set up the timestamp files.
@@ -1617,7 +1624,8 @@ do
     fi
 
     case $ac_tag in
-    *:-:* | *:-) cat >"$tmp/stdin";;
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || AC_MSG_ERROR([could not create $ac_file]) ;;
     esac
     ;;
   esac
diff --git a/tests/torture.at b/tests/torture.at
index 63d6ef9..a87a33b 100644
--- a/tests/torture.at
+++ b/tests/torture.at
@@ -193,6 +193,29 @@ AT_CHECK([grep OK var-$1], [], [OK
 ])# AT_CHECK_CONFIG_CREATION
 
 
+# AT_CHECK_CONFIG_CREATION_NOWRITE(THING = (header | link | file | command))
+# ------------------------------------------------------------------
+# Check that THING and var-THING (which uses variables in AC_CONFIG_THING)
+# are properly created, with the right content.
+# Use `grep OK' instead of a simple `cat' to avoid banners such as in
+# AC_CONFIG_HEADERS.
+m4_define([AT_CHECK_CONFIG_CREATION_NOWRITE],
+[AT_CHECK_CONFIGURE([what_to_test=$1])
+AT_CHECK([ls header var-header file var-file command var-command link var-link 
2>/dev/null],
+        [ignore], [$1
+])
+AT_CHECK([grep OK $1], [], [OK
+])
+
+AT_CHECK_CONFIGURE([what_to_test=var-$1 --no-create])
+# config.status might be stupidly expecting data on stdin, if it's
+# really broken...
+chmod a-w .
+AT_CHECK([./config.status var-$1 </dev/null], [1], [ignore], [ignore])
+chmod u+w .
+])# AT_CHECK_CONFIG_CREATION_NOWRITE
+
+
 # Create a file
 AT_CHECK_CONFIG_CREATION(file)
 
@@ -205,6 +228,24 @@ AT_CHECK_CONFIG_CREATION(command)
 # Create a link
 AT_CHECK_CONFIG_CREATION(link)
 
+# Now check for write errors
+
+# Create a file
+AT_CHECK_CONFIG_CREATION_NOWRITE(file)
+AT_CHECK([./config.status --file=-:input </dev/null >/dev/full],
+        [1], [ignore], [ignore])
+
+# Create a header
+AT_CHECK_CONFIG_CREATION_NOWRITE(header)
+AT_CHECK([./config.status --header=-:input </dev/null >/dev/full],
+        [1], [ignore], [ignore])
+
+# Execute a command
+AT_CHECK_CONFIG_CREATION_NOWRITE(command)
+
+# Create a link
+AT_CHECK_CONFIG_CREATION_NOWRITE(link)
+
 AT_CLEANUP
 
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]