From fd54f9f72a079c7983d38544d83a251932759ba2 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 28 Jun 2024 03:53:52 -0400 Subject: [PATCH] samefile: Cache FileInformation for the target (#409) And don't follow symlinks. --- src/find/matchers/mod.rs | 12 +++--------- src/find/matchers/samefile.rs | 23 ++++++++++++++++------- tests/find_cmd_tests.rs | 4 ++-- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/find/matchers/mod.rs b/src/find/matchers/mod.rs index 4a693fb..97d238b 100644 --- a/src/find/matchers/mod.rs +++ b/src/find/matchers/mod.rs @@ -540,16 +540,10 @@ fn build_matcher_tree( if i >= args.len() - 1 { return Err(From::from(format!("missing argument to {}", args[i]))); } - let path = Path::new(args[i + 1]).to_path_buf(); - // check if path is not found - if !path.exists() { - return Err(From::from(format!( - "{}: No such file or directory", - args[i + 1] - ))); - } i += 1; - Some(SameFileMatcher::new(path).into_box()) + let path = args[i]; + let matcher = SameFileMatcher::new(path).map_err(|e| format!("{path}: {e}"))?; + Some(matcher.into_box()) } "-user" => { if i >= args.len() - 1 { diff --git a/src/find/matchers/samefile.rs b/src/find/matchers/samefile.rs index c2744e7..7d98d78 100644 --- a/src/find/matchers/samefile.rs +++ b/src/find/matchers/samefile.rs @@ -3,23 +3,29 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -use std::path::PathBuf; - use super::Matcher; +use std::error::Error; +use std::path::Path; +use uucore::fs::FileInformation; pub struct SameFileMatcher { - path: PathBuf, + info: FileInformation, } impl SameFileMatcher { - pub fn new(path: PathBuf) -> SameFileMatcher { - SameFileMatcher { path } + pub fn new(path: impl AsRef) -> Result> { + let info = FileInformation::from_path(path, false)?; + Ok(Self { info }) } } impl Matcher for SameFileMatcher { fn matches(&self, file_info: &walkdir::DirEntry, _matcher_io: &mut super::MatcherIO) -> bool { - uucore::fs::paths_refer_to_same_file(file_info.path(), &self.path, true) + if let Ok(info) = FileInformation::from_path(file_info.path(), false) { + info == self.info + } else { + false + } } } @@ -38,11 +44,14 @@ mod tests { // But you can't delete a file that doesn't exist, // so ignore the error returned here. let _ = fs::remove_file("test_data/links/hard_link"); + + assert!(SameFileMatcher::new("test_data/links/hard_link").is_err()); + fs::hard_link("test_data/links/abbbc", "test_data/links/hard_link").unwrap(); let file = get_dir_entry_for("test_data/links", "abbbc"); let hard_link_file = get_dir_entry_for("test_data/links", "hard_link"); - let matcher = SameFileMatcher::new(file.into_path()); + let matcher = SameFileMatcher::new(file.into_path()).unwrap(); let deps = FakeDependencies::new(); assert!(matcher.matches(&hard_link_file, &mut deps.new_matcher_io())); diff --git a/tests/find_cmd_tests.rs b/tests/find_cmd_tests.rs index 787d784..ae4c8b3 100644 --- a/tests/find_cmd_tests.rs +++ b/tests/find_cmd_tests.rs @@ -878,6 +878,6 @@ fn find_samefile() { .args([".", "-samefile", "./test_data/links/not-exist-file"]) .assert() .failure() - .stdout(predicate::str::contains("")) - .stderr(predicate::str::contains("No such file or directory")); + .stdout(predicate::str::is_empty()) + .stderr(predicate::str::contains("not-exist-file")); }