diff options
| author | Pete Batard <pete@akeo.ie> | 2018-06-05 13:42:37 +0100 |
|---|---|---|
| committer | Pete Batard <pete@akeo.ie> | 2018-06-06 13:52:03 +0100 |
| commit | c93341a28bba1842d7df89d784951eccc18050ff (patch) | |
| tree | f46715776d36119e9259728845b132ee19f0edce | |
| parent | cc93005dc13ee6274077b9dc6c11b6e751793292 (diff) | |
| download | libcdio-c93341a28bba1842d7df89d784951eccc18050ff.tar.gz | |
Add support for ISO9660 multi extent files
This *breaking* change alters the iso9660_stat_s struct an requires
any application processing a statbuf returned by _cdio_list_node_data()
to either:
- update their code to loop through the extents
- replace the lsn and secsize attributes in existing code with lsn[0]
and seczise[0], if they are sure that the ISO9660 image they are
dealing with doesn't use multi extent files. Also if the code is
not compatible with the new 64-bit size attribute, they should use
extsize[0] instead of size.
| -rw-r--r-- | example/extract.c | 36 | ||||
| -rw-r--r-- | example/isofile.c | 29 | ||||
| -rw-r--r-- | example/isofile2.c | 33 | ||||
| -rw-r--r-- | example/isolist.c | 12 | ||||
| -rw-r--r-- | include/cdio/iso9660.h | 18 | ||||
| -rw-r--r-- | lib/iso9660/iso9660_fs.c | 228 | ||||
| -rw-r--r-- | src/iso-read.c | 12 | ||||
| -rw-r--r-- | src/util.c | 8 | ||||
| -rw-r--r-- | test/testisocd.c | 6 | ||||
| -rw-r--r-- | test/testisocd2.c | 8 | ||||
| -rw-r--r-- | test/testisocd_joliet.c | 10 |
11 files changed, 223 insertions, 177 deletions
diff --git a/example/extract.c b/example/extract.c index a9f5a31..314f7b5 100644 --- a/example/extract.c +++ b/example/extract.c @@ -174,9 +174,9 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) CdioListNode_t *p_entnode; iso9660_stat_t *p_statbuf; CdioISO9660FileList_t* p_entlist; - size_t i; + size_t i, j; lsn_t lsn; - int64_t i_file_length; + int64_t i_extent_length; if ((p_iso == NULL) || (psz_path == NULL)) return 1; @@ -210,22 +210,24 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) fprintf(stderr, " Unable to create file\n"); goto out; } - i_file_length = p_statbuf->size; - for (i = 0; i_file_length > 0; i++) { - memset(buf, 0, ISO_BLOCKSIZE); - lsn = p_statbuf->lsn + i; - if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { - fprintf(stderr, " Error reading ISO9660 file %s at LSN %lu\n", - psz_iso_name, (long unsigned int)lsn); - goto out; - } - fwrite(buf, (size_t)MIN(i_file_length, ISO_BLOCKSIZE), 1, fd); - if (ferror(fd)) { - fprintf(stderr, " Error writing file %s: %s\n", psz_iso_name, - strerror(errno)); - goto out; + for (j = 0; j < p_statbuf->extents; j++) { + i_extent_length = p_statbuf->extsize[j]; + for (i = 0; i_extent_length > 0; i++) { + memset(buf, 0, ISO_BLOCKSIZE); + lsn = p_statbuf->lsn[j] + i; + if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) { + fprintf(stderr, " Error reading ISO9660 file %s at LSN %lu\n", + psz_iso_name, (long unsigned int)lsn); + goto out; + } + fwrite(buf, (size_t)MIN(i_extent_length, ISO_BLOCKSIZE), 1, fd); + if (ferror(fd)) { + fprintf(stderr, " Error writing file %s: %s\n", psz_iso_name, + strerror(errno)); + goto out; + } + i_extent_length -= ISO_BLOCKSIZE; } - i_file_length -= ISO_BLOCKSIZE; } fclose(fd); fd = NULL; diff --git a/example/isofile.c b/example/isofile.c index bcfe06a..0efb805 100644 --- a/example/isofile.c +++ b/example/isofile.c @@ -67,7 +67,7 @@ main(int argc, const char *argv[]) { iso9660_stat_t *p_statbuf; FILE *p_outfd; - int i; + int i, j; char const *psz_image; char const *psz_fname; iso9660_t *p_iso; @@ -115,29 +115,26 @@ main(int argc, const char *argv[]) } /* Copy the blocks from the ISO-9660 filesystem to the local filesystem. */ - { - const unsigned int i_blocks = CEILING(p_statbuf->size, ISO_BLOCKSIZE); - for (i = 0; i < i_blocks ; i++) - { + for (j = 0; j < p_statbuf->extents; j++) { + const unsigned int i_blocks = CEILING(p_statbuf->extsize[j], ISO_BLOCKSIZE); + for (i = 0; i < i_blocks ; i++) { char buf[ISO_BLOCKSIZE]; - const lsn_t lsn = p_statbuf->lsn + i; + const lsn_t lsn = p_statbuf->lsn[j] + i; memset (buf, 0, ISO_BLOCKSIZE); - - if ( ISO_BLOCKSIZE != iso9660_iso_seek_read (p_iso, buf, lsn, 1) ) - { + + if ( ISO_BLOCKSIZE != iso9660_iso_seek_read (p_iso, buf, lsn, 1) ) { fprintf(stderr, "Error reading ISO 9660 file %s at LSN %lu\n", psz_fname, (long unsigned int) lsn); my_exit(4); } - + fwrite (buf, ISO_BLOCKSIZE, 1, p_outfd); - - if (ferror (p_outfd)) - { - perror ("fwrite()"); - my_exit(5); - } + + if (ferror (p_outfd)) { + perror ("fwrite()"); + my_exit(5); + } } } diff --git a/example/isofile2.c b/example/isofile2.c index 7148f2f..3c16c30 100644 --- a/example/isofile2.c +++ b/example/isofile2.c @@ -79,7 +79,7 @@ main(int argc, const char *argv[]) { iso9660_stat_t *p_statbuf; FILE *p_outfd; - int i; + int i, j; char const *psz_image; char const *psz_fname; char translated_name[256]; @@ -135,28 +135,27 @@ main(int argc, const char *argv[]) } /* Copy the blocks from the ISO-9660 filesystem to the local filesystem. */ - { - const unsigned int i_blocks = CEILING(p_statbuf->size, ISO_BLOCKSIZE); + for (j = 0; j < p_statbuf->extents; j++) { + const unsigned int i_blocks = CEILING(p_statbuf->extsize[j], ISO_BLOCKSIZE); for (i = 0; i < i_blocks; i ++) { - char buf[ISO_BLOCKSIZE]; - const lsn_t lsn = p_statbuf->lsn + i; + char buf[ISO_BLOCKSIZE]; + const lsn_t lsn = p_statbuf->lsn[j] + i; - memset (buf, 0, ISO_BLOCKSIZE); + memset (buf, 0, ISO_BLOCKSIZE); - if ( 0 != cdio_read_data_sectors (p_cdio, buf, lsn, ISO_BLOCKSIZE, 1) ) - { - fprintf(stderr, "Error reading ISO 9660 file at lsn %lu\n", - (long unsigned int) p_statbuf->lsn); - my_exit(4); - } + if ( 0 != cdio_read_data_sectors (p_cdio, buf, lsn, ISO_BLOCKSIZE, 1) ) { + fprintf(stderr, "Error reading ISO 9660 file at lsn %lu\n", + (long unsigned int) lsn); + my_exit(4); + } - fwrite (buf, ISO_BLOCKSIZE, 1, p_outfd); + fwrite (buf, ISO_BLOCKSIZE, 1, p_outfd); - if (ferror (p_outfd)) { - perror ("fwrite()"); - my_exit(5); - } + if (ferror (p_outfd)) { + perror ("fwrite()"); + my_exit(5); } + } } diff --git a/example/isolist.c b/example/isolist.c index 1168250..94b7a38 100644 --- a/example/isolist.c +++ b/example/isolist.c @@ -101,19 +101,21 @@ main(int argc, const char *argv[]) if (p_entlist) { _CDIO_LIST_FOREACH (p_entnode, p_entlist) { + int i; char filename[4096]; iso9660_stat_t *p_statbuf = (iso9660_stat_t *) _cdio_list_node_data (p_entnode); iso9660_name_translate(p_statbuf->filename, filename); - printf ("%s [LSN %6d] %8u %s%s\n", - _STAT_DIR == p_statbuf->type ? "d" : "-", - p_statbuf->lsn, p_statbuf->size, psz_path, filename); + for (i = 0; i < p_statbuf->extents; i++) { + printf ("%s [LSN %6d] %8u %s%s\n", + _STAT_DIR == p_statbuf->type ? "d" : "-", + p_statbuf->lsn[i], p_statbuf->extsize[i], psz_path, filename); + } } - iso9660_filelist_free(p_entlist); + iso9660_filelist_free(p_entlist); } - iso9660_close(p_iso); return 0; } diff --git a/include/cdio/iso9660.h b/include/cdio/iso9660.h index c653cdb..ce28deb 100644 --- a/include/cdio/iso9660.h +++ b/include/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. */ @@ -529,17 +532,22 @@ typedef CdioList_t CdioISO9660DirList_t; */ 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 size; /**< total size in bytes */ + uint8_t extents; /**< number of multiextents */ + /**v start logical sector number for each extent */ + lsn_t lsn[ISO_MAX_MULTIEXTENT]; + /**v size of each extent */ + uint32_t extsize[ISO_MAX_MULTIEXTENT]; + /**v number of sectors allocated for each extent */ + uint32_t secsize[ISO_MAX_MULTIEXTENT]; 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/lib/iso9660/iso9660_fs.c b/lib/iso9660/iso9660_fs.c index 33f4771..4e6b3df 100644 --- a/lib/iso9660/iso9660_fs.c +++ b/lib/iso9660/iso9660_fs.c @@ -299,8 +299,8 @@ check_pvd (const iso9660_pvd_t *p_pvd, cdio_log_level_t log_level) if (strncmp (p_pvd->id, ISO_STANDARD_ID, strlen (ISO_STANDARD_ID))) { - cdio_log (log_level, "unexpected ID encountered (expected `" - ISO_STANDARD_ID "', got `%.5s')", p_pvd->id); + cdio_log (log_level, "unexpected ID encountered (expected '" + ISO_STANDARD_ID "', got '%.5s')", p_pvd->id); return false; } return true; @@ -777,13 +777,16 @@ iso9660_check_dir_block_end(iso9660_dir_t *p_iso9660_dir, unsigned *offset) 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 = NULL; + iso9660_stat_t *p_stat = last_p_stat; + char rr_fname[256] = ""; + int i_rr_fname; if (!dir_len) return NULL; @@ -792,7 +795,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); @@ -800,16 +805,25 @@ _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 (p_iso9660_dir->extent); - p_stat->size = from_733 (p_iso9660_dir->size); - p_stat->secsize = _cdio_len2blocks (p_stat->size, ISO_BLOCKSIZE); + p_stat->lsn[p_stat->extents] = from_733 (p_iso9660_dir->extent); + p_stat->extsize[p_stat->extents] = from_733 (p_iso9660_dir->size); + p_stat->size += p_stat->extsize[p_stat->extents]; + p_stat->secsize[p_stat->extents] = _cdio_len2blocks (p_stat->extsize[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 @@ -856,8 +870,17 @@ _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_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; + } + p_stat->extents++; iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(p_stat->tm)); @@ -979,8 +1002,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; } @@ -1000,7 +1023,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; } @@ -1032,18 +1056,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; @@ -1052,8 +1076,8 @@ _fs_stat_traverse (const CdIo_t *p_cdio, const iso9660_stat_t *_root, if (iso9660_check_dir_block_end(p_iso9660_dir, &offset)) 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); @@ -1090,7 +1114,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); @@ -1103,11 +1127,12 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, { unsigned offset = 0; uint8_t *_dirbuf = NULL; - int ret; + int ret, cmp; + 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); @@ -1124,30 +1149,29 @@ _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) { + ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn[0], _root->secsize[0]); + if (ret!=ISO_BLOCKSIZE*_root->secsize[0]) { free(_dirbuf); 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; - int cmp; + p_iso9660_dir = (void *) &_dirbuf[offset]; if (iso9660_check_dir_block_end(p_iso9660_dir, &offset)) 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]); @@ -1155,6 +1179,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 @@ -1185,11 +1213,10 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, return ret_stat; } iso9660_stat_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); @@ -1354,6 +1381,8 @@ CdioISO9660FileList_t * iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[]) { 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; @@ -1374,38 +1403,43 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[]) uint8_t *_dirbuf = NULL; CdioISO9660DirList_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); iso9660_stat_free(p_stat); iso9660_dirlist_free(retval); 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])) { iso9660_stat_free(p_stat); iso9660_dirlist_free(retval); 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_check_dir_block_end(p_iso9660_dir, &offset)) 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); iso9660_stat_free(p_stat); @@ -1420,6 +1454,8 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char psz_path[]) CdioISO9660FileList_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; @@ -1438,12 +1474,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]); iso9660_stat_free(p_stat); _cdio_list_free (retval, true, NULL); return NULL; @@ -1458,7 +1494,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, NULL); iso9660_stat_free(p_stat); @@ -1468,21 +1504,21 @@ 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_check_dir_block_end(p_iso9660_dir, &offset)) 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); - else { - cdio_warn("Invalid directory stat at offset %lu", (unsigned long)offset); - break; - } + 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); } @@ -1530,6 +1566,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); @@ -1538,25 +1575,26 @@ find_lsn_recurse (void *p_image, iso9660_readdir_t iso9660_readdir, if (statbuf->type == _STAT_DIR && strcmp ((char *) statbuf->filename, ".") && strcmp ((char *) statbuf->filename, "..")) { - snprintf (*ppsz_full_filename, len, "%s%s/", psz_path, psz_filename); + snprintf (*ppsz_full_filename, len, "%s%s/", psz_path, psz_filename); _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) - { - iso9660_dirlist_free(dirlist); - cdio_warn("Couldn't calloc(1, %d)", len2); - free(*ppsz_full_filename); - *ppsz_full_filename = NULL; - return NULL; - } - memcpy(ret_stat, statbuf, len2); - iso9660_filelist_free (entlist); - iso9660_dirlist_free(dirlist); - return 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) { + iso9660_dirlist_free(dirlist); + cdio_warn("Couldn't calloc(1, %d)", len2); + free(*ppsz_full_filename); + *ppsz_full_filename = NULL; + return NULL; + } + memcpy(ret_stat, statbuf, len2); + iso9660_filelist_free (entlist); + iso9660_dirlist_free(dirlist); + return ret_stat; + } } } @@ -1576,7 +1614,7 @@ find_lsn_recurse (void *p_image, iso9660_readdir_t iso9660_readdir, ppsz_full_filename); if (NULL != ret_stat) { - iso9660_dirlist_free(dirlist); + iso9660_dirlist_free(dirlist); return ret_stat; } } @@ -1736,53 +1774,53 @@ 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) { + ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn[0], _root->secsize[0]); + if (ret!=ISO_BLOCKSIZE*_root->secsize[0]) { free(_dirbuf); 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; unsigned int i_last_component = 1; if (iso9660_check_dir_block_end(p_iso9660_dir, &offset)) - continue; + 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) { - if (strlen(splitpath[0]) == 0) - have_rr = false; - else - have_rr = iso_have_rr_traverse (p_iso, p_stat, &splitpath[i_last_component], + if (strlen(splitpath[0]) == 0) + have_rr = false; + else + have_rr = iso_have_rr_traverse (p_iso, p_stat, &splitpath[i_last_component], pu_file_limit); } free(p_stat); if (have_rr != nope) { - free (_dirbuf); - return have_rr; + free (_dirbuf); + return have_rr; } offset += iso9660_get_dir_len(p_iso9660_dir); *pu_file_limit = (*pu_file_limit)-1; if ((*pu_file_limit) == 0) { - free (_dirbuf); - return dunno; + free (_dirbuf); + return dunno; } } - cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); + cdio_assert (offset == (_root->secsize[0] * ISO_BLOCKSIZE)); /* not found */ free (_dirbuf); diff --git a/src/iso-read.c b/src/iso-read.c index 8647485..d36ab83 100644 --- a/src/iso-read.c +++ b/src/iso-read.c @@ -211,7 +211,7 @@ static int read_iso_file(const char *iso_name, const char *src, FILE *outfd, size_t *bytes_written) { iso9660_stat_t *statbuf; - int i; + int i, j; iso9660_t *iso; iso = iso9660_open (iso_name); @@ -239,22 +239,21 @@ static int read_iso_file(const char *iso_name, const char *src, /* Copy the blocks from the ISO-9660 filesystem to the local filesystem. */ - for (i = 0; i < statbuf->size; i += ISO_BLOCKSIZE) - { + for (j = 0; j < statbuf->extents; j++) { + for (i = 0; i < statbuf->extsize[j]; i += ISO_BLOCKSIZE) { char buf[ISO_BLOCKSIZE]; memset (buf, 0, ISO_BLOCKSIZE); - if ( ISO_BLOCKSIZE != iso9660_iso_seek_read (iso, buf, statbuf->lsn + if ( ISO_BLOCKSIZE != iso9660_iso_seek_read (iso, buf, statbuf->lsn[j] + (i / ISO_BLOCKSIZE), 1) ) { report(stderr, "Error reading ISO 9660 file at lsn %lu\n", - (long unsigned int) statbuf->lsn + (i / ISO_BLOCKSIZE)); + (long unsigned int) statbuf->lsn[j] + (i / ISO_BLOCKSIZE)); if (!opts.ignore) return 4; } - fwrite (buf, ISO_BLOCKSIZE, 1, outfd); if (ferror (outfd)) @@ -263,6 +262,7 @@ static int read_iso_file(const char *iso_name, const char *src, return 5; } } + } iso9660_close(iso); *bytes_written = statbuf->size; @@ -488,7 +488,7 @@ print_fs_attrs(iso9660_stat_t *p_statbuf, bool b_rock, bool b_xa, p_statbuf->rr.st_nlinks, p_statbuf->rr.st_uid, p_statbuf->rr.st_gid, - (long unsigned int) p_statbuf->lsn, + (long unsigned int) p_statbuf->lsn[0], S_ISLNK(p_statbuf->rr.st_mode) ? strlen(p_statbuf->rr.psz_symlink) : (unsigned int) p_statbuf->size ); @@ -501,18 +501,18 @@ print_fs_attrs(iso9660_stat_t *p_statbuf, bool b_rock, bool b_xa, uint16_from_be (p_statbuf->xa.user_id), uint16_from_be (p_statbuf->xa.group_id), p_statbuf->xa.filenum, - (long unsigned int) p_statbuf->lsn ); + (long unsigned int) p_statbuf->lsn[0] ); if (uint16_from_be(p_statbuf->xa.attributes) & XA_ATTR_MODE2FORM2) { report ( stdout, "%9u (%9u)", - (unsigned int) p_statbuf->secsize * M2F2_SECTOR_SIZE, + (unsigned int) p_statbuf->secsize[0] * M2F2_SECTOR_SIZE, (unsigned int) p_statbuf->size ); } else report (stdout, "%9u", (unsigned int) p_statbuf->size); } else { report ( stdout," %c [LSN %6lu] %9u", (p_statbuf->type == _STAT_DIR) ? 'd' : '-', - (long unsigned int) p_statbuf->lsn, + (long unsigned int) p_statbuf->lsn[0], (unsigned int) p_statbuf->size ); } diff --git a/test/testisocd.c b/test/testisocd.c index 6b1f60b..686dd01 100644 --- a/test/testisocd.c +++ b/test/testisocd.c @@ -99,7 +99,7 @@ main(int argc, const char *argv[]) char buf[ISO_BLOCKSIZE]; char *psz_path = NULL; - const lsn_t i_lsn = p_statbuf->lsn; + const lsn_t i_lsn = p_statbuf->lsn[0]; iso9660_stat_t *p_statbuf2 = iso9660_fs_find_lsn (p_cdio, i_lsn); iso9660_stat_t *p_statbuf3 = iso9660_fs_find_lsn_with_path (p_cdio, i_lsn, &psz_path); @@ -107,7 +107,7 @@ main(int argc, const char *argv[]) const unsigned int statbuf_test_size = 100; /* Compare the two statbufs. */ - if (p_statbuf->lsn != p_statbuf2->lsn || + if (p_statbuf->lsn[0] != p_statbuf2->lsn[0] || p_statbuf->size != p_statbuf2->size || p_statbuf->type != p_statbuf2->type) { fprintf(stderr, "File stat information between fs_stat and " @@ -143,7 +143,7 @@ main(int argc, const char *argv[]) if ( 0 != cdio_read_data_sectors (p_cdio, buf, i_lsn, ISO_BLOCKSIZE, 1) ) { fprintf(stderr, "Error reading ISO 9660 file at lsn %lu\n", - (long unsigned int) p_statbuf->lsn); + (long unsigned int) p_statbuf->lsn[0]); rc=7; } exit: diff --git a/test/testisocd2.c b/test/testisocd2.c index a118776..720e148 100644 --- a/test/testisocd2.c +++ b/test/testisocd2.c @@ -105,13 +105,13 @@ main(int argc, const char *argv[]) /* Now try getting the statbuf another way */ char buf[ISO_BLOCKSIZE]; char *psz_path = NULL; - const lsn_t i_lsn = p_statbuf->lsn; + const lsn_t i_lsn = p_statbuf->lsn[0]; iso9660_stat_t *p_statbuf2 = iso9660_ifs_find_lsn (p_iso, i_lsn); iso9660_stat_t *p_statbuf3 = iso9660_ifs_find_lsn_with_path (p_iso, i_lsn, &psz_path); /* Compare the two statbufs. */ - if (p_statbuf->lsn != p_statbuf2->lsn || + if (p_statbuf->lsn[0] != p_statbuf2->lsn[0] || p_statbuf->size != p_statbuf2->size || p_statbuf->type != p_statbuf2->type) { @@ -121,7 +121,7 @@ main(int argc, const char *argv[]) goto exit; } - if (p_statbuf3->lsn != p_statbuf2->lsn || + if (p_statbuf3->lsn[0] != p_statbuf2->lsn[0] || p_statbuf3->size != p_statbuf2->size || p_statbuf3->type != p_statbuf2->type) { rc = 4; @@ -147,7 +147,7 @@ main(int argc, const char *argv[]) if ( ISO_BLOCKSIZE != iso9660_iso_seek_read (p_iso, buf, i_lsn, 1) ) { fprintf(stderr, "Error reading ISO 9660 file at lsn %lu\n", - (long unsigned int) p_statbuf->lsn); + (long unsigned int) p_statbuf->lsn[0]); rc = 7; goto exit; } diff --git a/test/testisocd_joliet.c b/test/testisocd_joliet.c index 8eedc2f..f578936 100644 --- a/test/testisocd_joliet.c +++ b/test/testisocd_joliet.c @@ -106,7 +106,7 @@ main(int argc, const char *argv[]) /* Now try getting the statbuf another way */ char buf[ISO_BLOCKSIZE]; char *psz_path = NULL; - const lsn_t i_lsn = p_statbuf->lsn; + const lsn_t i_lsn = p_statbuf->lsn[0]; iso9660_stat_t *p_statbuf2 = iso9660_ifs_find_lsn (p_iso, i_lsn); iso9660_stat_t *p_statbuf3 = iso9660_ifs_find_lsn_with_path (p_iso, i_lsn, &psz_path); @@ -114,16 +114,16 @@ main(int argc, const char *argv[]) const unsigned int statbuf_test_size = 100; /* Compare the two statbufs. */ - if (p_statbuf->lsn != p_statbuf2->lsn || + if (p_statbuf->lsn[0] != p_statbuf2->lsn[0] || p_statbuf->size != p_statbuf2->size || p_statbuf->type != p_statbuf2->type) { fprintf(stderr, "File stat information between fs_stat and " "iso9660_ifs_find_lsn isn't the same\n"); printf("statbuf lsn: %d, size: %d, type: %d\n", - p_statbuf->lsn, p_statbuf->size, p_statbuf->type); + p_statbuf->lsn[0], p_statbuf->extsize[0], p_statbuf->type); printf("statbuf2 lsn: %d, size: %d, type: %d\n", - p_statbuf2->lsn, p_statbuf2->size, p_statbuf2->type); + p_statbuf2->lsn[0], p_statbuf2->extsize[0], p_statbuf2->type); rc=3; goto exit; } @@ -157,7 +157,7 @@ main(int argc, const char *argv[]) if ( ISO_BLOCKSIZE != iso9660_iso_seek_read (p_iso, buf, i_lsn, 1) ) { fprintf(stderr, "Error reading ISO 9660 file at lsn %lu\n", - (long unsigned int) p_statbuf->lsn); + (long unsigned int) p_statbuf->lsn[0]); rc=7; } exit: |
