diff --git a/src/chgrp/chgrp.rs b/src/chgrp/chgrp.rs index ff7ed6377..dce25c9d0 100644 --- a/src/chgrp/chgrp.rs +++ b/src/chgrp/chgrp.rs @@ -217,6 +217,22 @@ impl Chgrper { } } + #[cfg(windows)] + fn is_bind_root>(&self, root: P) -> bool { + // TODO: is there an equivalent on Windows? + false + } + + #[cfg(unix)] + fn is_bind_root>(&self, path: P) -> bool { + if let (Ok(given), Ok(root)) = (fs::metadata(path), fs::metadata("/")) { + given.dev() == root.dev() && given.ino() == root.ino() + } else { + // FIXME: not totally sure if it's okay to just ignore an error here + false + } + } + fn traverse>(&self, root: P) -> i32 { let follow_arg = self.dereference || self.bit_flag != FTS_PHYSICAL; let path = root.as_ref(); @@ -244,7 +260,7 @@ impl Chgrper { }; if let Some(p) = may_exist { - if p.parent().is_none() { + if p.parent().is_none() || self.is_bind_root(p) { show_info!("it is dangerous to operate recursively on '/'"); show_info!("use --no-preserve-root to override this failsafe"); return 1; diff --git a/src/uucore/fs.rs b/src/uucore/fs.rs index 6f6ff3e2b..6cc0d58da 100644 --- a/src/uucore/fs.rs +++ b/src/uucore/fs.rs @@ -14,7 +14,6 @@ use std::fs; use std::io::{Error, ErrorKind}; use std::io::Result as IOResult; use std::path::{Component, Path, PathBuf}; -#[cfg(unix)] use std::borrow::Cow; pub fn resolve_relative_path<'a>(path: &'a Path) -> Cow<'a, Path> { @@ -26,6 +25,9 @@ pub fn resolve_relative_path<'a>(path: &'a Path) -> Cow<'a, Path> { for comp in path.components() { match comp { Component::ParentDir => { + if let Ok(p) = result.read_link() { + result = p; + } result.pop(); } Component::CurDir => (),