mirror of
https://github.com/uutils/coreutils
synced 2024-11-15 17:28:03 +00:00
chmod: fix reference option
Reference option must have a file path. Fix C interface using CString. Better error message if the file doesn't exist.
This commit is contained in:
parent
8d278913c2
commit
5dc0a55630
2 changed files with 18 additions and 4 deletions
|
@ -36,7 +36,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
opts.optflag("v", "verbose", "output a diagnostic for every file processed (unimplemented)");
|
||||
opts.optflag("", "no-preserve-root", "do not treat '/' specially (the default)");
|
||||
opts.optflag("", "preserve-root", "fail to operate recursively on '/'");
|
||||
opts.optflagopt("", "reference", "use RFILE's mode instead of MODE values", "RFILE");
|
||||
opts.optopt("", "reference", "use RFILE's mode instead of MODE values", "RFILE");
|
||||
opts.optflag("R", "recursive", "change files and directories recursively");
|
||||
opts.optflag("h", "help", "display this help and exit");
|
||||
opts.optflag("V", "version", "output version information and exit");
|
||||
|
@ -62,7 +62,7 @@ Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.",
|
|||
return 0;
|
||||
} else if matches.opt_present("version") {
|
||||
println!("{} {}", NAME, VERSION);
|
||||
} else if matches.free.is_empty() && matches.opt_present("reference") || matches.free.len() < 2 {
|
||||
} else if matches.free.is_empty() {
|
||||
show_error!("missing an argument");
|
||||
show_error!("for help, try '{} --help'", NAME);
|
||||
return 1;
|
||||
|
@ -73,12 +73,15 @@ Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.",
|
|||
let preserve_root = matches.opt_present("preserve-root");
|
||||
let recursive = matches.opt_present("recursive");
|
||||
let fmode = matches.opt_str("reference").and_then(|fref| {
|
||||
let s = CString::new(fref).unwrap_or_else( |_| {
|
||||
crash!(1, "reference file name contains internal nul byte")
|
||||
});
|
||||
let mut stat : libc::stat = unsafe { mem::uninitialized() };
|
||||
let statres = unsafe { libc::stat(fref.as_ptr() as *const _, &mut stat as *mut libc::stat) };
|
||||
let statres = unsafe { libc::stat(s.as_ptr() as *const _, &mut stat as *mut libc::stat) };
|
||||
if statres == 0 {
|
||||
Some(stat.st_mode)
|
||||
} else {
|
||||
crash!(1, "{}", io::Error::last_os_error())
|
||||
crash!(1, "cannot stat attribues of '{}': {}", matches.opt_str("reference").unwrap(), io::Error::last_os_error())
|
||||
}
|
||||
});
|
||||
let cmode =
|
||||
|
|
|
@ -8,6 +8,8 @@ use common::util::*;
|
|||
|
||||
static UTIL_NAME: &'static str = "chmod";
|
||||
static TEST_FILE: &'static str = "file";
|
||||
static REFERENCE_FILE: &'static str = "reference";
|
||||
static REFERENCE_PERMS: mode_t = 0o247;
|
||||
|
||||
struct TestCase {
|
||||
args: Vec<&'static str>,
|
||||
|
@ -27,6 +29,7 @@ fn run_tests(tests: Vec<TestCase>) {
|
|||
let (at, mut ucmd) = testing(UTIL_NAME);
|
||||
|
||||
mkfile(&at.plus_as_string(TEST_FILE), test.before);
|
||||
mkfile(&at.plus_as_string(REFERENCE_FILE), REFERENCE_PERMS);
|
||||
let perms = at.metadata(TEST_FILE).permissions().mode();
|
||||
if perms != test.before{
|
||||
panic!(format!("{}: expected: {:o} got: {:o}", "setting permissions failed", test.after, perms));
|
||||
|
@ -87,3 +90,11 @@ fn test_chmod_ugo_copy() {
|
|||
};
|
||||
run_tests(tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_chmod_reference_file() {
|
||||
let tests = vec!{
|
||||
TestCase{args: vec!{"--reference", REFERENCE_FILE, TEST_FILE}, before: 0o070, after: 0o247},
|
||||
};
|
||||
run_tests(tests);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue