Skip to content

Commit

Permalink
[iso] fix handling of label-based ISOs
Browse files Browse the repository at this point in the history
* Linux has a MAJOR quirk in that labels such as "Contains Space"
  get converted to "/dev/disk/by-label/Contains\x20Space".
* While Rufus already had smart label Syslinux handling (by replacing
  the ones found in isolinux.cfg to their more limited FAT32 version)
  there was absolutely NO WAY of guessing this quirk until ISOs
  such as Red Hat 7 or CentOS 7 started to use spaces in their ISO
  labels and people reported breakage!
* This commit also fixes an issue where psz_fullpath was modified when
  it shouldn't, which broke Debian 7.7.0, and most likely any ISO
  containing a subdirectory in the directory where a syslinux/isolinux
  config file is located.
* Closes #396
* Closes #394
* Closes #388
* Closes #380
pbatard committed Nov 7, 2014
1 parent ed45184 commit 55a5eb0
Showing 4 changed files with 73 additions and 37 deletions.
68 changes: 37 additions & 31 deletions src/iso.c
Original file line number Diff line number Diff line change
@@ -199,6 +199,37 @@ static BOOL check_iso_props(const char* psz_dirname, BOOL* is_syslinux_cfg, BOOL
return FALSE;
}

static void fix_syslinux(const char* psz_fullpath, const char* psz_path, const char* psz_basename)
{
size_t i, nul_pos;
char *iso_label, *usb_label, *src, *dst;

nul_pos = safe_strlen(psz_fullpath);
src = safe_strdup(psz_fullpath);
if (src == NULL)
return;
for (i=0; i<nul_pos; i++)
if (src[i] == '/') src[i] = '\\';

// Workaround for isolinux config files requiring an ISO label for kernel
// append that may be different from our USB label. Oh, and these labels
// must have spaces converted to \x20.
iso_label = replace_char(iso_report.label, ' ', "\\x20");
usb_label = replace_char(iso_report.usb_label, ' ', "\\x20");
if (replace_in_token_data(src, "append", iso_label, usb_label, TRUE) != NULL)
uprintf(" Patched %s: '%s' -> '%s'\n", src, iso_label, usb_label);
free(iso_label);
free(usb_label);
// Fix dual BIOS + EFI support for tails and other ISOs
if ( (safe_stricmp(psz_path, efi_dirname) == 0) && (safe_stricmp(psz_basename, syslinux_cfg[0]) == 0) &&
(!iso_report.has_efi_syslinux) && (dst = safe_strdup(src)) ) {
dst[nul_pos-12] = 's'; dst[nul_pos-11] = 'y'; dst[nul_pos-10] = 's';
CopyFileA(src, dst, TRUE);
uprintf("Duplicated %s to %s\n", src, dst);
free(dst);
}
}

