mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
uucore/perms: take traverse_symlinks into account
This commit is contained in:
parent
a4fca2d4fc
commit
a7f6b4420a
2 changed files with 78 additions and 2 deletions
|
@ -265,10 +265,21 @@ impl ChownExecutor {
|
|||
}
|
||||
|
||||
fn dive_into<P: AsRef<Path>>(&self, root: P) -> i32 {
|
||||
let mut ret = 0;
|
||||
let root = root.as_ref();
|
||||
|
||||
// walkdir always dereferences the root directory, so we have to check it ourselves
|
||||
// TODO: replace with `root.is_symlink()` once it is stable
|
||||
if self.traverse_symlinks == TraverseSymlinks::None
|
||||
&& std::fs::symlink_metadata(root)
|
||||
.map(|m| m.file_type().is_symlink())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut ret = 0;
|
||||
let mut iterator = WalkDir::new(root)
|
||||
.follow_links(self.dereference)
|
||||
.follow_links(self.traverse_symlinks == TraverseSymlinks::All)
|
||||
.min_depth(1)
|
||||
.into_iter();
|
||||
// We can't use a for loop because we need to manipulate the iterator inside the loop.
|
||||
|
|
|
@ -288,3 +288,68 @@ fn test_subdir_permission_denied() {
|
|||
.stderr_only("chgrp: cannot access 'dir/subdir': Permission denied");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
fn test_traverse_symlinks() {
|
||||
use std::os::unix::prelude::MetadataExt;
|
||||
let groups = nix::unistd::getgroups().unwrap();
|
||||
if groups.len() < 2 {
|
||||
return;
|
||||
}
|
||||
let (first_group, second_group) = (groups[0], groups[1]);
|
||||
|
||||
for &(args, traverse_first, traverse_second) in &[
|
||||
(&[][..] as &[&str], false, false),
|
||||
(&["-H"][..], true, false),
|
||||
(&["-P"][..], false, false),
|
||||
(&["-L"][..], true, true),
|
||||
] {
|
||||
let scenario = TestScenario::new("chgrp");
|
||||
|
||||
let (at, mut ucmd) = (scenario.fixtures.clone(), scenario.ucmd());
|
||||
|
||||
at.mkdir("dir");
|
||||
at.mkdir("dir2");
|
||||
at.touch("dir2/file");
|
||||
at.mkdir("dir3");
|
||||
at.touch("dir3/file");
|
||||
at.symlink_dir("dir2", "dir/dir2_ln");
|
||||
at.symlink_dir("dir3", "dir3_ln");
|
||||
|
||||
scenario
|
||||
.ccmd("chgrp")
|
||||
.arg(first_group.to_string())
|
||||
.arg("dir2/file")
|
||||
.arg("dir3/file")
|
||||
.succeeds();
|
||||
|
||||
assert!(at.plus("dir2/file").metadata().unwrap().gid() == first_group.as_raw());
|
||||
assert!(at.plus("dir3/file").metadata().unwrap().gid() == first_group.as_raw());
|
||||
|
||||
ucmd.arg("-R")
|
||||
.args(args)
|
||||
.arg(second_group.to_string())
|
||||
.arg("dir")
|
||||
.arg("dir3_ln")
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert_eq!(
|
||||
at.plus("dir2/file").metadata().unwrap().gid(),
|
||||
if traverse_second {
|
||||
second_group.as_raw()
|
||||
} else {
|
||||
first_group.as_raw()
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
at.plus("dir3/file").metadata().unwrap().gid(),
|
||||
if traverse_first {
|
||||
second_group.as_raw()
|
||||
} else {
|
||||
first_group.as_raw()
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue