refactor(chgrp): move chgrp perms function into the uucore to reuse it into install

Will move chown later
This commit is contained in:
Sylvestre Ledru 2020-11-15 23:22:52 +01:00
parent 431a4e9f2f
commit 763de90fda
6 changed files with 114 additions and 81 deletions

View file

@ -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"

View file

@ -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<P: AsRef<Path>>(&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<P: AsRef<Path>>(&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<P: AsRef<Path>>(&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
}
}

View file

@ -43,6 +43,7 @@ entries = ["libc"]
fs = ["libc"]
mode = ["libc"]
parse_time = []
perms = ["libc"]
process = ["libc"]
signals = []
utf8 = []

View file

@ -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(

View file

@ -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<P: AsRef<Path>>(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<P: AsRef<Path>>(
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
}

View file

@ -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"))]