diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-19 00:38:10 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-19 00:38:10 +0000 |
commit | e8419c90f1f3880f96ff335c4ee0bdd7a86ab0c6 (patch) | |
tree | 2d316d993abf38208f190454e84e9da50c31aadd | |
parent | 5233cd38003724fad3b4355174d367337f5a3d49 (diff) | |
download | busybox-w32-e8419c90f1f3880f96ff335c4ee0bdd7a86ab0c6.tar.gz busybox-w32-e8419c90f1f3880f96ff335c4ee0bdd7a86ab0c6.tar.bz2 busybox-w32-e8419c90f1f3880f96ff335c4ee0bdd7a86ab0c6.zip |
tail: fix "tail -c 20 /dev/huge_disk" (was taking ages)
tail: a few variables renamed
wc: tiny optimization.
-rw-r--r-- | coreutils/tail.c | 79 | ||||
-rw-r--r-- | coreutils/wc.c | 2 |
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) | |||
74 | p++; | 74 | p++; |
75 | else if (*p == '+') { | 75 | else if (*p == '+') { |
76 | p++; | 76 | p++; |
77 | G.status = EXIT_FAILURE; | 77 | G.status = 1; /* mark that we saw "+" */ |
78 | } | 78 | } |
79 | return xatou_sfx(p, tail_suffixes); | 79 | return xatou_sfx(p, tail_suffixes); |
80 | } | 80 | } |
@@ -92,7 +92,7 @@ int tail_main(int argc, char **argv) | |||
92 | char *tailbuf; | 92 | char *tailbuf; |
93 | size_t tailbufsize; | 93 | size_t tailbufsize; |
94 | int taillen = 0; | 94 | int taillen = 0; |
95 | int newline = 0; | 95 | int newlines_seen = 0; |
96 | int nfiles, nread, nwrite, seen, i, opt; | 96 | int nfiles, nread, nwrite, seen, i, opt; |
97 | 97 | ||
98 | int *fds; | 98 | int *fds; |
@@ -128,12 +128,12 @@ int tail_main(int argc, char **argv) | |||
128 | #endif | 128 | #endif |
129 | argc -= optind; | 129 | argc -= optind; |
130 | argv += optind; | 130 | argv += optind; |
131 | from_top = G.status; | 131 | from_top = G.status; /* 1 if there was "-c +N" or "-n +N" */ |
132 | G.status = EXIT_SUCCESS; | ||
132 | 133 | ||
133 | /* open all the files */ | 134 | /* open all the files */ |
134 | fds = xmalloc(sizeof(int) * (argc + 1)); | 135 | fds = xmalloc(sizeof(int) * (argc + 1)); |
135 | nfiles = i = 0; | 136 | nfiles = i = 0; |
136 | G.status = EXIT_SUCCESS; | ||
137 | if (argc == 0) { | 137 | if (argc == 0) { |
138 | struct stat statbuf; | 138 | struct stat statbuf; |
139 | 139 | ||
@@ -155,39 +155,49 @@ int tail_main(int argc, char **argv) | |||
155 | if (!nfiles) | 155 | if (!nfiles) |
156 | bb_error_msg_and_die("no files"); | 156 | bb_error_msg_and_die("no files"); |
157 | 157 | ||
158 | /* prepare the buffer */ | ||
158 | tailbufsize = BUFSIZ; | 159 | tailbufsize = BUFSIZ; |
159 | |||
160 | /* tail the files */ | ||
161 | if (!from_top && COUNT_BYTES) { | 160 | if (!from_top && COUNT_BYTES) { |
162 | if (tailbufsize < count) { | 161 | if (tailbufsize < count + BUFSIZ) { |
163 | tailbufsize = count + BUFSIZ; | 162 | tailbufsize = count + BUFSIZ; |
164 | } | 163 | } |
165 | } | 164 | } |
165 | tailbuf = xmalloc(tailbufsize); | ||
166 | 166 | ||
167 | buf = tailbuf = xmalloc(tailbufsize); | 167 | /* tail the files */ |
168 | |||
169 | fmt = header_fmt + 1; /* Skip header leading newline on first output. */ | 168 | fmt = header_fmt + 1; /* Skip header leading newline on first output. */ |
170 | i = 0; | 169 | i = 0; |
171 | do { | 170 | do { |
172 | /* Be careful. It would be possible to optimize the count-bytes | 171 | off_t current; |
173 | * case if the file is seekable. If you do though, remember that | ||
174 | * starting file position may not be the beginning of the file. | ||
175 | * Beware of backing up too far. See example in wc.c. | ||
176 | */ | ||
177 | if (!(count | from_top) && lseek(fds[i], 0, SEEK_END) >= 0) { | ||
178 | continue; | ||
179 | } | ||
180 | 172 | ||
181 | if (nfiles > header_threshhold) { | 173 | if (nfiles > header_threshhold) { |
182 | tail_xprint_header(fmt, argv[i]); | 174 | tail_xprint_header(fmt, argv[i]); |
183 | fmt = header_fmt; | 175 | fmt = header_fmt; |
184 | } | 176 | } |
185 | 177 | ||
178 | /* Optimizing count-bytes case if the file is seekable. | ||
179 | * Beware of backing up too far. | ||
180 | * Also we exclude files with size 0 (because of /proc/xxx) */ | ||
181 | current = lseek(fds[i], 0, SEEK_END); | ||
182 | if (current > 0) { | ||
183 | if (!from_top) { | ||
184 | if (count == 0) | ||
185 | continue; /* showing zero lines is easy :) */ | ||
186 | if (COUNT_BYTES) { | ||
187 | current -= count; | ||
188 | if (current < 0) | ||
189 | current = 0; | ||
190 | xlseek(fds[i], current, SEEK_SET); | ||
191 | bb_copyfd_size(fds[i], STDOUT_FILENO, count); | ||
192 | continue; | ||
193 | } | ||
194 | } | ||
195 | } | ||
196 | |||
186 | buf = tailbuf; | 197 | buf = tailbuf; |
187 | taillen = 0; | 198 | taillen = 0; |
188 | seen = 1; | 199 | seen = 1; |
189 | newline = 0; | 200 | newlines_seen = 0; |
190 | |||
191 | while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { | 201 | while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { |
192 | if (from_top) { | 202 | if (from_top) { |
193 | nwrite = nread; | 203 | nwrite = nread; |
@@ -215,34 +225,32 @@ int tail_main(int argc, char **argv) | |||
215 | } | 225 | } |
216 | } else { | 226 | } else { |
217 | int k = nread; | 227 | int k = nread; |
218 | int nbuf = 0; | 228 | int newlines_in_buf = 0; |
219 | 229 | ||
220 | while (k) { | 230 | do { /* count '\n' in last read */ |
221 | --k; | 231 | k--; |
222 | if (buf[k] == '\n') { | 232 | if (buf[k] == '\n') { |
223 | ++nbuf; | 233 | newlines_in_buf++; |
224 | } | 234 | } |
225 | } | 235 | } while (k); |
226 | 236 | ||
227 | if (newline + nbuf < count) { | 237 | if (newlines_seen + newlines_in_buf < count) { |
228 | newline += nbuf; | 238 | newlines_seen += newlines_in_buf; |
229 | taillen += nread; | 239 | taillen += nread; |
230 | } else { | 240 | } else { |
231 | int extra = 0; | 241 | int extra = (buf[nread-1] != '\n'); |
232 | 242 | ||
233 | if (buf[nread-1] != '\n') | 243 | k = newlines_seen + newlines_in_buf + extra - count; |
234 | extra = 1; | ||
235 | k = newline + nbuf + extra - count; | ||
236 | s = tailbuf; | 244 | s = tailbuf; |
237 | while (k) { | 245 | while (k) { |
238 | if (*s == '\n') { | 246 | if (*s == '\n') { |
239 | --k; | 247 | k--; |
240 | } | 248 | } |
241 | ++s; | 249 | s++; |
242 | } | 250 | } |
243 | taillen += nread - (s - tailbuf); | 251 | taillen += nread - (s - tailbuf); |
244 | memmove(tailbuf, s, taillen); | 252 | memmove(tailbuf, s, taillen); |
245 | newline = count - extra; | 253 | newlines_seen = count - extra; |
246 | } | 254 | } |
247 | if (tailbufsize < taillen + BUFSIZ) { | 255 | if (tailbufsize < taillen + BUFSIZ) { |
248 | tailbufsize = taillen + BUFSIZ; | 256 | tailbufsize = taillen + BUFSIZ; |
@@ -251,13 +259,10 @@ int tail_main(int argc, char **argv) | |||
251 | } | 259 | } |
252 | buf = tailbuf + taillen; | 260 | buf = tailbuf + taillen; |
253 | } | 261 | } |
254 | } | 262 | } /* while (tail_read() > 0) */ |
255 | |||
256 | if (!from_top) { | 263 | if (!from_top) { |
257 | xwrite(STDOUT_FILENO, tailbuf, taillen); | 264 | xwrite(STDOUT_FILENO, tailbuf, taillen); |
258 | } | 265 | } |
259 | |||
260 | taillen = 0; | ||
261 | } while (++i < nfiles); | 266 | } while (++i < nfiles); |
262 | 267 | ||
263 | buf = xrealloc(tailbuf, BUFSIZ); | 268 | 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) | |||
73 | { | 73 | { |
74 | FILE *fp; | 74 | FILE *fp; |
75 | const char *s, *arg; | 75 | const char *s, *arg; |
76 | const char *start_fmt = "%9"COUNT_FMT; | 76 | const char *start_fmt = " %9"COUNT_FMT + 1; |
77 | const char *fname_fmt = " %s\n"; | 77 | const char *fname_fmt = " %s\n"; |
78 | COUNT_T *pcounts; | 78 | COUNT_T *pcounts; |
79 | COUNT_T counts[4]; | 79 | COUNT_T counts[4]; |