Subject: Re: bug#20795: [PATCH][TRY2] Fix behavior of --follow-symlinks on stdin

From: Jim Meyering <[email-masked]>
Date: Wed, 15 Jul 2015 21:45:42 -0700

On Mon, Jul 13, 2015 at 1:59 PM, Stanislav Brabec <[email-masked]> wrote:
> When reading from stdin, --follow-symlinks causes failure since
> v4.2.1-13-g84066bf:
> echo abc | sed --follow-symlinks s/a/d/
> sed: cannot stat -: No such file or directory
>
> Never call follow_symlink("-") to prevent this problem.
> http://bugs.gnu.org/20795

Thank you for the patch.
I've made only a few small changes.
E.g., I added the ChangeLog-style commit log we require,
adjusting wording in a few places, and I removed some
useless quotes in the new test file.

Just in case, I'll wait for you to review and ack before pushing this.
From e387009c78fa08aaebf5192a3ceeb04dcfc7781d Mon Sep 17 00:00:00 2001
From: Stanislav Brabec <[email-masked]>
Date: Mon, 13 Jul 2015 22:59:17 +0200
Subject: [PATCH] sed: fix --follow-symlinks to work when reading stdin

When reading from stdin, use of --follow-symlinks would cause failure:

  $ echo abc | sed --follow-symlinks s/a/d/
  sed: cannot stat -: No such file or directory

* sed/execute.c (open_next_file): Set input->in_file_name earlier,
so we can rearrange logic to avoid calling follow_symlink("-").
* testsuite/follow-symlinks-stdin.sh: New file.
* testsuite/Makefile.am (T): Add it.
* NEWS (Bug fixes): Mention it.
Bug introduced by commit v4.2.1-13-g84066bf.
http://bugs.gnu.org/20795
---
 NEWS                               |  3 +++
 sed/execute.c                      | 24 +++++++++++++-----------
 testsuite/Makefile.am              |  1 +
 testsuite/follow-symlinks-stdin.sh | 29 +++++++++++++++++++++++++++++
 4 files changed, 46 insertions(+), 11 deletions(-)
 create mode 100755 testsuite/follow-symlinks-stdin.sh

diff --git a/NEWS b/NEWS
index 61b8aa2..6367dea 100644
--- a/NEWS
+++ b/NEWS
@@ -37,6 +37,9 @@ GNU sed NEWS                                    -*- outline -*-
   leaves behind a temporary file.  Before, that command would create a file
   alongside F with a name matching /^sed......$/ and fail to remove it.

+  sed --follow-symlinks now works again for stdin.
+  [bug introduced in sed-4.2.2]
+
 ** Feature removal

   The "L" command (format a paragraph like the fmt(1) command would)
diff --git a/sed/execute.c b/sed/execute.c
index 49cfb45..7bc394a 100644
--- a/sed/execute.c
+++ b/sed/execute.c
@@ -549,6 +549,7 @@ open_next_file(const char *name, struct input *input)
 {
   buffer.length = 0;

+  input->in_file_name = name;
   if (name[0] == '-' && name[1] == '\0')
     {
       if (in_place_extension)
@@ -562,22 +563,23 @@ open_next_file(const char *name, struct input *input)
       input->fp = stdin;
 #endif
     }
-  else if ( ! (input->fp = ck_fopen(name, read_mode, false)) )
+  else
     {
-      const char *ptr = strerror(errno);
-      fprintf(stderr, _("%s: can't read %s: %s\n"), myname, name, ptr);
-      input->read_fn = read_always_fail; /* a redundancy */
-      ++input->bad_count;
-      return;
+      if (follow_symlinks)
+        input->in_file_name = follow_symlink (name);
+
+      if ( ! (input->fp = ck_fopen (name, read_mode, false)) )
+        {
+          const char *ptr = strerror (errno);
+          fprintf (stderr, _("%s: can't read %s: %s\n"), myname, name, ptr);
+          input->read_fn = read_always_fail; /* a redundancy */
+          ++input->bad_count;
+          return;
+        }
     }

   input->read_fn = read_file_line;

-  if (follow_symlinks)
-    input->in_file_name = follow_symlink (name);
-  else
-    input->in_file_name = name;
-
   if (in_place_extension)
     {
       int input_fd;
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index bfffda0..9bd7465 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -6,6 +6,7 @@ SH_LOG_COMPILER = $(SHELL)
 # Put new, init.sh-using tests here, so that each name
 # is listed in only one place.
 T =			\
+  follow-symlinks-stdin.sh \
   help-version.sh	\
   in-place-hyphen.sh	\
   invalid-mb-seq-UMR.sh	\
diff --git a/testsuite/follow-symlinks-stdin.sh b/testsuite/follow-symlinks-stdin.sh
new file mode 100755
index 0000000..3440439
--- /dev/null
+++ b/testsuite/follow-symlinks-stdin.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+# Verify that --follow-symlinks does not break reading from stdin.
+
+# Copyright (C) 2015 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+. "${srcdir=.}/init.sh"; path_prepend_ ../sed
+print_ver_ sed
+
+echo dbc > exp-out || framework_failure_
+
+fail=0
+echo abc | sed --follow-symlinks s/a/d/ > out 2> err || fail=1
+
+compare exp-out out || fail=1
+compare /dev/null err || fail=1
+
+Exit $fail
-- 
2.3.7