git: 1159a71ad777 - stable/13 - cmp: add -n, --bytes to limit number of bytes to compare

Kyle Evans kevans at FreeBSD.org
Sun Oct 3 05:15:49 UTC 2021


The branch stable/13 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=1159a71ad777dbcabd8d62afb8de2b85e0ee975b

commit 1159a71ad777dbcabd8d62afb8de2b85e0ee975b
Author:     Kyle Evans <kevans at FreeBSD.org>
AuthorDate: 2021-09-23 05:26:52 +0000
Commit:     Kyle Evans <kevans at FreeBSD.org>
CommitDate: 2021-10-03 05:15:05 +0000

    cmp: add -n, --bytes to limit number of bytes to compare
    
    This is compatible with GNU cmp.
    
    Reviewed by:    markj
    Sponsored by:   Klara, Inc.
    
    (cherry picked from commit 4e380e8474609875c4cf5277b3755ac29079a8b5)
---
 usr.bin/cmp/cmp.1              |  6 ++++++
 usr.bin/cmp/cmp.c              | 18 +++++++++++++-----
 usr.bin/cmp/extern.h           |  7 ++++---
 usr.bin/cmp/link.c             |  6 ++++--
 usr.bin/cmp/regular.c          |  8 +++++---
 usr.bin/cmp/special.c          |  4 ++--
 usr.bin/cmp/tests/cmp_test2.sh | 23 +++++++++++++++++++++++
 7 files changed, 57 insertions(+), 15 deletions(-)

diff --git a/usr.bin/cmp/cmp.1 b/usr.bin/cmp/cmp.1
index 6980f73e7be5..511e09ac8628 100644
--- a/usr.bin/cmp/cmp.1
+++ b/usr.bin/cmp/cmp.1
@@ -41,6 +41,7 @@
 .Nm
 .Op Fl l | s | x
 .Op Fl hz
+.Op Fl -bytes Ns Cm = Ns Ar num
 .Ar file1 file2
 .Op Ar skip1 Op Ar skip2
 .Sh DESCRIPTION
@@ -62,6 +63,10 @@ Do not follow symbolic links.
 .It Fl l , Fl -verbose
 Print the byte number (decimal) and the differing
 byte values (octal) for each difference.
+.It Fl n Ar num , Fl -bytes= Ns num
+Only compare up to
+.Ar num
+bytes.
 .It Fl s , Fl -silent , Fl -quiet
 Print nothing for differing files; return exit
 status only.
@@ -165,6 +170,7 @@ utility is expected to be
 compatible.
 The
 .Fl h ,
+.Fl n ,
 .Fl x ,
 and
 .Fl z
diff --git a/usr.bin/cmp/cmp.c b/usr.bin/cmp/cmp.c
index bab69125e83e..384c273f4632 100644
--- a/usr.bin/cmp/cmp.c
+++ b/usr.bin/cmp/cmp.c
@@ -67,6 +67,7 @@ bool	lflag, sflag, xflag, zflag;
 static const struct option long_opts[] =
 {
 	{"verbose",	no_argument,		NULL, 'l'},
+	{"bytes",	required_argument,	NULL, 'n'},
 	{"silent",	no_argument,		NULL, 's'},
 	{"quiet",	no_argument,		NULL, 's'},
 	{NULL,		no_argument,		NULL, 0}
@@ -78,14 +79,14 @@ int
 main(int argc, char *argv[])
 {
 	struct stat sb1, sb2;
-	off_t skip1, skip2;
+	off_t skip1, skip2, limit;
 	int ch, fd1, fd2, oflag;
 	bool special;
 	const char *file1, *file2;
 
 	skip1 = skip2 = 0;
 	oflag = O_RDONLY;
-	while ((ch = getopt_long(argc, argv, "+hlsxz", long_opts, NULL)) != -1)
+	while ((ch = getopt_long(argc, argv, "+hln:sxz", long_opts, NULL)) != -1)
 		switch (ch) {
 		case 'h':		/* Don't follow symlinks */
 			oflag |= O_NOFOLLOW;
@@ -93,6 +94,13 @@ main(int argc, char *argv[])
 		case 'l':		/* print all differences */
 			lflag = true;
 			break;
+		case 'n':		/* Limit */
+			if (expand_number(optarg, &limit) < 0 || limit < 0) {
+				fprintf(stderr, "Invalid --bytes: %s\n",
+				    optarg);
+				usage();
+			}
+			break;
 		case 's':		/* silent run */
 			sflag = true;
 			break;
@@ -163,7 +171,7 @@ main(int argc, char *argv[])
 
 	if (fd1 == -1) {
 		if (fd2 == -1) {
-			c_link(file1, skip1, file2, skip2);
+			c_link(file1, skip1, file2, skip2, limit);
 			exit(0);
 		} else if (!sflag)
 			errx(ERR_EXIT, "%s: Not a symbolic link", file2);
@@ -201,7 +209,7 @@ main(int argc, char *argv[])
 	}
 
 	if (special)
-		c_special(fd1, file1, skip1, fd2, file2, skip2);
+		c_special(fd1, file1, skip1, fd2, file2, skip2, limit);
 	else {
 		if (zflag && sb1.st_size != sb2.st_size) {
 			if (!sflag)
@@ -210,7 +218,7 @@ main(int argc, char *argv[])
 			exit(DIFF_EXIT);
 		}
 		c_regular(fd1, file1, skip1, sb1.st_size,
-		    fd2, file2, skip2, sb2.st_size);
+		    fd2, file2, skip2, sb2.st_size, limit);
 	}
 	exit(0);
 }
diff --git a/usr.bin/cmp/extern.h b/usr.bin/cmp/extern.h
index 82c5ea42b175..803319a50ca4 100644
--- a/usr.bin/cmp/extern.h
+++ b/usr.bin/cmp/extern.h
@@ -38,9 +38,10 @@
 #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	c_link(const char *, off_t, const char *, off_t, off_t);
+void	c_regular(int, const char *, off_t, off_t, int, const char *, off_t,
+	    off_t, off_t);
+void	c_special(int, const char *, off_t, int, const char *, off_t, off_t);
 void	diffmsg(const char *, const char *, off_t, off_t);
 void	eofmsg(const char *);
 
diff --git a/usr.bin/cmp/link.c b/usr.bin/cmp/link.c
index 9193147e830e..f0b4482a5792 100644
--- a/usr.bin/cmp/link.c
+++ b/usr.bin/cmp/link.c
@@ -40,7 +40,8 @@ __FBSDID("$FreeBSD$");
 #include "extern.h"
 
 void
-c_link(const char *file1, off_t skip1, const char *file2, off_t skip2)
+c_link(const char *file1, off_t skip1, const char *file2, off_t skip2,
+    off_t limit)
 {
 	char buf1[PATH_MAX], *p1;
 	char buf2[PATH_MAX], *p2;
@@ -72,7 +73,8 @@ c_link(const char *file1, off_t skip1, const char *file2, off_t skip2)
 
 	dfound = 0;
 	byte = 1;
-	for (p1 = buf1 + skip1, p2 = buf2 + skip2; *p1 && *p2; p1++, p2++) {
+	for (p1 = buf1 + skip1, p2 = buf2 + skip2;
+	    *p1 && *p2 && (limit == 0 || byte <= limit); p1++, p2++) {
 		if ((ch = *p1) != *p2) {
 			if (xflag) {
 				dfound = 1;
diff --git a/usr.bin/cmp/regular.c b/usr.bin/cmp/regular.c
index fe639663a560..a60398620282 100644
--- a/usr.bin/cmp/regular.c
+++ b/usr.bin/cmp/regular.c
@@ -60,7 +60,7 @@ static void segv_handler(int);
 
 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)
+    int fd2, const char *file2, off_t skip2, off_t len2, off_t limit)
 {
 	struct sigaction act, oact;
 	cap_rights_t rights;
@@ -86,15 +86,17 @@ c_regular(int fd1, const char *file1, off_t skip1, off_t len1,
 	off2 = ROUNDPAGE(skip2);
 
 	length = MIN(len1, len2);
+	if (limit > 0)
+		length = MIN(length, limit);
 
 	if ((m1 = remmap(NULL, fd1, off1)) == NULL) {
-		c_special(fd1, file1, skip1, fd2, file2, skip2);
+		c_special(fd1, file1, skip1, fd2, file2, skip2, limit);
 		return;
 	}
 
 	if ((m2 = remmap(NULL, fd2, off2)) == NULL) {
 		munmap(m1, MMAP_CHUNK);
-		c_special(fd1, file1, skip1, fd2, file2, skip2);
+		c_special(fd1, file1, skip1, fd2, file2, skip2, limit);
 		return;
 	}
 
diff --git a/usr.bin/cmp/special.c b/usr.bin/cmp/special.c
index 930fcd5492ff..25f755f6e70a 100644
--- a/usr.bin/cmp/special.c
+++ b/usr.bin/cmp/special.c
@@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$");
 
 void
 c_special(int fd1, const char *file1, off_t skip1,
-    int fd2, const char *file2, off_t skip2)
+    int fd2, const char *file2, off_t skip2, off_t limit)
 {
 	int ch1, ch2;
 	off_t byte, line;
@@ -76,7 +76,7 @@ c_special(int fd1, const char *file1, off_t skip1,
 		if (getc(fp2) == EOF)
 			goto eof;
 
-	for (byte = line = 1;; ++byte) {
+	for (byte = line = 1; limit == 0 || byte <= limit; ++byte) {
 		ch1 = getc(fp1);
 		ch2 = getc(fp2);
 		if (ch1 == EOF || ch2 == EOF)
diff --git a/usr.bin/cmp/tests/cmp_test2.sh b/usr.bin/cmp/tests/cmp_test2.sh
index 334e9f357730..c513984daf8b 100755
--- a/usr.bin/cmp/tests/cmp_test2.sh
+++ b/usr.bin/cmp/tests/cmp_test2.sh
@@ -91,10 +91,33 @@ skipsuff_body()
 	atf_check -s exit:0 cmp -s a b 1k 1k
 }
 
+atf_test_case limit
+limit_head()
+{
+	atf_set "descr" "Test cmp(1) -n (limit)"
+}
+limit_body()
+{
+	echo -n "aaaabbbb" > a
+	echo -n "aaaaxxxx" > b
+
+	atf_check -s exit:1 -o ignore cmp -s a b
+	atf_check -s exit:0 cmp -sn 4 a b
+	atf_check -s exit:0 cmp -sn 3 a b
+	atf_check -s exit:1 -o ignore cmp -sn 5 a b
+
+	# Test special, too.  The implementation for link is effectively
+	# identical.
+	atf_check -s exit:0 -e empty -x "cat a | cmp -sn 4 b -"
+	atf_check -s exit:0 -e empty -x "cat a | cmp -sn 3 b -"
+	atf_check -s exit:1 -o ignore -x "cat a | cmp -sn 5 b -"
+}
+
 atf_init_test_cases()
 {
 	atf_add_test_case special
 	atf_add_test_case symlink
 	atf_add_test_case pr252542
 	atf_add_test_case skipsuff
+	atf_add_test_case limit
 }


More information about the dev-commits-src-all mailing list