Fix closein for mingw.
authorEric Blake <ebb9@byu.net>
Fri, 27 Apr 2007 17:14:39 +0000 (17:14 +0000)
committerEric Blake <ebb9@byu.net>
Fri, 27 Apr 2007 17:14:39 +0000 (17:14 +0000)
* modules/closein-tests: Add tests for closein.
* tests/test-closein.c: New file.
* tests/test-closein.sh: Likewise.
* lib/unistd_.h [!SEEK_CUR]: Mingw also needs stdlib.h for _exit.
* lib/closein.c (close_stdin): Don't fflush non-seekable streams.

ChangeLog
lib/closein.c
lib/unistd_.h
modules/closein-tests [new file with mode: 0644]
tests/test-closein.c [new file with mode: 0644]
tests/test-closein.sh [new file with mode: 0755]

index 6b3e691102680e9fcbbb84a362f4e19b68d8cb39..7d8e5c3f2ec95e4b9230e1ca9d650c90bd1883af 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-04-27  Eric Blake  <ebb9@byu.net>
+
+       Fix closein for mingw.
+       * modules/closein-tests: Add tests for closein.
+       * tests/test-closein.c: New file.
+       * tests/test-closein.sh: Likewise.
+       * lib/unistd_.h [!SEEK_CUR]: Mingw also needs stdlib.h for _exit.
+       * lib/closein.c (close_stdin): Don't fflush non-seekable streams.
+
 2007-04-27  Bruno Haible  <bruno@clisp.org>
 
        * lib/inttypes_.h [_DECC]: Don't use #include_next if the compiler
index 51534842624451e877783ea56d2974ac55a1b0cb..4450d5bd8dd6be0a2fdd290942ad2773a916b001 100644 (file)
@@ -19,7 +19,6 @@
 #include <config.h>
 
 #include "closein.h"
-#include "closeout.h"
 
 #include <errno.h>
 #include <stdbool.h>
@@ -30,6 +29,7 @@
 #define _(msgid) gettext (msgid)
 
 #include "close-stream.h"
+#include "closeout.h"
 #include "error.h"
 #include "exitfail.h"
 #include "quotearg.h"
@@ -79,18 +79,23 @@ void
 close_stdin (void)
 {
   bool fail = false;
-  if (fflush (stdin) != 0 || close_stream (stdin) != 0)
+
+  /* Only attempt flush if stdin is seekable, as fflush is entitled to
+     fail on non-seekable streams.  */
+  if (fseeko (stdin, 0, SEEK_CUR) == 0 && fflush (stdin) != 0)
+    fail = true;
+  if (close_stream (stdin) != 0)
+    fail = true;
+  if (fail)
     {
+      /* Report failure, but defer exit until after closing stdout,
+        since the failure report should still be flushed.  */
       char const *close_error = _("error closing file");
       if (file_name)
        error (0, errno, "%s: %s", quotearg_colon (file_name),
               close_error);
       else
        error (0, errno, "%s", close_error);
-
-      /* Defer failure until after closing stdout, since the output
-        can still usefully be flushed.  */
-      fail = true;
     }
 
   close_stdout ();
index 344b5a388823a78509d23db7963cd28c6825b0dd..4febc90b46e6815deef64a57026edc0aa0bd660e 100644 (file)
@@ -27,6 +27,8 @@
 # include <stdio.h>
 #endif
 
+/* mingw fails to declare _exit in <unistd.h>.  */
+#include <stdlib.h>
 
 /* The definition of GL_LINK_WARNING is copied here.  */
 
diff --git a/modules/closein-tests b/modules/closein-tests
new file mode 100644 (file)
index 0000000..efadac5
--- /dev/null
@@ -0,0 +1,13 @@
+Files:
+tests/test-closein.sh
+tests/test-closein.c
+
+Depends-on:
+binary-io
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-closein.sh
+TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@'
+check_PROGRAMS += test-closein
diff --git a/tests/test-closein.c b/tests/test-closein.c
new file mode 100644 (file)
index 0000000..90214e8
--- /dev/null
@@ -0,0 +1,49 @@
+/* Test of closein module.
+   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 2, 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.  */
+
+#include <config.h>
+
+#include "closein.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "binary-io.h"
+
+char *program_name;
+
+/* With no arguments, do nothing.  With arguments, attempt to consume
+   first 6 bytes of stdin.  In either case, let exit() take care of
+   closing std streams and changing exit status if ferror(stdin).  */
+int
+main (int argc, char **argv)
+{
+  char buf[7];
+  int i = -1;
+  atexit(close_stdin);
+  program_name = argv[0];
+
+  /* close_stdin currently relies on ftell, but mingw ftell is
+     unreliable on text mode input.  */
+  SET_BINARY (0);
+
+  if (argc > 1)
+    i = fread (buf, 1, 6, stdin);
+  return 0;
+}
diff --git a/tests/test-closein.sh b/tests/test-closein.sh
new file mode 100755 (executable)
index 0000000..8623ead
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+tmpfiles=
+trap 'rm -fr $tmpfiles' 1 2 3 15
+
+p=t-closein-
+tmpfiles="${p}in.tmp ${p}xout.tmp ${p}out1.tmp ${p}out2.tmp"
+
+echo Hello world > ${p}in.tmp
+echo world > ${p}xout.tmp
+
+# Test with seekable stdin; followon process must see remaining data
+(./test-closein${EXEEXT}; cat) < ${p}in.tmp > ${p}out1.tmp || exit 1
+cmp ${p}out1.tmp ${p}in.tmp || exit 1
+
+(./test-closein${EXEEXT} consume; cat) < ${p}in.tmp > ${p}out2.tmp || exit 1
+cmp ${p}out2.tmp ${p}xout.tmp || exit 1
+
+# Test for lack of error on pipe
+cat ${p}in.tmp | ./test-closein${EXEEXT} || exit 1
+
+cat ${p}in.tmp | ./test-closein${EXEEXT} consume || exit 1
+
+# Test for lack of error when nothing is read
+./test-closein${EXEEXT} </dev/null || exit 1
+
+./test-closein${EXEEXT} <&- || exit 1
+
+# Test for no error when EOF is read early
+./test-closein${EXEEXT} consume </dev/null || exit 1
+
+# Test for error when read fails because no file available
+./test-closein${EXEEXT} consume <&- 2>/dev/null && exit 1
+
+# Cleanup
+rm -fr $tmpfiles
+
+exit 0