diff options
author | Assaf Gordon <assafgordon@gmail.com> | 2016-04-17 02:28:13 -0400 |
---|---|---|
committer | Assaf Gordon <assafgordon@gmail.com> | 2016-04-24 18:19:50 -0400 |
commit | c92585b10b29ce2c31c69cea52e69ef053c9679f (patch) | |
tree | ff733fa4b684abfa59dd5a7b3d56f411c9027fee /src | |
parent | 8c8163838aa5589f5dfe2c94dcc48f0ab443fd35 (diff) | |
download | coreutils-c92585b10b29ce2c31c69cea52e69ef053c9679f.tar.xz |
seq: detect and report I/O errors immediately
Ensure I/O errors are detected (and terminate seq), preventing seq
from infloop (or running for long time with a large
range) upon write errors or ignored SIGPIPE. Examples:
seq 1 inf > /dev/full (seq_fast)
seq 1.1 0.1 inf >/dev/full (print_numbers)
* src/seq.c (io_error): A new function to diagnose appropriate
stdio errors and exit the program with failure status.
(seq_fast, print_numbers): Explicitly check for write errors
and terminate the program with diagnostic.
* tests/misc/seq-io-errors.sh: Test error detection with /dev/full.
* tests/misc/seq-epipe.sh: Test error detection with broken pipes.
* tests/local.mk: Add new tests.
* NEWS: Mention the fix.
Diffstat (limited to 'src')
-rw-r--r-- | src/seq.c | 24 |
1 files changed, 19 insertions, 5 deletions
@@ -278,6 +278,15 @@ long_double_format (char const *fmt, struct layout *layout) } } +static void ATTRIBUTE_NORETURN +io_error (void) +{ + /* FIXME: consider option to silently ignore errno=EPIPE */ + error (0, errno, _("standard output")); + clearerr (stdout); + exit (EXIT_FAILURE); +} + /* Actually print the sequence of numbers in the specified range, with the given or default stepping and format. */ @@ -295,7 +304,8 @@ print_numbers (char const *fmt, struct layout layout, for (i = 1; ; i++) { long double x0 = x; - printf (fmt, x); + if (printf (fmt, x) < 0) + io_error (); if (out_of_range) break; x = first + i * step; @@ -336,10 +346,12 @@ print_numbers (char const *fmt, struct layout layout, break; } - fputs (separator, stdout); + if (fputs (separator, stdout) == EOF) + io_error (); } - fputs (terminator, stdout); + if (fputs (terminator, stdout) == EOF) + io_error (); } } @@ -506,14 +518,16 @@ seq_fast (char const *a, char const *b) output buffer so far, and reset to start of buffer. */ if (buf_end - (p_len + 1) < bufp) { - fwrite (buf, bufp - buf, 1, stdout); + if (fwrite (buf, bufp - buf, 1, stdout) != 1) + io_error (); bufp = buf; } } /* Write any remaining buffered output, and the terminator. */ *bufp++ = *terminator; - fwrite (buf, bufp - buf, 1, stdout); + if (fwrite (buf, bufp - buf, 1, stdout) != 1) + io_error (); IF_LINT (free (buf)); } |