Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Jan 2000 05:40:02 -0800 (PST)
From:      David Malone <dwmalone@maths.tcd.ie>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/14786: tail breaks on large files
Message-ID:  <200001111340.FAA19429@freefall.freebsd.org>

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

From: David Malone <dwmalone@maths.tcd.ie>
To: freebsd-gnats-submit@FreeBSD.org, chris@netmonger.net
Cc:  
Subject: Re: bin/14786: tail breaks on large files
Date: Tue, 11 Jan 2000 13:39:17 +0000

 I've produced a patch which works by mapping 4MB chunks of the file
 at a time, instead of trying to map the whole file. It seems to work
 reasonably well, and seems to produce the same results as the original
 version of tail - other than on large files where it works correctly.
 
 "tail -r" also suffers from similar problems, which I could produce
 a patch for if people think this is the correct way to do things.
 
 	David.
 
 --- forward.c.orig	Mon Dec 13 09:40:31 1999
 +++ forward.c	Mon Dec 13 01:11:42 1999
 @@ -207,9 +207,11 @@
  	long off;
  	struct stat *sbp;
  {
 -	register off_t size;
 +	register off_t size, curoff;
  	register char *p;
  	char *start;
 +	off_t mapoff;
 +	size_t maplen;
  
  	if (!(size = sbp->st_size))
  		return;
 @@ -220,27 +222,59 @@
  		return;
  	}
  
 -	if ((start = mmap(NULL, (size_t)size,
 -	    PROT_READ, MAP_SHARED, fileno(fp), (off_t)0)) == MAP_FAILED) {
 -		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 & (~((4<<20)-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;
 +		}
  	}
  
 -	/* Last char is special, ignore whether newline or not. */
 -	for (p = start + size - 1; --size;)
 -		if (*--p == '\n' && !--off) {
 -			++p;
 -			break;
 +	if (curoff < 0)
 +		curoff = 0;
 +
 +	while (curoff != size) {
 +		if (curoff < mapoff || curoff >= mapoff + maplen) {
 +			if (start && munmap(start, maplen)) {
 +				ierr();
 +				return;
 +			}
 +			mapoff = curoff & (~((4<<20)-1));
 +			maplen = 4<<20;
 +			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) {
  		ierr();
  		return;
  	}
 -	if (munmap(start, (size_t)sbp->st_size)) {
 +	if (start && munmap(start, maplen)) {
  		ierr();
  		return;
  	}
 


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?200001111340.FAA19429>