summaryrefslogtreecommitdiffstats
path: root/lib/libarchive/archive_read_support_compression_none.c
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2007-12-30 04:58:22 +0000
committerkientzle <kientzle@FreeBSD.org>2007-12-30 04:58:22 +0000
commit2b8395148ff378e52a5e00c0d2ac0123258b759b (patch)
tree743c28601a2502c30676ab2adfbbb665fa3f38b7 /lib/libarchive/archive_read_support_compression_none.c
parentb1a3a611be764b44dbdd47a17ec5076bcfbe6e88 (diff)
downloadFreeBSD-src-2b8395148ff378e52a5e00c0d2ac0123258b759b.zip
FreeBSD-src-2b8395148ff378e52a5e00c0d2ac0123258b759b.tar.gz
Update libarchive to 2.4.10. This includes a number of improvements
that I've been working on but put off committing until after the RELENG_7 branch, including: * New manpages: cpio.5 mtree.5 * New archive_entry_strmode() * New archive_entry_link_resolver() * New read support: mtree format * Internal API change: read format auction only runs once * Running the auction only once allowed simplifying a lot of bid logic. * Cpio robustness: search for next header after a sync error * Support device nodes on ISO9660 images * Eliminate a lot of unnecessary copies for uncompressed archives * Corrected handling of new GNU --sparse --posix formats * Correctly handle a zero-byte write to a compressed archive * Fixed memory leaks Many of these improvements were motivated by the upcoming bsdcpio front-end. There have also been extensive improvements to the libarchive_test test harness, which I'll commit separately.
Diffstat (limited to 'lib/libarchive/archive_read_support_compression_none.c')
-rw-r--r--lib/libarchive/archive_read_support_compression_none.c105
1 files changed, 55 insertions, 50 deletions
diff --git a/lib/libarchive/archive_read_support_compression_none.c b/lib/libarchive/archive_read_support_compression_none.c
index 99586c0..2b9d43f 100644
--- a/lib/libarchive/archive_read_support_compression_none.c
+++ b/lib/libarchive/archive_read_support_compression_none.c
@@ -170,56 +170,45 @@ archive_decompressor_none_read_ahead(struct archive_read *a, const void **buff,
min = state->buffer_size;
/*
- * Try to satisfy the request directly from the client
- * buffer. We can do this if all of the data in the copy
- * buffer was copied from the current client buffer. This
- * also covers the case where the copy buffer is empty and
- * the client buffer has all the data we need.
+ * Keep pulling more data until we can satisfy the request.
*/
- if (state->client_total >= state->client_avail + state->avail
- && state->client_avail + state->avail >= min) {
- state->client_avail += state->avail;
- state->client_next -= state->avail;
- state->avail = 0;
- state->next = state->buffer;
- *buff = state->client_next;
- return (state->client_avail);
- }
+ for (;;) {
- /*
- * If we can't use client buffer, we'll have to use copy buffer.
- */
+ /*
+ * If we can satisfy from the copy buffer, we're done.
+ */
+ if (state->avail >= min) {
+ *buff = state->next;
+ return (state->avail);
+ }
- /* Move data forward in copy buffer if necessary. */
- if (state->next > state->buffer &&
- state->next + min > state->buffer + state->buffer_size) {
- if (state->avail > 0)
- memmove(state->buffer, state->next, state->avail);
- state->next = state->buffer;
- }
+ /*
+ * We can satisfy directly from client buffer if everything
+ * currently in the copy buffer is still in the client buffer.
+ */
+ if (state->client_total >= state->client_avail + state->avail
+ && state->client_avail + state->avail >= min) {
+ /* "Roll back" to client buffer. */
+ state->client_avail += state->avail;
+ state->client_next -= state->avail;
+ /* Copy buffer is now empty. */
+ state->avail = 0;
+ state->next = state->buffer;
+ /* Return data from client buffer. */
+ *buff = state->client_next;
+ return (state->client_avail);
+ }
- /* Collect data in copy buffer to fulfill request. */
- while (state->avail < min) {
- /* Copy data from client buffer to our copy buffer. */
- if (state->client_avail > 0) {
- /* First estimate: copy to fill rest of buffer. */
- size_t tocopy = (state->buffer + state->buffer_size)
- - (state->next + state->avail);
- /* Don't copy more than is available. */
- if (tocopy > state->client_avail)
- tocopy = state->client_avail;
- memcpy(state->next + state->avail, state->client_next,
- tocopy);
- state->client_next += tocopy;
- state->client_avail -= tocopy;
- state->avail += tocopy;
- } else {
- /* There is no more client data: fetch more. */
- /*
- * It seems to me that const void ** and const
- * char ** should be compatible, but they
- * aren't, hence the cast.
- */
+ /* Move data forward in copy buffer if necessary. */
+ if (state->next > state->buffer &&
+ state->next + min > state->buffer + state->buffer_size) {
+ if (state->avail > 0)
+ memmove(state->buffer, state->next, state->avail);
+ state->next = state->buffer;
+ }
+
+ /* If we've used up the client data, get more. */
+ if (state->client_avail <= 0) {
bytes_read = (a->client_reader)(&a->archive,
a->client_data, &state->client_buff);
if (bytes_read < 0) { /* Read error. */
@@ -232,17 +221,33 @@ archive_decompressor_none_read_ahead(struct archive_read *a, const void **buff,
state->client_total = state->client_avail = 0;
state->client_next = state->client_buff = NULL;
state->end_of_file = 1;
- break;
+ /* Return whatever we do have. */
+ *buff = state->next;
+ return (state->avail);
}
a->archive.raw_position += bytes_read;
state->client_total = bytes_read;
state->client_avail = state->client_total;
state->client_next = state->client_buff;
}
+ else
+ {
+ /* We can add client data to copy buffer. */
+ /* First estimate: copy to fill rest of buffer. */
+ size_t tocopy = (state->buffer + state->buffer_size)
+ - (state->next + state->avail);
+ /* Don't copy more than is available. */
+ if (tocopy > state->client_avail)
+ tocopy = state->client_avail;
+ memcpy(state->next + state->avail, state->client_next,
+ tocopy);
+ /* Remove this data from client buffer. */
+ state->client_next += tocopy;
+ state->client_avail -= tocopy;
+ /* add it to copy buffer. */
+ state->avail += tocopy;
+ }
}
-
- *buff = state->next;
- return (state->avail);
}
/*
OpenPOWER on IntegriCloud