1
1
Fork 0
mirror of https://github.com/pbatard/rufus.git synced 2024-08-14 23:57:05 +00:00

Compare commits

...

2 commits

Author SHA1 Message Date
Pete Batard
cb561e7176
[iso] fix libcio processing of Rock Ridge CE fields
* Boy do you not want to use chars in struct iso_su_ce_s as
  from_733() will sign extend the bytes and you will end up
  with an offset like 0xffffffc4 instead of 0x000000c4...
* Addresses the leftover from 6c44dccc10.
* Also some headers clean up and pick up latest libcdio changes.
2023-02-28 18:27:21 +00:00
Pete Batard
6c44dccc10
[iso] duplicate Rock Ridge symbolic links for Debian non-free firmware ISOs
* Note that, because of an unrelated libcdio bug where it does not properly
  detect Rock Ridge symbolic links, some files may still not be instantiated.
* Also remove unneeded checks for ISO9660/UDF function cleanup and remove
  a workaround for an issue that has since been fixed in libcdio.
2023-02-27 17:43:39 +00:00
4 changed files with 107 additions and 97 deletions

View file

@ -1,7 +1,7 @@
/* /*
* Rufus: The Reliable USB Formatting Utility * Rufus: The Reliable USB Formatting Utility
* ISO file extraction * ISO file extraction
* Copyright © 2011-2022 Pete Batard <pete@akeo.ie> * Copyright © 2011-2023 Pete Batard <pete@akeo.ie>
* Based on libcdio's iso & udf samples: * Based on libcdio's iso & udf samples:
* Copyright © 2003-2014 Rocky Bernstein <rocky@gnu.org> * Copyright © 2003-2014 Rocky Bernstein <rocky@gnu.org>
* *
@ -607,7 +607,6 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
return 0; return 0;
out: out:
if (p_udf_dirent != NULL)
udf_dirent_free(p_udf_dirent); udf_dirent_free(p_udf_dirent);
ISO_BLOCKING(safe_closehandle(file_handle)); ISO_BLOCKING(safe_closehandle(file_handle));
safe_free(psz_sanpath); safe_free(psz_sanpath);
@ -677,7 +676,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
HANDLE file_handle = NULL; HANDLE file_handle = NULL;
DWORD buf_size, wr_size, err; DWORD buf_size, wr_size, err;
EXTRACT_PROPS props; EXTRACT_PROPS props;
BOOL is_symlink, is_identical; BOOL is_symlink, is_identical, free_p_statbuf = FALSE;
int length, r = 1; int length, r = 1;
char tmp[128], psz_fullpath[MAX_PATH], *psz_basename = NULL, *psz_sanpath = NULL; char tmp[128], psz_fullpath[MAX_PATH], *psz_basename = NULL, *psz_sanpath = NULL;
const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)]; const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)];
@ -708,6 +707,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
_CDIO_LIST_FOREACH(p_entnode, p_entlist) { _CDIO_LIST_FOREACH(p_entnode, p_entlist) {
if (FormatStatus) goto out; if (FormatStatus) goto out;
p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode); p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode);
free_p_statbuf = FALSE;
if (scan_only && (p_statbuf->rr.b3_rock == yep) && enable_rockridge) { if (scan_only && (p_statbuf->rr.b3_rock == yep) && enable_rockridge) {
if (p_statbuf->rr.u_su_fields & ISO_ROCK_SUF_PL) { if (p_statbuf->rr.u_su_fields & ISO_ROCK_SUF_PL) {
if (!img_report.has_deep_directories) if (!img_report.has_deep_directories)
@ -738,13 +738,9 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
safe_strcpy(psz_basename, sizeof(psz_fullpath) - length - 1, p_statbuf->filename); safe_strcpy(psz_basename, sizeof(psz_fullpath) - length - 1, p_statbuf->filename);
if (safe_strlen(p_statbuf->filename) > 64) if (safe_strlen(p_statbuf->filename) > 64)
img_report.has_long_filename = TRUE; img_report.has_long_filename = TRUE;
// libcdio has a memleak for Rock Ridge symlinks. It doesn't look like there's an easy fix there as
// a generic list that's unaware of RR extensions is being used, so we prevent that memleak ourselves
is_symlink = (p_statbuf->rr.psz_symlink != NULL); is_symlink = (p_statbuf->rr.psz_symlink != NULL);
if (is_symlink) if (is_symlink)
img_report.has_symlinks = SYMLINKS_RR; img_report.has_symlinks = SYMLINKS_RR;
if (scan_only)
safe_free(p_statbuf->rr.psz_symlink);
} else { } else {
iso9660_name_translate_ext(p_statbuf->filename, psz_basename, joliet_level); iso9660_name_translate_ext(p_statbuf->filename, psz_basename, joliet_level);
} }
@ -768,6 +764,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
if (check_iso_props(psz_path, file_length, psz_basename, psz_fullpath, &props)) { if (check_iso_props(psz_path, file_length, psz_basename, psz_fullpath, &props)) {
continue; continue;
} }
if (!is_symlink)
print_extracted_file(psz_fullpath, file_length); print_extracted_file(psz_fullpath, file_length);
for (i = 0; i < NB_OLD_C32; i++) { for (i = 0; i < NB_OLD_C32; i++) {
if (props.is_old_c32[i] && use_own_c32[i]) { if (props.is_old_c32[i] && use_own_c32[i]) {
@ -786,15 +783,35 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
uprintf(" File name sanitized to '%s'", psz_sanpath); uprintf(" File name sanitized to '%s'", psz_sanpath);
if (is_symlink) { if (is_symlink) {
if (file_length == 0) { if (file_length == 0) {
// Special handling for ISOs that have a syslinux → isolinux symbolic link (e.g. Knoppix)
if ((safe_stricmp(p_statbuf->filename, "syslinux") == 0) && if ((safe_stricmp(p_statbuf->filename, "syslinux") == 0) &&
// Special handling for ISOs that have a syslinux → isolinux symbolic link (e.g. Knoppix)
(safe_stricmp(p_statbuf->rr.psz_symlink, "isolinux") == 0)) { (safe_stricmp(p_statbuf->rr.psz_symlink, "isolinux") == 0)) {
static_strcpy(symlinked_syslinux, psz_fullpath); static_strcpy(symlinked_syslinux, psz_fullpath);
print_extracted_file(psz_fullpath, file_length);
uprintf(" Found Rock Ridge symbolic link to '%s'", p_statbuf->rr.psz_symlink); uprintf(" Found Rock Ridge symbolic link to '%s'", p_statbuf->rr.psz_symlink);
} else } else if (strcmp(psz_path, "/firmware") == 0) {
// Special handling for ISOs that use symlinks for /firmware/ (e.g. Debian non-free)
// TODO: Do we want to do this for all file symlinks?
char target_path[256];
static_sprintf(target_path, "%s/%s", psz_path, p_statbuf->rr.psz_symlink);
p_statbuf = iso9660_ifs_stat_translate(p_iso, target_path);
if (p_statbuf != NULL) {
// The original p_statbuf will be freed automatically, but not
// the new one so we need to force an explicit free.
free_p_statbuf = TRUE;
file_length = p_statbuf->total_size;
print_extracted_file(psz_fullpath, file_length);
uprintf(" Duplicated from '%s'", target_path);
} else {
uprintf("Could not resolve Rock Ridge Symlink - ABORTING!");
goto out;
}
} else {
// TODO: Ideally, we'd want to create a text file that contains the target link
print_extracted_file(psz_fullpath, file_length);
uprintf(" Ignoring Rock Ridge symbolic link to '%s'", p_statbuf->rr.psz_symlink); uprintf(" Ignoring Rock Ridge symbolic link to '%s'", p_statbuf->rr.psz_symlink);
} }
safe_free(p_statbuf->rr.psz_symlink); }
} }
file_handle = CreatePreallocatedFile(psz_sanpath, GENERIC_READ | GENERIC_WRITE, file_handle = CreatePreallocatedFile(psz_sanpath, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, file_length); FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, file_length);
@ -830,6 +847,8 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
if (!SetFileTime(file_handle, ft, ft, ft)) if (!SetFileTime(file_handle, ft, ft, ft))
uprintf(" Could not set timestamp: %s", WindowsErrorString()); uprintf(" Could not set timestamp: %s", WindowsErrorString());
} }
if (free_p_statbuf)
iso9660_stat_free(p_statbuf);
ISO_BLOCKING(safe_closehandle(file_handle)); ISO_BLOCKING(safe_closehandle(file_handle));
if (props.is_cfg || props.is_conf) if (props.is_cfg || props.is_conf)
fix_config(psz_sanpath, psz_path, psz_basename, &props); fix_config(psz_sanpath, psz_path, psz_basename, &props);
@ -1245,9 +1264,7 @@ out:
bled_exit(); bled_exit();
} }
} }
if (p_iso != NULL)
iso9660_close(p_iso); iso9660_close(p_iso);
if (p_udf != NULL)
udf_close(p_udf); udf_close(p_udf);
if ((r != 0) && (FormatStatus == 0)) if ((r != 0) && (FormatStatus == 0))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR((scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT)); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR((scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT));
@ -1342,16 +1359,10 @@ try_iso:
out: out:
safe_closehandle(file_handle); safe_closehandle(file_handle);
if (p_statbuf != NULL) iso9660_stat_free(p_statbuf);
safe_free(p_statbuf->rr.psz_symlink);
safe_free(p_statbuf);
if (p_udf_root != NULL)
udf_dirent_free(p_udf_root); udf_dirent_free(p_udf_root);
if (p_udf_file != NULL)
udf_dirent_free(p_udf_file); udf_dirent_free(p_udf_file);
if (p_iso != NULL)
iso9660_close(p_iso); iso9660_close(p_iso);
if (p_udf != NULL)
udf_close(p_udf); udf_close(p_udf);
return r; return r;
} }
@ -1412,16 +1423,10 @@ try_iso:
r = wim_header[3]; r = wim_header[3];
out: out:
if (p_statbuf != NULL) iso9660_stat_free(p_statbuf);
safe_free(p_statbuf->rr.psz_symlink);
safe_free(p_statbuf);
if (p_udf_root != NULL)
udf_dirent_free(p_udf_root); udf_dirent_free(p_udf_root);
if (p_udf_file != NULL)
udf_dirent_free(p_udf_file); udf_dirent_free(p_udf_file);
if (p_iso != NULL)
iso9660_close(p_iso); iso9660_close(p_iso);
if (p_udf != NULL)
udf_close(p_udf); udf_close(p_udf);
safe_free(wim_path); safe_free(wim_path);
return bswap_uint32(r); return bswap_uint32(r);
@ -1541,12 +1546,9 @@ BOOL HasEfiImgBootLoaders(void)
out: out:
if (lf_fs != NULL) if (lf_fs != NULL)
libfat_close(lf_fs); libfat_close(lf_fs);
if (p_statbuf != NULL) iso9660_stat_free(p_statbuf);
safe_free(p_statbuf->rr.psz_symlink);
safe_free(p_statbuf);
safe_free(p_private);
if (p_iso != NULL)
iso9660_close(p_iso); iso9660_close(p_iso);
safe_free(p_private);
return ret; return ret;
} }
@ -1671,12 +1673,9 @@ out:
libfat_close(lf_fs); libfat_close(lf_fs);
lf_fs = NULL; lf_fs = NULL;
} }
if (p_statbuf != NULL) iso9660_stat_free(p_statbuf);;
safe_free(p_statbuf->rr.psz_symlink);
safe_free(p_statbuf);
safe_free(p_private);
if (p_iso != NULL)
iso9660_close(p_iso); iso9660_close(p_iso);
safe_free(p_private);
} }
safe_closehandle(handle); safe_closehandle(handle);
safe_free(name); safe_free(name);

View file

@ -98,23 +98,23 @@ PRAGMA_BEGIN_PACKED
/*! system-use-sharing protocol */ /*! system-use-sharing protocol */
typedef struct iso_su_sp_s{ typedef struct iso_su_sp_s{
unsigned char magic[2]; uint8_t magic[2];
uint8_t skip; uint8_t skip;
} GNUC_PACKED iso_su_sp_t; } GNUC_PACKED iso_su_sp_t;
/*! system-use extension record */ /*! system-use extension record */
typedef struct iso_su_er_s { typedef struct iso_su_er_s {
iso711_t len_id; /**< Identifier length. Value 10?. */ iso711_t len_id; /**< Identifier length. Value 10?. */
unsigned char len_des; uint8_t len_des;
unsigned char len_src; uint8_t len_src;
iso711_t ext_ver; /**< Extension version. Value 1? */ iso711_t ext_ver; /**< Extension version. Value 1? */
char data[EMPTY_ARRAY_SIZE]; char data[EMPTY_ARRAY_SIZE];
} GNUC_PACKED iso_su_er_t; } GNUC_PACKED iso_su_er_t;
typedef struct iso_su_ce_s { typedef struct iso_su_ce_s {
char extent[8]; uint8_t extent[8];
char offset[8]; uint8_t offset[8];
char size[8]; uint8_t size[8];
} iso_su_ce_t; } iso_su_ce_t;
/*! POSIX file attributes, PX. See Rock Ridge Section 4.1.2 */ /*! POSIX file attributes, PX. See Rock Ridge Section 4.1.2 */
@ -165,7 +165,7 @@ typedef struct iso_rock_sl_part_s {
/*! Symbolic link. See Rock Ridge Section 4.1.3 */ /*! Symbolic link. See Rock Ridge Section 4.1.3 */
typedef struct iso_rock_sl_s { typedef struct iso_rock_sl_s {
unsigned char flags; uint8_t flags;
iso_rock_sl_part_t link; iso_rock_sl_part_t link;
} GNUC_PACKED iso_rock_sl_t ; } GNUC_PACKED iso_rock_sl_t ;
@ -184,7 +184,7 @@ typedef enum {
typedef struct iso_rock_nm_s { typedef struct iso_rock_nm_s {
unsigned char flags; uint8_t flags;
char name[EMPTY_ARRAY_SIZE]; char name[EMPTY_ARRAY_SIZE];
} GNUC_PACKED iso_rock_nm_t ; } GNUC_PACKED iso_rock_nm_t ;

View file

@ -1,6 +1,6 @@
/* /*
Copyright (C) 2020 Pete Batard <pete@akeo.ie> Copyright (C) 2020, 2023 Pete Batard <pete@akeo.ie>
Copyright (C) 2005, 2008, 2010-2011, 2014, 2017 Rocky Bernstein Copyright (C) 2005, 2008, 2010-2011, 2014, 2017, 2022 Rocky Bernstein
<rocky@gnu.org> <rocky@gnu.org>
Adapted from GNU/Linux fs/isofs/rock.c (C) 1992, 1993 Eric Youngdale Adapted from GNU/Linux fs/isofs/rock.c (C) 1992, 1993 Eric Youngdale
@ -95,27 +95,29 @@ realloc_symlink(/*in/out*/ iso9660_stat_t *p_stat, uint8_t i_grow)
/* This is a way of ensuring that we have something in the system /* This is a way of ensuring that we have something in the system
use fields that is compatible with Rock Ridge */ use fields that is compatible with Rock Ridge */
#define CHECK_SP(FAIL) \ #define CHECK_SP(FAIL) \
if(rr->u.SP.magic[0] != 0xbe) FAIL; \ if (rr->u.SP.magic[0] != 0xbe) FAIL; \
if(rr->u.SP.magic[1] != 0xef) FAIL; \ if (rr->u.SP.magic[1] != 0xef) FAIL; \
p_stat->rr.s_rock_offset = rr->u.SP.skip; p_stat->rr.s_rock_offset = rr->u.SP.skip;
/* We define a series of macros because each function must do exactly the /* We define a series of macros because each function must do exactly the
same thing in certain places. We use the macros to ensure that everything same thing in certain places. We use the macros to ensure that everything
is done correctly */ is done correctly */
#define CONTINUE_DECLS \ #define CONTINUE_DECLS \
int cont_extent = 0, cont_offset = 0, cont_size = 0; \ uint32_t cont_extent = 0, cont_offset = 0, cont_size = 0; \
void *buffer = NULL uint8_t *buffer = NULL
#define CHECK_CE \ #define CHECK_CE(FAIL) \
{ cont_extent = from_733(*rr->u.CE.extent); \ { cont_extent = from_733(*rr->u.CE.extent); \
cont_offset = from_733(*rr->u.CE.offset); \ cont_offset = from_733(*rr->u.CE.offset); \
if (cont_offset >= ISO_BLOCKSIZE) FAIL; \
cont_size = from_733(*rr->u.CE.size); \ cont_size = from_733(*rr->u.CE.size); \
(void)cont_extent; (void)cont_offset, (void)cont_size; } if (cont_size >= ISO_BLOCKSIZE) FAIL; \
}
#define SETUP_ROCK_RIDGE(DE,CHR,LEN) \ #define SETUP_ROCK_RIDGE(DE,CHR,LEN) \
{ \ { \
LEN= sizeof(iso9660_dir_t) + DE->filename.len; \ LEN= sizeof(iso9660_dir_t) + DE->filename.len; \
if(LEN & 1) LEN++; \ if (LEN & 1) LEN++; \
CHR = ((unsigned char *) DE) + LEN; \ CHR = ((unsigned char *) DE) + LEN; \
LEN = *((unsigned char *) DE) - LEN; \ LEN = *((unsigned char *) DE) - LEN; \
if (0xff != p_stat->rr.s_rock_offset) \ if (0xff != p_stat->rr.s_rock_offset) \
@ -202,7 +204,7 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
switch(sig) { switch(sig) {
case SIG('S','P'): case SIG('S','P'):
CHECK_SP(goto out); CHECK_SP({cdio_warn("Invalid Rock Ridge SP field"); goto out;});
p_stat->rr.u_su_fields |= ISO_ROCK_SUF_SP; p_stat->rr.u_su_fields |= ISO_ROCK_SUF_SP;
break; break;
case SIG('C','E'): case SIG('C','E'):
@ -213,8 +215,17 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname) if ('\1' == p_iso9660_dir->filename.str[1] && 1 == i_fname)
break; break;
} }
CHECK_CE; CHECK_CE({cdio_warn("Invalid Rock Ridge CE field"); goto out;});
p_stat->rr.u_su_fields |= ISO_ROCK_SUF_CE; p_stat->rr.u_su_fields |= ISO_ROCK_SUF_CE;
/* We may already be processing a continuation block so free it */
free(buffer);
buffer = calloc(1, ISO_BLOCKSIZE);
if (!buffer)
goto out;
if (iso9660_iso_seek_read(p_image, buffer, cont_extent, 1) != ISO_BLOCKSIZE)
goto out;
chr = &buffer[cont_offset];
len = cont_size;
break; break;
case SIG('E','R'): case SIG('E','R'):
cdio_debug("ISO 9660 Extensions: "); cdio_debug("ISO 9660 Extensions: ");
@ -471,7 +482,7 @@ iso9660_get_rock_attr_str(posix_mode_t st_mode)
result[ 8] = (st_mode & ISO_ROCK_IWOTH) ? 'w' : '-'; result[ 8] = (st_mode & ISO_ROCK_IWOTH) ? 'w' : '-';
result[ 9] = (st_mode & ISO_ROCK_IXOTH) ? 'x' : '-'; result[ 9] = (st_mode & ISO_ROCK_IXOTH) ? 'x' : '-';
result[11] = '\0'; result[10] = '\0';
return result; return result;
} }

View file

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326 IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 3.22.1983" CAPTION "Rufus 3.22.1985"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0 FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -392,8 +392,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,22,1983,0 FILEVERSION 3,22,1985,0
PRODUCTVERSION 3,22,1983,0 PRODUCTVERSION 3,22,1985,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -411,13 +411,13 @@ BEGIN
VALUE "Comments", "https://rufus.ie" VALUE "Comments", "https://rufus.ie"
VALUE "CompanyName", "Akeo Consulting" VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.22.1983" VALUE "FileVersion", "3.22.1985"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2023 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html" VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
VALUE "OriginalFilename", "rufus-3.22.exe" VALUE "OriginalFilename", "rufus-3.22.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.22.1983" VALUE "ProductVersion", "3.22.1985"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"