diff options
-rw-r--r-- | coreutils/tail.c | 36 |
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 | ||
61 | struct globals { | 61 | struct 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 | } |