Allow builtin source to read from non-regular files

Commit a91bf6d88 (builtin.c: builtin_source now checks that its argument is
a file., 2005-12-16) fixed an infinite loop for commands like "source /"
where the argument is a directory.

It did so by erroring out early unless the filename argument is a regular file.
This is too restrictive; it disallows reading from special files like /dev/null
and fifos.
Today we get a sensible error without this check, so remove it.
This commit is contained in:
Johannes Altmanninger 2024-10-13 10:37:58 +02:00
parent ba67d20b7c
commit 00875d0f83
2 changed files with 11 additions and 24 deletions

View File

@ -1,5 +1,4 @@
use std::os::fd::AsRawFd;
use std::os::unix::fs::MetadataExt;
use crate::{
common::{escape, scoped_push_replacer, FilenameRef},
@ -7,9 +6,7 @@ use crate::{
nix::isatty,
parser::Block,
reader::reader_read,
wutil::fstat,
};
use libc::{S_IFMT, S_IFREG};
use nix::{fcntl::OFlag, sys::stat::Mode};
use super::prelude::*;
@ -70,27 +67,6 @@ pub fn source(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> O
};
fd = opened_file.as_raw_fd();
let md = match fstat(fd) {
Ok(md) => md,
Err(_) => {
let esc = escape(args[optind]);
streams.err.append(wgettext_fmt!(
"%ls: Error encountered while sourcing file '%ls':\n",
cmd,
&esc
));
return STATUS_CMD_ERROR;
}
};
#[allow(clippy::useless_conversion)]
if md.mode() & u32::from(S_IFMT) != u32::from(S_IFREG) {
let esc = escape(args[optind]);
streams
.err
.append(wgettext_fmt!("%ls: '%ls' is not a file\n", cmd, esc));
return STATUS_CMD_ERROR;
}
func_filename = FilenameRef::new(args[optind].to_owned());
}

11
tests/checks/source.fish Normal file
View File

@ -0,0 +1,11 @@
#RUN: %fish %s
source /dev/null
echo $status
# CHECK: 0
source /
echo $status
# CHECKERR: error: Unable to read input file: Is a directory
# CHECKERR: source: Error while reading file '/'
# CHECK: 1