From bbf82342b577786ce2245e7d3d337fc8adb19868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mikrut?= Date: Tue, 2 May 2023 10:17:28 +0200 Subject: [PATCH] Next --- czkawka_core/src/broken_files.rs | 196 ++++++++++++----------- czkawka_core/src/common_dir_traversal.rs | 159 ++++++++++-------- czkawka_core/src/lib.rs | 1 + 3 files changed, 193 insertions(+), 163 deletions(-) diff --git a/czkawka_core/src/broken_files.rs b/czkawka_core/src/broken_files.rs index 44c6815..faf2474 100644 --- a/czkawka_core/src/broken_files.rs +++ b/czkawka_core/src/broken_files.rs @@ -345,6 +345,102 @@ impl BrokenFiles { Some(fe) } + fn check_broken_image(&self, mut file_entry: FileEntry) -> Option { + let mut file_entry_clone = file_entry.clone(); + + let result = panic::catch_unwind(|| { + if let Err(e) = image::open(&file_entry.path) { + let error_string = e.to_string(); + // This error is a problem with image library, remove check when https://github.com/image-rs/jpeg-decoder/issues/130 will be fixed + if error_string.contains("spectral selection is not allowed in non-progressive scan") { + return None; + } + file_entry.error_string = error_string; + } + Some(file_entry) + }); + + // If image crashed during opening, needs to be printed info about crashes thing + if let Ok(image_result) = result { + image_result + } else { + let message = create_crash_message("Image-rs", &file_entry_clone.path.to_string_lossy(), "https://github.com/Serial-ATA/lofty-rs"); + println!("{message}"); + file_entry_clone.error_string = message; + Some(file_entry_clone) + } + } + fn check_broken_zip(&self, mut file_entry: FileEntry) -> Option { + match File::open(&file_entry.path) { + Ok(file) => { + if let Err(e) = zip::ZipArchive::new(file) { + file_entry.error_string = e.to_string(); + } + Some(file_entry) + } + Err(_inspected) => None, + } + } + fn check_broken_audio(&self, mut file_entry: FileEntry) -> Option { + match File::open(&file_entry.path) { + Ok(file) => { + let mut file_entry_clone = file_entry.clone(); + + let result = panic::catch_unwind(|| { + if let Err(e) = audio_checker::parse_audio_file(file) { + file_entry.error_string = e.to_string(); + } + Some(file_entry) + }); + + if let Ok(audio_result) = result { + audio_result + } else { + let message = create_crash_message("Symphonia", &file_entry_clone.path.to_string_lossy(), "https://github.com/pdeljanov/Symphonia"); + println!("{message}"); + file_entry_clone.error_string = message; + Some(file_entry_clone) + } + } + Err(_inspected) => None, + } + } + fn check_broken_pdf(&self, mut file_entry: FileEntry) -> Option { + let parser_options = ParseOptions::tolerant(); // Only show as broken files with really big bugs + + let mut file_entry_clone = file_entry.clone(); + let result = panic::catch_unwind(|| { + if let Err(e) = FileOptions::cached().parse_options(parser_options).open(&file_entry.path) { + if let PdfError::Io { .. } = e { + return None; + } + + let mut error_string = e.to_string(); + // Workaround for strange error message https://github.com/qarmin/czkawka/issues/898 + if error_string.starts_with("Try at") { + if let Some(start_index) = error_string.find("/pdf-") { + error_string = format!("Decoding error in pdf-rs library - {}", &error_string[start_index..]); + } + } + + file_entry.error_string = error_string; + let error = unpack_pdf_error(e); + if let PdfError::InvalidPassword = error { + return None; + } + } + Some(file_entry) + }); + if let Ok(pdf_result) = result { + pdf_result + } else { + let message = create_crash_message("PDF-rs", &file_entry_clone.path.to_string_lossy(), "https://github.com/pdf-rs/pdf"); + println!("{message}"); + file_entry_clone.error_string = message; + Some(file_entry_clone) + } + } + fn look_for_broken_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&futures::channel::mpsc::UnboundedSender>) -> bool { let system_time = SystemTime::now(); @@ -389,106 +485,17 @@ impl BrokenFiles { let mut vec_file_entry: Vec = non_cached_files_to_check .into_par_iter() - .map(|(_, mut file_entry)| { + .map(|(_, file_entry)| { atomic_counter.fetch_add(1, Ordering::Relaxed); if stop_receiver.is_some() && stop_receiver.unwrap().try_recv().is_ok() { return None; } match file_entry.type_of_file { - TypeOfFile::Image => { - let mut file_entry_clone = file_entry.clone(); - - let result = panic::catch_unwind(|| { - if let Err(e) = image::open(&file_entry.path) { - let error_string = e.to_string(); - // This error is a problem with image library, remove check when https://github.com/image-rs/jpeg-decoder/issues/130 will be fixed - if error_string.contains("spectral selection is not allowed in non-progressive scan") { - return Some(None); - } - file_entry.error_string = error_string; - } - Some(Some(file_entry)) - }); - - // If image crashed during opening, needs to be printed info about crashes thing - if let Ok(image_result) = result { - image_result - } else { - let message = create_crash_message("Image-rs", &file_entry_clone.path.to_string_lossy(), "https://github.com/Serial-ATA/lofty-rs"); - println!("{message}"); - file_entry_clone.error_string = message; - Some(Some(file_entry_clone)) - } - } - TypeOfFile::ArchiveZip => match File::open(&file_entry.path) { - Ok(file) => { - if let Err(e) = zip::ZipArchive::new(file) { - file_entry.error_string = e.to_string(); - } - Some(Some(file_entry)) - } - Err(_inspected) => Some(None), - }, - TypeOfFile::Audio => match File::open(&file_entry.path) { - Ok(file) => { - let mut file_entry_clone = file_entry.clone(); - - let result = panic::catch_unwind(|| { - if let Err(e) = audio_checker::parse_audio_file(file) { - file_entry.error_string = e.to_string(); - } - Some(Some(file_entry)) - }); - - if let Ok(audio_result) = result { - audio_result - } else { - let message = create_crash_message("Symphonia", &file_entry_clone.path.to_string_lossy(), "https://github.com/pdeljanov/Symphonia"); - println!("{message}"); - file_entry_clone.error_string = message; - Some(Some(file_entry_clone)) - } - } - Err(_inspected) => Some(None), - }, - - TypeOfFile::PDF => { - let parser_options = ParseOptions::tolerant(); // Only show as broken files with really big bugs - - let mut file_entry_clone = file_entry.clone(); - let result = panic::catch_unwind(|| { - if let Err(e) = FileOptions::cached().parse_options(parser_options).open(&file_entry.path) { - if let PdfError::Io { .. } = e { - return Some(None); - } - - let mut error_string = e.to_string(); - // Workaround for strange error message https://github.com/qarmin/czkawka/issues/898 - if error_string.starts_with("Try at") { - if let Some(start_index) = error_string.find("/pdf-") { - error_string = format!("Decoding error in pdf-rs library - {}", &error_string[start_index..]); - } - } - - file_entry.error_string = error_string; - let error = unpack_pdf_error(e); - if let PdfError::InvalidPassword = error { - return Some(None); - } - } - Some(Some(file_entry)) - }); - if let Ok(pdf_result) = result { - pdf_result - } else { - let message = create_crash_message("PDF-rs", &file_entry_clone.path.to_string_lossy(), "https://github.com/pdf-rs/pdf"); - println!("{message}"); - file_entry_clone.error_string = message; - Some(Some(file_entry_clone)) - } - } - + TypeOfFile::Image => Some(self.check_broken_image(file_entry)), + TypeOfFile::ArchiveZip => Some(self.check_broken_zip(file_entry)), + TypeOfFile::Audio => Some(self.check_broken_audio(file_entry)), + TypeOfFile::PDF => Some(self.check_broken_pdf(file_entry)), // This means that cache read invalid value because maybe cache comes from different czkawka version TypeOfFile::Unknown => Some(None), } @@ -532,6 +539,7 @@ impl BrokenFiles { true } + /// Function to delete files, from filed Vector fn delete_files(&mut self) { let start_time: SystemTime = SystemTime::now(); diff --git a/czkawka_core/src/common_dir_traversal.rs b/czkawka_core/src/common_dir_traversal.rs index df8b9fa..456d5ab 100644 --- a/czkawka_core/src/common_dir_traversal.rs +++ b/czkawka_core/src/common_dir_traversal.rs @@ -489,75 +489,16 @@ where } (EntryType::Symlink, Collect::InvalidSymlinks) => { atomic_entry_counter.fetch_add(1, Ordering::Relaxed); - - let Some(file_name_lowercase) = get_lowercase_name(entry_data, &mut warnings) else { - continue 'dir; - }; - - if !allowed_extensions.matches_filename(&file_name_lowercase) { - continue 'dir; - } - - let current_file_name = current_folder.join(entry_data.file_name()); - if excluded_items.is_excluded(¤t_file_name) { - continue 'dir; - } - - #[cfg(target_family = "unix")] - if directories.exclude_other_filesystems() { - match directories.is_on_other_filesystems(current_folder) { - Ok(true) => continue 'dir, - Err(e) => warnings.push(e.to_string()), - _ => (), - } - } - - 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 - continue 'dir; - } - }; - - 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 { - path: current_file_name.clone(), - modified_date: get_modified_time(&metadata, &mut warnings, ¤t_file_name, false), - size: 0, - hash: String::new(), - symlink_info: Some(SymlinkInfo { destination_path, type_of_error }), - }; - - // Adding files to Vector - fe_result.push(fe); + process_symlink_in_symlink_mode( + &metadata, + entry_data, + &mut warnings, + &mut fe_result, + &allowed_extensions, + current_folder, + &directories, + &excluded_items, + ); } (EntryType::Symlink, Collect::Files) | (EntryType::Other, _) => { // nothing to do @@ -605,6 +546,86 @@ where } } +fn process_symlink_in_symlink_mode( + metadata: &Metadata, + entry_data: &DirEntry, + warnings: &mut Vec, + fe_result: &mut Vec, + allowed_extensions: &Extensions, + current_folder: &Path, + directories: &Directories, + excluded_items: &ExcludedItems, +) { + let Some(file_name_lowercase) = get_lowercase_name(entry_data, warnings) else { + return; + }; + + if !allowed_extensions.matches_filename(&file_name_lowercase) { + return; + } + + let current_file_name = current_folder.join(entry_data.file_name()); + if excluded_items.is_excluded(¤t_file_name) { + return; + } + + #[cfg(target_family = "unix")] + if directories.exclude_other_filesystems() { + match directories.is_on_other_filesystems(current_folder) { + Ok(true) => return, + Err(e) => warnings.push(e), + _ => (), + } + } + + 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 { + path: current_file_name.clone(), + modified_date: get_modified_time(metadata, warnings, ¤t_file_name, false), + size: 0, + hash: String::new(), + symlink_info: Some(SymlinkInfo { destination_path, type_of_error }), + }; + + // Adding files to Vector + fe_result.push(fe); +} + pub fn common_read_dir(current_folder: &Path, warnings: &mut Vec) -> Option { match fs::read_dir(current_folder) { Ok(t) => Some(t), diff --git a/czkawka_core/src/lib.rs b/czkawka_core/src/lib.rs index e37b1f5..ddbb975 100644 --- a/czkawka_core/src/lib.rs +++ b/czkawka_core/src/lib.rs @@ -1,6 +1,7 @@ #![allow(clippy::collapsible_else_if)] #![allow(clippy::type_complexity)] #![allow(clippy::needless_late_init)] +#![allow(clippy::too_many_arguments)] #[macro_use] extern crate bitflags;