diff options
author | Jim Meyering <jim@meyering.net> | 1995-02-09 17:05:43 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 1995-02-09 17:05:43 +0000 |
commit | 05d1bec3e5a34449ffde7f71648084069b1319f5 (patch) | |
tree | 3b561f642ae9a632ad8fe11bf0eba17cf362ce3d | |
parent | b968f43e9508fc16e225b749ce3368071630065a (diff) | |
download | coreutils-05d1bec3e5a34449ffde7f71648084069b1319f5.tar.xz |
(wc): Don't overcount the number of bytes when reading from
a regular file on stdin with file pointer not at BOF. From Karl Heuer.
-rw-r--r-- | src/wc.c | 20 |
1 files changed, 15 insertions, 5 deletions
@@ -201,19 +201,29 @@ wc (fd, file) register int bytes_read; register int in_word = 0; register unsigned long lines, words, chars; - struct stat stats; lines = words = chars = 0; /* When counting only bytes, save some line- and word-counting - overhead. If FD is a `regular' Unix file, using fstat is enough + overhead. If FD is a `regular' Unix file, using lseek is enough to get its size in bytes. Otherwise, read blocks of BUFFER_SIZE - bytes at a time until EOF. */ + bytes at a time until EOF. + + NOTE: using fstat and stats.st_size (and omitting the lseek calls) + over counts when the file is not positioned at the beginning. + For example the command `(dd skip=9999; wc -c) < /etc/group' + should make wc report `0' bytes. */ + if (print_chars && !print_words && !print_lines) { - if (fstat (fd, &stats) == 0 && S_ISREG (stats.st_mode)) + struct stat stats; + off_t current_pos, end_pos; + + if (fstat (fd, &stats) == 0 && S_ISREG (stats.st_mode) + && (current_pos = lseek (fd, (off_t)0, SEEK_CUR)) != -1 + && (end_pos = lseek (fd, (off_t)0, SEEK_END)) != -1) { - chars = stats.st_size; + chars = end_pos - current_pos; } else { |