1
0
Fork 0
mirror of synced 2024-05-17 19:03:08 +12:00
This commit is contained in:
Rafał Mikrut 2023-05-02 10:17:28 +02:00
parent 45da05c173
commit bbf82342b5
3 changed files with 193 additions and 163 deletions

View file

@ -345,6 +345,102 @@ impl BrokenFiles {
Some(fe)
}
fn check_broken_image(&self, mut file_entry: FileEntry) -> Option<FileEntry> {
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<FileEntry> {
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<FileEntry> {
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<FileEntry> {
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<ProgressData>>) -> bool {
let system_time = SystemTime::now();
@ -389,106 +485,17 @@ impl BrokenFiles {
let mut vec_file_entry: Vec<FileEntry> = 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();

View file

@ -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(&current_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, &current_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<String>,
fe_result: &mut Vec<FileEntry>,
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(&current_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, &current_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<String>) -> Option<ReadDir> {
match fs::read_dir(current_folder) {
Ok(t) => Some(t),

View file

@ -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;