Count words. FILE_X is the name of the file (or null for standard input) that is open on descriptor FD. *FSTATUS is its status. Return true if successful. */
| 369 | input) that is open on descriptor FD. *FSTATUS is its status. |
| 370 | Return true if successful. */ |
| 371 | static bool |
| 372 | wc (int fd, char const *file_x, struct fstatus *fstatus) |
| 373 | { |
| 374 | int err = 0; |
| 375 | char buf[IO_BUFSIZE + 1]; |
| 376 | intmax_t lines, words, chars, bytes, linelength; |
| 377 | bool count_bytes, count_chars, count_complicated; |
| 378 | char const *file = file_x ? file_x : _("standard input"); |
| 379 | |
| 380 | lines = words = chars = bytes = linelength = 0; |
| 381 | |
| 382 | /* If in the current locale, chars are equivalent to bytes, we prefer |
| 383 | counting bytes, because that's easier. */ |
| 384 | if (MB_CUR_MAX > 1) |
| 385 | { |
| 386 | count_bytes = print_bytes; |
| 387 | count_chars = print_chars; |
| 388 | } |
| 389 | else |
| 390 | { |
| 391 | count_bytes = print_bytes || print_chars; |
| 392 | count_chars = false; |
| 393 | } |
| 394 | count_complicated = print_words || print_linelength; |
| 395 | |
| 396 | /* Advise the kernel of our access pattern only if we will read(). */ |
| 397 | if (!count_bytes || count_chars || print_lines || count_complicated) |
| 398 | fdadvise (fd, 0, 0, FADVISE_SEQUENTIAL); |
| 399 | |
| 400 | /* When counting only bytes, save some line- and word-counting |
| 401 | overhead. If FD is a 'regular' Unix file, using lseek is enough |
| 402 | to get its 'size' in bytes. Otherwise, read blocks of IO_BUFSIZE |
| 403 | bytes at a time until EOF. Note that the 'size' (number of bytes) |
| 404 | that wc reports is smaller than stats.st_size when the file is not |
| 405 | positioned at its beginning. That's why the lseek calls below are |
| 406 | necessary. For example the command |
| 407 | '(dd ibs=99k skip=1 count=0; ./wc -c) < /etc/group' |
| 408 | should make wc report '0' bytes. */ |
| 409 | |
| 410 | if (count_bytes && !count_chars && !print_lines && !count_complicated) |
| 411 | { |
| 412 | bool skip_read = false; |
| 413 | |
| 414 | if (0 < fstatus->failed) |
| 415 | fstatus->failed = fstat (fd, &fstatus->st); |
| 416 | |
| 417 | /* For sized files, seek to one st_blksize before EOF rather than to EOF. |
| 418 | This works better for files in proc-like file systems where |
| 419 | the size is only approximate. */ |
| 420 | if (! fstatus->failed && usable_st_size (&fstatus->st) |
| 421 | && 0 <= fstatus->st.st_size) |
| 422 | { |
| 423 | off_t end_pos = fstatus->st.st_size; |
| 424 | off_t current_pos = lseek (fd, 0, SEEK_CUR); |
| 425 | if (current_pos < 0) |
| 426 | ; |
| 427 | else if (end_pos % page_size) |
| 428 | { |
no test coverage detected