libcdio-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libcdio-devel] [RFC] Hid ISO_MAX_MULTIEXTENT from public and made exten


From: Thomas Schmitt
Subject: [Libcdio-devel] [RFC] Hid ISO_MAX_MULTIEXTENT from public and made extent list dynamic memory
Date: Thu, 28 Jun 2018 21:05:52 +0200

Hi,

first changeset in new branch ts-multiextent :

"Hid ISO_MAX_MULTIEXTENT from public and made extent list dynamic memory"
  
http://git.savannah.gnu.org/cgit/libcdio.git/commit/?h=ts-multiextent&id=3b602d69cb116a297ee95e48471a097ce7456435


This is still Pete Batard's (compatible) API extension which would break ABI
by changing existing member offsets in public struct iso9660_stat_s.

As the commit message says, this change solves the problem of a publicly
known array size which would cause ABI breaking each time it gets enlarged.
It also reduces memory waste with single-extent files and gave me the
opportunity to push the file size limit to ~ 400 GiB without extra cost.

I refrained for now from changing the two arrays .extent_lsn and .extent_size
to a single array of a two-member struct, because this keeps valid the
changes by Pete in examples/ and test/.
But i had to transmogrify Pete's hack about "[# extents]" in example/isolist.c

---

Tested after ./configure --disable-shared  by 

  $ valgrind example/isolist .../multi_extent_8k.iso
  ...
  ==27675== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
  ...
  Preparer   : XORRISO-1.4.9 2018.05.18.152119, LIBISOBURN-1.4.9, 
LIBISOFS-1.4.9, LIBBURN-1.4.9
  Volume     : ISOIMAGE
  d [LSN       50]         2048 /.
  d [LSN       50]         2048 /..
  - [LSN       55]        54305 /multi_extent_file [7 extents]
  ...
  ==27675== All heap blocks were freed -- no leaks are possible
  ...
  ==27675== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

  $ valgrind example/isolist .../file_of_4gb.iso
  ...
  Preparer   : XORRISO-1.2.2 2012.04.02.133001, LIBISOBURN-1.2.2, 
LIBISOFS-1.2.2, LIBBURN-1.2.2
  Volume     : ISOIMAGE
  d [LSN       50]         2048 /.
  d [LSN       50]         2048 /..
  - [LSN  2098231]            4 /aaa
  - [LSN       55]   4297064448 /file_of_4gb [2 extents]
  - [LSN  2098232]            4 /zzz
  ...
  ==28079== All heap blocks were freed -- no leaks are possible
  ...
  ==28079== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

(Tempus fugit.)

==========================================================================

diff --git a/example/isolist.c b/example/isolist.c
index 2a6c4b3..61c385b 100644
--- a/example/isolist.c
+++ b/example/isolist.c
@@ -70,7 +70,7 @@ main(int argc, const char *argv[])
   char const *psz_fname;
   iso9660_t *p_iso;
   const char *psz_path = "/";
-  char psz_extents[] = " [# extents]";
+  char psz_extents[] = " [4294967296 extents]"; /* enough room for uint32_t */
 
   if (argc > 1)
     psz_fname = argv[1];
@@ -109,7 +109,8 @@ main(int argc, const char *argv[])
       iso9660_name_translate(p_statbuf->filename, filename);
 
        if (p_statbuf->num_extents > 1)
-           psz_extents[2] = '0' + p_statbuf->num_extents;
+           sprintf(psz_extents, " [%lu extents]",
+                   (unsigned long) p_statbuf->num_extents);
        printf ("%s [LSN %8d] %12" PRIi64 " %s%s%s\n",
                _STAT_DIR == p_statbuf->type ? "d" : "-",
                p_statbuf->extent_lsn[0], p_statbuf->total_size, psz_path, 
filename,
diff --git a/include/cdio/iso9660.h b/include/cdio/iso9660.h
index 819834b..01fd8f2 100644
--- a/include/cdio/iso9660.h
+++ b/include/cdio/iso9660.h
@@ -156,9 +156,6 @@ 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.
 */
@@ -550,9 +547,9 @@ struct iso9660_stat_s { /* big endian!! */
                      /**v combined size of all extents, in bytes */
   uint64_t           total_size;
                      /**v start logical sector number for each extent */
-  lsn_t              extent_lsn[ISO_MAX_MULTIEXTENT];
+  lsn_t              *extent_lsn;
                      /**v size of each extent */
-  uint32_t           extent_size[ISO_MAX_MULTIEXTENT];
+  uint32_t           *extent_size;
   /* NB: If you need to access the 'secsize' equivalent for an extent,
    * you should use CDIO_EXTENT_BLOCKS(extent_size[extent_nr]) */
 
diff --git a/lib/iso9660/iso9660_fs.c b/lib/iso9660/iso9660_fs.c
index 2d48fab..3f351f0 100644
--- a/lib/iso9660/iso9660_fs.c
+++ b/lib/iso9660/iso9660_fs.c
@@ -99,6 +99,10 @@ static long int iso9660_seek_read_framesize (const iso9660_t 
*p_iso,
                                             long int size,
                                             uint16_t i_framesize);
 
+/*! \brief Maximum number of multi file extent licdio supports. */
+#define ISO_MAX_MULTIEXTENT 100
+
+
 /* Adjust the p_iso's i_datastart, i_byte_offset and i_framesize
    based on whether we find a frame header or not.
 */
@@ -775,11 +779,38 @@ iso9660_check_dir_block_end(iso9660_dir_t *p_iso9660_dir, 
unsigned *offset)
 }
 
 
+static bool
+_iso9660_statbuf_alloc_extents(iso9660_stat_t *p_stat, int num_extents)
+{
+  p_stat->extent_lsn = calloc(num_extents, sizeof(lsn_t));
+  if (p_stat->extent_lsn == NULL) {
+no_memory:;
+    cdio_warn("Could not allocate %lu bytes",
+             (unsigned long) num_extents * (sizeof(lsn_t) + sizeof(uint32_t)));
+    return false;
+  }
+  p_stat->extent_size = calloc(num_extents, sizeof(uint32_t));
+  if (p_stat->extent_size == NULL) {
+    free(p_stat->extent_lsn);
+    goto no_memory;
+  }
+  return true;
+}
+
 
+/*!
+   @param single_extent Submit true to allocate only a single extent.
+                        Submit false to allocate the maximum number of extents.
+                        In the latter case, call _iso9660_statbuf_adj_extents()
+                        when all extents are assessed.
+                        Rule of thumb: If last_p_stat is submitted as constant
+                        NULL, then single_extent should be true, else false.
+*/
 static iso9660_stat_t *
 _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)
+                        bool_3way_t b_xa, uint8_t u_joliet_level,
+                        bool single_extent)
 {
   uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir);
   iso711_t i_fname;
@@ -802,6 +833,14 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
     cdio_warn("Couldn't calloc(1, %d)", stat_len);
     return NULL;
   }
+  if (last_p_stat == NULL) {
+    if (!_iso9660_statbuf_alloc_extents(p_stat, single_extent ?
+                                                1 : ISO_MAX_MULTIEXTENT)) {
+      free(p_stat);
+      return NULL;
+    }
+  }
+
   p_stat->type    = (p_iso9660_dir->file_flags & ISO_DIRECTORY)
     ? _STAT_DIR : _STAT_FILE;
   p_stat->extent_lsn[p_stat->num_extents] = from_733 (p_iso9660_dir->extent);
@@ -938,6 +977,28 @@ _iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir,
 
 }
 
