The cmp utility has the questionable feature of using mmap when

comparing regular files.  Add a SIGSEGV handler to make its
behavior less surprising when a read error occurs.  The handler
does not attempt to distinguish errors from file truncation, but
anyone actively modifying a file while trying to compare it
shouldn't even expect something sane to happen.

PR:		45391
Reviewed by:	mike (mentor)
This commit is contained in:
David Schultz 2003-02-26 06:44:46 +00:00
parent 0aef141cd0
commit d48905120d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=111538

View File

@ -45,7 +45,9 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -54,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include "extern.h"
static u_char *remmap(u_char *, int, off_t);
static void segv_handler(int);
#define MMAP_CHUNK (8*1024*1024)
#define ROUNDPAGE(i) ((i) & ~pagemask)
@ -67,6 +70,7 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
int dfound;
off_t pagemask, off1, off2;
size_t pagesize;
struct sigaction act, oact;
if (skip1 > len1)
eofmsg(file1);
@ -78,6 +82,12 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
if (sflag && len1 != len2)
exit(DIFF_EXIT);
sigemptyset(&act.sa_mask);
act.sa_flags = SA_NODEFER;
act.sa_handler = segv_handler;
if (sigaction(SIGSEGV, &act, &oact))
err(ERR_EXIT, "sigaction()");
pagesize = getpagesize();
pagemask = (off_t)pagesize - 1;
off1 = ROUNDPAGE(skip1);
@ -138,6 +148,9 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
munmap(m1, MMAP_CHUNK);
munmap(m2, MMAP_CHUNK);
if (sigaction(SIGSEGV, &oact, NULL))
err(ERR_EXIT, "sigaction()");
if (len1 != len2)
eofmsg (len1 > len2 ? file2 : file1);
if (dfound)
@ -155,3 +168,11 @@ remmap(u_char *mem, int fd, off_t offset)
madvise(mem, MMAP_CHUNK, MADV_SEQUENTIAL);
return (mem);
}
static void
segv_handler(int sig) {
static const char msg[] = "cmp: Input/output error (caught SIGSEGV)\n";
write(STDERR_FILENO, msg, sizeof(msg));
_exit(EXIT_FAILURE);
}