diff options
author | iedowse <iedowse@FreeBSD.org> | 2001-11-25 18:03:28 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2001-11-25 18:03:28 +0000 |
commit | f9343b357875432b2c6a2c2c812c1281a6ceb12b (patch) | |
tree | 52e8aac32a8eaf00efe49406bd271677c5d37f53 /usr.bin/tail | |
parent | f312390d6f16e3b6470e9873c6b7275d2fa24fca (diff) | |
download | FreeBSD-src-f9343b357875432b2c6a2c2c812c1281a6ceb12b.zip FreeBSD-src-f9343b357875432b2c6a2c2c812c1281a6ceb12b.tar.gz |
Since kqueue support was added to tail, the "-F" option (check for
renames/rotations) only detected cases where the file itself was
moved or deleted. If part of the path to the file (or a symlink
in the path) was changed instead, tail would not notice.
Fix this by ensuring that we stat the path at least once every
second in the -F case to check for changes. We still use kqueue
when possible to inform us quickly when the file has changed.
PR: bin/24955
Submitted by: Maxim Konovalov <maxim@macomnet.ru>
MFC after: 1 week
Diffstat (limited to 'usr.bin/tail')
-rw-r--r-- | usr.bin/tail/forward.c | 64 |
1 files changed, 34 insertions, 30 deletions
diff --git a/usr.bin/tail/forward.c b/usr.bin/tail/forward.c index ceacc04..c2f347c 100644 --- a/usr.bin/tail/forward.c +++ b/usr.bin/tail/forward.c @@ -94,10 +94,11 @@ forward(fp, style, off, sbp) off_t off; struct stat *sbp; { - int ch, kq = -1; + int ch, n, kq = -1; int action = USE_SLEEP; struct kevent ev[2]; struct stat sb2; + struct timespec ts; switch(style) { case FBYTES: @@ -193,9 +194,10 @@ forward(fp, style, off, sbp) clearerr(fp); switch (action) { - case ADD_EVENTS: { - int n = 0; - struct timespec ts = { 0, 0 }; + case ADD_EVENTS: + n = 0; + ts.tv_sec = 0; + ts.tv_nsec = 0; if (Fflag && fileno(fp) != STDIN_FILENO) { EV_SET(&ev[n], fileno(fp), EVFILT_VNODE, @@ -208,24 +210,27 @@ forward(fp, style, off, sbp) n++; if (kevent(kq, ev, n, NULL, 0, &ts) < 0) { - close(kq); - kq = -1; action = USE_SLEEP; } else { action = USE_KQUEUE; } break; - } case USE_KQUEUE: - if (kevent(kq, NULL, 0, ev, 1, NULL) < 0) + ts.tv_sec = 1; + ts.tv_nsec = 0; + /* + * In the -F case we set a timeout to ensure that + * we re-stat the file at least once every second. + */ + n = kevent(kq, NULL, 0, ev, 1, Fflag ? &ts : NULL); + if (n < 0) err(1, "kevent"); - - if (ev->filter == EVFILT_VNODE) { - /* file was rotated, wait until it reappears */ - action = USE_SLEEP; - } else if (ev->data < 0) { - /* file shrank, reposition to end */ + if (n == 0) { + /* timeout */ + break; + } else if (ev->filter == EVFILT_READ && ev->data < 0) { + /* file shrank, reposition to end */ if (fseeko(fp, (off_t)0, SEEK_END) == -1) { ierr(); return; @@ -236,26 +241,25 @@ forward(fp, style, off, sbp) case USE_SLEEP: (void) usleep(250000); clearerr(fp); + break; + } - if (Fflag && fileno(fp) != STDIN_FILENO && - stat(fname, &sb2) != -1) { - if (sb2.st_ino != sbp->st_ino || - sb2.st_dev != sbp->st_dev || - sb2.st_rdev != sbp->st_rdev || - sb2.st_nlink == 0) { - fp = freopen(fname, "r", fp); - if (fp == NULL) { - ierr(); - break; - } + if (Fflag && fileno(fp) != STDIN_FILENO) { + while (stat(fname, &sb2) != 0) + /* file was rotated, wait until it reappears */ + (void)sleep(1); + if (sb2.st_ino != sbp->st_ino || + sb2.st_dev != sbp->st_dev || + sb2.st_rdev != sbp->st_rdev || + sb2.st_nlink == 0) { + fp = freopen(fname, "r", fp); + if (fp == NULL) { + ierr(); + } else { *sbp = sb2; - if (kq != -1) - action = ADD_EVENTS; - } else if (kq != -1) { - action = USE_KQUEUE; + action = ADD_EVENTS; } } - break; } } } |