cmp(1): Take latest changes from FreeBSD's implementation.
authorEitan Adler <lists@eitanadler.com>
Mon, 18 Nov 2013 23:13:24 +0000 (18:13 -0500)
committerSascha Wildner <saw@online.de>
Mon, 18 Nov 2013 23:47:43 +0000 (00:47 +0100)
In particular handle symbolic links more correctly, add a
signal handler, and other misc changes.

usr.bin/cmp/Makefile
usr.bin/cmp/cmp.1
usr.bin/cmp/cmp.c
usr.bin/cmp/extern.h
usr.bin/cmp/link.c [new file with mode: 0644]
usr.bin/cmp/misc.c
usr.bin/cmp/regular.c
usr.bin/cmp/special.c

index 15db988..67f3772 100644 (file)
@@ -1,8 +1,7 @@
-# $FreeBSD: src/usr.bin/cmp/Makefile,v 1.2.6.1 2001/11/21 10:47:54 dwmalone Exp $
-# $DragonFly: src/usr.bin/cmp/Makefile,v 1.4 2007/08/27 16:50:52 pavalos Exp $
 #      @(#)Makefile    8.1 (Berkeley) 6/6/93
+# $FreeBSD: head/usr.bin/cmp/Makefile 149388 2005-08-23 13:13:13Z brian $
 
 PROG=  cmp
-SRCS=  cmp.c misc.c regular.c special.c
+SRCS=  cmp.c link.c misc.c regular.c special.c
 
 .include <bsd.prog.mk>
index 9622fcf..f2e197b 100644 (file)
@@ -29,9 +29,9 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)cmp.1      8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.bin/cmp/cmp.1,v 1.7.2.5 2003/02/24 22:37:41 trhodes Exp $
+.\" $FreeBSD: head/usr.bin/cmp/cmp.1 216370 2010-12-11 08:32:16Z joel $
 .\"
-.Dd April 10, 2013
+.Dd November 18, 2013
 .Dt CMP 1
 .Os
 .Sh NAME
@@ -39,8 +39,8 @@
 .Nd compare two files
 .Sh SYNOPSIS
 .Nm
-.Op Fl l | Fl s | Fl x
-.Op Fl z
+.Op Fl l | s | x
+.Op Fl hz
 .Ar file1 file2
 .Op Ar skip1 Op Ar skip2
 .Sh DESCRIPTION
@@ -56,7 +56,9 @@ and line number at which the first difference occurred is reported.
 Bytes and lines are numbered beginning with one.
 .Pp
 The following options are available:
-.Bl -tag -width flag
+.Bl -tag -width indent
+.It Fl h
+Do not follow symbolic links.
 .It Fl l
 Print the byte number (decimal) and the differing
 byte values (octal) for each difference.
@@ -104,12 +106,6 @@ file (before any differences were found).
 .It >1
 An error occurred.
 .El
-.Sh COMPATIBILITY
-The
-.Fl x
-and
-.Fl z
-options are extensions to the standard.
 .Sh SEE ALSO
 .Xr diff 1 ,
 .Xr diff3 1
@@ -119,6 +115,12 @@ The
 utility is expected to be
 .St -p1003.2
 compatible.
+The
+.Fl h ,
+.Fl x ,
+and
+.Fl z
+options are extensions to the standard.
 .Sh HISTORY
 A
 .Nm
index 59457cb..5fd26b6 100644 (file)
@@ -26,8 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.bin/cmp/cmp.c,v 1.6.6.4 2001/11/21 10:47:54 dwmalone Exp $
- * $DragonFly: src/usr.bin/cmp/cmp.c,v 1.3 2003/10/02 17:42:27 hmp Exp $
+ * $FreeBSD: head/usr.bin/cmp/cmp.c 216370 2010-12-11 08:32:16Z joel $
  *
  * @(#) Copyright (c) 1987, 1990, 1993, 1994 The Regents of the University of California.  All rights reserved.
  * @(#)cmp.c   8.3 (Berkeley) 4/2/94
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
-#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "extern.h"
 
-int    lflag, sflag, xflag;
-static int zflag;
+int    lflag, sflag, xflag, zflag;
 
 static void usage (void);
 
@@ -61,7 +58,7 @@ main(int argc, char **argv)
        const char *file1, *file2;
 
        oflag = O_RDONLY;
-       while ((ch = getopt(argc, argv, "-lhsxz")) != -1)
+       while ((ch = getopt(argc, argv, "hlsxz")) != -1)
                switch (ch) {
                case 'h':               /* Don't follow symlinks */
                        oflag |= O_NOFOLLOW;
@@ -80,14 +77,10 @@ main(int argc, char **argv)
                case 'z':               /* compare size first */
                        zflag = 1;
                        break;
-               case '-':               /* stdin (must be after options) */
-                       --optind;
-                       goto endargs;
                case '?':
                default:
                        usage();
                }
-endargs:
        argv += optind;
        argc -= optind;
 
@@ -108,9 +101,9 @@ endargs:
                if (!sflag)
                        err(ERR_EXIT, "%s", file1);
                else
-                       exit(1);
+                       exit(ERR_EXIT);
        }
-       if (strcmp(file2 = argv[1], "-") == 0 && errno != EMLINK) {
+       if (strcmp(file2 = argv[1], "-") == 0) {
                if (special)
                        errx(ERR_EXIT,
                                "standard input may only be specified once");
@@ -118,22 +111,37 @@ endargs:
                fd2 = 0;
                file2 = "stdin";
        }
-       else if ((fd2 = open(file2, oflag, 0)) < 0) {
+       else if ((fd2 = open(file2, oflag, 0)) < 0 && errno != EMLINK) {
                if (!sflag)
                        err(ERR_EXIT, "%s", file2);
                else
-                       exit(1);
+                       exit(ERR_EXIT);
        }
 
        skip1 = argc > 2 ? strtol(argv[2], NULL, 0) : 0;
        skip2 = argc == 4 ? strtol(argv[3], NULL, 0) : 0;
 
+       if (fd1 == -1) {
+               if (fd2 == -1) {
+                       c_link(file1, skip1, file2, skip2);
+                       exit(0);
+               } else if (!sflag)
+                       errx(ERR_EXIT, "%s: Not a symbolic link", file2);
+               else
+                       exit(ERR_EXIT);
+       } else if (fd2 == -1) {
+               if (!sflag)
+                       errx(ERR_EXIT, "%s: Not a symbolic link", file1);
+               else
+                       exit(ERR_EXIT);
+       }
+
        if (!special) {
                if (fstat(fd1, &sb1)) {
                        if (!sflag)
                                err(ERR_EXIT, "%s", file1);
                        else
-                               exit(1);
+                               exit(ERR_EXIT);
                }
                if (!S_ISREG(sb1.st_mode))
                        special = 1;
@@ -142,7 +150,7 @@ endargs:
                                if (!sflag)
                                        err(ERR_EXIT, "%s", file2);
                                else
-                                       exit(1);
+                                       exit(ERR_EXIT);
                        }
                        if (!S_ISREG(sb2.st_mode))
                                special = 1;
@@ -169,6 +177,6 @@ usage(void)
 {
 
        (void)fprintf(stderr,
-           "usage: cmp [-l | -s | -x] [-z] file1 file2 [skip1 [skip2]]\n");
+           "usage: cmp [-l | -s | -x] [-hz] file1 file2 [skip1 [skip2]]\n");
        exit(ERR_EXIT);
 }
index 0f44d64..7a9ff52 100644 (file)
  *
  *     @(#)extern.h    8.3 (Berkeley) 4/2/94
  *
- * $FreeBSD: src/usr.bin/cmp/extern.h,v 1.1.1.1.14.2 2001/11/21 10:47:54 dwmalone Exp $
- * $DragonFly: src/usr.bin/cmp/extern.h,v 1.3 2003/11/03 19:31:28 eirikn Exp $
- *
+ * $FreeBSD: head/usr.bin/cmp/extern.h 227156 2011-11-06 08:14:16Z ed $
  */
 
 #define OK_EXIT                0
 #define DIFF_EXIT      1
 #define ERR_EXIT       2       /* error exit code */
 
+void   c_link(const char *, off_t, const char *, off_t);
 void   c_regular(int, const char *, off_t, off_t, int, const char *, off_t, off_t);
 void   c_special(int, const char *, off_t, int, const char *, off_t);
 void   diffmsg(const char *, const char *, off_t, off_t);
 void   eofmsg(const char *);
 
-extern int lflag, sflag, xflag;
+extern int lflag, sflag, xflag, zflag;
diff --git a/usr.bin/cmp/link.c b/usr.bin/cmp/link.c
new file mode 100644 (file)
index 0000000..a65477b
--- /dev/null
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2005 Brian Somers <brian@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/usr.bin/cmp/link.c 149388 2005-08-23 13:13:13Z brian $
+ */
+
+#include <sys/types.h>
+#include <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+void
+c_link(const char *file1, off_t skip1, const char *file2, off_t skip2)
+{
+       char buf1[PATH_MAX], *p1;
+       char buf2[PATH_MAX], *p2;
+       int dfound, len1, len2;
+       off_t byte;
+       u_char ch;
+
+       if ((len1 = readlink(file1, buf1, sizeof(buf1) - 1)) < 0) {
+               if (!sflag)
+                       err(ERR_EXIT, "%s", file1);
+               else
+                       exit(ERR_EXIT);
+       }
+
+       if ((len2 = readlink(file2, buf2, sizeof(buf2) - 1)) < 0) {
+               if (!sflag)
+                       err(ERR_EXIT, "%s", file2);
+               else
+                       exit(ERR_EXIT);
+       }
+
+       if (skip1 > len1)
+               skip1 = len1;
+       buf1[len1] = '\0';
+
+       if (skip2 > len2)
+               skip2 = len2;
+       buf2[len2] = '\0';
+
+       dfound = 0;
+       byte = 1;
+       for (p1 = buf1 + skip1, p2 = buf2 + skip2; *p1 && *p2; p1++, p2++) {
+               if ((ch = *p1) != *p2) {
+                       if (xflag) {
+                               dfound = 1;
+                               (void)printf("%08llx %02x %02x\n",
+                                   (long long)byte - 1, ch, *p2);
+                       } else if (lflag) {
+                               dfound = 1;
+                               (void)printf("%6lld %3o %3o\n",
+                                   (long long)byte, ch, *p2);
+                       } else
+                               diffmsg(file1, file2, byte, 1);
+                               /* NOTREACHED */
+               }
+               byte++;
+       }
+
+       if (*p1 || *p2)
+               eofmsg (*p1 ? file2 : file1);
+       if (dfound)
+               exit(DIFF_EXIT);
+}
index bcab302..c987e5e 100644 (file)
@@ -26,8 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.bin/cmp/misc.c,v 1.2.6.1 2001/11/21 10:47:54 dwmalone Exp $
- * $DragonFly: src/usr.bin/cmp/misc.c,v 1.3 2003/10/02 17:42:27 hmp Exp $
+ * $FreeBSD: head/usr.bin/cmp/misc.c 216370 2010-12-11 08:32:16Z joel $
  *
  * @(#)misc.c  8.3 (Berkeley) 4/2/94
  */
index 045b582..bd23915 100644 (file)
@@ -26,8 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.bin/cmp/regular.c,v 1.7.2.3 2001/11/21 10:47:54 dwmalone Exp $
- * $DragonFly: src/usr.bin/cmp/regular.c,v 1.4 2003/11/03 19:31:28 eirikn Exp $
+ * $FreeBSD: head/usr.bin/cmp/regular.c 223376 2011-06-21 20:44:06Z delphij $
  *
  * @(#)regular.c       8.3 (Berkeley) 4/2/94
  */
 
 #include <err.h>
 #include <limits.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdio.h>
-#include <string.h>
 #include <unistd.h>
 
 #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)
 
 void
-c_regular(int fd1, const char *file1, off_t skip1, off_t len1, int fd2,
-          const char *file2, off_t skip2, off_t len2)
+c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
+    int fd2, const char *file2, off_t skip2, off_t len2)
 {
        u_char ch, *p1, *p2, *m1, *m2, *e1, *e2;
        off_t byte, length, line;
        int dfound;
        off_t pagemask, off1, off2;
        size_t pagesize;
+       struct sigaction act, oact;
 
        if (skip1 > len1)
                eofmsg(file1);
@@ -71,6 +72,12 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1, int fd2,
        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);
@@ -100,15 +107,14 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1, int fd2,
                        if (xflag) {
                                dfound = 1;
                                printf("%08jx %02x %02x\n",
-                                      (intmax_t)byte - 1, ch, *p2);
+                                   (intmax_t)byte - 1, ch, *p2);
                        } else if (lflag) {
                                dfound = 1;
                                printf("%6jd %3o %3o\n",
-                                      (intmax_t)byte, ch, *p2);
-                       } else {
+                                   (intmax_t)byte, ch, *p2);
+                       } else
                                diffmsg(file1, file2, byte, line);
                                /* NOTREACHED */
-                       }
                }
                if (ch == '\n')
                        ++line;
