summaryrefslogtreecommitdiff
path: root/src/od.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2014-10-07 16:46:08 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2014-10-07 16:47:37 -0700
commit2662702b9e8643f62c670bbf2fa94b1be1ccf9af (patch)
treec82775c20abc304fa4f187218830dc3aa2f7e481 /src/od.c
parentb020002b4bfae55d5bbcf66bd7ce787a4e6da689 (diff)
downloadcoreutils-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.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/src/od.c b/src/od.c
index 18b16836d..7ac663ad4 100644
--- a/src/od.c
+++ b/src/od.c
@@ -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;
}
}
}