1228753Smm/*- 2228753Smm * Copyright (c) 2009 Michihiro NAKAJIMA 3228753Smm * Copyright (c) 2003-2008 Tim Kientzle and Miklos Vajna 4228753Smm * All rights reserved. 5228753Smm * 6228753Smm * Redistribution and use in source and binary forms, with or without 7228753Smm * modification, are permitted provided that the following conditions 8228753Smm * are met: 9228753Smm * 1. Redistributions of source code must retain the above copyright 10228753Smm * notice, this list of conditions and the following disclaimer. 11228753Smm * 2. Redistributions in binary form must reproduce the above copyright 12228753Smm * notice, this list of conditions and the following disclaimer in the 13228753Smm * documentation and/or other materials provided with the distribution. 14228753Smm * 15228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25228753Smm */ 26228753Smm 27228753Smm#include "archive_platform.h" 28228753Smm 29229592Smm__FBSDID("$FreeBSD$"); 30228753Smm 31228753Smm#ifdef HAVE_ERRNO_H 32228753Smm#include <errno.h> 33228753Smm#endif 34228753Smm#include <stdio.h> 35228753Smm#ifdef HAVE_STDLIB_H 36228753Smm#include <stdlib.h> 37228753Smm#endif 38228753Smm#ifdef HAVE_STRING_H 39228753Smm#include <string.h> 40228753Smm#endif 41228753Smm#ifdef HAVE_UNISTD_H 42228753Smm#include <unistd.h> 43228753Smm#endif 44228753Smm#if HAVE_LZMA_H 45228753Smm#include <lzma.h> 46228753Smm#elif HAVE_LZMADEC_H 47228753Smm#include <lzmadec.h> 48228753Smm#endif 49228753Smm 50228753Smm#include "archive.h" 51228753Smm#include "archive_endian.h" 52228753Smm#include "archive_private.h" 53228753Smm#include "archive_read_private.h" 54228753Smm 55228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 56228753Smm 57228753Smmstruct private_data { 58228753Smm lzma_stream stream; 59228753Smm unsigned char *out_block; 60228753Smm size_t out_block_size; 61228753Smm int64_t total_out; 62228753Smm char eof; /* True = found end of compressed data. */ 63228753Smm}; 64228753Smm 65228753Smm/* Combined lzma/xz filter */ 66228753Smmstatic ssize_t xz_filter_read(struct archive_read_filter *, const void **); 67228753Smmstatic int xz_filter_close(struct archive_read_filter *); 68228753Smmstatic int xz_lzma_bidder_init(struct archive_read_filter *); 69228753Smm 70228753Smm#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC 71228753Smm 72228753Smmstruct private_data { 73228753Smm lzmadec_stream stream; 74228753Smm unsigned char *out_block; 75228753Smm size_t out_block_size; 76228753Smm int64_t total_out; 77228753Smm char eof; /* True = found end of compressed data. */ 78228753Smm}; 79228753Smm 80228753Smm/* Lzma-only filter */ 81228753Smmstatic ssize_t lzma_filter_read(struct archive_read_filter *, const void **); 82228753Smmstatic int lzma_filter_close(struct archive_read_filter *); 83228753Smm#endif 84228753Smm 85228753Smm/* 86228753Smm * Note that we can detect xz and lzma compressed files even if we 87228753Smm * can't decompress them. (In fact, we like detecting them because we 88228753Smm * can give better error messages.) So the bid framework here gets 89228753Smm * compiled even if no lzma library is available. 90228753Smm */ 91228753Smmstatic int xz_bidder_bid(struct archive_read_filter_bidder *, 92228753Smm struct archive_read_filter *); 93228753Smmstatic int xz_bidder_init(struct archive_read_filter *); 94228753Smmstatic int lzma_bidder_bid(struct archive_read_filter_bidder *, 95228753Smm struct archive_read_filter *); 96228753Smmstatic int lzma_bidder_init(struct archive_read_filter *); 97228753Smm 98228753Smmint 99228753Smmarchive_read_support_compression_xz(struct archive *_a) 100228753Smm{ 101228753Smm struct archive_read *a = (struct archive_read *)_a; 102228753Smm struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a); 103228753Smm 104228753Smm archive_clear_error(_a); 105228753Smm if (bidder == NULL) 106228753Smm return (ARCHIVE_FATAL); 107228753Smm 108228753Smm bidder->data = NULL; 109228753Smm bidder->bid = xz_bidder_bid; 110228753Smm bidder->init = xz_bidder_init; 111228753Smm bidder->options = NULL; 112228753Smm bidder->free = NULL; 113228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 114228753Smm return (ARCHIVE_OK); 115228753Smm#else 116228753Smm archive_set_error(_a, ARCHIVE_ERRNO_MISC, 117228753Smm "Using external unxz program for xz decompression"); 118228753Smm return (ARCHIVE_WARN); 119228753Smm#endif 120228753Smm} 121228753Smm 122228753Smmint 123228753Smmarchive_read_support_compression_lzma(struct archive *_a) 124228753Smm{ 125228753Smm struct archive_read *a = (struct archive_read *)_a; 126228753Smm struct archive_read_filter_bidder *bidder = __archive_read_get_bidder(a); 127228753Smm 128228753Smm archive_clear_error(_a); 129228753Smm if (bidder == NULL) 130228753Smm return (ARCHIVE_FATAL); 131228753Smm 132228753Smm bidder->data = NULL; 133228753Smm bidder->bid = lzma_bidder_bid; 134228753Smm bidder->init = lzma_bidder_init; 135228753Smm bidder->options = NULL; 136228753Smm bidder->free = NULL; 137228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 138228753Smm return (ARCHIVE_OK); 139228753Smm#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC 140228753Smm return (ARCHIVE_OK); 141228753Smm#else 142228753Smm archive_set_error(_a, ARCHIVE_ERRNO_MISC, 143228753Smm "Using external unlzma program for lzma decompression"); 144228753Smm return (ARCHIVE_WARN); 145228753Smm#endif 146228753Smm} 147228753Smm 148228753Smm/* 149228753Smm * Test whether we can handle this data. 150228753Smm */ 151228753Smmstatic int 152228753Smmxz_bidder_bid(struct archive_read_filter_bidder *self, 153228753Smm struct archive_read_filter *filter) 154228753Smm{ 155228753Smm const unsigned char *buffer; 156228753Smm ssize_t avail; 157228753Smm int bits_checked; 158228753Smm 159228753Smm (void)self; /* UNUSED */ 160228753Smm 161228753Smm buffer = __archive_read_filter_ahead(filter, 6, &avail); 162228753Smm if (buffer == NULL) 163228753Smm return (0); 164228753Smm 165228753Smm /* 166228753Smm * Verify Header Magic Bytes : FD 37 7A 58 5A 00 167228753Smm */ 168228753Smm bits_checked = 0; 169228753Smm if (buffer[0] != 0xFD) 170228753Smm return (0); 171228753Smm bits_checked += 8; 172228753Smm if (buffer[1] != 0x37) 173228753Smm return (0); 174228753Smm bits_checked += 8; 175228753Smm if (buffer[2] != 0x7A) 176228753Smm return (0); 177228753Smm bits_checked += 8; 178228753Smm if (buffer[3] != 0x58) 179228753Smm return (0); 180228753Smm bits_checked += 8; 181228753Smm if (buffer[4] != 0x5A) 182228753Smm return (0); 183228753Smm bits_checked += 8; 184228753Smm if (buffer[5] != 0x00) 185228753Smm return (0); 186228753Smm bits_checked += 8; 187228753Smm 188228753Smm return (bits_checked); 189228753Smm} 190228753Smm 191228753Smm/* 192228753Smm * Test whether we can handle this data. 193228753Smm * 194228753Smm * <sigh> LZMA has a rather poor file signature. Zeros do not 195228753Smm * make good signature bytes as a rule, and the only non-zero byte 196228753Smm * here is an ASCII character. For example, an uncompressed tar 197228753Smm * archive whose first file is ']' would satisfy this check. It may 198228753Smm * be necessary to exclude LZMA from compression_all() because of 199228753Smm * this. Clients of libarchive would then have to explicitly enable 200228753Smm * LZMA checking instead of (or in addition to) compression_all() when 201228753Smm * they have other evidence (file name, command-line option) to go on. 202228753Smm */ 203228753Smmstatic int 204228753Smmlzma_bidder_bid(struct archive_read_filter_bidder *self, 205228753Smm struct archive_read_filter *filter) 206228753Smm{ 207228753Smm const unsigned char *buffer; 208228753Smm ssize_t avail; 209228753Smm uint32_t dicsize; 210228753Smm uint64_t uncompressed_size; 211228753Smm int bits_checked; 212228753Smm 213228753Smm (void)self; /* UNUSED */ 214228753Smm 215228753Smm buffer = __archive_read_filter_ahead(filter, 14, &avail); 216228753Smm if (buffer == NULL) 217228753Smm return (0); 218228753Smm 219228753Smm /* First byte of raw LZMA stream is commonly 0x5d. 220228753Smm * The first byte is a special number, which consists of 221228753Smm * three parameters of LZMA compression, a number of literal 222228753Smm * context bits(which is from 0 to 8, default is 3), a number 223228753Smm * of literal pos bits(which is from 0 to 4, default is 0), 224228753Smm * a number of pos bits(which is from 0 to 4, default is 2). 225228753Smm * The first byte is made by 226228753Smm * (pos bits * 5 + literal pos bit) * 9 + * literal contest bit, 227228753Smm * and so the default value in this field is 228228753Smm * (2 * 5 + 0) * 9 + 3 = 0x5d. 229228753Smm * lzma of LZMA SDK has options to change those parameters. 230228753Smm * It means a range of this field is from 0 to 224. And lzma of 231228753Smm * XZ Utils with option -e records 0x5e in this field. */ 232228753Smm /* NOTE: If this checking of the first byte increases false 233228753Smm * recognition, we should allow only 0x5d and 0x5e for the first 234228753Smm * byte of LZMA stream. */ 235228753Smm bits_checked = 0; 236228753Smm if (buffer[0] > (4 * 5 + 4) * 9 + 8) 237228753Smm return (0); 238228753Smm /* Most likely value in the first byte of LZMA stream. */ 239228753Smm if (buffer[0] == 0x5d || buffer[0] == 0x5e) 240228753Smm bits_checked += 8; 241228753Smm 242228753Smm /* Sixth through fourteenth bytes are uncompressed size, 243228753Smm * stored in little-endian order. `-1' means uncompressed 244228753Smm * size is unknown and lzma of XZ Utils always records `-1' 245228753Smm * in this field. */ 246228753Smm uncompressed_size = archive_le64dec(buffer+5); 247228753Smm if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1)) 248228753Smm bits_checked += 64; 249228753Smm 250228753Smm /* Second through fifth bytes are dictionary size, stored in 251228753Smm * little-endian order. The minimum dictionary size is 252228753Smm * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option 253228753Smm * -d12 and the maxinam dictionary size is 1 << 27(128MiB) 254228753Smm * which the one uses with option -d27. 255228753Smm * NOTE: A comment of LZMA SDK source code says this dictionary 256228753Smm * range is from 1 << 12 to 1 << 30. */ 257228753Smm dicsize = archive_le32dec(buffer+1); 258228753Smm switch (dicsize) { 259228753Smm case 0x00001000:/* lzma of LZMA SDK option -d12. */ 260228753Smm case 0x00002000:/* lzma of LZMA SDK option -d13. */ 261228753Smm case 0x00004000:/* lzma of LZMA SDK option -d14. */ 262228753Smm case 0x00008000:/* lzma of LZMA SDK option -d15. */ 263228753Smm case 0x00010000:/* lzma of XZ Utils option -0 and -1. 264228753Smm * lzma of LZMA SDK option -d16. */ 265228753Smm case 0x00020000:/* lzma of LZMA SDK option -d17. */ 266228753Smm case 0x00040000:/* lzma of LZMA SDK option -d18. */ 267228753Smm case 0x00080000:/* lzma of XZ Utils option -2. 268228753Smm * lzma of LZMA SDK option -d19. */ 269228753Smm case 0x00100000:/* lzma of XZ Utils option -3. 270228753Smm * lzma of LZMA SDK option -d20. */ 271228753Smm case 0x00200000:/* lzma of XZ Utils option -4. 272228753Smm * lzma of LZMA SDK option -d21. */ 273228753Smm case 0x00400000:/* lzma of XZ Utils option -5. 274228753Smm * lzma of LZMA SDK option -d22. */ 275228753Smm case 0x00800000:/* lzma of XZ Utils option -6. 276228753Smm * lzma of LZMA SDK option -d23. */ 277228753Smm case 0x01000000:/* lzma of XZ Utils option -7. 278228753Smm * lzma of LZMA SDK option -d24. */ 279228753Smm case 0x02000000:/* lzma of XZ Utils option -8. 280228753Smm * lzma of LZMA SDK option -d25. */ 281228753Smm case 0x04000000:/* lzma of XZ Utils option -9. 282228753Smm * lzma of LZMA SDK option -d26. */ 283228753Smm case 0x08000000:/* lzma of LZMA SDK option -d27. */ 284228753Smm bits_checked += 32; 285228753Smm break; 286228753Smm default: 287228753Smm /* If a memory usage for encoding was not enough on 288228753Smm * the platform where LZMA stream was made, lzma of 289228753Smm * XZ Utils automatically decreased the dictionary 290228753Smm * size to enough memory for encoding by 1Mi bytes 291228753Smm * (1 << 20).*/ 292228753Smm if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 && 293228753Smm (dicsize & ((1 << 20)-1)) == 0 && 294228753Smm bits_checked == 8 + 64) { 295228753Smm bits_checked += 32; 296228753Smm break; 297228753Smm } 298228753Smm /* Otherwise dictionary size is unlikely. But it is 299228753Smm * possible that someone makes lzma stream with 300228753Smm * liblzma/LZMA SDK in one's dictionary size. */ 301228753Smm return (0); 302228753Smm } 303228753Smm 304228753Smm /* TODO: The above test is still very weak. It would be 305228753Smm * good to do better. */ 306228753Smm 307228753Smm return (bits_checked); 308228753Smm} 309228753Smm 310228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 311228753Smm 312228753Smm/* 313228753Smm * liblzma 4.999.7 and later support both lzma and xz streams. 314228753Smm */ 315228753Smmstatic int 316228753Smmxz_bidder_init(struct archive_read_filter *self) 317228753Smm{ 318228753Smm self->code = ARCHIVE_COMPRESSION_XZ; 319228753Smm self->name = "xz"; 320228753Smm return (xz_lzma_bidder_init(self)); 321228753Smm} 322228753Smm 323228753Smmstatic int 324228753Smmlzma_bidder_init(struct archive_read_filter *self) 325228753Smm{ 326228753Smm self->code = ARCHIVE_COMPRESSION_LZMA; 327228753Smm self->name = "lzma"; 328228753Smm return (xz_lzma_bidder_init(self)); 329228753Smm} 330228753Smm 331228753Smm/* 332228753Smm * Setup the callbacks. 333228753Smm */ 334228753Smmstatic int 335228753Smmxz_lzma_bidder_init(struct archive_read_filter *self) 336228753Smm{ 337228753Smm static const size_t out_block_size = 64 * 1024; 338228753Smm void *out_block; 339228753Smm struct private_data *state; 340228753Smm int ret; 341228753Smm 342228753Smm state = (struct private_data *)calloc(sizeof(*state), 1); 343228753Smm out_block = (unsigned char *)malloc(out_block_size); 344228753Smm if (state == NULL || out_block == NULL) { 345228753Smm archive_set_error(&self->archive->archive, ENOMEM, 346228753Smm "Can't allocate data for xz decompression"); 347228753Smm free(out_block); 348228753Smm free(state); 349228753Smm return (ARCHIVE_FATAL); 350228753Smm } 351228753Smm 352228753Smm self->data = state; 353228753Smm state->out_block_size = out_block_size; 354228753Smm state->out_block = out_block; 355228753Smm self->read = xz_filter_read; 356228753Smm self->skip = NULL; /* not supported */ 357228753Smm self->close = xz_filter_close; 358228753Smm 359228753Smm state->stream.avail_in = 0; 360228753Smm 361228753Smm state->stream.next_out = state->out_block; 362228753Smm state->stream.avail_out = state->out_block_size; 363228753Smm 364228753Smm /* Initialize compression library. 365228753Smm * TODO: I don't know what value is best for memlimit. 366228753Smm * maybe, it needs to check memory size which 367228753Smm * running system has. 368228753Smm */ 369228753Smm if (self->code == ARCHIVE_COMPRESSION_XZ) 370228753Smm ret = lzma_stream_decoder(&(state->stream), 371228753Smm (1U << 30),/* memlimit */ 372228753Smm LZMA_CONCATENATED); 373228753Smm else 374228753Smm ret = lzma_alone_decoder(&(state->stream), 375228753Smm (1U << 30));/* memlimit */ 376228753Smm 377228753Smm if (ret == LZMA_OK) 378228753Smm return (ARCHIVE_OK); 379228753Smm 380228753Smm /* Library setup failed: Choose an error message and clean up. */ 381228753Smm switch (ret) { 382228753Smm case LZMA_MEM_ERROR: 383228753Smm archive_set_error(&self->archive->archive, ENOMEM, 384228753Smm "Internal error initializing compression library: " 385228753Smm "Cannot allocate memory"); 386228753Smm break; 387228753Smm case LZMA_OPTIONS_ERROR: 388228753Smm archive_set_error(&self->archive->archive, 389228753Smm ARCHIVE_ERRNO_MISC, 390228753Smm "Internal error initializing compression library: " 391228753Smm "Invalid or unsupported options"); 392228753Smm break; 393228753Smm default: 394228753Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 395228753Smm "Internal error initializing lzma library"); 396228753Smm break; 397228753Smm } 398228753Smm 399228753Smm free(state->out_block); 400228753Smm free(state); 401228753Smm self->data = NULL; 402228753Smm return (ARCHIVE_FATAL); 403228753Smm} 404228753Smm 405228753Smm/* 406228753Smm * Return the next block of decompressed data. 407228753Smm */ 408228753Smmstatic ssize_t 409228753Smmxz_filter_read(struct archive_read_filter *self, const void **p) 410228753Smm{ 411228753Smm struct private_data *state; 412228753Smm size_t decompressed; 413228753Smm ssize_t avail_in; 414228753Smm int ret; 415228753Smm 416228753Smm state = (struct private_data *)self->data; 417228753Smm 418228753Smm /* Empty our output buffer. */ 419228753Smm state->stream.next_out = state->out_block; 420228753Smm state->stream.avail_out = state->out_block_size; 421228753Smm 422228753Smm /* Try to fill the output buffer. */ 423228753Smm while (state->stream.avail_out > 0 && !state->eof) { 424228753Smm state->stream.next_in = 425228753Smm __archive_read_filter_ahead(self->upstream, 1, &avail_in); 426228753Smm if (state->stream.next_in == NULL && avail_in < 0) 427228753Smm return (ARCHIVE_FATAL); 428228753Smm state->stream.avail_in = avail_in; 429228753Smm 430228753Smm /* Decompress as much as we can in one pass. */ 431228753Smm ret = lzma_code(&(state->stream), 432228753Smm (state->stream.avail_in == 0)? LZMA_FINISH: LZMA_RUN); 433228753Smm switch (ret) { 434228753Smm case LZMA_STREAM_END: /* Found end of stream. */ 435228753Smm state->eof = 1; 436228753Smm /* FALL THROUGH */ 437228753Smm case LZMA_OK: /* Decompressor made some progress. */ 438228753Smm __archive_read_filter_consume(self->upstream, 439228753Smm avail_in - state->stream.avail_in); 440228753Smm break; 441228753Smm case LZMA_MEM_ERROR: 442228753Smm archive_set_error(&self->archive->archive, ENOMEM, 443228753Smm "Lzma library error: Cannot allocate memory"); 444228753Smm return (ARCHIVE_FATAL); 445228753Smm case LZMA_MEMLIMIT_ERROR: 446228753Smm archive_set_error(&self->archive->archive, ENOMEM, 447228753Smm "Lzma library error: Out of memory"); 448228753Smm return (ARCHIVE_FATAL); 449228753Smm case LZMA_FORMAT_ERROR: 450228753Smm archive_set_error(&self->archive->archive, 451228753Smm ARCHIVE_ERRNO_MISC, 452228753Smm "Lzma library error: format not recognized"); 453228753Smm return (ARCHIVE_FATAL); 454228753Smm case LZMA_OPTIONS_ERROR: 455228753Smm archive_set_error(&self->archive->archive, 456228753Smm ARCHIVE_ERRNO_MISC, 457228753Smm "Lzma library error: Invalid options"); 458228753Smm return (ARCHIVE_FATAL); 459228753Smm case LZMA_DATA_ERROR: 460228753Smm archive_set_error(&self->archive->archive, 461228753Smm ARCHIVE_ERRNO_MISC, 462228753Smm "Lzma library error: Corrupted input data"); 463228753Smm return (ARCHIVE_FATAL); 464228753Smm case LZMA_BUF_ERROR: 465228753Smm archive_set_error(&self->archive->archive, 466228753Smm ARCHIVE_ERRNO_MISC, 467228753Smm "Lzma library error: No progress is possible"); 468228753Smm return (ARCHIVE_FATAL); 469228753Smm default: 470228753Smm /* Return an error. */ 471228753Smm archive_set_error(&self->archive->archive, 472228753Smm ARCHIVE_ERRNO_MISC, 473228753Smm "Lzma decompression failed: Unknown error"); 474228753Smm return (ARCHIVE_FATAL); 475228753Smm } 476228753Smm } 477228753Smm 478228753Smm decompressed = state->stream.next_out - state->out_block; 479228753Smm state->total_out += decompressed; 480228753Smm if (decompressed == 0) 481228753Smm *p = NULL; 482228753Smm else 483228753Smm *p = state->out_block; 484228753Smm return (decompressed); 485228753Smm} 486228753Smm 487228753Smm/* 488228753Smm * Clean up the decompressor. 489228753Smm */ 490228753Smmstatic int 491228753Smmxz_filter_close(struct archive_read_filter *self) 492228753Smm{ 493228753Smm struct private_data *state; 494228753Smm 495228753Smm state = (struct private_data *)self->data; 496228753Smm lzma_end(&(state->stream)); 497228753Smm free(state->out_block); 498228753Smm free(state); 499228753Smm return (ARCHIVE_OK); 500228753Smm} 501228753Smm 502228753Smm#else 503228753Smm 504228753Smm#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC 505228753Smm 506228753Smm/* 507228753Smm * If we have the older liblzmadec library, then we can handle 508228753Smm * LZMA streams but not XZ streams. 509228753Smm */ 510228753Smm 511228753Smm/* 512228753Smm * Setup the callbacks. 513228753Smm */ 514228753Smmstatic int 515228753Smmlzma_bidder_init(struct archive_read_filter *self) 516228753Smm{ 517228753Smm static const size_t out_block_size = 64 * 1024; 518228753Smm void *out_block; 519228753Smm struct private_data *state; 520228753Smm ssize_t ret, avail_in; 521228753Smm 522228753Smm self->code = ARCHIVE_COMPRESSION_LZMA; 523228753Smm self->name = "lzma"; 524228753Smm 525228753Smm state = (struct private_data *)calloc(sizeof(*state), 1); 526228753Smm out_block = (unsigned char *)malloc(out_block_size); 527228753Smm if (state == NULL || out_block == NULL) { 528228753Smm archive_set_error(&self->archive->archive, ENOMEM, 529228753Smm "Can't allocate data for lzma decompression"); 530228753Smm free(out_block); 531228753Smm free(state); 532228753Smm return (ARCHIVE_FATAL); 533228753Smm } 534228753Smm 535228753Smm self->data = state; 536228753Smm state->out_block_size = out_block_size; 537228753Smm state->out_block = out_block; 538228753Smm self->read = lzma_filter_read; 539228753Smm self->skip = NULL; /* not supported */ 540228753Smm self->close = lzma_filter_close; 541228753Smm 542228753Smm /* Prime the lzma library with 18 bytes of input. */ 543228753Smm state->stream.next_in = (unsigned char *)(uintptr_t) 544228753Smm __archive_read_filter_ahead(self->upstream, 18, &avail_in); 545228753Smm if (state->stream.next_in == NULL) 546228753Smm return (ARCHIVE_FATAL); 547228753Smm state->stream.avail_in = avail_in; 548228753Smm state->stream.next_out = state->out_block; 549228753Smm state->stream.avail_out = state->out_block_size; 550228753Smm 551228753Smm /* Initialize compression library. */ 552228753Smm ret = lzmadec_init(&(state->stream)); 553228753Smm __archive_read_filter_consume(self->upstream, 554228753Smm avail_in - state->stream.avail_in); 555228753Smm if (ret == LZMADEC_OK) 556228753Smm return (ARCHIVE_OK); 557228753Smm 558228753Smm /* Library setup failed: Clean up. */ 559228753Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 560228753Smm "Internal error initializing lzma library"); 561228753Smm 562228753Smm /* Override the error message if we know what really went wrong. */ 563228753Smm switch (ret) { 564228753Smm case LZMADEC_HEADER_ERROR: 565228753Smm archive_set_error(&self->archive->archive, 566228753Smm ARCHIVE_ERRNO_MISC, 567228753Smm "Internal error initializing compression library: " 568228753Smm "invalid header"); 569228753Smm break; 570228753Smm case LZMADEC_MEM_ERROR: 571228753Smm archive_set_error(&self->archive->archive, ENOMEM, 572228753Smm "Internal error initializing compression library: " 573228753Smm "out of memory"); 574228753Smm break; 575228753Smm } 576228753Smm 577228753Smm free(state->out_block); 578228753Smm free(state); 579228753Smm self->data = NULL; 580228753Smm return (ARCHIVE_FATAL); 581228753Smm} 582228753Smm 583228753Smm/* 584228753Smm * Return the next block of decompressed data. 585228753Smm */ 586228753Smmstatic ssize_t 587228753Smmlzma_filter_read(struct archive_read_filter *self, const void **p) 588228753Smm{ 589228753Smm struct private_data *state; 590228753Smm size_t decompressed; 591228753Smm ssize_t avail_in, ret; 592228753Smm 593228753Smm state = (struct private_data *)self->data; 594228753Smm 595228753Smm /* Empty our output buffer. */ 596228753Smm state->stream.next_out = state->out_block; 597228753Smm state->stream.avail_out = state->out_block_size; 598228753Smm 599228753Smm /* Try to fill the output buffer. */ 600228753Smm while (state->stream.avail_out > 0 && !state->eof) { 601228753Smm state->stream.next_in = (unsigned char *)(uintptr_t) 602228753Smm __archive_read_filter_ahead(self->upstream, 1, &avail_in); 603228753Smm if (state->stream.next_in == NULL && avail_in < 0) 604228753Smm return (ARCHIVE_FATAL); 605228753Smm state->stream.avail_in = avail_in; 606228753Smm 607228753Smm /* Decompress as much as we can in one pass. */ 608228753Smm ret = lzmadec_decode(&(state->stream), avail_in == 0); 609228753Smm switch (ret) { 610228753Smm case LZMADEC_STREAM_END: /* Found end of stream. */ 611228753Smm state->eof = 1; 612228753Smm /* FALL THROUGH */ 613228753Smm case LZMADEC_OK: /* Decompressor made some progress. */ 614228753Smm __archive_read_filter_consume(self->upstream, 615228753Smm avail_in - state->stream.avail_in); 616228753Smm break; 617228753Smm case LZMADEC_BUF_ERROR: /* Insufficient input data? */ 618228753Smm archive_set_error(&self->archive->archive, 619228753Smm ARCHIVE_ERRNO_MISC, 620228753Smm "Insufficient compressed data"); 621228753Smm return (ARCHIVE_FATAL); 622228753Smm default: 623228753Smm /* Return an error. */ 624228753Smm archive_set_error(&self->archive->archive, 625228753Smm ARCHIVE_ERRNO_MISC, 626228753Smm "Lzma decompression failed"); 627228753Smm return (ARCHIVE_FATAL); 628228753Smm } 629228753Smm } 630228753Smm 631228753Smm decompressed = state->stream.next_out - state->out_block; 632228753Smm state->total_out += decompressed; 633228753Smm if (decompressed == 0) 634228753Smm *p = NULL; 635228753Smm else 636228753Smm *p = state->out_block; 637228753Smm return (decompressed); 638228753Smm} 639228753Smm 640228753Smm/* 641228753Smm * Clean up the decompressor. 642228753Smm */ 643228753Smmstatic int 644228753Smmlzma_filter_close(struct archive_read_filter *self) 645228753Smm{ 646228753Smm struct private_data *state; 647228753Smm int ret; 648228753Smm 649228753Smm state = (struct private_data *)self->data; 650228753Smm ret = ARCHIVE_OK; 651228753Smm switch (lzmadec_end(&(state->stream))) { 652228753Smm case LZMADEC_OK: 653228753Smm break; 654228753Smm default: 655228753Smm archive_set_error(&(self->archive->archive), 656228753Smm ARCHIVE_ERRNO_MISC, 657228753Smm "Failed to clean up %s compressor", 658228753Smm self->archive->archive.compression_name); 659228753Smm ret = ARCHIVE_FATAL; 660228753Smm } 661228753Smm 662228753Smm free(state->out_block); 663228753Smm free(state); 664228753Smm return (ret); 665228753Smm} 666228753Smm 667228753Smm#else 668228753Smm 669228753Smm/* 670228753Smm * 671228753Smm * If we have no suitable library on this system, we can't actually do 672228753Smm * the decompression. We can, however, still detect compressed 673228753Smm * archives and emit a useful message. 674228753Smm * 675228753Smm */ 676228753Smmstatic int 677228753Smmlzma_bidder_init(struct archive_read_filter *self) 678228753Smm{ 679228753Smm int r; 680228753Smm 681228753Smm r = __archive_read_program(self, "unlzma"); 682228753Smm /* Note: We set the format here even if __archive_read_program() 683228753Smm * above fails. We do, after all, know what the format is 684228753Smm * even if we weren't able to read it. */ 685228753Smm self->code = ARCHIVE_COMPRESSION_LZMA; 686228753Smm self->name = "lzma"; 687228753Smm return (r); 688228753Smm} 689228753Smm 690228753Smm#endif /* HAVE_LZMADEC_H */ 691228753Smm 692228753Smm 693228753Smmstatic int 694228753Smmxz_bidder_init(struct archive_read_filter *self) 695228753Smm{ 696228753Smm int r; 697228753Smm 698228753Smm r = __archive_read_program(self, "unxz"); 699228753Smm /* Note: We set the format here even if __archive_read_program() 700228753Smm * above fails. We do, after all, know what the format is 701228753Smm * even if we weren't able to read it. */ 702228753Smm self->code = ARCHIVE_COMPRESSION_XZ; 703228753Smm self->name = "xz"; 704228753Smm return (r); 705228753Smm} 706228753Smm 707228753Smm 708228753Smm#endif /* HAVE_LZMA_H */ 709