diff options
author | kientzle <kientzle@FreeBSD.org> | 2007-05-29 01:00:21 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2007-05-29 01:00:21 +0000 |
commit | 013be331bc10706807599a452a143f4744398e9f (patch) | |
tree | 793787ab8615d768ba51341dfd934a5fb3039728 /lib/libarchive/archive_read.c | |
parent | c611006e893ac2bf962cabe02743954e3b3c3314 (diff) | |
download | FreeBSD-src-013be331bc10706807599a452a143f4744398e9f.zip FreeBSD-src-013be331bc10706807599a452a143f4744398e9f.tar.gz |
libarchive 2.2.3
* "compression_program" support uses an external program
* Portability: no longer uses "struct stat" as a primary
data interchange structure internally
* Part of the above: refactor archive_entry to separate
out copy_stat() and stat() functions
* More complete tests for archive_entry
* Finish archive_entry_clone()
* Isolate major()/minor()/makedev() in archive_entry; remove
these from everywhere else.
* Bug fix: properly handle decompression look-ahead at end-of-data
* Bug fixes to 'ar' support
* Fix memory leak in ZIP reader
* Portability: better timegm() emulation in iso9660 reader
* New write_disk flags to suppress auto dir creation and not
overwrite newer files (for future cpio front-end)
* Simplify trailing-'/' fixup when writing tar and pax
* Test enhancements: fix various compiler warnings, improve
portability, add lots of new tests.
* Documentation: document new functions, first draft of
libarchive_internals.3
MFC after: 14 days
Thanks to: Joerg Sonnenberger (compression_program)
Thanks to: Kai Wang (ar)
Thanks to: Colin Percival (many small fixes)
Thanks to: Many others who sent me various patches and problem reports.
Diffstat (limited to 'lib/libarchive/archive_read.c')
-rw-r--r-- | lib/libarchive/archive_read.c | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/lib/libarchive/archive_read.c b/lib/libarchive/archive_read.c index 4a62a99..e0763f2 100644 --- a/lib/libarchive/archive_read.c +++ b/lib/libarchive/archive_read.c @@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$"); #include "archive_private.h" #include "archive_read_private.h" -static int choose_decompressor(struct archive_read *, const void*, size_t); +static void choose_decompressor(struct archive_read *, const void*, size_t); static int choose_format(struct archive_read *); static off_t dummy_skip(struct archive_read *, off_t); @@ -131,7 +131,6 @@ archive_read_open2(struct archive *_a, void *client_data, struct archive_read *a = (struct archive_read *)_a; const void *buffer; ssize_t bytes_read; - int high_bidder; int e; __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_open"); @@ -163,7 +162,7 @@ archive_read_open2(struct archive *_a, void *client_data, } } - /* Read first block now for format detection. */ + /* Read first block now for compress format detection. */ bytes_read = (client_reader)(&a->archive, client_data, &buffer); if (bytes_read < 0) { @@ -182,12 +181,12 @@ archive_read_open2(struct archive *_a, void *client_data, a->client_data = client_data; /* Select a decompression routine. */ - high_bidder = choose_decompressor(a, buffer, (size_t)bytes_read); - if (high_bidder < 0) + choose_decompressor(a, buffer, (size_t)bytes_read); + if (a->decompressor == NULL) return (ARCHIVE_FATAL); /* Initialize decompression routine with the first block of data. */ - e = (a->decompressors[high_bidder].init)(a, buffer, (size_t)bytes_read); + e = (a->decompressor->init)(a, buffer, (size_t)bytes_read); if (e == ARCHIVE_OK) a->archive.state = ARCHIVE_STATE_HEADER; @@ -196,8 +195,8 @@ archive_read_open2(struct archive *_a, void *client_data, * If the decompressor didn't register a skip function, provide a * dummy compression-layer skip function. */ - if (a->compression_skip == NULL) - a->compression_skip = dummy_skip; + if (a->decompressor->skip == NULL) + a->decompressor->skip = dummy_skip; return (e); } @@ -206,33 +205,37 @@ archive_read_open2(struct archive *_a, void *client_data, * Allow each registered decompression routine to bid on whether it * wants to handle this stream. Return index of winning bidder. */ -static int +static void choose_decompressor(struct archive_read *a, const void *buffer, size_t bytes_read) { - int decompression_slots, i, bid, best_bid, best_bid_slot; + int decompression_slots, i, bid, best_bid; + struct decompressor_t *decompressor, *best_decompressor; decompression_slots = sizeof(a->decompressors) / sizeof(a->decompressors[0]); - best_bid = -1; - best_bid_slot = -1; + best_bid = 0; + a->decompressor = NULL; + best_decompressor = NULL; + decompressor = a->decompressors; for (i = 0; i < decompression_slots; i++) { - if (a->decompressors[i].bid) { - bid = (a->decompressors[i].bid)(buffer, bytes_read); - if ((bid > best_bid) || (best_bid_slot < 0)) { + if (decompressor->bid) { + bid = (decompressor->bid)(buffer, bytes_read); + if (bid > best_bid || best_decompressor == NULL) { best_bid = bid; - best_bid_slot = i; + best_decompressor = decompressor; } } + decompressor ++; } /* * There were no bidders; this is a serious programmer error * and demands a quick and definitive abort. */ - if (best_bid_slot < 0) + if (best_decompressor == NULL) __archive_errx(1, "No decompressors were registered; you " "must call at least one " "archive_read_support_compression_XXX function in order " @@ -245,10 +248,11 @@ choose_decompressor(struct archive_read *a, if (best_bid < 1) { archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Unrecognized archive format"); - return (ARCHIVE_FATAL); + return; } - return (best_bid_slot); + /* Record the best decompressor for this stream. */ + a->decompressor = best_decompressor; } /* @@ -263,7 +267,7 @@ dummy_skip(struct archive_read * a, off_t request) off_t bytes_skipped; for (bytes_skipped = 0; request > 0;) { - bytes_read = (a->compression_read_ahead)(a, &dummy_buffer, 1); + bytes_read = (a->decompressor->read_ahead)(a, &dummy_buffer, 1); if (bytes_read < 0) return (bytes_read); if (bytes_read == 0) { @@ -275,7 +279,7 @@ dummy_skip(struct archive_read * a, off_t request) } if (bytes_read > request) bytes_read = (ssize_t)request; - (a->compression_read_consume)(a, (size_t)bytes_read); + (a->decompressor->consume)(a, (size_t)bytes_read); request -= bytes_read; bytes_skipped += bytes_read; } @@ -326,7 +330,6 @@ archive_read_next_header(struct archive *_a, struct archive_entry **entryp) return (ARCHIVE_FATAL); } a->format = &(a->formats[slot]); - a->pformat_data = &(a->format->format_data); ret = (a->format->read_header)(a, entry); /* @@ -377,7 +380,6 @@ choose_format(struct archive_read *a) a->format = &(a->formats[0]); for (i = 0; i < slots; i++, a->format++) { if (a->format->bid) { - a->pformat_data = &(a->format->format_data); bid = (a->format->bid)(a); if (bid == ARCHIVE_FATAL) return (ARCHIVE_FATAL); @@ -591,6 +593,7 @@ archive_read_close(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; int r = ARCHIVE_OK, r1 = ARCHIVE_OK; + size_t i, n; __archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_ANY, "archive_read_close"); @@ -600,11 +603,21 @@ archive_read_close(struct archive *_a) if (a->cleanup_archive_extract != NULL) r = (a->cleanup_archive_extract)(a); - /* TODO: Finish the format processing. */ + /* TODO: Clean up the formatters. */ + + /* Clean up the decompressors. */ + n = sizeof(a->decompressors)/sizeof(a->decompressors[0]); + for (i = 0; i < n; i++) { + if (a->decompressors[i].finish != NULL) { + r1 = (a->decompressors[i].finish)(a); + if (r1 < r) + r = r1; + } + } - /* Close the input machinery. */ - if (a->compression_finish != NULL) { - r1 = (a->compression_finish)(a); + /* Close the client stream. */ + if (a->client_closer != NULL) { + r1 = ((a->client_closer)(&a->archive, a->client_data)); if (r1 < r) r = r1; } @@ -636,7 +649,7 @@ archive_read_finish(struct archive *_a) /* Cleanup format-specific data. */ slots = sizeof(a->formats) / sizeof(a->formats[0]); for (i = 0; i < slots; i++) { - a->pformat_data = &(a->formats[i].format_data); + a->format = &(a->formats[i]); if (a->formats[i].cleanup) (a->formats[i].cleanup)(a); } @@ -683,7 +696,7 @@ __archive_read_register_format(struct archive_read *a, a->formats[i].read_data = read_data; a->formats[i].read_data_skip = read_data_skip; a->formats[i].cleanup = cleanup; - a->formats[i].format_data = format_data; + a->formats[i].data = format_data; return (ARCHIVE_OK); } } @@ -696,7 +709,7 @@ __archive_read_register_format(struct archive_read *a, * Used internally by decompression routines to register their bid and * initialization functions. */ -int +struct decompressor_t * __archive_read_register_compression(struct archive_read *a, int (*bid)(const void *, size_t), int (*init)(struct archive_read *, const void *, size_t)) @@ -711,14 +724,14 @@ __archive_read_register_compression(struct archive_read *a, for (i = 0; i < number_slots; i++) { if (a->decompressors[i].bid == bid) - return (ARCHIVE_OK); /* We've already installed */ + return (a->decompressors + i); if (a->decompressors[i].bid == NULL) { a->decompressors[i].bid = bid; a->decompressors[i].init = init; - return (ARCHIVE_OK); + return (a->decompressors + i); } } __archive_errx(1, "Not enough slots for compression registration"); - return (ARCHIVE_FATAL); /* Never actually executed. */ + return (NULL); /* Never actually executed. */ } |