1/*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "archive_platform.h" 27 28#ifdef HAVE_ERRNO_H 29#include <errno.h> 30#endif 31#include <stdio.h> 32#ifdef HAVE_STDLIB_H 33#include <stdlib.h> 34#endif 35#ifdef HAVE_STRING_H 36#include <string.h> 37#endif 38#ifdef HAVE_UNISTD_H 39#include <unistd.h> 40#endif 41#ifdef HAVE_BZLIB_H 42#include <bzlib.h> 43#endif 44 45#include "archive.h" 46#include "archive_private.h" 47#include "archive_read_private.h" 48 49#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 50struct private_data { 51 bz_stream stream; 52 char *out_block; 53 size_t out_block_size; 54 char valid; /* True = decompressor is initialized */ 55 char eof; /* True = found end of compressed data. */ 56}; 57 58/* Bzip2 filter */ 59static ssize_t bzip2_filter_read(struct archive_read_filter *, const void **); 60static int bzip2_filter_close(struct archive_read_filter *); 61#endif 62 63/* 64 * Note that we can detect bzip2 archives even if we can't decompress 65 * them. (In fact, we like detecting them because we can give better 66 * error messages.) So the bid framework here gets compiled even 67 * if bzlib is unavailable. 68 */ 69static int bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); 70static int bzip2_reader_init(struct archive_read_filter *); 71 72#if ARCHIVE_VERSION_NUMBER < 4000000 73/* Deprecated; remove in libarchive 4.0 */ 74int 75archive_read_support_compression_bzip2(struct archive *a) 76{ 77 return archive_read_support_filter_bzip2(a); 78} 79#endif 80 81static const struct archive_read_filter_bidder_vtable 82bzip2_bidder_vtable = { 83 .bid = bzip2_reader_bid, 84 .init = bzip2_reader_init, 85}; 86 87int 88archive_read_support_filter_bzip2(struct archive *_a) 89{ 90 struct archive_read *a = (struct archive_read *)_a; 91 92 if (__archive_read_register_bidder(a, NULL, "bzip2", 93 &bzip2_bidder_vtable) != ARCHIVE_OK) 94 return (ARCHIVE_FATAL); 95 96#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 97 return (ARCHIVE_OK); 98#else 99 archive_set_error(_a, ARCHIVE_ERRNO_MISC, 100 "Using external bzip2 program"); 101 return (ARCHIVE_WARN); 102#endif 103} 104 105/* 106 * Test whether we can handle this data. 107 * 108 * This logic returns zero if any part of the signature fails. It 109 * also tries to Do The Right Thing if a very short buffer prevents us 110 * from verifying as much as we would like. 111 */ 112static int 113bzip2_reader_bid(struct archive_read_filter_bidder *self, struct archive_read_filter *filter) 114{ 115 const unsigned char *buffer; 116 ssize_t avail; 117 int bits_checked; 118 119 (void)self; /* UNUSED */ 120 121 /* Minimal bzip2 archive is 14 bytes. */ 122 buffer = __archive_read_filter_ahead(filter, 14, &avail); 123 if (buffer == NULL) 124 return (0); 125 126 /* First three bytes must be "BZh" */ 127 bits_checked = 0; 128 if (memcmp(buffer, "BZh", 3) != 0) 129 return (0); 130 bits_checked += 24; 131 132 /* Next follows a compression flag which must be an ASCII digit. */ 133 if (buffer[3] < '1' || buffer[3] > '9') 134 return (0); 135 bits_checked += 5; 136 137 /* After BZh[1-9], there must be either a data block 138 * which begins with 0x314159265359 or an end-of-data 139 * marker of 0x177245385090. */ 140 if (memcmp(buffer + 4, "\x31\x41\x59\x26\x53\x59", 6) == 0) 141 bits_checked += 48; 142 else if (memcmp(buffer + 4, "\x17\x72\x45\x38\x50\x90", 6) == 0) 143 bits_checked += 48; 144 else 145 return (0); 146 147 return (bits_checked); 148} 149 150#if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) 151 152/* 153 * If we don't have the library on this system, we can't actually do the 154 * decompression. We can, however, still detect compressed archives 155 * and emit a useful message. 156 */ 157static int 158bzip2_reader_init(struct archive_read_filter *self) 159{ 160 int r; 161 162 r = __archive_read_program(self, "bzip2 -d"); 163 /* Note: We set the format here even if __archive_read_program() 164 * above fails. We do, after all, know what the format is 165 * even if we weren't able to read it. */ 166 self->code = ARCHIVE_FILTER_BZIP2; 167 self->name = "bzip2"; 168 return (r); 169} 170 171 172#else 173 174static const struct archive_read_filter_vtable 175bzip2_reader_vtable = { 176 .read = bzip2_filter_read, 177 .close = bzip2_filter_close, 178}; 179 180/* 181 * Setup the callbacks. 182 */ 183static int 184bzip2_reader_init(struct archive_read_filter *self) 185{ 186 static const size_t out_block_size = 64 * 1024; 187 void *out_block; 188 struct private_data *state; 189 190 self->code = ARCHIVE_FILTER_BZIP2; 191 self->name = "bzip2"; 192 193 state = (struct private_data *)calloc(1, sizeof(*state)); 194 out_block = (unsigned char *)malloc(out_block_size); 195 if (state == NULL || out_block == NULL) { 196 archive_set_error(&self->archive->archive, ENOMEM, 197 "Can't allocate data for bzip2 decompression"); 198 free(out_block); 199 free(state); 200 return (ARCHIVE_FATAL); 201 } 202 203 self->data = state; 204 state->out_block_size = out_block_size; 205 state->out_block = out_block; 206 self->vtable = &bzip2_reader_vtable; 207 208 return (ARCHIVE_OK); 209} 210 211/* 212 * Return the next block of decompressed data. 213 */ 214static ssize_t 215bzip2_filter_read(struct archive_read_filter *self, const void **p) 216{ 217 struct private_data *state; 218 size_t decompressed; 219 const char *read_buf; 220 ssize_t ret; 221 222 state = (struct private_data *)self->data; 223 224 if (state->eof) { 225 *p = NULL; 226 return (0); 227 } 228 229 /* Empty our output buffer. */ 230 state->stream.next_out = state->out_block; 231 state->stream.avail_out = (uint32_t)state->out_block_size; 232 233 /* Try to fill the output buffer. */ 234 for (;;) { 235 if (!state->valid) { 236 if (bzip2_reader_bid(self->bidder, self->upstream) == 0) { 237 state->eof = 1; 238 *p = state->out_block; 239 decompressed = state->stream.next_out 240 - state->out_block; 241 return (decompressed); 242 } 243 /* Initialize compression library. */ 244 ret = BZ2_bzDecompressInit(&(state->stream), 245 0 /* library verbosity */, 246 0 /* don't use low-mem algorithm */); 247 248 /* If init fails, try low-memory algorithm instead. */ 249 if (ret == BZ_MEM_ERROR) 250 ret = BZ2_bzDecompressInit(&(state->stream), 251 0 /* library verbosity */, 252 1 /* do use low-mem algo */); 253 254 if (ret != BZ_OK) { 255 const char *detail = NULL; 256 int err = ARCHIVE_ERRNO_MISC; 257 switch (ret) { 258 case BZ_PARAM_ERROR: 259 detail = "invalid setup parameter"; 260 break; 261 case BZ_MEM_ERROR: 262 err = ENOMEM; 263 detail = "out of memory"; 264 break; 265 case BZ_CONFIG_ERROR: 266 detail = "mis-compiled library"; 267 break; 268 } 269 archive_set_error(&self->archive->archive, err, 270 "Internal error initializing decompressor%s%s", 271 detail == NULL ? "" : ": ", 272 detail); 273 return (ARCHIVE_FATAL); 274 } 275 state->valid = 1; 276 } 277 278 /* stream.next_in is really const, but bzlib 279 * doesn't declare it so. <sigh> */ 280 read_buf = 281 __archive_read_filter_ahead(self->upstream, 1, &ret); 282 if (read_buf == NULL) { 283 archive_set_error(&self->archive->archive, 284 ARCHIVE_ERRNO_MISC, 285 "truncated bzip2 input"); 286 return (ARCHIVE_FATAL); 287 } 288 state->stream.next_in = (char *)(uintptr_t)read_buf; 289 state->stream.avail_in = (uint32_t)ret; 290 /* There is no more data, return whatever we have. */ 291 if (ret == 0) { 292 state->eof = 1; 293 *p = state->out_block; 294 decompressed = state->stream.next_out 295 - state->out_block; 296 return (decompressed); 297 } 298 299 /* Decompress as much as we can in one pass. */ 300 ret = BZ2_bzDecompress(&(state->stream)); 301 __archive_read_filter_consume(self->upstream, 302 state->stream.next_in - read_buf); 303 304 switch (ret) { 305 case BZ_STREAM_END: /* Found end of stream. */ 306 switch (BZ2_bzDecompressEnd(&(state->stream))) { 307 case BZ_OK: 308 break; 309 default: 310 archive_set_error(&(self->archive->archive), 311 ARCHIVE_ERRNO_MISC, 312 "Failed to clean up decompressor"); 313 return (ARCHIVE_FATAL); 314 } 315 state->valid = 0; 316 /* FALLTHROUGH */ 317 case BZ_OK: /* Decompressor made some progress. */ 318 /* If we filled our buffer, update stats and return. */ 319 if (state->stream.avail_out == 0) { 320 *p = state->out_block; 321 decompressed = state->stream.next_out 322 - state->out_block; 323 return (decompressed); 324 } 325 break; 326 default: /* Return an error. */ 327 archive_set_error(&self->archive->archive, 328 ARCHIVE_ERRNO_MISC, "bzip decompression failed"); 329 return (ARCHIVE_FATAL); 330 } 331 } 332} 333 334/* 335 * Clean up the decompressor. 336 */ 337static int 338bzip2_filter_close(struct archive_read_filter *self) 339{ 340 struct private_data *state; 341 int ret = ARCHIVE_OK; 342 343 state = (struct private_data *)self->data; 344 345 if (state->valid) { 346 switch (BZ2_bzDecompressEnd(&state->stream)) { 347 case BZ_OK: 348 break; 349 default: 350 archive_set_error(&self->archive->archive, 351 ARCHIVE_ERRNO_MISC, 352 "Failed to clean up decompressor"); 353 ret = ARCHIVE_FATAL; 354 } 355 state->valid = 0; 356 } 357 358 free(state->out_block); 359 free(state); 360 return (ret); 361} 362 363#endif /* HAVE_BZLIB_H && BZ_CONFIG_ERROR */ 364