From 35793fc2607e504d21235cf78d903e29d831bc0c Mon Sep 17 00:00:00 2001 From: Jan Verbeek Date: Wed, 25 Aug 2021 14:09:24 +0200 Subject: [PATCH] wc: Accept badly-encoded filenames --- src/uu/wc/src/wc.rs | 33 ++++++++++++++++----------------- src/uu/wc/src/word_count.rs | 5 +++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/uu/wc/src/wc.rs b/src/uu/wc/src/wc.rs index 5b0ae0a0a..5832db25f 100644 --- a/src/uu/wc/src/wc.rs +++ b/src/uu/wc/src/wc.rs @@ -23,7 +23,7 @@ use thiserror::Error; use std::cmp::max; use std::fs::{self, File}; use std::io::{self, ErrorKind, Write}; -use std::path::Path; +use std::path::{Path, PathBuf}; /// The minimum character width for formatting counts when reading from stdin. const MINIMUM_WIDTH: usize = 7; @@ -33,7 +33,7 @@ pub enum WcError { #[error("{0}")] Io(#[from] io::Error), #[error("Expected a file, found directory {0}")] - IsDirectory(String), + IsDirectory(PathBuf), } type WcResult = Result; @@ -117,7 +117,7 @@ enum StdinKind { /// Supported inputs. enum Input { /// A regular file. - Path(String), + Path(PathBuf), /// Standard input. Stdin(StdinKind), @@ -125,10 +125,10 @@ enum Input { impl Input { /// Converts input to title that appears in stats. - fn to_title(&self) -> Option<&str> { + fn to_title(&self) -> Option<&Path> { match self { Input::Path(path) => Some(path), - Input::Stdin(StdinKind::Explicit) => Some("-"), + Input::Stdin(StdinKind::Explicit) => Some("-".as_ref()), Input::Stdin(StdinKind::Implicit) => None, } } @@ -140,13 +140,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 { let matches = uu_app().usage(&usage[..]).get_matches_from(args); let mut inputs: Vec = matches - .values_of(ARG_FILES) + .values_of_os(ARG_FILES) .map(|v| { v.map(|i| { if i == "-" { Input::Stdin(StdinKind::Explicit) } else { - Input::Path(ToString::to_string(i)) + Input::Path(i.into()) } }) .collect() @@ -206,7 +206,7 @@ pub fn uu_app() -> App<'static, 'static> { fn word_count_from_reader( mut reader: T, settings: &Settings, - path: &str, + path: &Path, ) -> WcResult { let only_count_bytes = settings.show_bytes && (!(settings.show_chars @@ -273,7 +273,7 @@ fn word_count_from_reader( total.bytes += bytes.len(); } Err(BufReadDecoderError::Io(e)) => { - show_warning!("Error while reading {}: {}", path, e); + show_warning!("Error while reading {}: {}", path.display(), e); } } } @@ -288,11 +288,10 @@ fn word_count_from_input(input: &Input, settings: &Settings) -> WcResult { let stdin = io::stdin(); let stdin_lock = stdin.lock(); - word_count_from_reader(stdin_lock, settings, "-") + word_count_from_reader(stdin_lock, settings, "-".as_ref()) } Input::Path(path) => { - let path_obj = Path::new(path); - if path_obj.is_dir() { + if path.is_dir() { Err(WcError::IsDirectory(path.to_owned())) } else { let file = File::open(path)?; @@ -314,10 +313,10 @@ fn word_count_from_input(input: &Input, settings: &Settings) -> WcResult { - show_error_custom_description!(path, "Is a directory"); + show_error_custom_description!(path.display(), "Is a directory"); } (Input::Path(path), WcError::Io(e)) if e.kind() == ErrorKind::NotFound => { - show_error_custom_description!(path, "No such file or directory"); + show_error_custom_description!(path.display(), "No such file or directory"); } (_, e) => { show_error!("{}", e); @@ -428,7 +427,7 @@ fn wc(inputs: Vec, settings: &Settings) -> Result<(), u32> { if let Err(err) = print_stats(settings, &result, max_width) { show_warning!( "failed to print result for {}: {}", - result.title.unwrap_or(""), + result.title.unwrap_or_else(|| "".as_ref()).display(), err ); error_count += 1; @@ -436,7 +435,7 @@ fn wc(inputs: Vec, settings: &Settings) -> Result<(), u32> { } if num_inputs > 1 { - let total_result = total_word_count.with_title(Some("total")); + let total_result = total_word_count.with_title(Some("total".as_ref())); if let Err(err) = print_stats(settings, &total_result, max_width) { show_warning!("failed to print total: {}", err); error_count += 1; @@ -506,7 +505,7 @@ fn print_stats( } if let Some(title) = result.title { - writeln!(stdout_lock, " {}", title)?; + writeln!(stdout_lock, " {}", title.display())?; } else { writeln!(stdout_lock)?; } diff --git a/src/uu/wc/src/word_count.rs b/src/uu/wc/src/word_count.rs index ac9de390c..617b811fc 100644 --- a/src/uu/wc/src/word_count.rs +++ b/src/uu/wc/src/word_count.rs @@ -1,5 +1,6 @@ use std::cmp::max; use std::ops::{Add, AddAssign}; +use std::path::Path; #[derive(Debug, Default, Copy, Clone)] pub struct WordCount { @@ -31,7 +32,7 @@ impl AddAssign for WordCount { } impl WordCount { - pub fn with_title(self, title: Option<&str>) -> TitledWordCount { + pub fn with_title(self, title: Option<&Path>) -> TitledWordCount { TitledWordCount { title, count: self } } } @@ -42,6 +43,6 @@ impl WordCount { /// it would result in unnecessary copying of `String`. #[derive(Debug, Default, Clone)] pub struct TitledWordCount<'a> { - pub title: Option<&'a str>, + pub title: Option<&'a Path>, pub count: WordCount, }