On Fri, Jan 08, 2021 at 07:09:01PM -0800, Jordan Geoghegan wrote:

> Hey folks,
> 
> I've noticed some surprising behaviour from cmp(1) when using the '-s' flag.
> 
> It appears that cmp -s is ignoring the byte offset arguments I'm giving it.
> 
> I don't want to waste time babbling, so here's an example snippet to show 
> what I'm talking about:
> 
> #!/bin/sh
> 
> echo 'my line' > /tmp/1.txt
> echo 'my other line' >> /tmp/1.txt
> echo 'same same' >> /tmp/1.txt
> 
> echo 'my differnt line' > /tmp/2.txt
> echo 'my other different line' >> /tmp/2.txt
> echo 'same same' >> /tmp/2.txt
> 
> # Determine byte offsets (we only want to compare lines >= 3)
> offset1="$(head -2 /tmp/1.txt | wc -c)"
> offset2="$(head -2 /tmp/2.txt | wc -c)"
> 
> # Compare files and show exit code
> cmp /tmp/1.txt /tmp/2.txt "$offset1" "$offset2"
> printf '\nReturn code = %s\n' "$?"
> 
> cmp -s /tmp/1.txt /tmp/2.txt "$offset1" "$offset2"
> printf '\nReturn code with "-s" = %s\n' "$?"
> 
> As you can see, 'cmp -s' returns an exit code of '1', unlike cmp without the 
> '-s' which returns '0'.
> 
> Not sure what to make of this, I noticed this same behaviour on DragonflyBSD 
> and FreeBSD, so maybe I'm just missing something obvious. This certainly 
> caused some frustration before I figured out what was going on.
> 
> Regards,
> 
> Jordan
> 

This is a bug. It has been there since the beginning, according to
http://cvsweb.openbsd.org/src/usr.bin/cmp/regular.c

FreeBSD has it fixed, NetBSD not.

        -Otto

Index: regular.c
===================================================================
RCS file: /cvs/src/usr.bin/cmp/regular.c,v
retrieving revision 1.12
diff -u -p -r1.12 regular.c
--- regular.c   6 Feb 2015 23:21:59 -0000       1.12
+++ regular.c   9 Jan 2021 06:53:20 -0000
@@ -51,15 +51,15 @@ c_regular(int fd1, char *file1, off_t sk
        off_t byte, length, line;
        int dfound;
 
-       if (sflag && len1 != len2)
-               exit(1);
-
        if (skip1 > len1)
                eofmsg(file1);
        len1 -= skip1;
        if (skip2 > len2)
                eofmsg(file2);
        len2 -= skip2;
+
+       if (sflag && len1 != len2)
+               exit(1);
 
        length = MINIMUM(len1, len2);
        if (length > SIZE_MAX) {

Reply via email to