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:
parent
ca1156458e
commit
670ed6324b
1 changed files with 57 additions and 43 deletions
|
@ -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)
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue