VISO: Automatically disable version suffixes upon detecting Windows NT El Torito boot structure

This commit is contained in:
RichardG867
2022-11-21 16:23:42 -03:00
parent 0f76828663
commit 711eaf5bdd

View File

@@ -115,7 +115,7 @@ typedef struct _viso_entry_ {
typedef struct {
uint64_t vol_size_offsets[2], pt_meta_offsets[2];
int format, flags;
int format, use_version_suffix : 1;
size_t metadata_sectors, all_sectors, entry_map_size, sector_size, file_fifo_pos;
uint8_t *metadata;
@@ -470,7 +470,7 @@ viso_fill_time(uint8_t *data, time_t time, int format, int longform)
}
static int
viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int flags, int type)
viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, viso_t *viso, int type)
{
uint8_t *p = data, *q, *r;
@@ -482,11 +482,11 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int flags,
if (entry->stats.st_mtime < 0)
pclog("VISO: Warning: Windows returned st_mtime %lld on file [%s]\n", (long long) entry->stats.st_mtime, entry->path);
#endif
p += viso_fill_time(p, entry->stats.st_mtime, format, 0); /* time */
*p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */
p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* time */
*p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */
VISO_SKIP(p, 2 + (format <= VISO_FORMAT_HSF)); /* file unit size (reserved on HSF), interleave gap size (HSF/ISO) and skip factor (HSF only) */
VISO_LBE_16(p, 1); /* volume sequence number */
VISO_SKIP(p, 2 + (viso->format <= VISO_FORMAT_HSF)); /* file unit size (reserved on HSF), interleave gap size (HSF/ISO) and skip factor (HSF only) */
VISO_LBE_16(p, 1); /* volume sequence number */
switch (type) {
case VISO_DIR_CURRENT:
@@ -496,7 +496,7 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int flags,
*p++ = (type == VISO_DIR_PARENT) ? 1 : 0; /* magic value corresponding to . or .. */
/* Fill Rock Ridge Extension Record for the root directory's . entry. */
if ((type == VISO_DIR_CURRENT_ROOT) && (format >= VISO_FORMAT_ISO_LFN)) {
if ((type == VISO_DIR_CURRENT_ROOT) && (viso->format >= VISO_FORMAT_ISO_LFN)) {
*p++ = 'E';
*p++ = 'R';
*p++ = 8 + (sizeof(rr_eid) - 1) + (sizeof(rr_edesc) - 1); /* length */
@@ -522,8 +522,8 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int flags,
*q = strlen(entry->name_short);
memcpy(p, entry->name_short, *q); /* file ID */
p += *q;
if ((format >= VISO_FORMAT_ISO) && !S_ISDIR(entry->stats.st_mode)) {
*p++ = ';'; /* version suffix for files (ISO only?) */
if (viso->use_version_suffix && !S_ISDIR(entry->stats.st_mode)) {
*p++ = ';'; /* version suffix for files (ISO only, except for Windows NT SETUPLDR.BIN El Torito hack) */
*p++ = '1';
*q += 2;
}
@@ -532,7 +532,7 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int flags,
*p++ = 0;
/* Fill Rock Ridge data. */
if (format >= VISO_FORMAT_ISO_LFN) {
if (viso->format >= VISO_FORMAT_ISO_LFN) {
*p++ = 'R'; /* RR = present Rock Ridge entries (only documented by RRIP revision 1.09!) */
*p++ = 'R';
*p++ = 5; /* length */
@@ -588,14 +588,14 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int flags,
*p++ = times; /* flags */
#ifdef st_birthtime
if (times & (1 << 0))
p += viso_fill_time(p, entry->stats.st_birthtime, format, 0); /* creation */
p += viso_fill_time(p, entry->stats.st_birthtime, viso->format, 0); /* creation */
#endif
if (times & (1 << 1))
p += viso_fill_time(p, entry->stats.st_mtime, format, 0); /* modify */
p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* modify */
if (times & (1 << 2))
p += viso_fill_time(p, entry->stats.st_atime, format, 0); /* access */
p += viso_fill_time(p, entry->stats.st_atime, viso->format, 0); /* access */
if (times & (1 << 3))
p += viso_fill_time(p, entry->stats.st_ctime, format, 0); /* attributes */
p += viso_fill_time(p, entry->stats.st_ctime, viso->format, 0); /* attributes */
*r += p - r; /* add to length */
}
@@ -764,8 +764,9 @@ viso_init(const char *dirname, int *error)
*error = 1;
if (viso == NULL)
goto end;
viso->sector_size = VISO_SECTOR_SIZE;
viso->format = VISO_FORMAT_ISO_LFN;
viso->sector_size = VISO_SECTOR_SIZE;
viso->format = VISO_FORMAT_ISO_LFN;
viso->use_version_suffix = (viso->format >= VISO_FORMAT_ISO); /* cleared later if required */
/* Prepare temporary data buffers. */
data = calloc(2, viso->sector_size);
@@ -815,7 +816,7 @@ viso_init(const char *dirname, int *error)
/* Iterate through this directory's children to determine the entry array size. */
size_t children_count = 3; /* include terminator, . and .. */
if (dirp) { /* create empty directory if opendir failed */
if (dirp) { /* create empty directory if opendir failed */
while ((readdir_entry = readdir(dirp))) {
/* Ignore . and .. pseudo-directories. */
if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || (*((uint16_t *) &readdir_entry->d_name[1]) == '.')))
@@ -896,7 +897,7 @@ viso_init(const char *dirname, int *error)
if (dir == eltorito_dir) {
if (!stricmp(readdir_entry->d_name, "Boot-NoEmul.img")) {
eltorito_type = 0x00;
have_eltorito_entry:
have_eltorito_entry:
if (eltorito_entry)
eltorito_others_present = 1; /* flag that the boot code directory contains other files */
eltorito_entry = entry;
@@ -915,6 +916,14 @@ viso_init(const char *dirname, int *error)
} else {
eltorito_others_present = 1; /* flag that the boot code directory contains other files */
}
} else {
/* Disable version suffixes if this structure appears to contain the Windows NT
El Torito boot code, which is known not to tolerate suffixed file names. */
if (eltorito_dir && /* El Torito directory present? */
(eltorito_type == 0x00) && /* El Torito directory not checked yet, or confirmed to contain non-emulation boot code? */
(dir->parent == viso->root_dir) && /* one subdirectory deep? (I386 for instance) */
!stricmp(readdir_entry->d_name, "SETUPLDR.BIN")) /* SETUPLDR.BIN present? */
viso->use_version_suffix = 0;
}
} else if ((dir == viso->root_dir) && !stricmp(readdir_entry->d_name, "[BOOT]")) {
/* Set this as the directory containing El Torito boot code. */
@@ -969,7 +978,7 @@ next_dir:
tzset();
time_t now = time(NULL);
if (viso->format >= VISO_FORMAT_ISO) /* timezones are ISO only */
tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4);
tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4);
/* Get root directory basename for the volume ID. */
char *basename = path_get_filename(viso->root_dir->path);
@@ -1025,7 +1034,7 @@ next_dir:
VISO_SKIP(p, 24 + (16 * (viso->format <= VISO_FORMAT_HSF))); /* PT size, LE PT offset, optional LE PT offset (three on HSF), BE PT offset, optional BE PT offset (three on HSF) */
viso->root_dir->dr_offsets[i] = ftello64(viso->tf.file) + (p - data);
p += viso_fill_dir_record(p, viso->root_dir, viso->format, viso->flags, VISO_DIR_CURRENT); /* root directory */
p += viso_fill_dir_record(p, viso->root_dir, viso, VISO_DIR_CURRENT); /* root directory */
if (i) {
viso_write_wstring((uint16_t *) p, L"", 64, VISO_CHARSET_D); /* volume set ID */
@@ -1322,7 +1331,7 @@ next_dir:
((dir_type == VISO_DIR_PARENT) ? ".." : ((dir_type < VISO_DIR_PARENT) ? "." : (i ? entry->basename : entry->name_short))));
/* Fill directory record. */
viso_fill_dir_record(data, entry, viso->format, viso->flags, dir_type);
viso_fill_dir_record(data, entry, viso, dir_type);
/* Entries cannot cross sector boundaries, so pad to the next sector if needed. */
write = viso->sector_size - (ftello64(viso->tf.file) % viso->sector_size);