diff --git a/src/uu/chown/src/chown.rs b/src/uu/chown/src/chown.rs index 20f3f8174..4abb9ac61 100644 --- a/src/uu/chown/src/chown.rs +++ b/src/uu/chown/src/chown.rs @@ -160,6 +160,7 @@ pub fn uu_app() -> App<'static, 'static> { .arg( Arg::with_name(options::verbosity::VERBOSE) .long(options::verbosity::VERBOSE) + .short("v") .help("output a diagnostic for every file processed"), ) } diff --git a/src/uucore/src/lib/features/perms.rs b/src/uucore/src/lib/features/perms.rs index 5f470d5a8..b605c0cdf 100644 --- a/src/uucore/src/lib/features/perms.rs +++ b/src/uucore/src/lib/features/perms.rs @@ -165,22 +165,26 @@ pub enum IfFrom { UserGroup(u32, u32), } +#[derive(PartialEq, Eq)] +pub enum TraverseSymlinks { + None, + First, + All, +} + pub struct ChownExecutor { pub dest_uid: Option, pub dest_gid: Option, - pub bit_flag: u8, + pub traverse_symlinks: TraverseSymlinks, pub verbosity: Verbosity, pub filter: IfFrom, pub files: Vec, pub recursive: bool, pub preserve_root: bool, + // Must be true if traverse_symlinks is not None pub dereference: bool, } -pub const FTS_COMFOLLOW: u8 = 1; -pub const FTS_PHYSICAL: u8 = 1 << 1; -pub const FTS_LOGICAL: u8 = 1 << 2; - impl ChownExecutor { pub fn exec(&self) -> UResult<()> { let mut ret = 0; @@ -194,9 +198,8 @@ impl ChownExecutor { } fn traverse>(&self, root: P) -> i32 { - let follow_arg = self.dereference || self.bit_flag != FTS_PHYSICAL; let path = root.as_ref(); - let meta = match self.obtain_meta(path, follow_arg) { + let meta = match self.obtain_meta(path, self.dereference) { Some(m) => m, _ => return 1, }; @@ -208,7 +211,7 @@ impl ChownExecutor { // (argument is symlink && should follow argument && resolved to be '/') // ) if self.recursive && self.preserve_root { - let may_exist = if follow_arg { + let may_exist = if self.dereference { path.canonicalize().ok() } else { let real = resolve_relative_path(path); @@ -234,7 +237,7 @@ impl ChownExecutor { &meta, self.dest_uid, self.dest_gid, - follow_arg, + self.dereference, self.verbosity.clone(), ) { Ok(n) => { @@ -264,9 +267,8 @@ impl ChownExecutor { fn dive_into>(&self, root: P) -> i32 { let mut ret = 0; let root = root.as_ref(); - let follow = self.dereference || self.bit_flag & FTS_LOGICAL != 0; let mut iterator = WalkDir::new(root) - .follow_links(follow) + .follow_links(self.dereference) .min_depth(1) .into_iter(); // We can't use a for loop because we need to manipulate the iterator inside the loop. @@ -292,7 +294,7 @@ impl ChownExecutor { Ok(entry) => entry, }; let path = entry.path(); - let meta = match self.obtain_meta(path, follow) { + let meta = match self.obtain_meta(path, self.dereference) { Some(m) => m, _ => { ret = 1; @@ -314,7 +316,7 @@ impl ChownExecutor { &meta, self.dest_uid, self.dest_gid, - follow, + self.dereference, self.verbosity.clone(), ) { Ok(n) => { @@ -452,31 +454,31 @@ pub fn chown_base<'a>( let preserve_root = matches.is_present(options::preserve_root::PRESERVE); let mut dereference = if matches.is_present(options::dereference::DEREFERENCE) { - 1 + Some(true) } else if matches.is_present(options::dereference::NO_DEREFERENCE) { - 0 + Some(false) } else { - -1 + None }; - let mut bit_flag = if matches.is_present(options::traverse::TRAVERSE) { - FTS_COMFOLLOW | FTS_PHYSICAL + let mut traverse_symlinks = if matches.is_present(options::traverse::TRAVERSE) { + TraverseSymlinks::First } else if matches.is_present(options::traverse::EVERY) { - FTS_LOGICAL + TraverseSymlinks::All } else { - FTS_PHYSICAL + TraverseSymlinks::None }; let recursive = matches.is_present(options::RECURSIVE); if recursive { - if bit_flag == FTS_PHYSICAL { - if dereference == 1 { + if traverse_symlinks == TraverseSymlinks::None { + if dereference == Some(true) { return Err(USimpleError::new(1, "-R --dereference requires -H or -L")); } - dereference = 0; + dereference = Some(false); } } else { - bit_flag = FTS_PHYSICAL; + traverse_symlinks = TraverseSymlinks::None; } let verbosity_level = if matches.is_present(options::verbosity::CHANGES) { @@ -493,15 +495,15 @@ pub fn chown_base<'a>( let (dest_gid, dest_uid, filter) = parse_gid_uid_and_filter(&matches)?; let executor = ChownExecutor { - bit_flag, + traverse_symlinks, dest_gid, dest_uid, verbosity: Verbosity { - groups_only: true, + groups_only, level: verbosity_level, }, recursive, - dereference: dereference != 0, + dereference: dereference.unwrap_or(true), preserve_root, files, filter,