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>
