Fix expand to handle non-UTF-8 filenames

This commit is contained in:
Sylvestre Ledru
2025-08-14 10:52:24 +02:00
parent 8b38336036
commit f02436be0f
2 changed files with 26 additions and 8 deletions
+10 -8
View File
@@ -170,7 +170,7 @@ fn tabstops_parse(s: &str) -> Result<(RemainingMode, Vec<usize>), ParseError> {
}
struct Options {
files: Vec<String>,
files: Vec<OsString>,
tabstops: Vec<usize>,
tspaces: String,
iflag: bool,
@@ -204,9 +204,9 @@ impl Options {
.unwrap(); // length of tabstops is guaranteed >= 1
let tspaces = " ".repeat(nspaces);
let files: Vec<String> = match matches.get_many::<String>(options::FILES) {
Some(s) => s.map(|v| v.to_string()).collect(),
None => vec!["-".to_owned()],
let files: Vec<OsString> = match matches.get_many::<OsString>(options::FILES) {
Some(s) => s.cloned().collect(),
None => vec![OsString::from("-")],
};
Ok(Self {
@@ -283,16 +283,18 @@ pub fn uu_app() -> Command {
Arg::new(options::FILES)
.action(ArgAction::Append)
.hide(true)
.value_hint(clap::ValueHint::FilePath),
.value_hint(clap::ValueHint::FilePath)
.value_parser(clap::value_parser!(OsString)),
)
}
fn open(path: &str) -> UResult<BufReader<Box<dyn Read + 'static>>> {
fn open(path: &OsString) -> UResult<BufReader<Box<dyn Read + 'static>>> {
let file_buf;
if path == "-" {
Ok(BufReader::new(Box::new(stdin()) as Box<dyn Read>))
} else {
file_buf = File::open(path).map_err_context(|| path.to_string())?;
let path_ref = Path::new(path);
file_buf = File::open(path_ref).map_err_context(|| path.to_string_lossy().to_string())?;
Ok(BufReader::new(Box::new(file_buf) as Box<dyn Read>))
}
}
@@ -446,7 +448,7 @@ fn expand(options: &Options) -> UResult<()> {
if Path::new(file).is_dir() {
show_error!(
"{}",
translate!("expand-error-is-directory", "file" => file)
translate!("expand-error-is-directory", "file" => file.to_string_lossy())
);
set_exit_code(1);
continue;
+16
View File
@@ -426,3 +426,19 @@ fn test_nonexisting_file() {
.stderr_contains("expand: nonexistent: No such file or directory")
.stdout_contains_line("// !note: file contains significant whitespace");
}
#[test]
#[cfg(target_os = "linux")]
fn test_expand_non_utf8_paths() {
use std::os::unix::ffi::OsStringExt;
use uutests::at_and_ucmd;
let (at, mut ucmd) = at_and_ucmd!();
let filename = std::ffi::OsString::from_vec(vec![0xFF, 0xFE]);
std::fs::write(at.plus(&filename), b"hello\tworld\ntest\tline\n").unwrap();
ucmd.arg(&filename)
.succeeds()
.stdout_is("hello world\ntest line\n");
}