]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
maint: use clearerr on stdin when appropriate
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 22 Aug 2021 18:54:44 +0000 (11:54 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 22 Aug 2021 20:10:26 +0000 (13:10 -0700)
This is so that commands like ‘fmt - -’ read from stdin
both times, even when it is a tty.  Fix some other minor
issues that are related.
* src/blake2/b2sum.c (main):
* src/cksum.c (cksum):
* src/cut.c (cut_file):
* src/expand-common.c (next_file):
* src/fmt.c (fmt):
* src/fold.c (fold_file):
* src/md5sum.c (digest_file, digest_check):
* src/nl.c (nl_file):
* src/od.c (check_and_close):
* src/paste.c (paste_parallel, paste_serial):
* src/pr.c (close_file):
* src/sum.c (bsd_sum_file):
Use clearerr on stdin so that stdin can be read multiple times
even if it is a tty.  Do not assume that ferror preserves errno as
POSIX does not guarantee this.  Coalesce duplicate diagnostic
calls.
* src/blake2/b2sum.c (main):
* src/fmt.c (main, fmt):
Report read error, even if it's merely fclose failure.
* src/fmt.c: Include die.h.
(fmt): New arg FILE.  Close input (reporting error) if not stdin.
All callers changed.
* src/ptx.c (swallow_file_in_memory): Clear stdin's EOF flag.
* src/sort.c (xfclose): Remove unnecessary feof call.

14 files changed:
src/blake2/b2sum.c
src/cksum.c
src/cut.c
src/expand-common.c
src/fmt.c
src/fold.c
src/md5sum.c
src/nl.c
src/od.c
src/paste.c
src/pr.c
src/ptx.c
src/sort.c
src/sum.c

index 9f1108137a08e05377268528e6f27fd1e3bbd9c6..0a2387b393b0c4ed7cf692732b52612ef1fcd429 100644 (file)
@@ -388,7 +388,10 @@ int main( int argc, char **argv )
         printf( "  %s\n", argv[i] );
     }
 
-    if( f != stdin ) fclose( f );
+    if( f == stdin )
+      clearerr( f );
+    else if( fclose( f ) != 0 )
+      fprintf( stderr, "Could not close `%s': %s\n", argv[i], strerror( errno ) );
   }
 
   return 0;
index c3416f8668d69fa91abb9f85cb3e9ad43c942b50..3cc4296bca897155466749fd4266ff69ea714340 100644 (file)
@@ -298,17 +298,16 @@ cksum (char const *file, bool print_name)
   if (! cksum_fp (fp, file, &crc, &length))
     return false;
 
-  if (ferror (fp))
-    {
-      error (0, errno, "%s", quotef (file));
-      if (!STREQ (file, "-"))
-        fclose (fp);
-      return false;
-    }
-
-  if (!STREQ (file, "-") && fclose (fp) == EOF)
+  int err = errno;
+  if (!ferror (fp))
+    err = 0;
+  if (STREQ (file, "-"))
+    clearerr (fp);
+  else if (fclose (fp) != 0 && !err)
+    err = errno;
+  if (err)
     {
-      error (0, errno, "%s", quotef (file));
+      error (0, err, "%s", quotef (file));
       return false;
     }
 
index f4d44c2113ce250030d6459088df6ed14da8cf7a..cdf33d897a46d01138ebe18565c653224d2c0bdd 100644 (file)
--- a/src/cut.c
+++ b/src/cut.c
@@ -460,16 +460,16 @@ cut_file (char const *file)
 
   cut_stream (stream);
 
-  if (ferror (stream))
-    {
-      error (0, errno, "%s", quotef (file));
-      return false;
-    }
+  int err = errno;
+  if (!ferror (stream))
+    err = 0;
   if (STREQ (file, "-"))
     clearerr (stream);         /* Also clear EOF. */
   else if (fclose (stream) == EOF)
+    err = errno;
+  if (err)
     {
-      error (0, errno, "%s", quotef (file));
+      error (0, err, "%s", quotef (file));
       return false;
     }
   return true;
