]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
od: promptly diagnose write errors
authorPádraig Brady <P@draigBrady.com>
Tue, 11 Jul 2023 11:46:50 +0000 (12:46 +0100)
committerPádraig Brady <P@draigBrady.com>
Mon, 17 Jul 2023 10:28:36 +0000 (11:28 +0100)
* src/od.c (dump): Check for write errors after each block written,
to exit early even with large / unbounded inputs.
* tests/misc/write-errors.sh: enable od check.
* NEWS: Mention the improvement.
Fixes https://bugs.gnu.org/64540

NEWS
src/od.c
tests/misc/write-errors.sh

diff --git a/NEWS b/NEWS
index 35ae02a8eb3fb61b5f682e2e90e9b3cb4e339d71..892db27b8d0e3df4b7567e993b759ce132069bb1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -62,6 +62,9 @@ GNU coreutils NEWS                                    -*- outline -*-
   irrespective of which kernel version coreutils is built against,
   reinstating that behaviour from coreutils-9.0.
 
+  od will now exit immediately upon receiving a write error, which is
+  significant when reading large / unbounded inputs.
+
   split now uses more tuned access patterns for its potentially large input.
   This was seen to improve throughput by 5% when reading from SSD.
 
index 6b66ceb4fb63d2a4515e125612984f1231e41f9b..cde483c984710f510aa04296510fe8a1e18147fc 100644 (file)
--- a/src/od.c
+++ b/src/od.c
@@ -1380,7 +1380,7 @@ dump (void)
 
   if (limit_bytes_to_format)
     {
-      while (true)
+      while (ok)
         {
           size_t n_needed;
           if (current_offset >= end_offset)
@@ -1396,13 +1396,15 @@ dump (void)
           affirm (n_bytes_read == bytes_per_block);
           write_block (current_offset, n_bytes_read,
                        block[!idx], block[idx]);
+          if (ferror (stdout))
+            ok = false;
           current_offset += n_bytes_read;
           idx = !idx;
         }
     }
   else
     {
-      while (true)
+      while (ok)
         {
           ok &= read_block (bytes_per_block, block[idx], &n_bytes_read);
           if (n_bytes_read < bytes_per_block)
@@ -1410,6 +1412,8 @@ dump (void)
           affirm (n_bytes_read == bytes_per_block);
           write_block (current_offset, n_bytes_read,
                        block[!idx], block[idx]);
+          if (ferror (stdout))
+            ok = false;
           current_offset += n_bytes_read;
           idx = !idx;
         }
index a1ba2deb14b7326494a2a882cfe090dc1486acd4..31b6433d7bd6fc271614b9c417012249b7937b8b 100755 (executable)
@@ -38,7 +38,7 @@ head -z -n-1 /dev/zero
 # TODO: join -a 1 -z /dev/zero /dev/null
 # TODO: nl --version; yes | nl
 # TODO: numfmt --version; yes 1 | numfmt
-# TODO: od -v /dev/zero
+od -v /dev/zero
 paste /dev/zero
 # TODO: pr /dev/zero
 seq inf