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 * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
3087628Sdwmalone#if 0
3187628Sdwmalone#ifndef lint
3287628Sdwmalonestatic char sccsid[] = "@(#)regular.c	8.3 (Berkeley) 4/2/94";
3387628Sdwmalone#endif
3487628Sdwmalone#endif
3587628Sdwmalone
3687241Smarkm#include <sys/cdefs.h>
3787241Smarkm__FBSDID("$FreeBSD$");
3887241Smarkm
391590Srgrimes#include <sys/param.h>
401590Srgrimes#include <sys/mman.h>
411590Srgrimes#include <sys/stat.h>
421590Srgrimes
431590Srgrimes#include <err.h>
441590Srgrimes#include <limits.h>
45111538Sdas#include <signal.h>
461590Srgrimes#include <stdlib.h>
471590Srgrimes#include <stdio.h>
4821429Sjoerg#include <unistd.h>
491590Srgrimes
501590Srgrimes#include "extern.h"
511590Srgrimes
5292920Simpstatic u_char *remmap(u_char *, int, off_t);
53111538Sdasstatic void segv_handler(int);
5486044Sdwmalone#define MMAP_CHUNK (8*1024*1024)
5586044Sdwmalone
5621429Sjoerg#define ROUNDPAGE(i) ((i) & ~pagemask)
5721429Sjoerg
581590Srgrimesvoid
59100815Sdwmalonec_regular(int fd1, const char *file1, off_t skip1, off_t len1,
60100815Sdwmalone    int fd2, const char *file2, off_t skip2, off_t len2)
611590Srgrimes{
6286044Sdwmalone	u_char ch, *p1, *p2, *m1, *m2, *e1, *e2;
631590Srgrimes	off_t byte, length, line;
641590Srgrimes	int dfound;
6521429Sjoerg	off_t pagemask, off1, off2;
6649235Sgreen	size_t pagesize;
67111538Sdas	struct sigaction act, oact;
681590Srgrimes
691590Srgrimes	if (skip1 > len1)
701590Srgrimes		eofmsg(file1);
711590Srgrimes	len1 -= skip1;
721590Srgrimes	if (skip2 > len2)
731590Srgrimes		eofmsg(file2);
741590Srgrimes	len2 -= skip2;
751590Srgrimes
7661883Sgreen	if (sflag && len1 != len2)
7761883Sgreen		exit(DIFF_EXIT);
7861883Sgreen
79111538Sdas	sigemptyset(&act.sa_mask);
80111538Sdas	act.sa_flags = SA_NODEFER;
81111538Sdas	act.sa_handler = segv_handler;
82111538Sdas	if (sigaction(SIGSEGV, &act, &oact))
83111538Sdas		err(ERR_EXIT, "sigaction()");
84111538Sdas
8549235Sgreen	pagesize = getpagesize();
8649235Sgreen	pagemask = (off_t)pagesize - 1;
8721429Sjoerg	off1 = ROUNDPAGE(skip1);
8821429Sjoerg	off2 = ROUNDPAGE(skip2);
8921429Sjoerg
901590Srgrimes	length = MIN(len1, len2);
911590Srgrimes
9286044Sdwmalone	if ((m1 = remmap(NULL, fd1, off1)) == NULL) {
9386044Sdwmalone		c_special(fd1, file1, skip1, fd2, file2, skip2);
9486044Sdwmalone		return;
9586044Sdwmalone	}
9620312Sdyson
9786044Sdwmalone	if ((m2 = remmap(NULL, fd2, off2)) == NULL) {
9886044Sdwmalone		munmap(m1, MMAP_CHUNK);
9986044Sdwmalone		c_special(fd1, file1, skip1, fd2, file2, skip2);
10086044Sdwmalone		return;
10186044Sdwmalone	}
1021590Srgrimes
1031590Srgrimes	dfound = 0;
10486044Sdwmalone	e1 = m1 + MMAP_CHUNK;
10586044Sdwmalone	e2 = m2 + MMAP_CHUNK;
10686044Sdwmalone	p1 = m1 + (skip1 - off1);
10786044Sdwmalone	p2 = m2 + (skip2 - off2);
10886044Sdwmalone
10986044Sdwmalone	for (byte = line = 1; length--; ++byte) {
11046081Simp		if ((ch = *p1) != *p2) {
11160583Sphk			if (xflag) {
1121590Srgrimes				dfound = 1;
11387282Sdwmalone				(void)printf("%08llx %02x %02x\n",
11487282Sdwmalone				    (long long)byte - 1, ch, *p2);
11560583Sphk			} else if (lflag) {
11660583Sphk				dfound = 1;
11787282Sdwmalone				(void)printf("%6lld %3o %3o\n",
11887282Sdwmalone				    (long long)byte, ch, *p2);
1191590Srgrimes			} else
1201590Srgrimes				diffmsg(file1, file2, byte, line);
1211590Srgrimes				/* NOTREACHED */
12246081Simp		}
1231590Srgrimes		if (ch == '\n')
1241590Srgrimes			++line;
12586044Sdwmalone		if (++p1 == e1) {
12686044Sdwmalone			off1 += MMAP_CHUNK;
12786044Sdwmalone			if ((p1 = m1 = remmap(m1, fd1, off1)) == NULL) {
12886044Sdwmalone				munmap(m2, MMAP_CHUNK);
12986044Sdwmalone				err(ERR_EXIT, "remmap %s", file1);
13086044Sdwmalone			}
13186044Sdwmalone			e1 = m1 + MMAP_CHUNK;
13286044Sdwmalone		}
13386044Sdwmalone		if (++p2 == e2) {
13486044Sdwmalone			off2 += MMAP_CHUNK;
13586044Sdwmalone			if ((p2 = m2 = remmap(m2, fd2, off2)) == NULL) {
13686044Sdwmalone				munmap(m1, MMAP_CHUNK);
13786044Sdwmalone				err(ERR_EXIT, "remmap %s", file2);
13886044Sdwmalone			}
13986044Sdwmalone			e2 = m2 + MMAP_CHUNK;
14086044Sdwmalone		}
1411590Srgrimes	}
14286044Sdwmalone	munmap(m1, MMAP_CHUNK);
14386044Sdwmalone	munmap(m2, MMAP_CHUNK);
1441590Srgrimes
145111538Sdas	if (sigaction(SIGSEGV, &oact, NULL))
146111538Sdas		err(ERR_EXIT, "sigaction()");
147111538Sdas
1481590Srgrimes	if (len1 != len2)
1491590Srgrimes		eofmsg (len1 > len2 ? file2 : file1);
1501590Srgrimes	if (dfound)
1511590Srgrimes		exit(DIFF_EXIT);
1521590Srgrimes}
15386044Sdwmalone
15486044Sdwmalonestatic u_char *
155100815Sdwmaloneremmap(u_char *mem, int fd, off_t offset)
15686044Sdwmalone{
15786044Sdwmalone	if (mem != NULL)
15886044Sdwmalone		munmap(mem, MMAP_CHUNK);
15986044Sdwmalone	mem = mmap(NULL, MMAP_CHUNK, PROT_READ, MAP_SHARED, fd, offset);
16086044Sdwmalone	if (mem == MAP_FAILED)
16186044Sdwmalone		return (NULL);
16286044Sdwmalone	madvise(mem, MMAP_CHUNK, MADV_SEQUENTIAL);
16386044Sdwmalone	return (mem);
16486044Sdwmalone}
165111538Sdas
166111538Sdasstatic void
167180426Scharniersegv_handler(int sig __unused) {
168111538Sdas	static const char msg[] = "cmp: Input/output error (caught SIGSEGV)\n";
169111538Sdas
170111538Sdas	write(STDERR_FILENO, msg, sizeof(msg));
171111538Sdas	_exit(EXIT_FAILURE);
172111538Sdas}
173