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>
This commit is contained in:
parent
e531759ef1
commit
79b021d738
@ -51,10 +51,10 @@ static ssize_t tail_read(int fd, char *buf, size_t count)
|
|||||||
struct stat sbuf;
|
struct stat sbuf;
|
||||||
|
|
||||||
/* /proc files report zero st_size, don't lseek them. */
|
/* /proc files report zero st_size, don't lseek them. */
|
||||||
if (fstat(fd, &sbuf) == 0 && sbuf.st_size) {
|
if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) {
|
||||||
current = lseek(fd, 0, SEEK_CUR);
|
current = lseek(fd, 0, SEEK_CUR);
|
||||||
if (sbuf.st_size < current)
|
if (sbuf.st_size < current)
|
||||||
lseek(fd, 0, SEEK_SET);
|
xlseek(fd, 0, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = full_read(fd, buf, count);
|
r = full_read(fd, buf, count);
|
||||||
@ -174,8 +174,9 @@ int tail_main(int argc, char **argv)
|
|||||||
int newlines_seen;
|
int newlines_seen;
|
||||||
unsigned seen;
|
unsigned seen;
|
||||||
int nread;
|
int nread;
|
||||||
|
int fd = fds[i];
|
||||||
|
|
||||||
if (ENABLE_FEATURE_FANCY_TAIL && fds[i] < 0)
|
if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
|
||||||
continue; /* may happen with -E */
|
continue; /* may happen with -E */
|
||||||
|
|
||||||
if (nfiles > header_threshhold) {
|
if (nfiles > header_threshhold) {
|
||||||
@ -183,30 +184,46 @@ int tail_main(int argc, char **argv)
|
|||||||
fmt = header_fmt;
|
fmt = header_fmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Optimizing count-bytes case if the file is seekable.
|
if (!from_top) {
|
||||||
* Beware of backing up too far.
|
off_t current = lseek(fd, 0, SEEK_END);
|
||||||
* Also we exclude files with size 0 (because of /proc/xxx) */
|
|
||||||
if (COUNT_BYTES && !from_top) {
|
|
||||||
off_t current = lseek(fds[i], 0, SEEK_END);
|
|
||||||
if (current > 0) {
|
if (current > 0) {
|
||||||
if (count == 0)
|
unsigned off;
|
||||||
continue; /* showing zero bytes is easy :) */
|
if (COUNT_BYTES) {
|
||||||
current -= count;
|
/* Optimizing count-bytes case if the file is seekable.
|
||||||
|
* Beware of backing up too far.
|
||||||
|
* Also we exclude files with size 0 (because of /proc/xxx) */
|
||||||
|
if (count == 0)
|
||||||
|
continue; /* showing zero bytes is easy :) */
|
||||||
|
current -= count;
|
||||||
|
if (current < 0)
|
||||||
|
current = 0;
|
||||||
|
xlseek(fd, current, SEEK_SET);
|
||||||
|
bb_copyfd_size(fd, STDOUT_FILENO, count);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#if 1 /* This is technically incorrect for *LONG* strings, but very useful */
|
||||||
|
/* Optimizing count-lines case if the file is seekable.
|
||||||
|
* We assume the lines are <64k.
|
||||||
|
* (Users complain that tail takes too long
|
||||||
|
* on multi-gigabyte files) */
|
||||||
|
off = (count | 0xf); /* for small counts, be more paranoid */
|
||||||
|
if (off > (INT_MAX / (64*1024)))
|
||||||
|
off = (INT_MAX / (64*1024));
|
||||||
|
current -= off * (64*1024);
|
||||||
if (current < 0)
|
if (current < 0)
|
||||||
current = 0;
|
current = 0;
|
||||||
xlseek(fds[i], current, SEEK_SET);
|
xlseek(fd, current, SEEK_SET);
|
||||||
bb_copyfd_size(fds[i], STDOUT_FILENO, count);
|
#endif
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = tailbuf;
|
buf = tailbuf;
|
||||||
taillen = 0;
|
taillen = 0;
|
||||||
/* "We saw 1st line/byte".
|
/* "We saw 1st line/byte".
|
||||||
* Used only by +N code ("start from Nth", 1-based) */
|
* Used only by +N code ("start from Nth", 1-based): */
|
||||||
seen = 1;
|
seen = 1;
|
||||||
newlines_seen = 0;
|
newlines_seen = 0;
|
||||||
while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
|
while ((nread = tail_read(fd, buf, tailbufsize-taillen)) > 0) {
|
||||||
if (from_top) {
|
if (from_top) {
|
||||||
int nwrite = nread;
|
int nwrite = nread;
|
||||||
if (seen < count) {
|
if (seen < count) {
|
||||||
|
Loading…
Reference in New Issue
Block a user