From a645ce6c04719ad616ecd3bd7a16cd14772d6a74 Mon Sep 17 00:00:00 2001 From: Pádraig Brady Date: Wed, 1 Jul 2015 22:37:26 +0100 Subject: wc: fix reading of /proc files on aarch64 tests/misc/wc-proc.sh fails when the page size is 64K * src/wc.c (wc): The lseek adjustment should be based on st_blksize, rather than on the internal buffer size. This is significant on aarch64 where st_blksize in /proc is the 64K (the page size) and thus larger than the internal buffer. * src/split.c (main): Even though the similar processing is done on the internal buffer size, that's based on st_blksize and so fine in this regard. Add an assert to enforce this. Avoid this path for the undocumented ---io-blksize option. --- src/split.c | 7 +++++-- src/wc.c | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/split.c b/src/split.c index b6fe2ddef..35f2629ae 100644 --- a/src/split.c +++ b/src/split.c @@ -1493,7 +1493,9 @@ main (int argc, char **argv) if (fstat (STDIN_FILENO, &in_stat_buf) != 0) error (EXIT_FAILURE, errno, "%s", infile); - if (in_blk_size == 0) + + bool specified_buf_size = !! in_blk_size; + if (! specified_buf_size) in_blk_size = io_blksize (in_stat_buf); void *b = xmalloc (in_blk_size + 1 + page_size - 1); @@ -1505,8 +1507,9 @@ main (int argc, char **argv) off_t input_offset = lseek (STDIN_FILENO, 0, SEEK_CUR); if (0 <= input_offset) { - if (usable_st_size (&in_stat_buf)) + if (usable_st_size (&in_stat_buf) && ! specified_buf_size) { + assert (ST_BLKSIZE (in_stat_buf) <= in_blk_size); file_size = input_file_size (STDIN_FILENO, in_stat_buf.st_size, buf, in_blk_size); if (file_size < in_blk_size) diff --git a/src/wc.c b/src/wc.c index eb7b5b69a..9fbaee7bc 100644 --- a/src/wc.c +++ b/src/wc.c @@ -36,6 +36,7 @@ #include "quotearg.h" #include "readtokens0.h" #include "safe-read.h" +#include "stat-size.h" #include "xfreopen.h" #if !defined iswspace && !HAVE_ISWSPACE @@ -238,14 +239,14 @@ wc (int fd, char const *file_x, struct fstatus *fstatus, off_t current_pos) if (0 < fstatus->failed) fstatus->failed = fstat (fd, &fstatus->st); - /* For sized files, seek to one buffer before EOF rather than to EOF. + /* For sized files, seek to one st_blksize before EOF rather than to EOF. This works better for files in proc-like file systems where the size is only approximate. */ if (! fstatus->failed && usable_st_size (&fstatus->st) && 0 <= fstatus->st.st_size) { size_t end_pos = fstatus->st.st_size; - off_t hi_pos = end_pos - end_pos % BUFFER_SIZE; + off_t hi_pos = end_pos - end_pos % (ST_BLKSIZE (fstatus->st) + 1); if (current_pos < 0) current_pos = lseek (fd, 0, SEEK_CUR); if (0 <= current_pos && current_pos < hi_pos -- cgit v1.2.3-54-g00ecf