From nobody@FreeBSD.org  Thu Feb  8 11:26:06 2001
Return-Path: <nobody@FreeBSD.org>
Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21])
	by hub.freebsd.org (Postfix) with ESMTP id 058CA37B65D
	for <freebsd-gnats-submit@FreeBSD.org>; Thu,  8 Feb 2001 11:26:06 -0800 (PST)
Received: (from nobody@localhost)
	by freefall.freebsd.org (8.11.1/8.11.1) id f18JQ5706603;
	Thu, 8 Feb 2001 11:26:05 -0800 (PST)
	(envelope-from nobody)
Message-Id: <200102081926.f18JQ5706603@freefall.freebsd.org>
Date: Thu, 8 Feb 2001 11:26:05 -0800 (PST)
From: kmarx@vicor-nb.com
To: freebsd-gnats-submit@FreeBSD.org
Subject: /usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0)
X-Send-Pr-Version: www-1.0

>Number:         24955
>Category:       bin
>Synopsis:       /usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Feb 08 11:30:01 PST 2001
>Closed-Date:    Sat Jan 19 11:02:48 PST 2002
>Last-Modified:  Sat Jan 19 11:03:44 PST 2002
>Originator:     ken marx
>Release:        4.2-RELEASE FreeBSD 4.2-RELEASE
>Organization:
vicor
>Environment:
FreeBSD sploot.vicor-nb.com 4.2-RELEASE FreeBSD 4.2-RELEASE #0: Fri Jan  5 16:27:52 PST 2001     kmarx@sploot.vicor-nb.com:/usr/src/sys/compile/KMARX  i386

>Description:
There appears to be a difference in /usr/bin/tail -F between 4.0 and 4.1+.

It's not updating the inode it's doing the tail -F on when the inode changes.
(E.g., if you tail through a soft link and the link moves.)

This doesn't match the man page:

 -F      The -F option implies the -f option, but tail will also check to
         see if the file being followed has been renamed or rotated.  The 
         file is closed and reopened when tail detects that the filename
         being read from has a new inode number.  The -F option is ignored
         if reading from standard input rather than a file.

I just rebuilt a version from a 4.0 soure tree I have, and
that works. The difference is in /usr/src/usr.bin/tail/forward.c.
The one that doesn't work is: $FreeBSD: src/usr.bin/tail/forward.c,v 1.11.6.1 20
00/07/18 21:49:41 jlemon Exp $. The working 4.0 one has no cvs info.

I don't know if this is as it should be. A quick slog throught the
freebsd archies shows only a discussion of -f in CURRENT, and a reference
to a version of /usr/src/sys/kern/kern_event.c,v 1.14 that doesn't easily
compare to our 4.2 kern_event.c,v 1.2.2.4. Doesn't seem relevant...

I'll use my 4.0 version of tail, but thought someone might know
or care what the real deal is.


>How-To-Repeat:
1. create file /tmp/poot1 containing:
     1  poot1
     2  poot1
     3  poot1
     4  poot1
     5  poot1
     6  poot1
     7  poot1
     8  poot1

2. creat file /tmp/poot2 containing:
     1  poot2
     2  poot2
     3  poot2
     4  poot2
     5  poot2
     6  poot2
     7  poot2
     8  poot2

3. Create a link to /tmp/poot1:

	ln -s /tmp/poot1 /tmp/pootlnk

4. In a separate shell, tail the link:

	tail -F /tmp/pootlnk

5. remove the link: rm /tmp/pootlnk

6. recreate the link pointing to the other file

	ln -s /tmp/poot2 /tmp/pootlnk

In 4.0 the tail -F will correctly show:

     1  poot1
     2  poot1
     3  poot1
     4  poot1
     5  poot1
     6  poot1
     7  poot1
     8  poot1
     1  poot2
     2  poot2
     3  poot2
     4  poot2
     5  poot2
     6  poot2
     7  poot2
     8  poot2

(And will continue to update correctly for any rm/ln sequence
when the new target of the link is != to the previous target)

In 4.1+ it will only show:

     1  poot1
     2  poot1
     3  poot1
     4  poot1
     5  poot1
     6  poot1
     7  poot1
     8  poot1



>Fix:


>Release-Note:
>Audit-Trail:

From: Maxim Konovalov <maxim@macomnet.ru>
To: freebsd-gnats-submit@FreeBSD.org
Cc: kmarx@vicor-nb.com
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode
 changes (works in 4.0)
Date: Sat, 3 Nov 2001 11:43:33 +0300 (MSK)

 Hello,
 
 Try this patch:
 
 Index: forward.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/forward.c,v
 retrieving revision 1.27
 diff -u -r1.27 forward.c
 --- forward.c	1 Sep 2001 22:22:44 -0000	1.27
 +++ forward.c	2 Nov 2001 21:46:27 -0000
 @@ -94,10 +94,10 @@
  	off_t off;
  	struct stat *sbp;
  {
 -	int ch, kq = -1;
 +	int ch, dirfd, kq = -1;
  	int action = USE_SLEEP;
 -	struct kevent ev[2];
 -	struct stat sb2;
 +	struct kevent ev[3];
 +	struct stat sb2, sbl;
 
  	switch(style) {
  	case FBYTES:
 @@ -179,6 +179,15 @@
  		action = ADD_EVENTS;
  	}
 
 +	if (lstat(fname, &sbl) != -1) {
 +		if ((sbl.st_mode & S_IFLNK) == S_IFLNK) {
 +			dirfd = open((const char *)dirname(fname), O_RDONLY);
 +			if (dirfd == -1)
 +				err(1, "open");
 +		}
 +	} else
 +		err(1, "lstat");
 +
  	for (;;) {
  		while ((ch = getc(fp)) != EOF)
  			if (putchar(ch) == EOF)
 @@ -202,6 +211,13 @@
  				    EV_ADD | EV_ENABLE | EV_CLEAR,
  				    NOTE_DELETE | NOTE_RENAME, 0, 0);
  				n++;
 +
 +				if ((sbl.st_mode & S_IFLNK) == S_IFLNK) {
 +					EV_SET(&ev[n], dirfd, EVFILT_VNODE,
 +					    EV_ADD | EV_ENABLE | EV_CLEAR,
 +					    NOTE_WRITE, 0, 0);
 +					n++;
 +				}
  			}
  			EV_SET(&ev[n], fileno(fp), EVFILT_READ,
  			    EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0);
 
 -- 
 Maxim Konovalov, MAcomnet, Internet-Intranet Dept., system engineer
 phone: +7 (095) 796-9079, mailto: maxim@macomnet.ru
 
 

