From owner-freebsd-bugs Tue Jan 11 5:40: 6 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id D9ED014CFA for ; Tue, 11 Jan 2000 05:40:02 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id FAA19429; Tue, 11 Jan 2000 05:40:02 -0800 (PST) (envelope-from gnats@FreeBSD.org) Date: Tue, 11 Jan 2000 05:40:02 -0800 (PST) Message-Id: <200001111340.FAA19429@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: David Malone Subject: Re: bin/14786: tail breaks on large files Reply-To: David Malone Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org The following reply was made to PR bin/14786; it has been noted by GNATS. From: David Malone 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