From f4f5fd5d785120a12cb61d6da5c684eac9d6f4af Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sun, 26 Dec 2021 17:59:44 -0600 Subject: [PATCH] Add cmp -n and wire up skip1 and skip2, plus new test, FLAG() conversions... --- tests/cmp.test | 32 ++++++++++++++++---------------- toys/posix/cmp.c | 35 ++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/tests/cmp.test b/tests/cmp.test index d1a8033b..ce776e8e 100755 --- a/tests/cmp.test +++ b/tests/cmp.test @@ -3,13 +3,13 @@ [ -f testing.sh ] && . testing.sh # TODO: coreutils cmp uses stdin if only one file is given -testing "one argument match" 'cmp input && echo yes' "yes\n" \ +testcmd "one argument match" 'input && echo yes' "yes\n" \ "one\ntwo\nthree" "one\ntwo\nthree" # posix says ""%s %s differ: char %d, line %d\n" but diffutils says "byte" -testing "one argument diff" 'cmp input | sed s/byte/char/' \ +testcmd "one argument diff" 'input | sed s/byte/char/' \ "input - differ: char 5, line 2\n" "one\ntwo\nthree" "one\nboing\nthree" -testing "missing file1 [fail]" 'cmp file1 input 2>/dev/null || echo $?' "2\n" "foo" "" +testcmd "missing file1 [fail]" 'file1 input 2>/dev/null || echo $?' "2\n" "foo" "" #mkdir dir #testing "directory [fail]" "cmp dir dir 2>/dev/null || echo yes" \ @@ -19,27 +19,27 @@ testing "missing file1 [fail]" 'cmp file1 input 2>/dev/null || echo $?' "2\n" "f echo "ab c" > input2 -testing "identical files, stdout" "cmp input input2" "" "ab\nc\n" "" -testing "identical files, return code" "cmp input input2 && echo yes" "yes\n" "ab\nc\n" "" +testcmd "identical files, stdout" "input input2" "" "ab\nc\n" "" +testcmd "identical files, return code" "input input2 && echo yes" "yes\n" "ab\nc\n" "" -testing "EOF, stderr" "cmp input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" "" -testing "EOF, return code" "cmp input input2 2>/dev/null || echo yes" "yes\n" "ab\nc\nx" "" +testcmd "EOF, stderr" "input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" "" +testcmd "EOF, return code" "input input2 2>/dev/null || echo yes" "yes\n" "ab\nc\nx" "" # The gnu/dammit version fails this because posix says "char" and they don't. -testing "diff, stdout" "cmp input input2 | sed s/byte/char/" \ +testcmd "diff, stdout" "input input2 | sed s/byte/char/" \ "input input2 differ: char 4, line 2\n" "ab\nx\nx" "" -testing "diff, return code" "cmp input input2 > /dev/null || echo yes" "yes\n" "ab\nx\nx" "" +testcmd "diff, return code" "input input2 > /dev/null || echo yes" "yes\n" "ab\nx\nx" "" -testing "-s EOF, return code" "cmp -s input input2 2>&1 || echo yes" "yes\n" "ab\nc\nx" "" -testing "-s diff, return code" "cmp -s input input2 2>&1 || echo yes" "yes\n" "ab\nx\nx" "" +testcmd "-s EOF, return code" "-s input input2 2>&1 || echo yes" "yes\n" "ab\nc\nx" "" +testcmd "-s diff, return code" "-s input input2 2>&1 || echo yes" "yes\n" "ab\nx\nx" "" -testing "-l EOF, stderr" "cmp -l input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" "" -testing "-l diff and EOF, stdout and stderr" "cmp -l input input2 2>&1 | sort" "4 170 143\ncmp: EOF on input2\n" "ab\nx\nx" "" +testcmd "-l EOF, stderr" "-l input input2 2>&1" "cmp: EOF on input2\n" "ab\nc\nx" "" +testcmd "-l diff and EOF, stdout and stderr" "-l input input2 2>&1 | sort" "4 170 143\ncmp: EOF on input2\n" "ab\nx\nx" "" -testing "-s not exist" "cmp -s input doesnotexist 2>&1 || echo yes" "yes\n" "x" "" +testcmd "-s not exist" "-s input doesnotexist 2>&1 || echo yes" "yes\n" "x" "" rm input2 -testing "stdin and file" "cmp input - | sed s/byte/char/" \ +testcmd "stdin and file" "input - | sed s/byte/char/" \ "input - differ: char 4, line 2\n" "ab\nc\n" "ab\nx\n" -#testing "stdin and stdin" "cmp input -" "" "" "ab\nc\n" +testcmd "-n skip1 skip2" "-n 3 input - 3 5 && echo yes" "yes\n" "abcdef123" "vwxyzdef987" diff --git a/toys/posix/cmp.c b/toys/posix/cmp.c index d1c73f1d..8e33c92d 100644 --- a/toys/posix/cmp.c +++ b/toys/posix/cmp.c @@ -4,17 +4,19 @@ * * See http://opengroup.org/onlinepubs/9699919799/utilities/cmp.html -USE_CMP(NEWTOY(cmp, "<1>2ls(silent)(quiet)[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2))) +USE_CMP(NEWTOY(cmp, "<1>4ls(silent)(quiet)n#<1[!ls]", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(2))) config CMP bool "cmp" default y help - usage: cmp [-l] [-s] FILE1 [FILE2 [SKIP1 [SKIP2]]] + usage: cmp [-ls] [-n LEN] FILE1 [FILE2 [SKIP1 [SKIP2]]] - Compare the contents of two files. (Or stdin and file if only one given.) + Compare the contents of files (vs stdin if only one given), optionally + skipping bytes at start. -l Show all differing bytes + -n LEN Compare at most LEN bytes -s Silent */ @@ -22,16 +24,22 @@ config CMP #include "toys.h" GLOBALS( + long n; + int fd; char *name; ) +// We hijack loopfiles() to open and understand the "-" filename for us. static void do_cmp(int fd, char *name) { int i, len1, len2, min_len, size = sizeof(toybuf)/2; long byte_no = 1, line_no = 1; char *buf2 = toybuf+size; + if (toys.optc>(i = 2+!!TT.fd) && lskip(fd, atolx(toys.optargs[i]))) + error_exit("EOF on %s", name); + // First time through, cache the data and return. if (!TT.fd) { TT.name = name; @@ -43,19 +51,17 @@ static void do_cmp(int fd, char *name) toys.exitval = 0; - for (;;) { + for (;!FLAG(n) || TT.n;) { + if (FLAG(n)) TT.n -= size = minof(size, TT.n); len1 = readall(TT.fd, toybuf, size); len2 = readall(fd, buf2, size); - - min_len = len1 < len2 ? len1 : len2; + min_len = minof(len1, len2); for (i=0; i