* 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 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
#include <config.h>
#include "closein.h"
-#include "closeout.h"
#include <errno.h>
#include <stdbool.h>
#define _(msgid) gettext (msgid)
#include "close-stream.h"
+#include "closeout.h"
#include "error.h"
#include "exitfail.h"
#include "quotearg.h"
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 ();
# include <stdio.h>
#endif
+/* mingw fails to declare _exit in <unistd.h>. */
+#include <stdlib.h>
/* The definition of GL_LINK_WARNING is copied here. */
--- /dev/null
+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
--- /dev/null
+/* 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;
+}
--- /dev/null
+#!/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