1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 20:47:46 +00:00

Merge pull request #792 from Arcterus/master

chmod: implement --verbose, --changes, and --quiet
This commit is contained in:
Heather 2016-01-06 10:51:13 +04:00
commit 5270761907
2 changed files with 44 additions and 31 deletions

View file

@ -150,7 +150,6 @@ To do
- chcon - chcon
- chgrp - chgrp
- chmod (mostly done, just needs verbosity options)
- chown - chown
- copy - copy
- cp (not much done) - cp (not much done)

View file

@ -9,8 +9,6 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
#![allow(unused_variables)] // only necessary while the TODOs still exist
extern crate aho_corasick; extern crate aho_corasick;
extern crate getopts; extern crate getopts;
extern crate libc; extern crate libc;
@ -125,7 +123,7 @@ fn chmod(files: Vec<String>, changes: bool, quiet: bool, verbose: bool, preserve
Some(s) => Some(s.to_string()), Some(s) => Some(s.to_string()),
None => None, None => None,
}, },
Err(e) => None, Err(_) => None,
}).collect(), }).collect(),
changes, quiet, verbose, preserve_root, recursive, fmode, cmode).and(r); changes, quiet, verbose, preserve_root, recursive, fmode, cmode).and(r);
r = chmod_file(&file, filename, changes, quiet, verbose, fmode, cmode).and(r); r = chmod_file(&file, filename, changes, quiet, verbose, fmode, cmode).and(r);
@ -157,25 +155,20 @@ fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool
#[cfg(unix)] #[cfg(unix)]
fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool, fmode: Option<libc::mode_t>, cmode: Option<&String>) -> Result<(), i32> { fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool, fmode: Option<libc::mode_t>, cmode: Option<&String>) -> Result<(), i32> {
let path = CString::new(name).unwrap_or_else(|e| panic!("{}", e)); let path = CString::new(name).unwrap_or_else(|e| panic!("{}", e));
match fmode { let mut stat: libc::stat = unsafe { mem::uninitialized() };
Some(mode) => { let statres = unsafe { libc::stat(path.as_ptr(), &mut stat as *mut libc::stat) };
if unsafe { libc::chmod(path.as_ptr(), mode) } == 0 { let mut fperm =
// TODO: handle changes, quiet, and verbose if statres == 0 {
} else { stat.st_mode & 0o7777
} else {
if !quiet {
show_error!("{}", io::Error::last_os_error()); show_error!("{}", io::Error::last_os_error());
return Err(1);
} }
} return Err(1);
};
match fmode {
Some(mode) => try!(change_file(fperm, mode, file, &path, verbose, changes, quiet)),
None => { None => {
let mut stat: libc::stat = unsafe { mem::uninitialized() };
let statres = unsafe { libc::stat(path.as_ptr(), &mut stat as *mut libc::stat) };
let mut fperm =
if statres == 0 {
stat.st_mode
} else {
show_error!("{}", io::Error::last_os_error());
return Err(1);
};
for mode in cmode.unwrap().split(',') { // cmode is guaranteed to be Some in this case for mode in cmode.unwrap().split(',') { // cmode is guaranteed to be Some in this case
let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
let result = let result =
@ -185,17 +178,16 @@ fn chmod_file(file: &Path, name: &str, changes: bool, quiet: bool, verbose: bool
parse_symbolic(fperm, mode, file) parse_symbolic(fperm, mode, file)
}; };
match result { match result {
Ok(m) => fperm = m, Ok(mode) => {
Err(f) => { try!(change_file(fperm, mode, file, &path, verbose, changes, quiet));
show_error!("{}", f); fperm = mode;
return Err(1) }
Err(f) => {
if !quiet {
show_error!("{}", f);
}
return Err(1);
} }
};
if unsafe { libc::chmod(path.as_ptr(), fperm) } == 0 {
// TODO: see above
} else {
show_error!("{}", io::Error::last_os_error());
return Err(1);
} }
} }
} }
@ -280,7 +272,7 @@ fn parse_op(mode: &str, default: Option<char>) -> Result<(char, usize), String>
fn parse_change(mode: &str, fperm: libc::mode_t, file: &Path) -> (libc::mode_t, usize) { fn parse_change(mode: &str, fperm: libc::mode_t, file: &Path) -> (libc::mode_t, usize) {
let mut srwx = fperm & 0o7000; let mut srwx = fperm & 0o7000;
let mut pos = 0; let mut pos = 0;
for (i, ch) in mode.chars().enumerate() { for ch in mode.chars() {
match ch { match ch {
'r' => srwx |= 0o444, 'r' => srwx |= 0o444,
'w' => srwx |= 0o222, 'w' => srwx |= 0o222,
@ -304,3 +296,25 @@ fn parse_change(mode: &str, fperm: libc::mode_t, file: &Path) -> (libc::mode_t,
} }
(srwx, pos) (srwx, pos)
} }
fn change_file(fperm: libc::mode_t, mode: libc::mode_t, file: &Path, path: &CString, verbose: bool, changes: bool, quiet: bool) -> Result<(), i32> {
if fperm == mode {
if verbose && !changes {
show_info!("mode of \"{}\" retained as {:o}", file.display(), fperm);
}
Ok(())
} else if unsafe { libc::chmod(path.as_ptr(), mode) } == 0 {
if verbose || changes {
show_info!("mode of \"{}\" changed from {:o} to {:o}", file.display(), fperm, mode);
}
Ok(())
} else {
if !quiet {
show_error!("{}", io::Error::last_os_error());
}
if verbose {
show_info!("failed to change mode of file \"{}\" from {:o} to {:o}", file.display(), fperm, mode);
}
return Err(1);
}
}