> 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 */
