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

chmod: use UResult

This commit is contained in:
Thomas Queiroz 2021-11-12 18:29:08 -03:00
parent ca1156458e
commit 670ed6324b
No known key found for this signature in database
GPG key ID: 229D2DDF7ECA5F8F

View file

@ -7,19 +7,17 @@
// spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's // spell-checker:ignore (ToDO) Chmoder cmode fmode fperm fref ugoa RFILE RFILE's
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg}; use clap::{crate_version, App, Arg};
use std::fs; use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt}; use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path; use std::path::Path;
use uucore::display::Quotable; use uucore::display::Quotable;
use uucore::error::{ExitCode, UResult, USimpleError, UUsageError};
use uucore::fs::display_permissions_unix; use uucore::fs::display_permissions_unix;
use uucore::libc::mode_t; use uucore::libc::mode_t;
#[cfg(not(windows))] #[cfg(not(windows))]
use uucore::mode; use uucore::mode;
use uucore::InvalidEncodingHandling; use uucore::{show_error, InvalidEncodingHandling};
use walkdir::WalkDir; use walkdir::WalkDir;
static ABOUT: &str = "Change the mode of each FILE to MODE. static ABOUT: &str = "Change the mode of each FILE to MODE.
@ -50,7 +48,8 @@ fn get_long_usage() -> String {
String::from("Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.") String::from("Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.")
} }
pub fn uumain(args: impl uucore::Args) -> i32 { #[uucore_procs::gen_uumain]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let mut args = args let mut args = args
.collect_str(InvalidEncodingHandling::ConvertLossy) .collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any(); .accept_any();
@ -72,12 +71,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let verbose = matches.is_present(options::VERBOSE); let verbose = matches.is_present(options::VERBOSE);
let preserve_root = matches.is_present(options::PRESERVE_ROOT); let preserve_root = matches.is_present(options::PRESERVE_ROOT);
let recursive = matches.is_present(options::RECURSIVE); let recursive = matches.is_present(options::RECURSIVE);
let fmode = matches let fmode = match matches.value_of(options::REFERENCE) {
.value_of(options::REFERENCE) Some(fref) => match fs::metadata(fref) {
.and_then(|fref| match fs::metadata(fref) {
Ok(meta) => Some(meta.mode()), Ok(meta) => Some(meta.mode()),
Err(err) => crash!(1, "cannot stat attributes of {}: {}", fref.quote(), err), Err(err) => {
}); return Err(USimpleError::new(
1,
format!("cannot stat attributes of {}: {}", fref.quote(), err),
))
}
},
None => None,
};
let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required
let cmode = if mode_had_minus_prefix { let cmode = if mode_had_minus_prefix {
// clap parsing is finished, now put prefix back // clap parsing is finished, now put prefix back
@ -100,7 +105,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}; };
if files.is_empty() { if files.is_empty() {
crash!(1, "missing operand"); return Err(UUsageError::new(1, "missing operand".to_string()));
} }
let chmoder = Chmoder { let chmoder = Chmoder {
@ -112,12 +117,8 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
fmode, fmode,
cmode, cmode,
}; };
match chmoder.chmod(files) {
Ok(()) => {}
Err(e) => return e,
}
0 chmoder.chmod(files)
} }
pub fn uu_app() -> App<'static, 'static> { pub fn uu_app() -> App<'static, 'static> {
@ -191,7 +192,7 @@ struct Chmoder {
} }
impl Chmoder { impl Chmoder {
fn chmod(&self, files: Vec<String>) -> Result<(), i32> { fn chmod(&self, files: Vec<String>) -> UResult<()> {
let mut r = Ok(()); let mut r = Ok(());
for filename in &files { for filename in &files {
@ -204,22 +205,30 @@ impl Chmoder {
filename.quote() filename.quote()
); );
if !self.quiet { if !self.quiet {
show_error!("cannot operate on dangling symlink {}", filename.quote()); return Err(USimpleError::new(
1,
format!("cannot operate on dangling symlink {}", filename.quote()),
));
} }
} else if !self.quiet { } else if !self.quiet {
show_error!( return Err(USimpleError::new(
"cannot access {}: No such file or directory", 1,
filename.quote() format!(
); "cannot access {}: No such file or directory",
filename.quote()
),
));
} }
return Err(1); return Err(ExitCode::new(1));
} }
if self.recursive && self.preserve_root && filename == "/" { if self.recursive && self.preserve_root && filename == "/" {
show_error!( return Err(USimpleError::new(
"it is dangerous to operate recursively on {}\nuse --no-preserve-root to override this failsafe", 1,
filename.quote() format!(
); "it is dangerous to operate recursively on {}\nuse --no-preserve-root to override this failsafe",
return Err(1); filename.quote()
)
));
} }
if !self.recursive { if !self.recursive {
r = self.chmod_file(file).and(r); r = self.chmod_file(file).and(r);
@ -234,14 +243,14 @@ impl Chmoder {
} }
#[cfg(windows)] #[cfg(windows)]
fn chmod_file(&self, file: &Path) -> Result<(), i32> { fn chmod_file(&self, file: &Path) -> UResult<()> {
// chmod is useless on Windows // chmod is useless on Windows
// it doesn't set any permissions at all // it doesn't set any permissions at all
// instead it just sets the readonly attribute on the file // instead it just sets the readonly attribute on the file
Err(0) Ok(())
} }
#[cfg(unix)] #[cfg(unix)]
fn chmod_file(&self, file: &Path) -> Result<(), i32> { fn chmod_file(&self, file: &Path) -> UResult<()> {
use uucore::mode::get_umask; use uucore::mode::get_umask;
let fperm = match fs::metadata(file) { let fperm = match fs::metadata(file) {
@ -258,11 +267,13 @@ impl Chmoder {
} else if err.kind() == std::io::ErrorKind::PermissionDenied { } else if err.kind() == std::io::ErrorKind::PermissionDenied {
// These two filenames would normally be conditionally // These two filenames would normally be conditionally
// quoted, but GNU's tests expect them to always be quoted // quoted, but GNU's tests expect them to always be quoted
show_error!("{}: Permission denied", file.quote()); return Err(USimpleError::new(
1,
format!("{}: Permission denied", file.quote()),
));
} else { } else {
show_error!("{}: {}", file.quote(), err); return Err(USimpleError::new(1, format!("{}: {}", file.quote(), err)));
} }
return Err(1);
} }
}; };
match self.fmode { match self.fmode {
@ -296,22 +307,25 @@ impl Chmoder {
} }
Err(f) => { Err(f) => {
if !self.quiet { if !self.quiet {
show_error!("{}", f); return Err(USimpleError::new(1, f));
} else {
return Err(ExitCode::new(1));
} }
return Err(1);
} }
} }
} }
self.change_file(fperm, new_mode, file)?; self.change_file(fperm, new_mode, file)?;
// if a permission would have been removed if umask was 0, but it wasn't because umask was not 0, print an error and fail // if a permission would have been removed if umask was 0, but it wasn't because umask was not 0, print an error and fail
if (new_mode & !naively_expected_new_mode) != 0 { if (new_mode & !naively_expected_new_mode) != 0 {
show_error!( return Err(USimpleError::new(
"{}: new permissions are {}, not {}", 1,
file.maybe_quote(), format!(
display_permissions_unix(new_mode as mode_t, false), "{}: new permissions are {}, not {}",
display_permissions_unix(naively_expected_new_mode as mode_t, false) file.maybe_quote(),
); display_permissions_unix(new_mode as mode_t, false),
return Err(1); display_permissions_unix(naively_expected_new_mode as mode_t, false)
),
));
} }
} }
} }