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:
+4
-1
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user