From e387009c78fa08aaebf5192a3ceeb04dcfc7781d Mon Sep 17 00:00:00 2001 From: Stanislav Brabec 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 . +. "${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