summaryrefslogtreecommitdiff
path: root/Utilities/cmlibarchive/libarchive/archive_write.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmlibarchive/libarchive/archive_write.c')
-rw-r--r--Utilities/cmlibarchive/libarchive/archive_write.c91
1 files changed, 73 insertions, 18 deletions
diff --git a/Utilities/cmlibarchive/libarchive/archive_write.c b/Utilities/cmlibarchive/libarchive/archive_write.c
index e8daf530d2..98a55fb2aa 100644
--- a/Utilities/cmlibarchive/libarchive/archive_write.c
+++ b/Utilities/cmlibarchive/libarchive/archive_write.c
@@ -212,6 +212,7 @@ __archive_write_allocate_filter(struct archive *_a)
f = calloc(1, sizeof(*f));
f->archive = _a;
+ f->state = ARCHIVE_WRITE_FILTER_STATE_NEW;
if (a->filter_first == NULL)
a->filter_first = f;
else
@@ -228,6 +229,9 @@ __archive_write_filter(struct archive_write_filter *f,
const void *buff, size_t length)
{
int r;
+ /* Never write to non-open filters */
+ if (f->state != ARCHIVE_WRITE_FILTER_STATE_OPEN)
+ return(ARCHIVE_FATAL);
if (length == 0)
return(ARCHIVE_OK);
if (f->write == NULL)
@@ -240,27 +244,70 @@ __archive_write_filter(struct archive_write_filter *f,
}
/*
- * Open a filter.
+ * Recursive function for opening the filter chain
+ * Last filter is opened first
*/
-int
+static int
__archive_write_open_filter(struct archive_write_filter *f)
{
- if (f->open == NULL)
+ int ret;
+
+ ret = ARCHIVE_OK;
+ if (f->next_filter != NULL)
+ ret = __archive_write_open_filter(f->next_filter);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ if (f->state != ARCHIVE_WRITE_FILTER_STATE_NEW)
+ return (ARCHIVE_FATAL);
+ if (f->open == NULL) {
+ f->state = ARCHIVE_WRITE_FILTER_STATE_OPEN;
return (ARCHIVE_OK);
- return (f->open)(f);
+ }
+ ret = (f->open)(f);
+ if (ret == ARCHIVE_OK)
+ f->state = ARCHIVE_WRITE_FILTER_STATE_OPEN;
+ else
+ f->state = ARCHIVE_WRITE_FILTER_STATE_FATAL;
+ return (ret);
}
/*
- * Close a filter.
+ * Open all filters
*/
-int
-__archive_write_close_filter(struct archive_write_filter *f)
+static int
+__archive_write_filters_open(struct archive_write *a)
{
- if (f->close != NULL)
- return (f->close)(f);
- if (f->next_filter != NULL)
- return (__archive_write_close_filter(f->next_filter));
- return (ARCHIVE_OK);
+ return (__archive_write_open_filter(a->filter_first));
+}
+
+/*
+ * Close all filtes
+ */
+static int
+__archive_write_filters_close(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) {
+ /* Do not close filters that are not open */
+ if (f->state == ARCHIVE_WRITE_FILTER_STATE_OPEN) {
+ if (f->close != NULL) {
+ ret1 = (f->close)(f);
+ if (ret1 < ret)
+ ret = ret1;
+ if (ret1 == ARCHIVE_OK) {
+ f->state =
+ ARCHIVE_WRITE_FILTER_STATE_CLOSED;
+ } else {
+ f->state =
+ ARCHIVE_WRITE_FILTER_STATE_FATAL;
+ }
+ } else
+ f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED;
+ }
+ }
+ return (ret);
}
int
@@ -292,6 +339,7 @@ archive_write_client_open(struct archive_write_filter *f)
struct archive_none *state;
void *buffer;
size_t buffer_size;
+ int ret;
f->bytes_per_block = archive_write_get_bytes_per_block(f->archive);
f->bytes_in_last_block =
@@ -316,7 +364,13 @@ archive_write_client_open(struct archive_write_filter *f)
if (a->client_opener == NULL)
return (ARCHIVE_OK);
- return (a->client_opener(f->archive, a->client_data));
+ ret = a->client_opener(f->archive, a->client_data);
+ if (ret != ARCHIVE_OK) {
+ free(state->buffer);
+ free(state);
+ f->data = NULL;
+ }
+ return (ret);
}
static int
@@ -439,8 +493,6 @@ archive_write_client_close(struct archive_write_filter *f)
(*a->client_closer)(&a->archive, a->client_data);
free(state->buffer);
free(state);
- /* Clear the close handler myself not to be called again. */
- f->close = NULL;
a->client_data = NULL;
/* Clear passphrase. */
if (a->passphrase != NULL) {
@@ -448,6 +500,8 @@ archive_write_client_close(struct archive_write_filter *f)
free(a->passphrase);
a->passphrase = NULL;
}
+ /* Clear the close handler myself not to be called again. */
+ f->state = ARCHIVE_WRITE_FILTER_STATE_CLOSED;
return (ret);
}
@@ -477,9 +531,10 @@ archive_write_open(struct archive *_a, void *client_data,
client_filter->write = archive_write_client_write;
client_filter->close = archive_write_client_close;
- ret = __archive_write_open_filter(a->filter_first);
+ ret = __archive_write_filters_open(a);
if (ret < ARCHIVE_WARN) {
- r1 = __archive_write_close_filter(a->filter_first);
+ r1 = __archive_write_filters_close(a);
+ __archive_write_filters_free(_a);
return (r1 < ret ? r1 : ret);
}
@@ -521,7 +576,7 @@ _archive_write_close(struct archive *_a)
}
/* Finish the compression and close the stream. */
- r1 = __archive_write_close_filter(a->filter_first);
+ r1 = __archive_write_filters_close(a);
if (r1 < r)
r = r1;