aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-08-10 03:16:18 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-08-10 03:16:18 +0200
commit79b021d738186ad0c581714626c7d2eea1bb6445 (patch)
treedccc053f0bf2593ca3b279a9d21399822d7a57b3
parente531759ef140c249fcab88a853567d2d31803105 (diff)
downloadbusybox-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.c49
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) {