bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: diff: incorrect and undocumented cmp output when stdout is redirecte


From: Paul Eggert
Subject: Re: diff: incorrect and undocumented cmp output when stdout is redirected
Date: Thu, 09 Mar 2006 12:48:07 -0800
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

Good catch.  Wow, that bug has been in GNU cmp ever since it was
entered into CVS in 1991.

>> The output of the cmp command should be documented.

The current documentation says this: is it not enough?
What more needs to be said?

   By default, @command{cmp} outputs nothing if the two files have the
   same contents.  If one file is a prefix of the other, @command{cmp}
   prints to standard error a message of the following form:

   @example
   cmp: EOF on @var{shorter-file}
   @end example

   Otherwise, @command{cmp} prints to standard output a message of the
   following form:

   @example
   @var{from-file} @var{to-file} differ: char @var{byte-number}, line 
@var{line-number}
   @end example

   The message formats can differ outside the @acronym{POSIX} locale.
   Also, @acronym{POSIX} allows the @acronym{EOF} message to be followed
   by a blank and some additional information.

Anyway, I installed the following patch:

2006-03-09  Paul Eggert  <address@hidden>

        * src/cmp.c (type_no_stdout): New constant.
        (main): Use it to avoid bug when the "EOF on foo" message is
        generated and stdout is /dev/null.
        Problem reported by Vincent Lefevre (Debian bug 356083).

--- src/cmp.c   5 Jan 2006 07:23:55 -0000       1.39
+++ src/cmp.c   9 Mar 2006 20:33:00 -0000
@@ -78,6 +78,7 @@ static enum comparison_type
   {
     type_first_diff,   /* Print the first difference.  */
     type_all_diffs,    /* Print all differences.  */
+    type_no_stdout,    /* Do not output to stdout; only stderr.  */
     type_status                /* Exit status only.  */
   } comparison_type;
 
@@ -317,7 +318,12 @@ main (int argc, char **argv)
       if (fstat (STDOUT_FILENO, &outstat) == 0
          && stat (NULL_DEVICE, &nullstat) == 0
          && 0 < same_file (&outstat, &nullstat))
-       comparison_type = type_status;
+       comparison_type =
+         ((fstat (STDERR_FILENO, &outstat) == 0
+           ? 0 < same_file (&outstat, &nullstat)
+           : errno == EBADF)
+          ? type_status
+          : type_no_stdout);
     }
 
   /* If only a return code is needed,
@@ -356,7 +362,7 @@ main (int argc, char **argv)
   for (f = 0; f < 2; f++)
     if (close (file_desc[f]) != 0)
       error (EXIT_TROUBLE, errno, "%s", file[f]);
-  if (exit_status != 0  &&  comparison_type != type_status)
+  if (exit_status != EXIT_SUCCESS && comparison_type < type_no_stdout)
     check_stdout ();
   exit (exit_status);
   return exit_status;
@@ -536,6 +542,9 @@ cmp (void)
              while (first_diff < smaller);
              ret = EXIT_FAILURE;
              break;
+
+           case type_no_stdout:
+             break;
            }
        }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]