diff --git a/src/uu/chgrp/Cargo.toml b/src/uu/chgrp/Cargo.toml index 3a6d6b18d..9f2e8c4a7 100644 --- a/src/uu/chgrp/Cargo.toml +++ b/src/uu/chgrp/Cargo.toml @@ -15,7 +15,7 @@ edition = "2018" path = "src/chgrp.rs" [dependencies] -uucore = { version=">=0.0.4", package="uucore", path="../../uucore", features=["entries", "fs"] } +uucore = { version=">=0.0.4", package="uucore", path="../../uucore", features=["entries", "fs", "perms"] } uucore_procs = { version=">=0.0.4", package="uucore_procs", path="../../uucore_procs" } walkdir = "2.2" diff --git a/src/uu/chgrp/src/chgrp.rs b/src/uu/chgrp/src/chgrp.rs index e60efa0c6..9fc72ab20 100644 --- a/src/uu/chgrp/src/chgrp.rs +++ b/src/uu/chgrp/src/chgrp.rs @@ -11,23 +11,18 @@ extern crate uucore; pub use uucore::entries; use uucore::fs::resolve_relative_path; -use uucore::libc::{self, gid_t, lchown}; +use uucore::libc::gid_t; +use uucore::perms::{wrap_chgrp, Verbosity}; extern crate walkdir; use walkdir::WalkDir; -use std::io::Error as IOError; -use std::io::Result as IOResult; - use std::fs; use std::fs::Metadata; use std::os::unix::fs::MetadataExt; use std::path::Path; -use std::ffi::CString; -use std::os::unix::ffi::OsStrExt; - static SYNTAX: &str = "chgrp [OPTION]... GROUP FILE...\n or : chgrp [OPTION]... --reference=RFILE FILE..."; static SUMMARY: &str = "Change the group of each FILE to GROUP."; @@ -165,14 +160,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 { executor.exec() } -#[derive(PartialEq, Debug)] -enum Verbosity { - Silent, - Changes, - Verbose, - Normal, -} - struct Chgrper { dest_gid: gid_t, bit_flag: u8, @@ -201,23 +188,6 @@ impl Chgrper { ret } - fn chgrp>(&self, path: P, dgid: gid_t, follow: bool) -> IOResult<()> { - let path = path.as_ref(); - let s = CString::new(path.as_os_str().as_bytes()).unwrap(); - let ret = unsafe { - if follow { - libc::chown(s.as_ptr(), (0 as gid_t).wrapping_sub(1), dgid) - } else { - lchown(s.as_ptr(), (0 as gid_t).wrapping_sub(1), dgid) - } - }; - if ret == 0 { - Ok(()) - } else { - Err(IOError::last_os_error()) - } - } - #[cfg(windows)] fn is_bind_root>(&self, root: P) -> bool { // TODO: is there an equivalent on Windows? @@ -269,7 +239,13 @@ impl Chgrper { } } - let ret = self.wrap_chgrp(path, &meta, follow_arg); + let ret = wrap_chgrp( + path, + &meta, + self.dest_gid, + follow_arg, + self.verbosity.clone(), + ); if !self.recursive { ret @@ -297,7 +273,7 @@ impl Chgrper { } }; - ret = self.wrap_chgrp(path, &meta, follow); + ret = wrap_chgrp(path, &meta, self.dest_gid, follow, self.verbosity.clone()); } ret } @@ -324,50 +300,4 @@ impl Chgrper { }; Some(meta) } - - fn wrap_chgrp>(&self, path: P, meta: &Metadata, follow: bool) -> i32 { - use self::Verbosity::*; - let mut ret = 0; - let dest_gid = self.dest_gid; - let path = path.as_ref(); - if let Err(e) = self.chgrp(path, dest_gid, follow) { - match self.verbosity { - Silent => (), - _ => { - show_info!("changing group of '{}': {}", path.display(), e); - if self.verbosity == Verbose { - println!( - "failed to change group of {} from {} to {}", - path.display(), - entries::gid2grp(meta.gid()).unwrap(), - entries::gid2grp(dest_gid).unwrap() - ); - }; - } - } - ret = 1; - } else { - let changed = dest_gid != meta.gid(); - if changed { - match self.verbosity { - Changes | Verbose => { - println!( - "changed group of {} from {} to {}", - path.display(), - entries::gid2grp(meta.gid()).unwrap(), - entries::gid2grp(dest_gid).unwrap() - ); - } - _ => (), - }; - } else if self.verbosity == Verbose { - println!( - "group of {} retained as {}", - path.display(), - entries::gid2grp(dest_gid).unwrap() - ); - } - } - ret - } } diff --git a/src/uucore/Cargo.toml b/src/uucore/Cargo.toml index db3b35004..94b7502d3 100644 --- a/src/uucore/Cargo.toml +++ b/src/uucore/Cargo.toml @@ -43,6 +43,7 @@ entries = ["libc"] fs = ["libc"] mode = ["libc"] parse_time = [] +perms = ["libc"] process = ["libc"] signals = [] utf8 = [] diff --git a/src/uucore/src/lib/features.rs b/src/uucore/src/lib/features.rs index d5927fc6f..c26225cb7 100644 --- a/src/uucore/src/lib/features.rs +++ b/src/uucore/src/lib/features.rs @@ -13,11 +13,15 @@ pub mod zero_copy; // ** non-windows #[cfg(all(not(windows), feature = "mode"))] pub mod mode; + // ** unix-only #[cfg(all(unix, feature = "entries"))] pub mod entries; +#[cfg(all(unix, feature = "perms"))] +pub mod perms; #[cfg(all(unix, feature = "process"))] pub mod process; + #[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))] pub mod signals; #[cfg(all( diff --git a/src/uucore/src/lib/features/perms.rs b/src/uucore/src/lib/features/perms.rs new file mode 100644 index 000000000..9eca7ea0e --- /dev/null +++ b/src/uucore/src/lib/features/perms.rs @@ -0,0 +1,96 @@ +// This file is part of the uutils coreutils package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +pub use crate::features::entries; +use libc::{self, gid_t, lchown}; + +#[macro_use] +pub use crate::*; + +use std::io::Error as IOError; +use std::io::Result as IOResult; + +use std::ffi::CString; +use std::fs::Metadata; +use std::os::unix::fs::MetadataExt; + +use std::os::unix::ffi::OsStrExt; +use std::path::Path; + +#[derive(PartialEq, Clone, Debug)] +pub enum Verbosity { + Silent, + Changes, + Verbose, + Normal, +} + +fn chgrp>(path: P, dgid: gid_t, follow: bool) -> IOResult<()> { + let path = path.as_ref(); + let s = CString::new(path.as_os_str().as_bytes()).unwrap(); + let ret = unsafe { + if follow { + libc::chown(s.as_ptr(), (0 as gid_t).wrapping_sub(1), dgid) + } else { + lchown(s.as_ptr(), (0 as gid_t).wrapping_sub(1), dgid) + } + }; + if ret == 0 { + Ok(()) + } else { + Err(IOError::last_os_error()) + } +} + +pub fn wrap_chgrp>( + path: P, + meta: &Metadata, + dest_gid: gid_t, + follow: bool, + verbosity: Verbosity, +) -> i32 { + use self::Verbosity::*; + let mut ret = 0; + let path = path.as_ref(); + if let Err(e) = chgrp(path, dest_gid, follow) { + match verbosity { + Silent => (), + _ => { + show_info!("changing group of '{}': {}", path.display(), e); + if verbosity == Verbose { + println!( + "failed to change group of {} from {} to {}", + path.display(), + entries::gid2grp(meta.gid()).unwrap(), + entries::gid2grp(dest_gid).unwrap() + ); + }; + } + } + ret = 1; + } else { + let changed = dest_gid != meta.gid(); + if changed { + match verbosity { + Changes | Verbose => { + println!( + "changed group of {} from {} to {}", + path.display(), + entries::gid2grp(meta.gid()).unwrap(), + entries::gid2grp(dest_gid).unwrap() + ); + } + _ => (), + }; + } else if verbosity == Verbose { + println!( + "group of {} retained as {}", + path.display(), + entries::gid2grp(dest_gid).unwrap() + ); + } + } + ret +} diff --git a/src/uucore/src/lib/lib.rs b/src/uucore/src/lib/lib.rs index 005759514..5d08dc9ac 100644 --- a/src/uucore/src/lib/lib.rs +++ b/src/uucore/src/lib/lib.rs @@ -53,6 +53,8 @@ pub use crate::features::mode; // ** unix-only #[cfg(all(unix, feature = "entries"))] pub use crate::features::entries; +#[cfg(all(unix, feature = "perms"))] +pub use crate::features::perms; #[cfg(all(unix, feature = "process"))] pub use crate::features::process; #[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))]