On 2025-02-12 22:45, lilydjwg wrote:
cat: -: input file is output file
Thanks for the bug report. The symptoms you observe are a bug in 'cat'.
I also see a bug in Gawk which I reported to the Gawk maintainer
<https://lists.gnu.org/r/bug-gawk/2025-02/msg00003.html>. I don't see a
bug in zsh or fish but perhaps I'm missing something.
To fix the 'cat' bug I installed the attached patch into bleeding-edge
Coreutils on Savannah, and something like this patch should appear in
the next release.From 7386c291be8e2de115f2e161886e872429edadd7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Fri, 14 Feb 2025 13:10:02 -0800
Subject: [PATCH] =?UTF-8?q?cat:=20fix=20plain=20=E2=80=98cat=E2=80=99=20bu?=
=?UTF-8?q?g?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* src/cat.c (main): Do not fail with plain ‘cat’ where input and
output are both /dev/tty, if the output happens to have O_APPEND set.
Problem reported by lilydjwg <https://bugs.gnu.org/76255>.
Also, don’t report an error if the seek position is at or after EOF,
even if O_APPEND is set.
---
NEWS | 6 +++++-
src/cat.c | 26 +++++++++++++-------------
2 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/NEWS b/NEWS
index c9ba5f196..c6edf16d4 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,11 @@ GNU coreutils NEWS -*- outline -*-
** Bug fixes
- `ls -Z dir` would crash.
+ 'cat' would fail with "input file is output file" if input and
+ output are the same terminal device and the output is append-only.
+ [bug introduced in coreutils-9.6]
+
+ 'ls -Z dir' would crash.
[bug introduced in coreutils-9.6]
diff --git a/src/cat.c b/src/cat.c
index 274f844a1..c02210301 100644
--- a/src/cat.c
+++ b/src/cat.c
@@ -717,20 +717,20 @@ main (int argc, char **argv)
&& have_out_dev
&& stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino)
{
- if (out_flags < -1)
- out_flags = fcntl (STDOUT_FILENO, F_GETFL);
- bool exhausting = 0 <= out_flags && out_flags & O_APPEND;
- if (!exhausting)
+ off_t in_pos = lseek (input_desc, 0, SEEK_CUR);
+ if (0 <= in_pos)
{
- off_t in_pos = lseek (input_desc, 0, SEEK_CUR);
- if (0 <= in_pos)
- exhausting = in_pos < lseek (STDOUT_FILENO, 0, SEEK_CUR);
- }
- if (exhausting)
- {
- error (0, 0, _("%s: input file is output file"), quotef (infile));
- ok = false;
- goto contin;
+ if (out_flags < -1)
+ out_flags = fcntl (STDOUT_FILENO, F_GETFL);
+ int whence = (0 <= out_flags && out_flags & O_APPEND
+ ? SEEK_END : SEEK_CUR);
+ if (in_pos < lseek (STDOUT_FILENO, 0, whence))
+ {
+ error (0, 0, _("%s: input file is output file"),
+ quotef (infile));
+ ok = false;
+ goto contin;
+ }
}
}
--
2.45.2