diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-09 22:06:56 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-09 22:06:56 +0200 |
| commit | a43df64eec6d02812b40d7e01edbeb47539866db (patch) | |
| tree | 591a7f6a995901fbbc8d4f893c48b565d6cac888 | |
| parent | 0568b6e45aa59c72815378134715232fd11d9100 (diff) | |
| download | busybox-w32-a43df64eec6d02812b40d7e01edbeb47539866db.tar.gz busybox-w32-a43df64eec6d02812b40d7e01edbeb47539866db.tar.bz2 busybox-w32-a43df64eec6d02812b40d7e01edbeb47539866db.zip | |
tail: fix "tail +N file_shorter_than_N"
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | coreutils/tail.c | 16 | ||||
| -rwxr-xr-x | testsuite/tail.tests | 17 |
2 files changed, 27 insertions, 6 deletions
diff --git a/coreutils/tail.c b/coreutils/tail.c index ef1326c83..5f98bff82 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c | |||
| @@ -50,12 +50,12 @@ static ssize_t tail_read(int fd, char *buf, size_t count) | |||
| 50 | off_t current; | 50 | off_t current; |
| 51 | struct stat sbuf; | 51 | struct stat sbuf; |
| 52 | 52 | ||
| 53 | /* (A good comment is missing here) */ | ||
| 54 | current = lseek(fd, 0, SEEK_CUR); | ||
| 55 | /* /proc files report zero st_size, don't lseek them. */ | 53 | /* /proc files report zero st_size, don't lseek them. */ |
| 56 | if (fstat(fd, &sbuf) == 0 && sbuf.st_size) | 54 | if (fstat(fd, &sbuf) == 0 && sbuf.st_size) { |
| 55 | current = lseek(fd, 0, SEEK_CUR); | ||
| 57 | if (sbuf.st_size < current) | 56 | if (sbuf.st_size < current) |
| 58 | lseek(fd, 0, SEEK_SET); | 57 | lseek(fd, 0, SEEK_SET); |
| 58 | } | ||
| 59 | 59 | ||
| 60 | r = full_read(fd, buf, count); | 60 | r = full_read(fd, buf, count); |
| 61 | if (r < 0) { | 61 | if (r < 0) { |
| @@ -119,10 +119,11 @@ int tail_main(int argc, char **argv) | |||
| 119 | #if ENABLE_FEATURE_FANCY_TAIL | 119 | #if ENABLE_FEATURE_FANCY_TAIL |
| 120 | /* q: make it impossible for nfiles to be > header_threshhold */ | 120 | /* q: make it impossible for nfiles to be > header_threshhold */ |
| 121 | if (opt & 0x8) header_threshhold = UINT_MAX; // -q | 121 | if (opt & 0x8) header_threshhold = UINT_MAX; // -q |
| 122 | //if (opt & 0x10) // -s | ||
| 122 | if (opt & 0x20) header_threshhold = 0; // -v | 123 | if (opt & 0x20) header_threshhold = 0; // -v |
| 123 | #define FOLLOW_RETRY (opt & 0x40) | 124 | # define FOLLOW_RETRY (opt & 0x40) |
| 124 | #else | 125 | #else |
| 125 | #define FOLLOW_RETRY 0 | 126 | # define FOLLOW_RETRY 0 |
| 126 | #endif | 127 | #endif |
| 127 | argc -= optind; | 128 | argc -= optind; |
| 128 | argv += optind; | 129 | argv += optind; |
| @@ -189,7 +190,7 @@ int tail_main(int argc, char **argv) | |||
| 189 | off_t current = lseek(fds[i], 0, SEEK_END); | 190 | off_t current = lseek(fds[i], 0, SEEK_END); |
| 190 | if (current > 0) { | 191 | if (current > 0) { |
| 191 | if (count == 0) | 192 | if (count == 0) |
| 192 | continue; /* showing zero lines is easy :) */ | 193 | continue; /* showing zero bytes is easy :) */ |
| 193 | current -= count; | 194 | current -= count; |
| 194 | if (current < 0) | 195 | if (current < 0) |
| 195 | current = 0; | 196 | current = 0; |
| @@ -201,12 +202,15 @@ int tail_main(int argc, char **argv) | |||
| 201 | 202 | ||
| 202 | buf = tailbuf; | 203 | buf = tailbuf; |
| 203 | taillen = 0; | 204 | taillen = 0; |
| 205 | /* "We saw 1st line/byte". | ||
| 206 | * Used only by +N code ("start from Nth", 1-based) */ | ||
| 204 | seen = 1; | 207 | seen = 1; |
| 205 | newlines_seen = 0; | 208 | newlines_seen = 0; |
| 206 | while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { | 209 | while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { |
| 207 | if (from_top) { | 210 | if (from_top) { |
| 208 | int nwrite = nread; | 211 | int nwrite = nread; |
| 209 | if (seen < count) { | 212 | if (seen < count) { |
| 213 | /* We need to skip a few more bytes/lines */ | ||
| 210 | if (COUNT_BYTES) { | 214 | if (COUNT_BYTES) { |
| 211 | nwrite -= (count - seen); | 215 | nwrite -= (count - seen); |
| 212 | seen = count; | 216 | seen = count; |
diff --git a/testsuite/tail.tests b/testsuite/tail.tests new file mode 100755 index 000000000..d97bf7bbe --- /dev/null +++ b/testsuite/tail.tests | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | # Copyright 2009 by Denys Vlasenko <vda.linux@googlemail.com> | ||
| 4 | # Licensed under GPL v2, see file LICENSE for details. | ||
| 5 | |||
| 6 | . testing.sh | ||
| 7 | |||
| 8 | # testing "test name" "command" "expected result" "file input" "stdin" | ||
| 9 | # file input will be file called "input" | ||
| 10 | # test can create a file "actual" instead of writing to stdout | ||
| 11 | |||
| 12 | testing "tail: +N with N > file length" \ | ||
| 13 | "tail -c +55 2>&1; echo \$?" \ | ||
| 14 | "0\n" \ | ||
| 15 | "" "qw" | ||
| 16 | |||
| 17 | exit $FAILCOUNT | ||
