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