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) 50 struct 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 */ 59 static ssize_t bzip2_filter_read(struct archive_read_filter *, const void **); 60 static 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 */ 69 static int bzip2_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *); 70 static int bzip2_reader_init(struct archive_read_filter *); 71 72 #if ARCHIVE_VERSION_NUMBER < 4000000 73 /* Deprecated; remove in libarchive 4.0 */ 74 int 75 archive_read_support_compression_bzip2(struct archive *a) 76 { 77 return archive_read_support_filter_bzip2(a); 78 } 79 #endif 80 81 static const struct archive_read_filter_bidder_vtable 82 bzip2_bidder_vtable = { 83 .bid = bzip2_reader_bid, 84 .init = bzip2_reader_init, 85 }; 86 87 int 88 archive_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 */ 112 static int 113 bzip2_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 */ 157 static int 158 bzip2_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 174 static const struct archive_read_filter_vtable 175 bzip2_reader_vtable = { 176 .read = bzip2_filter_read, 177 .close = bzip2_filter_close, 178 }; 179 180 /* 181 * Setup the callbacks. 182 */ 183 static int 184 bzip2_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 = calloc(1, sizeof(*state)); 194 out_block = 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 */ 214 static ssize_t 215 bzip2_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 */ 337 static int 338 bzip2_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