From: Ian Dowse <iedowse@maths.tcd.ie>
To: Maxim Konovalov <maxim@macomnet.ru>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0) 
Date: Mon, 19 Nov 2001 01:39:04 +0000

 In message <200111030850.fA38o2f55553@freefall.freebsd.org>, Maxim Konovalov wr
 ites:
 > Hello,
 > 
 > Try this patch:
 
 Hi,
 
 While this patch should address the particular case mentioned in this
 PR (tail is pointed at a symlink, but the symlink changes), it doesn't
 solve the general problem of any other component in the specified
 path changing. Maybe it is best to just resort to a polling approach
 when the '-F' flag is specified? It could still use kqueue, but just
 re-stat the path every ~1-10 seconds to check if the inode changed.
 
 Ian
 

From: Maxim Konovalov <maxim@macomnet.ru>
To: Ian Dowse <iedowse@maths.tcd.ie>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode
 changes (works in 4.0) 
Date: Mon, 19 Nov 2001 21:53:45 +0300 (MSK)

 Hello,
 
 On Sun, 18 Nov 2001, Ian Dowse wrote:
 
 [...]
 >  Hi,
 >
 >  While this patch should address the particular case mentioned in this
 >  PR (tail is pointed at a symlink, but the symlink changes), it doesn't
 >  solve the general problem of any other component in the specified
 >  path changing. Maybe it is best to just resort to a polling approach
 >  when the '-F' flag is specified? It could still use kqueue, but just
 >  re-stat the path every ~1-10 seconds to check if the inode changed.
 
 What about this one:
 
 Index: forward.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/forward.c,v
 retrieving revision 1.27
 diff -u -r1.27 forward.c
 --- forward.c	1 Sep 2001 22:22:44 -0000	1.27
 +++ forward.c	19 Nov 2001 18:31:49 -0000
 @@ -180,6 +180,9 @@
  	}
 
  	for (;;) {
 +		struct timespec ts;
 +		int n;
 +
  		while ((ch = getc(fp)) != EOF)
  			if (putchar(ch) == EOF)
  				oerr();
 @@ -194,8 +197,9 @@
 
  		switch (action) {
  		case ADD_EVENTS: {
 -			int n = 0;
 -			struct timespec ts = { 0, 0 };
 +			n = 0;
 +			ts.tv_sec = 0;
 +			ts.tv_nsec = 0;
 
  			if (Fflag && fileno(fp) != STDIN_FILENO) {
  				EV_SET(&ev[n], fileno(fp), EVFILT_VNODE,
 @@ -218,10 +222,16 @@
  		}
 
  		case USE_KQUEUE:
 -			if (kevent(kq, NULL, 0, ev, 1, NULL) < 0)
 +			ts.tv_sec = 0;
 +			ts.tv_nsec = 250000;
 +
 +			if ((n = kevent(kq, NULL, 0, ev, 1, &ts)) < 0)
  				err(1, "kevent");
 
 -			if (ev->filter == EVFILT_VNODE) {
 +			if (n == 0) {
 +				/* timeout */
 +				action = USE_SLEEP;
 +			} else if (ev->filter == EVFILT_VNODE) {
  				/* file was rotated, wait until it reappears */
  				action = USE_SLEEP;
  			} else if (ev->data < 0) {
 @@ -234,7 +244,7 @@
  			break;
 
  		case USE_SLEEP:
 -                	(void) usleep(250000);
 +                	(void)usleep(250000);
  	                clearerr(fp);
 
  			if (Fflag && fileno(fp) != STDIN_FILENO &&
 
 >  Ian
 
 - -maxim
 
 -- 
 Maxim Konovalov, MAcomnet, Internet-Intranet Dept., system engineer
 phone: +7 (095) 796-9079, mailto: maxim@macomnet.ru
 

From: Ian Dowse <iedowse@maths.tcd.ie>
To: Maxim Konovalov <maxim@macomnet.ru>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0) 
Date: Mon, 19 Nov 2001 22:59:21 +0000

 In message <20011119214750.L60209-100000@news1.macomnet.ru>, Maxim Konovalov wr
 ites:
 >
 >What about this one:
 
 Looks better, but unless I'm mistaken it introduces 250ms polling
 even when -F is not specified; this would undo the benefit of using
 kqueue in the first place.
 
 How about something like the modified version below? It only polls
 in the -F case (with a longer 1s interval), and it separates the
 choice of sleep vs kqueue from the stat calls necessary for -F.
 We always use kqueue if supported, but in the -F case, the kqueue
 timeout is set to 1 second. By keeping `kq' open, this patch also
 allows switching back to kqueue, for example if a symlink is changed
 so that the path moves from an NFS to a UFS filesystem.
 
 Note that the EVFILT_VNODE filter could probably be removed, since
 it is no longer needed to notice when the file is renamed or deleted.
 
 Ian
 
 Index: forward.c
 ===================================================================
 RCS file: /dump/FreeBSD-CVS/src/usr.bin/tail/forward.c,v
 retrieving revision 1.27
 diff -u -r1.27 forward.c
 --- forward.c	1 Sep 2001 22:22:44 -0000	1.27
 +++ forward.c	19 Nov 2001 22:34:00 -0000
 @@ -94,10 +94,11 @@
  	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 @@
  		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 @@
  			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,9 +241,11 @@
  		case USE_SLEEP:
                  	(void) usleep(250000);
  	                clearerr(fp);
 +			break;
 +		}
  
 -			if (Fflag && fileno(fp) != STDIN_FILENO &&
 -			    stat(fname, &sb2) != -1) {
 +		if (Fflag && fileno(fp) != STDIN_FILENO) {
 +			if (stat(fname, &sb2) != -1) {
  				if (sb2.st_ino != sbp->st_ino ||
  				    sb2.st_dev != sbp->st_dev ||
  				    sb2.st_rdev != sbp->st_rdev ||
 @@ -246,16 +253,15 @@
  					fp = freopen(fname, "r", fp);
  					if (fp == NULL) {
  						ierr();
 -						break;
 -					}
 -					*sbp = sb2;
 -					if (kq != -1)
 +					} else {
 +						*sbp = sb2;
  						action = ADD_EVENTS;
 -				} else if (kq != -1) {
 -					action = USE_KQUEUE;
 +					}
  				}
 +			} else {
 +				/* file was rotated, wait until it reappears */
 +				action = USE_SLEEP;
  			}
 -			break;
  		}
  	}
  }

From: Maxim Konovalov <maxim@macomnet.ru>
To: Ian Dowse <iedowse@maths.tcd.ie>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode
 changes (works in 4.0) 
Date: Thu, 22 Nov 2001 00:50:37 +0300 (MSK)

 Hello Ian,
 
 On Mon, 19 Nov 2001, Ian Dowse wrote:
 
 > In message <20011119214750.L60209-100000@news1.macomnet.ru>, Maxim Konovalov wr
 > ites:
 > >
 > >What about this one:
 >
 > Looks better, but unless I'm mistaken it introduces 250ms polling
 > even when -F is not specified; this would undo the benefit of using
 > kqueue in the first place.
 >
 > How about something like the modified version below? It only polls
 > in the -F case (with a longer 1s interval), and it separates the
 > choice of sleep vs kqueue from the stat calls necessary for -F.
 > We always use kqueue if supported, but in the -F case, the kqueue
 > timeout is set to 1 second. By keeping `kq' open, this patch also
 > allows switching back to kqueue, for example if a symlink is changed
 > so that the path moves from an NFS to a UFS filesystem.
 >
 > Note that the EVFILT_VNODE filter could probably be removed, since
 > it is no longer needed to notice when the file is renamed or deleted.
 
 Looks OK for me except one minor problem, see below
 
 > Ian
 >
 > Index: forward.c
 > ===================================================================
 > RCS file: /dump/FreeBSD-CVS/src/usr.bin/tail/forward.c,v
 > retrieving revision 1.27
 > diff -u -r1.27 forward.c
 > --- forward.c	1 Sep 2001 22:22:44 -0000	1.27
 > +++ forward.c	19 Nov 2001 22:34:00 -0000
 > @@ -94,10 +94,11 @@
 >  	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 @@
 >  		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 @@
 >  			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,9 +241,11 @@
 >  		case USE_SLEEP:
 >                  	(void) usleep(250000);
 >  	                clearerr(fp);
 +                       if (kq != -1)
 +                               action = ADD_EVENTS;
 
 It will help to break USE_SLEEP cycle when you remove symlink to fname
 and recreate it again. Of course it will break automatically when new
 data arrives but it may never happen.
 
 > +			break;
 > +		}
 >
 > -			if (Fflag && fileno(fp) != STDIN_FILENO &&
 > -			    stat(fname, &sb2) != -1) {
 > +		if (Fflag && fileno(fp) != STDIN_FILENO) {
 > +			if (stat(fname, &sb2) != -1) {
 >  				if (sb2.st_ino != sbp->st_ino ||
 >  				    sb2.st_dev != sbp->st_dev ||
 >  				    sb2.st_rdev != sbp->st_rdev ||
 > @@ -246,16 +253,15 @@
 >  					fp = freopen(fname, "r", fp);
 >  					if (fp == NULL) {
 >  						ierr();
 > -						break;
 > -					}
 > -					*sbp = sb2;
 > -					if (kq != -1)
 > +					} else {
 > +						*sbp = sb2;
 >  						action = ADD_EVENTS;
 > -				} else if (kq != -1) {
 > -					action = USE_KQUEUE;
 > +					}
 >  				}
 > +			} else {
 > +				/* file was rotated, wait until it reappears */
 > +				action = USE_SLEEP;
 >  			}
 > -			break;
 >  		}
 >  	}
 >  }
 >
 >
 
 There is still an issue when fname is renamed. Our tail will continue
 read data from the renamed file in USE_SLEEP cycle until a new fname
 appear. The old tail (RELENG_4_0_0_RELEASE f.e.) works in the same
 way. Imho it is not a correct behaviour but I am not quite sure.
 
 -- 
 Maxim Konovalov, MAcomnet, Internet-Intranet Dept., system engineer
 phone: +7 (095) 796-9079, mailto: maxim@macomnet.ru
 

From: Ian Dowse <iedowse@maths.tcd.ie>
To: Maxim Konovalov <maxim@macomnet.ru>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0) 
Date: Thu, 22 Nov 2001 00:39:28 +0000

 In message <20011122002632.O38176-100000@news1.macomnet.ru>, Maxim Konovalov wr
 ites:
 >
 >Looks OK for me except one minor problem, see below
 
 Yes, I expect there are still a few rough edges :-)
 
 >>  		case USE_SLEEP:
 >>                  	(void) usleep(250000);
 >>  	                clearerr(fp);
 >+                       if (kq != -1)
 >+                               action = ADD_EVENTS;
 >
 >It will help to break USE_SLEEP cycle when you remove symlink to fname
 >and recreate it again. Of course it will break automatically when new
 >data arrives but it may never happen.
 
 True, I think I noticed this problem also. I originally had it
 continuing to use kqueue while it was waiting for the file to
 reappear (i.e. there was no "else action = USE_SLEEP" for the failed
 stat case), but I was worried that in some cases the kevent() loop
 might spin where the file had really gone away (e.g NFS, forcibly
 unmounted filesystem etc). I guess another option would be to add
 a while loop around the stat() containing a sleep(), e.g
 
 	if (Fflag && ...) {
 		while (stat(...) != 0)
 			sleep(1);
 		if (sb2.st_ino != sbp->st_ino || ...) {
 			... freopen(...);
 			action = ADD_EVENTS;
 		}
 	}
 
 That would avoid a potential kevent() spin loop, and revert to the
 nicer situation where `action' can only change between sleep and
 kqueue via the ADD_EVENTS code. Any better suggestions welcome!
 
 I noticed, BTW, that tail -F doesn't work reliably on NFS (I assume
 it never did, and it is hard to fix). The problem is that stat()
 can succeed even after the file has been deleted due to cacheing,
 but as soon as you try to read, ESTALE is returned, so tail just
 exits with an error.
 
 Ian

From: Maxim Konovalov <maxim@macomnet.ru>
To: Ian Dowse <iedowse@maths.tcd.ie>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode
 changes (works in 4.0) 
Date: Sat, 24 Nov 2001 22:43:09 +0300 (MSK)

   This message is in MIME format.  The first part should be readable text,
   while the remaining parts are likely unreadable without MIME-aware tools.
   Send mail to mime@docserver.cac.washington.edu for more info.
 
 --0-1268137247-1006630989=:87876
 Content-Type: TEXT/PLAIN; charset=US-ASCII
 
 
 Hello Ian,
 
 Here is the final patch. I attached a cumulative patch which includes
 the changes below and changes for WARNS?=2.
 
 Index: forward.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/forward.c,v
 retrieving revision 1.27
 diff -u -r1.27 forward.c
 --- forward.c	1 Sep 2001 22:22:44 -0000	1.27
 +++ forward.c	24 Nov 2001 19:06:28 -0000
 @@ -94,10 +94,11 @@
  	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 @@
  		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 @@
  			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 @@
  		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;
  		}
  	}
  }
 
 - -maxim
 
 
 
 --0-1268137247-1006630989=:87876
 Content-Type: TEXT/PLAIN; charset=US-ASCII; name="tail.warns.diff"
 Content-Transfer-Encoding: BASE64
 Content-ID: <20011124224308.M87876@news1.macomnet.ru>
 Content-Description: 
 Content-Disposition: attachment; filename="tail.warns.diff"
 
 SW5kZXg6IE1ha2VmaWxlDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpSQ1Mg
 ZmlsZTogL2hvbWUvbmN2cy9zcmMvdXNyLmJpbi90YWlsL01ha2VmaWxlLHYN
 CnJldHJpZXZpbmcgcmV2aXNpb24gMS4xLjEuMQ0KZGlmZiAtdSAtcjEuMS4x
 LjEgTWFrZWZpbGUNCi0tLSBNYWtlZmlsZQkyNyBNYXkgMTk5NCAxMjozMjo0
 NSAtMDAwMAkxLjEuMS4xDQorKysgTWFrZWZpbGUJMjQgTm92IDIwMDEgMTk6
 MTI6MzMgLTAwMDANCkBAIC0yLDUgKzIsNiBAQA0KIA0KIFBST0c9CXRhaWwN
 CiBTUkNTPQlmb3J3YXJkLmMgbWlzYy5jIHJlYWQuYyByZXZlcnNlLmMgdGFp
 bC5jDQorV0FSTlM/PQkyDQogDQogLmluY2x1ZGUgPGJzZC5wcm9nLm1rPg0K
 SW5kZXg6IGV4dGVybi5oDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpSQ1Mg
 ZmlsZTogL2hvbWUvbmN2cy9zcmMvdXNyLmJpbi90YWlsL2V4dGVybi5oLHYN
 CnJldHJpZXZpbmcgcmV2aXNpb24gMS42DQpkaWZmIC11IC1yMS42IGV4dGVy
 bi5oDQotLS0gZXh0ZXJuLmgJMSBTZXAgMjAwMSAyMjoyMjo0NCAtMDAwMAkx
 LjYNCisrKyBleHRlcm4uaAkyNCBOb3YgMjAwMSAxOTozMToyNSAtMDAwMA0K
 QEAgLTM2LDcgKzM2LDcgQEANCiAgKi8NCiANCiAjZGVmaW5lCVdSKHAsIHNp
 emUpIGRvIHsgXA0KLQlpZiAod3JpdGUoU1RET1VUX0ZJTEVOTywgcCwgc2l6
 ZSkgIT0gc2l6ZSkgXA0KKwlpZiAod3JpdGUoU1RET1VUX0ZJTEVOTywgcCwg
 c2l6ZSkgIT0gKHNzaXplX3Qpc2l6ZSkgXA0KIAkJb2VycigpOyBcDQogCX0g
 d2hpbGUoMCkNCiANCkluZGV4OiBmb3J3YXJkLmMNCj09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09PT0NClJDUyBmaWxlOiAvaG9tZS9uY3ZzL3NyYy91c3IuYmluL3Rh
 aWwvZm9yd2FyZC5jLHYNCnJldHJpZXZpbmcgcmV2aXNpb24gMS4yNw0KZGlm
 ZiAtdSAtcjEuMjcgZm9yd2FyZC5jDQotLS0gZm9yd2FyZC5jCTEgU2VwIDIw
 MDEgMjI6MjI6NDQgLTAwMDAJMS4yNw0KKysrIGZvcndhcmQuYwkyNCBOb3Yg
 MjAwMSAxOToxNTowMiAtMDAwMA0KQEAgLTk0LDEwICs5NCwxMSBAQA0KIAlv
 ZmZfdCBvZmY7DQogCXN0cnVjdCBzdGF0ICpzYnA7DQogew0KLQlpbnQgY2gs
 IGtxID0gLTE7DQorCWludCBjaCwgbiwga3EgPSAtMTsNCiAJaW50IGFjdGlv
 biA9IFVTRV9TTEVFUDsNCiAJc3RydWN0IGtldmVudCBldlsyXTsNCiAJc3Ry
 dWN0IHN0YXQgc2IyOw0KKwlzdHJ1Y3QgdGltZXNwZWMgdHM7DQogDQogCXN3
 aXRjaChzdHlsZSkgew0KIAljYXNlIEZCWVRFUzoNCkBAIC0xNzAsNiArMTcx
 LDkgQEANCiAJCQlpZiAobGluZXMoZnAsIG9mZikpDQogCQkJCXJldHVybjsN
 CiAJCWJyZWFrOw0KKwljYXNlIE5PVFNFVDoNCisJY2FzZSBSRVZFUlNFOg0K
 KwkJYnJlYWs7DQogCX0NCiANCiAJaWYgKGZmbGFnKSB7DQpAQCAtMTkzLDkg
 KzE5NywxMCBAQA0KIAkJY2xlYXJlcnIoZnApOw0KIA0KIAkJc3dpdGNoIChh
 Y3Rpb24pIHsNCi0JCWNhc2UgQUREX0VWRU5UUzogew0KLQkJCWludCBuID0g
 MDsNCi0JCQlzdHJ1Y3QgdGltZXNwZWMgdHMgPSB7IDAsIDAgfTsNCisJCWNh
 c2UgQUREX0VWRU5UUzoNCisJCQluID0gMDsNCisJCQl0cy50dl9zZWMgPSAw
 Ow0KKwkJCXRzLnR2X25zZWMgPSAwOw0KIA0KIAkJCWlmIChGZmxhZyAmJiBm
 aWxlbm8oZnApICE9IFNURElOX0ZJTEVOTykgew0KIAkJCQlFVl9TRVQoJmV2
 W25dLCBmaWxlbm8oZnApLCBFVkZJTFRfVk5PREUsDQpAQCAtMjA4LDI0ICsy
 MTMsMjcgQEANCiAJCQluKys7DQogDQogCQkJaWYgKGtldmVudChrcSwgZXYs
 IG4sIE5VTEwsIDAsICZ0cykgPCAwKSB7DQotCQkJCWNsb3NlKGtxKTsNCi0J
 CQkJa3EgPSAtMTsNCiAJCQkJYWN0aW9uID0gVVNFX1NMRUVQOw0KIAkJCX0g
 ZWxzZSB7DQogCQkJCWFjdGlvbiA9IFVTRV9LUVVFVUU7DQogCQkJfQ0KIAkJ
 CWJyZWFrOw0KLQkJfQ0KIA0KIAkJY2FzZSBVU0VfS1FVRVVFOg0KLQkJCWlm
 IChrZXZlbnQoa3EsIE5VTEwsIDAsIGV2LCAxLCBOVUxMKSA8IDApDQorCQkJ
 dHMudHZfc2VjID0gMTsNCisJCQl0cy50dl9uc2VjID0gMDsNCisJCQkvKg0K
 KwkJCSAqIEluIHRoZSAtRiBjYXNlIHdlIHNldCBhIHRpbWVvdXQgdG8gZW5z
 dXJlIHRoYXQNCisJCQkgKiB3ZSByZS1zdGF0IHRoZSBmaWxlIGF0IGxlYXN0
 IG9uY2UgZXZlcnkgc2Vjb25kLg0KKwkJCSAqLw0KKwkJCW4gPSBrZXZlbnQo
 a3EsIE5VTEwsIDAsIGV2LCAxLCBGZmxhZyA/ICZ0cyA6IE5VTEwpOw0KKwkJ
 CWlmIChuIDwgMCkNCiAJCQkJZXJyKDEsICJrZXZlbnQiKTsNCi0NCi0JCQlp
 ZiAoZXYtPmZpbHRlciA9PSBFVkZJTFRfVk5PREUpIHsNCi0JCQkJLyogZmls
 ZSB3YXMgcm90YXRlZCwgd2FpdCB1bnRpbCBpdCByZWFwcGVhcnMgKi8NCi0J
 CQkJYWN0aW9uID0gVVNFX1NMRUVQOw0KLQkJCX0gZWxzZSBpZiAoZXYtPmRh
 dGEgPCAwKSB7DQotCQkJCS8qIGZpbGUgc2hyYW5rLCByZXBvc2l0aW9uIHRv
 IGVuZCAqLw0KKwkJCWlmIChuID09IDApIHsNCisJCQkJLyogdGltZW91dCAq
 Lw0KKwkJCQlicmVhazsNCisJCQl9IGVsc2UgaWYgKGV2LT5maWx0ZXIgPT0g
 RVZGSUxUX1JFQUQgJiYgZXYtPmRhdGEgPCAwKSB7DQorCQkJCSAvKiBmaWxl
 IHNocmFuaywgcmVwb3NpdGlvbiB0byBlbmQgKi8NCiAJCQkJaWYgKGZzZWVr
 byhmcCwgKG9mZl90KTAsIFNFRUtfRU5EKSA9PSAtMSkgew0KIAkJCQkJaWVy
 cigpOw0KIAkJCQkJcmV0dXJuOw0KQEAgLTIzNiwyNiArMjQ0LDI1IEBADQog
 CQljYXNlIFVTRV9TTEVFUDoNCiAgICAgICAgICAgICAgICAgCSh2b2lkKSB1
 c2xlZXAoMjUwMDAwKTsNCiAJICAgICAgICAgICAgICAgIGNsZWFyZXJyKGZw
 KTsNCisJCQlicmVhazsNCisJCX0NCiANCi0JCQlpZiAoRmZsYWcgJiYgZmls
 ZW5vKGZwKSAhPSBTVERJTl9GSUxFTk8gJiYNCi0JCQkgICAgc3RhdChmbmFt
 ZSwgJnNiMikgIT0gLTEpIHsNCi0JCQkJaWYgKHNiMi5zdF9pbm8gIT0gc2Jw
 LT5zdF9pbm8gfHwNCi0JCQkJICAgIHNiMi5zdF9kZXYgIT0gc2JwLT5zdF9k
 ZXYgfHwNCi0JCQkJICAgIHNiMi5zdF9yZGV2ICE9IHNicC0+c3RfcmRldiB8
 fA0KLQkJCQkgICAgc2IyLnN0X25saW5rID09IDApIHsNCi0JCQkJCWZwID0g
 ZnJlb3BlbihmbmFtZSwgInIiLCBmcCk7DQotCQkJCQlpZiAoZnAgPT0gTlVM
 TCkgew0KLQkJCQkJCWllcnIoKTsNCi0JCQkJCQlicmVhazsNCi0JCQkJCX0N
 CisJCWlmIChGZmxhZyAmJiBmaWxlbm8oZnApICE9IFNURElOX0ZJTEVOTykg
 ew0KKwkJCXdoaWxlIChzdGF0KGZuYW1lLCAmc2IyKSAhPSAwKQ0KKwkJCQkv
 KiBmaWxlIHdhcyByb3RhdGVkLCB3YWl0IHVudGlsIGl0IHJlYXBwZWFycyAq
 Lw0KKwkJCQkodm9pZClzbGVlcCgxKTsNCisJCQlpZiAoc2IyLnN0X2lubyAh
 PSBzYnAtPnN0X2lubyB8fA0KKwkJCSAgICBzYjIuc3RfZGV2ICE9IHNicC0+
 c3RfZGV2IHx8DQorCQkJICAgIHNiMi5zdF9yZGV2ICE9IHNicC0+c3RfcmRl
 diB8fA0KKwkJCSAgICBzYjIuc3RfbmxpbmsgPT0gMCkgew0KKwkJCQlmcCA9
 IGZyZW9wZW4oZm5hbWUsICJyIiwgZnApOw0KKwkJCQlpZiAoZnAgPT0gTlVM
 TCkgew0KKwkJCQkJaWVycigpOw0KKwkJCQl9IGVsc2Ugew0KIAkJCQkJKnNi
 cCA9IHNiMjsNCi0JCQkJCWlmIChrcSAhPSAtMSkNCi0JCQkJCQlhY3Rpb24g
 PSBBRERfRVZFTlRTOw0KLQkJCQl9IGVsc2UgaWYgKGtxICE9IC0xKSB7DQot
 CQkJCQlhY3Rpb24gPSBVU0VfS1FVRVVFOw0KKwkJCQkJYWN0aW9uID0gQURE
 X0VWRU5UUzsNCiAJCQkJfQ0KIAkJCX0NCi0JCQlicmVhazsNCiAJCX0NCiAJ
 fQ0KIH0NCkluZGV4OiByZWFkLmMNCj09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0N
 ClJDUyBmaWxlOiAvaG9tZS9uY3ZzL3NyYy91c3IuYmluL3RhaWwvcmVhZC5j
 LHYNCnJldHJpZXZpbmcgcmV2aXNpb24gMS44DQpkaWZmIC11IC1yMS44IHJl
 YWQuYw0KLS0tIHJlYWQuYwkzIERlYyAyMDAwIDE3OjA1OjQ1IC0wMDAwCTEu
 OA0KKysrIHJlYWQuYwkyNCBOb3YgMjAwMSAxOTozMzo0MSAtMDAwMA0KQEAg
 LTExNSw3ICsxMTUsNyBAQA0KIAl9IGVsc2Ugew0KIAkJaWYgKHdyYXAgJiYg
 KGxlbiA9IGVwIC0gcCkpDQogCQkJV1IocCwgbGVuKTsNCi0JCWlmIChsZW4g
 PSBwIC0gc3ApDQorCQlpZiAoKGxlbiA9IHAgLSBzcCkpDQogCQkJV1Ioc3As
 IGxlbik7DQogCX0NCiAJcmV0dXJuIDA7DQpAQCAtMTQwLDE1ICsxNDAsMTUg
 QEANCiAJCXVfaW50IGJsZW47DQogCQl1X2ludCBsZW47DQogCQljaGFyICps
 Ow0KLQl9ICpsaW5lczsNCisJfSAqc2xpbmVzOw0KIAlpbnQgY2g7DQogCWNo
 YXIgKnA7DQogCWludCBibGVuLCBjbnQsIHJlY25vLCB3cmFwOw0KIAljaGFy
 ICpzcDsNCiANCi0JaWYgKChsaW5lcyA9IG1hbGxvYyhvZmYgKiBzaXplb2Yo
 KmxpbmVzKSkpID09IE5VTEwpDQorCWlmICgoc2xpbmVzID0gbWFsbG9jKG9m
 ZiAqIHNpemVvZigqc2xpbmVzKSkpID09IE5VTEwpDQogCQllcnIoMSwgIm1h
 bGxvYyIpOw0KLQliemVybyhsaW5lcywgb2ZmICogc2l6ZW9mKCpsaW5lcykp
 Ow0KKwliemVybyhzbGluZXMsIG9mZiAqIHNpemVvZigqc2xpbmVzKSk7DQog
 CXNwID0gTlVMTDsNCiAJYmxlbiA9IGNudCA9IHJlY25vID0gd3JhcCA9IDA7
 DQogDQpAQCAtMTYwLDEzICsxNjAsMTMgQEANCiAJCX0NCiAJCSpwKysgPSBj
 aDsNCiAJCWlmIChjaCA9PSAnXG4nKSB7DQotCQkJaWYgKGxpbmVzW3JlY25v
 XS5ibGVuIDwgY250KSB7DQotCQkJCWxpbmVzW3JlY25vXS5ibGVuID0gY250
 ICsgMjU2Ow0KLQkJCQlpZiAoKGxpbmVzW3JlY25vXS5sID0gcmVhbGxvYyhs
 aW5lc1tyZWNub10ubCwNCi0JCQkJICAgIGxpbmVzW3JlY25vXS5ibGVuKSkg
 PT0gTlVMTCkNCisJCQlpZiAoc2xpbmVzW3JlY25vXS5ibGVuIDwgKHVfaW50
 KWNudCkgew0KKwkJCQlzbGluZXNbcmVjbm9dLmJsZW4gPSBjbnQgKyAyNTY7
 DQorCQkJCWlmICgoc2xpbmVzW3JlY25vXS5sID0gcmVhbGxvYyhzbGluZXNb
 cmVjbm9dLmwsDQorCQkJCSAgICBzbGluZXNbcmVjbm9dLmJsZW4pKSA9PSBO
 VUxMKQ0KIAkJCQkJZXJyKDEsICJyZWFsbG9jIik7DQogCQkJfQ0KLQkJCWJj
 b3B5KHNwLCBsaW5lc1tyZWNub10ubCwgbGluZXNbcmVjbm9dLmxlbiA9IGNu
 dCk7DQorCQkJYmNvcHkoc3AsIHNsaW5lc1tyZWNub10ubCwgc2xpbmVzW3Jl
 Y25vXS5sZW4gPSBjbnQpOw0KIAkJCWNudCA9IDA7DQogCQkJcCA9IHNwOw0K
 IAkJCWlmICgrK3JlY25vID09IG9mZikgew0KQEAgLTE4MCw4ICsxODAsOCBA
 QA0KIAkJcmV0dXJuIDE7DQogCX0NCiAJaWYgKGNudCkgew0KLQkJbGluZXNb
 cmVjbm9dLmwgPSBzcDsNCi0JCWxpbmVzW3JlY25vXS5sZW4gPSBjbnQ7DQor
 CQlzbGluZXNbcmVjbm9dLmwgPSBzcDsNCisJCXNsaW5lc1tyZWNub10ubGVu
 ID0gY250Ow0KIAkJaWYgKCsrcmVjbm8gPT0gb2ZmKSB7DQogCQkJd3JhcCA9
 IDE7DQogCQkJcmVjbm8gPSAwOw0KQEAgLTE5MCwxNiArMTkwLDE2IEBADQog
 DQogCWlmIChyZmxhZykgew0KIAkJZm9yIChjbnQgPSByZWNubyAtIDE7IGNu
 dCA+PSAwOyAtLWNudCkNCi0JCQlXUihsaW5lc1tjbnRdLmwsIGxpbmVzW2Nu
 dF0ubGVuKTsNCisJCQlXUihzbGluZXNbY250XS5sLCBzbGluZXNbY250XS5s
 ZW4pOw0KIAkJaWYgKHdyYXApDQogCQkJZm9yIChjbnQgPSBvZmYgLSAxOyBj
 bnQgPj0gcmVjbm87IC0tY250KQ0KLQkJCQlXUihsaW5lc1tjbnRdLmwsIGxp
 bmVzW2NudF0ubGVuKTsNCisJCQkJV1Ioc2xpbmVzW2NudF0ubCwgc2xpbmVz
 W2NudF0ubGVuKTsNCiAJfSBlbHNlIHsNCiAJCWlmICh3cmFwKQ0KIAkJCWZv
 ciAoY250ID0gcmVjbm87IGNudCA8IG9mZjsgKytjbnQpDQotCQkJCVdSKGxp
 bmVzW2NudF0ubCwgbGluZXNbY250XS5sZW4pOw0KKwkJCQlXUihzbGluZXNb
 Y250XS5sLCBzbGluZXNbY250XS5sZW4pOw0KIAkJZm9yIChjbnQgPSAwOyBj
 bnQgPCByZWNubzsgKytjbnQpDQotCQkJV1IobGluZXNbY250XS5sLCBsaW5l
 c1tjbnRdLmxlbik7DQorCQkJV1Ioc2xpbmVzW2NudF0ubCwgc2xpbmVzW2Nu
 dF0ubGVuKTsNCiAJfQ0KIAlyZXR1cm4gMDsNCiB9DQpJbmRleDogcmV2ZXJz
 ZS5jDQo9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09DQpSQ1MgZmlsZTogL2hvbWUv
 bmN2cy9zcmMvdXNyLmJpbi90YWlsL3JldmVyc2UuYyx2DQpyZXRyaWV2aW5n
 IHJldmlzaW9uIDEuMTINCmRpZmYgLXUgLXIxLjEyIHJldmVyc2UuYw0KLS0t
 IHJldmVyc2UuYwkxIFNlcCAyMDAxIDIyOjIyOjQ0IC0wMDAwCTEuMTINCisr
 KyByZXZlcnNlLmMJMjQgTm92IDIwMDEgMTk6MzQ6MTggLTAwMDANCkBAIC0x
 MDEsNiArMTAxLDggQEANCiAJCWNhc2UgUkVWRVJTRToNCiAJCQlyX2J1Zihm
 cCk7DQogCQkJYnJlYWs7DQorCQljYXNlIE5PVFNFVDoNCisJCQlicmVhazsN
 CiAJCX0NCiB9DQogDQpJbmRleDogdGFpbC5jDQo9PT09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09DQpSQ1MgZmlsZTogL2hvbWUvbmN2cy9zcmMvdXNyLmJpbi90YWls
 L3RhaWwuYyx2DQpyZXRyaWV2aW5nIHJldmlzaW9uIDEuMTINCmRpZmYgLXUg
 LXIxLjEyIHRhaWwuYw0KLS0tIHRhaWwuYwkyIE9jdCAyMDAxIDA2OjIyOjAx
 IC0wMDAwCTEuMTINCisrKyB0YWlsLmMJMjQgTm92IDIwMDEgMTk6MzY6MTYg
 LTAwMDANCkBAIC0xNjksNyArMTY5LDcgQEANCiAJfQ0KIA0KIAlpZiAoKmFy
 Z3YpDQotCQlmb3IgKGZpcnN0ID0gMTsgZm5hbWUgPSAqYXJndisrOykgew0K
 KwkJZm9yIChmaXJzdCA9IDE7IChmbmFtZSA9ICphcmd2KyspOykgew0KIAkJ
 CWlmICgoZnAgPSBmb3BlbihmbmFtZSwgInIiKSkgPT0gTlVMTCB8fA0KIAkJ
 CSAgICBmc3RhdChmaWxlbm8oZnApLCAmc2IpKSB7DQogCQkJCWllcnIoKTsN
 CkBAIC0xODksNyArMTg5LDcgQEANCiAJCQkodm9pZClmY2xvc2UoZnApOw0K
 IAkJfQ0KIAllbHNlIHsNCi0JCWZuYW1lID0gInN0ZGluIjsNCisJCWZuYW1l
 ID0gc3RyZHVwKCJzdGRpbiIpOw0KIA0KIAkJaWYgKGZzdGF0KGZpbGVubyhz
 dGRpbiksICZzYikpIHsNCiAJCQlpZXJyKCk7DQpAQCAtMjI3LDcgKzIyNyw3
 IEBADQogCXNpemVfdCBsZW47DQogCWNoYXIgKnN0YXJ0Ow0KIA0KLQl3aGls
 ZSAoYXAgPSAqKythcmd2KSB7DQorCXdoaWxlICgoYXAgPSAqKythcmd2KSkg
 ew0KIAkJLyogUmV0dXJuIGlmICItLSIgb3Igbm90IGFuIG9wdGlvbiBvZiBh
 bnkgZm9ybS4gKi8NCiAJCWlmIChhcFswXSAhPSAnLScpIHsNCiAJCQlpZiAo
 YXBbMF0gIT0gJysnKQ0K
 --0-1268137247-1006630989=:87876--

From: Ian Dowse <iedowse@maths.tcd.ie>
To: Maxim Konovalov <maxim@macomnet.ru>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode changes (works in 4.0) 
Date: Sun, 25 Nov 2001 18:15:04 +0000

 In message <20011124220954.I87876-200000@news1.macomnet.ru>, Maxim Konovalov wr
 ites:
 >Hello Ian,
 >
 >Here is the final patch.
 
 Committed, thanks!
 
 >I attached a cumulative patch which includes
 >the changes below and changes for WARNS?=2.
 
 Thanks, I'll commit this separately. I just had a glance at that patch,
 and one thing I noticed was that where gcc complains about something
 like
 
 	while (c = *p++) {
 
 it's better to take the opportunity to make the code more readable
 rather than just adding brackets. e.g, change it to:
 
 	while ((c = *p++) != '\0') {
 
 Also, with constness warnings, try to avoid adding code to strdup
 a string unless you actually need to modify it (e.g. make the
 pointer const if possible). I didn't check the example carefully
 though, so what you did may be the easiest way.
 
 Ian

From: Maxim Konovalov <maxim@macomnet.ru>
To: Ian Dowse <iedowse@maths.tcd.ie>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode
 changes (works in 4.0) 
Date: Sun, 25 Nov 2001 23:14:03 +0300 (MSK)

 Hello Ian,
 
 WARNS?=2 patch:
 
 Index: Makefile
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/Makefile,v
 retrieving revision 1.1.1.1
 diff -u -r1.1.1.1 Makefile
 --- Makefile	27 May 1994 12:32:45 -0000	1.1.1.1
 +++ Makefile	25 Nov 2001 19:57:39 -0000
 @@ -2,5 +2,6 @@
 
  PROG=	tail
  SRCS=	forward.c misc.c read.c reverse.c tail.c
 +WARNS?=	2
 
  .include <bsd.prog.mk>
 Index: extern.h
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/extern.h,v
 retrieving revision 1.6
 diff -u -r1.6 extern.h
 --- extern.h	1 Sep 2001 22:22:44 -0000	1.6
 +++ extern.h	25 Nov 2001 20:00:04 -0000
 @@ -36,7 +36,7 @@
   */
 
  #define	WR(p, size) do { \
 -	if (write(STDOUT_FILENO, p, size) != size) \
 +	if (write(STDOUT_FILENO, p, size) != (ssize_t)size) \
  		oerr(); \
  	} while(0)
 
 Index: forward.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/forward.c,v
 retrieving revision 1.28
 diff -u -r1.28 forward.c
 --- forward.c	25 Nov 2001 18:03:28 -0000	1.28
 +++ forward.c	25 Nov 2001 19:58:20 -0000
 @@ -171,6 +171,9 @@
  			if (lines(fp, off))
  				return;
  		break;
 +	case REVERSE:
 +	case NOTSET:
 +		break;
  	}
 
  	if (fflag) {
 Index: read.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/read.c,v
 retrieving revision 1.8
 diff -u -r1.8 read.c
 --- read.c	3 Dec 2000 17:05:45 -0000	1.8
 +++ read.c	25 Nov 2001 20:00:26 -0000
 @@ -115,7 +115,7 @@
  	} else {
  		if (wrap && (len = ep - p))
  			WR(p, len);
 -		if (len = p - sp)
 +		if ((len = p - sp) != 0)
  			WR(sp, len);
  	}
  	return 0;
 @@ -140,15 +140,15 @@
  		u_int blen;
  		u_int len;
  		char *l;
 -	} *lines;
 +	} *slines;
  	int ch;
  	char *p;
  	int blen, cnt, recno, wrap;
  	char *sp;
 
 -	if ((lines = malloc(off * sizeof(*lines))) == NULL)
 +	if ((slines = malloc(off * sizeof(*slines))) == NULL)
  		err(1, "malloc");
 -	bzero(lines, off * sizeof(*lines));
 +	bzero(slines, off * sizeof(*slines));
  	sp = NULL;
  	blen = cnt = recno = wrap = 0;
 
 @@ -160,13 +160,13 @@
  		}
  		*p++ = ch;
  		if (ch == '\n') {
 -			if (lines[recno].blen < cnt) {
 -				lines[recno].blen = cnt + 256;
 -				if ((lines[recno].l = realloc(lines[recno].l,
 -				    lines[recno].blen)) == NULL)
 +			if (slines[recno].blen < (u_int)cnt) {
 +				slines[recno].blen = cnt + 256;
 +				if ((slines[recno].l = realloc(slines[recno].l,
 +				    slines[recno].blen)) == NULL)
  					err(1, "realloc");
  			}
 -			bcopy(sp, lines[recno].l, lines[recno].len = cnt);
 +			bcopy(sp, slines[recno].l, slines[recno].len = cnt);
  			cnt = 0;
  			p = sp;
  			if (++recno == off) {
 @@ -180,8 +180,8 @@
  		return 1;
  	}
  	if (cnt) {
 -		lines[recno].l = sp;
 -		lines[recno].len = cnt;
 +		slines[recno].l = sp;
 +		slines[recno].len = cnt;
  		if (++recno == off) {
  			wrap = 1;
  			recno = 0;
 @@ -190,16 +190,16 @@
 
  	if (rflag) {
  		for (cnt = recno - 1; cnt >= 0; --cnt)
 -			WR(lines[cnt].l, lines[cnt].len);
 +			WR(slines[cnt].l, slines[cnt].len);
  		if (wrap)
  			for (cnt = off - 1; cnt >= recno; --cnt)
 -				WR(lines[cnt].l, lines[cnt].len);
 +				WR(slines[cnt].l, slines[cnt].len);
  	} else {
  		if (wrap)
  			for (cnt = recno; cnt < off; ++cnt)
 -				WR(lines[cnt].l, lines[cnt].len);
 +				WR(slines[cnt].l, slines[cnt].len);
  		for (cnt = 0; cnt < recno; ++cnt)
 -			WR(lines[cnt].l, lines[cnt].len);
 +			WR(slines[cnt].l, slines[cnt].len);
  	}
  	return 0;
  }
 Index: reverse.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/reverse.c,v
 retrieving revision 1.12
 diff -u -r1.12 reverse.c
 --- reverse.c	1 Sep 2001 22:22:44 -0000	1.12
 +++ reverse.c	25 Nov 2001 20:00:51 -0000
 @@ -101,6 +101,8 @@
  		case REVERSE:
  			r_buf(fp);
  			break;
 +		case NOTSET:
 +			break;
  		}
  }
 
 Index: tail.c
 ===================================================================
 RCS file: /home/ncvs/src/usr.bin/tail/tail.c,v
 retrieving revision 1.12
 diff -u -r1.12 tail.c
 --- tail.c	2 Oct 2001 06:22:01 -0000	1.12
 +++ tail.c	25 Nov 2001 20:09:59 -0000
 @@ -169,7 +169,7 @@
  	}
 
  	if (*argv)
 -		for (first = 1; fname = *argv++;) {
 +		for (first = 1; (fname = *argv++) != '\0';) {
  			if ((fp = fopen(fname, "r")) == NULL ||
  			    fstat(fileno(fp), &sb)) {
  				ierr();
 @@ -189,7 +189,7 @@
  			(void)fclose(fp);
  		}
  	else {
 -		fname = "stdin";
 +		(const char *)fname = "stdin";
 
  		if (fstat(fileno(stdin), &sb)) {
  			ierr();
 @@ -227,7 +227,7 @@
  	size_t len;
  	char *start;
 
 -	while (ap = *++argv) {
 +	while ((ap = *++argv) != '\0') {
  		/* Return if "--" or not an option of any form. */
  		if (ap[0] != '-') {
  			if (ap[0] != '+')
 

From: Maxim Konovalov <maxim@macomnet.ru>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: bin/24955:/usr/bin/tail -F in 4.1+ doesn't work if file inode
 changes (works in 4.0)
Date: Sat, 19 Jan 2002 20:05:24 +0300 (MSK)

 Please close this PR, a fix was committed to -current and -stable.
 
 -- 
 Maxim Konovalov, MAcomnet, Internet-Intranet Dept., system engineer
 phone: +7 (095) 796-9079, mailto: maxim@macomnet.ru
 
State-Changed-From-To: open->closed 
State-Changed-By: iedowse 
State-Changed-When: Sat Jan 19 11:02:48 PST 2002 
State-Changed-Why:  

Fixed in both -current and -stable. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=24955 
>Unformatted:
