aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-02-19 00:38:10 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-02-19 00:38:10 +0000
commite8419c90f1f3880f96ff335c4ee0bdd7a86ab0c6 (patch)
tree2d316d993abf38208f190454e84e9da50c31aadd
parent5233cd38003724fad3b4355174d367337f5a3d49 (diff)
downloadbusybox-e8419c90f1f3880f96ff335c4ee0bdd7a86ab0c6.tar.gz
tail: fix "tail -c 20 /dev/huge_disk" (was taking ages)
tail: a few variables renamed wc: tiny optimization.
-rw-r--r--coreutils/tail.c79
-rw-r--r--coreutils/wc.c2
2 files changed, 43 insertions, 38 deletions
diff --git a/coreutils/tail.c b/coreutils/tail.c
index beecbaedf..340697f88 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -74,7 +74,7 @@ static unsigned eat_num(const char *p)
p++;
else if (*p == '+') {
p++;
- G.status = EXIT_FAILURE;
+ G.status = 1; /* mark that we saw "+" */
}
return xatou_sfx(p, tail_suffixes);
}
@@ -92,7 +92,7 @@ int tail_main(int argc, char **argv)
char *tailbuf;
size_t tailbufsize;
int taillen = 0;
- int newline = 0;
+ int newlines_seen = 0;
int nfiles, nread, nwrite, seen, i, opt;
int *fds;
@@ -128,12 +128,12 @@ int tail_main(int argc, char **argv)
#endif
argc -= optind;
argv += optind;
- from_top = G.status;
+ from_top = G.status; /* 1 if there was "-c +N" or "-n +N" */
+ G.status = EXIT_SUCCESS;
/* open all the files */
fds = xmalloc(sizeof(int) * (argc + 1));
nfiles = i = 0;
- G.status = EXIT_SUCCESS;
if (argc == 0) {
struct stat statbuf;
@@ -155,39 +155,49 @@ int tail_main(int argc, char **argv)
if (!nfiles)
bb_error_msg_and_die("no files");
+ /* prepare the buffer */
tailbufsize = BUFSIZ;
-
- /* tail the files */
if (!from_top && COUNT_BYTES) {
- if (tailbufsize < count) {
+ if (tailbufsize < count + BUFSIZ) {
tailbufsize = count + BUFSIZ;
}
}
+ tailbuf = xmalloc(tailbufsize);
- buf = tailbuf = xmalloc(tailbufsize);
-
+ /* tail the files */
fmt = header_fmt + 1; /* Skip header leading newline on first output. */
i = 0;
do {
- /* Be careful. It would be possible to optimize the count-bytes
- * case if the file is seekable. If you do though, remember that
- * starting file position may not be the beginning of the file.
- * Beware of backing up too far. See example in wc.c.
- */
- if (!(count | from_top) && lseek(fds[i], 0, SEEK_END) >= 0) {
- continue;
- }
+ off_t current;
if (nfiles > header_threshhold) {
tail_xprint_header(fmt, argv[i]);
fmt = header_fmt;
}
+ /* 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) */
+ current = lseek(fds[i], 0, SEEK_END);
+ if (current > 0) {
+ if (!from_top) {
+ if (count == 0)
+ continue; /* showing zero lines is easy :) */
+ if (COUNT_BYTES) {
+ current -= count;
+ if (current < 0)
+ current = 0;
+ xlseek(fds[i], current, SEEK_SET);
+ bb_copyfd_size(fds[i], STDOUT_FILENO, count);
+ continue;
+ }
+ }
+ }
+
buf = tailbuf;
taillen = 0;
seen = 1;
- newline = 0;
-
+ newlines_seen = 0;
while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) {
if (from_top) {
nwrite = nread;
@@ -215,34 +225,32 @@ int tail_main(int argc, char **argv)
}
} else {
int k = nread;
- int nbuf = 0;
+ int newlines_in_buf = 0;
- while (k) {
- --k;
+ do { /* count '\n' in last read */
+ k--;
if (buf[k] == '\n') {
- ++nbuf;
+ newlines_in_buf++;
}
- }
+ } while (k);
- if (newline + nbuf < count) {
- newline += nbuf;
+ if (newlines_seen + newlines_in_buf < count) {
+ newlines_seen += newlines_in_buf;
taillen += nread;
} else {
- int extra = 0;
+ int extra = (buf[nread-1] != '\n');
- if (buf[nread-1] != '\n')
- extra = 1;
- k = newline + nbuf + extra - count;
+ k = newlines_seen + newlines_in_buf + extra - count;
s = tailbuf;
while (k) {
if (*s == '\n') {
- --k;
+ k--;
}
- ++s;
+ s++;
}
taillen += nread - (s - tailbuf);
memmove(tailbuf, s, taillen);
- newline = count - extra;
+ newlines_seen = count - extra;
}
if (tailbufsize < taillen + BUFSIZ) {
tailbufsize = taillen + BUFSIZ;
@@ -251,13 +259,10 @@ int tail_main(int argc, char **argv)
}
buf = tailbuf + taillen;
}
- }
-
+ } /* while (tail_read() > 0) */
if (!from_top) {
xwrite(STDOUT_FILENO, tailbuf, taillen);
}
-
- taillen = 0;
} while (++i < nfiles);
buf = xrealloc(tailbuf, BUFSIZ);
diff --git a/coreutils/wc.c b/coreutils/wc.c
index 291af411f..58ea1c7db 100644
--- a/coreutils/wc.c
+++ b/coreutils/wc.c
@@ -73,7 +73,7 @@ int wc_main(int argc, char **argv)
{
FILE *fp;
const char *s, *arg;
- const char *start_fmt = "%9"COUNT_FMT;
+ const char *start_fmt = " %9"COUNT_FMT + 1;
const char *fname_fmt = " %s\n";
COUNT_T *pcounts;
COUNT_T counts[4];