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