Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Jan 2001 04:00:03 -0800 (PST)
From:      David Malone <dwmalone@maths.tcd.ie>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/24730: tail -f barfs on files bigger than 2 Gig
Message-ID:  <200101301200.f0UC03w12619@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/24730; it has been noted by GNATS.

From: David Malone <dwmalone@maths.tcd.ie>
To: chris@zeus.foote.com.au
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/24730: tail -f barfs on files bigger than 2 Gig
Date: Tue, 30 Jan 2001 11:55:57 +0000

 On Tue, Jan 30, 2001 at 01:21:15AM -0800, chris@zeus.foote.com.au wrote:
 
 > >Synopsis:       tail -f barfs on files bigger than 2 Gig
 
 I've been waiting for people to test the patch in:
 
 	http://www.freebsd.org/cgi/query-pr.cgi?pr=14786
 
 for a while - I've had atleast one report of success. The patch
 below is against -current, and also fixes "tail -r".  Please let
 me know if this patch fixes the problems you're seeing.
 
 	David.
 
 
 Index: usr.bin/tail/extern.h
 ===================================================================
 RCS file: /cvs/FreeBSD-CVS/src/usr.bin/tail/extern.h,v
 retrieving revision 1.4
 diff -u -7 -r1.4 extern.h
 --- usr.bin/tail/extern.h	1998/04/06 16:13:48	1.4
 +++ usr.bin/tail/extern.h	2000/12/16 14:11:30
 @@ -29,17 +29,20 @@
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   *
   *	@(#)extern.h	8.1 (Berkeley) 6/6/93
   */
  
 -#define	WR(p, size) \
 +#define	WR(p, size) do { \
  	if (write(STDOUT_FILENO, p, size) != size) \
 -		oerr();
 +		oerr(); \
 +	} while(0)
 +
 +#define TAILMAPLEN (4<<20)
  
  enum STYLE { NOTSET = 0, FBYTES, FLINES, RBYTES, RLINES, REVERSE };
  
  void forward __P((FILE *, enum STYLE, long, struct stat *));
  void reverse __P((FILE *, enum STYLE, long, struct stat *));
  
  int bytes __P((FILE *, off_t));
 Index: usr.bin/tail/forward.c
 ===================================================================
 RCS file: /cvs/FreeBSD-CVS/src/usr.bin/tail/forward.c,v
 retrieving revision 1.17
 diff -u -7 -r1.17 forward.c
 --- usr.bin/tail/forward.c	2000/12/03 17:05:44	1.17
 +++ usr.bin/tail/forward.c	2000/12/16 14:12:07
 @@ -265,45 +265,73 @@
   */
  static void
  rlines(fp, off, sbp)
  	FILE *fp;
  	long off;
  	struct stat *sbp;
  {
 -	off_t size;
 +	off_t size, curoff;
  	char *p;
  	char *start;
 +	off_t mapoff;
 +	size_t maplen;
  
  	if (!(size = sbp->st_size))
  		return;
  
 -	if (size > SIZE_T_MAX) {
 -		errno = EFBIG;
 -		ierr();
 -		return;
 +	start = NULL;
 +	for (curoff = size - 1, mapoff = size; curoff >= 0; curoff--) {
 +		if (curoff < mapoff) {
 +			if (start && munmap(start, maplen)) {
 +				ierr();
 +				return;
 +			}
 +			mapoff = curoff & (~(TAILMAPLEN-1));
 +			maplen = curoff - mapoff + 1;
 +			if ((start = mmap(NULL, maplen, PROT_READ,
 +			    MAP_SHARED, fileno(fp), mapoff)) == MAP_FAILED) {
 +				ierr();
 +				return;
 +			}
 +		}
 +		p = start + (curoff - mapoff);
 +		/* Last char is special, ignore whether newline or not. */
 +		if (*p == '\n' && curoff != size -1 && !--off) {
 +			curoff++;
 +			break;
 +		}
  	}
  
 -	if ((start = mmap(NULL, (size_t)size,
 -	    PROT_READ, MAP_SHARED, fileno(fp), (off_t)0)) == MAP_FAILED) {
 -		ierr();
 -		return;
 -	}
 +	if (curoff < 0)
 +		curoff = 0;
  
 -	/* Last char is special, ignore whether newline or not. */
 -	for (p = start + size - 1; --size;)
 -		if (*--p == '\n' && !--off) {
 -			++p;
 -			break;
 +	while (curoff != size) {
 +		if (curoff < mapoff || curoff >= mapoff + maplen) {
 +			if (start && munmap(start, maplen)) {
 +				ierr();
 +				return;
 +			}
 +			mapoff = curoff & (~(TAILMAPLEN-1));
 +			maplen = TAILMAPLEN;
 +			if (mapoff + maplen > size)
 +				maplen = size - mapoff;
 +			if ((start = mmap(NULL, maplen, PROT_READ,
 +			    MAP_SHARED, fileno(fp), mapoff)) == MAP_FAILED) {
 +				ierr();
 +				return;
 +			}
  		}
 +		p = start + (curoff - mapoff);
 +		WR(p, maplen - (curoff - mapoff));
 +		curoff += maplen - (curoff - mapoff);
 +	}
  
  	/* Set the file pointer to reflect the length displayed. */
 -	size = sbp->st_size - size;
 -	WR(p, size);
 -	if (fseek(fp, (long)sbp->st_size, SEEK_SET) == -1) {
 +	if (fseeko(fp, sbp->st_size, SEEK_SET) == -1) {
  		ierr();
  		return;
  	}
 -	if (munmap(start, (size_t)sbp->st_size)) {
 +	if (start != NULL && munmap(start, maplen)) {
  		ierr();
  		return;
  	}
  }
 Index: usr.bin/tail/reverse.c
 ===================================================================
 RCS file: /cvs/FreeBSD-CVS/src/usr.bin/tail/reverse.c,v
 retrieving revision 1.10
 diff -u -7 -r1.10 reverse.c
 --- usr.bin/tail/reverse.c	2000/12/03 17:05:45	1.10
 +++ usr.bin/tail/reverse.c	2000/12/16 14:54:55
 @@ -110,51 +110,90 @@
  static void
  r_reg(fp, style, off, sbp)
  	FILE *fp;
  	enum STYLE style;
  	long off;
  	struct stat *sbp;
  {
 -	off_t size;
 +	off_t size, curoff;
  	int llen;
  	char *p;
  	char *start;
 +	off_t mapoff;
 +	size_t maplen;
  
  	if (!(size = sbp->st_size))
  		return;
  
 -	if (size > SIZE_T_MAX) {
 -		errno = EFBIG;
 -		ierr();
 -		return;
 -	}
 -
 -	if ((start = mmap(NULL, (size_t)size,
 -	    PROT_READ, MAP_SHARED, fileno(fp), (off_t)0)) == MAP_FAILED) {
 -		ierr();
 -		return;
 -	}
 -	p = start + size - 1;
 -
  	if (style == RBYTES && off < size)
  		size = off;
  
 -	/* Last char is special, ignore whether newline or not. */
 -	for (llen = 1; --size; ++llen)
 -		if (*--p == '\n') {
 -			WR(p + 1, llen);
 +	start = NULL;
 +	for (llen = 0, curoff = size - 1, mapoff = size; curoff >= 0; ++llen, curoff--) {
 +		if (curoff < mapoff) {
 +			if (start && munmap(start, maplen)) {
 +				ierr();
 +				return;
 +			}
 +			mapoff = curoff & (~(TAILMAPLEN-1));
 +			maplen = curoff - mapoff + 1;
 +			if ((start = mmap(NULL, maplen, PROT_READ,
 +			    MAP_SHARED, fileno(fp), mapoff)) == MAP_FAILED) {
 +				ierr();
 +				return;
 +			}
 +		}
 +		p = start + (curoff - mapoff);
 +		/* Last char is special, ignore whether newline or not. */
 +		if (*p == '\n' && curoff != size - 1) {
 +			if (curoff + 1 + llen <= mapoff + maplen)
 +				WR(p + 1, llen);
 +			else {
 +				char *q;
 +				if ((q = mmap(NULL, llen, PROT_READ, MAP_SHARED,
 +				    fileno(fp), curoff + 1)) ==  MAP_FAILED) {
 +					ierr();
 +					return;
 +				}
 +				fprintf(stderr, "Got 1\n");
 +				WR(q, llen);
 +				if (munmap(q, llen)) {
 +					ierr();
 +					return;
 +				}
 +			}
  			llen = 0;
  			if (style == RLINES && !--off) {
  				++p;
  				break;
  			}
 +		}
 +	}
 +	if (curoff < 0)
 +		curoff = 0;
 +
 +	if (llen) {
 +		if (curoff + llen <= mapoff + maplen)
 +			WR(p, llen);
 +		else {
 +			char *q;
 +			if ((q = mmap(NULL, llen, PROT_READ, MAP_SHARED,
 +			    fileno(fp), curoff)) ==  MAP_FAILED) {
 +				ierr();
 +				return;
 +			}
 +			fprintf(stderr, "Got 2\n");
 +			WR(q, llen);
 +			if (munmap(q, llen)) {
 +				ierr();
 +				return;
 +			}
  		}
 -	if (llen)
 -		WR(p, llen);
 -	if (munmap(start, (size_t)sbp->st_size))
 +	}
 +	if (start != NULL && munmap(start, maplen))
  		ierr();
  }
  
  typedef struct bf {
  	struct bf *next;
  	struct bf *prev;
  	int len;
 


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200101301200.f0UC03w12619>