public inbox for cygwin-apps@cygwin.com
 help / color / mirror / Atom feed
From: Jon Turney <jon.turney@dronecode.org.uk>
To: cygwin-apps@cygwin.com
Cc: Jon Turney <jon.turney@dronecode.org.uk>
Subject: [PATCH setup 04/11] Add seek() method to archive and compress file classes
Date: Tue, 10 Aug 2021 18:02:21 +0100	[thread overview]
Message-ID: <20210810170228.1690-5-jon.turney@dronecode.org.uk> (raw)
In-Reply-To: <20210810170228.1690-1-jon.turney@dronecode.org.uk>

Add seek() method to archive and compressed file isostream classes
(which can only rewind to the start).

Also clean up some cruft in archive class.

This still needs testing on a .gz archive (slightly involved as there
aren't any currently!)
---
 archive.cc       | 52 --------------------------------------
 archive.h        | 14 +++--------
 archive_tar.cc   | 14 +++++++----
 compress_bz.cc   | 12 +++++++++
 compress_bz.h    |  1 +
 compress_gz.cc   | 65 +++++++++++++++++++++++++++++-------------------
 compress_gz.h    |  3 ++-
 compress_xz.cc   | 34 ++++++++++++++++++-------
 compress_xz.h    |  3 ++-
 compress_zstd.cc | 19 +++++++++++---
 compress_zstd.h  |  3 ++-
 11 files changed, 111 insertions(+), 109 deletions(-)

diff --git a/archive.cc b/archive.cc
index 1ceb355..448ea0e 100644
--- a/archive.cc
+++ b/archive.cc
@@ -45,7 +45,6 @@
  * offset 257     string  ustar\040\040\0
  */
 
-
 #define longest_magic 265
 
 archive *
@@ -65,15 +64,6 @@ archive::extract (io_stream * original)
 	    return rv;
 	  return NULL;
 	}
-#if 0
-      else if (memcmp (magic, "BZh", 3) == 0)
-	{
-	  archive_bz *rv = new archive_bz (original);
-	  if (!rv->error ())
-	    return rv;
-	  return NULL;
-	}
-#endif
     }
   return NULL;
 }
@@ -194,45 +184,3 @@ out:
 }
 
 archive::~archive () {};
-
-#if 0
-ssize_t archive::read (void *buffer, size_t len)
-{
-  Log (LOG_TIMESTAMP, "archive::read called");
-  return 0;
-}
-
-ssize_t archive::write (void *buffer, size_t len)
-{
-  Log (LOG_TIMESTAMP, "archive::write called");
-  return 0;
-}
-
-ssize_t archive::peek (void *buffer, size_t len)
-{
-  Log (LOG_TIMESTAMP, "archive::peek called");
-  return 0;
-}
-
-long
-archive::tell ()
-{
-  Log (LOG_TIMESTAMP, "bz::tell called");
-  return 0;
-}
-
-int
-archive::error ()
-{
-  Log (LOG_TIMESTAMP, "archive::error called");
-  return 0;
-}
-
-const char *
-archive::next_file_name ()
-{
-  Log (LOG_TIMESTAMP, "archive::next_file_name called");
-  return NULL;
-}
-
-#endif
diff --git a/archive.h b/archive.h
index d3c795a..adab9f0 100644
--- a/archive.h
+++ b/archive.h
@@ -69,14 +69,9 @@ public:
   /* read data - not valid for archives (duh!) 
    * Could be made valid via the read-child-directly model 
    */
-//  virtual ssize_t read(void *buffer, size_t len) {return -1;};
-  /* provide data to (double duh!) */
-//  virtual ssize_t write(void *buffer, size_t len) { return -1;};
-  /* read data without removing it from the class's internal buffer */
-//  virtual ssize_t peek(void *buffer, size_t len);
-//  virtual long tell ();
-  /* try guessing this one */
-//  virtual int error ();
+
+  virtual int seek (long offset, io_stream_seek_t whence) = 0;
+
   /* Find out the next stream name -
    * ie for foo.tar.gz, at offset 0, next_file_name = foo.tar
    * for foobar that is an compress, next_file_name is the next
@@ -88,14 +83,11 @@ public:
   virtual archive_file_t next_file_type () = 0;
   virtual const std::string linktarget () = 0;
   virtual int skip_file () = 0;
-  /* if you are still needing these hints... give up now! */
   virtual ~archive() = 0;
 protected:
   void operator= (const archive &);
   archive () {};
   archive (const archive &);
