cmp: add -i, --ignore-initial, an alternative to skip1/skip2 args

This is compatible with GNU cmp.

Reviewed by:	markj
Sponsored by:	Klara, Inc.
Differential Revision:	https://reviews.freebsd.org/D32073
This commit is contained in:
Kyle Evans 2021-09-23 00:43:32 -05:00
parent 4e380e8474
commit 8d546b6832
3 changed files with 53 additions and 1 deletions

View File

@ -41,6 +41,7 @@
.Nm
.Op Fl l | s | x
.Op Fl hz
.Op Fl -ignore-initial Ns Cm = Ns Ar num1 Ns Op :num2
.Op Fl -bytes Ns Cm = Ns Ar num
.Ar file1 file2
.Op Ar skip1 Op Ar skip2
@ -60,6 +61,23 @@ The following options are available:
.Bl -tag -width indent
.It Fl h
Do not follow symbolic links.
.It Fl i Ar num1 Ns Oo :num2 Oc , Fl -ignore-initial= Ns Ar num1 Ns Op :num2
Skip
.Ar num1
bytes from
.Ar file1 ,
and optionally skip
.Ar num2
bytes from
.Ar file2 .
If
.Ar num2
is not specified, then
.Ar num1
is applied for both
.Ar file1
and
.Ar file2 .
.It Fl l , Fl -verbose
Print the byte number (decimal) and the differing
byte values (octal) for each difference.
@ -170,6 +188,7 @@ utility is expected to be
compatible.
The
.Fl h ,
.Fl i ,
.Fl n ,
.Fl x ,
and

View File

@ -66,6 +66,7 @@ bool lflag, sflag, xflag, zflag;
static const struct option long_opts[] =
{
{"ignore-initial", required_argument, NULL, 'i'},
{"verbose", no_argument, NULL, 'l'},
{"bytes", required_argument, NULL, 'n'},
{"silent", no_argument, NULL, 's'},
@ -75,6 +76,25 @@ static const struct option long_opts[] =
static void usage(void);
static bool
parse_iskipspec(char *spec, off_t *skip1, off_t *skip2)
{
char *colon;
colon = strchr(spec, ':');
if (colon != NULL)
*colon++ = '\0';
if (expand_number(spec, skip1) < 0)
return (false);
if (colon != NULL)
return (expand_number(colon, skip2) == 0);
*skip2 = *skip1;
return (true);
}
int
main(int argc, char *argv[])
{
@ -86,11 +106,19 @@ main(int argc, char *argv[])
skip1 = skip2 = 0;
oflag = O_RDONLY;
while ((ch = getopt_long(argc, argv, "+hln:sxz", long_opts, NULL)) != -1)
while ((ch = getopt_long(argc, argv, "+hi:ln:sxz", long_opts, NULL)) != -1)
switch (ch) {
case 'h': /* Don't follow symlinks */
oflag |= O_NOFOLLOW;
break;
case 'i':
if (!parse_iskipspec(optarg, &skip1, &skip2)) {
fprintf(stderr,
"Invalid --ignore-initial: %s\n",
optarg);
usage();
}
break;
case 'l': /* print all differences */
lflag = true;
break;

View File

@ -71,8 +71,13 @@ pr252542_body()
{
echo -n '1234567890' > a
echo -n 'abc567890' > b
echo -n 'xbc567890' > c
atf_check -s exit:0 cmp -s a b 4 3
atf_check -s exit:0 cmp -i 4:3 -s a b
atf_check -s exit:0 cmp -i 1 -s b c
atf_check -s exit:1 -o ignore cmp -z a b 4 3
atf_check -s exit:1 -o ignore cmp -i 4:3 -z a b
atf_check -s exit:1 -o ignore cmp -i 1 -z a b
}
atf_test_case skipsuff