]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cut: promptly diagnose write errors
authorPádraig Brady <P@draigBrady.com>
Sat, 15 Jul 2023 20:23:55 +0000 (21:23 +0100)
committerPádraig Brady <P@draigBrady.com>
Mon, 17 Jul 2023 10:28:36 +0000 (11:28 +0100)
* src/cut.c (cut_bytes): Diagnose errors from fwrite() and putchar().
(cut_fields): Likewise.
* tests/misc/write-errors.sh: Enable the test for cut,
and augment to cover both cut_bytes() and cut_fields().
* NEWS: Mention the improvement.

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

diff --git a/NEWS b/NEWS
index dc5d21d9b508f26c0910a82780c06b2a694cbd86..8d15f27382918e486b8fa2eb506708ee043a5509 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -62,8 +62,8 @@ GNU coreutils NEWS                                    -*- outline -*-
   irrespective of which kernel version coreutils is built against,
   reinstating that behaviour from coreutils-9.0.
 
-  od and uniq will now exit immediately upon receiving a write error, which is
-  significant when reading large / unbounded inputs.
+  cut, od, and uniq 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 12dfd2299f847ef23e21fdfff9a83b410eb1f51c..476df0943b203e3c19098f9c51dec76d58cd1c27 100644 (file)
--- a/src/cut.c
+++ b/src/cut.c
@@ -232,7 +232,8 @@ cut_bytes (FILE *stream)
 
       if (c == line_delim)
         {
-          putchar (c);
+          if (putchar (c) < 0)
+            write_error ();
           byte_idx = 0;
           print_delimiter = false;
           current_rp = frp;
@@ -252,13 +253,16 @@ cut_bytes (FILE *stream)
                 {
                   if (print_delimiter && is_range_start_index (byte_idx))
                     {
-                      fwrite (output_delimiter_string, sizeof (char),
-                              output_delimiter_length, stdout);
+                      if (fwrite (output_delimiter_string, sizeof (char),
+                                  output_delimiter_length, stdout)
+                          != output_delimiter_length)
+                        write_error ();
                     }
                   print_delimiter = true;
                 }
 
-              putchar (c);
+              if (putchar (c) < 0)
+                write_error ();
             }
         }
     }
@@ -325,7 +329,9 @@ cut_fields (FILE *stream)
                 }
               else
                 {
-                  fwrite (field_1_buffer, sizeof (char), n_bytes, stdout);
+                  if (fwrite (field_1_buffer, sizeof (char), n_bytes, stdout)
+                      != n_bytes)
+                    write_error ();
                   /* Make sure the output line is newline terminated.  */
                   if (field_1_buffer[n_bytes - 1] != line_delim)
                     putchar (line_delim);
@@ -336,7 +342,9 @@ cut_fields (FILE *stream)
           if (print_kth (1))
             {
               /* Print the field, but not the trailing delimiter.  */
-              fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout);
+              if (fwrite (field_1_buffer, sizeof (char), n_bytes - 1, stdout)
+                  != n_bytes - 1)
+                write_error ();
 
               /* With -d$'\n' don't treat the last '\n' as a delimiter.  */
               if (delim == line_delim)
@@ -360,14 +368,17 @@ cut_fields (FILE *stream)
         {
           if (found_any_selected_field)
             {
-              fwrite (output_delimiter_string, sizeof (char),
-                      output_delimiter_length, stdout);
+              if (fwrite (output_delimiter_string, sizeof (char),
+                          output_delimiter_length, stdout)
+                  != output_delimiter_length)
+                write_error ();
             }
           found_any_selected_field = true;
 
           while ((c = getc (stream)) != delim && c != line_delim && c != EOF)
             {
-              putchar (c);
+              if (putchar (c) < 0)
+                write_error ();
               prev_c = c;
             }
         }
@@ -398,7 +409,8 @@ cut_fields (FILE *stream)
             {
               if (c == line_delim || prev_c != line_delim
                   || delim == line_delim)
-                putchar (line_delim);
+                if (putchar (line_delim) < 0)
+                  write_error ();
             }
           if (c == EOF)
             break;
index 20942e06856aa47104cbdc7a9e0b4706a4cbffcb..e217c5512b62dd3fae32e247fa07af03b1d2fc3e 100755 (executable)
@@ -28,7 +28,8 @@ fi
 echo "\
 cat /dev/zero
 # TODO: comm -z /dev/zero /dev/zero
-# TODO: cut -z -c1- /dev/zero
+cut -z -c1- /dev/zero
+cut -z -f1- /dev/zero
 dd if=/dev/zero
 expand /dev/zero
 factor --version; yes 1 | factor