-private:
-//  archive () {};
 };
 
 #endif /* SETUP_ARCHIVE_H */
diff --git a/archive_tar.cc b/archive_tar.cc
index c359238..5b2a771 100644
--- a/archive_tar.cc
+++ b/archive_tar.cc
@@ -100,11 +100,15 @@ archive_tar::tell ()
 int
 archive_tar::seek (long where, io_stream_seek_t whence)
 {
-  /* seeking in the parent archive doesn't make sense. although we could
-     map to files ? 
-     Also, seeking might make sense for rewing..?? 
-     */
-  return -1; 
+  /* Because the parent stream is compressed, we can only easily support
+     seek()-ing to rewind to the start */
+  if ((whence == IO_SEEK_SET) && (where == 0))
+    {
+      state.header_read = 0;
+      return state.parent->seek(where, whence);
+    }
+
+  return -1;
 }
 
 int
diff --git a/compress_bz.cc b/compress_bz.cc
index 18773d4..e4792d6 100644
--- a/compress_bz.cc
+++ b/compress_bz.cc
@@ -35,7 +35,12 @@ compress_bz::compress_bz (io_stream * parent) : peeklen (0), position (0)
     }
   original = parent;
   owns_original = true;
+  init_state();
+}
 
+void
+compress_bz::init_state(void)
+{
   initialisedOk = 0;
   endReached = 0;
   writing = 0;
@@ -194,6 +199,13 @@ compress_bz::tell ()
 int
 compress_bz::seek (long where, io_stream_seek_t whence)
 {
+  if ((whence == IO_SEEK_SET) && (where == 0))
+    {
+      int result = original->seek(where, whence);
+      init_state();
+      return result;
+    }
+
   throw new std::logic_error ("compress_bz::seek is not implemented");
 }
 
diff --git a/compress_bz.h b/compress_bz.h
index 39a0d5b..a7e865a 100644
--- a/compress_bz.h
+++ b/compress_bz.h
@@ -67,6 +67,7 @@ private:
   char buf[4096];
   int writing;
   size_t position;
+  void init_state(void);
 };
 
 #endif /* SETUP_COMPRESS_BZ_H */
diff --git a/compress_gz.cc b/compress_gz.cc
index 55a015e..e73ccd3 100644
--- a/compress_gz.cc
+++ b/compress_gz.cc
@@ -41,19 +41,23 @@ static int gz_magic[2] = { 0x1f, 0x8b };	/* gzip magic header */
  */
 compress_gz::compress_gz (io_stream * parent)
 {
-  construct (parent, "r");
+  original = parent;
+  owns_original = true;
+  openmode = "r";
+  construct ();
 }
 
-compress_gz::compress_gz (io_stream * parent, const char *openmode)
+compress_gz::compress_gz (io_stream * parent, const char *_openmode)
 {
-  construct (parent, openmode);
+  original = parent;
+  owns_original = true;
+  openmode = _openmode;
+  construct ();
 }
 
 void
-compress_gz::construct (io_stream * parent, const char *openmode)
+compress_gz::construct ()
 {
-  original = parent;
-  owns_original = true;
   peeklen = 0;
   int err;
   int level = Z_DEFAULT_COMPRESSION;	/* compression level */
@@ -76,7 +80,7 @@ compress_gz::construct (io_stream * parent, const char *openmode)
 
   mode = '\0';
 
-  if (!parent)
+  if (!original)
     {
       z_err = Z_STREAM_ERROR;
       return;
@@ -413,6 +417,14 @@ compress_gz::tell ()
 int
 compress_gz::seek (long where, io_stream_seek_t whence)
 {
+  if ((whence == IO_SEEK_SET) && (where == 0))
+    {
+      int result = original->seek(where, whence);
+      destroy();
+      construct();
+      return result;
+    }
+
   throw new std::logic_error("compress_gz::seek is not implemented");
 }
 
@@ -458,7 +470,11 @@ void
 compress_gz::destroy ()
 {
   if (msg)
-    free (msg);
+    {
+      free (msg);
+      msg = NULL;
+    }
+
   if (stream.state != NULL)
     {
       if (mode == 'w')
@@ -472,12 +488,15 @@ compress_gz::destroy ()
     }
 
   if (inbuf)
-
-    free (inbuf);
+    {
+      free (inbuf);
+      inbuf = NULL;
+    }
   if (outbuf)
-    free (outbuf);
-  if (original && owns_original)
-    delete original;
+    {
+      free (outbuf);
+      outbuf = NULL;
+    }
 }
 
 compress_gz::~compress_gz ()
@@ -485,16 +504,15 @@ compress_gz::~compress_gz ()
   if (mode == 'w')
     {
       z_err = do_flush (Z_FINISH);
-      if (z_err != Z_OK)
-	{
-	  destroy ();
-	  return;
-	}
-
-      putLong (crc);
-      putLong (stream.total_in);
+      if (z_err == Z_OK)
+        {
+          putLong (crc);
+          putLong (stream.total_in);
+        }
     }
   destroy ();
+  if (original && owns_original)
+    delete original;
 }
 
 int
@@ -534,11 +552,6 @@ compress_gz::do_flush (int flush)
   return z_err == Z_STREAM_END ? Z_OK : z_err;
 }
 
-
-#if 0
-
-gzclose (lst);
-#endif
 /* ===========================================================================
  *  Read a byte from a gz_stream; update next_in and avail_in. Return EOF
  *  for end of file.
diff --git a/compress_gz.h b/compress_gz.h
index 50b6e66..90073e5 100644
--- a/compress_gz.h
+++ b/compress_gz.h
@@ -60,7 +60,7 @@ private:
   };
   char peekbuf[512];
   size_t peeklen;
-  void construct (io_stream *, const char *);
+  void construct ();
   void check_header ();
   int get_byte ();
   unsigned long getLong ();
@@ -69,6 +69,7 @@ private:
   int do_flush (int);
   io_stream *original;
   bool owns_original;
+  const char *openmode;
   /* from zlib */
   z_stream stream;
   int z_err;			/* error code for last stream operation */
diff --git a/compress_xz.cc b/compress_xz.cc
index a5167d6..bb64595 100644
--- a/compress_xz.cc
+++ b/compress_xz.cc
@@ -51,9 +51,6 @@ compress_xz::compress_xz (io_stream * parent)
   lasterr(0),
   compression_type (COMPRESSION_UNKNOWN)
 {
-  unsigned char * out_block = NULL;
-  unsigned char * in_block = NULL;
-
   /* read only */
   if (!parent || parent->error())
     {
@@ -62,6 +59,16 @@ compress_xz::compress_xz (io_stream * parent)
     }
   original = parent;
 
+  create ();
+  init_decoder ();
+}
+
+void
+compress_xz::create ()
+{
+  unsigned char * out_block = NULL;
+  unsigned char * in_block = NULL;
+
   state = (struct private_data *)calloc(sizeof(*state), 1);
   out_block = (unsigned char *)malloc(out_block_size);
   in_block = (unsigned char *)malloc(in_block_size);
@@ -79,12 +86,10 @@ compress_xz::compress_xz (io_stream * parent)
   state->out_block = out_block;
   state->in_block_size = in_block_size;
   state->in_block = in_block;
-  state->out_p = out_block;
+  state->out_p = state->out_block;
   state->stream.avail_in = 0;
   state->stream.next_out = state->out_block;
   state->stream.avail_out = state->out_block_size;
-
-  init_decoder ();
 }
 
 ssize_t
@@ -267,6 +272,17 @@ compress_xz::tell ()
 int
 compress_xz::seek (long where, io_stream_seek_t whence)
 {
+  if ((whence == IO_SEEK_SET) && (where == 0))
+    {
+      int result = original->seek(where, whence);
+      destroy ();
+      peeklen = 0;
+      lasterr = 0;
+      create ();
+      init_decoder ();
+      return result;
+    }
+
   throw new std::logic_error("compress_xz::seek is not implemented");
 }
 
@@ -334,14 +350,14 @@ compress_xz::destroy ()
 
       compression_type = COMPRESSION_UNKNOWN;
     }
-
-  if (original && owns_original)
-    delete original;
 }
 
 compress_xz::~compress_xz ()
 {
   destroy ();
+
+  if (original && owns_original)
+    delete original;
 }
 
 /* ===========================================================================
diff --git a/compress_xz.h b/compress_xz.h
index 24cbb09..31d499c 100644
--- a/compress_xz.h
+++ b/compress_xz.h
@@ -27,7 +27,7 @@ public:
   virtual ssize_t write (const void *buffer, size_t len); /* not implemented */
   virtual ssize_t peek (void *buffer, size_t len);
   virtual long tell (); /* not implemented */
