1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

Update message quoting and filename printing

This commit is contained in:
Jan Verbeek 2021-09-03 16:10:39 +02:00
parent 60df3c6b7c
commit 259f18fcab
91 changed files with 777 additions and 550 deletions

View file

@ -9,6 +9,8 @@ bytewise
canonicalization
canonicalize
canonicalizing
codepoint
codepoints
colorizable
colorize
coprime

View file

@ -10,10 +10,12 @@ use clap::Arg;
use clap::Shell;
use std::cmp;
use std::collections::hash_map::HashMap;
use std::ffi::OsStr;
use std::ffi::OsString;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process;
use uucore::display::Quotable;
const VERSION: &str = env!("CARGO_PKG_VERSION");
@ -76,13 +78,21 @@ fn main() {
// 0th argument equals util name?
if let Some(util_os) = util_name {
let util = util_os.as_os_str().to_string_lossy();
fn not_found(util: &OsStr) -> ! {
println!("{}: function/utility not found", util.maybe_quote());
process::exit(1);
}
let util = match util_os.to_str() {
Some(util) => util,
None => not_found(&util_os),
};
if util == "completion" {
gen_completions(args, utils);
}
match utils.get(&util[..]) {
match utils.get(util) {
Some(&(uumain, _)) => {
process::exit(uumain((vec![util_os].into_iter()).chain(args)));
}
@ -90,9 +100,12 @@ fn main() {
if util == "--help" || util == "-h" {
// see if they want help on a specific util
if let Some(util_os) = args.next() {
let util = util_os.as_os_str().to_string_lossy();
let util = match util_os.to_str() {
Some(util) => util,
None => not_found(&util_os),
};
match utils.get(&util[..]) {
match utils.get(util) {
Some(&(uumain, _)) => {
let code = uumain(
(vec![util_os, OsString::from("--help")].into_iter())
@ -101,17 +114,13 @@ fn main() {
io::stdout().flush().expect("could not flush stdout");
process::exit(code);
}
None => {
println!("{}: function/utility not found", util);
process::exit(1);
}
None => not_found(&util_os),
}
}
usage(&utils, binary_as_util);
process::exit(0);
} else {
println!("{}: function/utility not found", util);
process::exit(1);
not_found(&util_os);
}
}
}

View file

@ -9,6 +9,7 @@
use std::io::{stdout, Read, Write};
use uucore::display::Quotable;
use uucore::encoding::{wrap_print, Data, Format};
use uucore::InvalidEncodingHandling;
@ -40,8 +41,9 @@ impl Config {
let name = values.next().unwrap();
if let Some(extra_op) = values.next() {
return Err(format!(
"extra operand '{}'\nTry '{} --help' for more information.",
extra_op, app_name
"extra operand {}\nTry '{} --help' for more information.",
extra_op.quote(),
app_name
));
}
@ -49,7 +51,7 @@ impl Config {
None
} else {
if !Path::exists(Path::new(name)) {
return Err(format!("{}: No such file or directory", name));
return Err(format!("{}: No such file or directory", name.maybe_quote()));
}
Some(name.to_owned())
}
@ -61,7 +63,7 @@ impl Config {
.value_of(options::WRAP)
.map(|num| {
num.parse::<usize>()
.map_err(|_| format!("invalid wrap size: '{}'", num))
.map_err(|_| format!("invalid wrap size: {}", num.quote()))
})
.transpose()?;

View file

@ -20,6 +20,7 @@ use clap::{crate_version, App, Arg};
use std::fs::{metadata, File};
use std::io::{self, Read, Write};
use thiserror::Error;
use uucore::display::Quotable;
use uucore::error::UResult;
#[cfg(unix)]
@ -386,7 +387,7 @@ fn cat_files(files: Vec<String>, options: &OutputOptions) -> UResult<()> {
for path in &files {
if let Err(err) = cat_path(path, options, &mut state, &out_info) {
error_messages.push(format!("{}: {}", path, err));
error_messages.push(format!("{}: {}", path.maybe_quote(), err));
}
}
if state.skipped_carriage_return {

View file

@ -2,7 +2,7 @@
#![allow(clippy::upper_case_acronyms)]
use uucore::{show_error, show_usage_error, show_warning};
use uucore::{display::Quotable, show_error, show_usage_error, show_warning};
use clap::{App, Arg};
use selinux::{OpaqueSecurityContext, SecurityContext};
@ -111,13 +111,13 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
Ok(context) => context,
Err(_r) => {
show_error!("Invalid security context '{}'.", context.to_string_lossy());
show_error!("Invalid security context {}.", context.quote());
return libc::EXIT_FAILURE;
}
};
if SecurityContext::from_c_str(&c_context, false).check() == Some(false) {
show_error!("Invalid security context '{}'.", context.to_string_lossy());
show_error!("Invalid security context {}.", context.quote());
return libc::EXIT_FAILURE;
}
@ -564,7 +564,7 @@ fn process_file(
println!(
"{}: Changing security context of: {}",
uucore::util_name(),
file_full_name.to_string_lossy()
file_full_name.quote()
);
}
@ -699,9 +699,9 @@ fn root_dev_ino_warn(dir_name: &Path) {
);
} else {
show_warning!(
"It is dangerous to operate recursively on '{}' (same as '/'). \
"It is dangerous to operate recursively on {} (same as '/'). \
Use --{} to override this failsafe.",
dir_name.to_string_lossy(),
dir_name.quote(),
options::preserve_root::NO_PRESERVE_ROOT,
);
}
@ -726,8 +726,8 @@ fn emit_cycle_warning(file_name: &Path) {
"Circular directory structure.\n\
This almost certainly means that you have a corrupted file system.\n\
NOTIFY YOUR SYSTEM MANAGER.\n\
The following directory is part of the cycle '{}'.",
file_name.display()
The following directory is part of the cycle {}.",
file_name.quote()
)
}

View file

@ -2,6 +2,8 @@ use std::ffi::OsString;
use std::fmt::Write;
use std::io;
use uucore::display::Quotable;
pub(crate) type Result<T> = std::result::Result<T, Error>;
#[derive(thiserror::Error, Debug)]
@ -30,7 +32,7 @@ pub(crate) enum Error {
source: io::Error,
},
#[error("{operation} failed on '{}'", .operand1.to_string_lossy())]
#[error("{operation} failed on {}", .operand1.quote())]
Io1 {
operation: &'static str,
operand1: OsString,

View file

@ -9,6 +9,7 @@
#[macro_use]
extern crate uucore;
use uucore::display::Quotable;
pub use uucore::entries;
use uucore::error::{FromIo, UResult, USimpleError};
use uucore::perms::{chown_base, options, IfFrom};
@ -32,7 +33,7 @@ fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<(Option<u32>, Option<u32>,
let dest_gid = if let Some(file) = matches.value_of(options::REFERENCE) {
fs::metadata(&file)
.map(|meta| Some(meta.gid()))
.map_err_context(|| format!("failed to get attributes of '{}'", file))?
.map_err_context(|| format!("failed to get attributes of {}", file.quote()))?
} else {
let group = matches.value_of(options::ARG_GROUP).unwrap_or_default();
if group.is_empty() {
@ -40,7 +41,12 @@ fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<(Option<u32>, Option<u32>,
} else {
match entries::grp2gid(group) {
Ok(g) => Some(g),
_ => return Err(USimpleError::new(1, format!("invalid group: '{}'", group))),
_ => {
return Err(USimpleError::new(
1,
format!("invalid group: {}", group.quote()),
))
}
}
}
};

View file

@ -14,6 +14,7 @@ use clap::{crate_version, App, Arg};
use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path;
use uucore::display::Quotable;
use uucore::fs::display_permissions_unix;
use uucore::libc::mode_t;
#[cfg(not(windows))]
@ -75,7 +76,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.value_of(options::REFERENCE)
.and_then(|fref| match fs::metadata(fref) {
Ok(meta) => Some(meta.mode()),
Err(err) => crash!(1, "cannot stat attributes of '{}': {}", fref, err),
Err(err) => crash!(1, "cannot stat attributes of {}: {}", fref.quote(), err),
});
let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required
let cmode = if mode_had_minus_prefix {
@ -223,21 +224,24 @@ impl Chmoder {
if !file.exists() {
if is_symlink(file) {
println!(
"failed to change mode of '{}' from 0000 (---------) to 0000 (---------)",
filename
"failed to change mode of {} from 0000 (---------) to 0000 (---------)",
filename.quote()
);
if !self.quiet {
show_error!("cannot operate on dangling symlink '{}'", filename);
show_error!("cannot operate on dangling symlink {}", filename.quote());
}
} else if !self.quiet {
show_error!("cannot access '{}': No such file or directory", filename);
show_error!(
"cannot access {}: No such file or directory",
filename.quote()
);
}
return Err(1);
}
if self.recursive && self.preserve_root && filename == "/" {
show_error!(
"it is dangerous to operate recursively on '{}'\nuse --no-preserve-root to override this failsafe",
filename
"it is dangerous to operate recursively on {}\nuse --no-preserve-root to override this failsafe",
filename.quote()
);
return Err(1);
}
@ -270,15 +274,17 @@ impl Chmoder {
if is_symlink(file) {
if self.verbose {
println!(
"neither symbolic link '{}' nor referent has been changed",
file.display()
"neither symbolic link {} nor referent has been changed",
file.quote()
);
}
return Ok(());
} else if err.kind() == std::io::ErrorKind::PermissionDenied {
show_error!("'{}': Permission denied", file.display());
// These two filenames would normally be conditionally
// quoted, but GNU's tests expect them to always be quoted
show_error!("{}: Permission denied", file.quote());
} else {
show_error!("'{}': {}", file.display(), err);
show_error!("{}: {}", file.quote(), err);
}
return Err(1);
}
@ -325,7 +331,7 @@ impl Chmoder {
if (new_mode & !naively_expected_new_mode) != 0 {
show_error!(
"{}: new permissions are {}, not {}",
file.display(),
file.maybe_quote(),
display_permissions_unix(new_mode as mode_t, false),
display_permissions_unix(naively_expected_new_mode as mode_t, false)
);
@ -342,8 +348,8 @@ impl Chmoder {
if fperm == mode {
if self.verbose && !self.changes {
println!(
"mode of '{}' retained as {:04o} ({})",
file.display(),
"mode of {} retained as {:04o} ({})",
file.quote(),
fperm,
display_permissions_unix(fperm as mode_t, false),
);
@ -355,8 +361,8 @@ impl Chmoder {
}
if self.verbose {
println!(
"failed to change mode of file '{}' from {:04o} ({}) to {:04o} ({})",
file.display(),
"failed to change mode of file {} from {:04o} ({}) to {:04o} ({})",
file.quote(),
fperm,
display_permissions_unix(fperm as mode_t, false),
mode,
@ -367,8 +373,8 @@ impl Chmoder {
} else {
if self.verbose || self.changes {
println!(
"mode of '{}' changed from {:04o} ({}) to {:04o} ({})",
file.display(),
"mode of {} changed from {:04o} ({}) to {:04o} ({})",
file.quote(),
fperm,
display_permissions_unix(fperm as mode_t, false),
mode,

View file

@ -9,6 +9,7 @@
#[macro_use]
extern crate uucore;
use uucore::display::Quotable;
pub use uucore::entries::{self, Group, Locate, Passwd};
use uucore::perms::{chown_base, options, IfFrom};
@ -44,7 +45,7 @@ fn parse_gid_uid_and_filter(matches: &ArgMatches) -> UResult<(Option<u32>, Optio
let dest_gid: Option<u32>;
if let Some(file) = matches.value_of(options::REFERENCE) {
let meta = fs::metadata(&file)
.map_err_context(|| format!("failed to get attributes of '{}'", file))?;
.map_err_context(|| format!("failed to get attributes of {}", file.quote()))?;
dest_gid = Some(meta.gid());
dest_uid = Some(meta.uid());
} else {
@ -173,7 +174,7 @@ fn parse_spec(spec: &str) -> UResult<(Option<u32>, Option<u32>)> {
let uid = if usr_only || usr_grp {
Some(
Passwd::locate(args[0])
.map_err(|_| USimpleError::new(1, format!("invalid user: '{}'", spec)))?
.map_err(|_| USimpleError::new(1, format!("invalid user: {}", spec.quote())))?
.uid(),
)
} else {
@ -182,7 +183,7 @@ fn parse_spec(spec: &str) -> UResult<(Option<u32>, Option<u32>)> {
let gid = if grp_only || usr_grp {
Some(
Group::locate(args[1])
.map_err(|_| USimpleError::new(1, format!("invalid group: '{}'", spec)))?
.map_err(|_| USimpleError::new(1, format!("invalid group: {}", spec.quote())))?
.gid(),
)
} else {

View file

@ -15,6 +15,7 @@ use std::ffi::CString;
use std::io::Error;
use std::path::Path;
use std::process::Command;
use uucore::display::Quotable;
use uucore::libc::{self, chroot, setgid, setgroups, setuid};
use uucore::{entries, InvalidEncodingHandling};
@ -53,8 +54,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if !newroot.is_dir() {
crash!(
1,
"cannot change root directory to `{}`: no such directory",
newroot.display()
"cannot change root directory to {}: no such directory",
newroot.quote()
);
}
@ -170,7 +171,6 @@ fn set_context(root: &Path, options: &clap::ArgMatches) {
}
fn enter_chroot(root: &Path) {
let root_str = root.display();
std::env::set_current_dir(root).unwrap();
let err = unsafe {
chroot(CString::new(".").unwrap().as_bytes_with_nul().as_ptr() as *const libc::c_char)
@ -179,7 +179,7 @@ fn enter_chroot(root: &Path) {
crash!(
1,
"cannot chroot to {}: {}",
root_str,
root.quote(),
Error::last_os_error()
)
};
@ -189,7 +189,7 @@ fn set_main_group(group: &str) {
if !group.is_empty() {
let group_id = match entries::grp2gid(group) {
Ok(g) => g,
_ => crash!(1, "no such group: {}", group),
_ => crash!(1, "no such group: {}", group.maybe_quote()),
};
let err = unsafe { setgid(group_id) };
if err != 0 {
@ -234,7 +234,12 @@ fn set_user(user: &str) {
let user_id = entries::usr2uid(user).unwrap();
let err = unsafe { setuid(user_id as libc::uid_t) };
if err != 0 {
crash!(1, "cannot set user to {}: {}", user, Error::last_os_error())
crash!(
1,
"cannot set user to {}: {}",
user.maybe_quote(),
Error::last_os_error()
)
}
}
}

View file

@ -14,6 +14,7 @@ use clap::{crate_version, App, Arg};
use std::fs::File;
use std::io::{self, stdin, BufReader, Read};
use std::path::Path;
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
// NOTE: CRC_TABLE_LEN *must* be <= 256 as we cast 0..CRC_TABLE_LEN to u8
@ -191,7 +192,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
match cksum("-") {
Ok((crc, size)) => println!("{} {}", crc, size),
Err(err) => {
show_error!("{}", err);
show_error!("-: {}", err);
return 2;
}
}
@ -203,7 +204,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
match cksum(fname.as_ref()) {
Ok((crc, size)) => println!("{} {} {}", crc, size, fname),
Err(err) => {
show_error!("'{}' {}", fname, err);
show_error!("{}: {}", fname.maybe_quote(), err);
exit_code = 2;
}
}

View file

@ -18,6 +18,7 @@ extern crate quick_error;
#[macro_use]
extern crate uucore;
use uucore::display::Quotable;
#[cfg(windows)]
use winapi::um::fileapi::CreateFileW;
#[cfg(windows)]
@ -541,8 +542,8 @@ impl FromStr for Attribute {
"xattr" => Attribute::Xattr,
_ => {
return Err(Error::InvalidArgument(format!(
"invalid attribute '{}'",
value
"invalid attribute {}",
value.quote()
)));
}
})
@ -659,8 +660,8 @@ impl Options {
"never" => ReflinkMode::Never,
value => {
return Err(Error::InvalidArgument(format!(
"invalid argument '{}' for \'reflink\'",
value
"invalid argument {} for \'reflink\'",
value.quote()
)));
}
}
@ -832,7 +833,7 @@ fn copy(sources: &[Source], target: &TargetSlice, options: &Options) -> CopyResu
let mut seen_sources = HashSet::with_capacity(sources.len());
for source in sources {
if seen_sources.contains(source) {
show_warning!("source '{}' specified more than once", source.display());
show_warning!("source {} specified more than once", source.quote());
} else {
let mut found_hard_link = false;
if preserve_hard_links {
@ -873,8 +874,8 @@ fn construct_dest_path(
) -> CopyResult<PathBuf> {
if options.no_target_dir && target.is_dir() {
return Err(format!(
"cannot overwrite directory '{}' with non-directory",
target.display()
"cannot overwrite directory {} with non-directory",
target.quote()
)
.into());
}
@ -941,7 +942,7 @@ fn adjust_canonicalization(p: &Path) -> Cow<Path> {
/// will not cause a short-circuit.
fn copy_directory(root: &Path, target: &TargetSlice, options: &Options) -> CopyResult<()> {
if !options.recursive {
return Err(format!("omitting directory '{}'", root.display()).into());
return Err(format!("omitting directory {}", root.quote()).into());
}
// if no-dereference is enabled and this is a symlink, copy it as a file
@ -1041,12 +1042,12 @@ impl OverwriteMode {
match *self {
OverwriteMode::NoClobber => Err(Error::NotAllFilesCopied),
OverwriteMode::Interactive(_) => {
if prompt_yes!("{}: overwrite {}? ", uucore::util_name(), path.display()) {
if prompt_yes!("{}: overwrite {}? ", uucore::util_name(), path.quote()) {
Ok(())
} else {
Err(Error::Skipped(format!(
"Not overwriting {} at user request",
path.display()
path.quote()
)))
}
}
@ -1056,7 +1057,7 @@ impl OverwriteMode {
}
fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResult<()> {
let context = &*format!("'{}' -> '{}'", source.display().to_string(), dest.display());
let context = &*format!("{} -> {}", source.quote(), dest.quote());
let source_metadata = fs::symlink_metadata(source).context(context)?;
match *attribute {
Attribute::Mode => {
@ -1152,7 +1153,7 @@ fn symlink_file(source: &Path, dest: &Path, context: &str) -> CopyResult<()> {
}
fn context_for(src: &Path, dest: &Path) -> String {
format!("'{}' -> '{}'", src.display(), dest.display())
format!("{} -> {}", src.quote(), dest.quote())
}
/// Implements a simple backup copy for the destination file.
@ -1332,8 +1333,8 @@ fn copy_link(source: &Path, dest: &Path) -> CopyResult<()> {
Some(name) => dest.join(name).into(),
None => crash!(
EXIT_ERR,
"cannot stat '{}': No such file or directory",
source.display()
"cannot stat {}: No such file or directory",
source.quote()
),
}
} else {
@ -1454,11 +1455,11 @@ fn copy_on_write_macos(
pub fn verify_target_type(target: &Path, target_type: &TargetType) -> CopyResult<()> {
match (target_type, target.is_dir()) {
(&TargetType::Directory, false) => {
Err(format!("target: '{}' is not a directory", target.display()).into())
Err(format!("target: {} is not a directory", target.quote()).into())
}
(&TargetType::File, true) => Err(format!(
"cannot overwrite directory '{}' with non-directory",
target.display()
"cannot overwrite directory {} with non-directory",
target.quote()
)
.into()),
_ => Ok(()),

View file

@ -10,6 +10,7 @@ use std::{
fs::{remove_file, File},
io::{BufRead, BufWriter, Write},
};
use uucore::display::Quotable;
mod csplit_error;
mod patterns;
@ -734,7 +735,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let file = crash_if_err!(1, File::open(file_name));
let file_metadata = crash_if_err!(1, file.metadata());
if !file_metadata.is_file() {
crash!(1, "'{}' is not a regular file", file_name);
crash!(1, "{} is not a regular file", file_name.quote());
}
crash_if_err!(1, csplit(&options, patterns, BufReader::new(file)));
};

View file

@ -1,26 +1,28 @@
use std::io;
use thiserror::Error;
use uucore::display::Quotable;
/// Errors thrown by the csplit command
#[derive(Debug, Error)]
pub enum CsplitError {
#[error("IO error: {}", _0)]
IoError(io::Error),
#[error("'{}': line number out of range", _0)]
#[error("{}: line number out of range", ._0.quote())]
LineOutOfRange(String),
#[error("'{}': line number out of range on repetition {}", _0, _1)]
#[error("{}: line number out of range on repetition {}", ._0.quote(), _1)]
LineOutOfRangeOnRepetition(String, usize),
#[error("'{}': match not found", _0)]
#[error("{}: match not found", ._0.quote())]
MatchNotFound(String),
#[error("'{}': match not found on repetition {}", _0, _1)]
#[error("{}: match not found on repetition {}", ._0.quote(), _1)]
MatchNotFoundOnRepetition(String, usize),
#[error("line number must be greater than zero")]
LineNumberIsZero,
#[error("line number '{}' is smaller than preceding line number, {}", _0, _1)]
LineNumberSmallerThanPrevious(usize, usize),
#[error("invalid pattern: {}", _0)]
#[error("{}: invalid pattern", ._0.quote())]
InvalidPattern(String),
#[error("invalid number: '{}'", _0)]
#[error("invalid number: {}", ._0.quote())]
InvalidNumber(String),
#[error("incorrect conversion specification in suffix")]
SuffixFormatIncorrect,

View file

@ -15,6 +15,7 @@ use clap::{crate_version, App, Arg};
use std::fs::File;
use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write};
use std::path::Path;
use uucore::display::Quotable;
use self::searcher::Searcher;
use uucore::ranges::Range;
@ -351,19 +352,19 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> i32 {
let path = Path::new(&filename[..]);
if path.is_dir() {
show_error!("{}: Is a directory", filename);
show_error!("{}: Is a directory", filename.maybe_quote());
continue;
}
if path.metadata().is_err() {
show_error!("{}: No such file or directory", filename);
show_error!("{}: No such file or directory", filename.maybe_quote());
continue;
}
let file = match File::open(&path) {
Ok(f) => f,
Err(e) => {
show_error!("opening '{}': {}", &filename[..], e);
show_error!("opening {}: {}", filename.quote(), e);
continue;
}
};

View file

@ -17,6 +17,7 @@ use libc::{clock_settime, timespec, CLOCK_REALTIME};
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use uucore::display::Quotable;
#[cfg(windows)]
use winapi::{
shared::minwindef::WORD,
@ -145,7 +146,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let format = if let Some(form) = matches.value_of(OPT_FORMAT) {
if !form.starts_with('+') {
eprintln!("date: invalid date '{}'", form);
eprintln!("date: invalid date {}", form.quote());
return 1;
}
let form = form[1..].to_string();
@ -174,7 +175,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let set_to = match matches.value_of(OPT_SET).map(parse_date) {
None => None,
Some(Err((input, _err))) => {
eprintln!("date: invalid date '{}'", input);
eprintln!("date: invalid date {}", input.quote());
return 1;
}
Some(Ok(date)) => Some(date),
@ -240,7 +241,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
println!("{}", formatted);
}
Err((input, _err)) => {
println!("date: invalid date '{}'", input);
println!("date: invalid date {}", input.quote());
}
}
}

View file

@ -17,6 +17,7 @@ use std::fs::File;
use std::io::{BufRead, BufReader};
use clap::{crate_version, App, Arg};
use uucore::display::Quotable;
mod options {
pub const BOURNE_SHELL: &str = "bourne-shell";
@ -94,9 +95,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if matches.is_present(options::PRINT_DATABASE) {
if !files.is_empty() {
show_usage_error!(
"extra operand '{}'\nfile operands cannot be combined with \
"extra operand {}\nfile operands cannot be combined with \
--print-database (-p)",
files[0]
files[0].quote()
);
return 1;
}
@ -126,7 +127,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
result = parse(INTERNAL_DB.lines(), out_format, "")
} else {
if files.len() > 1 {
show_usage_error!("extra operand '{}'", files[1]);
show_usage_error!("extra operand {}", files[1].quote());
return 1;
}
match File::open(files[0]) {
@ -135,7 +136,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
result = parse(fin.lines().filter_map(Result::ok), out_format, files[0])
}
Err(e) => {
show_error!("{}: {}", files[0], e);
show_error!("{}: {}", files[0].maybe_quote(), e);
return 1;
}
}
@ -314,7 +315,8 @@ where
if val.is_empty() {
return Err(format!(
"{}:{}: invalid line; missing second token",
fp, num
fp.maybe_quote(),
num
));
}
let lower = key.to_lowercase();
@ -341,7 +343,12 @@ where
} else if let Some(s) = table.get(lower.as_str()) {
result.push_str(format!("{}={}:", s, val).as_str());
} else {
return Err(format!("{}:{}: unrecognized keyword {}", fp, num, key));
return Err(format!(
"{}:{}: unrecognized keyword {}",
fp.maybe_quote(),
num,
key
));
}
}
}

View file

@ -10,6 +10,7 @@ extern crate uucore;
use clap::{crate_version, App, Arg};
use std::path::Path;
use uucore::display::print_verbatim;
use uucore::error::{UResult, UUsageError};
use uucore::InvalidEncodingHandling;
@ -65,7 +66,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
if d.components().next() == None {
print!(".")
} else {
print!("{}", d.to_string_lossy());
print_verbatim(d).unwrap();
}
}
None => {

View file

@ -32,6 +32,7 @@ use std::path::PathBuf;
use std::str::FromStr;
use std::time::{Duration, UNIX_EPOCH};
use std::{error::Error, fmt::Display};
use uucore::display::{print_verbatim, Quotable};
use uucore::error::{UError, UResult};
use uucore::parse_size::{parse_size, ParseSizeError};
use uucore::InvalidEncodingHandling;
@ -293,9 +294,9 @@ fn du(
Err(e) => {
safe_writeln!(
stderr(),
"{}: cannot read directory '{}': {}",
"{}: cannot read directory {}: {}",
options.util_name,
my_stat.path.display(),
my_stat.path.quote(),
e
);
return Box::new(iter::once(my_stat));
@ -334,11 +335,11 @@ fn du(
}
Err(error) => match error.kind() {
ErrorKind::PermissionDenied => {
let description = format!("cannot access '{}'", entry.path().display());
let description = format!("cannot access {}", entry.path().quote());
let error_message = "Permission denied";
show_error_custom_description!(description, "{}", error_message)
}
_ => show_error!("cannot access '{}': {}", entry.path().display(), error),
_ => show_error!("cannot access {}: {}", entry.path().quote(), error),
},
},
Err(error) => show_error!("{}", error),
@ -411,26 +412,30 @@ enum DuError {
impl Display for DuError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
DuError::InvalidMaxDepthArg(s) => write!(f, "invalid maximum depth '{}'", s),
DuError::InvalidMaxDepthArg(s) => write!(f, "invalid maximum depth {}", s.quote()),
DuError::SummarizeDepthConflict(s) => {
write!(f, "summarizing conflicts with --max-depth={}", s)
write!(
f,
"summarizing conflicts with --max-depth={}",
s.maybe_quote()
)
}
DuError::InvalidTimeStyleArg(s) => write!(
f,
"invalid argument '{}' for 'time style'
"invalid argument {} for 'time style'
Valid arguments are:
- 'full-iso'
- 'long-iso'
- 'iso'
Try '{} --help' for more information.",
s,
s.quote(),
uucore::execution_phrase()
),
DuError::InvalidTimeArg(s) => write!(
f,
"Invalid argument '{}' for --time.
"Invalid argument {} for --time.
'birth' and 'creation' arguments are not supported on this platform.",
s
s.quote()
),
}
}
@ -566,21 +571,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
};
if !summarize || index == len - 1 {
let time_str = tm.format(time_format_str).to_string();
print!(
"{}\t{}\t{}{}",
convert_size(size),
time_str,
stat.path.display(),
line_separator
);
print!("{}\t{}\t", convert_size(size), time_str);
print_verbatim(stat.path).unwrap();
print!("{}", line_separator);
}
} else if !summarize || index == len - 1 {
print!(
"{}\t{}{}",
convert_size(size),
stat.path.display(),
line_separator
);
print!("{}\t", convert_size(size));
print_verbatim(stat.path).unwrap();
print!("{}", line_separator);
}
if options.total && index == (len - 1) {
// The last element will be the total size of the the path under
@ -590,7 +588,11 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
}
Err(_) => {
show_error!("{}: {}", path_string, "No such file or directory");
show_error!(
"{}: {}",
path_string.maybe_quote(),
"No such file or directory"
);
}
}
}
@ -837,8 +839,8 @@ fn format_error_message(error: ParseSizeError, s: &str, option: &str) -> String
// GNU's du echos affected flag, -B or --block-size (-t or --threshold), depending user's selection
// GNU's du does distinguish between "invalid (suffix in) argument"
match error {
ParseSizeError::ParseFailure(_) => format!("invalid --{} argument '{}'", option, s),
ParseSizeError::SizeTooBig(_) => format!("--{} argument '{}' too large", option, s),
ParseSizeError::ParseFailure(_) => format!("invalid --{} argument {}", option, s.quote()),
ParseSizeError::SizeTooBig(_) => format!("--{} argument {} too large", option, s.quote()),
}
}

10
src/uu/env/src/env.rs vendored
View file

@ -65,8 +65,14 @@ fn parse_name_value_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<bool
fn parse_program_opt<'a>(opts: &mut Options<'a>, opt: &'a str) -> Result<(), i32> {
if opts.null {
eprintln!("{}: cannot specify --null (-0) with command", crate_name!());
eprintln!("Type \"{} --help\" for detailed information", crate_name!());
eprintln!(
"{}: cannot specify --null (-0) with command",
uucore::util_name()
);
eprintln!(
"Type \"{} --help\" for detailed information",
uucore::execution_phrase()
);
Err(1)
} else {
opts.program.push(opt);

View file

@ -17,6 +17,7 @@ use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::str::from_utf8;
use unicode_width::UnicodeWidthChar;
use uucore::display::Quotable;
static ABOUT: &str = "Convert tabs in each FILE to spaces, writing to standard output.
With no FILE, or when FILE is -, read standard input.";
@ -216,7 +217,7 @@ fn open(path: String) -> BufReader<Box<dyn Read + 'static>> {
} else {
file_buf = match File::open(&path[..]) {
Ok(a) => a,
Err(e) => crash!(1, "{}: {}\n", &path[..], e),
Err(e) => crash!(1, "{}: {}\n", path.maybe_quote(), e),
};
BufReader::new(Box::new(file_buf) as Box<dyn Read>)
}

View file

@ -16,6 +16,7 @@ use std::io::{self, stdin, stdout, BufRead, Write};
mod factor;
use clap::{crate_version, App, Arg};
pub use factor::*;
use uucore::display::Quotable;
mod miller_rabin;
pub mod numeric;
@ -52,7 +53,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if let Some(values) = matches.values_of(options::NUMBER) {
for number in values {
if let Err(e) = print_factors_str(number, &mut w, &mut factors_buffer) {
show_warning!("{}: {}", number, e);
show_warning!("{}: {}", number.maybe_quote(), e);
}
}
} else {
@ -61,7 +62,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
for line in stdin.lock().lines() {
for number in line.unwrap().split_whitespace() {
if let Err(e) = print_factors_str(number, &mut w, &mut factors_buffer) {
show_warning!("{}: {}", number, e);
show_warning!("{}: {}", number.maybe_quote(), e);
}
}
}

View file

@ -15,6 +15,7 @@ use std::cmp;
use std::fs::File;
use std::io::{stdin, stdout, Write};
use std::io::{BufReader, BufWriter, Read};
use uucore::display::Quotable;
use self::linebreak::break_lines;
use self::parasplit::ParagraphStream;
@ -187,7 +188,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
_ => match File::open(i) {
Ok(f) => BufReader::new(Box::new(f) as Box<dyn Read + 'static>),
Err(e) => {
show_warning!("{}: {}", i, e);
show_warning!("{}: {}", i.maybe_quote(), e);
continue;
}
},

View file

@ -17,7 +17,10 @@
#[macro_use]
extern crate uucore;
use uucore::entries::{get_groups_gnu, gid2grp, Locate, Passwd};
use uucore::{
display::Quotable,
entries::{get_groups_gnu, gid2grp, Locate, Passwd},
};
use clap::{crate_version, App, Arg};
@ -77,7 +80,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.join(" ")
);
} else {
show_error!("'{}': no such user", user);
show_error!("{}: no such user", user.quote());
exit_code = 1;
}
}

View file

@ -34,6 +34,7 @@ use std::io::{self, stdin, BufRead, BufReader, Read};
use std::iter;
use std::num::ParseIntError;
use std::path::Path;
use uucore::display::Quotable;
const NAME: &str = "hashsum";
@ -525,7 +526,7 @@ where
if options.warn {
show_warning!(
"{}: {}: improperly formatted {} checksum line",
filename.display(),
filename.maybe_quote(),
i + 1,
options.algoname
);
@ -546,6 +547,10 @@ where
)
)
.to_ascii_lowercase();
// FIXME: (How) should these be quoted?
// They seem like they would be processed programmatically, and
// our ordinary quoting might interfere, but newlines should be
// sanitized probably
if sum == real_sum {
if !options.quiet {
println!("{}: OK", ck_filename);

View file

@ -9,6 +9,7 @@ use clap::{crate_version, App, Arg};
use std::convert::TryFrom;
use std::ffi::OsString;
use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write};
use uucore::display::Quotable;
use uucore::{crash, show_error_custom_description};
const EXIT_FAILURE: i32 = 1;
@ -127,10 +128,10 @@ fn arg_iterate<'a>(
match parse::parse_obsolete(s) {
Some(Ok(iter)) => Ok(Box::new(vec![first].into_iter().chain(iter).chain(args))),
Some(Err(e)) => match e {
parse::ParseError::Syntax => Err(format!("bad argument format: '{}'", s)),
parse::ParseError::Syntax => Err(format!("bad argument format: {}", s.quote())),
parse::ParseError::Overflow => Err(format!(
"invalid argument: '{}' Value too large for defined datatype",
s
"invalid argument: {} Value too large for defined datatype",
s.quote()
)),
},
None => Ok(Box::new(vec![first, second].into_iter().chain(args))),
@ -418,7 +419,7 @@ fn uu_head(options: &HeadOptions) -> Result<(), u32> {
let mut file = match std::fs::File::open(name) {
Ok(f) => f,
Err(err) => {
let prefix = format!("cannot open '{}' for reading", name);
let prefix = format!("cannot open {} for reading", name.quote());
match err.kind() {
ErrorKind::NotFound => {
show_error_custom_description!(prefix, "No such file or directory");

View file

@ -41,6 +41,7 @@ extern crate uucore;
use clap::{crate_version, App, Arg};
use std::ffi::CStr;
use uucore::display::Quotable;
use uucore::entries::{self, Group, Locate, Passwd};
use uucore::error::UResult;
use uucore::error::{set_exit_code, USimpleError};
@ -230,7 +231,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
match Passwd::locate(users[i].as_str()) {
Ok(p) => Some(p),
Err(_) => {
show_error!("'{}': no such user", users[i]);
show_error!("{}: no such user", users[i].quote());
set_exit_code(1);
if i + 1 >= users.len() {
break;

View file

@ -16,6 +16,7 @@ use clap::{crate_version, App, Arg, ArgMatches};
use file_diff::diff;
use filetime::{set_file_times, FileTime};
use uucore::backup_control::{self, BackupMode};
use uucore::display::Quotable;
use uucore::entries::{grp2gid, usr2uid};
use uucore::error::{FromIo, UError, UIoError, UResult};
use uucore::mode::get_umask;
@ -95,40 +96,30 @@ impl Display for InstallError {
)
}
IE::CreateDirFailed(dir, e) => {
Display::fmt(&uio_error!(e, "failed to create {}", dir.display()), f)
Display::fmt(&uio_error!(e, "failed to create {}", dir.quote()), f)
}
IE::ChmodFailed(file) => write!(f, "failed to chmod {}", file.display()),
IE::ChmodFailed(file) => write!(f, "failed to chmod {}", file.quote()),
IE::InvalidTarget(target) => write!(
f,
"invalid target {}: No such file or directory",
target.display()
target.quote()
),
IE::TargetDirIsntDir(target) => {
write!(f, "target '{}' is not a directory", target.display())
write!(f, "target {} is not a directory", target.quote())
}
IE::BackupFailed(from, to, e) => Display::fmt(
&uio_error!(
e,
"cannot backup '{}' to '{}'",
from.display(),
to.display()
),
&uio_error!(e, "cannot backup {} to {}", from.quote(), to.quote()),
f,
),
IE::InstallFailed(from, to, e) => Display::fmt(
&uio_error!(
e,
"cannot install '{}' to '{}'",
from.display(),
to.display()
),
&uio_error!(e, "cannot install {} to {}", from.quote(), to.quote()),
f,
),
IE::StripProgramFailed(msg) => write!(f, "strip program failed: {}", msg),
IE::MetadataFailed(e) => Display::fmt(&uio_error!(e, ""), f),
IE::NoSuchUser(user) => write!(f, "no such user: {}", user),
IE::NoSuchGroup(group) => write!(f, "no such group: {}", group),
IE::OmittingDirectory(dir) => write!(f, "omitting directory '{}'", dir.display()),
IE::NoSuchUser(user) => write!(f, "no such user: {}", user.maybe_quote()),
IE::NoSuchGroup(group) => write!(f, "no such group: {}", group.maybe_quote()),
IE::OmittingDirectory(dir) => write!(f, "omitting directory {}", dir.quote()),
}
}
}
@ -416,14 +407,14 @@ fn directory(paths: Vec<String>, b: Behavior) -> UResult<()> {
// the default mode. Hence it is safe to use fs::create_dir_all
// and then only modify the target's dir mode.
if let Err(e) =
fs::create_dir_all(path).map_err_context(|| format!("{}", path.display()))
fs::create_dir_all(path).map_err_context(|| path.maybe_quote().to_string())
{
show!(e);
continue;
}
if b.verbose {
println!("creating directory '{}'", path.display());
println!("creating directory {}", path.quote());
}
}
@ -445,7 +436,7 @@ fn directory(paths: Vec<String>, b: Behavior) -> UResult<()> {
fn is_new_file_path(path: &Path) -> bool {
!path.exists()
&& (path.parent().map(Path::is_dir).unwrap_or(true)
|| path.parent().unwrap().to_string_lossy().is_empty()) // In case of a simple file
|| path.parent().unwrap().as_os_str().is_empty()) // In case of a simple file
}
/// Perform an install, given a list of paths and behavior.
@ -502,7 +493,7 @@ fn copy_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> UR
if !sourcepath.exists() {
let err = UIoError::new(
std::io::ErrorKind::NotFound,
format!("cannot stat '{}'", sourcepath.display()),
format!("cannot stat {}", sourcepath.quote()),
);
show!(err);
continue;
@ -566,7 +557,7 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
}
}
if from.to_string_lossy() == "/dev/null" {
if from.as_os_str() == "/dev/null" {
/* workaround a limitation of fs::copy
* https://github.com/rust-lang/rust/issues/79390
*/
@ -674,9 +665,9 @@ fn copy(from: &Path, to: &Path, b: &Behavior) -> UResult<()> {
}
if b.verbose {
print!("'{}' -> '{}'", from.display(), to.display());
print!("{} -> {}", from.quote(), to.quote());
match backup_path {
Some(path) => println!(" (backup: '{}')", path.display()),
Some(path) => println!(" (backup: {})", path.quote()),
None => println!(),
}
}

View file

@ -22,8 +22,9 @@ pub fn parse(mode_string: &str, considering_dir: bool, umask: u32) -> Result<u32
#[cfg(any(unix, target_os = "redox"))]
pub fn chmod(path: &Path, mode: u32) -> Result<(), ()> {
use std::os::unix::fs::PermissionsExt;
use uucore::display::Quotable;
fs::set_permissions(path, fs::Permissions::from_mode(mode)).map_err(|err| {
show_error!("{}: chmod failed with error {}", path.display(), err);
show_error!("{}: chmod failed with error {}", path.maybe_quote(), err);
})
}

View file

@ -14,6 +14,7 @@ use clap::{crate_version, App, Arg};
use std::cmp::Ordering;
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Lines, Stdin};
use uucore::display::Quotable;
static NAME: &str = "join";
@ -181,18 +182,18 @@ impl Spec {
return Spec::Key;
}
crash!(1, "invalid field specifier: '{}'", format);
crash!(1, "invalid field specifier: {}", format.quote());
}
Some('1') => FileNum::File1,
Some('2') => FileNum::File2,
_ => crash!(1, "invalid file number in field spec: '{}'", format),
_ => crash!(1, "invalid file number in field spec: {}", format.quote()),
};
if let Some('.') = chars.next() {
return Spec::Field(file_num, parse_field_number(chars.as_str()));
}
crash!(1, "invalid field specifier: '{}'", format);
crash!(1, "invalid field specifier: {}", format.quote());
}
}
@ -245,7 +246,7 @@ impl<'a> State<'a> {
} else {
match File::open(name) {
Ok(file) => Box::new(BufReader::new(file)) as Box<dyn BufRead>,
Err(err) => crash!(1, "{}: {}", name, err),
Err(err) => crash!(1, "{}: {}", name.maybe_quote(), err),
}
};
@ -393,7 +394,11 @@ impl<'a> State<'a> {
let diff = input.compare(self.get_current_key(), line.get_field(self.key));
if diff == Ordering::Greater {
eprintln!("{}:{}: is not sorted", self.file_name, self.line_num);
eprintln!(
"{}:{}: is not sorted",
self.file_name.maybe_quote(),
self.line_num
);
// This is fatal if the check is enabled.
if input.check_order == CheckOrder::Enabled {
@ -727,7 +732,7 @@ fn get_field_number(keys: Option<usize>, key: Option<usize>) -> usize {
fn parse_field_number(value: &str) -> usize {
match value.parse::<usize>() {
Ok(result) if result > 0 => result - 1,
_ => crash!(1, "invalid field number: '{}'", value),
_ => crash!(1, "invalid field number: {}", value.quote()),
}
}
@ -735,7 +740,7 @@ fn parse_file_number(value: &str) -> FileNum {
match value {
"1" => FileNum::File1,
"2" => FileNum::File2,
value => crash!(1, "invalid file number: '{}'", value),
value => crash!(1, "invalid file number: {}", value.quote()),
}
}

View file

@ -13,6 +13,7 @@ extern crate uucore;
use clap::{crate_version, App, Arg};
use libc::{c_int, pid_t};
use std::io::Error;
use uucore::display::Quotable;
use uucore::error::{UResult, USimpleError};
use uucore::signals::ALL_SIGNALS;
use uucore::InvalidEncodingHandling;
@ -154,7 +155,7 @@ fn print_signal(signal_name_or_value: &str) -> UResult<()> {
}
Err(USimpleError::new(
1,
format!("unknown signal name {}", signal_name_or_value),
format!("unknown signal name {}", signal_name_or_value.quote()),
))
}
@ -190,7 +191,7 @@ fn kill(signalname: &str, pids: &[String]) -> UResult<()> {
None => {
return Err(USimpleError::new(
1,
format!("unknown signal name {}", signalname),
format!("unknown signal name {}", signalname.quote()),
));
}
};
@ -204,7 +205,7 @@ fn kill(signalname: &str, pids: &[String]) -> UResult<()> {
Err(e) => {
return Err(USimpleError::new(
1,
format!("failed to parse argument {}: {}", pid, e),
format!("failed to parse argument {}: {}", pid.quote(), e),
));
}
};

View file

@ -11,11 +11,12 @@
extern crate uucore;
use clap::{crate_version, App, Arg};
use uucore::display::Quotable;
use uucore::error::{UError, UResult};
use std::borrow::Cow;
use std::error::Error;
use std::ffi::OsStr;
use std::ffi::{OsStr, OsString};
use std::fmt::Display;
use std::fs;
@ -49,26 +50,26 @@ pub enum OverwriteMode {
#[derive(Debug)]
enum LnError {
TargetIsDirectory(String),
TargetIsDirectory(PathBuf),
SomeLinksFailed,
FailedToLink(String),
MissingDestination(String),
ExtraOperand(String),
MissingDestination(PathBuf),
ExtraOperand(OsString),
}
impl Display for LnError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::TargetIsDirectory(s) => write!(f, "target '{}' is not a directory", s),
Self::FailedToLink(s) => write!(f, "failed to link '{}'", s),
Self::TargetIsDirectory(s) => write!(f, "target {} is not a directory", s.quote()),
Self::FailedToLink(e) => write!(f, "failed to link: {}", e),
Self::SomeLinksFailed => write!(f, "some links failed to create"),
Self::MissingDestination(s) => {
write!(f, "missing destination file operand after '{}'", s)
write!(f, "missing destination file operand after {}", s.quote())
}
Self::ExtraOperand(s) => write!(
f,
"extra operand '{}'\nTry '{} --help' for more information.",
s,
"extra operand {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase()
),
}
@ -279,10 +280,10 @@ fn exec(files: &[PathBuf], settings: &Settings) -> UResult<()> {
// 1st form. Now there should be only two operands, but if -T is
// specified we may have a wrong number of operands.
if files.len() == 1 {
return Err(LnError::MissingDestination(files[0].to_string_lossy().into()).into());
return Err(LnError::MissingDestination(files[0].clone()).into());
}
if files.len() > 2 {
return Err(LnError::ExtraOperand(files[2].display().to_string()).into());
return Err(LnError::ExtraOperand(files[2].clone().into()).into());
}
assert!(!files.is_empty());
@ -294,7 +295,7 @@ fn exec(files: &[PathBuf], settings: &Settings) -> UResult<()> {
fn link_files_in_dir(files: &[PathBuf], target_dir: &Path, settings: &Settings) -> UResult<()> {
if !target_dir.is_dir() {
return Err(LnError::TargetIsDirectory(target_dir.display().to_string()).into());
return Err(LnError::TargetIsDirectory(target_dir.to_owned()).into());
}
let mut all_successful = true;
@ -306,7 +307,7 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &Path, settings: &Settings)
if is_symlink(target_dir) {
if target_dir.is_file() {
if let Err(e) = fs::remove_file(target_dir) {
show_error!("Could not update {}: {}", target_dir.display(), e)
show_error!("Could not update {}: {}", target_dir.quote(), e)
};
}
if target_dir.is_dir() {
@ -314,7 +315,7 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &Path, settings: &Settings)
// considered as a dir
// See test_ln::test_symlink_no_deref_dir
if let Err(e) = fs::remove_dir(target_dir) {
show_error!("Could not update {}: {}", target_dir.display(), e)
show_error!("Could not update {}: {}", target_dir.quote(), e)
};
}
}
@ -332,10 +333,7 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &Path, settings: &Settings)
}
}
None => {
show_error!(
"cannot stat '{}': No such file or directory",
srcpath.display()
);
show_error!("cannot stat {}: No such file or directory", srcpath.quote());
all_successful = false;
continue;
}
@ -344,9 +342,9 @@ fn link_files_in_dir(files: &[PathBuf], target_dir: &Path, settings: &Settings)
if let Err(e) = link(srcpath, &targetpath, settings) {
show_error!(
"cannot link '{}' to '{}': {}",
targetpath.display(),
srcpath.display(),
"cannot link {} to {}: {}",
targetpath.quote(),
srcpath.quote(),
e
);
all_successful = false;
@ -399,7 +397,7 @@ fn link(src: &Path, dst: &Path, settings: &Settings) -> Result<()> {
match settings.overwrite {
OverwriteMode::NoClobber => {}
OverwriteMode::Interactive => {
print!("{}: overwrite '{}'? ", uucore::util_name(), dst.display());
print!("{}: overwrite {}? ", uucore::util_name(), dst.quote());
if !read_yes() {
return Ok(());
}
@ -426,9 +424,9 @@ fn link(src: &Path, dst: &Path, settings: &Settings) -> Result<()> {
}
if settings.verbose {
print!("'{}' -> '{}'", dst.display(), &source.display());
print!("{} -> {}", dst.quote(), source.quote());
match backup_path {
Some(path) => println!(" (backup: '{}')", path.display()),
Some(path) => println!(" (backup: {})", path.quote()),
None => println!(),
}
}

View file

@ -40,7 +40,10 @@ use std::{
time::Duration,
};
use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
use uucore::error::{set_exit_code, FromIo, UError, UResult};
use uucore::{
display::Quotable,
error::{set_exit_code, FromIo, UError, UResult},
};
use unicode_width::UnicodeWidthStr;
#[cfg(unix)]
@ -150,8 +153,8 @@ impl Error for LsError {}
impl Display for LsError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
LsError::InvalidLineWidth(s) => write!(f, "invalid line width: '{}'", s),
LsError::NoMetadata(p) => write!(f, "could not open file: '{}'", p.display()),
LsError::InvalidLineWidth(s) => write!(f, "invalid line width: {}", s.quote()),
LsError::NoMetadata(p) => write!(f, "could not open file: {}", p.quote()),
}
}
}
@ -410,18 +413,18 @@ impl Config {
},
None => match termsize::get() {
Some(size) => size.cols,
None => match std::env::var("COLUMNS") {
Ok(columns) => match columns.parse() {
Ok(columns) => columns,
Err(_) => {
None => match std::env::var_os("COLUMNS") {
Some(columns) => match columns.to_str().and_then(|s| s.parse().ok()) {
Some(columns) => columns,
None => {
show_error!(
"ignoring invalid width in environment variable COLUMNS: '{}'",
columns
"ignoring invalid width in environment variable COLUMNS: {}",
columns.quote()
);
DEFAULT_TERM_WIDTH
}
},
Err(_) => DEFAULT_TERM_WIDTH,
None => DEFAULT_TERM_WIDTH,
},
},
};
@ -538,7 +541,7 @@ impl Config {
Ok(p) => {
ignore_patterns.add(p);
}
Err(_) => show_warning!("Invalid pattern for ignore: '{}'", pattern),
Err(_) => show_warning!("Invalid pattern for ignore: {}", pattern.quote()),
}
}
@ -548,7 +551,7 @@ impl Config {
Ok(p) => {
ignore_patterns.add(p);
}
Err(_) => show_warning!("Invalid pattern for hide: '{}'", pattern),
Err(_) => show_warning!("Invalid pattern for hide: {}", pattern.quote()),
}
}
}
@ -1255,7 +1258,7 @@ fn list(locs: Vec<&Path>, config: Config) -> UResult<()> {
if path_data.md().is_none() {
show!(std::io::ErrorKind::NotFound
.map_err_context(|| format!("cannot access '{}'", path_data.p_buf.display())));
.map_err_context(|| format!("cannot access {}", path_data.p_buf.quote())));
// We found an error, no need to continue the execution
continue;
}

View file

@ -12,6 +12,7 @@ use clap::OsValues;
use clap::{crate_version, App, Arg};
use std::fs;
use std::path::Path;
use uucore::display::Quotable;
use uucore::error::{FromIo, UResult, USimpleError};
static ABOUT: &str = "Create the given DIRECTORY(ies) if they do not exist";
@ -43,7 +44,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
// Not tested on Windows
let mode: u16 = match matches.value_of(options::MODE) {
Some(m) => u16::from_str_radix(m, 8)
.map_err(|_| USimpleError::new(1, format!("invalid mode '{}'", m)))?,
.map_err(|_| USimpleError::new(1, format!("invalid mode {}", m.quote())))?,
None => 0o755_u16,
};
@ -100,13 +101,13 @@ fn mkdir(path: &Path, recursive: bool, mode: u16, verbose: bool) -> UResult<()>
fs::create_dir
};
create_dir(path).map_err_context(|| format!("cannot create directory '{}'", path.display()))?;
create_dir(path).map_err_context(|| format!("cannot create directory {}", path.quote()))?;
if verbose {
println!(
"{}: created directory '{}'",
"{}: created directory {}",
uucore::util_name(),
path.display()
path.quote()
);
}
@ -121,7 +122,7 @@ fn chmod(path: &Path, mode: u16) -> UResult<()> {
let mode = Permissions::from_mode(u32::from(mode));
set_permissions(path, mode)
.map_err_context(|| format!("cannot set permissions '{}'", path.display()))
.map_err_context(|| format!("cannot set permissions {}", path.quote()))
}
#[cfg(windows)]

View file

@ -11,7 +11,7 @@ extern crate uucore;
use clap::{crate_version, App, Arg};
use libc::mkfifo;
use std::ffi::CString;
use uucore::InvalidEncodingHandling;
use uucore::{display::Quotable, InvalidEncodingHandling};
static NAME: &str = "mkfifo";
static USAGE: &str = "mkfifo [OPTION]... NAME...";
@ -61,7 +61,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
mkfifo(name.as_ptr(), mode as libc::mode_t)
};
if err == -1 {
show_error!("cannot create fifo '{}': File exists", f);
show_error!("cannot create fifo {}: File exists", f.quote());
exit_code = 1;
}
}

View file

@ -16,6 +16,7 @@ use clap::{crate_version, App, Arg, ArgMatches};
use libc::{dev_t, mode_t};
use libc::{S_IFBLK, S_IFCHR, S_IFIFO, S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
static ABOUT: &str = "Create the special file NAME of the given TYPE.";
@ -219,7 +220,7 @@ fn valid_type(tpe: String) -> Result<(), String> {
if vec!['b', 'c', 'u', 'p'].contains(&first_char) {
Ok(())
} else {
Err(format!("invalid device type '{}'", tpe))
Err(format!("invalid device type {}", tpe.quote()))
}
})
}

View file

@ -12,6 +12,7 @@
extern crate uucore;
use clap::{crate_version, App, Arg};
use uucore::display::{println_verbatim, Quotable};
use uucore::error::{FromIo, UError, UResult};
use std::env;
@ -57,16 +58,20 @@ impl Display for MkTempError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use MkTempError::*;
match self {
PersistError(p) => write!(f, "could not persist file '{}'", p.display()),
MustEndInX(s) => write!(f, "with --suffix, template '{}' must end in X", s),
TooFewXs(s) => write!(f, "too few X's in template '{}'", s),
PersistError(p) => write!(f, "could not persist file {}", p.quote()),
MustEndInX(s) => write!(f, "with --suffix, template {} must end in X", s.quote()),
TooFewXs(s) => write!(f, "too few X's in template {}", s.quote()),
ContainsDirSeparator(s) => {
write!(f, "invalid suffix '{}', contains directory separator", s)
write!(
f,
"invalid suffix {}, contains directory separator",
s.quote()
)
}
InvalidTemplate(s) => write!(
f,
"invalid template, '{}'; with --tmpdir, it may not be absolute",
s
"invalid template, {}; with --tmpdir, it may not be absolute",
s.quote()
),
}
}
@ -244,8 +249,7 @@ pub fn dry_exec(mut tmpdir: PathBuf, prefix: &str, rand: usize, suffix: &str) ->
}
}
tmpdir.push(buf);
println!("{}", tmpdir.display());
Ok(())
println_verbatim(tmpdir).map_err_context(|| "failed to print directory name".to_owned())
}
fn exec(dir: PathBuf, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -> UResult<()> {
@ -274,6 +278,5 @@ fn exec(dir: PathBuf, prefix: &str, rand: usize, suffix: &str, make_dir: bool) -
.map_err(|e| MkTempError::PersistError(e.file.path().to_path_buf()))?
.1
};
println!("{}", path.display());
Ok(())
println_verbatim(path).map_err_context(|| "failed to print directory name".to_owned())
}

View file

@ -30,6 +30,7 @@ use crossterm::{
use unicode_segmentation::UnicodeSegmentation;
use unicode_width::UnicodeWidthStr;
use uucore::display::Quotable;
const BELL: &str = "\x07";
@ -64,12 +65,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let file = Path::new(file);
if file.is_dir() {
terminal::disable_raw_mode().unwrap();
show_usage_error!("'{}' is a directory.", file.display());
show_usage_error!("{} is a directory.", file.quote());
return 1;
}
if !file.exists() {
terminal::disable_raw_mode().unwrap();
show_error!("cannot open {}: No such file or directory", file.display());
show_error!("cannot open {}: No such file or directory", file.quote());
return 1;
}
if length > 1 {

View file

@ -21,6 +21,7 @@ use std::os::unix;
use std::os::windows;
use std::path::{Path, PathBuf};
use uucore::backup_control::{self, BackupMode};
use uucore::display::Quotable;
use fs_extra::dir::{move_dir, CopyOptions as DirCopyOptions};
@ -223,10 +224,7 @@ fn exec(files: &[PathBuf], b: Behavior) -> i32 {
// `Ok()` results unless the source does not exist, or the user
// lacks permission to access metadata.
if source.symlink_metadata().is_err() {
show_error!(
"cannot stat '{}': No such file or directory",
source.display()
);
show_error!("cannot stat {}: No such file or directory", source.quote());
return 1;
}
@ -234,8 +232,8 @@ fn exec(files: &[PathBuf], b: Behavior) -> i32 {
if b.no_target_dir {
if !source.is_dir() {
show_error!(
"cannot overwrite directory '{}' with non-directory",
target.display()
"cannot overwrite directory {} with non-directory",
target.quote()
);
return 1;
}
@ -243,9 +241,9 @@ fn exec(files: &[PathBuf], b: Behavior) -> i32 {
return match rename(source, target, &b) {
Err(e) => {
show_error!(
"cannot move '{}' to '{}': {}",
source.display(),
target.display(),
"cannot move {} to {}: {}",
source.quote(),
target.quote(),
e.to_string()
);
1
@ -257,9 +255,9 @@ fn exec(files: &[PathBuf], b: Behavior) -> i32 {
return move_files_into_dir(&[source.clone()], target, &b);
} else if target.exists() && source.is_dir() {
show_error!(
"cannot overwrite non-directory '{}' with directory '{}'",
target.display(),
source.display()
"cannot overwrite non-directory {} with directory {}",
target.quote(),
source.quote()
);
return 1;
}
@ -272,9 +270,9 @@ fn exec(files: &[PathBuf], b: Behavior) -> i32 {
_ => {
if b.no_target_dir {
show_error!(
"mv: extra operand '{}'\n\
"mv: extra operand {}\n\
Try '{} --help' for more information.",
files[2].display(),
files[2].quote(),
uucore::execution_phrase()
);
return 1;
@ -288,7 +286,7 @@ fn exec(files: &[PathBuf], b: Behavior) -> i32 {
fn move_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> i32 {
if !target_dir.is_dir() {
show_error!("target '{}' is not a directory", target_dir.display());
show_error!("target {} is not a directory", target_dir.quote());
return 1;
}
@ -298,8 +296,8 @@ fn move_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> i3
Some(name) => target_dir.join(name),
None => {
show_error!(
"cannot stat '{}': No such file or directory",
sourcepath.display()
"cannot stat {}: No such file or directory",
sourcepath.quote()
);
all_successful = false;
@ -309,9 +307,9 @@ fn move_files_into_dir(files: &[PathBuf], target_dir: &Path, b: &Behavior) -> i3
if let Err(e) = rename(sourcepath, &targetpath, b) {
show_error!(
"cannot move '{}' to '{}': {}",
sourcepath.display(),
targetpath.display(),
"cannot move {} to {}: {}",
sourcepath.quote(),
targetpath.quote(),
e.to_string()
);
all_successful = false;
@ -332,7 +330,7 @@ fn rename(from: &Path, to: &Path, b: &Behavior) -> io::Result<()> {
match b.overwrite {
OverwriteMode::NoClobber => return Ok(()),
OverwriteMode::Interactive => {
println!("{}: overwrite '{}'? ", uucore::util_name(), to.display());
println!("{}: overwrite {}? ", uucore::util_name(), to.quote());
if !read_yes() {
return Ok(());
}
@ -365,9 +363,9 @@ fn rename(from: &Path, to: &Path, b: &Behavior) -> io::Result<()> {
rename_with_fallback(from, to)?;
if b.verbose {
print!("'{}' -> '{}'", from.display(), to.display());
print!("{} -> {}", from.quote(), to.quote());
match backup_path {
Some(path) => println!(" (backup: '{}')", path.display()),
Some(path) => println!(" (backup: {})", path.quote()),
None => println!(),
}
}

View file

@ -19,6 +19,7 @@ use std::fs::{File, OpenOptions};
use std::io::Error;
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
static ABOUT: &str = "Run COMMAND ignoring hangup signals.";
@ -122,13 +123,16 @@ fn find_stdout() -> File {
.open(Path::new(NOHUP_OUT))
{
Ok(t) => {
show_error!("ignoring input and appending output to '{}'", NOHUP_OUT);
show_error!(
"ignoring input and appending output to {}",
NOHUP_OUT.quote()
);
t
}
Err(e1) => {
let home = match env::var("HOME") {
Err(_) => {
show_error!("failed to open '{}': {}", NOHUP_OUT, e1);
show_error!("failed to open {}: {}", NOHUP_OUT.quote(), e1);
exit!(internal_failure_code)
}
Ok(h) => h,
@ -143,12 +147,15 @@ fn find_stdout() -> File {
.open(&homeout)
{
Ok(t) => {
show_error!("ignoring input and appending output to '{}'", homeout_str);
show_error!(
"ignoring input and appending output to {}",
homeout_str.quote()
);
t
}
Err(e2) => {
show_error!("failed to open '{}': {}", NOHUP_OUT, e1);
show_error!("failed to open '{}': {}", homeout_str, e2);
show_error!("failed to open {}: {}", NOHUP_OUT.quote(), e1);
show_error!("failed to open {}: {}", homeout_str.quote(), e2);
exit!(internal_failure_code)
}
}

View file

@ -1,3 +1,5 @@
use uucore::display::Quotable;
use crate::options::{NumfmtOptions, RoundMethod};
use crate::units::{DisplayableSuffix, RawSuffix, Result, Suffix, Unit, IEC_BASES, SI_BASES};
@ -78,7 +80,7 @@ fn parse_suffix(s: &str) -> Result<(f64, Option<Suffix>)> {
Some('Z') => Some((RawSuffix::Z, with_i)),
Some('Y') => Some((RawSuffix::Y, with_i)),
Some('0'..='9') => None,
_ => return Err(format!("invalid suffix in input: '{}'", s)),
_ => return Err(format!("invalid suffix in input: {}", s.quote())),
};
let suffix_len = match suffix {
@ -89,7 +91,7 @@ fn parse_suffix(s: &str) -> Result<(f64, Option<Suffix>)> {
let number = s[..s.len() - suffix_len]
.parse::<f64>()
.map_err(|_| format!("invalid number: '{}'", s))?;
.map_err(|_| format!("invalid number: {}", s.quote()))?;
Ok((number, suffix))
}

View file

@ -15,6 +15,7 @@ use crate::options::*;
use crate::units::{Result, Unit};
use clap::{crate_version, App, AppSettings, Arg, ArgMatches};
use std::io::{BufRead, Write};
use uucore::display::Quotable;
use uucore::ranges::Range;
pub mod format;
@ -113,7 +114,7 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
0 => Err(value),
_ => Ok(n),
})
.map_err(|value| format!("invalid header value '{}'", value))
.map_err(|value| format!("invalid header value {}", value.quote()))
}
}?;

View file

@ -5,6 +5,8 @@ use std::io;
use std::io::BufReader;
use std::vec::Vec;
use uucore::display::Quotable;
pub enum InputSource<'a> {
FileName(&'a str),
Stdin,
@ -57,7 +59,7 @@ impl<'b> MultifileReader<'b> {
// print an error at the time that the file is needed,
// then move on the the next file.
// This matches the behavior of the original `od`
eprintln!("{}: '{}': {}", uucore::util_name(), fname, e);
eprintln!("{}: {}: {}", uucore::util_name(), fname.maybe_quote(), e);
self.any_err = true
}
}

View file

@ -43,6 +43,7 @@ use crate::partialreader::*;
use crate::peekreader::*;
use crate::prn_char::format_ascii_dump;
use clap::{self, crate_version, AppSettings, Arg, ArgMatches};
use uucore::display::Quotable;
use uucore::parse_size::ParseSizeError;
use uucore::InvalidEncodingHandling;
@ -635,7 +636,7 @@ fn format_error_message(error: ParseSizeError, s: &str, option: &str) -> String
// GNU's od echos affected flag, -N or --read-bytes (-j or --skip-bytes, etc.), depending user's selection
// GNU's od does distinguish between "invalid (suffix in) argument"
match error {
ParseSizeError::ParseFailure(_) => format!("invalid --{} argument '{}'", option, s),
ParseSizeError::SizeTooBig(_) => format!("--{} argument '{}' too large", option, s),
ParseSizeError::ParseFailure(_) => format!("invalid --{} argument {}", option, s.quote()),
ParseSizeError::SizeTooBig(_) => format!("--{} argument {} too large", option, s.quote()),
}
}

View file

@ -1,5 +1,7 @@
// spell-checker:ignore formatteriteminfo docopt fvox fvoxw vals acdx
use uucore::display::Quotable;
use crate::formatteriteminfo::FormatterItemInfo;
use crate::prn_char::*;
use crate::prn_float::*;
@ -272,8 +274,9 @@ fn parse_type_string(params: &str) -> Result<Vec<ParsedFormatterItemInfo>, Strin
while let Some(type_char) = ch {
let type_char = format_type(type_char).ok_or_else(|| {
format!(
"unexpected char '{}' in format specification '{}'",
type_char, params
"unexpected char '{}' in format specification {}",
type_char,
params.quote()
)
})?;
@ -293,8 +296,9 @@ fn parse_type_string(params: &str) -> Result<Vec<ParsedFormatterItemInfo>, Strin
if !decimal_size.is_empty() {
byte_size = decimal_size.parse().map_err(|_| {
format!(
"invalid number '{}' in format specification '{}'",
decimal_size, params
"invalid number {} in format specification {}",
decimal_size.quote(),
params.quote()
)
})?;
}
@ -305,8 +309,9 @@ fn parse_type_string(params: &str) -> Result<Vec<ParsedFormatterItemInfo>, Strin
let ft = od_format_type(type_char, byte_size).ok_or_else(|| {
format!(
"invalid size '{}' in format specification '{}'",
byte_size, params
"invalid size '{}' in format specification {}",
byte_size,
params.quote()
)
})?;
formats.push(ParsedFormatterItemInfo::new(ft, show_ascii_dump));

View file

@ -15,6 +15,7 @@ extern crate uucore;
use clap::{crate_version, App, Arg};
use std::fs;
use std::io::{ErrorKind, Write};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
// operating mode
@ -153,10 +154,10 @@ fn check_basic(path: &[String]) -> bool {
if component_len > POSIX_NAME_MAX {
writeln!(
&mut std::io::stderr(),
"limit {} exceeded by length {} of file name component '{}'",
"limit {} exceeded by length {} of file name component {}",
POSIX_NAME_MAX,
component_len,
p
p.quote()
);
return false;
}
@ -175,8 +176,8 @@ fn check_extra(path: &[String]) -> bool {
if p.starts_with('-') {
writeln!(
&mut std::io::stderr(),
"leading hyphen in file name component '{}'",
p
"leading hyphen in file name component {}",
p.quote()
);
return false;
}
@ -197,10 +198,10 @@ fn check_default(path: &[String]) -> bool {
if total_len > libc::PATH_MAX as usize {
writeln!(
&mut std::io::stderr(),
"limit {} exceeded by length {} of file name '{}'",
"limit {} exceeded by length {} of file name {}",
libc::PATH_MAX,
total_len,
joined_path
joined_path.quote()
);
return false;
}
@ -210,10 +211,10 @@ fn check_default(path: &[String]) -> bool {
if component_len > libc::FILENAME_MAX as usize {
writeln!(
&mut std::io::stderr(),
"limit {} exceeded by length {} of file name component '{}'",
"limit {} exceeded by length {} of file name component {}",
libc::FILENAME_MAX,
component_len,
p
p.quote()
);
return false;
}
@ -246,9 +247,9 @@ fn check_portable_chars(path_segment: &str) -> bool {
let invalid = path_segment[i..].chars().next().unwrap();
writeln!(
&mut std::io::stderr(),
"nonportable character '{}' in file name component '{}'",
"nonportable character '{}' in file name component {}",
invalid,
path_segment
path_segment.quote()
);
return false;
}

View file

@ -24,6 +24,8 @@ use std::io::{stdin, stdout, BufRead, BufReader, Lines, Read, Stdout, Write};
#[cfg(unix)]
use std::os::unix::fs::FileTypeExt;
use uucore::display::Quotable;
type IOError = std::io::Error;
const NAME: &str = "pr";
@ -517,7 +519,7 @@ fn parse_usize(matches: &Matches, opt: &str) -> Option<Result<usize, PrError>> {
let i = value_to_parse.0;
let option = value_to_parse.1;
i.parse().map_err(|_e| {
PrError::EncounteredErrors(format!("invalid {} argument '{}'", option, i))
PrError::EncounteredErrors(format!("invalid {} argument {}", option, i.quote()))
})
};
matches
@ -619,7 +621,7 @@ fn build_options(
let unparsed_num = i.get(1).unwrap().as_str().trim();
let x: Vec<_> = unparsed_num.split(':').collect();
x[0].to_string().parse::<usize>().map_err(|_e| {
PrError::EncounteredErrors(format!("invalid {} argument '{}'", "+", unparsed_num))
PrError::EncounteredErrors(format!("invalid {} argument {}", "+", unparsed_num.quote()))
})
}) {
Some(res) => res?,
@ -633,7 +635,11 @@ fn build_options(
.map(|unparsed_num| {
let x: Vec<_> = unparsed_num.split(':').collect();
x[1].to_string().parse::<usize>().map_err(|_e| {
PrError::EncounteredErrors(format!("invalid {} argument '{}'", "+", unparsed_num))
PrError::EncounteredErrors(format!(
"invalid {} argument {}",
"+",
unparsed_num.quote()
))
})
}) {
Some(res) => Some(res?),
@ -643,7 +649,10 @@ fn build_options(
let invalid_pages_map = |i: String| {
let unparsed_value = matches.opt_str(options::PAGE_RANGE_OPTION).unwrap();
i.parse::<usize>().map_err(|_e| {
PrError::EncounteredErrors(format!("invalid --pages argument '{}'", unparsed_value))
PrError::EncounteredErrors(format!(
"invalid --pages argument {}",
unparsed_value.quote()
))
})
};
@ -741,7 +750,7 @@ fn build_options(
let start_column_option = match re_col.captures(&free_args).map(|i| {
let unparsed_num = i.get(1).unwrap().as_str().trim();
unparsed_num.parse::<usize>().map_err(|_e| {
PrError::EncounteredErrors(format!("invalid {} argument '{}'", "-", unparsed_num))
PrError::EncounteredErrors(format!("invalid {} argument {}", "-", unparsed_num.quote()))
})
}) {
Some(res) => Some(res?),

View file

@ -2,20 +2,11 @@
// spell-checker:ignore (ToDO) bslice
use std::env;
use std::io::{stderr, stdout, Write};
use std::io::{stdout, Write};
pub const EXIT_OK: i32 = 0;
pub const EXIT_ERR: i32 = 1;
pub fn err_msg(msg: &str) {
let exe_path = match env::current_exe() {
Ok(p) => p.to_string_lossy().into_owned(),
_ => String::from(""),
};
writeln!(&mut stderr(), "{}: {}", exe_path, msg).unwrap();
}
// by default stdout only flushes
// to console when a newline is passed.
pub fn flush_char(c: char) {

View file

@ -8,8 +8,9 @@
use itertools::put_back_n;
use std::iter::Peekable;
use std::slice::Iter;
use uucore::display::Quotable;
use uucore::show_error;
use crate::cli;
use crate::tokenize::sub::Sub;
use crate::tokenize::token::{Token, Tokenizer};
use crate::tokenize::unescaped_text::UnescapedText;
@ -19,10 +20,10 @@ pub struct Memo {
}
fn warn_excess_args(first_arg: &str) {
cli::err_msg(&format!(
"warning: ignoring excess arguments, starting with '{}'",
first_arg
));
show_error!(
"warning: ignoring excess arguments, starting with {}",
first_arg.quote()
);
}
impl Memo {

View file

@ -3,11 +3,10 @@
use itertools::{put_back_n, PutBackN};
use std::str::Chars;
use uucore::{display::Quotable, show_error};
use super::format_field::FormatField;
use crate::cli;
// contains the rough ingredients to final
// output for a number, organized together
// to allow for easy generalization of output manipulation
@ -66,5 +65,5 @@ pub fn get_it_at(offset: usize, str_in: &str) -> PutBackN<Chars> {
// TODO: put this somewhere better
pub fn warn_incomplete_conv(pf_arg: &str) {
// important: keep println here not print
cli::err_msg(&format!("{}: value not completely converted", pf_arg))
show_error!("{}: value not completely converted", pf_arg.maybe_quote());
}

View file

@ -7,6 +7,9 @@
use std::env;
use std::vec::Vec;
use uucore::display::Quotable;
use uucore::show_error;
use super::format_field::{FieldType, FormatField};
use super::formatter::{Base, FormatPrimitive, Formatter, InitialPrefix};
use super::formatters::cninetyninehexfloatf::CninetyNineHexFloatf;
@ -15,11 +18,9 @@ use super::formatters::floatf::Floatf;
use super::formatters::intf::Intf;
use super::formatters::scif::Scif;
use crate::cli;
pub fn warn_expected_numeric(pf_arg: &str) {
// important: keep println here not print
cli::err_msg(&format!("{}: expected a numeric value", pf_arg));
show_error!("{}: expected a numeric value", pf_arg.maybe_quote());
}
// when character constant arguments have excess characters
@ -29,11 +30,11 @@ fn warn_char_constant_ign(remaining_bytes: Vec<u8>) {
Ok(_) => {}
Err(e) => {
if let env::VarError::NotPresent = e {
cli::err_msg(&format!(
show_error!(
"warning: {:?}: character(s) following character \
constant have been ignored",
&*remaining_bytes
));
);
}
}
}

View file

@ -10,6 +10,7 @@ use std::iter::Peekable;
use std::process::exit;
use std::slice::Iter;
use std::str::Chars;
use uucore::show_error;
// use std::collections::HashSet;
use super::num_format::format_field::{FieldType, FormatField};
@ -19,7 +20,7 @@ use super::unescaped_text::UnescapedText;
use crate::cli;
fn err_conv(sofar: &str) {
cli::err_msg(&format!("%{}: invalid conversion specification", sofar));
show_error!("%{}: invalid conversion specification", sofar);
exit(cli::EXIT_ERR);
}

View file

@ -17,6 +17,7 @@ use std::collections::{BTreeSet, HashMap, HashSet};
use std::default::Default;
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
static NAME: &str = "ptx";
@ -292,7 +293,11 @@ fn create_word_set(config: &Config, filter: &WordFilter, file_map: &FileMap) ->
fn get_reference(config: &Config, word_ref: &WordRef, line: &str, context_reg: &Regex) -> String {
if config.auto_ref {
format!("{}:{}", word_ref.filename, word_ref.local_line_nr + 1)
format!(
"{}:{}",
word_ref.filename.maybe_quote(),
word_ref.local_line_nr + 1
)
} else if config.input_ref {
let (beg, end) = match context_reg.find(line) {
Some(x) => (x.start(), x.end()),

View file

@ -14,6 +14,7 @@ use clap::{crate_version, App, Arg};
use std::fs;
use std::io::{stdout, Write};
use std::path::{Path, PathBuf};
use uucore::display::Quotable;
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
const ABOUT: &str = "Print value of a symbolic link or canonical file name.";
@ -71,10 +72,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
if no_newline && files.len() > 1 && !silent {
eprintln!(
"{}: ignoring --no-newline with multiple arguments",
uucore::util_name()
);
show_error!("ignoring --no-newline with multiple arguments");
no_newline = false;
}
@ -85,12 +83,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
Ok(path) => show(&path, no_newline, use_zero),
Err(err) => {
if verbose {
eprintln!(
"{}: {}: errno {}",
uucore::util_name(),
f,
err.raw_os_error().unwrap()
);
show_error!("{}: errno {}", f.maybe_quote(), err.raw_os_error().unwrap());
}
return 1;
}
@ -100,12 +93,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
Ok(path) => show(&path, no_newline, use_zero),
Err(err) => {
if verbose {
eprintln!(
"{}: {}: errno {:?}",
uucore::util_name(),
f,
err.raw_os_error().unwrap()
);
show_error!("{}: errno {}", f.maybe_quote(), err.raw_os_error().unwrap());
}
return 1;
}

View file

@ -11,8 +11,14 @@
extern crate uucore;
use clap::{crate_version, App, Arg};
use std::path::{Path, PathBuf};
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
use std::{
io::{stdout, Write},
path::{Path, PathBuf},
};
use uucore::{
display::{print_verbatim, Quotable},
fs::{canonicalize, MissingHandling, ResolveMode},
};
static ABOUT: &str = "print the resolved path";
@ -58,7 +64,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
for path in &paths {
if let Err(e) = resolve_path(path, strip, zero, logical, can_mode) {
if !quiet {
show_error!("{}: {}", e, path.display());
show_error!("{}: {}", path.maybe_quote(), e);
}
retcode = 1
};
@ -154,8 +160,9 @@ fn resolve_path(
ResolveMode::Physical
};
let abs = canonicalize(p, can_mode, resolve)?;
let line_ending = if zero { '\0' } else { '\n' };
let line_ending = if zero { b'\0' } else { b'\n' };
print!("{}{}", abs.display(), line_ending);
print_verbatim(&abs)?;
stdout().write_all(&[line_ending])?;
Ok(())
}

View file

@ -10,6 +10,7 @@
use clap::{crate_version, App, Arg};
use std::env;
use std::path::{Path, PathBuf};
use uucore::display::println_verbatim;
use uucore::fs::{canonicalize, MissingHandling, ResolveMode};
use uucore::InvalidEncodingHandling;
@ -48,7 +49,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if !absto.as_path().starts_with(absbase.as_path())
|| !absfrom.as_path().starts_with(absbase.as_path())
{
println!("{}", absto.display());
println_verbatim(absto).unwrap();
return 0;
}
}
@ -74,7 +75,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.map(|x| result.push(x.as_os_str()))
.last();
println!("{}", result.display());
println_verbatim(result).unwrap();
0
}

View file

@ -17,6 +17,7 @@ use std::fs;
use std::io::{stderr, stdin, BufRead, Write};
use std::ops::BitOr;
use std::path::{Path, PathBuf};
use uucore::display::Quotable;
use walkdir::{DirEntry, WalkDir};
#[derive(Eq, PartialEq, Clone, Copy)]
@ -236,7 +237,10 @@ fn remove(files: Vec<String>, options: Options) -> bool {
// (e.g., permission), even rm -f should fail with
// outputting the error, but there's no easy eay.
if !options.force {
show_error!("cannot remove '{}': No such file or directory", filename);
show_error!(
"cannot remove {}: No such file or directory",
filename.quote()
);
true
} else {
false
@ -263,13 +267,9 @@ fn handle_dir(path: &Path, options: &Options) -> bool {
// GNU compatibility (rm/fail-eacces.sh)
// here, GNU doesn't use some kind of remove_dir_all
// It will show directory+file
show_error!(
"cannot remove '{}': {}",
path.display(),
"Permission denied"
);
show_error!("cannot remove {}: {}", path.quote(), "Permission denied");
} else {
show_error!("cannot remove '{}': {}", path.display(), e);
show_error!("cannot remove {}: {}", path.quote(), e);
}
}
} else {
@ -287,7 +287,7 @@ fn handle_dir(path: &Path, options: &Options) -> bool {
}
Err(e) => {
had_err = true;
show_error!("recursing in '{}': {}", path.display(), e);
show_error!("recursing in {}: {}", path.quote(), e);
}
}
}
@ -299,12 +299,12 @@ fn handle_dir(path: &Path, options: &Options) -> bool {
} else if options.dir && (!is_root || !options.preserve_root) {
had_err = remove_dir(path, options).bitor(had_err);
} else if options.recursive {
show_error!("could not remove directory '{}'", path.display());
show_error!("could not remove directory {}", path.quote());
had_err = true;
} else {
show_error!(
"cannot remove '{}': Is a directory", // GNU's rm error message does not include help
path.display()
"cannot remove {}: Is a directory", // GNU's rm error message does not include help
path.quote()
);
had_err = true;
}
@ -325,36 +325,36 @@ fn remove_dir(path: &Path, options: &Options) -> bool {
match fs::remove_dir(path) {
Ok(_) => {
if options.verbose {
println!("removed directory '{}'", normalize(path).display());
println!("removed directory {}", normalize(path).quote());
}
}
Err(e) => {
if e.kind() == std::io::ErrorKind::PermissionDenied {
// GNU compatibility (rm/fail-eacces.sh)
show_error!(
"cannot remove '{}': {}",
path.display(),
"cannot remove {}: {}",
path.quote(),
"Permission denied"
);
} else {
show_error!("cannot remove '{}': {}", path.display(), e);
show_error!("cannot remove {}: {}", path.quote(), e);
}
return true;
}
}
} else {
// directory can be read but is not empty
show_error!("cannot remove '{}': Directory not empty", path.display());
show_error!("cannot remove {}: Directory not empty", path.quote());
return true;
}
} else {
// called to remove a symlink_dir (windows) without "-r"/"-R" or "-d"
show_error!("cannot remove '{}': Is a directory", path.display());
show_error!("cannot remove {}: Is a directory", path.quote());
return true;
}
} else {
// GNU's rm shows this message if directory is empty but not readable
show_error!("cannot remove '{}': Directory not empty", path.display());
show_error!("cannot remove {}: Directory not empty", path.quote());
return true;
}
}
@ -372,19 +372,15 @@ fn remove_file(path: &Path, options: &Options) -> bool {
match fs::remove_file(path) {
Ok(_) => {
if options.verbose {
println!("removed '{}'", normalize(path).display());
println!("removed {}", normalize(path).quote());
}
}
Err(e) => {
if e.kind() == std::io::ErrorKind::PermissionDenied {
// GNU compatibility (rm/fail-eacces.sh)
show_error!(
"cannot remove '{}': {}",
path.display(),
"Permission denied"
);
show_error!("cannot remove {}: {}", path.quote(), "Permission denied");
} else {
show_error!("cannot remove '{}': {}", path.display(), e);
show_error!("cannot remove {}: {}", path.quote(), e);
}
return true;
}
@ -396,9 +392,9 @@ fn remove_file(path: &Path, options: &Options) -> bool {
fn prompt_file(path: &Path, is_dir: bool) -> bool {
if is_dir {
prompt(&(format!("rm: remove directory '{}'? ", path.display())))
prompt(&(format!("rm: remove directory {}? ", path.quote())))
} else {
prompt(&(format!("rm: remove file '{}'? ", path.display())))
prompt(&(format!("rm: remove file {}? ", path.quote())))
}
}

View file

@ -3,6 +3,8 @@ use std::fmt::Write;
use std::io;
use std::str::Utf8Error;
use uucore::display::Quotable;
pub(crate) type Result<T> = std::result::Result<T, Error>;
#[derive(thiserror::Error, Debug)]
@ -31,7 +33,7 @@ pub(crate) enum Error {
source: io::Error,
},
#[error("{operation} failed on '{}'", .operand1.to_string_lossy())]
#[error("{operation} failed on {}", .operand1.quote())]
Io1 {
operation: &'static str,
operand1: OsString,

View file

@ -14,6 +14,7 @@ use num_traits::{Num, ToPrimitive};
use std::cmp;
use std::io::{stdout, Write};
use std::str::FromStr;
use uucore::display::Quotable;
static ABOUT: &str = "Display numbers from FIRST to LAST, in steps of INCREMENT.";
static OPT_SEPARATOR: &str = "separator";
@ -115,14 +116,14 @@ impl FromStr for Number {
}
Err(_) => match s.parse::<f64>() {
Ok(value) if value.is_nan() => Err(format!(
"invalid 'not-a-number' argument: '{}'\nTry '{} --help' for more information.",
s,
"invalid 'not-a-number' argument: {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase(),
)),
Ok(value) => Ok(Number::F64(value)),
Err(_) => Err(format!(
"invalid floating point argument: '{}'\nTry '{} --help' for more information.",
s,
"invalid floating point argument: {}\nTry '{} --help' for more information.",
s.quote(),
uucore::execution_phrase(),
)),
},

View file

@ -18,12 +18,12 @@ use std::io;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::path::{Path, PathBuf};
use uucore::InvalidEncodingHandling;
use uucore::display::Quotable;
use uucore::{util_name, InvalidEncodingHandling};
#[macro_use]
extern crate uucore;
static NAME: &str = "shred";
const BLOCK_SIZE: usize = 512;
const NAME_CHARSET: &[u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.";
@ -281,7 +281,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if !matches.is_present(options::FILE) {
show_error!("Missing an argument");
show_error!("For help, try '{} --help'", NAME);
show_error!("For help, try '{} --help'", uucore::execution_phrase());
return 0;
}
@ -289,7 +289,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
Some(s) => match s.parse::<usize>() {
Ok(u) => u,
Err(_) => {
errs.push(format!("invalid number of passes: '{}'", s));
errs.push(format!("invalid number of passes: {}", s.quote()));
0
}
},
@ -414,7 +414,11 @@ fn get_size(size_str_opt: Option<String>) -> Option<u64> {
let coefficient = match size_str.parse::<u64>() {
Ok(u) => u,
Err(_) => {
println!("{}: {}: Invalid file size", NAME, size_str_opt.unwrap());
println!(
"{}: {}: Invalid file size",
util_name(),
size_str_opt.unwrap().maybe_quote()
);
exit!(1);
}
};
@ -452,11 +456,11 @@ fn wipe_file(
// Get these potential errors out of the way first
let path: &Path = Path::new(path_str);
if !path.exists() {
show_error!("{}: No such file or directory", path.display());
show_error!("{}: No such file or directory", path.maybe_quote());
return;
}
if !path.is_file() {
show_error!("{}: Not a file", path.display());
show_error!("{}: Not a file", path.maybe_quote());
return;
}
@ -520,7 +524,7 @@ fn wipe_file(
let mut file: File = match OpenOptions::new().write(true).truncate(false).open(path) {
Ok(f) => f,
Err(e) => {
show_error!("{}: failed to open for writing: {}", path.display(), e);
show_error!("{}: failed to open for writing: {}", path.maybe_quote(), e);
return;
}
};
@ -535,8 +539,8 @@ fn wipe_file(
if total_passes.to_string().len() == 1 {
println!(
"{}: {}: pass {}/{} ({})... ",
NAME,
path.display(),
util_name(),
path.maybe_quote(),
i + 1,
total_passes,
pass_name
@ -544,8 +548,8 @@ fn wipe_file(
} else {
println!(
"{}: {}: pass {:2.0}/{:2.0} ({})... ",
NAME,
path.display(),
util_name(),
path.maybe_quote(),
i + 1,
total_passes,
pass_name
@ -556,7 +560,7 @@ fn wipe_file(
match do_pass(&mut file, path, &mut generator, *pass_type, size) {
Ok(_) => {}
Err(e) => {
show_error!("{}: File write pass failed: {}", path.display(), e);
show_error!("{}: File write pass failed: {}", path.maybe_quote(), e);
}
}
// Ignore failed writes; just keep trying
@ -567,7 +571,7 @@ fn wipe_file(
match do_remove(path, path_str, verbose) {
Ok(_) => {}
Err(e) => {
show_error!("{}: failed to remove file: {}", path.display(), e);
show_error!("{}: failed to remove file: {}", path.maybe_quote(), e);
}
}
}
@ -622,9 +626,9 @@ fn wipe_name(orig_path: &Path, verbose: bool) -> Option<PathBuf> {
if verbose {
println!(
"{}: {}: renamed to {}",
NAME,
last_path.display(),
new_path.display()
util_name(),
last_path.maybe_quote(),
new_path.quote()
);
}
@ -641,9 +645,9 @@ fn wipe_name(orig_path: &Path, verbose: bool) -> Option<PathBuf> {
Err(e) => {
println!(
"{}: {}: Couldn't rename to {}: {}",
NAME,
last_path.display(),
new_path.display(),
util_name(),
last_path.maybe_quote(),
new_path.quote(),
e
);
return None;
@ -657,7 +661,7 @@ fn wipe_name(orig_path: &Path, verbose: bool) -> Option<PathBuf> {
fn do_remove(path: &Path, orig_filename: &str, verbose: bool) -> Result<(), io::Error> {
if verbose {
println!("{}: {}: removing", NAME, orig_filename);
println!("{}: {}: removing", util_name(), orig_filename.maybe_quote());
}
let renamed_path: Option<PathBuf> = wipe_name(path, verbose);
@ -666,7 +670,7 @@ fn do_remove(path: &Path, orig_filename: &str, verbose: bool) -> Result<(), io::
}
if verbose {
println!("{}: {}: removed", NAME, orig_filename);
println!("{}: {}: removed", util_name(), orig_filename.maybe_quote());
}
Ok(())

View file

@ -14,6 +14,7 @@ use clap::{crate_version, App, Arg};
use rand::Rng;
use std::fs::File;
use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
enum Mode {
@ -76,7 +77,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
Some(count) => match count.parse::<usize>() {
Ok(val) => val,
Err(_) => {
show_error!("invalid line count: '{}'", count);
show_error!("invalid line count: {}", count.quote());
return 1;
}
},
@ -185,13 +186,13 @@ fn read_input_file(filename: &str) -> Vec<u8> {
} else {
match File::open(filename) {
Ok(f) => Box::new(f) as Box<dyn Read>,
Err(e) => crash!(1, "failed to open '{}': {}", filename, e),
Err(e) => crash!(1, "failed to open {}: {}", filename.quote(), e),
}
});
let mut data = Vec::new();
if let Err(e) = file.read_to_end(&mut data) {
crash!(1, "failed reading '{}': {}", filename, e)
crash!(1, "failed reading {}: {}", filename.quote(), e)
};
data
@ -235,7 +236,7 @@ fn shuf_bytes(input: &mut Vec<&[u8]>, opts: Options) {
None => Box::new(stdout()) as Box<dyn Write>,
Some(s) => match File::create(&s[..]) {
Ok(f) => Box::new(f) as Box<dyn Write>,
Err(e) => crash!(1, "failed to open '{}' for writing: {}", &s[..], e),
Err(e) => crash!(1, "failed to open {} for writing: {}", s.quote(), e),
},
});
@ -243,7 +244,7 @@ fn shuf_bytes(input: &mut Vec<&[u8]>, opts: Options) {
Some(r) => WrappedRng::RngFile(rand::rngs::adapter::ReadRng::new(
match File::open(&r[..]) {
Ok(f) => f,
Err(e) => crash!(1, "failed to open random source '{}': {}", &r[..], e),
Err(e) => crash!(1, "failed to open random source {}: {}", r.quote(), e),
},
)),
None => WrappedRng::RngDefault(rand::thread_rng()),
@ -288,14 +289,14 @@ fn shuf_bytes(input: &mut Vec<&[u8]>, opts: Options) {
fn parse_range(input_range: &str) -> Result<(usize, usize), String> {
let split: Vec<&str> = input_range.split('-').collect();
if split.len() != 2 {
Err(format!("invalid input range: '{}'", input_range))
Err(format!("invalid input range: {}", input_range.quote()))
} else {
let begin = split[0]
.parse::<usize>()
.map_err(|_| format!("invalid input range: '{}'", split[0]))?;
.map_err(|_| format!("invalid input range: {}", split[0].quote()))?;
let end = split[1]
.parse::<usize>()
.map_err(|_| format!("invalid input range: '{}'", split[1]))?;
.map_err(|_| format!("invalid input range: {}", split[1].quote()))?;
Ok((begin, end + 1))
}
}

View file

@ -45,6 +45,7 @@ use std::path::Path;
use std::path::PathBuf;
use std::str::Utf8Error;
use unicode_width::UnicodeWidthStr;
use uucore::display::Quotable;
use uucore::error::{set_exit_code, strip_errno, UError, UResult, USimpleError, UUsageError};
use uucore::parse_size::{parse_size, ParseSizeError};
use uucore::version_cmp::version_cmp;
@ -139,7 +140,7 @@ enum SortError {
error: std::io::Error,
},
ReadFailed {
path: String,
path: PathBuf,
error: std::io::Error,
},
ParseKeyError {
@ -189,7 +190,7 @@ impl Display for SortError {
write!(
f,
"{}:{}: disorder: {}",
file.to_string_lossy(),
file.maybe_quote(),
line_number,
line
)
@ -198,13 +199,23 @@ impl Display for SortError {
}
}
SortError::OpenFailed { path, error } => {
write!(f, "open failed: {}: {}", path, strip_errno(error))
write!(
f,
"open failed: {}: {}",
path.maybe_quote(),
strip_errno(error)
)
}
SortError::ParseKeyError { key, msg } => {
write!(f, "failed to parse key `{}`: {}", key, msg)
write!(f, "failed to parse key {}: {}", key.quote(), msg)
}
SortError::ReadFailed { path, error } => {
write!(f, "cannot read: {}: {}", path, strip_errno(error))
write!(
f,
"cannot read: {}: {}",
path.maybe_quote(),
strip_errno(error)
)
}
SortError::OpenTmpFileFailed { error } => {
write!(f, "failed to open temporary file: {}", strip_errno(error))
@ -213,7 +224,7 @@ impl Display for SortError {
write!(f, "couldn't execute compress program: errno {}", code)
}
SortError::CompressProgTerminatedAbnormally { prog } => {
write!(f, "'{}' terminated abnormally", prog)
write!(f, "{} terminated abnormally", prog.quote())
}
SortError::TmpDirCreationFailed => write!(f, "could not create temporary directory"),
SortError::Uft8Error { error } => write!(f, "{}", error),
@ -1179,7 +1190,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
if let Some(n_merge) = matches.value_of(options::BATCH_SIZE) {
settings.merge_batch_size = n_merge.parse().map_err(|_| {
UUsageError::new(2, format!("invalid --batch-size argument '{}'", n_merge))
UUsageError::new(
2,
format!("invalid --batch-size argument {}", n_merge.quote()),
)
})?;
}
@ -1211,23 +1225,30 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
} else if settings.check && files.len() != 1 {
return Err(UUsageError::new(
2,
format!(
"extra operand `{}' not allowed with -c",
files[1].to_string_lossy()
),
format!("extra operand {} not allowed with -c", files[1].quote()),
));
}
if let Some(arg) = matches.args.get(options::SEPARATOR) {
let separator = arg.vals[0].to_string_lossy();
let mut separator = separator.as_ref();
let mut separator = arg.vals[0].to_str().ok_or_else(|| {
UUsageError::new(
2,
format!("separator is not valid unicode: {}", arg.vals[0].quote()),
)
})?;
if separator == "\\0" {
separator = "\0";
}
// This rejects non-ASCII codepoints, but perhaps we don't have to.
// On the other hand GNU accepts any single byte, valid unicode or not.
// (Supporting multi-byte chars would require changes in tokenize_with_separator().)
if separator.len() != 1 {
return Err(UUsageError::new(
2,
"separator must be exactly one character long",
format!(
"separator must be exactly one character long: {}",
separator.quote()
),
));
}
settings.separator = Some(separator.chars().next().unwrap())
@ -1816,7 +1837,7 @@ fn open(path: impl AsRef<OsStr>) -> UResult<Box<dyn Read + Send>> {
match File::open(path) {
Ok(f) => Ok(Box::new(f) as Box<dyn Read + Send>),
Err(error) => Err(SortError::ReadFailed {
path: path.to_string_lossy().to_string(),
path: path.to_owned(),
error,
}
.into()),
@ -1828,8 +1849,8 @@ fn format_error_message(error: ParseSizeError, s: &str, option: &str) -> String
// GNU's sort echos affected flag, -S or --buffer-size, depending user's selection
// GNU's sort does distinguish between "invalid (suffix in) argument"
match error {
ParseSizeError::ParseFailure(_) => format!("invalid --{} argument '{}'", option, s),
ParseSizeError::SizeTooBig(_) => format!("--{} argument '{}' too large", option, s),
ParseSizeError::ParseFailure(_) => format!("invalid --{} argument {}", option, s.quote()),
ParseSizeError::SizeTooBig(_) => format!("--{} argument {} too large", option, s.quote()),
}
}

View file

@ -19,6 +19,7 @@ use std::fs::File;
use std::io::{stdin, BufRead, BufReader, BufWriter, Read, Write};
use std::path::Path;
use std::{char, fs::remove_file};
use uucore::display::Quotable;
use uucore::parse_size::parse_size;
static OPT_BYTES: &str = "bytes";
@ -238,7 +239,11 @@ impl LineSplitter {
fn new(settings: &Settings) -> LineSplitter {
LineSplitter {
lines_per_split: settings.strategy_param.parse().unwrap_or_else(|_| {
crash!(1, "invalid number of lines: '{}'", settings.strategy_param)
crash!(
1,
"invalid number of lines: {}",
settings.strategy_param.quote()
)
}),
}
}
@ -373,8 +378,8 @@ fn split(settings: &Settings) -> i32 {
let r = File::open(Path::new(&settings.input)).unwrap_or_else(|_| {
crash!(
1,
"cannot open '{}' for reading: No such file or directory",
settings.input
"cannot open {} for reading: No such file or directory",
settings.input.quote()
)
});
Box::new(r) as Box<dyn Read>
@ -383,7 +388,7 @@ fn split(settings: &Settings) -> i32 {
let mut splitter: Box<dyn Splitter> = match settings.strategy.as_str() {
s if s == OPT_LINES => Box::new(LineSplitter::new(settings)),
s if (s == OPT_BYTES || s == OPT_LINE_BYTES) => Box::new(ByteSplitter::new(settings)),
a => crash!(1, "strategy {} not supported", a),
a => crash!(1, "strategy {} not supported", a.quote()),
};
let mut fileno = 0;

View file

@ -7,6 +7,7 @@
#[macro_use]
extern crate uucore;
use uucore::display::Quotable;
use uucore::entries;
use uucore::fs::display_permissions;
use uucore::fsext::{
@ -24,7 +25,7 @@ use std::{cmp, fs, iter};
macro_rules! check_bound {
($str: ident, $bound:expr, $beg: expr, $end: expr) => {
if $end >= $bound {
return Err(format!("'{}': invalid directive", &$str[$beg..$end]));
return Err(format!("{}: invalid directive", $str[$beg..$end].quote()));
}
};
}
@ -652,11 +653,7 @@ impl Stater {
return 1;
}
};
arg = format!(
"`{}' -> `{}'",
file,
dst.to_string_lossy()
);
arg = format!("{} -> {}", file.quote(), dst.quote());
} else {
arg = file.to_string();
}
@ -750,7 +747,7 @@ impl Stater {
}
}
Err(e) => {
show_error!("cannot stat '{}': {}", file, e);
show_error!("cannot stat {}: {}", file.quote(), e);
return 1;
}
}
@ -843,7 +840,11 @@ impl Stater {
}
}
Err(e) => {
show_error!("cannot read file system information for '{}': {}", file, e);
show_error!(
"cannot read file system information for {}: {}",
file.quote(),
e
);
return 1;
}
}

View file

@ -14,6 +14,7 @@ use clap::{crate_version, App, Arg};
use std::fs::File;
use std::io::{stdin, Read, Result};
use std::path::Path;
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
static NAME: &str = "sum";
@ -118,7 +119,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let reader = match open(file) {
Ok(f) => f,
Err(error) => {
show_error!("'{}' {}", file, error);
show_error!("{}: {}", file.maybe_quote(), error);
exit_code = 2;
continue;
}

View file

@ -14,6 +14,7 @@ extern crate uucore;
use clap::{crate_version, App, Arg};
use std::path::Path;
use uucore::display::Quotable;
static EXIT_ERR: i32 = 1;
@ -175,7 +176,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
for f in &files {
if !Path::new(&f).exists() {
crash!(EXIT_ERR, "cannot stat '{}': No such file or directory", f);
crash!(
EXIT_ERR,
"cannot stat {}: No such file or directory",
f.quote()
);
}
}

View file

@ -14,6 +14,7 @@ use clap::{crate_version, App, Arg};
use memchr::memmem;
use std::io::{stdin, stdout, BufReader, Read, Write};
use std::{fs::File, path::Path};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
static NAME: &str = "tac";
@ -141,11 +142,11 @@ fn tac(filenames: Vec<String>, before: bool, _: bool, separator: &str) -> i32 {
let path = Path::new(filename);
if path.is_dir() || path.metadata().is_err() {
if path.is_dir() {
show_error!("{}: read error: Invalid argument", filename);
show_error!("{}: read error: Invalid argument", filename.maybe_quote());
} else {
show_error!(
"failed to open '{}' for reading: No such file or directory",
filename
"failed to open {} for reading: No such file or directory",
filename.quote()
);
}
exit_code = 1;
@ -154,7 +155,7 @@ fn tac(filenames: Vec<String>, before: bool, _: bool, separator: &str) -> i32 {
match File::open(path) {
Ok(f) => Box::new(f) as Box<dyn Read>,
Err(e) => {
show_error!("failed to open '{}' for reading: {}", filename, e);
show_error!("failed to open {} for reading: {}", filename.quote(), e);
exit_code = 1;
continue;
}
@ -163,7 +164,7 @@ fn tac(filenames: Vec<String>, before: bool, _: bool, separator: &str) -> i32 {
let mut data = Vec::new();
if let Err(e) = file.read_to_end(&mut data) {
show_error!("failed to read '{}': {}", filename, e);
show_error!("failed to read {}: {}", filename.quote(), e);
exit_code = 1;
continue;
};

View file

@ -12,7 +12,8 @@ use clap::{crate_version, App, Arg};
use retain_mut::RetainMut;
use std::fs::OpenOptions;
use std::io::{copy, sink, stdin, stdout, Error, ErrorKind, Read, Result, Write};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use uucore::display::Quotable;
#[cfg(unix)]
use uucore::libc;
@ -167,7 +168,7 @@ impl Write for MultiWriter {
let result = writer.write_all(buf);
match result {
Err(f) => {
show_error!("{}: {}", writer.name, f.to_string());
show_error!("{}: {}", writer.name.maybe_quote(), f);
false
}
_ => true,
@ -181,7 +182,7 @@ impl Write for MultiWriter {
let result = writer.flush();
match result {
Err(f) => {
show_error!("{}: {}", writer.name, f.to_string());
show_error!("{}: {}", writer.name.maybe_quote(), f);
false
}
_ => true,
@ -214,7 +215,7 @@ impl Read for NamedReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
match self.inner.read(buf) {
Err(f) => {
show_error!("{}: {}", Path::new("stdin").display(), f.to_string());
show_error!("stdin: {}", f);
Err(f)
}
okay => okay,

View file

@ -10,6 +10,8 @@
use std::ffi::OsString;
use std::iter::Peekable;
use uucore::display::Quotable;
/// Represents one of the binary comparison operators for strings, integers, or files
#[derive(Debug, PartialEq)]
pub enum Operator {
@ -43,7 +45,8 @@ impl Symbol {
/// Returns Symbol::None in place of None
fn new(token: Option<OsString>) -> Symbol {
match token {
Some(s) => match s.to_string_lossy().as_ref() {
Some(s) => match s.to_str() {
Some(t) => match t {
"(" => Symbol::LParen,
"!" => Symbol::Bang,
"-a" | "-o" => Symbol::BoolOp(s),
@ -57,6 +60,8 @@ impl Symbol {
}
_ => Symbol::Literal(s),
},
None => Symbol::Literal(s),
},
None => Symbol::None,
}
}
@ -391,7 +396,7 @@ impl Parser {
self.expr();
match self.tokens.next() {
Some(token) => Err(format!("extra argument '{}'", token.to_string_lossy())),
Some(token) => Err(format!("extra argument {}", token.quote())),
None => Ok(()),
}
}

View file

@ -13,7 +13,7 @@ mod parser;
use clap::{crate_version, App, AppSettings};
use parser::{parse, Operator, Symbol, UnaryOperator};
use std::ffi::{OsStr, OsString};
use std::path::Path;
use uucore::{display::Quotable, show_error};
const USAGE: &str = "test EXPRESSION
or: test
@ -93,10 +93,7 @@ pub fn uu_app() -> App<'static, 'static> {
pub fn uumain(mut args: impl uucore::Args) -> i32 {
let program = args.next().unwrap_or_else(|| OsString::from("test"));
let binary_name = Path::new(&program)
.file_name()
.unwrap_or_else(|| OsStr::new("test"))
.to_string_lossy();
let binary_name = uucore::util_name();
let mut args: Vec<_> = args.collect();
if binary_name.ends_with('[') {
@ -116,8 +113,8 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 {
}
// If invoked via name '[', matching ']' must be in the last arg
let last = args.pop();
if last != Some(OsString::from("]")) {
eprintln!("[: missing ']'");
if last.as_deref() != Some(OsStr::new("]")) {
show_error!("missing ']'");
return 2;
}
}
@ -133,7 +130,7 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 {
}
}
Err(e) => {
eprintln!("test: {}", e);
show_error!("{}", e);
2
}
}
@ -190,11 +187,11 @@ fn eval(stack: &mut Vec<Symbol>) -> Result<bool, String> {
})
}
Some(Symbol::UnaryOp(UnaryOperator::FiletestOp(op))) => {
let op = op.to_string_lossy();
let op = op.to_str().unwrap();
let f = pop_literal!();
Ok(match op.as_ref() {
Ok(match op {
"-b" => path(&f, PathCondition::BlockSpecial),
"-c" => path(&f, PathCondition::CharacterSpecial),
"-d" => path(&f, PathCondition::Directory),
@ -231,31 +228,33 @@ fn eval(stack: &mut Vec<Symbol>) -> Result<bool, String> {
}
fn integers(a: &OsStr, b: &OsStr, op: &OsStr) -> Result<bool, String> {
let format_err = |value| format!("invalid integer '{}'", value);
let format_err = |value: &OsStr| format!("invalid integer {}", value.quote());
let a = a.to_string_lossy();
let a: i64 = a.parse().map_err(|_| format_err(a))?;
let a: i64 = a
.to_str()
.and_then(|s| s.parse().ok())
.ok_or_else(|| format_err(a))?;
let b = b.to_string_lossy();
let b: i64 = b.parse().map_err(|_| format_err(b))?;
let b: i64 = b
.to_str()
.and_then(|s| s.parse().ok())
.ok_or_else(|| format_err(b))?;
let operator = op.to_string_lossy();
Ok(match operator.as_ref() {
"-eq" => a == b,
"-ne" => a != b,
"-gt" => a > b,
"-ge" => a >= b,
"-lt" => a < b,
"-le" => a <= b,
_ => return Err(format!("unknown operator '{}'", operator)),
Ok(match op.to_str() {
Some("-eq") => a == b,
Some("-ne") => a != b,
Some("-gt") => a > b,
Some("-ge") => a >= b,
Some("-lt") => a < b,
Some("-le") => a <= b,
_ => return Err(format!("unknown operator {}", op.quote())),
})
}
fn isatty(fd: &OsStr) -> Result<bool, String> {
let fd = fd.to_string_lossy();
fd.parse()
.map_err(|_| format!("invalid integer '{}'", fd))
fd.to_str()
.and_then(|s| s.parse().ok())
.ok_or_else(|| format!("invalid integer {}", fd.quote()))
.map(|i| {
#[cfg(not(target_os = "redox"))]
unsafe {

View file

@ -16,6 +16,7 @@ use clap::{crate_version, App, AppSettings, Arg};
use std::io::ErrorKind;
use std::process::{Command, Stdio};
use std::time::Duration;
use uucore::display::Quotable;
use uucore::process::ChildExt;
use uucore::signals::{signal_by_name_or_value, signal_name_by_value};
use uucore::InvalidEncodingHandling;
@ -61,7 +62,7 @@ impl Config {
let signal_result = signal_by_name_or_value(signal_);
match signal_result {
None => {
unreachable!("invalid signal '{}'", signal_);
unreachable!("invalid signal {}", signal_.quote());
}
Some(signal_value) => signal_value,
}
@ -216,9 +217,9 @@ fn timeout(
Ok(None) => {
if verbose {
show_error!(
"sending signal {} to command '{}'",
"sending signal {} to command {}",
signal_name_by_value(signal).unwrap(),
cmd[0]
cmd[0].quote()
);
}
crash_if_err!(ERR_EXIT_STATUS, process.send_signal(signal));
@ -233,7 +234,7 @@ fn timeout(
}
Ok(None) => {
if verbose {
show_error!("sending signal KILL to command '{}'", cmd[0]);
show_error!("sending signal KILL to command {}", cmd[0].quote());
}
crash_if_err!(
ERR_EXIT_STATUS,

View file

@ -17,6 +17,7 @@ use clap::{crate_version, App, Arg, ArgGroup};
use filetime::*;
use std::fs::{self, File};
use std::path::Path;
use uucore::display::Quotable;
use uucore::error::{FromIo, UError, UResult, USimpleError};
static ABOUT: &str = "Update the access and modification times of each FILE to the current time.";
@ -82,7 +83,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
if let Err(e) = File::create(path) {
show!(e.map_err_context(|| format!("cannot touch '{}'", path.display())));
show!(e.map_err_context(|| format!("cannot touch {}", path.quote())));
continue;
};
@ -122,7 +123,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
} else {
filetime::set_file_times(path, atime, mtime)
}
.map_err_context(|| format!("setting times of '{}'", path.display()))?;
.map_err_context(|| format!("setting times of {}", path.quote()))?;
}
Ok(())
@ -209,7 +210,7 @@ fn stat(path: &Path, follow: bool) -> UResult<(FileTime, FileTime)> {
} else {
fs::metadata(path)
}
.map_err_context(|| format!("failed to get attributes of '{}'", path.display()))?;
.map_err_context(|| format!("failed to get attributes of {}", path.quote()))?;
Ok((
FileTime::from_last_access_time(&metadata),
@ -249,11 +250,16 @@ fn parse_timestamp(s: &str) -> UResult<FileTime> {
10 => ("%y%m%d%H%M", s.to_owned()),
11 => ("%Y%m%d%H%M.%S", format!("{}{}", now.tm_year + 1900, s)),
8 => ("%Y%m%d%H%M", format!("{}{}", now.tm_year + 1900, s)),
_ => return Err(USimpleError::new(1, format!("invalid date format '{}'", s))),
_ => {
return Err(USimpleError::new(
1,
format!("invalid date format {}", s.quote()),
))
}
};
let tm = time::strptime(&ts, format)
.map_err(|_| USimpleError::new(1, format!("invalid date format '{}'", s)))?;
.map_err(|_| USimpleError::new(1, format!("invalid date format {}", s.quote())))?;
let mut local = to_local(tm);
local.tm_isdst = -1;
@ -269,7 +275,10 @@ fn parse_timestamp(s: &str) -> UResult<FileTime> {
};
let tm2 = time::at(ts);
if tm.tm_hour != tm2.tm_hour {
return Err(USimpleError::new(1, format!("invalid date format '{}'", s)));
return Err(USimpleError::new(
1,
format!("invalid date format {}", s.quote()),
));
}
Ok(ft)

View file

@ -21,7 +21,7 @@ use fnv::FnvHashMap;
use std::io::{stdin, stdout, BufRead, BufWriter, Write};
use crate::expand::ExpandSet;
use uucore::InvalidEncodingHandling;
use uucore::{display::Quotable, InvalidEncodingHandling};
static ABOUT: &str = "translate or delete characters";
@ -271,8 +271,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if !(delete_flag || squeeze_flag) && sets.len() < 2 {
show_error!(
"missing operand after '{}'\nTry '{} --help' for more information.",
sets[0],
"missing operand after {}\nTry '{} --help' for more information.",
sets[0].quote(),
uucore::execution_phrase()
);
return 1;

View file

@ -15,6 +15,7 @@ use std::convert::TryFrom;
use std::fs::{metadata, OpenOptions};
use std::io::ErrorKind;
use std::path::Path;
use uucore::display::Quotable;
use uucore::parse_size::{parse_size, ParseSizeError};
#[derive(Debug, Eq, PartialEq)]
@ -120,8 +121,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let reference = matches.value_of(options::REFERENCE).map(String::from);
crash!(
1,
"cannot stat '{}': No such file or directory",
reference.unwrap_or_else(|| "".to_string())
"cannot stat {}: No such file or directory",
reference.as_deref().unwrap_or("").quote()
); // TODO: fix '--no-create' see test_reference and test_truncate_bytes_size
}
_ => crash!(1, "{}", e.to_string()),

View file

@ -14,6 +14,7 @@ use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read};
use std::path::Path;
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
static SUMMARY: &str = "Topological sort the strings in FILE.
@ -45,7 +46,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
file_buf = match File::open(Path::new(&input)) {
Ok(a) => a,
_ => {
show_error!("{}: No such file or directory", input);
show_error!("{}: No such file or directory", input.maybe_quote());
return 1;
}
};
@ -68,7 +69,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
for ab in tokens.chunks(2) {
match ab.len() {
2 => g.add_edge(&ab[0], &ab[1]),
_ => crash!(1, "{}: input contains an odd number of tokens", input),
_ => crash!(
1,
"{}: input contains an odd number of tokens",
input.maybe_quote()
),
}
}
}

View file

@ -16,6 +16,7 @@ use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Stdout, Write};
use std::str::from_utf8;
use unicode_width::UnicodeWidthChar;
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
static NAME: &str = "unexpand";
@ -141,9 +142,9 @@ fn open(path: String) -> BufReader<Box<dyn Read + 'static>> {
if path == "-" {
BufReader::new(Box::new(stdin()) as Box<dyn Read>)
} else {
file_buf = match File::open(&path[..]) {
file_buf = match File::open(&path) {
Ok(a) => a,
Err(e) => crash!(1, "{}: {}", &path[..], e),
Err(e) => crash!(1, "{}: {}", path.maybe_quote(), e),
};
BufReader::new(Box::new(file_buf) as Box<dyn Read>)
}

View file

@ -14,6 +14,7 @@ use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Result, Write}
use std::path::Path;
use std::str::FromStr;
use strum_macros::{AsRefStr, EnumString};
use uucore::display::Quotable;
static ABOUT: &str = "Report or omit repeated lines.";
pub mod options {
@ -217,7 +218,14 @@ fn get_line_string(io_line: Result<Vec<u8>>) -> String {
fn opt_parsed<T: FromStr>(opt_name: &str, matches: &ArgMatches) -> Option<T> {
matches.value_of(opt_name).map(|arg_str| {
let opt_val: Option<T> = arg_str.parse().ok();
opt_val.unwrap_or_else(|| crash!(1, "Invalid argument for {}: {}", opt_name, arg_str))
opt_val.unwrap_or_else(|| {
crash!(
1,
"Invalid argument for {}: {}",
opt_name,
arg_str.maybe_quote()
)
})
})
}

View file

@ -17,6 +17,7 @@ use libc::{lstat, stat, unlink};
use libc::{S_IFLNK, S_IFMT, S_IFREG};
use std::ffi::CString;
use std::io::{Error, ErrorKind};
use uucore::display::Quotable;
use uucore::InvalidEncodingHandling;
static ABOUT: &str = "Unlink the file at [FILE].";
@ -63,7 +64,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let result = unsafe { lstat(c_string.as_ptr(), &mut buf as *mut stat) };
if result < 0 {
crash!(1, "Cannot stat '{}': {}", paths[0], Error::last_os_error());
crash!(
1,
"Cannot stat {}: {}",
paths[0].quote(),
Error::last_os_error()
);
}
buf.st_mode & S_IFMT

View file

@ -5,6 +5,7 @@
//! Common functions to manage permissions
use crate::display::Quotable;
use crate::error::strip_errno;
use crate::error::UResult;
use crate::error::USimpleError;
@ -80,29 +81,29 @@ pub fn wrap_chown<P: AsRef<Path>>(
VerbosityLevel::Silent => (),
level => {
out = format!(
"changing {} of '{}': {}",
"changing {} of {}: {}",
if verbosity.groups_only {
"group"
} else {
"ownership"
},
path.display(),
path.quote(),
e
);
if level == VerbosityLevel::Verbose {
out = if verbosity.groups_only {
format!(
"{}\nfailed to change group of '{}' from {} to {}",
"{}\nfailed to change group of {} from {} to {}",
out,
path.display(),
path.quote(),
entries::gid2grp(meta.gid()).unwrap(),
entries::gid2grp(dest_gid).unwrap()
)
} else {
format!(
"{}\nfailed to change ownership of '{}' from {}:{} to {}:{}",
"{}\nfailed to change ownership of {} from {}:{} to {}:{}",
out,
path.display(),
path.quote(),
entries::uid2usr(meta.uid()).unwrap(),
entries::gid2grp(meta.gid()).unwrap(),
entries::uid2usr(dest_uid).unwrap(),
@ -120,15 +121,15 @@ pub fn wrap_chown<P: AsRef<Path>>(
VerbosityLevel::Changes | VerbosityLevel::Verbose => {
out = if verbosity.groups_only {
format!(
"changed group of '{}' from {} to {}",
path.display(),
"changed group of {} from {} to {}",
path.quote(),
entries::gid2grp(meta.gid()).unwrap(),
entries::gid2grp(dest_gid).unwrap()
)
} else {
format!(
"changed ownership of '{}' from {}:{} to {}:{}",
path.display(),
"changed ownership of {} from {}:{} to {}:{}",
path.quote(),
entries::uid2usr(meta.uid()).unwrap(),
entries::gid2grp(meta.gid()).unwrap(),
entries::uid2usr(dest_uid).unwrap(),
@ -141,14 +142,14 @@ pub fn wrap_chown<P: AsRef<Path>>(
} else if verbosity.level == VerbosityLevel::Verbose {
out = if verbosity.groups_only {
format!(
"group of '{}' retained as {}",
path.display(),
"group of {} retained as {}",
path.quote(),
entries::gid2grp(dest_gid).unwrap_or_default()
)
} else {
format!(
"ownership of '{}' retained as {}:{}",
path.display(),
"ownership of {} retained as {}:{}",
path.quote(),
entries::uid2usr(dest_uid).unwrap(),
entries::gid2grp(dest_gid).unwrap()
)
@ -358,9 +359,9 @@ impl ChownExecutor {
match self.verbosity.level {
VerbosityLevel::Silent => (),
_ => show_error!(
"cannot {} '{}': {}",
"cannot {} {}: {}",
if follow { "dereference" } else { "access" },
path.display(),
path.quote(),
strip_errno(&e)
),
}

View file

@ -72,6 +72,8 @@ use std::sync::atomic::Ordering;
use once_cell::sync::Lazy;
use crate::display::Quotable;
pub fn get_utility_is_second_arg() -> bool {
crate::macros::UTILITY_IS_SECOND_ARG.load(Ordering::SeqCst)
}
@ -171,14 +173,15 @@ pub trait Args: Iterator<Item = OsString> + Sized {
Ok(string) => Ok(string),
Err(s_ret) => {
full_conversion = false;
let lossy_conversion = s_ret.to_string_lossy();
eprintln!(
"Input with broken encoding occurred! (s = '{}') ",
&lossy_conversion
"Input with broken encoding occurred! (s = {}) ",
s_ret.quote()
);
match handling {
InvalidEncodingHandling::Ignore => Err(String::new()),
InvalidEncodingHandling::ConvertLossy => Err(lossy_conversion.to_string()),
InvalidEncodingHandling::ConvertLossy => {
Err(s_ret.to_string_lossy().into_owned())
}
InvalidEncodingHandling::Panic => {
panic!("Broken encoding found but caller cannot handle it")
}

View file

@ -78,7 +78,10 @@
// spell-checker:ignore backupopt
use crate::error::{UError, UResult};
use crate::{
display::Quotable,
error::{UError, UResult},
};
use clap::ArgMatches;
use std::{
env,
@ -167,18 +170,22 @@ impl Display for BackupError {
match self {
BE::InvalidArgument(arg, origin) => write!(
f,
"invalid argument '{}' for '{}'\n{}",
arg, origin, VALID_ARGS_HELP
"invalid argument {} for '{}'\n{}",
arg.quote(),
origin,
VALID_ARGS_HELP
),
BE::AmbiguousArgument(arg, origin) => write!(
f,
"ambiguous argument '{}' for '{}'\n{}",
arg, origin, VALID_ARGS_HELP
"ambiguous argument {} for '{}'\n{}",
arg.quote(),
origin,
VALID_ARGS_HELP
),
BE::BackupImpossible() => write!(f, "cannot create backup"),
// Placeholder for later
// BE::BackupFailed(from, to, e) => Display::fmt(
// &uio_error!(e, "failed to backup '{}' to '{}'", from.display(), to.display()),
// &uio_error!(e, "failed to backup {} to {}", from.quote(), to.quote()),
// f
// ),
}

View file

@ -87,13 +87,16 @@ macro_rules! impl_as_ref {
};
}
impl_as_ref!(str);
impl_as_ref!(&'_ str);
impl_as_ref!(String);
impl_as_ref!(std::path::Path);
impl_as_ref!(&'_ std::path::Path);
impl_as_ref!(std::path::PathBuf);
impl_as_ref!(std::path::Component<'_>);
impl_as_ref!(std::path::Components<'_>);
impl_as_ref!(std::path::Iter<'_>);
impl_as_ref!(std::ffi::OsStr);
impl_as_ref!(&'_ std::ffi::OsStr);
impl_as_ref!(std::ffi::OsString);
@ -106,6 +109,13 @@ impl Quotable for Cow<'_, str> {
}
}
impl Quotable for Cow<'_, std::path::Path> {
fn quote(&self) -> Quoted<'_> {
let text: &std::path::Path = self.as_ref();
Quoted::new(text.as_ref())
}
}
/// A wrapper around [`OsStr`] for printing paths with quoting and escaping applied.
#[derive(Debug, Copy, Clone)]
pub struct Quoted<'a> {
@ -407,6 +417,19 @@ pub fn println_verbatim<S: AsRef<OsStr>>(text: S) -> io::Result<()> {
Ok(())
}
/// Like `println_verbatim`, without the trailing newline.
pub fn print_verbatim<S: AsRef<OsStr>>(text: S) -> io::Result<()> {
let mut stdout = io::stdout();
#[cfg(any(unix, target_os = "wasi"))]
{
stdout.write_all(text.as_ref().as_bytes())
}
#[cfg(not(any(unix, target_os = "wasi")))]
{
write!(stdout, "{}", std::path::Path::new(text.as_ref()).display())
}
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -99,7 +99,10 @@ pub type UResult<T> = Result<T, Box<dyn UError>>;
/// An example of a custom error from `ls`:
///
/// ```
/// use uucore::error::{UError, UResult};
/// use uucore::{
/// display::Quotable,
/// error::{UError, UResult}
/// };
/// use std::{
/// error::Error,
/// fmt::{Display, Debug},
@ -126,8 +129,8 @@ pub type UResult<T> = Result<T, Box<dyn UError>>;
/// impl Display for LsError {
/// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
/// match self {
/// LsError::InvalidLineWidth(s) => write!(f, "invalid line width: '{}'", s),
/// LsError::NoMetadata(p) => write!(f, "could not open file: '{}'", p.display()),
/// LsError::InvalidLineWidth(s) => write!(f, "invalid line width: {}", s.quote()),
/// LsError::NoMetadata(p) => write!(f, "could not open file: {}", p.quote()),
/// }
/// }
/// }
@ -158,7 +161,10 @@ pub trait UError: Error + Send {
/// # Example
///
/// ```
/// use uucore::error::{UError};
/// use uucore::{
/// display::Quotable,
/// error::UError
/// };
/// use std::{
/// error::Error,
/// fmt::{Display, Debug},
@ -189,8 +195,8 @@ pub trait UError: Error + Send {
/// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
/// use MyError as ME;
/// match self {
/// ME::Foo(s) => write!(f, "Unknown Foo: '{}'", s),
/// ME::Bar(p) => write!(f, "Couldn't find Bar: '{}'", p.display()),
/// ME::Foo(s) => write!(f, "Unknown Foo: {}", s.quote()),
/// ME::Bar(p) => write!(f, "Couldn't find Bar: {}", p.quote()),
/// ME::Bing() => write!(f, "Exterminate!"),
/// }
/// }
@ -209,7 +215,10 @@ pub trait UError: Error + Send {
/// # Example
///
/// ```
/// use uucore::error::{UError};
/// use uucore::{
/// display::Quotable,
/// error::UError
/// };
/// use std::{
/// error::Error,
/// fmt::{Display, Debug},
@ -240,8 +249,8 @@ pub trait UError: Error + Send {
/// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
/// use MyError as ME;
/// match self {
/// ME::Foo(s) => write!(f, "Unknown Foo: '{}'", s),
/// ME::Bar(p) => write!(f, "Couldn't find Bar: '{}'", p.display()),
/// ME::Foo(s) => write!(f, "Unknown Foo: {}", s.quote()),
/// ME::Bar(p) => write!(f, "Couldn't find Bar: {}", p.quote()),
/// ME::Bing() => write!(f, "Exterminate!"),
/// }
/// }
@ -342,7 +351,10 @@ impl UError for UUsageError {
/// There are two ways to construct this type: with [`UIoError::new`] or by calling the
/// [`FromIo::map_err_context`] method on a [`std::io::Result`] or [`std::io::Error`].
/// ```
/// use uucore::error::{FromIo, UResult, UIoError, UError};
/// use uucore::{
/// display::Quotable,
/// error::{FromIo, UResult, UIoError, UError}
/// };
/// use std::fs::File;
/// use std::path::Path;
/// let path = Path::new("test.txt");
@ -350,12 +362,12 @@ impl UError for UUsageError {
/// // Manual construction
/// let e: Box<dyn UError> = UIoError::new(
/// std::io::ErrorKind::NotFound,
/// format!("cannot access '{}'", path.display())
/// format!("cannot access {}", path.quote())
/// );
/// let res: UResult<()> = Err(e.into());
///
/// // Converting from an `std::io::Error`.
/// let res: UResult<File> = File::open(path).map_err_context(|| format!("cannot access '{}'", path.display()));
/// let res: UResult<File> = File::open(path).map_err_context(|| format!("cannot access {}", path.quote()));
/// ```
#[derive(Debug)]
pub struct UIoError {

View file

@ -9,6 +9,8 @@
use std::str::FromStr;
use crate::display::Quotable;
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct Range {
pub low: usize,
@ -86,7 +88,7 @@ impl Range {
for item in list.split(',') {
let range_item = FromStr::from_str(item)
.map_err(|e| format!("range '{}' was invalid: {}", item, e))?;
.map_err(|e| format!("range {} was invalid: {}", item.quote(), e))?;
ranges.push(range_item);
}

View file

@ -9,6 +9,8 @@ use std::convert::TryFrom;
use std::error::Error;
use std::fmt;
use crate::display::Quotable;
/// Parse a size string into a number of bytes.
///
/// A size string comprises an integer and an optional unit. The unit
@ -107,6 +109,9 @@ impl fmt::Display for ParseSizeError {
}
}
// FIXME: It's more idiomatic to move the formatting into the Display impl,
// but there's a lot of downstream code that constructs these errors manually
// that would be affected
impl ParseSizeError {
fn parse_failure(s: &str) -> ParseSizeError {
// stderr on linux (GNU coreutils 8.32) (LC_ALL=C)
@ -140,7 +145,7 @@ impl ParseSizeError {
// --width
// --strings
// etc.
ParseSizeError::ParseFailure(format!("'{}'", s))
ParseSizeError::ParseFailure(format!("{}", s.quote()))
}
fn size_too_big(s: &str) -> ParseSizeError {
@ -160,7 +165,10 @@ impl ParseSizeError {
// stderr on macos (brew - GNU coreutils 8.32) also differs for the same version, e.g.:
// ghead: invalid number of bytes: '1Y': Value too large to be stored in data type
// gtail: invalid number of bytes: '1Y': Value too large to be stored in data type
ParseSizeError::SizeTooBig(format!("'{}': Value too large for defined data type", s))
ParseSizeError::SizeTooBig(format!(
"{}: Value too large for defined data type",
s.quote()
))
}
}
@ -262,7 +270,7 @@ mod tests {
for &test_string in &test_strings {
assert_eq!(
parse_size(test_string).unwrap_err(),
ParseSizeError::ParseFailure(format!("'{}'", test_string))
ParseSizeError::ParseFailure(format!("{}", test_string.quote()))
);
}
}

View file

@ -9,6 +9,8 @@
use std::time::Duration;
use crate::display::Quotable;
pub fn from_str(string: &str) -> Result<Duration, String> {
let len = string.len();
if len == 0 {
@ -25,13 +27,13 @@ pub fn from_str(string: &str) -> Result<Duration, String> {
if string == "inf" || string == "infinity" {
("inf", 1)
} else {
return Err(format!("invalid time interval '{}'", string));
return Err(format!("invalid time interval {}", string.quote()));
}
}
};
let num = numstr
.parse::<f64>()
.map_err(|e| format!("invalid time interval '{}': {}", string, e))?;
.map_err(|e| format!("invalid time interval {}: {}", string.quote(), e))?;
const NANOS_PER_SEC: u32 = 1_000_000_000;
let whole_secs = num.trunc();

View file

@ -23,7 +23,7 @@ fn test_enter_chroot_fails() {
assert!(result
.stderr_str()
.starts_with("chroot: cannot chroot to jail: Operation not permitted (os error 1)"));
.starts_with("chroot: cannot chroot to 'jail': Operation not permitted (os error 1)"));
}
#[test]
@ -34,7 +34,7 @@ fn test_no_such_directory() {
ucmd.arg("a")
.fails()
.stderr_is("chroot: cannot change root directory to `a`: no such directory");
.stderr_is("chroot: cannot change root directory to 'a': no such directory");
}
#[test]

View file

@ -68,7 +68,7 @@ fn test_invalid_file() {
.arg(folder_name)
.fails()
.no_stdout()
.stderr_contains("cksum: 'asdf' No such file or directory");
.stderr_contains("cksum: asdf: No such file or directory");
// Then check when the file is of an invalid type
at.mkdir(folder_name);
@ -76,7 +76,7 @@ fn test_invalid_file() {
.arg(folder_name)
.fails()
.no_stdout()
.stderr_contains("cksum: 'asdf' Is a directory");
.stderr_contains("cksum: asdf: Is a directory");
}
// Make sure crc is correct for files larger than 32 bytes

View file

@ -531,7 +531,7 @@ fn test_keys_invalid_field() {
new_ucmd!()
.args(&["-k", "1."])
.fails()
.stderr_only("sort: failed to parse key `1.`: failed to parse character index ``: cannot parse integer from empty string");
.stderr_only("sort: failed to parse key '1.': failed to parse character index ``: cannot parse integer from empty string");
}
#[test]
@ -539,7 +539,7 @@ fn test_keys_invalid_field_option() {
new_ucmd!()
.args(&["-k", "1.1x"])
.fails()
.stderr_only("sort: failed to parse key `1.1x`: invalid option: `x`");
.stderr_only("sort: failed to parse key '1.1x': invalid option: `x`");
}
#[test]
@ -547,7 +547,7 @@ fn test_keys_invalid_field_zero() {
new_ucmd!()
.args(&["-k", "0.1"])
.fails()
.stderr_only("sort: failed to parse key `0.1`: field index can not be 0");
.stderr_only("sort: failed to parse key '0.1': field index can not be 0");
}
#[test]
@ -555,7 +555,7 @@ fn test_keys_invalid_char_zero() {
new_ucmd!()
.args(&["-k", "1.0"])
.fails()
.stderr_only("sort: failed to parse key `1.0`: invalid character index 0 for the start position of a field");
.stderr_only("sort: failed to parse key '1.0': invalid character index 0 for the start position of a field");
}
#[test]

View file

@ -59,7 +59,7 @@ fn test_invalid_file() {
at.mkdir("a");
ucmd.arg("a").fails().stderr_is("sum: 'a' Is a directory");
ucmd.arg("a").fails().stderr_is("sum: a: Is a directory");
}
#[test]
@ -68,5 +68,5 @@ fn test_invalid_metadata() {
ucmd.arg("b")
.fails()
.stderr_is("sum: 'b' No such file or directory");
.stderr_is("sum: b: No such file or directory");
}

View file

@ -320,7 +320,7 @@ fn test_invalid_utf8_integer_compare() {
cmd.run()
.status_code(2)
.stderr_is("test: invalid integer 'fo<66>o'");
.stderr_is("test: invalid integer $'fo\\x80o'");
let mut cmd = new_ucmd!();
cmd.raw.arg(arg);
@ -328,7 +328,7 @@ fn test_invalid_utf8_integer_compare() {
cmd.run()
.status_code(2)
.stderr_is("test: invalid integer 'fo<66>o'");
.stderr_is("test: invalid integer $'fo\\x80o'");
}
#[test]