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>