mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
Fix sum to handle non-UTF-8 filenames
This commit is contained in:
parent
6e55a2a3bb
commit
fddaa1187a
2 changed files with 42 additions and 24 deletions
|
|
@ -6,6 +6,7 @@
|
|||
// spell-checker:ignore (ToDO) sysv
|
||||
|
||||
use clap::{Arg, ArgAction, Command};
|
||||
use std::ffi::OsString;
|
||||
use std::fs::File;
|
||||
use std::io::{ErrorKind, Read, Write, stdin, stdout};
|
||||
use std::path::Path;
|
||||
|
|
@ -67,27 +68,26 @@ fn sysv_sum(mut reader: impl Read) -> std::io::Result<(usize, u16)> {
|
|||
Ok((blocks_read, ret as u16))
|
||||
}
|
||||
|
||||
fn open(name: &str) -> UResult<Box<dyn Read>> {
|
||||
match name {
|
||||
"-" => Ok(Box::new(stdin()) as Box<dyn Read>),
|
||||
_ => {
|
||||
let path = &Path::new(name);
|
||||
if path.is_dir() {
|
||||
return Err(USimpleError::new(
|
||||
2,
|
||||
translate!("sum-error-is-directory", "name" => name.maybe_quote()),
|
||||
));
|
||||
}
|
||||
// Silent the warning as we want to the error message
|
||||
if path.metadata().is_err() {
|
||||
return Err(USimpleError::new(
|
||||
2,
|
||||
translate!("sum-error-no-such-file-or-directory", "name" => name.maybe_quote()),
|
||||
));
|
||||
}
|
||||
let f = File::open(path).map_err_context(String::new)?;
|
||||
Ok(Box::new(f) as Box<dyn Read>)
|
||||
fn open(name: &OsString) -> UResult<Box<dyn Read>> {
|
||||
if name == "-" {
|
||||
Ok(Box::new(stdin()) as Box<dyn Read>)
|
||||
} else {
|
||||
let path = Path::new(name);
|
||||
if path.is_dir() {
|
||||
return Err(USimpleError::new(
|
||||
2,
|
||||
translate!("sum-error-is-directory", "name" => name.to_string_lossy().maybe_quote()),
|
||||
));
|
||||
}
|
||||
// Silent the warning as we want to the error message
|
||||
if path.metadata().is_err() {
|
||||
return Err(USimpleError::new(
|
||||
2,
|
||||
translate!("sum-error-no-such-file-or-directory", "name" => name.to_string_lossy().maybe_quote()),
|
||||
));
|
||||
}
|
||||
let f = File::open(path).map_err_context(String::new)?;
|
||||
Ok(Box::new(f) as Box<dyn Read>)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,9 +101,9 @@ mod options {
|
|||
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||
let matches = uu_app().get_matches_from_localized(args);
|
||||
|
||||
let files: Vec<String> = match matches.get_many::<String>(options::FILE) {
|
||||
let files: Vec<OsString> = match matches.get_many::<OsString>(options::FILE) {
|
||||
Some(v) => v.cloned().collect(),
|
||||
None => vec!["-".to_owned()],
|
||||
None => vec![OsString::from("-")],
|
||||
};
|
||||
|
||||
let sysv = matches.get_flag(options::SYSTEM_V_COMPATIBLE);
|
||||
|
|
@ -127,7 +127,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
|
||||
let mut stdout = stdout().lock();
|
||||
if print_names {
|
||||
writeln!(stdout, "{sum:0width$} {blocks:width$} {file}")?;
|
||||
writeln!(
|
||||
stdout,
|
||||
"{sum:0width$} {blocks:width$} {}",
|
||||
file.to_string_lossy()
|
||||
)?;
|
||||
} else {
|
||||
writeln!(stdout, "{sum:0width$} {blocks:width$}")?;
|
||||
}
|
||||
|
|
@ -146,7 +150,8 @@ pub fn uu_app() -> Command {
|
|||
Arg::new(options::FILE)
|
||||
.action(ArgAction::Append)
|
||||
.hide(true)
|
||||
.value_hint(clap::ValueHint::FilePath),
|
||||
.value_hint(clap::ValueHint::FilePath)
|
||||
.value_parser(clap::value_parser!(OsString)),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(options::BSD_COMPATIBLE)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::os::unix::ffi::OsStringExt;
|
||||
use uutests::at_and_ucmd;
|
||||
use uutests::new_ucmd;
|
||||
|
||||
|
|
@ -80,3 +82,14 @@ fn test_invalid_metadata() {
|
|||
.fails()
|
||||
.stderr_is("sum: b: No such file or directory\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn test_sum_non_utf8_paths() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
let filename = std::ffi::OsString::from_vec(vec![0xFF, 0xFE]);
|
||||
std::fs::write(at.plus(&filename), b"test content").unwrap();
|
||||
|
||||
ucmd.arg(&filename).succeeds();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue