5959#include "_cdio_stdio.h"
6060#include "cdio_private.h"
6161
62+ #define MAX_BOOT_IMAGES 8
63+
6264/** Implementation of iso9660_t type */
6365struct _iso9660_s {
6466 cdio_header_t header ; /**< Internal header - MUST come first. */
@@ -83,6 +85,10 @@ struct _iso9660_s {
8385 be CDIO_CD_FRAMESIZE_RAW (2352) or
8486 M2RAW_SECTOR_SIZE (2336).
8587 */
88+ struct {
89+ uint32_t lsn ; /**< Start LSN of an El-Torito bootable image */
90+ uint32_t num_sectors ; /**< Number of sectors of a bootable image */
91+ } boot_img [MAX_BOOT_IMAGES ];
8692 int i_fuzzy_offset ; /**< Adjustment in bytes to make ISO_STANDARD_ID
8793 ("CD001") come out as ISO_PVD_SECTOR
8894 (frame 16). Normally this should be 0
@@ -505,7 +511,8 @@ iso9660_ifs_read_superblock (iso9660_t *p_iso,
505511 iso_extension_mask_t iso_extension_mask )
506512{
507513 iso9660_svd_t p_svd ; /* Secondary volume descriptor. */
508- int i ;
514+ iso9660_brvd_t * p_brvd = (iso9660_brvd_t * )& p_svd ; /* Boot record volume descriptor. */
515+ int i , j , k ;
509516
510517 if (!p_iso || !iso9660_ifs_read_pvd (p_iso , & (p_iso -> pvd )))
511518 return false;
@@ -516,6 +523,24 @@ iso9660_ifs_read_superblock (iso9660_t *p_iso,
516523 for (i = 1 ; (0 != iso9660_iso_seek_read (p_iso , & p_svd , ISO_PVD_SECTOR + i , 1 )); i ++ ) {
517524 if (ISO_VD_END == from_711 (p_svd .type ) ) /* Last SVD */
518525 break ;
526+ if (iso_extension_mask & ISO_EXTENSION_EL_TORITO ) {
527+ /* Check for an El-Torito boot volume descriptor */
528+ if (ISO_VD_BOOT_RECORD == from_711 (p_svd .type ) &&
529+ (memcmp (p_brvd -> system_id , EL_TORITO_ID , ISO_MAX_SYSTEM_ID ) == 0 )) {
530+ /* Perform very basic parsing of boot entries to fill an image table */
531+ iso9660_br_t br [ISO_BLOCKSIZE / sizeof (iso9660_br_t )];
532+ if (iso9660_iso_seek_read (p_iso , & br , p_brvd -> boot_catalog_sector , 1 ) == ISO_BLOCKSIZE ) {
533+ for (j = 0 , k = 0 ;
534+ j < (ISO_BLOCKSIZE / sizeof (iso9660_br_t )) && k < MAX_BOOT_IMAGES ;
535+ j ++ ) {
536+ if (br [j ].boot_id == 0x88 && br [j ].media_type == 0 ) {
537+ p_iso -> boot_img [k ].lsn = br [j ].image_lsn ;
538+ p_iso -> boot_img [k ++ ].num_sectors = br [j ].num_sectors ;
539+ }
540+ }
541+ }
542+ }
543+ }
519544 if ( ISO_VD_SUPPLEMENTARY == from_711 (p_svd .type ) ) {
520545 /* We're only interested in Joliet => make sure the SVD isn't overwritten */
521546 if (p_iso -> u_joliet_level == 0 )
@@ -1441,6 +1466,28 @@ iso9660_fs_stat_translate (CdIo_t *p_cdio, const char psz_path[])
14411466iso9660_stat_t *
14421467iso9660_ifs_stat_translate (iso9660_t * p_iso , const char psz_path [])
14431468{
1469+ /* Special case for virtual El-Torito boot images ('[BOOT]/#.img') */
1470+ if (psz_path && (strncmp (psz_path , "[BOOT]/" , 7 ) == 0 )) {
1471+ int index = psz_path [7 ] - '0' ;
1472+ iso9660_stat_t * p_stat ;
1473+ if (strlen (psz_path ) < 8 )
1474+ return NULL ;
1475+ if ((psz_path [7 ] < '0' ) || (psz_path [7 ] > '0' + MAX_BOOT_IMAGES - 1 ))
1476+ return NULL ;
1477+ if (p_iso -> boot_img [index ].lsn == 0 || p_iso -> boot_img [index ].num_sectors == 0 )
1478+ return NULL ;
1479+ p_stat = calloc (1 , sizeof (iso9660_stat_t ) + strlen (psz_path ));
1480+ if (!p_stat ) {
1481+ cdio_warn ("Couldn't calloc(1, %d)" , (int )sizeof (iso9660_stat_t ));
1482+ return NULL ;
1483+ }
1484+ p_stat -> lsn = p_iso -> boot_img [index ].lsn ;
1485+ p_stat -> total_size = p_iso -> boot_img [index ].num_sectors * ISO_BLOCKSIZE ;
1486+ p_stat -> type = _STAT_FILE ;
1487+ strcpy (p_stat -> filename , psz_path );
1488+ return p_stat ;
1489+ }
1490+
14441491 return fs_stat_translate (p_iso , (stat_root_t * ) _ifs_stat_root ,
14451492 (stat_traverse_t * ) _fs_iso_stat_traverse ,
14461493 psz_path );
0 commit comments