// Returns 0 on success, nonzero on error
static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path)
{
@@ -207,7 +238,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
BOOL r, is_syslinux_cfg, is_old_c32[NB_OLD_C32];
int i_length;
size_t i, nul_pos;
char tmp[128], *psz_fullpath = NULL, *dst;
char tmp[128], *psz_fullpath = NULL;
const char* psz_basename;
udf_dirent_t *p_udf_dirent2;
uint8_t buf[UDF_BLOCKSIZE];
@@ -309,20 +340,8 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
// The drawback however is with cancellation. With a large file, CloseHandle()
// may take forever to complete and is not interruptible. We try to detect this.
ISO_BLOCKING(safe_closehandle(file_handle));
if (is_syslinux_cfg) {
// Workaround for isolinux config files requiring an ISO label for kernel
// append that may be different from our USB label.
if (replace_in_token_data(psz_fullpath, "append", iso_report.label, iso_report.usb_label, TRUE) != NULL)
uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label);
// Fix dual BIOS + EFI support for tails and other ISOs
if ( (safe_stricmp(psz_path, efi_dirname) == 0) && (safe_stricmp(psz_basename, syslinux_cfg[0]) == 0) &&
(!iso_report.has_efi_syslinux) && (dst = safe_strdup(psz_fullpath)) ) {
dst[nul_pos-12] = 's'; dst[nul_pos-11] = 'y'; dst[nul_pos-10] = 's';
CopyFileA(psz_fullpath, dst, TRUE);
uprintf("Duplicated %s to %s\n", psz_fullpath, dst);
free(dst);
}
}
if (is_syslinux_cfg)
fix_syslinux(psz_fullpath, psz_path, psz_basename);
}
safe_free(psz_fullpath);
}
@@ -343,7 +362,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
DWORD buf_size, wr_size, err;
BOOL s, is_syslinux_cfg, is_old_c32[NB_OLD_C32], is_symlink;
int i_length, r = 1;
char tmp[128], psz_fullpath[MAX_PATH], *psz_basename, *dst;
char tmp[128], psz_fullpath[MAX_PATH], *psz_basename;
const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)];
unsigned char buf[ISO_BLOCKSIZE];
CdioListNode_t* p_entnode;
@@ -467,21 +486,8 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
}
}
ISO_BLOCKING(safe_closehandle(file_handle));
if (is_syslinux_cfg) {
nul_pos = safe_strlen(psz_fullpath);
for (i=0; i<nul_pos; i++)
if (psz_fullpath[i] == '/') psz_fullpath[i] = '\\';
if (replace_in_token_data(psz_fullpath, "append", iso_report.label, iso_report.usb_label, TRUE) != NULL)
uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label);
// Fix dual BIOS + EFI support for tails and other ISOs
if ( (safe_stricmp(psz_path, efi_dirname) == 0) && (safe_stricmp(psz_basename, syslinux_cfg[0]) == 0) &&
(!iso_report.has_efi_syslinux) && (dst = safe_strdup(psz_fullpath)) ) {
dst[nul_pos-12] = 's'; dst[nul_pos-11] = 'y'; dst[nul_pos-10] = 's';
CopyFileA(psz_fullpath, dst, TRUE);
uprintf("Duplicated %s to %s\n", psz_fullpath, dst);
free(dst);
}
}
if (is_syslinux_cfg)
fix_syslinux(psz_fullpath, psz_path, psz_basename);
}
}
r = 0;
29 changes: 29 additions & 0 deletions src/parser.c
Original file line number Diff line number Diff line change
@@ -1067,3 +1067,32 @@ char* replace_in_token_data(const char* filename, const char* token, const char*

return ret;
}


/*
* Replace all 'c' characters in string 'src' with the subtsring 'rep'
* The returned string is allocated and must be freed by the caller.
*/
char* replace_char(const char* src, const char c, const char* rep)
{
size_t i, j, k, count=0, str_len = safe_strlen(src), rep_len = safe_strlen(rep);
char* res;

if ((src == NULL) || (rep == NULL))
return NULL;
for (i=0; i<str_len; i++) {
if (src[i] == c)
count++;
}
res = (char*)malloc(str_len + count*rep_len + 1);
for (i=0,j=0; i<str_len; i++) {
if (src[i] == c) {
for(k=0; k<rep_len; k++)
res[j++] = rep[k];
} else {
res[j++] = src[i];
}
}
res[j] = 0;
return res;
}
1 change: 1 addition & 0 deletions src/rufus.h
Original file line number Diff line number Diff line change
@@ -389,6 +389,7 @@ extern char* get_token_data_file(const char* token, const char* filename);
extern char* get_token_data_buffer(const char* token, unsigned int n, const char* buffer, size_t buffer_size);
extern char* insert_section_data(const char* filename, const char* section, const char* data, BOOL dos2unix);
extern char* replace_in_token_data(const char* filename, const char* token, const char* src, const char* rep, BOOL dos2unix);
extern char* replace_char(const char* src, const char c, const char* rep);
extern void parse_update(char* buf, size_t len);
extern BOOL WimExtractCheck(void);
extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst);
12 changes: 6 additions & 6 deletions src/rufus.rc
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL

IDD_DIALOG DIALOGEX 12, 12, 206, 329
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 1.4.11.531"
CAPTION "Rufus 1.4.11.532"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
@@ -165,7 +165,7 @@ END
RTL_IDD_DIALOG DIALOGEX 12, 12, 206, 329
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 1.4.11.531"
CAPTION "Rufus 1.4.11.532"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
@@ -428,8 +428,8 @@ END
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,4,11,531
PRODUCTVERSION 1,4,11,531
FILEVERSION 1,4,11,532
PRODUCTVERSION 1,4,11,532
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -446,13 +446,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "1.4.11.531"
VALUE "FileVersion", "1.4.11.532"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "� 2011-2014 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "1.4.11.531"
VALUE "ProductVersion", "1.4.11.532"
END
END
BLOCK "VarFileInfo"

0 comments on commit 55a5eb0

Please sign in to comment.