From 4b7558e108c17de1417fb427ce0f771049e10ec5 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Sat, 14 Mar 2020 21:44:48 +0000 Subject: [PATCH] reader: introduce struct archive_read_filter_vtable As before - move the dispatch/function pointer so a const data segment. Separating it from the RW data section. Note: the close function is _not_ optional - remove the NULL check. Signed-off-by: Emil Velikov --- libarchive/archive_read.c | 22 +++++++++++-------- libarchive/archive_read_private.h | 16 +++++++++----- .../archive_read_support_filter_bzip2.c | 9 ++++++-- .../archive_read_support_filter_compress.c | 9 ++++++-- libarchive/archive_read_support_filter_gzip.c | 15 ++++++++----- libarchive/archive_read_support_filter_lz4.c | 9 ++++++-- libarchive/archive_read_support_filter_lzop.c | 10 +++++++-- .../archive_read_support_filter_program.c | 9 ++++++-- libarchive/archive_read_support_filter_rpm.c | 9 ++++++-- libarchive/archive_read_support_filter_uu.c | 9 ++++++-- libarchive/archive_read_support_filter_xz.c | 9 ++++++-- libarchive/archive_read_support_filter_zstd.c | 9 ++++++-- 12 files changed, 97 insertions(+), 38 deletions(-) diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index 0ed27a8c0..45a38aed0 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -451,6 +451,12 @@ archive_read_prepend_callback_data(struct archive *_a, void *client_data) return archive_read_add_callback_data(_a, client_data, 0); } +static const struct archive_read_filter_vtable +none_reader_vtable = { + .read = client_read_proxy, + .close = client_close_proxy, +}; + int archive_read_open1(struct archive *_a) { @@ -486,8 +492,7 @@ archive_read_open1(struct archive *_a) filter->upstream = NULL; filter->archive = a; filter->data = a->client.dataset[0].data; - filter->read = client_read_proxy; - filter->close = client_close_proxy; + filter->vtable = &none_reader_vtable; filter->name = "none"; filter->code = ARCHIVE_FILTER_NONE; filter->can_skip = 1; @@ -599,10 +604,9 @@ choose_filters(struct archive_read *a) int __archive_read_header(struct archive_read *a, struct archive_entry *entry) { - if (a->filter->read_header) - return a->filter->read_header(a->filter, entry); - else + if (!a->filter->vtable->read_header) return (ARCHIVE_OK); + return a->filter->vtable->read_header(a->filter, entry); } /* @@ -991,8 +995,8 @@ close_filters(struct archive_read *a) /* Close each filter in the pipeline. */ while (f != NULL) { struct archive_read_filter *t = f->upstream; - if (!f->closed && f->close != NULL) { - int r1 = (f->close)(f); + if (!f->closed && f->vtable != NULL) { + int r1 = (f->vtable->close)(f); f->closed = 1; if (r1 < r) r = r1; @@ -1382,7 +1386,7 @@ __archive_read_filter_ahead(struct archive_read_filter *filter, *avail = 0; return (NULL); } - bytes_read = (filter->read)(filter, + bytes_read = (filter->vtable->read)(filter, &filter->client_buff); if (bytes_read < 0) { /* Read error. */ filter->client_total = filter->client_avail = 0; @@ -1576,7 +1580,7 @@ advance_file_pointer(struct archive_read_filter *filter, int64_t request) /* Use ordinary reads as necessary to complete the request. */ for (;;) { - bytes_read = (filter->read)(filter, &filter->client_buff); + bytes_read = (filter->vtable->read)(filter, &filter->client_buff); if (bytes_read < 0) { filter->client_buff = NULL; filter->fatal = 1; diff --git a/libarchive/archive_read_private.h b/libarchive/archive_read_private.h index 98d45fe87..383405d52 100644 --- a/libarchive/archive_read_private.h +++ b/libarchive/archive_read_private.h @@ -75,6 +75,15 @@ struct archive_read_filter_bidder { const struct archive_read_filter_bidder_vtable *vtable; }; +struct archive_read_filter_vtable { + /* Return next block. */ + ssize_t (*read)(struct archive_read_filter *, const void **); + /* Close (just this filter) and free(self). */ + int (*close)(struct archive_read_filter *self); + /* Read any header metadata if available. */ + int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry); +}; + /* * This structure is allocated within the archive_read core * and initialized by archive_read and the init() method of the @@ -87,12 +96,7 @@ struct archive_read_filter { struct archive_read_filter_bidder *bidder; /* My bidder. */ struct archive_read_filter *upstream; /* Who I read from. */ struct archive_read *archive; /* Associated archive. */ - /* Return next block. */ - ssize_t (*read)(struct archive_read_filter *, const void **); - /* Close (just this filter) and free(self). */ - int (*close)(struct archive_read_filter *self); - /* Read any header metadata if available. */ - int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry); + const struct archive_read_filter_vtable *vtable; /* My private data. */ void *data; diff --git a/libarchive/archive_read_support_filter_bzip2.c b/libarchive/archive_read_support_filter_bzip2.c index d969383ef..793d605c8 100644 --- a/libarchive/archive_read_support_filter_bzip2.c +++ b/libarchive/archive_read_support_filter_bzip2.c @@ -173,6 +173,12 @@ bzip2_reader_init(struct archive_read_filter *self) #else +static const struct archive_read_filter_vtable +bzip2_reader_vtable = { + .read = bzip2_filter_read, + .close = bzip2_filter_close, +}; + /* * Setup the callbacks. */ @@ -199,8 +205,7 @@ bzip2_reader_init(struct archive_read_filter *self) self->data = state; state->out_block_size = out_block_size; state->out_block = out_block; - self->read = bzip2_filter_read; - self->close = bzip2_filter_close; + self->vtable = &bzip2_reader_vtable; return (ARCHIVE_OK); } diff --git a/libarchive/archive_read_support_filter_compress.c b/libarchive/archive_read_support_filter_compress.c index f278ac7d6..05b80a576 100644 --- a/libarchive/archive_read_support_filter_compress.c +++ b/libarchive/archive_read_support_filter_compress.c @@ -198,6 +198,12 @@ compress_bidder_bid(struct archive_read_filter_bidder *self, return (bits_checked); } +static const struct archive_read_filter_vtable +compress_reader_vtable = { + .read = compress_filter_read, + .close = compress_filter_close, +}; + /* * Setup the callbacks. */ @@ -226,8 +232,7 @@ compress_bidder_init(struct archive_read_filter *self) self->data = state; state->out_block_size = out_block_size; state->out_block = out_block; - self->read = compress_filter_read; - self->close = compress_filter_close; + self->vtable = &compress_reader_vtable; /* XXX MOVE THE FOLLOWING OUT OF INIT() XXX */ diff --git a/libarchive/archive_read_support_filter_gzip.c b/libarchive/archive_read_support_filter_gzip.c index 0a9c065a6..4135a6361 100644 --- a/libarchive/archive_read_support_filter_gzip.c +++ b/libarchive/archive_read_support_filter_gzip.c @@ -288,6 +288,15 @@ gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry) return (ARCHIVE_OK); } +static const struct archive_read_filter_vtable +gzip_reader_vtable = { + .read = gzip_filter_read, + .close = gzip_filter_close, +#ifdef HAVE_ZLIB_H + .read_header = gzip_read_header, +#endif +}; + /* * Initialize the filter object. */ @@ -314,11 +323,7 @@ gzip_bidder_init(struct archive_read_filter *self) self->data = state; state->out_block_size = out_block_size; state->out_block = out_block; - self->read = gzip_filter_read; - self->close = gzip_filter_close; -#ifdef HAVE_ZLIB_H - self->read_header = gzip_read_header; -#endif + self->vtable = &gzip_reader_vtable; state->in_stream = 0; /* We're not actually within a stream yet. */ diff --git a/libarchive/archive_read_support_filter_lz4.c b/libarchive/archive_read_support_filter_lz4.c index 082bb7fe7..ae0b08003 100644 --- a/libarchive/archive_read_support_filter_lz4.c +++ b/libarchive/archive_read_support_filter_lz4.c @@ -208,6 +208,12 @@ lz4_reader_init(struct archive_read_filter *self) #else +static const struct archive_read_filter_vtable +lz4_reader_vtable = { + .read = lz4_filter_read, + .close = lz4_filter_close, +}; + /* * Setup the callbacks. */ @@ -228,8 +234,7 @@ lz4_reader_init(struct archive_read_filter *self) self->data = state; state->stage = SELECT_STREAM; - self->read = lz4_filter_read; - self->close = lz4_filter_close; + self->vtable = &lz4_reader_vtable; return (ARCHIVE_OK); } diff --git a/libarchive/archive_read_support_filter_lzop.c b/libarchive/archive_read_support_filter_lzop.c index 98902bfd8..53850928a 100644 --- a/libarchive/archive_read_support_filter_lzop.c +++ b/libarchive/archive_read_support_filter_lzop.c @@ -169,6 +169,13 @@ lzop_bidder_init(struct archive_read_filter *self) return (r); } #else + +static const struct archive_read_filter_vtable +lzop_reader_vtable = { + .read = lzop_filter_read, + .close = lzop_filter_close. +}; + /* * Initialize the filter object. */ @@ -188,8 +195,7 @@ lzop_bidder_init(struct archive_read_filter *self) } self->data = state; - self->read = lzop_filter_read; - self->close = lzop_filter_close; + self->vtable = &lzop_reader_vtable; return (ARCHIVE_OK); } diff --git a/libarchive/archive_read_support_filter_program.c b/libarchive/archive_read_support_filter_program.c index 839354748..885b2c205 100644 --- a/libarchive/archive_read_support_filter_program.c +++ b/libarchive/archive_read_support_filter_program.c @@ -382,6 +382,12 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len) } } +static const struct archive_read_filter_vtable +program_reader_vtable = { + .read = program_filter_read, + .close = program_filter_close, +}; + int __archive_read_program(struct archive_read_filter *self, const char *cmd) { @@ -428,8 +434,7 @@ __archive_read_program(struct archive_read_filter *self, const char *cmd) } self->data = state; - self->read = program_filter_read; - self->close = program_filter_close; + self->vtable = &program_reader_vtable; /* XXX Check that we can read at least one byte? */ return (ARCHIVE_OK); diff --git a/libarchive/archive_read_support_filter_rpm.c b/libarchive/archive_read_support_filter_rpm.c index 2cce17455..67a979cd7 100644 --- a/libarchive/archive_read_support_filter_rpm.c +++ b/libarchive/archive_read_support_filter_rpm.c @@ -127,6 +127,12 @@ rpm_bidder_bid(struct archive_read_filter_bidder *self, return (bits_checked); } +static const struct archive_read_filter_vtable +rpm_reader_vtable = { + .read = rpm_filter_read, + .close = rpm_filter_close, +}; + static int rpm_bidder_init(struct archive_read_filter *self) { @@ -134,8 +140,6 @@ rpm_bidder_init(struct archive_read_filter *self) self->code = ARCHIVE_FILTER_RPM; self->name = "rpm"; - self->read = rpm_filter_read; - self->close = rpm_filter_close; rpm = (struct rpm *)calloc(sizeof(*rpm), 1); if (rpm == NULL) { @@ -146,6 +150,7 @@ rpm_bidder_init(struct archive_read_filter *self) self->data = rpm; rpm->state = ST_LEAD; + self->vtable = &rpm_reader_vtable; return (ARCHIVE_OK); } diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c index 7252a6d67..209b2a159 100644 --- a/libarchive/archive_read_support_filter_uu.c +++ b/libarchive/archive_read_support_filter_uu.c @@ -351,6 +351,12 @@ uudecode_bidder_bid(struct archive_read_filter_bidder *self, return (0); } +static const struct archive_read_filter_vtable +uudecode_reader_vtable = { + .read = uudecode_filter_read, + .close = uudecode_filter_close, +}; + static int uudecode_bidder_init(struct archive_read_filter *self) { @@ -360,8 +366,6 @@ uudecode_bidder_init(struct archive_read_filter *self) self->code = ARCHIVE_FILTER_UU; self->name = "uu"; - self->read = uudecode_filter_read; - self->close = uudecode_filter_close; uudecode = (struct uudecode *)calloc(sizeof(*uudecode), 1); out_buff = malloc(OUT_BUFF_SIZE); @@ -381,6 +385,7 @@ uudecode_bidder_init(struct archive_read_filter *self) uudecode->in_allocated = IN_BUFF_SIZE; uudecode->out_buff = out_buff; uudecode->state = ST_FIND_HEAD; + self->vtable = &uudecode_reader_vtable; return (ARCHIVE_OK); } diff --git a/libarchive/archive_read_support_filter_xz.c b/libarchive/archive_read_support_filter_xz.c index e8b5300c5..ce89807e1 100644 --- a/libarchive/archive_read_support_filter_xz.c +++ b/libarchive/archive_read_support_filter_xz.c @@ -461,6 +461,12 @@ set_error(struct archive_read_filter *self, int ret) } } +static const struct archive_read_filter_vtable +xz_lzma_reader_vtable = { + .read = xz_filter_read, + .close = xz_filter_close, +}; + /* * Setup the callbacks. */ @@ -485,8 +491,7 @@ xz_lzma_bidder_init(struct archive_read_filter *self) self->data = state; state->out_block_size = out_block_size; state->out_block = out_block; - self->read = xz_filter_read; - self->close = xz_filter_close; + self->vtable = &xz_lzma_reader_vtable; state->stream.avail_in = 0; diff --git a/libarchive/archive_read_support_filter_zstd.c b/libarchive/archive_read_support_filter_zstd.c index f7e2923cf..39f25f1bf 100644 --- a/libarchive/archive_read_support_filter_zstd.c +++ b/libarchive/archive_read_support_filter_zstd.c @@ -157,6 +157,12 @@ zstd_bidder_init(struct archive_read_filter *self) #else +static const struct archive_read_filter_vtable +zstd_reader_vtable = { + .read = zstd_filter_read, + .close = zstd_filter_close, +}; + /* * Initialize the filter object */ @@ -189,8 +195,7 @@ zstd_bidder_init(struct archive_read_filter *self) state->out_block_size = out_block_size; state->out_block = out_block; state->dstream = dstream; - self->read = zstd_filter_read; - self->close = zstd_filter_close; + self->vtable = &zstd_reader_vtable; state->eof = 0; state->in_frame = 0; -- 2.47.2