1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-08-17 09:06:50 +02:00

maint: use clearerr on stdin when appropriate

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.
This commit is contained in:
Paul Eggert
2021-08-22 11:54:44 -07:00
parent 4d355e5270
commit 88846befff
14 changed files with 129 additions and 107 deletions
+4 -1
View 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;
+9 -10
View File
@@ -298,17 +298,16 @@ cksum (char const *file, bool print_name)
if (! cksum_fp (fp, file, &crc, &length))
return false;
if (ferror (fp))
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));
if (!STREQ (file, "-"))
fclose (fp);
return false;
}
if (!STREQ (file, "-") && fclose (fp) == EOF)
{
error (0, errno, "%s", quotef (file));
error (0, err, "%s", quotef (file));
return false;
}
+6 -6
View File
@@ -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;
+6 -6
View 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;
}
}
+31 -14
View File
@@ -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
+8 -8
View 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;
}
+15 -16
View File
@@ -631,17 +631,15 @@ digest_file (char const *filename, int *binary, unsigned char *bin_result,
#else
err = DIGEST_STREAM (fp, bin_result);
#endif
err = err ? errno : 0;
if (is_stdin)
clearerr (fp);
else if (fclose (fp) != 0 && !err)
err = errno;
if (err)
{
error (0, errno, "%s", quotef (filename));
if (fp != stdin)
fclose (fp);
return false;
}
if (!is_stdin && fclose (fp) != 0)
{
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;
}
+7 -7
View File
@@ -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;
+8 -9
View File
@@ -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;
}
+12 -14
View 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;
}
}
+10 -4
View File
@@ -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)
{
+3
View File
@@ -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;
}
+1 -2
View 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:
+9 -10
View File
@@ -120,17 +120,16 @@ bsd_sum_file (char const *file, int print_name)
checksum &= 0xffff; /* Keep it within bounds. */
}
if (ferror (fp))
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));
if (!is_stdin)
fclose (fp);
return false;
}
if (!is_stdin && fclose (fp) != 0)
{
error (0, errno, "%s", quotef (file));
error (0, err, "%s", quotef (file));
return false;
}