diff --git a/src/iso.c b/src/iso.c index 8574c71f..cbecbdd5 100644 --- a/src/iso.c +++ b/src/iso.c @@ -498,7 +498,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) CdioListNode_t* p_entnode; iso9660_stat_t *p_statbuf; CdioList_t* p_entlist; - size_t i; + size_t i, j; lsn_t lsn; int64_t i_file_length; @@ -552,7 +552,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) if (iso_extract_files(p_iso, psz_iso_name)) goto out; } else { - i_file_length = p_statbuf->size; + i_file_length = p_statbuf->total_size; if (check_iso_props(psz_path, i_file_length, psz_basename, psz_fullpath, &props)) { continue; } @@ -586,24 +586,27 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) uprintf(stupid_antivirus); else goto out; - } else for (i=0; i_file_length>0; i++) { - if (FormatStatus) goto out; - memset(buf, 0, ISO_BLOCKSIZE); - lsn = p_statbuf->lsn + (lsn_t)i; - if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { - uprintf(" Error reading ISO9660 file %s at LSN %lu", - psz_iso_name, (long unsigned int)lsn); - goto out; + } else for (j=0; jextents; j++) { + i_file_length = p_statbuf->size[j]; + for (i=0; i_file_length>0; i++) { + if (FormatStatus) goto out; + memset(buf, 0, ISO_BLOCKSIZE); + lsn = p_statbuf->lsn[j] + (lsn_t)i; + if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { + uprintf(" Error reading ISO9660 file %s at LSN %lu", + psz_iso_name, (long unsigned int)lsn); + goto out; + } + buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE); + ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)); + if (!r) { + uprintf(" Error writing file: %s", WindowsErrorString()); + goto out; + } + i_file_length -= ISO_BLOCKSIZE; + if (nb_blocks++ % PROGRESS_THRESHOLD == 0) + UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } - buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE); - ISO_BLOCKING(r = WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)); - if (!r) { - uprintf(" Error writing file: %s", WindowsErrorString()); - goto out; - } - i_file_length -= ISO_BLOCKSIZE; - if (nb_blocks++ % PROGRESS_THRESHOLD == 0) - UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks); } if (preserve_timestamps) { LPFILETIME ft = to_filetime(mktime(&p_statbuf->tm)); @@ -944,7 +947,7 @@ out: int64_t ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file, DWORD attributes) { - size_t i; + size_t i, j; ssize_t read_size; int64_t file_length, r = 0; char buf[UDF_BLOCKSIZE]; @@ -1009,21 +1012,23 @@ try_iso: goto out; } - file_length = p_statbuf->size; - for (i = 0; file_length > 0; i++) { - memset(buf, 0, ISO_BLOCKSIZE); - lsn = p_statbuf->lsn + (lsn_t)i; - if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { - uprintf(" Error reading ISO9660 file %s at LSN %lu", iso_file, (long unsigned int)lsn); - goto out; + for (j = 0; j < p_statbuf->extents; j++) { + file_length = p_statbuf->size[j]; + for (i = 0; file_length > 0; i++) { + memset(buf, 0, ISO_BLOCKSIZE); + lsn = p_statbuf->lsn[j] + (lsn_t)i; + if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { + uprintf(" Error reading ISO9660 file %s at LSN %lu", iso_file, (long unsigned int)lsn); + goto out; + } + buf_size = (DWORD)MIN(file_length, ISO_BLOCKSIZE); + if (!WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)) { + uprintf(" Error writing file %s: %s", dest_file, WindowsErrorString()); + goto out; + } + file_length -= ISO_BLOCKSIZE; + r += ISO_BLOCKSIZE; } - buf_size = (DWORD)MIN(file_length, ISO_BLOCKSIZE); - if (!WriteFileWithRetry(file_handle, buf, buf_size, &wr_size, WRITE_RETRIES)) { - uprintf(" Error writing file %s: %s", dest_file, WindowsErrorString()); - goto out; - } - file_length -= ISO_BLOCKSIZE; - r += ISO_BLOCKSIZE; } out: @@ -1092,8 +1097,8 @@ try_iso: uprintf("Could not get ISO-9660 file information for file %s", wim_path); goto out; } - if (iso9660_iso_seek_read(p_iso, buf, p_statbuf->lsn, 1) != ISO_BLOCKSIZE) { - uprintf("Error reading ISO-9660 file %s at LSN %lu", wim_path, (long unsigned int)p_statbuf->lsn); + if (iso9660_iso_seek_read(p_iso, buf, p_statbuf->lsn[0], 1) != ISO_BLOCKSIZE) { + uprintf("Error reading ISO-9660 file %s at LSN %d", wim_path, p_statbuf->lsn[0]); goto out; } r = wim_header[3]; @@ -1190,7 +1195,7 @@ BOOL ExtractEfiImgFiles(const char* dir) if (p_private == NULL) goto out; p_private->p_iso = p_iso; - p_private->lsn = p_statbuf->lsn; + p_private->lsn = p_statbuf->lsn[0]; // Image should be small enough not to use multiextents p_private->sec_start = 0; // Populate our intial buffer if (iso9660_iso_seek_read(p_private->p_iso, p_private->buf, p_private->lsn, ISO_NB_BLOCKS) != ISO_NB_BLOCKS * ISO_BLOCKSIZE) { diff --git a/src/libcdio/cdio/iso9660.h b/src/libcdio/cdio/iso9660.h index 829ab1a6..22d73942 100644 --- a/src/libcdio/cdio/iso9660.h +++ b/src/libcdio/cdio/iso9660.h @@ -156,6 +156,9 @@ extern enum iso_vd_enum_s { /*! \brief Maximum number of characters in a volume-set id. */ #define ISO_MAX_VOLUMESET_ID 128 +/*! \brief Maximum number of multi file extent licdio supports. */ +#define ISO_MAX_MULTIEXTENT 8 + /*! String inside frame which identifies an ISO 9660 filesystem. This string is the "id" field of an iso9660_pvd_t or an iso9660_svd_t. */ @@ -517,17 +520,19 @@ PRAGMA_END_PACKED */ struct iso9660_stat_s { /* big endian!! */ - iso_rock_statbuf_t rr; /**< Rock Ridge-specific fields */ + iso_rock_statbuf_t rr; /**< Rock Ridge-specific fields */ struct tm tm; /**< time on entry - FIXME merge with one of entries above, like ctime? */ - lsn_t lsn; /**< start logical sector number */ - uint32_t size; /**< total size in bytes */ - uint32_t secsize; /**< number of sectors allocated */ + uint64_t total_size; /**< total size in bytes */ + uint8_t extents; /**< number of multiextents */ + lsn_t lsn[ISO_MAX_MULTIEXTENT]; /**< start logical sector number for each extent */ + uint32_t size[ISO_MAX_MULTIEXTENT]; /**< size of each extent */ + uint32_t secsize[ISO_MAX_MULTIEXTENT]; /**< number of sectors allocated for each extent*/ iso9660_xa_t xa; /**< XA attributes */ enum { _STAT_FILE = 1, _STAT_DIR = 2 } type; bool b_xa; - char filename[EMPTY_ARRAY_SIZE]; /**< filename */ + char filename[EMPTY_ARRAY_SIZE]; /**< filename */ }; /** A mask used in iso9660_ifs_read_vd which allows what kinds diff --git a/src/libcdio/iso9660/iso9660_fs.c b/src/libcdio/iso9660/iso9660_fs.c index 646daaaf..c0bd2249 100644 --- a/src/libcdio/iso9660/iso9660_fs.c +++ b/src/libcdio/iso9660/iso9660_fs.c @@ -709,14 +709,17 @@ iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, lsn_t start, static iso9660_stat_t * -_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, - uint8_t u_joliet_level) +_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, + iso9660_stat_t *last_p_stat, + bool_3way_t b_xa, uint8_t u_joliet_level) { uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir); iso711_t i_fname; unsigned int stat_len; - iso9660_stat_t *p_stat; + iso9660_stat_t *p_stat = last_p_stat; bool err; + char rr_fname[256] = ""; + int i_rr_fname; if (!dir_len) return NULL; @@ -725,7 +728,9 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */ stat_len = sizeof(iso9660_stat_t)+i_fname+2; - p_stat = calloc(1, stat_len); + /* Reuse multiextent p_stat if not NULL */ + if (!p_stat) + p_stat = calloc(1, stat_len); if (!p_stat) { cdio_warn("Couldn't calloc(1, %d)", stat_len); @@ -733,24 +738,33 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, } p_stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY) ? _STAT_DIR : _STAT_FILE; - p_stat->lsn = from_733_with_err (p_iso9660_dir->extent, &err); + p_stat->lsn[p_stat->extents] = from_733_with_err (p_iso9660_dir->extent, &err); if (err) { free(p_stat); return NULL; } - p_stat->size = from_733_with_err (p_iso9660_dir->size, &err); + p_stat->size[p_stat->extents] = from_733_with_err (p_iso9660_dir->size, &err); + p_stat->total_size += p_stat->size[p_stat->extents]; if (err) { free(p_stat); return NULL; } - p_stat->secsize = _cdio_len2blocks (p_stat->size, ISO_BLOCKSIZE); + p_stat->secsize[p_stat->extents] = _cdio_len2blocks (p_stat->size[p_stat->extents], ISO_BLOCKSIZE); p_stat->rr.b3_rock = dunno; /*FIXME should do based on mask */ p_stat->b_xa = false; + /* Only resolve the full filename when we're not dealing with extent */ + if ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0) { - char rr_fname[256] = ""; - - int i_rr_fname = + /* Check if this is the last part of a multiextent file */ + if (p_stat->extents != 0) { + if (strcmp(p_stat->filename, &p_iso9660_dir->filename.str[1]) != 0) { + cdio_warn("Warning: Non consecutive multiextent file parts for '%s'", p_stat->filename); + free(p_stat); + return NULL; + } + } + i_rr_fname = #ifdef HAVE_ROCK get_rock_ridge_filename(p_iso9660_dir, rr_fname, p_stat); #else @@ -797,13 +811,16 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, bool_3way_t b_xa, strncpy (p_stat->filename, &p_iso9660_dir->filename.str[1], i_fname); } } + } else { + /* Use the plain ISO-9660 name when dealing with a multiextent file part */ + strncpy(p_stat->filename, &p_iso9660_dir->filename.str[1], i_fname); } - - if (p_iso9660_dir->file_flags & ISO_MULTIEXTENT) - { - cdio_warn("Can't handle multi-extent file '%s' - Data will be truncated!", p_stat->filename); - free(p_stat); - return NULL; + p_stat->extents++; + if (p_stat->extents > ISO_MAX_MULTIEXTENT) { + cdio_warn("Warning: Too many multiextent file parts for '%s'", p_stat->filename); + free(p_stat->rr.psz_symlink); + free(p_stat); + return NULL; } iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(p_stat->tm)); @@ -927,8 +944,8 @@ _fs_stat_root (CdIo_t *p_cdio) p_iso9660_dir = &(p_env->pvd.root_directory_record) ; #endif - p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, b_xa, - p_env->u_joliet_level); + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, + b_xa, p_env->u_joliet_level); return p_stat; } @@ -948,7 +965,8 @@ _ifs_stat_root (iso9660_t *p_iso) p_iso9660_dir = &(p_iso->pvd.root_directory_record) ; #endif - p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso->b_xa, + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, + p_iso->b_xa, p_iso->u_joliet_level); return p_stat; } @@ -980,18 +998,18 @@ _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, cdio_assert (_root->type == _STAT_DIR); - _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE); + _dirbuf = calloc(1, _root->secsize[0] * ISO_BLOCKSIZE); if (!_dirbuf) { - cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE); + cdio_warn("Couldn't calloc(1, %d)", _root->secsize[0] * ISO_BLOCKSIZE); return NULL; } - if (cdio_read_data_sectors (p_cdio, _dirbuf, _root->lsn, ISO_BLOCKSIZE, - _root->secsize)) + if (cdio_read_data_sectors (p_cdio, _dirbuf, _root->lsn[0], ISO_BLOCKSIZE, + _root->secsize[0])) return NULL; - while (offset < (_root->secsize * ISO_BLOCKSIZE)) + while (offset < (_root->secsize[0] * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_iso9660_stat; @@ -1003,8 +1021,8 @@ _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, continue; } - p_iso9660_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, dunno, - p_env->u_joliet_level); + p_iso9660_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, + dunno, p_env->u_joliet_level); cmp = strcmp(splitpath[0], p_iso9660_stat->filename); @@ -1043,7 +1061,7 @@ _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, offset += iso9660_get_dir_len(p_iso9660_dir); } - cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); + cdio_assert (offset == (_root->secsize[0] * ISO_BLOCKSIZE)); /* not found */ free (_dirbuf); @@ -1054,13 +1072,14 @@ static iso9660_stat_t * _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, char **splitpath) { - unsigned offset = 0; + unsigned offset; uint8_t *_dirbuf = NULL; int ret; + iso9660_stat_t *p_stat = NULL; + iso9660_dir_t *p_iso9660_dir = NULL; if (!splitpath[0]) { - iso9660_stat_t *p_stat; unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1; p_stat = calloc(1, len); cdio_assert (p_stat != NULL); @@ -1077,20 +1096,20 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, cdio_assert (_root->type == _STAT_DIR); - _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE); + _dirbuf = calloc(1, _root->secsize[0] * ISO_BLOCKSIZE); if (!_dirbuf) { - cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE); + cdio_warn("Couldn't calloc(1, %d)", _root->secsize[0] * ISO_BLOCKSIZE); return NULL; } - ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn, _root->secsize); - if (ret!=ISO_BLOCKSIZE*_root->secsize) return NULL; + ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn[0], _root->secsize[0]); + if (ret!=ISO_BLOCKSIZE*_root->secsize[0]) return NULL; - while (offset < (_root->secsize * ISO_BLOCKSIZE)) + for (offset = 0; offset < (_root->secsize[0] * ISO_BLOCKSIZE); + offset += iso9660_get_dir_len(p_iso9660_dir)) { - iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; - iso9660_stat_t *p_stat; + p_iso9660_dir = (void *) &_dirbuf[offset]; int cmp; if (!iso9660_get_dir_len(p_iso9660_dir)) @@ -1099,8 +1118,8 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, continue; } - p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso->b_xa, - p_iso->u_joliet_level); + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_stat, + p_iso->b_xa, p_iso->u_joliet_level); if (!p_stat) { cdio_warn("Bad directory information for %s", splitpath[0]); @@ -1108,6 +1127,10 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, return NULL; } + /* If we have multiextent file parts, loop until the last one */ + if (p_iso9660_dir->file_flags & ISO_MULTIEXTENT) + continue; + cmp = strcmp(splitpath[0], p_stat->filename); if ( 0 != cmp && 0 == p_iso->u_joliet_level @@ -1141,11 +1164,10 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, free(p_stat->rr.psz_symlink); free(p_stat); - - offset += iso9660_get_dir_len(p_iso9660_dir); + p_stat = NULL; } - cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); + cdio_assert (offset == (_root->secsize[0] * ISO_BLOCKSIZE)); /* not found */ free (_dirbuf); @@ -1268,6 +1290,8 @@ CdioList_t * iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], bool b_mode2) { generic_img_private_t *p_env; + iso9660_dir_t *p_iso9660_dir; + iso9660_stat_t *p_iso9660_stat = NULL; iso9660_stat_t *p_stat; if (!p_cdio) return NULL; @@ -1289,24 +1313,23 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], bool b_mode2) uint8_t *_dirbuf = NULL; CdioList_t *retval = _cdio_list_new (); - _dirbuf = calloc(1, p_stat->secsize * ISO_BLOCKSIZE); + _dirbuf = calloc(1, p_stat->secsize[0] * ISO_BLOCKSIZE); if (!_dirbuf) { - cdio_warn("Couldn't calloc(1, %d)", p_stat->secsize * ISO_BLOCKSIZE); + cdio_warn("Couldn't calloc(1, %d)", p_stat->secsize[0] * ISO_BLOCKSIZE); _cdio_list_free (retval, true); return NULL; } - if (cdio_read_data_sectors (p_cdio, _dirbuf, p_stat->lsn, - ISO_BLOCKSIZE, p_stat->secsize)) { + if (cdio_read_data_sectors (p_cdio, _dirbuf, p_stat->lsn[0], + ISO_BLOCKSIZE, p_stat->secsize[0])) { _cdio_list_free (retval, true); return NULL; } - while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) + while (offset < (p_stat->secsize[0] * ISO_BLOCKSIZE)) { - iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; - iso9660_stat_t *p_iso9660_stat; + p_iso9660_dir = (void *) &_dirbuf[offset]; if (!iso9660_get_dir_len(p_iso9660_dir)) { @@ -1314,14 +1337,20 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], bool b_mode2) continue; } - p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, dunno, + p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, + p_iso9660_stat, dunno, p_env->u_joliet_level); - _cdio_list_append (retval, p_iso9660_stat); + if ((p_iso9660_stat) && + ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0)) + { + _cdio_list_append (retval, p_iso9660_stat); + p_iso9660_stat = NULL; + } offset += iso9660_get_dir_len(p_iso9660_dir); } - cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE)); + cdio_assert (offset == (p_stat->secsize[0] * ISO_BLOCKSIZE)); free (_dirbuf); free (p_stat); @@ -1336,6 +1365,8 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[], bool b_mode2) CdioList_t * iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]) { + iso9660_dir_t *p_iso9660_dir; + iso9660_stat_t *p_iso9660_stat = NULL; iso9660_stat_t *p_stat; if (!p_iso) return NULL; @@ -1355,12 +1386,12 @@ iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]) unsigned offset = 0; uint8_t *_dirbuf = NULL; CdioList_t *retval = _cdio_list_new (); - const size_t dirbuf_len = p_stat->secsize * ISO_BLOCKSIZE; + const size_t dirbuf_len = p_stat->secsize[0] * ISO_BLOCKSIZE; if (!dirbuf_len) { - cdio_warn("Invalid directory buffer sector size %u", p_stat->secsize); + cdio_warn("Invalid directory buffer sector size %u", p_stat->secsize[0]); free(p_stat->rr.psz_symlink); free(p_stat); _cdio_list_free (retval, true); @@ -1377,7 +1408,7 @@ iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]) return NULL; } - ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn, p_stat->secsize); + ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn[0], p_stat->secsize[0]); if (ret != dirbuf_len) { _cdio_list_free (retval, true); free(p_stat->rr.psz_symlink); @@ -1388,8 +1419,7 @@ iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]) while (offset < (dirbuf_len)) { - iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; - iso9660_stat_t *p_iso9660_stat; + p_iso9660_dir = (void *) &_dirbuf[offset]; if (!iso9660_get_dir_len(p_iso9660_dir)) { @@ -1397,11 +1427,16 @@ iso9660_ifs_readdir (iso9660_t *p_iso, const char psz_path[]) continue; } - p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, p_iso->b_xa, + p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, + p_iso9660_stat, + p_iso->b_xa, p_iso->u_joliet_level); - - if (p_iso9660_stat) - _cdio_list_append (retval, p_iso9660_stat); + if ((p_iso9660_stat) && + ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0)) + { + _cdio_list_append(retval, p_iso9660_stat); + p_iso9660_stat = NULL; + } offset += iso9660_get_dir_len(p_iso9660_dir); } @@ -1440,6 +1475,7 @@ find_lsn_recurse (void *p_image, iso9660_readdir_t iso9660_readdir, iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); const char *psz_filename = (char *) statbuf->filename; unsigned int len = strlen(psz_path) + strlen(psz_filename)+2; + size_t extent; if (*ppsz_full_filename != NULL) free(*ppsz_full_filename); *ppsz_full_filename = calloc(1, len); @@ -1451,19 +1487,20 @@ find_lsn_recurse (void *p_image, iso9660_readdir_t iso9660_readdir, _cdio_list_append (dirlist, strdup(*ppsz_full_filename)); } - if (statbuf->lsn == lsn) { - const unsigned int len2 = sizeof(iso9660_stat_t)+strlen(statbuf->filename)+1; - iso9660_stat_t *ret_stat = calloc(1, len2); - if (!ret_stat) - { + for (extent = 0; extent < statbuf->extents; extent++) { + if (statbuf->lsn[extent] == lsn) { + const unsigned int len2 = sizeof(iso9660_stat_t)+strlen(statbuf->filename)+1; + iso9660_stat_t *ret_stat = calloc(1, len2); + if (!ret_stat) { _cdio_list_free (dirlist, true); cdio_warn("Couldn't calloc(1, %d)", len2); return NULL; } - memcpy(ret_stat, statbuf, len2); - _cdio_list_free (entlist, true); - _cdio_list_free (dirlist, true); - return ret_stat; + memcpy(ret_stat, statbuf, len2); + _cdio_list_free (entlist, true); + _cdio_list_free (dirlist, true); + return ret_stat; + } } } @@ -1588,17 +1625,17 @@ iso_have_rr_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, cdio_assert (_root->type == _STAT_DIR); - _dirbuf = calloc(1, _root->secsize * ISO_BLOCKSIZE); + _dirbuf = calloc(1, _root->secsize[0] * ISO_BLOCKSIZE); if (!_dirbuf) { - cdio_warn("Couldn't calloc(1, %d)", _root->secsize * ISO_BLOCKSIZE); + cdio_warn("Couldn't calloc(1, %d)", _root->secsize[0] * ISO_BLOCKSIZE); return dunno; } - ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn, _root->secsize); - if (ret!=ISO_BLOCKSIZE*_root->secsize) return false; + ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn[0], _root->secsize[0]); + if (ret!=ISO_BLOCKSIZE*_root->secsize[0]) return false; - while (offset < (_root->secsize * ISO_BLOCKSIZE)) + while (offset < (_root->secsize[0] * ISO_BLOCKSIZE)) { iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; iso9660_stat_t *p_stat; @@ -1609,7 +1646,7 @@ iso_have_rr_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, continue; } - p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, p_iso->b_xa, + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, p_iso->b_xa, p_iso->u_joliet_level); have_rr = p_stat->rr.b3_rock; if ( have_rr != yep) { @@ -1629,7 +1666,7 @@ iso_have_rr_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, } } - cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); + cdio_assert (offset == (_root->secsize[0] * ISO_BLOCKSIZE)); /* not found */ free (_dirbuf); diff --git a/src/rufus.c b/src/rufus.c index c0787c35..903daae9 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -484,9 +484,14 @@ static void SetFSFromISO(void) fs_mask |= 1<