chown - Removed several clones
This commit is contained in:
parent
3016f4c234
commit
7fc064a441
@ -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?;
|
||||
|
Loading…
Reference in New Issue
Block a user