summaryrefslogtreecommitdiff
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-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.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)
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];