mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
chown,chgrp: fix bug in option --preserve-root
This commit is contained in:
parent
448764e611
commit
f8bd9e2a1b
4 changed files with 62 additions and 11 deletions
|
@ -235,7 +235,12 @@ impl Chgrper {
|
||||||
let may_exist = if follow_arg {
|
let may_exist = if follow_arg {
|
||||||
path.canonicalize().ok()
|
path.canonicalize().ok()
|
||||||
} else {
|
} else {
|
||||||
Some(resolve_relative_path(path).into_owned())
|
let real = resolve_relative_path(path);
|
||||||
|
if real.is_dir() {
|
||||||
|
Some(real.canonicalize().expect("failed to get real path"))
|
||||||
|
} else {
|
||||||
|
Some(real.into_owned())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(p) = may_exist {
|
if let Some(p) = may_exist {
|
||||||
|
|
|
@ -298,7 +298,12 @@ impl Chowner {
|
||||||
let may_exist = if follow_arg {
|
let may_exist = if follow_arg {
|
||||||
path.canonicalize().ok()
|
path.canonicalize().ok()
|
||||||
} else {
|
} else {
|
||||||
Some(resolve_relative_path(path).into_owned())
|
let real = resolve_relative_path(path);
|
||||||
|
if real.is_dir() {
|
||||||
|
Some(real.canonicalize().expect("failed to get real path"))
|
||||||
|
} else {
|
||||||
|
Some(real.into_owned())
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(p) = may_exist {
|
if let Some(p) = may_exist {
|
||||||
|
|
|
@ -16,20 +16,21 @@ use std::io::Result as IOResult;
|
||||||
use std::path::{Component, Path, PathBuf};
|
use std::path::{Component, Path, PathBuf};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
pub fn resolve_relative_path<'a>(path: &'a Path) -> Cow<'a, Path> {
|
pub fn resolve_relative_path<'a>(path: &'a Path) -> Cow<'a, Path> {
|
||||||
if path.is_absolute() {
|
if path.components().all(|e| e != Component::ParentDir) {
|
||||||
return path.into();
|
return path.into();
|
||||||
}
|
}
|
||||||
let mut result = env::current_dir().unwrap_or(PathBuf::from("/"));
|
let root = Component::RootDir.as_os_str();
|
||||||
|
let mut result = env::current_dir().unwrap_or(PathBuf::from(root));
|
||||||
for comp in path.components() {
|
for comp in path.components() {
|
||||||
match comp {
|
match comp {
|
||||||
Component::ParentDir => {
|
Component::ParentDir => {
|
||||||
result.pop();
|
result.pop();
|
||||||
}
|
}
|
||||||
Component::CurDir => (),
|
Component::CurDir => (),
|
||||||
Component::Normal(s) => result.push(s),
|
Component::RootDir |
|
||||||
_ => unreachable!(),
|
Component::Normal(_) |
|
||||||
|
Component::Prefix(_) => result.push(comp.as_os_str()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.into()
|
result.into()
|
||||||
|
|
|
@ -43,13 +43,53 @@ fn test_fail_silently() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_preserve_root() {
|
fn test_preserve_root() {
|
||||||
|
// It's weird that on OS X, `realpath /etc/..` returns '/private'
|
||||||
|
for d in &["/", "/////tmp///../../../../",
|
||||||
|
"../../../../../../../../../../../../../../",
|
||||||
|
"./../../../../../../../../../../../../../../"] {
|
||||||
new_ucmd!()
|
new_ucmd!()
|
||||||
.arg("--preserve-root")
|
.arg("--preserve-root")
|
||||||
.arg("-R")
|
.arg("-R")
|
||||||
.arg("bin").arg("/")
|
.arg("bin").arg(d)
|
||||||
.fails()
|
.fails()
|
||||||
.stderr_is("chgrp: it is dangerous to operate recursively on '/'\nchgrp: use --no-preserve-root to override this failsafe");
|
.stderr_is("chgrp: it is dangerous to operate recursively on '/'\nchgrp: use --no-preserve-root to override this failsafe");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_preserve_root_symlink() {
|
||||||
|
let file = "test_chgrp_symlink2root";
|
||||||
|
for d in &["/", "////tmp//../../../../",
|
||||||
|
"..//../../..//../..//../../../../../../../../",
|
||||||
|
".//../../../../../../..//../../../../../../../"] {
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
at.symlink(d, file);
|
||||||
|
ucmd.arg("--preserve-root")
|
||||||
|
.arg("-HR")
|
||||||
|
.arg("bin").arg(file)
|
||||||
|
.fails()
|
||||||
|
.stderr_is("chgrp: it is dangerous to operate recursively on '/'\nchgrp: use --no-preserve-root to override this failsafe");
|
||||||
|
}
|
||||||
|
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
at.symlink("///usr", file);
|
||||||
|
ucmd.arg("--preserve-root")
|
||||||
|
.arg("-HR")
|
||||||
|
.arg("bin").arg(format!(".//{}/..//..//../../", file))
|
||||||
|
.fails()
|
||||||
|
.stderr_is("chgrp: it is dangerous to operate recursively on '/'\nchgrp: use --no-preserve-root to override this failsafe");
|
||||||
|
|
||||||
|
let (at, mut ucmd) = at_and_ucmd!();
|
||||||
|
at.symlink("/", "/tmp/__root__");
|
||||||
|
ucmd.arg("--preserve-root")
|
||||||
|
.arg("-R")
|
||||||
|
.arg("bin").arg("/tmp/__root__/.")
|
||||||
|
.fails()
|
||||||
|
.stderr_is("chgrp: it is dangerous to operate recursively on '/'\nchgrp: use --no-preserve-root to override this failsafe");
|
||||||
|
|
||||||
|
use ::std::fs;
|
||||||
|
fs::remove_file("/tmp/__root__").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue