diff --git a/czkawka_core/src/common_dir_traversal.rs b/czkawka_core/src/common_dir_traversal.rs index 292a0d1..f547f68 100644 --- a/czkawka_core/src/common_dir_traversal.rs +++ b/czkawka_core/src/common_dir_traversal.rs @@ -65,7 +65,6 @@ pub struct FileEntry { pub size: u64, pub modified_date: u64, pub hash: String, - pub symlink_info: Option, } impl ResultEntry for FileEntry { @@ -82,14 +81,6 @@ impl ResultEntry for FileEntry { // Symlinks -const MAX_NUMBER_OF_SYMLINK_JUMPS: i32 = 20; - -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -pub struct SymlinkInfo { - pub destination_path: PathBuf, - pub type_of_error: ErrorType, -} - #[derive(Clone, Debug, PartialEq, Eq, Copy, Deserialize, Serialize)] pub enum ErrorType { InfiniteRecursion, @@ -478,7 +469,6 @@ fn process_file_in_file_mode( modified_date: get_modified_time(&metadata, warnings, ¤t_file_name, false), path: current_file_name, hash: String::new(), - symlink_info: None, }; fe_result.push(fe); @@ -548,51 +538,14 @@ fn process_symlink_in_symlink_mode( return; }; - let mut destination_path = PathBuf::new(); - let type_of_error; - - match current_file_name.read_link() { - Ok(t) => { - destination_path.push(t); - let mut number_of_loop = 0; - let mut current_path = current_file_name.clone(); - loop { - if number_of_loop == 0 && !current_path.exists() { - type_of_error = ErrorType::NonExistentFile; - break; - } - if number_of_loop == MAX_NUMBER_OF_SYMLINK_JUMPS { - type_of_error = ErrorType::InfiniteRecursion; - break; - } - - current_path = match current_path.read_link() { - Ok(t) => t, - Err(_inspected) => { - // Looks that some next symlinks are broken, but we do nothing with it - TODO why they are broken - return; - } - }; - - number_of_loop += 1; - } - } - Err(_inspected) => { - // Failed to load info about it - type_of_error = ErrorType::NonExistentFile; - } - } - // Creating new file entry let fe: FileEntry = FileEntry { + size: metadata.len(), modified_date: get_modified_time(&metadata, warnings, ¤t_file_name, false), path: current_file_name, - size: 0, hash: String::new(), - symlink_info: Some(SymlinkInfo { destination_path, type_of_error }), }; - // Adding files to Vector fe_result.push(fe); } diff --git a/czkawka_core/src/invalid_symlinks.rs b/czkawka_core/src/invalid_symlinks.rs index 8c8de19..93f3836 100644 --- a/czkawka_core/src/invalid_symlinks.rs +++ b/czkawka_core/src/invalid_symlinks.rs @@ -1,10 +1,12 @@ use std::fs; use std::io::prelude::*; +use std::path::{Path, PathBuf}; use crossbeam_channel::{Receiver, Sender}; use fun_time::fun_time; use log::debug; +use serde::{Deserialize, Serialize}; use crate::common_dir_traversal::{Collect, DirTraversalBuilder, DirTraversalResult, ErrorType, FileEntry, ProgressData, ToolType}; use crate::common_tool::{CommonData, CommonToolData, DeleteMethod}; @@ -15,10 +17,50 @@ pub struct Info { pub number_of_invalid_symlinks: usize, } +const MAX_NUMBER_OF_SYMLINK_JUMPS: i32 = 20; + +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +pub struct SymlinkInfo { + pub destination_path: PathBuf, + pub type_of_error: ErrorType, +} + +#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +pub struct SymlinksFileEntry { + pub path: PathBuf, + pub size: u64, + pub modified_date: u64, + pub symlink_info: Option, +} + +impl ResultEntry for SymlinksFileEntry { + fn get_path(&self) -> &Path { + &self.path + } + fn get_modified_date(&self) -> u64 { + self.modified_date + } + fn get_size(&self) -> u64 { + self.size + } +} + +impl FileEntry { + fn into_symlinks_entry(self) -> SymlinksFileEntry { + SymlinksFileEntry { + size: self.size, + path: self.path, + modified_date: self.modified_date, + + symlink_info: None, + } + } +} + pub struct InvalidSymlinks { common_data: CommonToolData, information: Info, - invalid_symlinks: Vec, + invalid_symlinks: Vec, } impl InvalidSymlinks { pub fn new() -> Self { @@ -53,7 +95,18 @@ impl InvalidSymlinks { match result { DirTraversalResult::SuccessFiles { grouped_file_entries, warnings } => { - self.invalid_symlinks = grouped_file_entries.into_values().flatten().collect(); + self.invalid_symlinks = grouped_file_entries + .into_values() + .flatten() + .filter_map(|e| { + let mut entry = e.into_symlinks_entry(); + let Some((destination_path, type_of_error)) = Self::check_invalid_symlinks(&entry.path) else { + return None; + }; + entry.symlink_info = Some(SymlinkInfo { destination_path, type_of_error }); + Some(entry) + }) + .collect(); self.information.number_of_invalid_symlinks = self.invalid_symlinks.len(); self.common_data.text_messages.warnings.extend(warnings); debug!("Found {} invalid symlinks.", self.information.number_of_invalid_symlinks); @@ -63,6 +116,44 @@ impl InvalidSymlinks { } } + fn check_invalid_symlinks(current_file_name: &Path) -> Option<(PathBuf, ErrorType)> { + let mut destination_path = PathBuf::new(); + let type_of_error; + + match current_file_name.read_link() { + Ok(t) => { + destination_path.push(t); + let mut number_of_loop = 0; + let mut current_path = current_file_name.to_path_buf(); + loop { + if number_of_loop == 0 && !current_path.exists() { + type_of_error = ErrorType::NonExistentFile; + break; + } + if number_of_loop == MAX_NUMBER_OF_SYMLINK_JUMPS { + type_of_error = ErrorType::InfiniteRecursion; + break; + } + + current_path = match current_path.read_link() { + Ok(t) => t, + Err(_inspected) => { + // Looks that some next symlinks are broken, but we do nothing with it - TODO why they are broken + return None; + } + }; + + number_of_loop += 1; + } + } + Err(_inspected) => { + // Failed to load info about it + type_of_error = ErrorType::NonExistentFile; + } + } + Some((destination_path, type_of_error)) + } + #[fun_time(message = "delete_files", level = "debug")] fn delete_files(&mut self) { match self.common_data.delete_method { @@ -137,7 +228,7 @@ impl CommonData for InvalidSymlinks { } impl InvalidSymlinks { - pub const fn get_invalid_symlinks(&self) -> &Vec { + pub const fn get_invalid_symlinks(&self) -> &Vec { &self.invalid_symlinks } diff --git a/czkawka_gui/src/compute_results.rs b/czkawka_gui/src/compute_results.rs index 9cd8f9f..dbba231 100644 --- a/czkawka_gui/src/compute_results.rs +++ b/czkawka_gui/src/compute_results.rs @@ -15,6 +15,7 @@ use czkawka_core::broken_files::BrokenFiles; use czkawka_core::common::{split_path, split_path_compare}; use czkawka_core::common_dir_traversal::{CheckingMethod, FileEntry}; use czkawka_core::common_tool::CommonData; +use czkawka_core::common_traits::ResultEntry; use czkawka_core::duplicate::DuplicateFinder; use czkawka_core::empty_files::EmptyFiles; use czkawka_core::empty_folder::EmptyFolder; @@ -1336,9 +1337,12 @@ fn vector_sort_unstable_entry_by_path(vector: &[FileEntry]) -> Vec { } } -fn vector_sort_simple_unstable_entry_by_path(vector: &[FileEntry]) -> Vec { - let mut vector = vector.to_owned(); - vector.sort_unstable_by(|a, b| split_path_compare(a.path.as_path(), b.path.as_path())); +fn vector_sort_simple_unstable_entry_by_path(vector: &[T]) -> Vec +where + T: ResultEntry + Clone, +{ + let mut vector = vector.to_vec(); + vector.sort_unstable_by(|a, b| split_path_compare(a.get_path(), b.get_path())); vector }