From c60d92c4a7834866d3dee9ad5c2dfc72849c7470 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@meta.com>
Date: Tue, 15 Apr 2025 18:44:55 -0700
Subject: [PATCH] close-stream: don't clobber errno upon prior failure
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Don't reset errno when returning due to a prior stream error.
* lib/close-stream.c (close_stream): Don't clobber errno if prev_fail
is true.  Reported by Jaroslav Škarvada in https://bugs.gnu.org/77800
---
 ChangeLog          |  7 +++++++
 lib/close-stream.c | 11 ++++++-----
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 28322a2655..7c09f61044 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2025-04-15  Jim Meyering  <meyering@meta.com>
+
+	close-stream: don't clobber errno upon prior failure
+	Don't reset errno when returning due to a prior stream error.
+	* lib/close-stream.c (close_stream): Don't clobber errno if prev_fail
+	is true.  Reported by Jaroslav Škarvada in https://bugs.gnu.org/77800
+
 2025-04-15  Paul Eggert  <eggert@cs.ucla.edu>

 	dfa: pacify gcc -Wstringop-overflow
diff --git a/lib/close-stream.c b/lib/close-stream.c
index 5dbb19c6ce..ddb04ce6f5 100644
--- a/lib/close-stream.c
+++ b/lib/close-stream.c
@@ -61,14 +61,15 @@ close_stream (FILE *stream)
   /* Return an error indication if there was a previous failure or if
      fclose failed, with one exception: ignore an fclose failure if
      there was no previous error, no data remains to be flushed, and
-     fclose failed with EBADF.  That can happen when a program like cp
-     is invoked like this 'cp a b >&-' (i.e., with standard output
-     closed) and doesn't generate any output (hence no previous error
-     and nothing to be flushed).  */
+     fclose failed with EBADF.  In the case of an ignorable fclose
+     failure, clear errno to avoid misleading diagnostics. That can
+     happen when a program like cp is invoked like this 'cp a b >&-'
+     (i.e., with standard output closed) and doesn't generate any output
+     (hence no previous error and nothing to be flushed).  */

   if (prev_fail || (fclose_fail && (some_pending || errno != EBADF)))
     {
-      if (! fclose_fail)
+      if (!fclose_fail && !prev_fail)
         errno = 0;
       return EOF;
     }
-- 
2.49.0.154.g9d22ac5122

