From 9de87afec611783439b260bc20f1fc088ad4bbc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Mon, 14 Nov 2022 19:05:42 +0100 Subject: Flush write filters between entries. * Add a flush() method to write filters. * Add an __archive_write_filters_flush() function which iterates over filters in order and invokes the flush method for any filter that has one and that has written data. * Call __archive_write_filters_flush() before writing a new header. --- libarchive/archive_write.c | 31 +++++++++++++++++++++++++++++++ libarchive/archive_write_private.h | 1 + 2 files changed, 32 insertions(+) diff --git a/libarchive/archive_write.c b/libarchive/archive_write.c index 27626b54..ec3c95c5 100644 --- a/libarchive/archive_write.c +++ b/libarchive/archive_write.c @@ -310,6 +310,25 @@ __archive_write_output(struct archive_write *a, const void *buff, size_t length) return (__archive_write_filter(a->filter_first, buff, length)); } +static int +__archive_write_filters_flush(struct archive_write *a) +{ + struct archive_write_filter *f; + int ret, ret1; + + ret = ARCHIVE_OK; + for (f = a->filter_first; f != NULL; f = f->next_filter) { + if (f->flush != NULL && f->bytes_written > 0) { + ret1 = (f->flush)(f); + if (ret1 < ret) + ret = ret1; + if (ret1 < ARCHIVE_WARN) + f->state = ARCHIVE_WRITE_FILTER_STATE_FATAL; + } + } + return (ret); +} + int __archive_write_nulls(struct archive_write *a, size_t length) { @@ -740,6 +759,18 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry) return (ARCHIVE_FAILED); } + /* Flush filters at boundary. */ + r2 = __archive_write_filters_flush(a); + if (r2 == ARCHIVE_FAILED) { + return (ARCHIVE_FAILED); + } + if (r2 == ARCHIVE_FATAL) { + a->archive.state = ARCHIVE_STATE_FATAL; + return (ARCHIVE_FATAL); + } + if (r2 < ret) + ret = r2; + /* Format and write header. */ r2 = ((a->format_write_header)(a, entry)); if (r2 == ARCHIVE_FAILED) { diff --git a/libarchive/archive_write_private.h b/libarchive/archive_write_private.h index 155fdd73..6522e652 100644 --- a/libarchive/archive_write_private.h +++ b/libarchive/archive_write_private.h @@ -53,6 +53,7 @@ struct archive_write_filter { const char *key, const char *value); int (*open)(struct archive_write_filter *); int (*write)(struct archive_write_filter *, const void *, size_t); + int (*flush)(struct archive_write_filter *); int (*close)(struct archive_write_filter *); int (*free)(struct archive_write_filter *); void *data; -- cgit v1.2.1