tail: fix "tail -c 20 /dev/huge_disk" (was taking ages) tail: a few variables renamed wc: tiny optimization.
No binary (build failed)
—
(log yok)
| @@ -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); | |
| @@ -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]; | |