summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@des.no>2022-11-14 19:05:42 +0100
committerMartin Matuška <martin@matuska.de>2023-01-09 15:23:53 +0100
commit9de87afec611783439b260bc20f1fc088ad4bbc8 (patch)
tree2b2ab50a33fb8824d65211f1e31aaad05347ec01
parentc7b51f04c57bac386be9548b68bee7d511f18a76 (diff)
downloadlibarchive-9de87afec611783439b260bc20f1fc088ad4bbc8.tar.gz
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.
-rw-r--r--libarchive/archive_write.c31
-rw-r--r--libarchive/archive_write_private.h1
2 files changed, 32 insertions, 0 deletions
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;