regular.c revision 111538
11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1991, 1993, 1994
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
3487628Sdwmalone#if 0
3587628Sdwmalone#ifndef lint
3687628Sdwmalonestatic char sccsid[] = "@(#)regular.c	8.3 (Berkeley) 4/2/94";
3787628Sdwmalone#endif
3887628Sdwmalone#endif
3987628Sdwmalone
4087241Smarkm#include <sys/cdefs.h>
4187241Smarkm__FBSDID("$FreeBSD: head/usr.bin/cmp/regular.c 111538 2003-02-26 06:44:46Z das $");
4287241Smarkm
431590Srgrimes#include <sys/param.h>
441590Srgrimes#include <sys/mman.h>
451590Srgrimes#include <sys/stat.h>
461590Srgrimes
471590Srgrimes#include <err.h>
48111538Sdas#include <errno.h>
491590Srgrimes#include <limits.h>
50111538Sdas#include <signal.h>
511590Srgrimes#include <stdlib.h>
521590Srgrimes#include <stdio.h>
531590Srgrimes#include <string.h>
5421429Sjoerg#include <unistd.h>
551590Srgrimes
561590Srgrimes#include "extern.h"
571590Srgrimes
5892920Simpstatic u_char *remmap(u_char *, int, off_t);
59111538Sdasstatic void segv_handler(int);
6086044Sdwmalone#define MMAP_CHUNK (8*1024*1024)
6186044Sdwmalone
6221429Sjoerg#define ROUNDPAGE(i) ((i) & ~pagemask)
6321429Sjoerg
641590Srgrimesvoid
65100815Sdwmalonec_regular(int fd1, const char *file1, off_t skip1, off_t len1,
66100815Sdwmalone    int fd2, const char *file2, off_t skip2, off_t len2)
671590Srgrimes{
6886044Sdwmalone	u_char ch, *p1, *p2, *m1, *m2, *e1, *e2;
691590Srgrimes	off_t byte, length, line;
701590Srgrimes	int dfound;
7121429Sjoerg	off_t pagemask, off1, off2;
7249235Sgreen	size_t pagesize;
73111538Sdas	struct sigaction act, oact;
741590Srgrimes
751590Srgrimes	if (skip1 > len1)
761590Srgrimes		eofmsg(file1);
771590Srgrimes	len1 -= skip1;
781590Srgrimes	if (skip2 > len2)
791590Srgrimes		eofmsg(file2);
801590Srgrimes	len2 -= skip2;
811590Srgrimes
8261883Sgreen	if (sflag && len1 != len2)
8361883Sgreen		exit(DIFF_EXIT);
8461883Sgreen
85111538Sdas	sigemptyset(&act.sa_mask);
86111538Sdas	act.sa_flags = SA_NODEFER;
87111538Sdas	act.sa_handler = segv_handler;
88111538Sdas	if (sigaction(SIGSEGV, &act, &oact))
89111538Sdas		err(ERR_EXIT, "sigaction()");
90111538Sdas
9149235Sgreen	pagesize = getpagesize();
9249235Sgreen	pagemask = (off_t)pagesize - 1;
9321429Sjoerg	off1 = ROUNDPAGE(skip1);
9421429Sjoerg	off2 = ROUNDPAGE(skip2);
9521429Sjoerg
961590Srgrimes	length = MIN(len1, len2);
971590Srgrimes
9886044Sdwmalone	if ((m1 = remmap(NULL, fd1, off1)) == NULL) {
9986044Sdwmalone		c_special(fd1, file1, skip1, fd2, file2, skip2);
10086044Sdwmalone		return;
10186044Sdwmalone	}
10220312Sdyson
10386044Sdwmalone	if ((m2 = remmap(NULL, fd2, off2)) == NULL) {
10486044Sdwmalone		munmap(m1, MMAP_CHUNK);
10586044Sdwmalone		c_special(fd1, file1, skip1, fd2, file2, skip2);
10686044Sdwmalone		return;
10786044Sdwmalone	}
1081590Srgrimes
1091590Srgrimes	dfound = 0;
11086044Sdwmalone	e1 = m1 + MMAP_CHUNK;
11186044Sdwmalone	e2 = m2 + MMAP_CHUNK;
11286044Sdwmalone	p1 = m1 + (skip1 - off1);
11386044Sdwmalone	p2 = m2 + (skip2 - off2);
11486044Sdwmalone
11586044Sdwmalone	for (byte = line = 1; length--; ++byte) {
11646081Simp		if ((ch = *p1) != *p2) {
11760583Sphk			if (xflag) {
1181590Srgrimes				dfound = 1;
11987282Sdwmalone				(void)printf("%08llx %02x %02x\n",
12087282Sdwmalone				    (long long)byte - 1, ch, *p2);
12160583Sphk			} else if (lflag) {
12260583Sphk				dfound = 1;
12387282Sdwmalone				(void)printf("%6lld %3o %3o\n",
12487282Sdwmalone				    (long long)byte, ch, *p2);
1251590Srgrimes			} else
1261590Srgrimes				diffmsg(file1, file2, byte, line);
1271590Srgrimes				/* NOTREACHED */
12846081Simp		}
1291590Srgrimes		if (ch == '\n')
1301590Srgrimes			++line;
13186044Sdwmalone		if (++p1 == e1) {
13286044Sdwmalone			off1 += MMAP_CHUNK;
13386044Sdwmalone			if ((p1 = m1 = remmap(m1, fd1, off1)) == NULL) {
13486044Sdwmalone				munmap(m2, MMAP_CHUNK);
13586044Sdwmalone				err(ERR_EXIT, "remmap %s", file1);
13686044Sdwmalone			}
13786044Sdwmalone			e1 = m1 + MMAP_CHUNK;
13886044Sdwmalone		}
13986044Sdwmalone		if (++p2 == e2) {
14086044Sdwmalone			off2 += MMAP_CHUNK;
14186044Sdwmalone			if ((p2 = m2 = remmap(m2, fd2, off2)) == NULL) {
14286044Sdwmalone				munmap(m1, MMAP_CHUNK);
14386044Sdwmalone				err(ERR_EXIT, "remmap %s", file2);
14486044Sdwmalone			}
14586044Sdwmalone			e2 = m2 + MMAP_CHUNK;
14686044Sdwmalone		}
1471590Srgrimes	}
14886044Sdwmalone	munmap(m1, MMAP_CHUNK);
14986044Sdwmalone	munmap(m2, MMAP_CHUNK);
1501590Srgrimes
151111538Sdas	if (sigaction(SIGSEGV, &oact, NULL))
152111538Sdas		err(ERR_EXIT, "sigaction()");
153111538Sdas
1541590Srgrimes	if (len1 != len2)
1551590Srgrimes		eofmsg (len1 > len2 ? file2 : file1);
1561590Srgrimes	if (dfound)
1571590Srgrimes		exit(DIFF_EXIT);
1581590Srgrimes}
15986044Sdwmalone
16086044Sdwmalonestatic u_char *
161100815Sdwmaloneremmap(u_char *mem, int fd, off_t offset)
16286044Sdwmalone{
16386044Sdwmalone	if (mem != NULL)
16486044Sdwmalone		munmap(mem, MMAP_CHUNK);
16586044Sdwmalone	mem = mmap(NULL, MMAP_CHUNK, PROT_READ, MAP_SHARED, fd, offset);
16686044Sdwmalone	if (mem == MAP_FAILED)
16786044Sdwmalone		return (NULL);
16886044Sdwmalone	madvise(mem, MMAP_CHUNK, MADV_SEQUENTIAL);
16986044Sdwmalone	return (mem);
17086044Sdwmalone}
171111538Sdas
172111538Sdasstatic void
173111538Sdassegv_handler(int sig) {
174111538Sdas	static const char msg[] = "cmp: Input/output error (caught SIGSEGV)\n";
175111538Sdas
176111538Sdas	write(STDERR_FILENO, msg, sizeof(msg));
177111538Sdas	_exit(EXIT_FAILURE);
178111538Sdas}
179