summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-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)
int nread;
const char *filename = argv[i];
int fd = fds[i];
+ int new_fd = -1;
+ struct stat sbuf;
if (FOLLOW_RETRY) {
- struct stat sbuf, fsbuf;
+ struct stat fsbuf;
if (fd < 0
|| fstat(fd, &fsbuf) < 0
@@ -356,19 +358,21 @@ int tail_main(int argc, char **argv)
|| fsbuf.st_dev != sbuf.st_dev
|| fsbuf.st_ino != sbuf.st_ino
) {
- int new_fd;
-
- if (fd >= 0)
- close(fd);
+ /* Looks like file has been created/renamed/deleted */
new_fd = open(filename, O_RDONLY);
if (new_fd >= 0) {
bb_error_msg("%s has %s; following end of new file",
filename, (fd < 0) ? "appeared" : "been replaced"
);
+ if (fd < 0) {
+ /* No previously open fd for this file,
+ * start using new_fd immediately. */
+ fds[i] = fd = new_fd;
+ new_fd = -1;
+ }
} else if (fd >= 0) {
- bb_perror_msg("%s has become inaccessible", filename);
+ bb_perror_msg("%s has been renamed or deleted", filename);
}
- fds[i] = fd = new_fd;
}
}
if (ENABLE_FEATURE_FANCY_TAIL && fd < 0)
@@ -378,17 +382,27 @@ int tail_main(int argc, char **argv)
}
for (;;) {
/* tail -f keeps following files even if they are truncated */
- struct stat sbuf;
/* /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);
- 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);
+ }
}
nread = tail_read(fd, tailbuf, BUFSIZ);
- if (nread <= 0)
- break;
+ if (nread <= 0) {
+ if (new_fd < 0)
+ break;
+ /* Switch to "tail -F"ing the new file */
+ xmove_fd(new_fd, fd);
+ new_fd = -1;
+ continue;
+ }
if (fmt && (fd != prev_fd)) {
tail_xprint_header(fmt, filename);
fmt = NULL;