Remove redirection_is_to_real_file

This was previously required so that, if there was a redirection to a
file, we would fork a process to create the file even if there was no
output. For example `echo -n >/tmp/file.txt` would have to create
file.txt even though it would be empty.

However now we open the file before fork, so we no longer need special
logic around this.
This commit is contained in:
ridiculousfish 2019-12-20 14:40:57 -08:00
parent 17b499d2ea
commit 97dd5ece26
2 changed files with 18 additions and 22 deletions

View File

@ -71,19 +71,6 @@ void exec_close(int fd) {
}
}
/// Returns true if the redirection is a file redirection to a file other than /dev/null.
static bool redirection_is_to_real_file(const shared_ptr<const io_data_t> &io) {
bool result = false;
if (io && io->io_mode == io_mode_t::file) {
// It's a file redirection. Compare the path to /dev/null.
if (!static_cast<const io_file_t *>(io.get())->is_dev_null()) {
// It's not /dev/null.
result = true;
}
}
return result;
}
/// Returns the interpreter for the specified script. Returns NULL if file is not a script with a
/// shebang.
char *get_interpreter(const char *command, char *interpreter, size_t buff_size) {
@ -499,13 +486,8 @@ static bool handle_builtin_output(parser_t &parser, const std::shared_ptr<job_t>
p->status = proc_status_t::from_exit_code(STATUS_READ_TOO_MUCH);
}
// We will try to elide constructing an internal process. However if the output is going to a
// real file, we have to do it. For example in `echo -n > file.txt` we proceed to open file.txt
// even though there is no output, so that it is properly truncated.
const shared_ptr<const io_data_t> stdout_io = io_chain->io_for_fd(STDOUT_FILENO);
const shared_ptr<const io_data_t> stderr_io = io_chain->io_for_fd(STDERR_FILENO);
bool must_use_process =
redirection_is_to_real_file(stdout_io) || redirection_is_to_real_file(stderr_io);
// If we are directing output to a buffer, then we can just transfer it directly without needing
// to write to the bufferfill pipe. Note this is how we handle explicitly separated stdout
@ -554,7 +536,7 @@ static bool handle_builtin_output(parser_t &parser, const std::shared_ptr<job_t>
errbuff.clear();
}
if (!must_use_process && outbuff.empty() && errbuff.empty()) {
if (outbuff.empty() && errbuff.empty()) {
// We do not need to construct a background process.
// TODO: factor this job-status-setting stuff into a single place.
p->completed = true;

View File

@ -9,19 +9,19 @@ outnerr 0 &| count
#CHECK: 2
set -l tmpdir (mktemp -d)
outnerr overwrite &> $tmpdir/file.txt
outnerr overwrite &>$tmpdir/file.txt
cat $tmpdir/file.txt
#CHECK: out overwrite
#CHECK: err overwrite
outnerr append &>> $tmpdir/file.txt
outnerr append &>>$tmpdir/file.txt
cat $tmpdir/file.txt
#CHECK: out overwrite
#CHECK: err overwrite
#CHECK: out append
#CHECK: err append
echo noclobber &>>? $tmpdir/file.txt
echo noclobber &>>?$tmpdir/file.txt
#CHECKERR: {{.*}} The file {{.*}} already exists
eval "echo foo |& false"
@ -29,4 +29,18 @@ eval "echo foo |& false"
#CHECKERR: echo foo |& false
#CHECKERR: ^
# Ensure that redirection empty data still creates the file.
rm -f $tmpdir/file.txt
test -f $tmpdir/file.txt && echo "File exists" || echo "File does not exist"
#CHECK: File does not exist
echo -n >$tmpdir/file.txt
test -f $tmpdir/file.txt && echo "File exists" || echo "File does not exist"
#CHECK: File exists
rm $tmpdir/file.txt
echo -n 2>$tmpdir/file.txt
test -f $tmpdir/file.txt && echo "File exists" || echo "File does not exist"
#CHECK: File exists
rm -Rf $tmpdir