Re: 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]>
> Date: Sat, 12 May 2012 19:17:01 +0300
> From: Eli Zaretskii <[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.

Sorry, I found 2 subtle mistakes in the patches I sent.  Please use
the ones below instead:

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 __MINGW32__
 #  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) : O_BINARY)
 # 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.