Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Oct 2001 03:51:56 +0400 (MSD)
From:      "Andrew L. Neporada" <andr@dgap.mipt.ru>
To:        freebsd-bugs@freebsd.org
Cc:        freebsd-gnuts-submit@freebsd.org
Subject:   Re: bin/24732: cmp can not compare files lager 2GB but smaller 4GB
Message-ID:  <20011018034848.H24599-100000@nas.dgap.mipt.ru>

next in thread | raw e-mail | index | archive | help
Patch below solves (I hope) this problem. Basic idea of the patch --
to mmap() some moderate amount (8MB) of data rather then entire file
(this idea belongs to phk@FreeBSD.org -- see bin/18589).

				Andrew.

P.S. Patch was made against RELENG_4 sources
(extern.h v 1.1.1.1.14.1 and regular.c v 1.7.2.2). Unfortunately
anoncvs.freebsd.org is down ;-(

diff -ruN cmp.orig/extern.h cmp/extern.h
--- cmp.orig/extern.h	Sun Jul  2 13:28:37 2000
+++ cmp/extern.h	Wed Oct 17 06:51:49 2001
@@ -40,9 +40,11 @@
 #define DIFF_EXIT	1
 #define ERR_EXIT	2	/* error exit code */

-void	c_regular __P((int, char *, off_t, off_t, int, char *, off_t, off_t));
-void	c_special __P((int, char *, off_t, int, char *, off_t));
-void	diffmsg __P((char *, char *, off_t, off_t));
-void	eofmsg __P((char *));
+void		c_regular __P((int, char *, off_t, off_t, int, char *, off_t,
+			       off_t));
+void		c_special __P((int, char *, off_t, int, char *, off_t));
+void		diffmsg __P((char *, char *, off_t, off_t));
+void		eofmsg __P((char *));
+u_char *	remmap __P((u_char *, int, off_t));

 extern int lflag, sflag, xflag;
diff -ruN cmp.orig/regular.c cmp/regular.c
--- cmp.orig/regular.c	Sun Jul  2 15:14:42 2000
+++ cmp/regular.c	Thu Oct 18 02:48:34 2001
@@ -52,6 +52,7 @@
 #include "extern.h"

 #define ROUNDPAGE(i) ((i) & ~pagemask)
+#define	MMAP_CHUNK	(8*1024*1024)

 void
 c_regular(fd1, file1, skip1, len1, fd2, file2, skip2, len2)
@@ -59,10 +60,10 @@
 	char *file1, *file2;
 	off_t skip1, len1, skip2, len2;
 {
-	u_char ch, *p1, *p2;
+	u_char ch, *p1, *p2, *m1, *m2;
 	off_t byte, length, line;
 	int dfound;
-	off_t pagemask, off1, off2;
+	off_t pagemask, off1, off2, st1, st2;
 	size_t pagesize;

 	if (skip1 > len1)
@@ -81,27 +82,25 @@
 	off2 = ROUNDPAGE(skip2);

 	length = MIN(len1, len2);
-	if (length > SIZE_T_MAX)
-		return (c_special(fd1, file1, skip1, fd2, file2, skip2));
+	dfound = 0;
+	st1 = skip1 - off1;
+	st2 = skip2 - off2;

-	if ((p1 = (u_char *)mmap(NULL, (size_t)len1 + skip1 % pagesize,
-	    PROT_READ, MAP_SHARED, fd1, off1)) == (u_char *)MAP_FAILED)
-		err(ERR_EXIT, "%s", file1);
-
-	madvise(p1, len1 + skip1 % pagesize, MADV_SEQUENTIAL);
-	if ((p2 = (u_char *)mmap(NULL, (size_t)len2 + skip2 % pagesize,
-	    PROT_READ, MAP_SHARED, fd2, off2)) == (u_char *)MAP_FAILED)
-		err(ERR_EXIT, "%s", file2);
-	madvise(p2, len2 + skip2 % pagesize, MADV_SEQUENTIAL);
+	m1 = remmap(NULL, fd1, off1);
+	m2 = remmap(NULL, fd2, off2);
+	if (!m1 || !m2)
+		c_special(fd1, file1, skip1, fd2, file2, skip2);
+		/* NOTREACHED */

-	dfound = 0;
-	p1 += skip1 - off1;
-	p2 += skip2 - off2;
-	for (byte = line = 1; length--; ++p1, ++p2, ++byte) {
+	p1 = m1 + st1;
+	p2 = m2 + st2;
+
+	for (byte = line = 1; length--; ++byte) {
 		if ((ch = *p1) != *p2) {
 			if (xflag) {
 				dfound = 1;
-				(void)printf("%08qx %02x %02x\n", byte - 1, ch, *p2);
+				(void)printf("%08qx %02x %02x\n", byte - 1,
+					     ch, *p2);
 			} else if (lflag) {
 				dfound = 1;
 				(void)printf("%6qd %3o %3o\n", byte, ch, *p2);
@@ -111,10 +110,41 @@
 		}
 		if (ch == '\n')
 			++line;
+		if (++st1 == MMAP_CHUNK) {
+			st1 = 0;
+			off1 += MMAP_CHUNK;
+			p1 = m1 = remmap(m1, fd1, off1);
+		} else
+			++p1;
+		if (++st2 == MMAP_CHUNK) {
+			st2 = 0;
+			off2 += MMAP_CHUNK;
+			p2 = m2 = remmap(m2, fd2, off2);
+		} else
+			++p2;
+		if (!m1 || !m2)
+			c_special(fd1, file1, skip1, fd2, file2, skip2);
+			/* NOTREACHED */
 	}

 	if (len1 != len2)
 		eofmsg (len1 > len2 ? file2 : file1);
 	if (dfound)
 		exit(DIFF_EXIT);
+}
+
+u_char *
+remmap(mem, fd, offset)
+	u_char	*mem;
+	int	fd;
+	off_t	offset;
+{
+	if (mem)
+		munmap(mem, MMAP_CHUNK);
+	mem = (u_char *)mmap(NULL, MMAP_CHUNK, PROT_READ, MAP_SHARED, fd,
+			     offset);
+	if (mem == (u_char *)MAP_FAILED)
+		return (NULL);
+	madvise(mem, MMAP_CHUNK, MADV_SEQUENTIAL);
+	return (mem);
 }


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?20011018034848.H24599-100000>