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]>
> From: Bruno Haible <[email protected]>
> Cc: [email protected], [email protected]
> Date: Sat, 12 May 2012 21:04:17 +0200
> 
> Eli Zaretskii wrote:
> > > I would suggest to use a function
> > > 
> > >   int setmode (int fd, int o_mode);
> > > 
> > > exactly like in Cygwin, so that no code is needed on Cygwin.
> > 
> > You mean, us it directly, not through a macro?
> 
> I meant, through a macro or a function, depending on what's easiest on each
> platform.

Like this?

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

	* lib/binary-io.h [O_BINARY]: Include io.h on all systems that
	have non-zero O_BINARY.
	(O_TEXT) [!O_BINARY]: Define if not defined.
	(setmode) [!O_BINARY]: Define to do nothing and return O_BINARY.

	* 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 22:49:54.561125000 +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 = setmode (current->desc, O_BINARY);
 
 	  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) setmode (current->desc, O_TEXT);
+              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) setmode (filevec[0].desc, O_BINARY);
+      (void) setmode (filevec[1].desc, O_BINARY);
       return true;
     }
 
--- lib/binary-io.h~1	2012-05-12 17:31:43.639250000 +0300
+++ lib/binary-io.h	2012-05-12 22:50:07.217375000 +0300
@@ -28,9 +28,8 @@
 /* SET_BINARY (fd);
    changes the file descriptor fd to perform binary I/O.  */
 #if O_BINARY
-# if defined __EMX__ || defined __DJGPP__ || defined __CYGWIN__
-#  include <io.h> /* declares setmode() */
-# else
+# include <io.h> /* declares setmode() */
+# if !defined __EMX__ && !defined __DJGPP__ && !defined __CYGWIN__
 #  define setmode _setmode
 #  undef fileno
 #  define fileno _fileno
@@ -46,7 +45,14 @@
 # endif
 #else
   /* On reasonable systems, binary I/O is the default.  */
+# ifndef O_BINARY
+#  define O_BINARY 0
+# endif
+# ifndef O_TEXT
+#  define O_TEXT 0
+# endif
 # define SET_BINARY(fd) /* do nothing */ ((void) 0)
+# define setmode(fd,m)                   (O_BINARY)
 #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.