diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2014-10-07 16:46:08 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2014-10-07 16:47:37 -0700 |
commit | 2662702b9e8643f62c670bbf2fa94b1be1ccf9af (patch) | |
tree | c82775c20abc304fa4f187218830dc3aa2f7e481 /src/od.c | |
parent | b020002b4bfae55d5bbcf66bd7ce787a4e6da689 (diff) | |
download | coreutils-2662702b9e8643f62c670bbf2fa94b1be1ccf9af.tar.xz |
wc: don't miscount /sys and similar file systems
Fix similar problems in head, od, split, tac, and tail.
Reported by George Shuklin in: http://bugs.gnu.org/18621
* NEWS: Document this.
* src/head.c (elseek): Move up.
(elide_tail_bytes_pipe, elide_tail_lines_pipe): New arg
CURRENT_POS. All uses changed.
(elide_tail_bytes_file, elide_tail_lines_file):
New arg ST and remove arg SIZE. All uses changed.
* src/head.c (elide_tail_bytes_file):
* src/od.c (skip): Avoid optimization for /sys files, where
st_size is bogus and st_size == st_blksize.
Don't report error at EOF when not optimizing.
* src/head.c, src/od.c, src/tail.c: Include "stat-size.h".
* src/split.c (input_file_size): New function.
(bytes_split, lines_chunk_split, bytes_chunk_extract): New arg
INITIAL_READ. All uses changed. Use it to double-check st_size.
* src/tac.c (tac_seekable): New arg FILE_POS. All uses changed.
(copy_to_temp): Return size of temp file. All uses changed.
* src/tac.c (tac_seekable):
* src/tail.c (tail_bytes):
* src/wc.c (wc):
Don't trust st_size; double-check by reading.
* src/wc.c (wc): New arg CURRENT_POS. All uses changed.
* tests/local.mk (all_tests): Add tests/misc/wc-proc.sh,
tests/misc/od-j.sh, tests/tail-2/tail-c.sh.
* tests/misc/head-c.sh:
* tests/misc/tac-2-nonseekable.sh:
* tests/split/b-chunk.sh:
Add tests for problems with /proc and /sys files.
* tests/misc/od-j.sh, tests/misc/wc-proc.sh, tests/tail-2/tail-c.sh:
New files.
Diffstat (limited to 'src/od.c')
-rw-r--r-- | src/od.c | 23 |
1 files changed, 16 insertions, 7 deletions
@@ -27,6 +27,7 @@ #include "error.h" #include "ftoastr.h" #include "quote.h" +#include "stat-size.h" #include "xfreopen.h" #include "xprintf.h" #include "xstrtol.h" @@ -1034,9 +1035,11 @@ skip (uintmax_t n_skip) If the number of bytes left to skip is larger than the size of the current file, we can decrement n_skip and go on to the next file. Skip this optimization also - when st_size is 0, because some kernels report that - nonempty files in /proc have st_size == 0. */ - if (S_ISREG (file_stats.st_mode) && 0 < file_stats.st_size) + when st_size is no greater than the block size, because + some kernels report nonsense small file sizes for + proc-like file systems. */ + if (usable_st_size (&file_stats) + && ST_BLKSIZE (file_stats) < file_stats.st_size) { if ((uintmax_t) file_stats.st_size < n_skip) n_skip -= file_stats.st_size; @@ -1052,6 +1055,7 @@ skip (uintmax_t n_skip) } /* If it's not a regular file with nonnegative size, + or if it's so small that it might be in a proc-like file system, position the file pointer by reading. */ else @@ -1067,10 +1071,15 @@ skip (uintmax_t n_skip) n_skip -= n_bytes_read; if (n_bytes_read != n_bytes_to_read) { - in_errno = errno; - ok = false; - n_skip = 0; - break; + if (ferror (in_stream)) + { + in_errno = errno; + ok = false; + n_skip = 0; + break; + } + if (feof (in_stream)) + break; } } } |