changeset 8730:4bf589f923fc

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.
author Eric Blake <ebb9@byu.net>
date Fri, 27 Apr 2007 17:14:39 +0000
parents 9901a6759c3a
children 2e1ecfc17762
files ChangeLog lib/closein.c lib/unistd_.h modules/closein-tests tests/test-closein.c tests/test-closein.sh
diffstat 6 files changed, 122 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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
--- a/lib/closein.c
+++ b/lib/closein.c
@@ -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 @@
 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 ();
--- a/lib/unistd_.h
+++ b/lib/unistd_.h
@@ -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.  */
 
new file mode 100644
--- /dev/null
+++ b/modules/closein-tests
@@ -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
new file mode 100644
--- /dev/null
+++ b/tests/test-closein.c
@@ -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;
+}
new file mode 100755
--- /dev/null
+++ b/tests/test-closein.sh
@@ -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