diff options
author | das <das@FreeBSD.org> | 2003-02-26 06:44:46 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2003-02-26 06:44:46 +0000 |
commit | 3fa6bd360fe3ba14be1ccfd435a3ebf4c8c977c8 (patch) | |
tree | 880444af9a8eecac34d56a8917f377e0ba9b2e0f /usr.bin/cmp | |
parent | aa73de5a6fe9ae99a9b01fa48f4ded1faec95aab (diff) | |
download | FreeBSD-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/cmp')
-rw-r--r-- | usr.bin/cmp/regular.c | 21 |
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); +} |