diff --git a/NEWS b/NEWS index 4126b4028..01b3e4dff 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,10 @@ GNU coreutils NEWS -*- outline -*- in GB18030 locales, and word counts in UTF-8 locales. [bug introduced in coreutils-9.5] + 'wc -c' no longer miscounts bytes when stdin has a nonzero offset + into a seekable file whose size is a multiple of the page size. + [bug introduced in coreutils-8.24] + ** New Features 'env' and 'printenv' now support the --quoting-style option diff --git a/THANKS.in b/THANKS.in index 6a098897d..94669125b 100644 --- a/THANKS.in +++ b/THANKS.in @@ -577,6 +577,7 @@ Santiago Vila Doncel sanvila@unex.es Savochkin Andrey Vladimirovich saw@msu.ru Scott Harrison scott.gnu.2009@scottrix.co.uk Scott Lurndal slurn@griffin.engr.sgi.com +Scott Orme scott.orme@gmail.com Sébastien Maret smaret@umich.edu Sergei Steshenko sergstesh@yahoo.com Sergey Vlasov vsu@altlinux.org diff --git a/src/wc.c b/src/wc.c index 272a905f5..d0aab941d 100644 --- a/src/wc.c +++ b/src/wc.c @@ -428,7 +428,7 @@ wc (int fd, char const *file_x, struct fstatus *fstatus) ; else if (end_pos % page_size) { - /* We only need special handling of /proc and /sys files etc. + /* We need special handling of /proc and /sys files etc. only when they're a multiple of PAGE_SIZE. In the common case for files with st_size not a multiple of PAGE_SIZE, it's more efficient and accurate to use st_size. @@ -436,20 +436,25 @@ wc (int fd, char const *file_x, struct fstatus *fstatus) Be careful here. The current position may actually be beyond the end of the file. As in the example above. */ - bytes = end_pos < current_pos ? 0 : end_pos - current_pos; - if (bytes && 0 <= lseek (fd, bytes, SEEK_CUR)) - skip_read = true; - else - bytes = 0; + if (current_pos < end_pos) + { + bytes = end_pos - current_pos; + skip_read = true; + } } - else + else if (0 < end_pos) { - off_t hi_pos = (end_pos - - end_pos % (STP_BLKSIZE (&fstatus->st) + 1)); - if (0 <= current_pos && current_pos < hi_pos - && 0 <= lseek (fd, hi_pos, SEEK_CUR)) + off_t ep_1 = end_pos - 1; + off_t hi_pos = ep_1 - ep_1 % STP_BLKSIZE (&fstatus->st); + if (current_pos < hi_pos) bytes = hi_pos - current_pos; } + + if (0 < bytes && lseek (fd, bytes, SEEK_CUR) < 0) + { + bytes = 0; + skip_read = false; + } } if (! skip_read)