summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pete@akeo.ie>2018-06-05 13:42:37 +0100
committerPete Batard <pete@akeo.ie>2018-06-06 13:52:03 +0100
commitc93341a28bba1842d7df89d784951eccc18050ff (patch)
treef46715776d36119e9259728845b132ee19f0edce
parentcc93005dc13ee6274077b9dc6c11b6e751793292 (diff)
downloadlibcdio-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.c36
-rw-r--r--example/isofile.c29
-rw-r--r--example/isofile2.c33
-rw-r--r--example/isolist.c12
-rw-r--r--include/cdio/iso9660.h18
-rw-r--r--lib/iso9660/iso9660_fs.c228
-rw-r--r--src/iso-read.c12
-rw-r--r--src/util.c8
-rw-r--r--test/testisocd.c6
-rw-r--r--test/testisocd2.c8
-rw-r--r--test/testisocd_joliet.c10
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;
diff --git a/src/util.c b/src/util.c
index dde2f40..9c14262 100644
--- a/src/util.c
+++ b/src/util.c
@@ -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: