Hi,

I have put together the attached simple patch for diff.c of the Diffutils package (specifically version 2.8.1). This patch suppresses the messages (and failure exit status) when non-regular files are encountered during recursive comparisons, if the "-Q" or "--ignore_special" command line arguments are given. Examples of the suppressed messages are:

File original/dev/char1-3 is a character special file while file test1/dev/char1-3 is a character special file
File original/misc/a-fifo is a fifo while file test1/misc/a-fifo is a fifo
File original/misc/a-socket is a socket while file test1/misc/a-socket is a fifo

Instead, the patch looks a little further, and if the files are of the same type and are not device files, it considers them a match. In the case of device files, if they are of the same type (block or character) and refer to the same device (via stat.st_rdev), then it considers them a match.

When comparing two complete filesystems, or large portions of them (which I do a lot), these messages tend to get in the way. Broken symlinks, which are common in almost every distribution, are still reported, but those messages I am willing to filter outside of diff.

I can submit a larger patch that includes the relevant changes to the documentation supplied with Diffutils, if you would like. Further, I can update and re-package everything as diffutils-2.8.2 if you would like (but I don't want to intrude too much). Just let me know.

Thanks,
Jason Todd
diff -Naur diffutils-2.8.1/src/diff.c new.diffutils-2.8.1/src/diff.c
--- diffutils-2.8.1/src/diff.c  2002-03-24 02:35:28.000000000 -0500
+++ new.diffutils-2.8.1/src/diff.c      2008-11-11 16:49:21.000000000 -0500
@@ -70,6 +70,10 @@
    recursively.  */
 static bool recursive;
 
+/* If two non-regular files are of the same type, suppress the POSIX-specified
+   message and prevent a failure exit status in this case.  */
+static bool ignore_special;
+
 /* In context diffs, show previous lines that match these regexps.  */
 static struct regexp_list function_regexp_list;
 
@@ -139,7 +143,7 @@
 }
 
 static char const shortopts[] =
-"0123456789abBcC:dD:eEfF:hHiI:lL:nNpPqrsS:tTuU:vwW:x:X:y";
+"0123456789abBcC:dD:eEfF:hHiI:lL:nNpPqQrsS:tTuU:vwW:x:X:y";
 
 /* Values for long options that do not have single-letter equivalents.  */
 enum
@@ -207,6 +211,7 @@
   {"ignore-file-name-case", 0, 0, IGNORE_FILE_NAME_CASE_OPTION},
   {"ignore-matching-lines", 1, 0, 'I'},
   {"ignore-space-change", 0, 0, 'b'},
+  {"ignore-special", 0, 0, 'Q'},
   {"ignore-tab-expansion", 0, 0, 'E'},
   {"inhibit-hunk-merge", 0, 0, INHIBIT_HUNK_MERGE_OPTION},
   {"initial-tab", 0, 0, 'T'},
@@ -441,6 +446,10 @@
          brief = 1;
          break;
 
+       case 'Q':
+         ignore_special = 1;
+         break;
+
        case 'r':
          recursive = 1;
          break;
@@ -851,6 +860,7 @@
   -p  --show-c-function  Show which C function each change is in.\n\
   -F RE  --show-function-line=RE  Show the most recent line matching RE."),
   N_("-q  --brief  Output only whether files differ."),
+  N_("-Q  --ignore-special  Ignore non-regular files with matching types."),
   N_("-e  --ed  Output an ed script."),
   N_("--normal  Output a normal diff."),
   N_("-n  --rcs  Output an RCS format diff."),
@@ -1258,10 +1268,13 @@
              status = EXIT_FAILURE;
            }
        }
-      else
+      else if ((filetype(&cmp.file[0].stat) != filetype(&cmp.file[1].stat)) ||
+              !ignore_special)
        {
          /* We have two files that are not to be compared.  */
 
+         /* This is suppressed if "-Q" has been specified.  */
+
          /* See POSIX 1003.1-2001 for this format.  */
          message5 ("File %s is a %s while file %s is a %s\n",
                    file_label[0] ? file_label[0] : cmp.file[0].name,
@@ -1272,6 +1285,30 @@
          /* This is a difference.  */
          status = EXIT_FAILURE;
        }
+#if HAVE_STRUCT_STAT_ST_RDEV && (defined S_ISCHR) && (defined S_ISBLK)
+      else
+       {
+         /* We have two non-regular files, and "-Q" has been specified.  */
+
+         /* The file types (and names, if recursive) match, and that is all
+            that is necessary to know that they represent the same thing in
+            the case of FIFOs and sockets.  For device nodes, check the major
+            and minor numbers.  */
+
+         /* Note, st_rdev is an extension to POSIX/SUSv3.  */
+
+         if ((S_ISCHR(cmp.file[0].stat.st_mode) ||
+              S_ISBLK(cmp.file[0].stat.st_mode)) &&
+             (cmp.file[0].stat.st_rdev != cmp.file[1].stat.st_rdev))
+           {
+             message ("Device nodes %s and %s represent different devices\n",
+                      file_label[0] ? file_label[0] : cmp.file[0].name,
+                      file_label[1] ? file_label[1] : cmp.file[1].name);
+
+             status = EXIT_FAILURE;
+           }
+       }
+#endif
     }
   else if (files_can_be_treated_as_binary
           && cmp.file[0].stat.st_size != cmp.file[1].stat.st_size

Reply via email to