sort: crash when failing to open an input file (#2265)

* sort: crash when failing to open an input file

Instead of ignoring files we fail to open, crash.
The error message does not exactly match gnu, but that would require
more effort.

* use split_whitespace instead of a manual implementation

* fix expected error on windows

* sort: update expected error message
This commit is contained in:
Michael Debertol 2021-05-28 22:39:33 +02:00 committed by GitHub
parent e9656a6c32
commit bb268d1500
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 11 deletions

View file

@ -26,7 +26,7 @@ use std::{
///
/// The code we should exit with.
pub fn check(path: &str, settings: &GlobalSettings) -> i32 {
let file = open(path).expect("failed to open input file");
let file = open(path);
let (recycled_sender, recycled_receiver) = sync_channel(2);
let (loaded_sender, loaded_receiver) = sync_channel(2);
thread::spawn({

View file

@ -29,7 +29,7 @@ pub fn merge<'a>(files: &[impl AsRef<OsStr>], settings: &'a GlobalSettings) -> F
let (request_sender, request_receiver) = channel();
let mut reader_files = Vec::with_capacity(files.len());
let mut loaded_receivers = Vec::with_capacity(files.len());
for (file_number, file) in files.iter().filter_map(open).enumerate() {
for (file_number, file) in files.iter().map(open).enumerate() {
let (sender, receiver) = sync_channel(2);
loaded_receivers.push(receiver);
reader_files.push(ReaderFile {

View file

@ -955,7 +955,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let mut files = Vec::new();
for path in &files0_from {
let reader = open(path.as_str()).expect("Could not read from file specified.");
let reader = open(path.as_str());
let buf_reader = BufReader::new(reader);
for line in buf_reader.split(b'\0').flatten() {
files.push(
@ -1116,7 +1116,7 @@ fn exec(files: &[String], settings: &GlobalSettings) -> i32 {
}
return check::check(files.first().unwrap(), settings);
} else {
let mut lines = files.iter().filter_map(open);
let mut lines = files.iter().map(open);
ext_sort(&mut lines, &settings);
}
@ -1413,18 +1413,17 @@ fn print_sorted<'a, T: Iterator<Item = &'a Line<'a>>>(iter: T, settings: &Global
}
// from cat.rs
fn open(path: impl AsRef<OsStr>) -> Option<Box<dyn Read + Send>> {
fn open(path: impl AsRef<OsStr>) -> Box<dyn Read + Send> {
let path = path.as_ref();
if path == "-" {
let stdin = stdin();
return Some(Box::new(stdin) as Box<dyn Read + Send>);
return Box::new(stdin) as Box<dyn Read + Send>;
}
match File::open(Path::new(path)) {
Ok(f) => Some(Box::new(f) as Box<dyn Read + Send>),
Ok(f) => Box::new(f) as Box<dyn Read + Send>,
Err(e) => {
show_error!("{0:?}: {1}", path, e.to_string());
None
crash!(2, "cannot read: {0:?}: {1}", path, e);
}
}
}

View file

@ -4,14 +4,14 @@ fn test_helper(file_name: &str, possible_args: &[&str]) {
for args in possible_args {
new_ucmd!()
.arg(format!("{}.txt", file_name))
.args(&args.split(' ').collect::<Vec<&str>>())
.args(&args.split_whitespace().collect::<Vec<&str>>())
.succeeds()
.stdout_is_fixture(format!("{}.expected", file_name));
new_ucmd!()
.arg(format!("{}.txt", file_name))
.arg("--debug")
.args(&args.split(' ').collect::<Vec<&str>>())
.args(&args.split_whitespace().collect::<Vec<&str>>())
.succeeds()
.stdout_is_fixture(format!("{}.expected.debug", file_name));
}
@ -723,3 +723,17 @@ fn test_trailing_separator() {
.succeeds()
.stdout_is("aax\naaa\n");
}
#[test]
fn test_nonexistent_file() {
new_ucmd!()
.arg("nonexistent.txt")
.fails()
.status_code(2)
.stderr_only(
#[cfg(not(windows))]
"sort: cannot read: \"nonexistent.txt\": No such file or directory (os error 2)",
#[cfg(windows)]
"sort: cannot read: \"nonexistent.txt\": The system cannot find the file specified. (os error 2)",
);
}