bug#81604: [PATCH] truncate: don't hang with FIFO --reference

Iván Ezequiel Rodriguez <[email protected]>
Newsgroups gmane.comp.gnu.core-utils.bugs
Message-ID <[email protected]>
When st_size is not usable, truncate opens the --reference operand and
uses lseek(SEEK_END) to obtain a size.  Opening a FIFO with O_RDONLY
blocks until a writer appears, so "truncate --reference=fifo file"
could hang indefinitely.  Use O_NONBLOCK, matching the existing open of
the output file and the approach taken in df.

Introduced by commit v8.16-49-g9d308df13.

* NEWS: Mention the fix.
* src/truncate.c (main): Open the reference with O_NONBLOCK.
* tests/truncate/truncate-fifo.sh: Also cover --reference=FIFO.

Signed-off-by: Iván Ezequiel Rodriguez <[email protected]>
---
 NEWS                            | 3 +++
 src/truncate.c                  | 3 ++-
 tests/truncate/truncate-fifo.sh | 8 ++++++++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/NEWS b/NEWS
index 67ffc1bf2..946627523 100644
--- a/NEWS
+++ b/NEWS
@@ -58,6 +58,9 @@ GNU coreutils NEWS                                    -*- outline -*-
   with an error.
   [This bug was present in "the beginning".]
 
+  'truncate --reference=R' no longer hangs when R is a FIFO.
+  [bug introduced in coreutils-8.17]
+
   'unexpand -t' no longer overflows a heap buffer, for tab values > SIZE_MAX/16,
   or with multi-byte blank characters longer than the tab value.
   [bugs introduced in coreutils-9.11]
diff --git a/src/truncate.c b/src/truncate.c
index 7119132e0..e6c20b70a 100644
--- a/src/truncate.c
+++ b/src/truncate.c
@@ -326,7 +326,8 @@ main (int argc, char **argv)
         file_size = sb.st_size;
       else
         {
-          int ref_fd = open (ref_file, O_RDONLY);
+          /* O_NONBLOCK so we do not hang forever on a FIFO with no writer.  */
+          int ref_fd = open (ref_file, O_RDONLY | O_NONBLOCK);
           if (0 <= ref_fd)
             {
               off_t file_end = lseek (ref_fd, 0, SEEK_END);
diff --git a/tests/truncate/truncate-fifo.sh b/tests/truncate/truncate-fifo.sh
index c456c76ff..9b8a40910 100755
--- a/tests/truncate/truncate-fifo.sh
+++ b/tests/truncate/truncate-fifo.sh
@@ -21,7 +21,15 @@ print_ver_ truncate
 
 mkfifo_or_skip_ fifo
 
+
+# Output FIFO must not hang.
 timeout 10 truncate -s0 fifo
 test "$?" = 124 && fail=1
 
+# Reference FIFO must not hang either.
+touch file || framework_failure_
+timeout 10 truncate --reference=fifo file 2>/dev/null
+test "$?" = 124 && fail=1
+
+
 Exit $fail
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.