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