aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/tail.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/coreutils/tail.c b/coreutils/tail.c
index eac982735..4b42ebc52 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -59,7 +59,8 @@ static const struct suffix_mult tail_suffixes[] = {
59}; 59};
60 60
61struct globals { 61struct globals {
62 bool status; 62 bool from_top;
63 bool exitcode;
63} FIX_ALIASING; 64} FIX_ALIASING;
64#define G (*(struct globals*)&bb_common_bufsiz1) 65#define G (*(struct globals*)&bb_common_bufsiz1)
65 66
@@ -85,7 +86,7 @@ static ssize_t tail_read(int fd, char *buf, size_t count)
85 r = full_read(fd, buf, count); 86 r = full_read(fd, buf, count);
86 if (r < 0) { 87 if (r < 0) {
87 bb_perror_msg(bb_msg_read_error); 88 bb_perror_msg(bb_msg_read_error);
88 G.status = EXIT_FAILURE; 89 G.exitcode = EXIT_FAILURE;
89 } 90 }
90 91
91 return r; 92 return r;
@@ -99,7 +100,7 @@ static unsigned eat_num(const char *p)
99 p++; 100 p++;
100 else if (*p == '+') { 101 else if (*p == '+') {
101 p++; 102 p++;
102 G.status = 1; /* mark that we saw "+" */ 103 G.from_top = 1;
103 } 104 }
104 return xatou_sfx(p, tail_suffixes); 105 return xatou_sfx(p, tail_suffixes);
105} 106}
@@ -109,7 +110,6 @@ int tail_main(int argc, char **argv)
109{ 110{
110 unsigned count = 10; 111 unsigned count = 10;
111 unsigned sleep_period = 1; 112 unsigned sleep_period = 1;
112 bool from_top;
113 const char *str_c, *str_n; 113 const char *str_c, *str_n;
114 114
115 char *tailbuf; 115 char *tailbuf;
@@ -152,8 +152,6 @@ int tail_main(int argc, char **argv)
152#endif 152#endif
153 argc -= optind; 153 argc -= optind;
154 argv += optind; 154 argv += optind;
155 from_top = G.status; /* 1 if there was "-c +N" or "-n +N" */
156 G.status = EXIT_SUCCESS;
157 155
158 /* open all the files */ 156 /* open all the files */
159 fds = xmalloc(sizeof(fds[0]) * (argc + 1)); 157 fds = xmalloc(sizeof(fds[0]) * (argc + 1));
@@ -171,7 +169,7 @@ int tail_main(int argc, char **argv)
171 do { 169 do {
172 int fd = open_or_warn_stdin(argv[i]); 170 int fd = open_or_warn_stdin(argv[i]);
173 if (fd < 0 && !FOLLOW_RETRY) { 171 if (fd < 0 && !FOLLOW_RETRY) {
174 G.status = EXIT_FAILURE; 172 G.exitcode = EXIT_FAILURE;
175 continue; 173 continue;
176 } 174 }
177 fds[nfiles] = fd; 175 fds[nfiles] = fd;
@@ -183,15 +181,19 @@ int tail_main(int argc, char **argv)
183 181
184 /* prepare the buffer */ 182 /* prepare the buffer */
185 tailbufsize = BUFSIZ; 183 tailbufsize = BUFSIZ;
186 if (!from_top && COUNT_BYTES) { 184 if (!G.from_top && COUNT_BYTES) {
187 if (tailbufsize < count + BUFSIZ) { 185 if (tailbufsize < count + BUFSIZ) {
188 tailbufsize = count + BUFSIZ; 186 tailbufsize = count + BUFSIZ;
189 } 187 }
190 } 188 }
191 tailbuf = xmalloc(tailbufsize); 189 /* tail -c1024m REGULAR_FILE doesn't really need 1G mem block.
190 * (In fact, it doesn't need ANY memory). So delay allocation.
191 */
192 tailbuf = NULL;
192 193
193 /* tail the files */ 194 /* tail the files */
194 fmt = header_fmt_str + 1; /* skip header leading newline on first output */ 195
196 fmt = header_fmt_str + 1; /* skip leading newline in the header on the first output */
195 i = 0; 197 i = 0;
196 do { 198 do {
197 char *buf; 199 char *buf;
@@ -209,7 +211,7 @@ int tail_main(int argc, char **argv)
209 fmt = header_fmt_str; 211 fmt = header_fmt_str;
210 } 212 }
211 213
212 if (!from_top) { 214 if (!G.from_top) {
213 off_t current = lseek(fd, 0, SEEK_END); 215 off_t current = lseek(fd, 0, SEEK_END);
214 if (current > 0) { 216 if (current > 0) {
215 unsigned off; 217 unsigned off;
@@ -242,6 +244,9 @@ int tail_main(int argc, char **argv)
242 } 244 }
243 } 245 }
244 246
247 if (!tailbuf)
248 tailbuf = xmalloc(tailbufsize);
249
245 buf = tailbuf; 250 buf = tailbuf;
246 taillen = 0; 251 taillen = 0;
247 /* "We saw 1st line/byte". 252 /* "We saw 1st line/byte".
@@ -249,7 +254,7 @@ int tail_main(int argc, char **argv)
249 seen = 1; 254 seen = 1;
250 newlines_seen = 0; 255 newlines_seen = 0;
251 while ((nread = tail_read(fd, buf, tailbufsize-taillen)) > 0) { 256 while ((nread = tail_read(fd, buf, tailbufsize-taillen)) > 0) {
252 if (from_top) { 257 if (G.from_top) {
253 int nwrite = nread; 258 int nwrite = nread;
254 if (seen < count) { 259 if (seen < count) {
255 /* We need to skip a few more bytes/lines */ 260 /* We need to skip a few more bytes/lines */
@@ -313,7 +318,7 @@ int tail_main(int argc, char **argv)
313 buf = tailbuf + taillen; 318 buf = tailbuf + taillen;
314 } 319 }
315 } /* while (tail_read() > 0) */ 320 } /* while (tail_read() > 0) */
316 if (!from_top) { 321 if (!G.from_top) {
317 xwrite(STDOUT_FILENO, tailbuf, taillen); 322 xwrite(STDOUT_FILENO, tailbuf, taillen);
318 } 323 }
319 } while (++i < nfiles); 324 } while (++i < nfiles);
@@ -368,10 +373,11 @@ int tail_main(int argc, char **argv)
368 xwrite(STDOUT_FILENO, tailbuf, nread); 373 xwrite(STDOUT_FILENO, tailbuf, nread);
369 } 374 }
370 } while (++i < nfiles); 375 } while (++i < nfiles);
371 } 376 } /* while (1) */
377
372 if (ENABLE_FEATURE_CLEAN_UP) { 378 if (ENABLE_FEATURE_CLEAN_UP) {
373 free(fds); 379 free(fds);
374 free(tailbuf); 380 free(tailbuf);
375 } 381 }
376 return G.status; 382 return G.exitcode;
377} 383}