diff --git a/src/iso.c b/src/iso.c index cd1cb2c1..1e809014 100644 --- a/src/iso.c +++ b/src/iso.c @@ -631,7 +631,7 @@ static void update_md5sum(void) free(md5_data); } -// Returns 0 on success, nonzero on error +// Returns 0 on success, >0 on error, <0 to ignore current dir static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) { HANDLE file_handle = NULL; @@ -668,9 +668,20 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) _CDIO_LIST_FOREACH(p_entnode, p_entlist) { if (FormatStatus) goto out; p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode); - if ((p_statbuf->rr.b3_rock == yep) && enable_rockridge) { - if (p_statbuf->rr.u_su_fields & ISO_ROCK_SUF_PL) + if (scan_only && (p_statbuf->rr.b3_rock == yep) && enable_rockridge) { + if (p_statbuf->rr.u_su_fields & ISO_ROCK_SUF_PL) { img_report.has_deep_directories = TRUE; + // Due to the nature of the parsing of Rock Ridge deep directories + // which requires performing a *very costly* search of the whole + // ISO9660 file system to find the matching LSN, ISOs with loads of + // deep directory entries (e.g. OPNsense) are very slow to parse... + // To speed up the scan process, and since we expect deep directory + // entries to appear below anything we care for, we cut things + // short by telling the parent not to bother any further once we + // find that we are dealing with a deep directory. + r = -1; + goto out; + } } // Eliminate . and .. entries if ( (strcmp(p_statbuf->filename, ".") == 0) @@ -702,15 +713,18 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) } safe_free(psz_sanpath); } - if (iso_extract_files(p_iso, psz_iso_name)) + r = iso_extract_files(p_iso, psz_iso_name); + if (r > 0) goto out; + if (r < 0) // Stop processing current dir + break; } else { file_length = p_statbuf->total_size; if (check_iso_props(psz_path, file_length, psz_basename, psz_fullpath, &props)) { continue; } print_extracted_file(psz_fullpath, file_length); - for (i=0; i