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>
This commit is contained in:
Denys Vlasenko 2021-06-02 04:55:10 +02:00
parent e0ea125ce2
commit f193aeac1f

View File

@ -346,9 +346,11 @@ int tail_main(int argc, char **argv)
int nread; int nread;
const char *filename = argv[i]; const char *filename = argv[i];
int fd = fds[i]; int fd = fds[i];
int new_fd = -1;
struct stat sbuf;
if (FOLLOW_RETRY) { if (FOLLOW_RETRY) {
struct stat sbuf, fsbuf; struct stat fsbuf;
if (fd < 0 if (fd < 0
|| fstat(fd, &fsbuf) < 0 || fstat(fd, &fsbuf) < 0
@ -356,19 +358,21 @@ int tail_main(int argc, char **argv)
|| fsbuf.st_dev != sbuf.st_dev || fsbuf.st_dev != sbuf.st_dev
|| fsbuf.st_ino != sbuf.st_ino || fsbuf.st_ino != sbuf.st_ino
) { ) {
int new_fd; /* Looks like file has been created/renamed/deleted */
if (fd >= 0)
close(fd);
new_fd = open(filename, O_RDONLY); new_fd = open(filename, O_RDONLY);
if (new_fd >= 0) { if (new_fd >= 0) {
bb_error_msg("%s has %s; following end of new file", bb_error_msg("%s has %s; following end of new file",
filename, (fd < 0) ? "appeared" : "been replaced" filename, (fd < 0) ? "appeared" : "been replaced"
); );
} else if (fd >= 0) { if (fd < 0) {
bb_perror_msg("%s has become inaccessible", filename); /* No previously open fd for this file,
} * start using new_fd immediately. */
fds[i] = fd = new_fd; fds[i] = fd = new_fd;
new_fd = -1;
}
} else if (fd >= 0) {
bb_perror_msg("%s has been renamed or deleted", filename);
}
} }
} }
if (ENABLE_FEATURE_FANCY_TAIL && fd < 0) if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
@ -378,17 +382,27 @@ int tail_main(int argc, char **argv)
} }
for (;;) { for (;;) {
/* tail -f keeps following files even if they are truncated */ /* tail -f keeps following files even if they are truncated */
struct stat sbuf;
/* /proc files report zero st_size, don't lseek them */ /* /proc files report zero st_size, don't lseek them */
if (fstat(fd, &sbuf) == 0 && sbuf.st_size > 0) { if (fstat(fd, &sbuf) == 0
/* && S_ISREG(sbuf.st_mode) TODO? */
&& sbuf.st_size > 0
) {
off_t current = lseek(fd, 0, SEEK_CUR); off_t current = lseek(fd, 0, SEEK_CUR);
if (sbuf.st_size < current) if (sbuf.st_size < current) {
//bb_perror_msg("%s: file truncated", filename); - says coreutils 8.32
xlseek(fd, 0, SEEK_SET); xlseek(fd, 0, SEEK_SET);
} }
}
nread = tail_read(fd, tailbuf, BUFSIZ); nread = tail_read(fd, tailbuf, BUFSIZ);
if (nread <= 0) if (nread <= 0) {
if (new_fd < 0)
break; break;
/* Switch to "tail -F"ing the new file */
xmove_fd(new_fd, fd);
new_fd = -1;
continue;
}
if (fmt && (fd != prev_fd)) { if (fmt && (fd != prev_fd)) {
tail_xprint_header(fmt, filename); tail_xprint_header(fmt, filename);
fmt = NULL; fmt = NULL;