summaryrefslogtreecommitdiff
path: root/src/tail.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/tail.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/tail.c')
-rw-r--r--src/tail.c43
1 files changed, 17 insertions, 26 deletions
diff --git a/src/tail.c b/src/tail.c
index f5d258517..4c5f943c7 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -40,6 +40,7 @@
#include "posixver.h"
#include "quote.h"
#include "safe-read.h"
+#include "stat-size.h"
#include "stat-time.h"
#include "xfreopen.h"
#include "xnanosleep.h"
@@ -1665,40 +1666,30 @@ tail_bytes (const char *pretty_filename, int fd, uintmax_t n_bytes,
if (t)
return t < 0;
}
- *read_pos += dump_remainder (pretty_filename, fd, COPY_TO_EOF);
+ n_bytes = COPY_TO_EOF;
}
else
{
- if ( ! presume_input_pipe
- && S_ISREG (stats.st_mode) && n_bytes <= OFF_T_MAX)
+ off_t end_pos = ((! presume_input_pipe && usable_st_size (&stats)
+ && n_bytes <= OFF_T_MAX)
+ ? stats.st_size : -1);
+ if (end_pos <= ST_BLKSIZE (stats))
+ return pipe_bytes (pretty_filename, fd, n_bytes, read_pos);
+ off_t current_pos = xlseek (fd, 0, SEEK_CUR, pretty_filename);
+ if (current_pos < end_pos)
{
- off_t current_pos = xlseek (fd, 0, SEEK_CUR, pretty_filename);
- off_t end_pos = xlseek (fd, 0, SEEK_END, pretty_filename);
- off_t diff = end_pos - current_pos;
- /* Be careful here. The current position may actually be
- beyond the end of the file. */
- off_t bytes_remaining = diff < 0 ? 0 : diff;
- off_t nb = n_bytes;
-
- if (bytes_remaining <= nb)
- {
- /* From the current position to end of file, there are no
- more bytes than have been requested. So reposition the
- file pointer to the incoming current position and print
- everything after that. */
- *read_pos = xlseek (fd, current_pos, SEEK_SET, pretty_filename);
- }
- else
+ off_t bytes_remaining = end_pos - current_pos;
+
+ if (n_bytes < bytes_remaining)
{
- /* There are more bytes remaining than were requested.
- Back up. */
- *read_pos = xlseek (fd, -nb, SEEK_END, pretty_filename);
+ current_pos = end_pos - n_bytes;
+ xlseek (fd, current_pos, SEEK_SET, pretty_filename);
}
- *read_pos += dump_remainder (pretty_filename, fd, n_bytes);
}
- else
- return pipe_bytes (pretty_filename, fd, n_bytes, read_pos);
+ *read_pos = current_pos;
}
+
+ *read_pos += dump_remainder (pretty_filename, fd, n_bytes);
return true;
}