bug-gnulib
[Top][All Lists]
Advanced

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

Re: [Bug-gnulib] *now*, close_stdout always does


From: Jim Meyering
Subject: Re: [Bug-gnulib] *now*, close_stdout always does
Date: Sun, 14 Nov 2004 01:41:14 +0100

Jim Meyering <address@hidden> wrote:
> I wrote:
>> That makes it clear to me that close_stdout must always close
>> standard output.

Well, almost always.
Not when it's already closed at start-up.

Does anyone know how portable the use of EBADF is, below?

Without this change, ``mkdir D >&-'' (and many other tools
that needn't generate output) would fail unnecessarily.
I've just committed this in coreutils, along with some tests.
I'll update gnulib tomorrow.

2004-11-14  Jim Meyering  <address@hidden>

        * closeout.c (close_stdout): Don't fail just because stdout was
        closed initially, since some programs don't write to stdout in the
        normal course of operation (other than --version and --help), and
        we don't want this function to make e.g. `cp 1 2 >&-' fail.
        But do fail if it was closed and someone has tried to write to it.
        E.g., printf 'foo' >&-

Index: lib/closeout.c
===================================================================
RCS file: /fetish/cu/lib/closeout.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -p -u -r1.16 -r1.17
--- lib/closeout.c      6 Nov 2004 22:37:23 -0000       1.16
+++ lib/closeout.c      14 Nov 2004 00:20:01 -0000      1.17
@@ -24,6 +24,7 @@
 #include "closeout.h"
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <errno.h>
 
 #include "gettext.h"
@@ -32,6 +33,7 @@
 #include "error.h"
 #include "exitfail.h"
 #include "quotearg.h"
+#include "__fpending.h"
 
 #if USE_UNLOCKED_IO
 # include "unlocked-io.h"
@@ -71,14 +73,25 @@ close_stdout_set_file_name (const char *
 void
 close_stdout (void)
 {
-  int e = ferror (stdout) ? 0 : -1;
+  bool prev_fail = ferror (stdout);
+  bool none_pending = (0 == __fpending (stdout));
+  bool fclose_fail = fclose (stdout);
 
-  if (fclose (stdout) != 0)
-    e = errno;
-
-  if (0 <= e)
+  if (prev_fail || fclose_fail)
     {
-      char const *write_error = _("write error");
+      int e = fclose_fail ? errno : 0;
+      char const *write_error;
+
+      /* If ferror returned zero, no data remains to be flushed, and we'd
+        otherwise fail with EBADF due to a failed fclose, then assume that
+        it's ok to ignore the fclose failure.  That can happen when a
+        program like cp is invoked like this `cp a b >&-' (i.e., with
+        stdout closed) and doesn't generate any output (hence no previous
+        error and nothing to be flushed).  */
+      if (e == EBADF && !prev_fail && none_pending)
+       return;
+
+      write_error = _("write error");
       if (file_name)
        error (exit_failure, e, "%s: %s", quotearg_colon (file_name),
               write_error);




reply via email to

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