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

[iso] add Rock Ridge deep directory support

* Closes #1526
This commit is contained in:
Pete Batard 2020-05-29 12:21:56 +01:00
parent 7463fa6da3
commit 77d319267f
No known key found for this signature in database
GPG key ID: 38E0CF5E69EDD671
8 changed files with 216 additions and 246 deletions

View file

@ -654,6 +654,10 @@ 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);
if ((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;
}
// Eliminate . and .. entries // Eliminate . and .. entries
if ( (strcmp(p_statbuf->filename, ".") == 0) if ( (strcmp(p_statbuf->filename, ".") == 0)
|| (strcmp(p_statbuf->filename, "..") == 0) ) || (strcmp(p_statbuf->filename, "..") == 0) )

View file

@ -190,12 +190,12 @@ typedef struct iso_rock_nm_s {
/*! Child link. See Section 4.1.5.1 */ /*! Child link. See Section 4.1.5.1 */
typedef struct iso_rock_cl_s { typedef struct iso_rock_cl_s {
char location[1]; iso733_t location;
} GNUC_PACKED iso_rock_cl_t ; } GNUC_PACKED iso_rock_cl_t ;
/*! Parent link. See Section 4.1.5.2 */ /*! Parent link. See Section 4.1.5.2 */
typedef struct iso_rock_pl_s { typedef struct iso_rock_pl_s {
char location[1]; iso733_t location;
} GNUC_PACKED iso_rock_pl_t ; } GNUC_PACKED iso_rock_pl_t ;
/*! These are the bits and their meanings for flags in the TF structure. */ /*! These are the bits and their meanings for flags in the TF structure. */
@ -264,9 +264,29 @@ typedef struct iso_extension_record_s {
iso_rock_cl_t CL; /**< Rock Ridge child link */ iso_rock_cl_t CL; /**< Rock Ridge child link */
iso_rock_pl_t PL; /**< Rock Ridge parent link */ iso_rock_pl_t PL; /**< Rock Ridge parent link */
iso_rock_tf_t TF; /**< Rock Ridge timestamp(s) for a file */ iso_rock_tf_t TF; /**< Rock Ridge timestamp(s) for a file */
iso_rock_sf_t SF; /**< Rock Ridge sparse file */
} u; } u;
} GNUC_PACKED iso_extension_record_t; } GNUC_PACKED iso_extension_record_t;
/* Bits for the u_su_fields of iso_rock_statbuf_t */
#define ISO_ROCK_SUF_SP 0x00000001
#define ISO_ROCK_SUF_ER 0x00000002
#define ISO_ROCK_SUF_CE 0x00000004
#define ISO_ROCK_SUF_PX 0x00000008
#define ISO_ROCK_SUF_PN 0x00000010
#define ISO_ROCK_SUF_SL 0x00000020
#define ISO_ROCK_SUF_NM 0x00000040
#define ISO_ROCK_SUF_TF 0x00000080
#define ISO_ROCK_SUF_CL 0x00000100
#define ISO_ROCK_SUF_PL 0x00000200
#define ISO_ROCK_SUF_RE 0x00000400
#define ISO_ROCK_SUF_SF 0x00000800
#define ISO_ROCK_SUF_FORMAL (ISO_ROCK_SUF_ER | ISO_ROCK_SUF_PX | ISO_ROCK_SUF_PN | \
ISO_ROCK_SUF_SL | ISO_ROCK_SUF_NM | ISO_ROCK_SUF_CL | \
ISO_ROCK_SUF_PL | ISO_ROCK_SUF_RE | ISO_ROCK_SUF_TF | \
ISO_ROCK_SUF_SF)
typedef struct iso_rock_time_s { typedef struct iso_rock_time_s {
bool b_used; /**< If true, field has been set and is valid. bool b_used; /**< If true, field has been set and is valid.
Otherwise remaning fields are meaningless. */ Otherwise remaning fields are meaningless. */
@ -306,19 +326,23 @@ typedef struct iso_rock_statbuf_s {
9660:9.5.6. */ 9660:9.5.6. */
iso_rock_time_t effective; /**< Effective time; See ISO 9660:9.5.7. iso_rock_time_t effective; /**< Effective time; See ISO 9660:9.5.7.
*/ */
uint32_t i_rdev; /**< the upper 16-bits is major device uint32_t i_rdev; /**< the upper 16-bits is major device
number, the lower 16-bits is the number, the lower 16-bits is the
minor device number */ minor device number */
uint32_t u_su_fields; /**< System Use field attributes */
} iso_rock_statbuf_t; } iso_rock_statbuf_t;
PRAGMA_END_PACKED PRAGMA_END_PACKED
/*! return length of name field; 0: not found, -1: to be ignored */ /*! return length of name field; 0: not found, -1: to be ignored */
int get_rock_ridge_filename(iso9660_dir_t * de, /*out*/ char * retname, int get_rock_ridge_filename(iso9660_dir_t * de,
/*in*/ void * p_iso,
/*out*/ char * retname,
/*out*/ iso9660_stat_t *p_stat); /*out*/ iso9660_stat_t *p_stat);
int parse_rock_ridge_stat(iso9660_dir_t *de, /*out*/ iso9660_stat_t *p_stat); int parse_rock_ridge_stat(iso9660_dir_t *de,
/*out*/ iso9660_stat_t *p_stat);
/*! /*!
Returns POSIX mode bitstring for a given file. Returns POSIX mode bitstring for a given file.

View file

@ -55,7 +55,7 @@ static inline char *libcdio_strndup(const char *s, size_t n)
if (!result) if (!result)
return 0; return 0;
result[len] = '\0'; result[len] = '\0';
return (char *) strncpy (result, s, len); return (char *) memcpy (result, s, len);
} }
#endif /*HAVE_STRNDUP*/ #endif /*HAVE_STRNDUP*/
@ -467,13 +467,23 @@ extern "C" {
} cdio_funcs_t; } cdio_funcs_t;
typedef struct {
uint16_t u_type;
uint16_t u_flags;
} cdio_header_t;
#define CDIO_HEADER_TYPE_CDIO 0x0000
#define CDIO_HEADER_TYPE_ISO 0x0001
#define CDIO_HEADER_FLAGS_DISABLE_RR_DD 0x0001
/*! Implementation of CdIo type */ /*! Implementation of CdIo type */
struct _CdIo { struct _CdIo {
driver_id_t driver_id; /**< Particular driver opened. */ cdio_header_t header; /**< Internal header - MUST come first. */
cdio_funcs_t op; /**< driver-specific routines handling driver_id_t driver_id; /**< Particular driver opened. */
implementation*/ cdio_funcs_t op; /**< driver-specific routines handling
void *env; /**< environment. Passed to routine above. */ implementation. */
void* env; /**< environment. Passed to routine above. */
}; };
/* This is used in drivers that must keep their own internal /* This is used in drivers that must keep their own internal

View file

@ -61,6 +61,7 @@
/** Implementation of iso9660_t type */ /** Implementation of iso9660_t type */
struct _iso9660_s { struct _iso9660_s {
cdio_header_t header; /**< Internal header - MUST come first. */
CdioDataSource_t *stream; /**< Stream pointer */ CdioDataSource_t *stream; /**< Stream pointer */
bool_3way_t b_xa; /**< true if has XA attributes. */ bool_3way_t b_xa; /**< true if has XA attributes. */
bool_3way_t b_mode2; /**< true if has mode 2, false for mode 1. */ bool_3way_t b_mode2; /**< true if has mode 2, false for mode 1. */
@ -92,8 +93,7 @@ struct _iso9660_s {
filesystem inside that it may be filesystem inside that it may be
different. different.
*/ */
bool b_have_superblock; /**< Superblock has been read in? */ bool b_have_superblock; /**< Superblock has been read in? */
}; };
static long int iso9660_seek_read_framesize (const iso9660_t *p_iso, static long int iso9660_seek_read_framesize (const iso9660_t *p_iso,
@ -174,8 +174,10 @@ iso9660_open_ext_private (const char *psz_path,
{ {
iso9660_t *p_iso = (iso9660_t *) calloc(1, sizeof(iso9660_t)) ; iso9660_t *p_iso = (iso9660_t *) calloc(1, sizeof(iso9660_t)) ;
if (!p_iso) return NULL; if (!p_iso)
return NULL;
p_iso->header.u_type = CDIO_HEADER_TYPE_ISO;
p_iso->stream = cdio_stdio_new( psz_path ); p_iso->stream = cdio_stdio_new( psz_path );
if (NULL == p_iso->stream) if (NULL == p_iso->stream)
goto error; goto error;
@ -778,19 +780,34 @@ iso9660_check_dir_block_end(iso9660_dir_t *p_iso9660_dir, unsigned *offset)
return false; return false;
} }
static inline bool
_iso9660_is_rock_ridge_enabled(void* p_image)
{
cdio_header_t* p_header = (cdio_header_t*)p_image;
if (!p_header)
return false;
if (p_header->u_type == CDIO_HEADER_TYPE_ISO) {
iso9660_t* p_iso = (iso9660_t*)p_image;
return (p_iso->iso_extension_mask & ISO_EXTENSION_ROCK_RIDGE);
}
/* Rock Ridge is always enabled for other types */
return true;
}
static iso9660_stat_t * static iso9660_stat_t *
_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
iso9660_stat_t *last_p_stat, iso9660_stat_t *last_p_stat,
bool_3way_t b_xa, uint8_t u_joliet_level) void* p_image,
bool_3way_t b_xa,
uint8_t u_joliet_level)
{ {
uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir); uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir);
iso711_t i_fname; iso711_t i_fname;
unsigned int stat_len; unsigned int stat_len;
iso9660_stat_t *p_stat = last_p_stat; iso9660_stat_t *p_stat = last_p_stat;
char rr_fname[256] = ""; char rr_fname[256] = "";
int i_rr_fname; int i_rr_fname = 0;
lsn_t extent_lsn; lsn_t extent_lsn;
bool first_extent; bool first_extent;
@ -814,6 +831,9 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
} }
p_stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY) p_stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY)
? _STAT_DIR : _STAT_FILE; ? _STAT_DIR : _STAT_FILE;
/* Ignore Rock Ridge Deep Directory RE entries */
if (p_stat->rr.u_su_fields & ISO_ROCK_SUF_RE)
goto fail;
/* Test for gaps between extents. Important: Use previous .total_size */ /* Test for gaps between extents. Important: Use previous .total_size */
extent_lsn = from_733 (p_iso9660_dir->extent); extent_lsn = from_733 (p_iso9660_dir->extent);
@ -831,8 +851,11 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
/* Only now update .total_size */ /* Only now update .total_size */
p_stat->total_size += from_733(p_iso9660_dir->size); p_stat->total_size += from_733(p_iso9660_dir->size);
p_stat->rr.b3_rock = dunno; /*FIXME should do based on mask */ #ifdef HAVE_ROCK
p_stat->b_xa = false; if (_iso9660_is_rock_ridge_enabled(p_image))
p_stat->rr.b3_rock = dunno;
#endif
p_stat->b_xa = false;
#ifndef DO_NOT_WANT_COMPATIBILITY #ifndef DO_NOT_WANT_COMPATIBILITY
if (first_extent) { if (first_extent) {
@ -842,8 +865,7 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
#endif /* DO_NOT_WANT_COMPATIBILITY */ #endif /* DO_NOT_WANT_COMPATIBILITY */
/* Only resolve the full filename when we're not dealing with extent */ /* Only resolve the full filename when we're not dealing with extent */
if ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0) if ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0) {
{
/* Check if this is the last part of a multiextent file */ /* Check if this is the last part of a multiextent file */
if (!first_extent) { if (!first_extent) {
if (strlen(p_stat->filename) != i_fname || if (strlen(p_stat->filename) != i_fname ||
@ -853,11 +875,9 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
goto fail; goto fail;
} }
} }
i_rr_fname =
#ifdef HAVE_ROCK #ifdef HAVE_ROCK
get_rock_ridge_filename(p_iso9660_dir, rr_fname, p_stat); i_rr_fname = get_rock_ridge_filename(p_iso9660_dir, p_image, rr_fname, p_stat);
#else
0;
#endif #endif
if (i_rr_fname > 0) { if (i_rr_fname > 0) {
@ -1024,7 +1044,7 @@ _fs_stat_root (CdIo_t *p_cdio)
p_iso9660_dir = &(p_env->pvd.root_directory_record) ; p_iso9660_dir = &(p_env->pvd.root_directory_record) ;
#endif #endif
p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, p_cdio,
b_xa, p_env->u_joliet_level); b_xa, p_env->u_joliet_level);
return p_stat; return p_stat;
} }
@ -1046,7 +1066,7 @@ _ifs_stat_root (iso9660_t *p_iso)
#endif #endif
p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL,
p_iso->b_xa, p_iso, p_iso->b_xa,
p_iso->u_joliet_level); p_iso->u_joliet_level);
return p_stat; return p_stat;
} }
@ -1105,8 +1125,8 @@ _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root,
/* Do not register remaining extents of ill file */ /* Do not register remaining extents of ill file */
p_iso9660_stat = NULL; p_iso9660_stat = NULL;
} else { } else {
p_iso9660_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso9660_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso9660_stat,
p_iso9660_stat, dunno, p_env->u_joliet_level); (CdIo_t*)p_cdio, dunno, p_env->u_joliet_level);
if (NULL == p_iso9660_stat) if (NULL == p_iso9660_stat)
skip_following_extents = true; /* Start ill file mode */ skip_following_extents = true; /* Start ill file mode */
} }
@ -1213,7 +1233,7 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root,
if (iso9660_check_dir_block_end(p_iso9660_dir, &offset)) if (iso9660_check_dir_block_end(p_iso9660_dir, &offset))
continue; continue;
p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_stat, p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_stat, p_iso,
p_iso->b_xa, p_iso->u_joliet_level); p_iso->b_xa, p_iso->u_joliet_level);
if (!p_stat) { if (!p_stat) {
@ -1476,8 +1496,8 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[])
p_iso9660_stat = NULL; p_iso9660_stat = NULL;
} else { } else {
p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir,
p_iso9660_stat, dunno, p_iso9660_stat, p_cdio,
p_env->u_joliet_level); dunno, p_env->u_joliet_level);
if (NULL == p_iso9660_stat) if (NULL == p_iso9660_stat)
skip_following_extents = true; /* Start ill file mode */ skip_following_extents = true; /* Start ill file mode */
} }
@ -1570,10 +1590,13 @@ iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[])
} else { } else {
p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir,
p_iso9660_stat, p_iso9660_stat,
p_iso,
p_iso->b_xa, p_iso->b_xa,
p_iso->u_joliet_level); p_iso->u_joliet_level);
if (NULL == p_iso9660_stat) if (NULL == p_iso9660_stat)
skip_following_extents = true; /* Start ill file mode */ skip_following_extents = true; /* Start ill file mode */
else if (p_iso9660_stat->rr.u_su_fields & ISO_ROCK_SUF_RE)
continue; /* Ignore RE entries */
} }
if ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0) if ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0)
skip_following_extents = false; /* Ill or not: The file ends now */ skip_following_extents = false; /* Ill or not: The file ends now */
@ -1752,6 +1775,55 @@ iso9660_ifs_find_lsn(iso9660_t *p_iso, lsn_t i_lsn)
return ret; return ret;
} }
#ifdef HAVE_ROCK
/* Some compilers complain if the prototype is not defined */
iso9660_stat_t *
_iso9660_dd_find_lsn(void* p_image, lsn_t i_lsn);
/* Same as above for Rock Ridge deep directory traversing. */
iso9660_stat_t *
_iso9660_dd_find_lsn(void* p_image, lsn_t i_lsn)
{
cdio_header_t* p_header = (cdio_header_t*)p_image;
char* psz_full_filename = NULL;
void* p_image_dd;
iso9660_readdir_t* f_readdir;
iso9660_stat_t* ret;
size_t size;
switch(p_header->u_type) {
case CDIO_HEADER_TYPE_ISO:
size = sizeof(iso9660_t);
f_readdir = (iso9660_readdir_t*)iso9660_ifs_readdir;
break;
case CDIO_HEADER_TYPE_CDIO:
size = sizeof(CdIo_t);
f_readdir = (iso9660_readdir_t*)iso9660_fs_readdir;
break;
default:
cdio_assert(false);
return NULL;
}
/* Work with a duplicate to allow concurrency. */
p_image_dd = calloc(1, size);
if (!p_image_dd) {
cdio_warn("Memory duplication error");
return NULL;
}
memcpy(p_image_dd, p_image, size);
/* Disable the deep directory flag so we can process all entries */
p_header = (cdio_header_t*)p_image_dd;
p_header->u_flags |= CDIO_HEADER_FLAGS_DISABLE_RR_DD;
ret = find_lsn_recurse(p_image_dd, f_readdir, "/", i_lsn, &psz_full_filename);
if (psz_full_filename != NULL)
free(psz_full_filename);
free(p_image_dd);
return ret;
}
#endif /* HAVE ROCK */
/*! /*!
Given a directory pointer, find the filesystem entry that contains Given a directory pointer, find the filesystem entry that contains
lsn and return information about it. lsn and return information about it.
@ -1860,8 +1932,8 @@ iso_have_rr_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root,
if (iso9660_check_dir_block_end(p_iso9660_dir, &offset)) if (iso9660_check_dir_block_end(p_iso9660_dir, &offset))
continue; continue;
p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, p_iso->b_xa, p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, p_iso,
p_iso->u_joliet_level); p_iso->b_xa, p_iso->u_joliet_level);
have_rr = p_stat->rr.b3_rock; have_rr = p_stat->rr.b3_rock;
if ( have_rr != yep) { if ( have_rr != yep) {
if (strlen(splitpath[0]) == 0) if (strlen(splitpath[0]) == 0)

View file

@ -1,4 +1,5 @@
/* /*
Copyright (C) 2020 Pete Batard <pete@akeo.ie>
Copyright (C) 2005, 2008, 2010-2011, 2014, 2017 Rocky Bernstein Copyright (C) 2005, 2008, 2010-2011, 2014, 2017 Rocky Bernstein
<rocky@gnu.org> <rocky@gnu.org>
@ -40,6 +41,7 @@
#include <cdio/logging.h> #include <cdio/logging.h>
#include <cdio/bytesex.h> #include <cdio/bytesex.h>
#include "filemode.h" #include "filemode.h"
#include "cdio_private.h"
#define CDIO_MKDEV(ma,mi) ((ma)<<16 | (mi)) #define CDIO_MKDEV(ma,mi) ((ma)<<16 | (mi))
@ -48,6 +50,10 @@ iso_rock_nm_flag_t iso_rock_nm_flag;
iso_rock_sl_flag_t iso_rock_sl_flag; iso_rock_sl_flag_t iso_rock_sl_flag;
iso_rock_tf_flag_t iso_rock_tf_flag; iso_rock_tf_flag_t iso_rock_tf_flag;
/* Used by get_rock_ridge_filename() */
extern iso9660_stat_t*
_iso9660_dd_find_lsn(void* p_image, lsn_t i_lsn);
/* Our own realloc routine tailored for the iso9660_stat_t symlink /* Our own realloc routine tailored for the iso9660_stat_t symlink
field. I can't figure out how to make realloc() work without field. I can't figure out how to make realloc() work without
valgrind complaint. valgrind complaint.
@ -142,12 +148,22 @@ realloc_symlink(/*in/out*/ iso9660_stat_t *p_stat, uint8_t i_grow)
} \ } \
} }
/* Indicates if we should process deep directory entries */
static inline bool
is_rr_dd_enabled(void * p_image) {
cdio_header_t* p_header = (cdio_header_t*)p_image;
if (!p_header)
return false;
return !(p_header->u_flags & CDIO_HEADER_FLAGS_DISABLE_RR_DD);
}
/*! /*!
Get Get
@return length of name field; 0: not found, -1: to be ignored @return length of name field; 0: not found, -1: to be ignored
*/ */
int int
get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir, get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
/*in*/ void * p_image,
/*out*/ char * psz_name, /*out*/ char * psz_name,
/*in/out*/ iso9660_stat_t *p_stat) /*in/out*/ iso9660_stat_t *p_stat)
{ {
@ -158,7 +174,8 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
int i_namelen = 0; int i_namelen = 0;
int truncate=0; int truncate=0;
if (!p_stat || nope == p_stat->rr.b3_rock) return 0; if (!p_stat || nope == p_stat->rr.b3_rock)
return 0;
*psz_name = 0; *psz_name = 0;
SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len); SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len);
@ -172,19 +189,21 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
rr = (iso_extension_record_t *) chr; rr = (iso_extension_record_t *) chr;
sig = *chr+(*(chr+1) << 8); sig = *chr+(*(chr+1) << 8);
/* We used to check for some vaid values of SIG, specifically /* We used to check for some valid values of SIG, specifically
SP, CE, ER, RR, PX, PN, SL, NM, CL, PL, TF, and ZF. SP, CE, ER, RR, PX, PN, SL, NM, CL, PL, TF, and ZF.
However there are various extensions to this set. So we However there are various extensions to this set. So we
skip checking now. skip checking now.
*/ */
if (rr->len == 0) goto out; /* Something got screwed up here */ if (rr->len == 0)
goto out; /* Something got screwed up here */
chr += rr->len; chr += rr->len;
len -= rr->len; len -= rr->len;
switch(sig){ switch(sig) {
case SIG('S','P'): case SIG('S','P'):
CHECK_SP(goto out); CHECK_SP(goto out);
p_stat->rr.u_su_fields |= ISO_ROCK_SUF_SP;
break; break;
case SIG('C','E'): case SIG('C','E'):
{ {
@ -195,19 +214,21 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
break; break;
} }
CHECK_CE; CHECK_CE;
p_stat->rr.u_su_fields |= ISO_ROCK_SUF_CE;
break; break;
case SIG('E','R'): case SIG('E','R'):
p_stat->rr.b3_rock = yep;
cdio_debug("ISO 9660 Extensions: "); cdio_debug("ISO 9660 Extensions: ");
{ {
int p; int p;
for(p=0;p<rr->u.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]); for (p=0; p < rr->u.ER.len_id; p++)
cdio_debug("%c", rr->u.ER.data[p]);
} }
break; break;
case SIG('N','M'): case SIG('N','M'):
/* Alternate name */ /* Alternate name */
p_stat->rr.b3_rock = yep; p_stat->rr.u_su_fields |= ISO_ROCK_SUF_NM;
if (truncate) break; if (truncate)
break;
if (rr->u.NM.flags & ISO_ROCK_NM_PARENT) { if (rr->u.NM.flags & ISO_ROCK_NM_PARENT) {
i_namelen = sizeof(".."); i_namelen = sizeof("..");
strncat(psz_name, "..", i_namelen); strncat(psz_name, "..", i_namelen);
@ -235,7 +256,7 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks); p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks);
p_stat->rr.st_uid = from_733(rr->u.PX.st_uid); p_stat->rr.st_uid = from_733(rr->u.PX.st_uid);
p_stat->rr.st_gid = from_733(rr->u.PX.st_gid); p_stat->rr.st_gid = from_733(rr->u.PX.st_gid);
p_stat->rr.b3_rock = yep; p_stat->rr.u_su_fields |= ISO_ROCK_SUF_PX;
break; break;
case SIG('S','L'): case SIG('S','L'):
{ {
@ -246,6 +267,7 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
slen = rr->len - 5; slen = rr->len - 5;
p_sl = &rr->u.SL.link; p_sl = &rr->u.SL.link;
p_stat->rr.i_symlink = symlink_len; p_stat->rr.i_symlink = symlink_len;
p_stat->rr.u_su_fields |= ISO_ROCK_SUF_SL;
while (slen > 1){ while (slen > 1){
rootflag = 0; rootflag = 0;
switch(p_sl->flags &~1){ switch(p_sl->flags &~1){
@ -294,9 +316,6 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
realloc_symlink(p_stat, 1); realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[symlink_len]='\0'; p_stat->rr.psz_symlink[symlink_len]='\0';
break; break;
case SIG('R','E'):
free(buffer);
return -1;
case SIG('T','F'): case SIG('T','F'):
/* Time stamp(s) for a file */ /* Time stamp(s) for a file */
{ {
@ -308,217 +327,56 @@ get_rock_ridge_filename(iso9660_dir_t * p_iso9660_dir,
add_time(ISO_ROCK_TF_BACKUP, backup); add_time(ISO_ROCK_TF_BACKUP, backup);
add_time(ISO_ROCK_TF_EXPIRATION, expiration); add_time(ISO_ROCK_TF_EXPIRATION, expiration);
add_time(ISO_ROCK_TF_EFFECTIVE, effective); add_time(ISO_ROCK_TF_EFFECTIVE, effective);
p_stat->rr.b3_rock = yep; p_stat->rr.u_su_fields |= ISO_ROCK_SUF_TF;
break; break;
} }
default:
break;
}
}
}
free(buffer);
return i_namelen; /* If 0, this file did not have a NM field */
out:
free(buffer);
return 0;
}
static int
parse_rock_ridge_stat_internal(iso9660_dir_t *p_iso9660_dir,
iso9660_stat_t *p_stat, int regard_xa)
{
int len;
unsigned char * chr;
int symlink_len = 0;
CONTINUE_DECLS;
if (nope == p_stat->rr.b3_rock) return 0;
SETUP_ROCK_RIDGE(p_iso9660_dir, chr, len);
if (regard_xa)
{
chr+=14;
len-=14;
if (len<0) len=0;
}
/* repeat:*/
{
int sig;
iso_extension_record_t * rr;
int rootflag;
while (len > 1){ /* There may be one byte for padding somewhere */
rr = (iso_extension_record_t *) chr;
if (rr->len == 0) goto out; /* Something got screwed up here */
sig = from_721(*chr);
chr += rr->len;
len -= rr->len;
switch(sig){
case SIG('S','P'):
CHECK_SP(goto out);
break;
case SIG('C','E'):
CHECK_CE;
break;
case SIG('E','R'):
p_stat->rr.b3_rock = yep;
cdio_debug("ISO 9660 Extensions: ");
{ int p;
for(p=0;p<rr->u.ER.len_id;p++) cdio_debug("%c",rr->u.ER.data[p]);
}
break;
case SIG('P','X'):
p_stat->rr.st_mode = from_733(rr->u.PX.st_mode);
p_stat->rr.st_nlinks = from_733(rr->u.PX.st_nlinks);
p_stat->rr.st_uid = from_733(rr->u.PX.st_uid);
p_stat->rr.st_gid = from_733(rr->u.PX.st_gid);
break;
case SIG('P','N'):
/* Device major,minor number */
{ int32_t high, low;
high = from_733(rr->u.PN.dev_high);
low = from_733(rr->u.PN.dev_low);
/*
* The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
* then the high field is unused, and the device number is completely
* stored in the low field. Some writers may ignore this subtlety,
* and as a result we test to see if the entire device number is
* stored in the low field, and use that.
*/
if((low & ~0xff) && high == 0) {
p_stat->rr.i_rdev = CDIO_MKDEV(low >> 8, low & 0xff);
} else {
p_stat->rr.i_rdev = CDIO_MKDEV(high, low);
}
}
break;
case SIG('T','F'):
/* Time stamp(s) for a file */
{
int cnt = 0;
add_time(ISO_ROCK_TF_CREATE, create);
add_time(ISO_ROCK_TF_MODIFY, modify);
add_time(ISO_ROCK_TF_ACCESS, access);
add_time(ISO_ROCK_TF_ATTRIBUTES, attributes);
add_time(ISO_ROCK_TF_BACKUP, backup);
add_time(ISO_ROCK_TF_EXPIRATION, expiration);
add_time(ISO_ROCK_TF_EFFECTIVE, effective);
p_stat->rr.b3_rock = yep;
break;
}
case SIG('S','L'):
{
/* Symbolic link */
uint8_t slen;
iso_rock_sl_part_t * p_sl;
iso_rock_sl_part_t * p_oldsl;
slen = rr->len - 5;
p_sl = &rr->u.SL.link;
p_stat->rr.i_symlink = symlink_len;
while (slen > 1){
rootflag = 0;
switch(p_sl->flags &~1){
case 0:
realloc_symlink(p_stat, p_sl->len);
if (p_sl->len)
memcpy(&(p_stat->rr.psz_symlink[p_stat->rr.i_symlink]),
p_sl->text, p_sl->len);
p_stat->rr.i_symlink += p_sl->len;
break;
case 4:
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.';
/* continue into next case. */
case 2:
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '.';
break;
case 8:
rootflag = 1;
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/';
p_stat->rr.i_symlink++;
break;
default:
cdio_warn("Symlink component flag not implemented");
}
slen -= p_sl->len + 2;
p_oldsl = p_sl;
p_sl = (iso_rock_sl_part_t *) (((char *) p_sl) + p_sl->len + 2);
if (slen < 2) {
if (((rr->u.SL.flags & 1) != 0) && ((p_oldsl->flags & 1) == 0))
p_stat->rr.i_symlink += 1;
break;
}
/*
* If this component record isn't continued, then append a '/'.
*/
if (!rootflag && (p_oldsl->flags & 1) == 0) {
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[p_stat->rr.i_symlink++] = '/';
}
}
}
symlink_len = p_stat->rr.i_symlink;
realloc_symlink(p_stat, 1);
p_stat->rr.psz_symlink[symlink_len]='\0';
break;
case SIG('R','E'):
cdio_warn("Attempt to read p_stat for relocated directory");
goto out;
#ifdef FINISHED
case SIG('C','L'): case SIG('C','L'):
/* Child Link for a deep directory */
if (!is_rr_dd_enabled(p_image))
break;
{ {
iso9660_stat_t * reloc; iso9660_stat_t* target = NULL;
ISOFS_I(p_stat)->i_first_extent = from_733(rr->u.CL.location); p_stat->rr.u_su_fields |= ISO_ROCK_SUF_CL;
reloc = isofs_iget(p_stat->rr.i_sb, p_stat->rr.i_first_extent, 0); target = _iso9660_dd_find_lsn(p_image, from_733(rr->u.PL.location));
if (!reloc) if (!target) {
goto out; cdio_warn("Could not get Rock Ridge deep directory child");
p_stat->rr.st_mode = reloc->st_mode; break;
p_stat->rr.st_nlinks = reloc->st_nlinks; }
p_stat->rr.st_uid = reloc->st_uid; memcpy(p_stat, target, sizeof(iso9660_stat_t));
p_stat->rr.st_gid = reloc->st_gid; /* Prevent the symlink from being freed on the duplicated struct */
p_stat->rr.i_rdev = reloc->i_rdev; target->rr.psz_symlink = NULL;
p_stat->rr.i_symlink = reloc->i_symlink; iso9660_stat_free(target);
p_stat->rr.i_blocks = reloc->i_blocks;
p_stat->rr.i_atime = reloc->i_atime;
p_stat->rr.i_ctime = reloc->i_ctime;
p_stat->rr.i_mtime = reloc->i_mtime;
iput(reloc);
} }
break; break;
#endif case SIG('P','L'):
/* Parent link of a deep directory */
if (is_rr_dd_enabled(p_image))
p_stat->rr.u_su_fields |= ISO_ROCK_SUF_PL;
break;
case SIG('R','E'):
/* Relocated entry for a deep directory */
if (is_rr_dd_enabled(p_image))
p_stat->rr.u_su_fields |= ISO_ROCK_SUF_RE;
break;
case SIG('S','F'):
/* Sparse File */
p_stat->rr.u_su_fields |= ISO_ROCK_SUF_SF;
cdio_warn("Rock Ridge Sparse File detected");
break;
default: default:
break; break;
} }
} }
} }
out: free(buffer);
if (p_stat->rr.u_su_fields & ISO_ROCK_SUF_FORMAL)
p_stat->rr.b3_rock = yep;
return i_namelen; /* If 0, this file did not have a NM field */
out:
free(buffer); free(buffer);
return 0; return 0;
} }
int
parse_rock_ridge_stat(iso9660_dir_t *p_iso9660_dir,
/*out*/ iso9660_stat_t *p_stat)
{
int result;
if (!p_stat) return 0;
result = parse_rock_ridge_stat_internal(p_iso9660_dir, p_stat, 0);
/* if Rock-Ridge flag was reset and we didn't look for attributes
* behind eventual XA attributes, have a look there */
if (0xFF == p_stat->rr.s_rock_offset && nope != p_stat->rr.b3_rock) {
result = parse_rock_ridge_stat_internal(p_iso9660_dir, p_stat, 14);
}
return result;
}
#define BUF_COUNT 16 #define BUF_COUNT 16
#define BUF_SIZE sizeof("drwxrwxrwx") #define BUF_SIZE sizeof("drwxrwxrwx")

