From 7386c291be8e2de115f2e161886e872429edadd7 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 14 Feb 2025 13:10:02 -0800 Subject: =?UTF-8?q?cat:=20fix=20plain=20=E2=80=98cat=E2=80=99=20bug?= 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 . Also, don’t report an error if the seek position is at or after EOF, even if O_APPEND is set. --- src/cat.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/cat.c') diff --git a/src/cat.c b/src/cat.c index 274f844..c022103 100644 --- a/src/cat.c +++ b/src/cat.c @@ -646,9 +646,15 @@ idx_t outsize = io_blksize (stat_buf); /* Device, I-node number and lazily-acquired flags of the output. */ - dev_t out_dev = stat_buf.st_dev; - ino_t out_ino = stat_buf.st_ino; + dev_t out_dev; + ino_t out_ino; int out_flags = -2; + bool have_out_dev = ! (S_TYPEISSHM (&stat_buf) || S_TYPEISTMO (&stat_buf)); + if (have_out_dev) + { + out_dev = stat_buf.st_dev; + out_ino = stat_buf.st_ino; + } /* True if the output is a regular file. */ bool out_isreg = S_ISREG (stat_buf.st_mode) != 0; @@ -706,22 +712,25 @@ output device. It's better to catch this error earlier rather than later. */ - if (stat_buf.st_dev == out_dev && stat_buf.st_ino == out_ino) + if (! (S_ISFIFO (stat_buf.st_mode) || S_ISSOCK (stat_buf.st_mode) + || S_TYPEISSHM (&stat_buf) || S_TYPEISTMO (&stat_buf)) + && 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) - exhausting = in_pos < lseek (STDOUT_FILENO, 0, SEEK_CUR); - } - if (exhausting) + off_t in_pos = lseek (input_desc, 0, SEEK_CUR); + if (0 <= in_pos) { - 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; + } } }