regular.c revision 272461
1285612Sdelphij/*- 2285612Sdelphij * Copyright (c) 1991, 1993, 1994 3285612Sdelphij * The Regents of the University of California. All rights reserved. 4285612Sdelphij * 5285612Sdelphij * Redistribution and use in source and binary forms, with or without 6285612Sdelphij * modification, are permitted provided that the following conditions 7285612Sdelphij * are met: 8285612Sdelphij * 1. Redistributions of source code must retain the above copyright 9285612Sdelphij * notice, this list of conditions and the following disclaimer. 10285612Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 11285612Sdelphij * notice, this list of conditions and the following disclaimer in the 12285612Sdelphij * documentation and/or other materials provided with the distribution. 13285612Sdelphij * 4. Neither the name of the University nor the names of its contributors 14289997Sglebius * may be used to endorse or promote products derived from this software 15285612Sdelphij * without specific prior written permission. 16285612Sdelphij * 17285612Sdelphij * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18285612Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19285612Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20285612Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21285612Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22285612Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23285612Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24285612Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25285612Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26285612Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27285612Sdelphij * SUCH DAMAGE. 28285612Sdelphij */ 29285612Sdelphij 30285612Sdelphij#if 0 31285612Sdelphij#ifndef lint 32285612Sdelphijstatic char sccsid[] = "@(#)regular.c 8.3 (Berkeley) 4/2/94"; 33285612Sdelphij#endif 34285612Sdelphij#endif 35285612Sdelphij 36285612Sdelphij#include <sys/cdefs.h> 37285612Sdelphij__FBSDID("$FreeBSD: releng/10.1/usr.bin/cmp/regular.c 223376 2011-06-21 20:44:06Z delphij $"); 38285612Sdelphij 39285612Sdelphij#include <sys/param.h> 40285612Sdelphij#include <sys/mman.h> 41285612Sdelphij#include <sys/stat.h> 42285612Sdelphij 43285612Sdelphij#include <err.h> 44285612Sdelphij#include <limits.h> 45285612Sdelphij#include <signal.h> 46285612Sdelphij#include <stdlib.h> 47285612Sdelphij#include <stdio.h> 48285612Sdelphij#include <unistd.h> 49285612Sdelphij 50182007Sroberto#include "extern.h" 51285612Sdelphij 52285612Sdelphijstatic u_char *remmap(u_char *, int, off_t); 53285612Sdelphijstatic void segv_handler(int); 54285612Sdelphij#define MMAP_CHUNK (8*1024*1024) 55285612Sdelphij 56132451Sroberto#define ROUNDPAGE(i) ((i) & ~pagemask) 57285612Sdelphij 58316069Sdelphijvoid 59316069Sdelphijc_regular(int fd1, const char *file1, off_t skip1, off_t len1, 60132451Sroberto int fd2, const char *file2, off_t skip2, off_t len2) 61285612Sdelphij{ 62182007Sroberto u_char ch, *p1, *p2, *m1, *m2, *e1, *e2; 63285612Sdelphij off_t byte, length, line; 64285612Sdelphij int dfound; 65285612Sdelphij off_t pagemask, off1, off2; 66285612Sdelphij size_t pagesize; 67285612Sdelphij struct sigaction act, oact; 68200576Sroberto 69285612Sdelphij if (skip1 > len1) 70285612Sdelphij eofmsg(file1); 71285612Sdelphij len1 -= skip1; 72182007Sroberto if (skip2 > len2) 73285612Sdelphij eofmsg(file2); 74182007Sroberto len2 -= skip2; 75285612Sdelphij 76285612Sdelphij if (sflag && len1 != len2) 77285612Sdelphij exit(DIFF_EXIT); 78285612Sdelphij 79285612Sdelphij sigemptyset(&act.sa_mask); 80285612Sdelphij act.sa_flags = SA_NODEFER; 81285612Sdelphij act.sa_handler = segv_handler; 82285612Sdelphij if (sigaction(SIGSEGV, &act, &oact)) 83285612Sdelphij err(ERR_EXIT, "sigaction()"); 84285612Sdelphij 85285612Sdelphij pagesize = getpagesize(); 86285612Sdelphij pagemask = (off_t)pagesize - 1; 87182007Sroberto off1 = ROUNDPAGE(skip1); 88182007Sroberto off2 = ROUNDPAGE(skip2); 89182007Sroberto 90182007Sroberto length = MIN(len1, len2); 91182007Sroberto 92182007Sroberto if ((m1 = remmap(NULL, fd1, off1)) == NULL) { 93182007Sroberto c_special(fd1, file1, skip1, fd2, file2, skip2); 94182007Sroberto return; 95182007Sroberto } 96182007Sroberto 97182007Sroberto if ((m2 = remmap(NULL, fd2, off2)) == NULL) { 98182007Sroberto munmap(m1, MMAP_CHUNK); 99182007Sroberto c_special(fd1, file1, skip1, fd2, file2, skip2); 100285612Sdelphij return; 101182007Sroberto } 102182007Sroberto 103285612Sdelphij dfound = 0; 104285612Sdelphij e1 = m1 + MMAP_CHUNK; 105285612Sdelphij e2 = m2 + MMAP_CHUNK; 106285612Sdelphij p1 = m1 + (skip1 - off1); 107285612Sdelphij p2 = m2 + (skip2 - off2); 108285612Sdelphij 109182007Sroberto for (byte = line = 1; length--; ++byte) { 110285612Sdelphij if ((ch = *p1) != *p2) { 111182007Sroberto if (xflag) { 112285612Sdelphij dfound = 1; 113200576Sroberto (void)printf("%08llx %02x %02x\n", 114285612Sdelphij (long long)byte - 1, ch, *p2); 115285612Sdelphij } else if (lflag) { 116200576Sroberto dfound = 1; 117285612Sdelphij (void)printf("%6lld %3o %3o\n", 118285612Sdelphij (long long)byte, ch, *p2); 119285612Sdelphij } else 120285612Sdelphij diffmsg(file1, file2, byte, line); 121200576Sroberto /* NOTREACHED */ 122132451Sroberto } 123285612Sdelphij if (ch == '\n') 124285612Sdelphij ++line; 125285612Sdelphij if (++p1 == e1) { 126132451Sroberto off1 += MMAP_CHUNK; 127132451Sroberto if ((p1 = m1 = remmap(m1, fd1, off1)) == NULL) { 128285612Sdelphij munmap(m2, MMAP_CHUNK); 129132451Sroberto err(ERR_EXIT, "remmap %s", file1); 130285612Sdelphij } 131285612Sdelphij e1 = m1 + MMAP_CHUNK; 132132451Sroberto } 133285612Sdelphij if (++p2 == e2) { 134132451Sroberto off2 += MMAP_CHUNK; 135285612Sdelphij if ((p2 = m2 = remmap(m2, fd2, off2)) == NULL) { 136285612Sdelphij munmap(m1, MMAP_CHUNK); 137285612Sdelphij err(ERR_EXIT, "remmap %s", file2); 138285612Sdelphij } 139132451Sroberto e2 = m2 + MMAP_CHUNK; 140132451Sroberto } 141285612Sdelphij } 142132451Sroberto munmap(m1, MMAP_CHUNK); 143285612Sdelphij munmap(m2, MMAP_CHUNK); 144316069Sdelphij 145316069Sdelphij if (sigaction(SIGSEGV, &oact, NULL)) 146316069Sdelphij err(ERR_EXIT, "sigaction()"); 147132451Sroberto 148301256Sdelphij if (len1 != len2) 149301256Sdelphij eofmsg (len1 > len2 ? file2 : file1); 150285612Sdelphij if (dfound) 151285612Sdelphij exit(DIFF_EXIT); 152285612Sdelphij} 153285612Sdelphij 154182007Srobertostatic u_char * 155285612Sdelphijremmap(u_char *mem, int fd, off_t offset) 156285612Sdelphij{ 157285612Sdelphij if (mem != NULL) 158285612Sdelphij munmap(mem, MMAP_CHUNK); 159285612Sdelphij mem = mmap(NULL, MMAP_CHUNK, PROT_READ, MAP_SHARED, fd, offset); 160285612Sdelphij if (mem == MAP_FAILED) 161182007Sroberto return (NULL); 162132451Sroberto madvise(mem, MMAP_CHUNK, MADV_SEQUENTIAL); 163 return (mem); 164} 165 166static void 167segv_handler(int sig __unused) { 168 static const char msg[] = "cmp: Input/output error (caught SIGSEGV)\n"; 169 170 write(STDERR_FILENO, msg, sizeof(msg)); 171 _exit(EXIT_FAILURE); 172} 173