From 3c438db3fd1448d97074781f40a9f25217222ec7 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Mon, 14 Oct 2013 00:02:32 +0100 Subject: [PATCH] [iso] add smart testing for Rock Ridge over Joliet * Some ISO9660 images (such as Ubuntu) use both Joliet and Rock Ridge, so we have to make a choice which should be preferred. * Since Rock Ridge allows a greater filename length compared to Joliet, we perform our scan pass with Joliet disabled, to find out if RR is being used and if a filename longer than 64 chars exist. If that is the case, we'll perform the extraction using RR, else we'll use Joliet. * Also add Alt-J and Alt-K to toggle Joliet/Rock Ridge * Closes #178 --- src/iso.c | 24 +++++++++++++++++++----- src/rufus.c | 27 ++++++++++++++++++++++----- src/rufus.h | 1 + src/rufus.rc | 10 +++++----- 4 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/iso.c b/src/iso.c index 0086fea1..ada677f3 100644 --- a/src/iso.c +++ b/src/iso.c @@ -53,6 +53,7 @@ void cdio_destroy (CdIo_t* p_cdio) {} RUFUS_ISO_REPORT iso_report; int64_t iso_blocking_status = -1; +BOOL enable_joliet = TRUE, enable_rockridge = TRUE; #define ISO_BLOCKING(x) do {x; iso_blocking_status++; } while(0) static const char* psz_extract_dir; static const char* bootmgr_efi_name = "bootmgr.efi"; @@ -327,11 +328,13 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) if ( (strcmp(p_statbuf->filename, ".") == 0) || (strcmp(p_statbuf->filename, "..") == 0) ) continue; - // Rock Ridge requires an exception (Can't people just use Joliet?) - if (p_statbuf->rr.b3_rock != yep) { - iso9660_name_translate_ext(p_statbuf->filename, psz_basename, i_joliet_level); - } else { + // Rock Ridge requires an exception + if ((p_statbuf->rr.b3_rock == yep) && enable_rockridge) { safe_strcpy(psz_basename, sizeof(psz_fullpath)-i_length-1, p_statbuf->filename); + if (safe_strlen(p_statbuf->filename) > 64) + iso_report.has_long_filename = TRUE; + } else { + iso9660_name_translate_ext(p_statbuf->filename, psz_basename, i_joliet_level); } if (p_statbuf->type == _STAT_DIR) { if (!scan_only) _mkdirU(psz_fullpath); @@ -419,6 +422,7 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan) const char* scan_text = "Scanning ISO image..."; const char* basedir[] = { "i386", "minint" }; const char* tmp_sif = ".\\txtsetup.sif~"; + iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL; if ((src_iso == NULL) || (dest_dir == NULL)) return FALSE; @@ -472,7 +476,17 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan) goto out; try_iso: - p_iso = iso9660_open_ext(src_iso, ISO_EXTENSION_ALL); + // Perform our first scan with Joliet disabled (if Rock Ridge is enabled), so that we can find if + // there exists a Rock Ridge file with a name > 64 chars. If that is the case (has_long_filename) + // then we also disable Joliet during the extract phase. + if ((!enable_joliet) || (scan_only && enable_rockridge) || (iso_report.has_long_filename && enable_rockridge)) { + iso_extension_mask &= ~ISO_EXTENSION_JOLIET; + } + if (!enable_rockridge) { + iso_extension_mask &= ~ISO_EXTENSION_ROCK_RIDGE; + } + + p_iso = iso9660_open_ext(src_iso, iso_extension_mask); if (p_iso == NULL) { uprintf("Unable to open image '%s'.\n", src_iso); goto out; diff --git a/src/rufus.c b/src/rufus.c index f0739dbc..a2e791b9 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -99,7 +99,7 @@ static BOOL existing_key = FALSE; // For LGP set/restore static BOOL size_check = TRUE; static BOOL log_displayed = FALSE; static BOOL iso_provided = FALSE; -extern BOOL force_large_fat32; +extern BOOL force_large_fat32, enable_joliet, enable_rockridge; static int selection_default; char msgbox[1024], msgbox_title[32]; @@ -1034,8 +1034,10 @@ DWORD WINAPI ISOScanThread(LPVOID param) safe_free(iso_path); goto out; } - uprintf("ISO label: '%s'\r\n Size: %lld bytes\r\n Has a >4GB file: %s\r\n Uses EFI: %s%s\r\n Uses Bootmgr: %s\r\n Uses WinPE: %s%s\r\n Uses isolinux: %s %s\n", - iso_report.label, iso_report.projected_size, iso_report.has_4GB_file?"Yes":"No", (iso_report.has_efi || iso_report.has_win7_efi)?"Yes":"No", + uprintf("ISO label: '%s'\r\n Size: %lld bytes\r\n Has a >64 chars filename: %s\r\n Has a >4GB file: %s\r\n" + " Uses EFI: %s%s\r\n Uses Bootmgr: %s\r\n Uses WinPE: %s%s\r\n Uses isolinux: %s %s\n", + iso_report.label, iso_report.projected_size, iso_report.has_long_filename?"Yes":"No", + iso_report.has_4GB_file?"Yes":"No", (iso_report.has_efi || iso_report.has_win7_efi)?"Yes":"No", (iso_report.has_win7_efi && (!iso_report.has_efi))?" (win7_x64)":"", iso_report.has_bootmgr?"Yes":"No", IS_WINPE(iso_report.winpe)?"Yes":"No", (iso_report.uses_minint)?" (with /minint)":"", iso_report.has_isolinux?"Yes":"No", iso_report.has_syslinux_v5?"(v5.0 or later)":iso_report.has_isolinux?"(v4.x or earlier)":""); @@ -2056,12 +2058,27 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine existing_key = FALSE; continue; } - // Alt K => Toggle fake drive detection during bad blocks check + // Alt J => Toggle Joliet support for ISO9660 images + // Some ISOs (Ubuntu) have Joliet extensions but expect applications not to use them, + // due to their reliance on filenames that are > 64 chars (the Joliet max length for + // a file name). This option allows users to ignore Joliet when using such images. + if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'J')) { + enable_joliet = !enable_joliet; + PrintStatus2000("Joliet support", enable_joliet); + continue; + } + // Alt K => Toggle Rock Ridge support for ISO9660 image + if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'K')) { + enable_rockridge = !enable_rockridge; + PrintStatus2000("Rock Ridge support", enable_rockridge); + continue; + } + // Alt L => Toggle fake drive detection during bad blocks check // By default, Rufus will check for fake USB flash drives that mistakenly present // more capacity than they already have by looping over the flash. This check which // is enabled by default is performed by writing the block number sequence and reading // it back during the bad block check. - if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'K')) { + if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'L')) { detect_fakes = !detect_fakes; PrintStatus2000("Fake drive detection", detect_fakes); continue; diff --git a/src/rufus.h b/src/rufus.h index 475d9246..b0ba811a 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -214,6 +214,7 @@ typedef struct { // TODO: use a bitmask and #define tests for the following uint8_t winpe; BOOL has_4GB_file; + BOOL has_long_filename; BOOL has_bootmgr; BOOL has_efi; BOOL has_win7_efi; diff --git a/src/rufus.rc b/src/rufus.rc index c51b34d3..5ce3566e 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -30,7 +30,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 329 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.3.4.278" +CAPTION "Rufus v1.3.4.279" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,291,50,14 @@ -278,8 +278,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,4,278 - PRODUCTVERSION 1,3,4,278 + FILEVERSION 1,3,4,279 + PRODUCTVERSION 1,3,4,279 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -296,13 +296,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.3.4.278" + VALUE "FileVersion", "1.3.4.279" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2013 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.3.4.278" + VALUE "ProductVersion", "1.3.4.279" END END BLOCK "VarFileInfo"