aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2021-06-02 04:55:10 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2021-06-02 05:17:44 +0200
commitf193aeac1fe27c94d0f0b27314777df41480feb6 (patch)
tree9a21f60faa1a4a803fb9a60284a7d57d1c559834
parente0ea125ce24ebdd1febf930fca436f1a8fb7d48d (diff)
downloadbusybox-w32-f193aeac1fe27c94d0f0b27314777df41480feb6.tar.gz
busybox-w32-f193aeac1fe27c94d0f0b27314777df41480feb6.tar.bz2
busybox-w32-f193aeac1fe27c94d0f0b27314777df41480feb6.zip
tail: do not lose the tail of old file if new file (-F) is detected
function old new delta tail_main 1619 1645 +26 .rodata 103246 103250 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 30/0) Total: 30 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/tail.c38
1 files changed, 26 insertions, 12 deletions
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 93f1514d0..6201eb023 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -346,9 +346,11 @@ int tail_main(int argc, char **argv)
346 int nread; 346 int nread;
347 const char *filename = argv[i]; 347 const char *filename = argv[i];
348 int fd = fds[i]; 348 int fd = fds[i];
349 int new_fd = -1;
350 struct stat sbuf;
349 351
350 if (FOLLOW_RETRY) { 352 if (FOLLOW_RETRY) {
351 struct stat sbuf, fsbuf; 353 struct stat fsbuf;
352 354
353 if (fd < 0 355 if (fd < 0
354 || fstat(fd, &fsbuf) < 0 356 || fstat(fd, &fsbuf) < 0
@@ -356,19 +358,21 @@ int tail_main(int argc, char **argv)
356 || fsbuf.st_dev != sbuf.st_dev 358 || fsbuf.st_dev != sbuf.st_dev
357 || fsbuf.st_ino != sbuf.st_ino 359 || fsbuf.st_ino != sbuf.st_ino
358 ) { 360 ) {
359 int new_fd; 361 /* Looks like file has been created/renamed/deleted */
360
361 if (fd >= 0)
362 close(fd);
363 new_fd = open(filename, O_RDONLY); 362 new_fd = open(filename, O_RDONLY);
364 if (new_fd >= 0) { 363 if (new_fd >= 0) {
365 bb_error_msg("%s has %s; following end of new file", 364 bb_error_msg("%s has %s; following end of new file",
366 filename, (fd < 0) ? "appeared" : "been replaced" 365 filename, (fd < 0) ? "appeared" : "been replaced"
367 ); 366 );
367 if (fd < 0) {
368 /* No previously open fd for this file,
369 * start using new_fd immediately. */
370 fds[i] = fd = new_fd;
371 new_fd = -1;
372 }
368 } else if (fd >= 0) { 373 } else if (fd >= 0) {
369 bb_perror_msg("%s has become inaccessible", filename); 374 bb_perror_msg("%s has been renamed or deleted", filename);
370 } 375 }
371 fds[i] = fd = new_fd;
372 } 376 }
373 } 377 }
374 if (ENABLE_FEATURE_FANCY_TAIL && fd < 0) 378 if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
@@ -378,17 +382,27 @@ int tail_main(int argc, char **argv)
378 } 382 }
379 for (;;) { 383 for (;;) {
380 /* tail -f keeps following files even if they are truncated */ 384 /* tail -f keeps following files even if they are truncated */
381 struct stat sbuf;
382 /* /proc files report zero st_size, don't lseek them */ 385 /* /proc files report zero st_size, don't lseek them */
383 if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { 386 if (fstat(fd, &sbuf) == 0
387 /* && S_ISREG(sbuf.st_mode) TODO? */
388 && sbuf.st_size > 0
389 ) {
384 off_t current = lseek(fd, 0, SEEK_CUR); 390 off_t current = lseek(fd, 0, SEEK_CUR);
385 if (sbuf.st_size < current) 391 if (sbuf.st_size < current) {
392 //bb_perror_msg("%s: file truncated", filename); - says coreutils 8.32
386 xlseek(fd, 0, SEEK_SET); 393 xlseek(fd, 0, SEEK_SET);
394 }
387 } 395 }
388 396
389 nread = tail_read(fd, tailbuf, BUFSIZ); 397 nread = tail_read(fd, tailbuf, BUFSIZ);
390 if (nread <= 0) 398 if (nread <= 0) {
391 break; 399 if (new_fd < 0)
400 break;
401 /* Switch to "tail -F"ing the new file */
402 xmove_fd(new_fd, fd);
403 new_fd = -1;
404 continue;
405 }
392 if (fmt && (fd != prev_fd)) { 406 if (fmt && (fd != prev_fd)) {
393 tail_xprint_header(fmt, filename); 407 tail_xprint_header(fmt, filename);
394 fmt = NULL; 408 fmt = NULL;