index 55df8dc0fd71e6e03e9ce986f11606cdabd89939..4deb7bd8a6de1332027c34f7e9f5a7bc91f2c311 100644 (file)
@@ -338,16 +338,16 @@ next_file (FILE *fp)
   if (fp)
     {
       assert (prev_file);
-      if (ferror (fp))
-        {
-          error (0, errno, "%s", quotef (prev_file));
-          exit_status = EXIT_FAILURE;
-        }
+      int err = errno;
+      if (!ferror (fp))
+        err = 0;
       if (STREQ (prev_file, "-"))
         clearerr (fp);         /* Also clear EOF.  */
       else if (fclose (fp) != 0)
+        err = errno;
+      if (err)
         {
-          error (0, errno, "%s", quotef (prev_file));
+          error (0, err, "%s", quotef (prev_file));
           exit_status = EXIT_FAILURE;
         }
     }
index ca9231b991203fe963c4c5de14b633a82951126d..bfccd9ba111e17efa1a3545bbca770fc2740b24d 100644 (file)
--- a/src/fmt.c
+++ b/src/fmt.c
@@ -28,6 +28,7 @@
 
 #include "system.h"
 #include "error.h"
+#include "die.h"
 #include "fadvise.h"
 #include "xdectoint.h"
 
@@ -151,7 +152,7 @@ struct Word
 /* Forward declarations.  */
 
 static void set_prefix (char *p);
-static void fmt (FILE *f);
+static bool fmt (FILE *f, char const *);
 static bool get_paragraph (FILE *f);
 static int get_line (FILE *f, int c);
 static int get_prefix (FILE *f);
@@ -412,28 +413,29 @@ main (int argc, char **argv)
       goal_width = max_width * (2 * (100 - LEEWAY) + 1) / 200;
     }
 
+  bool have_read_stdin = false;
+
   if (optind == argc)
-    fmt (stdin);
+    {
+      have_read_stdin = true;
+      ok = fmt (stdin, "-");
+    }
   else
     {
       for (; optind < argc; optind++)
         {
           char *file = argv[optind];
           if (STREQ (file, "-"))
-            fmt (stdin);
+            {
+              ok &= fmt (stdin, file);
+              have_read_stdin = true;
+            }
           else
             {
               FILE *in_stream;
               in_stream = fopen (file, "r");
               if (in_stream != NULL)
-                {
-                  fmt (in_stream);
-                  if (fclose (in_stream) == EOF)
-                    {
-                      error (0, errno, "%s", quotef (file));
-                      ok = false;
-                    }
-                }
+                ok &= fmt (in_stream, file);
               else
                 {
                   error (0, errno, _("cannot open %s for reading"),
@@ -444,6 +446,9 @@ main (int argc, char **argv)
         }
     }
 
+  if (have_read_stdin && fclose (stdin) != 0)
+    die (EXIT_FAILURE, errno, "%s", _("closing standard input"));
+
   return ok ? EXIT_SUCCESS : EXIT_FAILURE;
 }
 
@@ -470,10 +475,13 @@ set_prefix (char *p)
   prefix_length = s - p;
 }
 
-/* read file F and send formatted output to stdout.  */
+/* Read F and send formatted output to stdout.
+   Close F when done, unless F is stdin.  Diagnose input errors, using FILE.
+   If !F, assume F resulted from an fopen failure and diagnose that.
+   Return true if successful.  */
 
-static void
-fmt (FILE *f)
+static bool
+fmt (FILE *f, char const *file)
 {
   fadvise (f, FADVISE_SEQUENTIAL);
   tabs = false;
@@ -484,6 +492,15 @@ fmt (FILE *f)
       fmt_paragraph ();
       put_paragraph (word_limit);
     }
+
+  int err = ferror (f) ? 0 : -1;
+  if (f == stdin)
+    clearerr (f);
+  else if (fclose (f) != 0 && err < 0)
+    err = errno;
+  if (0 <= err)
+    error (0, err, err ? "%s" : _("read error"), quotef (file));
+  return err < 0;
 }
 
 /* Set the global variable 'other_indent' according to SAME_PARAGRAPH
index ae33dd36895c8c3d020e80039622d3499d2d2f38..94a6d378eb6e01bcce69a37ce110f2fc30ea7fb1 100644 (file)
@@ -216,20 +216,20 @@ fold_file (char const *filename, size_t width)
     }
 
   saved_errno = errno;
+  if (!ferror (istream))
+    saved_errno = 0;
 
   if (offset_out)
     fwrite (line_out, sizeof (char), (size_t) offset_out, stdout);
 
-  if (ferror (istream))
+  if (STREQ (filename, "-"))
+    clearerr (istream);
+  else if (fclose (istream) != 0 && !saved_errno)
+    saved_errno = errno;
+
+  if (saved_errno)
     {
       error (0, saved_errno, "%s", quotef (filename));
-      if (!STREQ (filename, "-"))
-        fclose (istream);
-      return false;
-    }
-  if (!STREQ (filename, "-") && fclose (istream) == EOF)
-    {
-      error (0, errno, "%s", quotef (filename));
       return false;
     }
 
index cbfdc3ab228aea4c95e13c9ab87eace2b89fc8f9..e2071cfd2998ec90d28089a96b248c1b3619caaf 100644 (file)
@@ -631,17 +631,15 @@ digest_file (char const *filename, int *binary, unsigned char *bin_result,
 #else
   err = DIGEST_STREAM (fp, bin_result);
 #endif
-  if (err)
-    {
-      error (0, errno, "%s", quotef (filename));
-      if (fp != stdin)
-        fclose (fp);
-      return false;
-    }
+  err = err ? errno : 0;
+  if (is_stdin)
+    clearerr (fp);
+  else if (fclose (fp) != 0 && !err)
+    err = errno;
 
-  if (!is_stdin && fclose (fp) != 0)
+  if (err)
     {
-      error (0, errno, "%s", quotef (filename));
+      error (0, err, "%s", quotef (filename));
       return false;
     }
 
@@ -798,15 +796,16 @@ digest_check (char const *checkfile_name)
 
   free (line);
 
-  if (ferror (checkfile_stream))
-    {
-      error (0, 0, _("%s: read error"), quotef (checkfile_name));
-      return false;
-    }
+  int err = ferror (checkfile_stream) ? 0 : -1;
+  if (is_stdin)
+    clearerr (checkfile_stream);
+  else if (fclose (checkfile_stream) != 0 && err < 0)
+    err = errno;
 
-  if (!is_stdin && fclose (checkfile_stream) != 0)
+  if (0 <= err)
     {
-      error (0, errno, "%s", quotef (checkfile_name));
+      error (0, err, err ? "%s" : _("%s: read error"),
+             quotef (checkfile_name));
       return false;
     }
 
index f3ba46c9bb44c78c0e2b66e5ba01b9b8e52f986a..7a13bcb97e02262d1c72433e2275eb68e59d9a6a 100644 (file)
--- a/src/nl.c
+++ b/src/nl.c
@@ -457,16 +457,16 @@ nl_file (char const *file)
 
   process_file (stream);
 
-  if (ferror (stream))
-    {
-      error (0, errno, "%s", quotef (file));
-      return false;
-    }
+  int err = errno;
+  if (!ferror (stream))
+    err = 0;
   if (STREQ (file, "-"))
     clearerr (stream);         /* Also clear EOF. */
