diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-10 03:16:18 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-08-10 03:16:18 +0200 |
commit | 79b021d738186ad0c581714626c7d2eea1bb6445 (patch) | |
tree | dccc053f0bf2593ca3b279a9d21399822d7a57b3 | |
parent | e531759ef140c249fcab88a853567d2d31803105 (diff) | |
download | busybox-w32-79b021d738186ad0c581714626c7d2eea1bb6445.tar.gz busybox-w32-79b021d738186ad0c581714626c7d2eea1bb6445.tar.bz2 busybox-w32-79b021d738186ad0c581714626c7d2eea1bb6445.zip |
tail: read only a portion of a file if it's huge. closes bug 551
function old new delta
tail_main 1494 1526 +32
tail_read 125 129 +4
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | coreutils/tail.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/coreutils/tail.c b/coreutils/tail.c index 5f98bff82..05dadcd9b 100644 --- a/coreutils/tail.c +++ b/coreutils/tail.c | |||
@@ -51,10 +51,10 @@ static ssize_t tail_read(int fd, char *buf, size_t count) | |||
51 | struct stat sbuf; | 51 | struct stat sbuf; |
52 | 52 | ||
53 | /* /proc files report zero st_size, don't lseek them. */ | 53 | /* /proc files report zero st_size, don't lseek them. */ |
54 | if (fstat(fd, &sbuf) == 0 && sbuf.st_size) { | 54 | if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { |
55 | current = lseek(fd, 0, SEEK_CUR); | 55 | current = lseek(fd, 0, SEEK_CUR); |
56 | if (sbuf.st_size < current) | 56 | if (sbuf.st_size < current) |
57 | lseek(fd, 0, SEEK_SET); | 57 | xlseek(fd, 0, SEEK_SET); |
58 | } | 58 | } |
59 | 59 | ||
60 | r = full_read(fd, buf, count); | 60 | r = full_read(fd, buf, count); |
@@ -174,8 +174,9 @@ int tail_main(int argc, char **argv) | |||
174 | int newlines_seen; | 174 | int newlines_seen; |
175 | unsigned seen; | 175 | unsigned seen; |
176 | int nread; | 176 | int nread; |
177 | int fd = fds[i]; | ||
177 | 178 | ||
178 | if (ENABLE_FEATURE_FANCY_TAIL && fds[i] < 0) | 179 | if (ENABLE_FEATURE_FANCY_TAIL && fd < 0) |
179 | continue; /* may happen with -E */ | 180 | continue; /* may happen with -E */ |
180 | 181 | ||
181 | if (nfiles > header_threshhold) { | 182 | if (nfiles > header_threshhold) { |
@@ -183,30 +184,46 @@ int tail_main(int argc, char **argv) | |||
183 | fmt = header_fmt; | 184 | fmt = header_fmt; |
184 | } | 185 | } |
185 | 186 | ||
186 | /* Optimizing count-bytes case if the file is seekable. | 187 | if (!from_top) { |
187 | * Beware of backing up too far. | 188 | off_t current = lseek(fd, 0, SEEK_END); |
188 | * Also we exclude files with size 0 (because of /proc/xxx) */ | ||
189 | if (COUNT_BYTES && !from_top) { | ||
190 | off_t current = lseek(fds[i], 0, SEEK_END); | ||
191 | if (current > 0) { | 189 | if (current > 0) { |
192 | if (count == 0) | 190 | unsigned off; |
193 | continue; /* showing zero bytes is easy :) */ | 191 | if (COUNT_BYTES) { |
194 | current -= count; | 192 | /* Optimizing count-bytes case if the file is seekable. |
193 | * Beware of backing up too far. | ||
194 | * Also we exclude files with size 0 (because of /proc/xxx) */ | ||
195 | if (count == 0) | ||
196 | continue; /* showing zero bytes is easy :) */ | ||
197 | current -= count; | ||
198 | if (current < 0) | ||
199 | current = 0; | ||
200 | xlseek(fd, current, SEEK_SET); | ||
201 | bb_copyfd_size(fd, STDOUT_FILENO, count); | ||
202 | continue; | ||
203 | } | ||
204 | #if 1 /* This is technically incorrect for *LONG* strings, but very useful */ | ||
205 | /* Optimizing count-lines case if the file is seekable. | ||
206 | * We assume the lines are <64k. | ||
207 | * (Users complain that tail takes too long | ||
208 | * on multi-gigabyte files) */ | ||
209 | off = (count | 0xf); /* for small counts, be more paranoid */ | ||
210 | if (off > (INT_MAX / (64*1024))) | ||
211 | off = (INT_MAX / (64*1024)); | ||
212 | current -= off * (64*1024); | ||
195 | if (current < 0) | 213 | if (current < 0) |
196 | current = 0; | 214 | current = 0; |
197 | xlseek(fds[i], current, SEEK_SET); | 215 | xlseek(fd, current, SEEK_SET); |
198 | bb_copyfd_size(fds[i], STDOUT_FILENO, count); | 216 | #endif |
199 | continue; | ||
200 | } | 217 | } |
201 | } | 218 | } |
202 | 219 | ||
203 | buf = tailbuf; | 220 | buf = tailbuf; |
204 | taillen = 0; | 221 | taillen = 0; |
205 | /* "We saw 1st line/byte". | 222 | /* "We saw 1st line/byte". |
206 | * Used only by +N code ("start from Nth", 1-based) */ | 223 | * Used only by +N code ("start from Nth", 1-based): */ |
207 | seen = 1; | 224 | seen = 1; |
208 | newlines_seen = 0; | 225 | newlines_seen = 0; |
209 | while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { | 226 | while ((nread = tail_read(fd, buf, tailbufsize-taillen)) > 0) { |
210 | if (from_top) { | 227 | if (from_top) { |
211 | int nwrite = nread; | 228 | int nwrite = nread; |
212 | if (seen < count) { | 229 | if (seen < count) { |