Comparing binary files with Diff 3.2 compiled with MinGW

Eli Zaretskii <[email protected]>
Newsgroups gmane.comp.gnu.utils.bugs,gmane.comp.lib.gnulib.bugs
Message-ID <[email protected]>
At some point between Diffutils 2.8.7 and 2.9, the code that handles
binary files was removed from io.c.  The changes below resurrect the
correct behavior.  To accomplish this, I needed to add the binary-io
module, and make changes there as well.  Patches are below.

Thanks.

2012-05-12  Eli Zaretskii  <[email protected]>

	* lib/binary-io.h (SET_BINARY) [O_BINARY]: Return the previous mode.
	(UNSET_BINARY): New macro, to reset I/O to text mode.
	(SET_BINARY, UNSET_BINARY): Include _WIN32 in the conditional for
	MS systems.

	* src/io.c: Include binary-io.h.
	(sip, read_files): Switch file I/O to binary mode and back as
	appropriate, to support binary files on systems that distinguish
	between text and binary I/O.


--- src/io.c~0	2011-08-15 08:24:38.000000000 +0300
+++ src/io.c	2012-05-12 18:55:24.201750000 +0300
@@ -22,6 +22,7 @@
 #include <cmpbuf.h>
 #include <file-type.h>
 #include <xalloc.h>
+#include <binary-io.h>
 
 /* Rotate an unsigned value to the left.  */
 #define ROL(v, n) ((v) << (n) | (v) >> (sizeof (v) * CHAR_BIT - (n)))
@@ -110,12 +111,25 @@ sip (struct file_data *current, bool ski
       if (! skip_test)
 	{
 	  /* Check first part of file to see if it's a binary file.  */
-
-	  /* FIXME: if O_BINARY, this should revert to text mode
-	     if the file is not binary.  */
+	  bool binary_file;
+	  int prev_mode = SET_BINARY (current->desc);
 
 	  file_block_read (current, current->bufsize);
-	  return binary_file_p (current->buffer, current->buffered);
+	  binary_file = binary_file_p (current->buffer, current->buffered);
+	  if (prev_mode != O_BINARY)
+	    {
+	      /* Revert to text mode and seek back to the beginning to
+		 reread the file.  Use relative seek, since file
+		 descriptors like stdin might not start at offset
+		 zero.  */
+
+	      if (lseek (current->desc, -current->buffered, SEEK_CUR) == -1)
+		pfatal_with_name (current->name);
+	      (void) UNSET_BINARY (current->desc);
+              current->buffered = 0;
+              current->eof = false;
+	    }
+	  return binary_file;
 	}
     }
 
@@ -761,7 +775,8 @@ read_files (struct file_data filevec[], 
     }
   if (appears_binary)
     {
-      /* FIXME: If O_BINARY, this should set both files to binary mode.  */
+      (void) SET_BINARY (filevec[0].desc);
+      (void) SET_BINARY (filevec[1].desc);
       return true;
     }
 
--- lib/binary-io.h~1	2012-05-12 17:31:43.639250000 +0300
+++ lib/binary-io.h	2012-05-12 18:19:53.842375000 +0300
@@ -26,9 +26,14 @@
 #include <stdio.h>
 
 /* SET_BINARY (fd);
-   changes the file descriptor fd to perform binary I/O.  */
+   changes the file descriptor fd to perform binary I/O, returns
+   the previous I/O mode.
+
+   UNSET_BINARY (fd);
+   changes the file descriptor fd to perform text I/O, returns
+   the previous I/O mode. */
 #if O_BINARY
-# if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__
+# if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__ || defined _WIN32
 #  include <io.h> /* declares setmode() */
 # else
 #  define setmode _setmode
@@ -40,13 +45,15 @@
    /* Avoid putting stdin/stdout in binary mode if it is connected to
       the console, because that would make it impossible for the user
       to interrupt the program through Ctrl-C or Ctrl-Break.  */
-#  define SET_BINARY(fd) ((void) (!isatty (fd) ? (setmode (fd, O_BINARY), 0) : 0))
+#  define SET_BINARY(fd) (!isatty (fd) ? setmode (fd, O_BINARY) : -1)
 # else
-#  define SET_BINARY(fd) ((void) setmode (fd, O_BINARY))
+#  define SET_BINARY(fd) (setmode (fd, O_BINARY))
 # endif
+# define UNSET_BINARY(fd) (setmode (fd, O_TEXT))
 #else
   /* On reasonable systems, binary I/O is the default.  */
-# define SET_BINARY(fd) /* do nothing */ ((void) 0)
+# define SET_BINARY(fd) /* do nothing */ (O_BINARY)
+# define UNSET_BINARY(fd) /* do nothing */ (-1)
 #endif
 
 #endif /* _BINARY_H */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.