-  virtual int seek (long where, io_stream_seek_t whence); /* not implemented */
+  virtual int seek (long where, io_stream_seek_t whence);
   virtual int error ();
   virtual const char *next_file_name () { return NULL; };
   virtual int set_mtime (time_t);
@@ -49,6 +49,7 @@ private:
   char peekbuf[512];
   size_t peeklen;
   int lasterr;
+  void create ();
   void destroy ();
 
   struct private_data {
diff --git a/compress_zstd.cc b/compress_zstd.cc
index 3588dbd..bb17785 100644
--- a/compress_zstd.cc
+++ b/compress_zstd.cc
@@ -35,7 +35,12 @@ compress_zstd::compress_zstd (io_stream * parent)
       return;
     }
   original = parent;
+  create();
+}
 
+void
+compress_zstd::create (void)
+{
   state = (struct private_data *)calloc(sizeof(*state), 1);
   if (state == NULL)
     {
@@ -179,6 +184,14 @@ compress_zstd::tell ()
 int
 compress_zstd::seek (long where, io_stream_seek_t whence)
 {
+  if ((whence == IO_SEEK_SET) && (where == 0))
+    {
+      int result = original->seek(where, whence);
+      destroy();
+      create();
+      return result;
+    }
+
   throw new std::logic_error("compress_zstd::seek is not implemented");
 }
 
@@ -240,14 +253,14 @@ compress_zstd::destroy ()
       free(state);
       state = NULL;
     }
-
-  if (original && owns_original)
-    delete original;
 }
 
 compress_zstd::~compress_zstd ()
 {
   destroy ();
+
+  if (original && owns_original)
+    delete original;
 }
 
 bool
diff --git a/compress_zstd.h b/compress_zstd.h
index be5712c..3303daa 100644
--- a/compress_zstd.h
+++ b/compress_zstd.h
@@ -25,7 +25,7 @@ public:
   virtual ssize_t write (const void *buffer, size_t len); /* not implemented */
   virtual ssize_t peek (void *buffer, size_t len);
   virtual long tell (); /* not implemented */
-  virtual int seek (long where, io_stream_seek_t whence); /* not implemented */
+  virtual int seek (long where, io_stream_seek_t whence);
   virtual int error ();
   virtual const char *next_file_name () { return NULL; };
   virtual int set_mtime (time_t);
@@ -42,6 +42,7 @@ private:
   io_stream *original;
   bool owns_original;
   int lasterr;
+  void create ();
   void destroy ();
 
   struct private_data {
-- 
2.32.0


  parent reply	other threads:[~2021-08-10 17:04 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-10 17:02 [PATCH setup 00/11] Add options to choose symlink type (v2) Jon Turney
2021-08-10 17:02 ` [PATCH setup 01/11] Add support for creating WSL symlinks Jon Turney
2021-08-10 17:02 ` [PATCH setup 02/11] Add support for creating native symlinks Jon Turney
2021-08-10 17:02 ` [PATCH setup 03/11] Factor out the iteration over archive files to install Jon Turney
2021-08-10 17:02 ` Jon Turney [this message]
2021-08-10 17:02 ` [PATCH setup 05/11] Add separate symlink-creation phase when extracting archive Jon Turney
2021-08-10 17:02 ` [PATCH setup 06/11] Enable SeCreateSymbolicLink privilege Jon Turney
2021-08-11  8:46   ` Corinna Vinschen
2021-09-14 11:53     ` Jon Turney
2021-08-10 17:02 ` [PATCH setup 07/11] Add symlink capabilities to user-agent telemetry Jon Turney
2021-08-10 17:02 ` [PATCH setup 08/11] Factor out StringChoiceOption Jon Turney
2021-08-10 17:02 ` [PATCH setup 09/11] Add a command line option to choose symlink type used Jon Turney
2021-08-10 17:02 ` [PATCH setup 10/11] Propagate --symlink-type setting to post-install scripts Jon Turney
2021-08-10 17:02 ` [PATCH setup 11/11] Default symlink mode from CYGWIN env var Jon Turney
2021-09-14 11:53 ` [PATCH setup 00/11] Add options to choose symlink type (v2) Jon Turney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210810170228.1690-5-jon.turney@dronecode.org.uk \
    --to=jon.turney@dronecode.org.uk \
    --cc=cygwin-apps@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).