View file

@ -1052,6 +1052,7 @@ static void DisplayISOProps(void)
PRINT_ISO_PROP(img_report.has_4GB_file, " Has a >4GB file"); PRINT_ISO_PROP(img_report.has_4GB_file, " Has a >4GB file");
PRINT_ISO_PROP(img_report.has_long_filename, " Has a >64 chars filename"); PRINT_ISO_PROP(img_report.has_long_filename, " Has a >64 chars filename");
PRINT_ISO_PROP(img_report.has_deep_directories, " Has a Rock Ridge deep directory");
PRINT_ISO_PROP(HAS_SYSLINUX(img_report), " Uses: Syslinux/Isolinux v%s", img_report.sl_version_str); PRINT_ISO_PROP(HAS_SYSLINUX(img_report), " Uses: Syslinux/Isolinux v%s", img_report.sl_version_str);
if (HAS_SYSLINUX(img_report) && (SL_MAJOR(img_report.sl_version) < 5)) { if (HAS_SYSLINUX(img_report) && (SL_MAJOR(img_report.sl_version) < 5)) {
for (i = 0; i<NB_OLD_C32; i++) { for (i = 0; i<NB_OLD_C32; i++) {

View file

@ -338,6 +338,7 @@ typedef struct {
uint8_t has_symlinks; uint8_t has_symlinks;
BOOLEAN has_4GB_file; BOOLEAN has_4GB_file;
BOOLEAN has_long_filename; BOOLEAN has_long_filename;
BOOLEAN has_deep_directories;
BOOLEAN has_bootmgr; BOOLEAN has_bootmgr;
BOOLEAN has_bootmgr_efi; BOOLEAN has_bootmgr_efi;
BOOLEAN has_autorun; BOOLEAN has_autorun;

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.11.1658" CAPTION "Rufus 3.11.1659"
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
@ -395,8 +395,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,11,1658,0 FILEVERSION 3,11,1659,0
PRODUCTVERSION 3,11,1658,0 PRODUCTVERSION 3,11,1659,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -414,13 +414,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.11.1658" VALUE "FileVersion", "3.11.1659"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2020 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2020 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.11.exe" VALUE "OriginalFilename", "rufus-3.11.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.11.1658" VALUE "ProductVersion", "3.11.1659"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"