summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authordas <das@FreeBSD.org>2003-02-26 06:44:46 +0000
committerdas <das@FreeBSD.org>2003-02-26 06:44:46 +0000
commit3fa6bd360fe3ba14be1ccfd435a3ebf4c8c977c8 (patch)
tree880444af9a8eecac34d56a8917f377e0ba9b2e0f /usr.bin
parentaa73de5a6fe9ae99a9b01fa48f4ded1faec95aab (diff)
downloadFreeBSD-src-3fa6bd360fe3ba14be1ccfd435a3ebf4c8c977c8.zip
FreeBSD-src-3fa6bd360fe3ba14be1ccfd435a3ebf4c8c977c8.tar.gz
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)
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/cmp/regular.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/usr.bin/cmp/regular.c b/usr.bin/cmp/regular.c
index 7e38fcd..7a27f5e 100644
--- a/usr.bin/cmp/regular.c
+++ b/usr.bin/cmp/regular.c
@@ -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);
+}
OpenPOWER on IntegriCloud