regular.c revision 180426
1251877Speter/*-
2251877Speter * Copyright (c) 1991, 1993, 1994
3251877Speter *	The Regents of the University of California.  All rights reserved.
4251877Speter *
5251877Speter * Redistribution and use in source and binary forms, with or without
6251877Speter * modification, are permitted provided that the following conditions
7251877Speter * are met:
8251877Speter * 1. Redistributions of source code must retain the above copyright
9251877Speter *    notice, this list of conditions and the following disclaimer.
10251877Speter * 2. Redistributions in binary form must reproduce the above copyright
11251877Speter *    notice, this list of conditions and the following disclaimer in the
12251877Speter *    documentation and/or other materials provided with the distribution.
13251877Speter * 3. All advertising materials mentioning features or use of this software
14251877Speter *    must display the following acknowledgement:
15251877Speter *	This product includes software developed by the University of
16251877Speter *	California, Berkeley and its contributors.
17251877Speter * 4. Neither the name of the University nor the names of its contributors
18251877Speter *    may be used to endorse or promote products derived from this software
19251877Speter *    without specific prior written permission.
20251877Speter *
21251877Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22251877Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23251877Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24251877Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25251877Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26253895Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27253895Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28251877Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29251877Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30251877Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31251877Speter * SUCH DAMAGE.
32251877Speter */
33251877Speter
34251877Speter#if 0
35251877Speter#ifndef lint
36251877Speterstatic char sccsid[] = "@(#)regular.c	8.3 (Berkeley) 4/2/94";
37251877Speter#endif
38251877Speter#endif
39251877Speter
40251877Speter#include <sys/cdefs.h>
41251877Speter__FBSDID("$FreeBSD: head/usr.bin/cmp/regular.c 180426 2008-07-10 13:26:46Z charnier $");
42251877Speter
43251877Speter#include <sys/param.h>
44251877Speter#include <sys/mman.h>
45251877Speter#include <sys/stat.h>
46253895Speter
47253895Speter#include <err.h>
48251877Speter#include <errno.h>
49251877Speter#include <limits.h>
50253895Speter#include <signal.h>
51262339Speter#include <stdlib.h>
52251877Speter#include <stdio.h>
53251877Speter#include <string.h>
54251877Speter#include <unistd.h>
55251877Speter
56251877Speter#include "extern.h"
57251877Speter
58251877Speterstatic u_char *remmap(u_char *, int, off_t);
59253895Speterstatic void segv_handler(int);
60253895Speter#define MMAP_CHUNK (8*1024*1024)
61253895Speter
62253895Speter#define ROUNDPAGE(i) ((i) & ~pagemask)
63253895Speter
64253895Spetervoid
65251877Speterc_regular(int fd1, const char *file1, off_t skip1, off_t len1,
66253895Speter    int fd2, const char *file2, off_t skip2, off_t len2)
67253895Speter{
68251877Speter	u_char ch, *p1, *p2, *m1, *m2, *e1, *e2;
69253895Speter	off_t byte, length, line;
70253895Speter	int dfound;
71253895Speter	off_t pagemask, off1, off2;
72253895Speter	size_t pagesize;
73253895Speter	struct sigaction act, oact;
74253895Speter
75253895Speter	if (skip1 > len1)
76253895Speter		eofmsg(file1);
77253895Speter	len1 -= skip1;
78251877Speter	if (skip2 > len2)
79251877Speter		eofmsg(file2);
80251877Speter	len2 -= skip2;
81251877Speter
82251877Speter	if (sflag && len1 != len2)
83251877Speter		exit(DIFF_EXIT);
84251877Speter
85253895Speter	sigemptyset(&act.sa_mask);
86253895Speter	act.sa_flags = SA_NODEFER;
87253895Speter	act.sa_handler = segv_handler;
88251877Speter	if (sigaction(SIGSEGV, &act, &oact))
89251877Speter		err(ERR_EXIT, "sigaction()");
90251877Speter
91251877Speter	pagesize = getpagesize();
92253895Speter	pagemask = (off_t)pagesize - 1;
93253895Speter	off1 = ROUNDPAGE(skip1);
94253895Speter	off2 = ROUNDPAGE(skip2);
95253895Speter
96253895Speter	length = MIN(len1, len2);
97251877Speter
98251877Speter	if ((m1 = remmap(NULL, fd1, off1)) == NULL) {
99251877Speter		c_special(fd1, file1, skip1, fd2, file2, skip2);
100251877Speter		return;
101251877Speter	}
102251877Speter
103251877Speter	if ((m2 = remmap(NULL, fd2, off2)) == NULL) {
104251877Speter		munmap(m1, MMAP_CHUNK);
105251877Speter		c_special(fd1, file1, skip1, fd2, file2, skip2);
106251877Speter		return;
107251877Speter	}
108251877Speter
109251877Speter	dfound = 0;
110251877Speter	e1 = m1 + MMAP_CHUNK;
111251877Speter	e2 = m2 + MMAP_CHUNK;
112251877Speter	p1 = m1 + (skip1 - off1);
113251877Speter	p2 = m2 + (skip2 - off2);
114251877Speter
115251877Speter	for (byte = line = 1; length--; ++byte) {
116251877Speter		if ((ch = *p1) != *p2) {
117251877Speter			if (xflag) {
118251877Speter				dfound = 1;
119251877Speter				(void)printf("%08llx %02x %02x\n",
120251877Speter				    (long long)byte - 1, ch, *p2);
121251877Speter			} else if (lflag) {
122253895Speter				dfound = 1;
123253895Speter				(void)printf("%6lld %3o %3o\n",
124253895Speter				    (long long)byte, ch, *p2);
125253895Speter			} else
126253895Speter				diffmsg(file1, file2, byte, line);
127253895Speter				/* NOTREACHED */
128251877Speter		}
129253895Speter		if (ch == '\n')
130253895Speter			++line;
131251877Speter		if (++p1 == e1) {
132251877Speter			off1 += MMAP_CHUNK;
133251877Speter			if ((p1 = m1 = remmap(m1, fd1, off1)) == NULL) {
134253895Speter				munmap(m2, MMAP_CHUNK);
135253895Speter				err(ERR_EXIT, "remmap %s", file1);
136253895Speter			}
137253895Speter			e1 = m1 + MMAP_CHUNK;
138253895Speter		}
139253895Speter		if (++p2 == e2) {
140253895Speter			off2 += MMAP_CHUNK;
141253895Speter			if ((p2 = m2 = remmap(m2, fd2, off2)) == NULL) {
142253895Speter				munmap(m1, MMAP_CHUNK);
143253895Speter				err(ERR_EXIT, "remmap %s", file2);
144253895Speter			}
145253895Speter			e2 = m2 + MMAP_CHUNK;
146253895Speter		}
147251877Speter	}
148251877Speter	munmap(m1, MMAP_CHUNK);
149251877Speter	munmap(m2, MMAP_CHUNK);
150251877Speter
151251877Speter	if (sigaction(SIGSEGV, &oact, NULL))
152251877Speter		err(ERR_EXIT, "sigaction()");
153251877Speter
154251877Speter	if (len1 != len2)
155251877Speter		eofmsg (len1 > len2 ? file2 : file1);
156251877Speter	if (dfound)
157251877Speter		exit(DIFF_EXIT);
158251877Speter}
159251877Speter
160253895Speterstatic u_char *
161253895Speterremmap(u_char *mem, int fd, off_t offset)
162251877Speter{
163251877Speter	if (mem != NULL)
164253895Speter		munmap(mem, MMAP_CHUNK);
165251877Speter	mem = mmap(NULL, MMAP_CHUNK, PROT_READ, MAP_SHARED, fd, offset);
166253895Speter	if (mem == MAP_FAILED)
167251877Speter		return (NULL);
168253895Speter	madvise(mem, MMAP_CHUNK, MADV_SEQUENTIAL);
169251877Speter	return (mem);
170253895Speter}
171253895Speter
172253895Speterstatic void
173251877Spetersegv_handler(int sig __unused) {
174251877Speter	static const char msg[] = "cmp: Input/output error (caught SIGSEGV)\n";
175251877Speter
176251877Speter	write(STDERR_FILENO, msg, sizeof(msg));
177251877Speter	_exit(EXIT_FAILURE);
178}
179