>From 601eceb57cfb87ded594701acc401277c53ff837 Mon Sep 17 00:00:00 2001
From: Paul Eggert
Date: Sat, 5 Jan 2019 19:55:08 -0800
Subject: [PATCH 3/3] diff: fix cmp, diff3, sdiff with stdin closed
* NEWS: Mention this.
* src/cmp.c, src/diff3.c, src/sdiff.c: Include stdopen.h.
(main): Call stdopen early.
* src/cmp.c (main): Simplify now that we need not worry about
stdin being closed.
* src/diff.c (main): Translate stdopen diagnostic.
---
NEWS | 8 ++++++++
src/cmp.c | 28 ++++++++++++++--------------
src/diff.c | 2 +-
src/diff3.c | 4 ++++
src/sdiff.c | 4 ++++
5 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/NEWS b/NEWS
index af675da..9ab0748 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,14 @@ GNU diffutils NEWS -*- outline -*-
transition, or HP-UX even if not setuid.
[bug#33965 introduced in 2.8]
+** Bug fixes
+
+ diff and related programs no longer get confused if stdin, stdout,
+ or stderr are closed. Previously, they sometimes opened files into
+ file descriptors 0, 1, or 2 and then mistakenly did I/O with them
+ that was intended for stdin, stdout, or stderr.
+ [bug#33965 present since "the beginning"]
+
* Noteworthy changes in release 3.7 (2018-12-31) [stable]
diff --git a/src/cmp.c b/src/cmp.c
index 53ff210..7bad6dd 100644
--- a/src/cmp.c
+++ b/src/cmp.c
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -199,7 +200,7 @@ GB 1,000,000,000, G 1,073,741,824, and so on for T, P, E, Z, Y."),
int
main (int argc, char **argv)
{
- int c, f, exit_status;
+ int c, exit_status;
size_t words_per_buffer;
exit_failure = EXIT_TROUBLE;
@@ -209,6 +210,9 @@ main (int argc, char **argv)
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
c_stack_action (0);
+ int stdopen_errno = stdopen ();
+ if (stdopen_errno != 0)
+ error (EXIT_TROUBLE, stdopen_errno, _("standard file descriptors"));
/* Parse command line options. */
@@ -268,7 +272,7 @@ main (int argc, char **argv)
file[0] = argv[optind++];
file[1] = optind < argc ? argv[optind++] : "-";
- for (f = 0; f < 2 && optind < argc; f++)
+ for (int f = 0; f < 2 && optind < argc; f++)
{
char *arg = argv[optind++];
specify_ignore_initial (f, &arg, 0);
@@ -277,33 +281,29 @@ main (int argc, char **argv)
if (optind < argc)
try_help ("extra operand '%s'", argv[optind]);
- for (f = 0; f < 2; f++)
+ for (int f = 0; f < 2; f++)
{
- /* If file[1] is "-", treat it first; this avoids a misdiagnostic if
- stdin is closed and opening file[0] yields file descriptor 0. */
- int f1 = f ^ (STREQ (file[1], "-"));
-
/* Two files with the same name and offset are identical.
But wait until we open the file once, for proper diagnostics. */
if (f && ignore_initial[0] == ignore_initial[1]
&& file_name_cmp (file[0], file[1]) == 0)
return EXIT_SUCCESS;
- if (STREQ (file[f1], "-"))
+ if (STREQ (file[f], "-"))
{
- file_desc[f1] = STDIN_FILENO;
+ file_desc[f] = STDIN_FILENO;
if (O_BINARY && ! isatty (STDIN_FILENO))
set_binary_mode (STDIN_FILENO, O_BINARY);
}
else
- file_desc[f1] = open (file[f1], O_RDONLY | O_BINARY, 0);
+ file_desc[f] = open (file[f], O_RDONLY | O_BINARY, 0);
- if (file_desc[f1] < 0 || fstat (file_desc[f1], stat_buf + f1) != 0)
+ if (file_desc[f] < 0 || fstat (file_desc[f], stat_buf + f) != 0)
{
- if (file_desc[f1] < 0 && comparison_type == type_status)
+ if (file_desc[f] < 0 && comparison_type == type_status)
exit (EXIT_TROUBLE);
else
- die (EXIT_TROUBLE, errno, "%s", file[f1]);
+ die (EXIT_TROUBLE, errno, "%s", file[f]);
}
}
@@ -361,7 +361,7 @@ main (int argc, char **argv)
exit_status = cmp ();
- for (f = 0; f < 2; f++)
+ for (int f = 0; f < 2; f++)
if (close (file_desc[f]) != 0)
die (EXIT_TROUBLE, errno, "%s", file[f]);
if (exit_status != EXIT_SUCCESS && comparison_type < type_no_stdout)
diff --git a/src/diff.c b/src/diff.c
index a5ec7f4..d54782c 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -300,7 +300,7 @@ main (int argc, char **argv)
presume_output_tty = false;
int stdopen_errno = stdopen ();
if (stdopen_errno != 0)
- error (EXIT_TROUBLE, stdopen_errno, "standard file descriptors");
+ error (EXIT_TROUBLE, stdopen_errno, _("standard file descriptors"));
/* Decode the options. */
diff --git a/src/diff3.c b/src/diff3.c
index c7b2840..36bf4a6 100644
--- a/src/diff3.c
+++ b/src/diff3.c
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -272,6 +273,9 @@ main (int argc, char **argv)
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
c_stack_action (0);
+ int stdopen_errno = stdopen ();
+ if (stdopen_errno != 0)
+ error (EXIT_TROUBLE, stdopen_errno, _("standard file descriptors"));
while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != -1)
{
diff --git a/src/sdiff.c b/src/sdiff.c
index 25ce3fe..bbbe16c 100644
--- a/src/sdiff.c
+++ b/src/sdiff.c
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -455,6 +456,9 @@ main (int argc, char *argv[])
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
c_stack_action (cleanup);
+ int stdopen_errno = stdopen ();
+ if (stdopen_errno != 0)
+ error (EXIT_TROUBLE, stdopen_errno, _("standard file descriptors"));
prog = getenv ("EDITOR");
if (prog)
--
2.17.1