On 02/15/2017 06:23 AM, Eric Blake wrote:
xfreopen() may need a patch
Thanks for pointing out the problems with my suggestion. I think I'd rather leave xfreopen alone, as silently adjusting its argument from "wb" to "ab" might cause other problems. Instead, I added a Gnulib module to set the file's text-vs-binary mode and changed grep to use that, by installing the attached patches, which I hope address your comments.
From cde60563801884ae65546090b24cb92620b1f828 Mon Sep 17 00:00:00 2001 From: Paul Eggert <eggert@cs.ucla.edu> Date: Thu, 16 Feb 2017 08:40:29 -0800 Subject: [PATCH 1/2] build: update gnulib submodule to latest --- gnulib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gnulib b/gnulib index b6acb8d..fad631e 160000 --- a/gnulib +++ b/gnulib @@ -1 +1 @@ -Subproject commit b6acb8db44af728e88a065526be035f7b927c0bf +Subproject commit fad631e74dd6c1f0c7fadd99bad1b4b732f6eeb8 -- 2.9.3
From c4485ac49a977d666187db4c5c25045215976577 Mon Sep 17 00:00:00 2001 From: Paul Eggert <eggert@cs.ucla.edu> Date: Thu, 16 Feb 2017 08:51:34 -0800 Subject: [PATCH 2/2] Fix up recent -U patches Inspired by a suggestion by Eric Blake (Bug#25707#17). * bootstrap.conf (gnulib_modules): Add xbinary-io, and remove binary-io and xfreopen. * doc/grep.texi (Other Options): Fix typo and reword to be a bit more general. * src/grep.c: Include xbinary-io.h instead of xfreopen.h. (grepfile): Open with O_BINARY if binary. (grepdesc): No need for set_binary_mode now. (grep_command_line_arg, main): Set stdin to binary mode if binary. (main): Avoid unnecessary test of stdin == NULL. Use xsetmode instead of xfreopen. * src/system.h: Do not include binary-io.h. --- bootstrap.conf | 7 +++---- doc/grep.texi | 27 ++++++++++++++------------- src/grep.c | 27 ++++++++++++--------------- src/system.h | 1 - 4 files changed, 29 insertions(+), 33 deletions(-) diff --git a/bootstrap.conf b/bootstrap.conf index 4115f35..1c50974 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -26,7 +26,6 @@ gnulib_modules=' alloca announce-gen argmatch -binary-io c-ctype closeout dfa @@ -53,10 +52,10 @@ isatty isblank iswctype largefile -lseek locale -malloc-gnu +lseek maintainer-makefile +malloc-gnu manywarnings mbrlen mbrtowc @@ -95,7 +94,7 @@ wcrtomb wctob wctype-h xalloc -xfreopen +xbinary-io xstrtoimax ' gnulib_name=libgreputils diff --git a/doc/grep.texi b/doc/grep.texi index 94a0621..077c05f 100644 --- a/doc/grep.texi +++ b/doc/grep.texi @@ -741,25 +741,26 @@ This can cause a performance penalty. @opindex -U @opindex --binary @cindex MS-Windows binary I/O -@cindex binary I/O, /MS-Windows -Under MS-Windows, use binary I/O when reading and writing files other +@cindex binary I/O +On platforms that distinguish between text and binary I/O, +use the latter when reading and writing files other than the user's terminal, so that all input bytes are read and written as-is. This overrides the default behavior where @command{grep} -follows the operating system's advice whether to use binary or text -I/O. When @command{grep} uses text I/O it reads a carriage -return--newline pair as a newline and a Control-Z as end-of-file, and -it writes a newline as a carriage return--newline pair. When this -option is combined with @option{--byte-offset} (@option{-b}), byte -counts treat each text I/O carriage return--newline as a single byte. - -When using text I/O, @option{--binary-files} heuristics are applied to -input data after text-I/O processing. These heuristics need not agree +follows the operating system's advice whether to use text or binary +I/O@. On MS-Windows when @command{grep} uses text I/O it reads a +carriage return--newline pair as a newline and a Control-Z as +end-of-file, and it writes a newline as a carriage return--newline +pair. + +When using text I/O @option{--byte-offset} (@option{-b}) counts and +@option{--binary-files} heuristics apply to input data after text-I/O +processing. Also, the @option{--binary-files} heuristics need not agree with the @option{--binary} option; that is, they may treat the data as text even if @option{--binary} is given, or vice versa. @xref{File and Directory Selection}. -This option has no effect on platforms other than MS-Windows. - +This option has no effect on GNU and other POSIX-compatible platforms, +which do not distinguish text from binary I/O. @item -z @itemx --null-data diff --git a/src/grep.c b/src/grep.c index 32cb642..775f227 100644 --- a/src/grep.c +++ b/src/grep.c @@ -48,7 +48,7 @@ #include "search.h" #include "version-etc.h" #include "xalloc.h" -#include "xfreopen.h" +#include "xbinary-io.h" #include "xstrtol.h" enum { SEP_CHAR_SELECTED = ':' }; @@ -1700,6 +1700,7 @@ static bool grepfile (int dirdesc, char const *name, bool follow, bool command_line) { int oflag = (O_RDONLY | O_NOCTTY + | (binary ? O_BINARY : 0) | (follow ? 0 : O_NOFOLLOW) | (skip_devices (command_line) ? O_NONBLOCK : 0)); int desc = openat_safer (dirdesc, name, oflag); @@ -1854,11 +1855,6 @@ grepdesc (int desc, bool command_line) goto closeout; } - /* Set input to binary mode. Pipes are simulated with files - on DOS, so this includes the case of "foo | grep bar". */ - if (binary && !isatty (desc)) - set_binary_mode (desc, O_BINARY); - count = grep (desc, &st, &ineof); if (count_matches) { @@ -1899,6 +1895,8 @@ grep_command_line_arg (char const *arg) if (STREQ (arg, "-")) { filename = label; + if (binary) + xset_binary_mode (STDIN_FILENO, O_BINARY); return grepdesc (STDIN_FILENO, true); } else @@ -2579,14 +2577,15 @@ main (int argc, char **argv) if (STREQ (optarg, "-")) { if (binary) - xfreopen (NULL, "rb", stdin); + xset_binary_mode (STDIN_FILENO, O_BINARY); fp = stdin; } else - fp = fopen (optarg, binary ? "rb" : "r"); - - if (!fp) - die (EXIT_TROUBLE, errno, "%s", optarg); + { + fp = fopen (optarg, binary ? "rb" : "r"); + if (!fp) + die (EXIT_TROUBLE, errno, "%s", optarg); + } oldcc = keycc; for (;; keycc += cc) { @@ -2897,10 +2896,8 @@ main (int argc, char **argv) if ((argc - optind > 1 && !no_filenames) || with_filenames) out_file = 1; - /* Output is set to binary mode because we shouldn't convert - NL to CR-LF pairs, especially when grepping binary files. */ - if (binary && !isatty (STDOUT_FILENO)) - xfreopen (NULL, "wb", stdout); + if (binary) + xset_binary_mode (STDOUT_FILENO, O_BINARY); /* Prefer sysconf for page size, as getpagesize typically returns int. */ #ifdef _SC_PAGESIZE diff --git a/src/system.h b/src/system.h index 05d8f1a..6292a28 100644 --- a/src/system.h +++ b/src/system.h @@ -23,7 +23,6 @@ #include <unistd.h> #include <errno.h> -#include "binary-io.h" #include "configmake.h" #include "dirname.h" #include "ignore-value.h" -- 2.9.3