@@ -132,6 +138,9 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1, int fd2,
        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)
@@ -149,3 +158,11 @@ remmap(u_char *mem, int fd, off_t offset)
        madvise(mem, MMAP_CHUNK, MADV_SEQUENTIAL);
        return (mem);
 }
+
+static void
+segv_handler(int sig __unused) {
+       static const char msg[] = "cmp: Input/output error (caught SIGSEGV)\n";
+
+       write(STDERR_FILENO, msg, sizeof(msg));
+       _exit(EXIT_FAILURE);
+}
index b47a13c..ac8d747 100644 (file)
@@ -26,8 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/usr.bin/cmp/special.c,v 1.4.2.1 2001/11/21 10:47:54 dwmalone Exp $
- * $DragonFly: src/usr.bin/cmp/special.c,v 1.3 2003/10/02 17:42:27 hmp Exp $
+ * $FreeBSD: head/usr.bin/cmp/special.c 223376 2011-06-21 20:44:06Z delphij $
  *
  * @(#)special.c       8.3 (Berkeley) 4/2/94
  */
@@ -43,8 +42,8 @@
 #include "extern.h"
 
 void
-c_special(int fd1, const char *file1, off_t skip1, int fd2, const char *file2,
-          off_t skip2)
+c_special(int fd1, const char *file1, off_t skip1,
+    int fd2, const char *file2, off_t skip2)
 {
        int ch1, ch2;
        off_t byte, line;
@@ -73,11 +72,11 @@ c_special(int fd1, const char *file1, off_t skip1, int fd2, const char *file2,
                        if (xflag) {
                                dfound = 1;
                                printf("%08jx %02x %02x\n",
-                                      (intmax_t)byte - 1, ch1, ch2);
+                                   (intmax_t)byte - 1, ch1, ch2);
                        } else if (lflag) {
                                dfound = 1;
                                printf("%6jd %3o %3o\n",
-                                      (intmax_t)byte, ch1, ch2);
+                                   (intmax_t)byte, ch1, ch2);
                        } else {
                                diffmsg(file1, file2, byte, line);
                                /* NOTREACHED */