chown - Removed several clones

This commit is contained in:
Nathan Fisher 2023-01-18 21:45:18 -05:00
parent 3016f4c234
commit 7fc064a441

View File

@ -1,7 +1,13 @@
use super::Cmd;
use crate::{fs::FileType, pw};
use clap::{Arg, ArgAction, ArgGroup, Command, ValueHint};
use std::{error::Error, fs::{File, self}, io, path::PathBuf, os::{unix::prelude::MetadataExt, fd::AsRawFd}};
use std::{
error::Error,
fs::{self, File},
io,
os::{fd::AsRawFd, unix::prelude::MetadataExt},
path::PathBuf,
};
use walkdir::{DirEntry, WalkDir};
#[derive(Debug, Default)]
@ -78,17 +84,17 @@ impl Cmd for Chown {
if matches.get_flag("full-traverse") {
Some(Recurse {
traversal: Traversal::FullLinks,
same_filesystem: matches.get_flag("same-filesystem")
same_filesystem: matches.get_flag("same-filesystem"),
})
} else if matches.get_flag("cli-traverse") {
Some(Recurse {
traversal: Traversal::CliLinks,
same_filesystem: matches.get_flag("same-filesystem")
same_filesystem: matches.get_flag("same-filesystem"),
})
} else {
Some(Recurse {
traversal: Traversal::NoLinks,
same_filesystem: matches.get_flag("same-filesystem")
same_filesystem: matches.get_flag("same-filesystem"),
})
}
} else {
@ -103,12 +109,30 @@ impl Cmd for Chown {
};
let (user, group) = if let Some(who) = matches.get_one::<String>("user") {
if let Some((u, g)) = who.split_once(':') {
let uid = pw::get_uid_for_name(u).ok_or(io::Error::new(io::ErrorKind::Other, "cannot get uid"))?;
let gid = pw::get_gid_for_groupname(g).ok_or(io::Error::new(io::ErrorKind::Other, "cannot get gid"))?;
(User { name: u.to_string(), uid }, Some(Group { name: g.to_string(), gid }))
let uid = pw::get_uid_for_name(u)
.ok_or(io::Error::new(io::ErrorKind::Other, "cannot get uid"))?;
let gid = pw::get_gid_for_groupname(g)
.ok_or(io::Error::new(io::ErrorKind::Other, "cannot get gid"))?;
(
User {
name: u.to_string(),
uid,
},
Some(Group {
name: g.to_string(),
gid,
}),
)
} else {
let uid = pw::get_uid_for_name(who).ok_or(io::Error::new(io::ErrorKind::Other, "cannot get uid"))?;
(User { name: who.to_string(), uid }, None)
let uid = pw::get_uid_for_name(who)
.ok_or(io::Error::new(io::ErrorKind::Other, "cannot get uid"))?;
(
User {
name: who.to_string(),
uid,
},
None,
)
}
} else {
return Err(Box::new(io::Error::new(
@ -201,13 +225,18 @@ impl Action {
let uid = meta.uid();
let gid = meta.gid();
unsafe {
if libc::fchown(fd.as_raw_fd(), self.user.uid, self.group.clone().map(|x| x.gid).unwrap_or(gid)) != 0 {
if libc::fchown(
fd.as_raw_fd(),
self.user.uid,
self.group.as_ref().map(|x| x.gid).unwrap_or(gid),
) != 0
{
return Err(io::Error::last_os_error().into());
}
}
let ft = FileType::from(meta);
match ft {
FileType::File => {},
FileType::File => {}
FileType::Symlink => {
let tgt = fs::read_link(&self.path)?;
if tgt.is_dir() {
@ -217,41 +246,56 @@ impl Action {
}
}
}
},
}
FileType::Dir => {
if let Some(r) = self.recurse {
if r.traversal != Traversal::NoLinks {
self.recurse()?;
}
}
},
}
}
if let Some(feedback) = self.feedback {
match feedback {
Feedback::Full => {
if self.user.uid != uid || self.group.clone().map(|x| x.gid) != Some(gid) {
if self.user.uid != uid || self.group.as_ref().map(|x| x.gid) != Some(gid) {
if let Some(g) = &self.group {
println!("{} changed to {}:{}", &self.path.display(), &self.user.name, &g.name);
println!(
"{} changed to {}:{}",
&self.path.display(),
&self.user.name,
&g.name
);
} else {
println!("{} changed to {}", &self.path.display(), &self.user.name);
}
} else {
if let Some(g) = &self.group {
println!("{} retained as {}:{}", &self.path.display(), &self.user.name, &g.name);
println!(
"{} retained as {}:{}",
&self.path.display(),
&self.user.name,
&g.name
);
} else {
println!("{} retained as {}", &self.path.display(), &self.user.name);
}
}
}
Feedback::Changes => {
if self.user.uid != uid || self.group.clone().map(|x| x.gid) != Some(gid) {
if self.user.uid != uid || self.group.as_ref().map(|x| x.gid) != Some(gid) {
if let Some(g) = &self.group {
println!("{} changed to {}:{}", self.path.display(), &self.user.name, &g.name);
println!(
"{} changed to {}:{}",
self.path.display(),
&self.user.name,
&g.name
);
} else {
println!("{}, changed to {}", self.path.display(), &self.user.name);
}
}
},
}
}
}
Ok(())
@ -259,7 +303,11 @@ impl Action {
fn into_child(&self, entry: DirEntry) -> Result<Self, Box<dyn Error>> {
let path = entry.path().to_path_buf();
let recurse = if let Some(r) = self.recurse { Some(r.increment()) } else { None };
let recurse = if let Some(r) = self.recurse {
Some(r.increment())
} else {
None
};
Ok(Self {
path,
user: self.user.clone(),
@ -272,11 +320,9 @@ impl Action {
fn recurse(&self) -> Result<(), Box<dyn Error>> {
let walker = WalkDir::new(&self.path)
.same_file_system(self.recurse.map_or(false, |x| !x.same_filesystem))
.follow_links(self.recurse.map_or(false, |x| {
match x.traversal {
Traversal::NoLinks | Traversal::CliLinks => false,
_ => true,
}
.follow_links(self.recurse.map_or(false, |x| match x.traversal {
Traversal::NoLinks | Traversal::CliLinks => false,
_ => true,
}));
for entry in walker {
let entry = entry?;