From cea3eabae7c369ec658745ba3f8e4328a4de975f Mon Sep 17 00:00:00 2001 From: cyqsimon <28627918+cyqsimon@users.noreply.github.com> Date: Tue, 5 Sep 2023 13:37:18 +0800 Subject: Rewrite `contains_symlink` --- src/file_utils.rs | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'src/file_utils.rs') diff --git a/src/file_utils.rs b/src/file_utils.rs index ba976de..114a08f 100644 --- a/src/file_utils.rs +++ b/src/file_utils.rs @@ -1,4 +1,7 @@ -use std::path::{Component, Path, PathBuf}; +use std::{ + io, + path::{Component, Path, PathBuf}, +}; /// Guarantee that the path is relative and cannot traverse back to parent directories /// and optionally prevent traversing hidden directories. @@ -29,26 +32,23 @@ pub fn sanitize_path(path: impl AsRef, traverse_hidden: bool) -> Option) -> bool { - let mut joined_path = PathBuf::new(); - for path_slice in path.as_ref().iter() { - joined_path = joined_path.join(path_slice); - if !joined_path.exists() { - // On Windows, `\\?\` won't exist even though it's the root - // So, we can't just return here - // But we don't need to check if it's a symlink since it won't be - continue; - } - if joined_path - .symlink_metadata() - .map(|m| m.file_type().is_symlink()) - .unwrap_or(false) - { - return true; - } - } - false +/// Checks if any segment of the path is a symlink. +/// +/// This function fails if [`std::fs::symlink_metadata`] fails, which usually +/// means user has no permission to access the path. +pub fn contains_symlink(path: impl AsRef) -> io::Result { + let contains_symlink = path + .as_ref() + .ancestors() + // On Windows, `\\?\` won't exist even though it's the root, but there's no need to check it + // So we filter it out + .filter(|p| p.exists()) + .map(|p| p.symlink_metadata()) + .collect::, _>>()? + .into_iter() + .any(|p| p.file_type().is_symlink()); + + Ok(contains_symlink) } #[cfg(test)] -- cgit v1.2.3