+
+static bool
+_iso9660_statbuf_adj_extents(iso9660_stat_t *p_stat)
+{
+  lsn_t *lsn;
+  uint32_t *sizes;
+
+  lsn = p_stat->extent_lsn;
+  sizes =  p_stat->extent_size;
+  if (!_iso9660_statbuf_alloc_extents(p_stat, p_stat->num_extents)) {
+    p_stat->extent_lsn = lsn;
+    p_stat->extent_size = sizes;
+    return false;
+  }
+  memcpy(p_stat->extent_lsn, lsn, p_stat->num_extents * sizeof(lsn_t));
+  memcpy(p_stat->extent_size, sizes, p_stat->num_extents * sizeof(uint32_t));
+  free(lsn);
+  free(sizes);
+  return true;
+}
+
+
 /*!
   Return the directory name stored in the iso9660_dir_t
 
@@ -1009,7 +1070,7 @@ _fs_stat_root (CdIo_t *p_cdio)
 #endif
 
     p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL,
-                                     b_xa, p_env->u_joliet_level);
+                                     b_xa, p_env->u_joliet_level, true);
     return p_stat;
   }
 
@@ -1031,7 +1092,8 @@ _ifs_stat_root (iso9660_t *p_iso)
 
   p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL,
                                    p_iso->b_xa,
-                                   p_iso->u_joliet_level);
+                                   p_iso->u_joliet_level,
+                                   true);
   return p_stat;
 }
 
@@ -1085,7 +1147,7 @@ _fs_stat_traverse (const CdIo_t *p_cdio, const 
iso9660_stat_t *_root,
        continue;
 
       p_iso9660_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL,
-                                       dunno, p_env->u_joliet_level);
+                                       dunno, p_env->u_joliet_level, true);
 
       cmp = strcmp(splitpath[0], p_iso9660_stat->filename);
 
@@ -1181,7 +1243,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_stat,
-                                       p_iso->b_xa, p_iso->u_joliet_level);
+                                       p_iso->b_xa, p_iso->u_joliet_level,
+                                       false);
 
       if (!p_stat) {
        cdio_warn("Bad directory information for %s", splitpath[0]);
@@ -1193,6 +1256,11 @@ _fs_iso_stat_traverse (iso9660_t *p_iso, const 
iso9660_stat_t *_root,
       if (p_iso9660_dir->file_flags & ISO_MULTIEXTENT)
         continue;
 
+      if (!_iso9660_statbuf_adj_extents(p_stat)) {
+       free(_dirbuf);
+       return NULL;
+      }
+
       cmp = strcmp(splitpath[0], p_stat->filename);
 
       if ( 0 != cmp && 0 == p_iso->u_joliet_level
@@ -1439,10 +1507,16 @@ iso9660_fs_readdir (CdIo_t *p_cdio, const char 
psz_path[])
 
        p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir,
                                                 p_iso9660_stat, dunno,
-                                                p_env->u_joliet_level);
+                                                p_env->u_joliet_level,
+                                                false);
        if ((p_iso9660_stat) &&
            ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0))
          {
+            if (!_iso9660_statbuf_adj_extents(p_stat)) {
+              iso9660_stat_free(p_stat);
+              iso9660_dirlist_free(retval);
+              return NULL;
+            }
            _cdio_list_append (retval, p_iso9660_stat);
            p_iso9660_stat = NULL;
          }
@@ -1524,10 +1598,17 @@ iso9660_ifs_readdir (iso9660_t *p_iso, const char 
psz_path[])
        p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir,
                                                 p_iso9660_stat,
                                                 p_iso->b_xa,
-                                                p_iso->u_joliet_level);
+                                                p_iso->u_joliet_level,
+                                                false);
        if ((p_iso9660_stat) &&
            ((p_iso9660_dir->file_flags & ISO_MULTIEXTENT) == 0))
          {
+           if (!_iso9660_statbuf_adj_extents(p_stat)) {
+             _cdio_list_free (retval, true, NULL);
+             iso9660_stat_free(p_stat);
+             free (_dirbuf);
+             return NULL;
+           }
            _cdio_list_append(retval, p_iso9660_stat);
            p_iso9660_stat = NULL;
          }
@@ -1739,6 +1820,8 @@ iso9660_stat_free(iso9660_stat_t *p_stat)
     if (p_stat->rr.psz_symlink) {
       CDIO_FREE_IF_NOT_NULL(p_stat->rr.psz_symlink);
     }
+    CDIO_FREE_IF_NOT_NULL(p_stat->extent_lsn);
+    CDIO_FREE_IF_NOT_NULL(p_stat->extent_size);
     free(p_stat);
   }
 }
@@ -1811,7 +1894,7 @@ iso_have_rr_traverse (iso9660_t *p_iso, const 
iso9660_stat_t *_root,
         continue;
 
       p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, NULL, p_iso->b_xa,
-                                       p_iso->u_joliet_level);
+                                       p_iso->u_joliet_level, true);
       have_rr = p_stat->rr.b3_rock;
       if ( have_rr != yep) {
         if (strlen(splitpath[0]) == 0)

==========================================================================

Have a nice day :)

Thomas




reply via email to

[Prev in Thread] Current Thread [Next in Thread]