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

Merge pull request #2822 from jfinkels/shred-uresult

shred: return UResult from uumain() function
This commit is contained in:
Sylvestre Ledru 2021-12-30 09:51:51 +01:00 committed by GitHub
commit 9f21cd0d37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -19,6 +19,7 @@ use std::io::prelude::*;
use std::io::SeekFrom; use std::io::SeekFrom;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use uucore::display::Quotable; use uucore::display::Quotable;
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
use uucore::{util_name, InvalidEncodingHandling}; use uucore::{util_name, InvalidEncodingHandling};
#[macro_use] #[macro_use]
@ -266,7 +267,8 @@ pub mod options {
pub const ZERO: &str = "zero"; pub const ZERO: &str = "zero";
} }
pub fn uumain(args: impl uucore::Args) -> i32 { #[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let args = args let args = args
.collect_str(InvalidEncodingHandling::Ignore) .collect_str(InvalidEncodingHandling::Ignore)
.accept_any(); .accept_any();
@ -277,20 +279,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let matches = app.get_matches_from(args); let matches = app.get_matches_from(args);
let mut errs: Vec<String> = vec![];
if !matches.is_present(options::FILE) { if !matches.is_present(options::FILE) {
show_error!("Missing an argument"); return Err(UUsageError::new(1, "missing file operand"));
show_error!("For help, try '{} --help'", uucore::execution_phrase());
return 0;
} }
let iterations = match matches.value_of(options::ITERATIONS) { let iterations = match matches.value_of(options::ITERATIONS) {
Some(s) => match s.parse::<usize>() { Some(s) => match s.parse::<usize>() {
Ok(u) => u, Ok(u) => u,
Err(_) => { Err(_) => {
errs.push(format!("invalid number of passes: {}", s.quote())); return Err(USimpleError::new(
0 1,
format!("invalid number of passes: {}", s.quote()),
))
} }
}, },
None => unreachable!(), None => unreachable!(),
@ -313,21 +313,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let zero = matches.is_present(options::ZERO); let zero = matches.is_present(options::ZERO);
let verbose = matches.is_present(options::VERBOSE); let verbose = matches.is_present(options::VERBOSE);
if !errs.is_empty() {
show_error!("Invalid arguments supplied.");
for message in errs {
show_error!("{}", message);
}
return 1;
}
for path_str in matches.values_of(options::FILE).unwrap() { for path_str in matches.values_of(options::FILE).unwrap() {
wipe_file( show_if_err!(wipe_file(
path_str, iterations, remove, size, exact, zero, verbose, force, path_str, iterations, remove, size, exact, zero, verbose, force,
); ));
} }
Ok(())
0
} }
pub fn uu_app() -> App<'static, 'static> { pub fn uu_app() -> App<'static, 'static> {
@ -452,34 +443,28 @@ fn wipe_file(
zero: bool, zero: bool,
verbose: bool, verbose: bool,
force: bool, force: bool,
) { ) -> UResult<()> {
// Get these potential errors out of the way first // Get these potential errors out of the way first
let path: &Path = Path::new(path_str); let path: &Path = Path::new(path_str);
if !path.exists() { if !path.exists() {
show_error!("{}: No such file or directory", path.maybe_quote()); return Err(USimpleError::new(
return; 1,
format!("{}: No such file or directory", path.maybe_quote()),
));
} }
if !path.is_file() { if !path.is_file() {
show_error!("{}: Not a file", path.maybe_quote()); return Err(USimpleError::new(
return; 1,
format!("{}: Not a file", path.maybe_quote()),
));
} }
// If force is true, set file permissions to not-readonly. // If force is true, set file permissions to not-readonly.
if force { if force {
let metadata = match fs::metadata(path) { let metadata = fs::metadata(path).map_err_context(String::new)?;
Ok(m) => m,
Err(e) => {
show_error!("{}", e);
return;
}
};
let mut perms = metadata.permissions(); let mut perms = metadata.permissions();
perms.set_readonly(false); perms.set_readonly(false);
if let Err(e) = fs::set_permissions(path, perms) { fs::set_permissions(path, perms).map_err_context(String::new)?;
show_error!("{}", e);
return;
}
} }
// Fill up our pass sequence // Fill up our pass sequence
@ -521,13 +506,11 @@ fn wipe_file(
{ {
let total_passes: usize = pass_sequence.len(); let total_passes: usize = pass_sequence.len();
let mut file: File = match OpenOptions::new().write(true).truncate(false).open(path) { let mut file: File = OpenOptions::new()
Ok(f) => f, .write(true)
Err(e) => { .truncate(false)
show_error!("{}: failed to open for writing: {}", path.maybe_quote(), e); .open(path)
return; .map_err_context(|| format!("{}: failed to open for writing", path.maybe_quote()))?;
}
};
// NOTE: it does not really matter what we set for total_bytes and gen_type here, so just // NOTE: it does not really matter what we set for total_bytes and gen_type here, so just
// use bogus values // use bogus values
@ -557,24 +540,17 @@ fn wipe_file(
} }
} }
// size is an optional argument for exactly how many bytes we want to shred // size is an optional argument for exactly how many bytes we want to shred
match do_pass(&mut file, path, &mut generator, *pass_type, size) { show_if_err!(do_pass(&mut file, path, &mut generator, *pass_type, size)
Ok(_) => {} .map_err_context(|| format!("{}: File write pass failed", path.maybe_quote())));
Err(e) => {
show_error!("{}: File write pass failed: {}", path.maybe_quote(), e);
}
}
// Ignore failed writes; just keep trying // Ignore failed writes; just keep trying
} }
} }
if remove { if remove {
match do_remove(path, path_str, verbose) { do_remove(path, path_str, verbose)
Ok(_) => {} .map_err_context(|| format!("{}: failed to remove file", path.maybe_quote()))?;
Err(e) => {
show_error!("{}: failed to remove file: {}", path.maybe_quote(), e);
}
}
} }
Ok(())
} }
fn do_pass<'a>( fn do_pass<'a>(