aboutsummaryrefslogtreecommitdiff
path: root/lib/libarchive/archive_read_support_compression_bzip2.c
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@FreeBSD.org>2009-03-05 02:19:42 +0000
committerTim Kientzle <kientzle@FreeBSD.org>2009-03-05 02:19:42 +0000
commitfacbbae9f9c0085b9c8ccc26b5c42069f14eb5f1 (patch)
treea2be4a14d3ab97078c1d2359ee7402136230237a /lib/libarchive/archive_read_support_compression_bzip2.c
parenta48ae5111e6c4232f0c0fefcdb463c8efd2d5892 (diff)
Notes
Diffstat (limited to 'lib/libarchive/archive_read_support_compression_bzip2.c')
-rw-r--r--lib/libarchive/archive_read_support_compression_bzip2.c175
1 files changed, 60 insertions, 115 deletions
diff --git a/lib/libarchive/archive_read_support_compression_bzip2.c b/lib/libarchive/archive_read_support_compression_bzip2.c
index 6849771c98071..ea39cfee3a704 100644
--- a/lib/libarchive/archive_read_support_compression_bzip2.c
+++ b/lib/libarchive/archive_read_support_compression_bzip2.c
@@ -57,9 +57,9 @@ struct private_data {
char eof; /* True = found end of compressed data. */
};
-/* Bzip2 source */
-static ssize_t bzip2_source_read(struct archive_read_source *, const void **);
-static int bzip2_source_close(struct archive_read_source *);
+/* Bzip2 filter */
+static ssize_t bzip2_filter_read(struct archive_read_filter *, const void **);
+static int bzip2_filter_close(struct archive_read_filter *);
#endif
/*
@@ -68,17 +68,15 @@ static int bzip2_source_close(struct archive_read_source *);
* error messages.) So the bid framework here gets compiled even
* if bzlib is unavailable.
*/
-static int bzip2_reader_bid(struct archive_reader *, const void *, size_t);
-static struct archive_read_source *bzip2_reader_init(struct archive_read *,
- struct archive_reader *, struct archive_read_source *,
- const void *, size_t);
-static int bzip2_reader_free(struct archive_reader *);
+static int bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
+static int bzip2_reader_init(struct archive_read_filter *);
+static int bzip2_reader_free(struct archive_read_filter_bidder *);
int
archive_read_support_compression_bzip2(struct archive *_a)
{
struct archive_read *a = (struct archive_read *)_a;
- struct archive_reader *reader = __archive_read_get_reader(a);
+ struct archive_read_filter_bidder *reader = __archive_read_get_bidder(a);
if (reader == NULL)
return (ARCHIVE_FATAL);
@@ -91,7 +89,7 @@ archive_read_support_compression_bzip2(struct archive *_a)
}
static int
-bzip2_reader_free(struct archive_reader *self){
+bzip2_reader_free(struct archive_read_filter_bidder *self){
(void)self; /* UNUSED */
return (ARCHIVE_OK);
}
@@ -104,61 +102,38 @@ bzip2_reader_free(struct archive_reader *self){
* from verifying as much as we would like.
*/
static int
-bzip2_reader_bid(struct archive_reader *self, const void *buff, size_t len)
+bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter)
{
const unsigned char *buffer;
+ size_t avail;
int bits_checked;
(void)self; /* UNUSED */
- if (len < 1)
+ /* Minimal bzip2 archive is 14 bytes. */
+ buffer = __archive_read_filter_ahead(filter, 14, &avail);
+ if (buffer == NULL)
return (0);
- buffer = (const unsigned char *)buff;
+ /* First three bytes must be "BZh" */
bits_checked = 0;
- if (buffer[0] != 'B') /* Verify first ID byte. */
+ if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')
return (0);
- bits_checked += 8;
- if (len < 2)
- return (bits_checked);
-
- if (buffer[1] != 'Z') /* Verify second ID byte. */
- return (0);
- bits_checked += 8;
- if (len < 3)
- return (bits_checked);
-
- if (buffer[2] != 'h') /* Verify third ID byte. */
- return (0);
- bits_checked += 8;
- if (len < 4)
- return (bits_checked);
+ bits_checked += 24;
+ /* Next follows a compression flag which must be an ASCII digit. */
if (buffer[3] < '1' || buffer[3] > '9')
return (0);
bits_checked += 5;
- if (len < 5)
- return (bits_checked);
/* After BZh[1-9], there must be either a data block
* which begins with 0x314159265359 or an end-of-data
* marker of 0x177245385090. */
-
- if (buffer[4] == 0x31) {
- /* Verify the data block signature. */
- size_t s = len;
- if (s > 10) s = 10;
- if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", s - 4) != 0)
- return (0);
- bits_checked += 8 * (s - 4);
- } else if (buffer[4] == 0x17) {
- /* Verify the end-of-data marker. */
- size_t s = len;
- if (s > 10) s = 10;
- if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", s - 4) != 0)
- return (0);
- bits_checked += 8 * (s - 4);
- } else
+ if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", 6) == 0)
+ bits_checked += 48;
+ else if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", 6) == 0)
+ bits_checked += 48;
+ else
return (0);
return (bits_checked);
@@ -171,19 +146,13 @@ bzip2_reader_bid(struct archive_reader *self, const void *buff, size_t len)
* decompression. We can, however, still detect compressed archives
* and emit a useful message.
*/
-static struct archive_read_source *
-bzip2_reader_init(struct archive_read *a, struct archive_reader *reader,
- struct archive_read_source *upstream, const void *buff, size_t n)
+static int
+bzip2_reader_init(struct archive_read_filter *self)
{
- (void)a; /* UNUSED */
- (void)reader; /* UNUSED */
- (void)upstream; /* UNUSED */
- (void)buff; /* UNUSED */
- (void)n; /* UNUSED */
- archive_set_error(&a->archive, -1,
+ archive_set_error(&self->archive->archive, -1,
"This version of libarchive was compiled without bzip2 support");
- return (NULL);
+ return (ARCHIVE_FATAL);
}
@@ -192,67 +161,45 @@ bzip2_reader_init(struct archive_read *a, struct archive_reader *reader,
/*
* Setup the callbacks.
*/
-static struct archive_read_source *
-bzip2_reader_init(struct archive_read *a, struct archive_reader *reader,
- struct archive_read_source *upstream, const void *buff, size_t n)
+static int
+bzip2_reader_init(struct archive_read_filter *self)
{
static const size_t out_block_size = 64 * 1024;
void *out_block;
- struct archive_read_source *self;
struct private_data *state;
- (void)reader; /* UNUSED */
+ self->code = ARCHIVE_COMPRESSION_BZIP2;
+ self->name = "bzip2";
- a->archive.compression_code = ARCHIVE_COMPRESSION_BZIP2;
- a->archive.compression_name = "bzip2";
-
- self = calloc(sizeof(*self), 1);
state = (struct private_data *)calloc(sizeof(*state), 1);
out_block = (unsigned char *)malloc(out_block_size);
if (self == NULL || state == NULL || out_block == NULL) {
- archive_set_error(&a->archive, ENOMEM,
- "Can't allocate data for %s decompression",
- a->archive.compression_name);
+ archive_set_error(&self->archive->archive, ENOMEM,
+ "Can't allocate data for bzip2 decompression");
free(out_block);
free(state);
- free(self);
- return (NULL);
+ return (ARCHIVE_FATAL);
}
-
- self->archive = a;
self->data = state;
state->out_block_size = out_block_size;
state->out_block = out_block;
- self->upstream = upstream;
- self->read = bzip2_source_read;
+ self->read = bzip2_filter_read;
self->skip = NULL; /* not supported */
- self->close = bzip2_source_close;
-
- /*
- * A bug in bzlib.h: stream.next_in should be marked 'const'
- * but isn't (the library never alters data through the
- * next_in pointer, only reads it). The result: this ugly
- * cast to remove 'const'.
- */
- state->stream.next_in = (char *)(uintptr_t)(const void *)buff;
- state->stream.avail_in = n;
-
- state->stream.next_out = state->out_block;
- state->stream.avail_out = state->out_block_size;
+ self->close = bzip2_filter_close;
- return (self);
+ return (ARCHIVE_OK);
}
/*
* Return the next block of decompressed data.
*/
static ssize_t
-bzip2_source_read(struct archive_read_source *self, const void **p)
+bzip2_filter_read(struct archive_read_filter *self, const void **p)
{
struct private_data *state;
size_t read_avail, decompressed;
- const void *read_buf;
+ unsigned char *read_buf;
int ret;
state = (struct private_data *)self->data;
@@ -269,29 +216,8 @@ bzip2_source_read(struct archive_read_source *self, const void **p)
/* Try to fill the output buffer. */
for (;;) {
- /* If the last upstream block is done, get another one. */
- if (state->stream.avail_in == 0) {
- ret = (self->upstream->read)(self->upstream,
- &read_buf);
- /* stream.next_in is really const, but bzlib
- * doesn't declare it so. <sigh> */
- state->stream.next_in
- = (unsigned char *)(uintptr_t)read_buf;
- if (ret < 0)
- return (ARCHIVE_FATAL);
- /* There is no more data, return whatever we have. */
- if (ret == 0) {
- state->eof = 1;
- *p = state->out_block;
- decompressed = state->stream.next_out
- - state->out_block;
- return (decompressed);
- }
- state->stream.avail_in = ret;
- }
-
if (!state->valid) {
- if (state->stream.next_in[0] != 'B') {
+ if (bzip2_reader_bid(self->bidder, self->upstream) == 0) {
state->eof = 1;
*p = state->out_block;
decompressed = state->stream.next_out
@@ -333,8 +259,28 @@ bzip2_source_read(struct archive_read_source *self, const void **p)
state->valid = 1;
}
+ /* stream.next_in is really const, but bzlib
+ * doesn't declare it so. <sigh> */
+ read_buf = (unsigned char *)(uintptr_t)
+ __archive_read_filter_ahead(self->upstream, 1, &ret);
+ if (read_buf == NULL)
+ return (ARCHIVE_FATAL);
+ state->stream.next_in = read_buf;
+ state->stream.avail_in = ret;
+ /* There is no more data, return whatever we have. */
+ if (ret == 0) {
+ state->eof = 1;
+ *p = state->out_block;
+ decompressed = state->stream.next_out
+ - state->out_block;
+ return (decompressed);
+ }
+
/* Decompress as much as we can in one pass. */
ret = BZ2_bzDecompress(&(state->stream));
+ __archive_read_filter_consume(self->upstream,
+ (unsigned char *)state->stream.next_in - read_buf);
+
switch (ret) {
case BZ_STREAM_END: /* Found end of stream. */
switch (BZ2_bzDecompressEnd(&(state->stream))) {
@@ -369,7 +315,7 @@ bzip2_source_read(struct archive_read_source *self, const void **p)
* Clean up the decompressor.
*/
static int
-bzip2_source_close(struct archive_read_source *self)
+bzip2_filter_close(struct archive_read_filter *self)
{
struct private_data *state;
int ret = ARCHIVE_OK;
@@ -390,7 +336,6 @@ bzip2_source_close(struct archive_read_source *self)
free(state->out_block);
free(state);
- free(self);
return (ARCHIVE_OK);
}