-  else if (fclose (stream) == EOF)
+  else if (fclose (stream) != 0 && !err)
+    err = errno;
+  if (err)
     {
-      error (0, errno, "%s", quotef (file));
+      error (0, err, "%s", quotef (file));
       return false;
     }
   return true;
index f04e0ccb70b995f04468ff3d907cf7de88fd9e45..111c94935c2cd9d61296149bb270364178eff008 100644 (file)
--- a/src/od.c
+++ b/src/od.c
@@ -949,16 +949,15 @@ check_and_close (int in_errno)
 
   if (in_stream != NULL)
     {
-      if (ferror (in_stream))
+      if (!ferror (in_stream))
+        in_errno = 0;
+      if (STREQ (file_list[-1], "-"))
+        clearerr (in_stream);
+      else if (fclose (in_stream) != 0 && !in_errno)
+        in_errno = errno;
+      if (in_errno)
         {
-          error (0, in_errno, _("%s: read error"), quotef (input_filename));
-          if (! STREQ (file_list[-1], "-"))
-            fclose (in_stream);
-          ok = false;
-        }
-      else if (! STREQ (file_list[-1], "-") && fclose (in_stream) != 0)
-        {
-          error (0, errno, "%s", quotef (input_filename));
+          error (0, in_errno, "%s", quotef (input_filename));
           ok = false;
         }
 
index 48229acc5c0a2be475f36dcfc30816c998bbba51..f43fb56c2d7ac10c40774ea8d08e560d50469ba8 100644 (file)
@@ -266,16 +266,15 @@ paste_parallel (size_t nfiles, char **fnamptr)
                  If an EOF or error, close the file.  */
               if (fileptr[i])
                 {
-                  if (ferror (fileptr[i]))
-                    {
-                      error (0, err, "%s", quotef (fnamptr[i]));
-                      ok = false;
-                    }
+                  if (!ferror (fileptr[i]))
+                    err = 0;
                   if (fileptr[i] == stdin)
                     clearerr (fileptr[i]); /* Also clear EOF. */
-                  else if (fclose (fileptr[i]) == EOF)
+                  else if (fclose (fileptr[i]) == EOF && !err)
+                    err = errno;
+                  if (err)
                     {
-                      error (0, errno, "%s", quotef (fnamptr[i]));
+                      error (0, err, "%s", quotef (fnamptr[i]));
                       ok = false;
                     }
 
@@ -410,16 +409,15 @@ paste_serial (size_t nfiles, char **fnamptr)
       if (charold != line_delim)
         xputchar (line_delim);
 
-      if (ferror (fileptr))
-        {
-          error (0, saved_errno, "%s", quotef (*fnamptr));
-          ok = false;
-        }
+      if (!ferror (fileptr))
+        saved_errno = 0;
       if (is_stdin)
         clearerr (fileptr);    /* Also clear EOF. */
-      else if (fclose (fileptr) == EOF)
+      else if (fclose (fileptr) != 0 && !saved_errno)
+        saved_errno = errno;
+      if (saved_errno)
         {
-          error (0, errno, "%s", quotef (*fnamptr));
+          error (0, saved_errno, "%s", quotef (*fnamptr));
           ok = false;
         }
     }
index da57955544e4e78501d9863646f425bbe259125d..8f84d0f594d494f3dac64b2ce6853129f90029ae 100644 (file)
--- a/src/pr.c
+++ b/src/pr.c
@@ -1506,10 +1506,16 @@ close_file (COLUMN *p)
 
   if (p->status == CLOSED)
     return;
-  if (ferror (p->fp))
-    die (EXIT_FAILURE, errno, "%s", quotef (p->name));
-  if (fileno (p->fp) != STDIN_FILENO && fclose (p->fp) != 0)
-    die (EXIT_FAILURE, errno, "%s", quotef (p->name));
+
+  int err = errno;
+  if (!ferror (p->fp))
+    err = 0;
+  if (fileno (p->fp) == STDIN_FILENO)
+    clearerr (p->fp);
+  else if (fclose (p->fp) != 0 && !err)
+    err = errno;
+  if (err)
+    die (EXIT_FAILURE, err, "%s", quotef (p->name));
 
   if (!parallel_files)
     {
index 85c26aa1d720468356cca4d8d02217d91282adc4..43075c840a73dbf41adb249ab5150afe8945ff4e 100644 (file)
--- a/src/ptx.c
+++ b/src/ptx.c
@@ -526,6 +526,9 @@ swallow_file_in_memory (char const *file_name, BLOCK *block)
   if (!block->start)
     die (EXIT_FAILURE, errno, "%s", quotef (using_stdin ? "-" : file_name));
 
+  if (using_stdin)
+    clearerr (stdin);
+
   block->end = block->start + used_length;
 }
 
index cba809c33f6423dc09dc6a55afba0eacdb6f55b6..5f4c817ded7f6b209ea979d15c124610d0b9fc87 100644 (file)
@@ -1001,8 +1001,7 @@ xfclose (FILE *fp, char const *file)
     {
     case STDIN_FILENO:
       /* Allow reading stdin from tty more than once.  */
-      if (feof (fp))
-        clearerr (fp);
+      clearerr (fp);
       break;
 
     case STDOUT_FILENO:
index f9641dbb1dbadd43f06e7cd2aac4b3acb28fb055..c17af3f6b3ddcbc857a7b47379cfd7896017e654 100644 (file)
--- a/src/sum.c
+++ b/src/sum.c
@@ -120,17 +120,16 @@ bsd_sum_file (char const *file, int print_name)
       checksum &= 0xffff;      /* Keep it within bounds. */
     }
 
-  if (ferror (fp))
-    {
-      error (0, errno, "%s", quotef (file));
-      if (!is_stdin)
-        fclose (fp);
-      return false;
-    }
-
-  if (!is_stdin && fclose (fp) != 0)
+  int err = errno;
+  if (!ferror (fp))
+    err = 0;
+  if (is_stdin)
+    clearerr (fp);
+  else if (fclose (fp) != 0 && !err)
+    err = errno;
+  if (err)
     {
-      error (0, errno, "%s", quotef (file));
+      error (0, err, "%s", quotef (file));
       return false;
     }