1228753Smm/*- 2231200Smm * Copyright (c) 2009-2011 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 29231200Smm__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#endif 47228753Smm 48228753Smm#include "archive.h" 49228753Smm#include "archive_endian.h" 50228753Smm#include "archive_private.h" 51228753Smm#include "archive_read_private.h" 52228753Smm 53228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 54228753Smm 55228753Smmstruct private_data { 56228753Smm lzma_stream stream; 57228753Smm unsigned char *out_block; 58228753Smm size_t out_block_size; 59228753Smm int64_t total_out; 60228753Smm char eof; /* True = found end of compressed data. */ 61231200Smm char in_stream; 62231200Smm 63231200Smm /* Following variables are used for lzip only. */ 64231200Smm char lzip_ver; 65231200Smm uint32_t crc32; 66231200Smm int64_t member_in; 67231200Smm int64_t member_out; 68228753Smm}; 69228753Smm 70231200Smm#if LZMA_VERSION_MAJOR >= 5 71231200Smm/* Effectively disable the limiter. */ 72231200Smm#define LZMA_MEMLIMIT UINT64_MAX 73231200Smm#else 74231200Smm/* NOTE: This needs to check memory size which running system has. */ 75231200Smm#define LZMA_MEMLIMIT (1U << 30) 76231200Smm#endif 77231200Smm 78231200Smm/* Combined lzip/lzma/xz filter */ 79228753Smmstatic ssize_t xz_filter_read(struct archive_read_filter *, const void **); 80228753Smmstatic int xz_filter_close(struct archive_read_filter *); 81228753Smmstatic int xz_lzma_bidder_init(struct archive_read_filter *); 82228753Smm 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 *); 97231200Smmstatic int lzip_has_member(struct archive_read_filter *); 98231200Smmstatic int lzip_bidder_bid(struct archive_read_filter_bidder *, 99231200Smm struct archive_read_filter *); 100231200Smmstatic int lzip_bidder_init(struct archive_read_filter *); 101228753Smm 102231200Smm#if ARCHIVE_VERSION_NUMBER < 4000000 103231200Smm/* Deprecated; remove in libarchive 4.0 */ 104228753Smmint 105231200Smmarchive_read_support_compression_xz(struct archive *a) 106228753Smm{ 107231200Smm return archive_read_support_filter_xz(a); 108231200Smm} 109231200Smm#endif 110231200Smm 111231200Smmint 112231200Smmarchive_read_support_filter_xz(struct archive *_a) 113231200Smm{ 114228753Smm struct archive_read *a = (struct archive_read *)_a; 115231200Smm struct archive_read_filter_bidder *bidder; 116228753Smm 117231200Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 118231200Smm ARCHIVE_STATE_NEW, "archive_read_support_filter_xz"); 119231200Smm 120231200Smm if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) 121228753Smm return (ARCHIVE_FATAL); 122228753Smm 123228753Smm bidder->data = NULL; 124248616Smm bidder->name = "xz"; 125228753Smm bidder->bid = xz_bidder_bid; 126228753Smm bidder->init = xz_bidder_init; 127228753Smm bidder->options = NULL; 128228753Smm bidder->free = NULL; 129228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 130228753Smm return (ARCHIVE_OK); 131228753Smm#else 132228753Smm archive_set_error(_a, ARCHIVE_ERRNO_MISC, 133248616Smm "Using external xz program for xz decompression"); 134228753Smm return (ARCHIVE_WARN); 135228753Smm#endif 136228753Smm} 137228753Smm 138231200Smm#if ARCHIVE_VERSION_NUMBER < 4000000 139228753Smmint 140231200Smmarchive_read_support_compression_lzma(struct archive *a) 141228753Smm{ 142231200Smm return archive_read_support_filter_lzma(a); 143231200Smm} 144231200Smm#endif 145231200Smm 146231200Smmint 147231200Smmarchive_read_support_filter_lzma(struct archive *_a) 148231200Smm{ 149228753Smm struct archive_read *a = (struct archive_read *)_a; 150231200Smm struct archive_read_filter_bidder *bidder; 151228753Smm 152231200Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 153231200Smm ARCHIVE_STATE_NEW, "archive_read_support_filter_lzma"); 154231200Smm 155231200Smm if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) 156228753Smm return (ARCHIVE_FATAL); 157228753Smm 158228753Smm bidder->data = NULL; 159248616Smm bidder->name = "lzma"; 160228753Smm bidder->bid = lzma_bidder_bid; 161228753Smm bidder->init = lzma_bidder_init; 162228753Smm bidder->options = NULL; 163228753Smm bidder->free = NULL; 164228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 165228753Smm return (ARCHIVE_OK); 166228753Smm#else 167228753Smm archive_set_error(_a, ARCHIVE_ERRNO_MISC, 168248616Smm "Using external lzma program for lzma decompression"); 169228753Smm return (ARCHIVE_WARN); 170228753Smm#endif 171228753Smm} 172228753Smm 173231200Smm 174231200Smm#if ARCHIVE_VERSION_NUMBER < 4000000 175231200Smmint 176231200Smmarchive_read_support_compression_lzip(struct archive *a) 177231200Smm{ 178231200Smm return archive_read_support_filter_lzip(a); 179231200Smm} 180231200Smm#endif 181231200Smm 182231200Smmint 183231200Smmarchive_read_support_filter_lzip(struct archive *_a) 184231200Smm{ 185231200Smm struct archive_read *a = (struct archive_read *)_a; 186231200Smm struct archive_read_filter_bidder *bidder; 187231200Smm 188231200Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 189231200Smm ARCHIVE_STATE_NEW, "archive_read_support_filter_lzip"); 190231200Smm 191231200Smm if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK) 192231200Smm return (ARCHIVE_FATAL); 193231200Smm 194231200Smm bidder->data = NULL; 195248616Smm bidder->name = "lzip"; 196231200Smm bidder->bid = lzip_bidder_bid; 197231200Smm bidder->init = lzip_bidder_init; 198231200Smm bidder->options = NULL; 199231200Smm bidder->free = NULL; 200231200Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 201231200Smm return (ARCHIVE_OK); 202231200Smm#else 203231200Smm archive_set_error(_a, ARCHIVE_ERRNO_MISC, 204231200Smm "Using external lzip program for lzip decompression"); 205231200Smm return (ARCHIVE_WARN); 206231200Smm#endif 207231200Smm} 208231200Smm 209228753Smm/* 210228753Smm * Test whether we can handle this data. 211228753Smm */ 212228753Smmstatic int 213228753Smmxz_bidder_bid(struct archive_read_filter_bidder *self, 214228753Smm struct archive_read_filter *filter) 215228753Smm{ 216228753Smm const unsigned char *buffer; 217228753Smm ssize_t avail; 218228753Smm 219228753Smm (void)self; /* UNUSED */ 220228753Smm 221228753Smm buffer = __archive_read_filter_ahead(filter, 6, &avail); 222228753Smm if (buffer == NULL) 223228753Smm return (0); 224228753Smm 225228753Smm /* 226228753Smm * Verify Header Magic Bytes : FD 37 7A 58 5A 00 227228753Smm */ 228231200Smm if (memcmp(buffer, "\xFD\x37\x7A\x58\x5A\x00", 6) != 0) 229228753Smm return (0); 230228753Smm 231231200Smm return (48); 232228753Smm} 233228753Smm 234228753Smm/* 235228753Smm * Test whether we can handle this data. 236228753Smm * 237228753Smm * <sigh> LZMA has a rather poor file signature. Zeros do not 238228753Smm * make good signature bytes as a rule, and the only non-zero byte 239228753Smm * here is an ASCII character. For example, an uncompressed tar 240228753Smm * archive whose first file is ']' would satisfy this check. It may 241228753Smm * be necessary to exclude LZMA from compression_all() because of 242228753Smm * this. Clients of libarchive would then have to explicitly enable 243228753Smm * LZMA checking instead of (or in addition to) compression_all() when 244228753Smm * they have other evidence (file name, command-line option) to go on. 245228753Smm */ 246228753Smmstatic int 247228753Smmlzma_bidder_bid(struct archive_read_filter_bidder *self, 248228753Smm struct archive_read_filter *filter) 249228753Smm{ 250228753Smm const unsigned char *buffer; 251228753Smm ssize_t avail; 252228753Smm uint32_t dicsize; 253228753Smm uint64_t uncompressed_size; 254228753Smm int bits_checked; 255228753Smm 256228753Smm (void)self; /* UNUSED */ 257228753Smm 258228753Smm buffer = __archive_read_filter_ahead(filter, 14, &avail); 259228753Smm if (buffer == NULL) 260228753Smm return (0); 261228753Smm 262228753Smm /* First byte of raw LZMA stream is commonly 0x5d. 263228753Smm * The first byte is a special number, which consists of 264228753Smm * three parameters of LZMA compression, a number of literal 265228753Smm * context bits(which is from 0 to 8, default is 3), a number 266228753Smm * of literal pos bits(which is from 0 to 4, default is 0), 267228753Smm * a number of pos bits(which is from 0 to 4, default is 2). 268228753Smm * The first byte is made by 269228753Smm * (pos bits * 5 + literal pos bit) * 9 + * literal contest bit, 270228753Smm * and so the default value in this field is 271228753Smm * (2 * 5 + 0) * 9 + 3 = 0x5d. 272228753Smm * lzma of LZMA SDK has options to change those parameters. 273228753Smm * It means a range of this field is from 0 to 224. And lzma of 274228753Smm * XZ Utils with option -e records 0x5e in this field. */ 275228753Smm /* NOTE: If this checking of the first byte increases false 276228753Smm * recognition, we should allow only 0x5d and 0x5e for the first 277228753Smm * byte of LZMA stream. */ 278228753Smm bits_checked = 0; 279228753Smm if (buffer[0] > (4 * 5 + 4) * 9 + 8) 280228753Smm return (0); 281228753Smm /* Most likely value in the first byte of LZMA stream. */ 282228753Smm if (buffer[0] == 0x5d || buffer[0] == 0x5e) 283228753Smm bits_checked += 8; 284228753Smm 285228753Smm /* Sixth through fourteenth bytes are uncompressed size, 286228753Smm * stored in little-endian order. `-1' means uncompressed 287228753Smm * size is unknown and lzma of XZ Utils always records `-1' 288228753Smm * in this field. */ 289228753Smm uncompressed_size = archive_le64dec(buffer+5); 290228753Smm if (uncompressed_size == (uint64_t)ARCHIVE_LITERAL_LL(-1)) 291228753Smm bits_checked += 64; 292228753Smm 293228753Smm /* Second through fifth bytes are dictionary size, stored in 294228753Smm * little-endian order. The minimum dictionary size is 295228753Smm * 1 << 12(4KiB) which the lzma of LZMA SDK uses with option 296311042Smm * -d12 and the maximum dictionary size is 1 << 27(128MiB) 297228753Smm * which the one uses with option -d27. 298228753Smm * NOTE: A comment of LZMA SDK source code says this dictionary 299228753Smm * range is from 1 << 12 to 1 << 30. */ 300228753Smm dicsize = archive_le32dec(buffer+1); 301228753Smm switch (dicsize) { 302228753Smm case 0x00001000:/* lzma of LZMA SDK option -d12. */ 303228753Smm case 0x00002000:/* lzma of LZMA SDK option -d13. */ 304228753Smm case 0x00004000:/* lzma of LZMA SDK option -d14. */ 305228753Smm case 0x00008000:/* lzma of LZMA SDK option -d15. */ 306228753Smm case 0x00010000:/* lzma of XZ Utils option -0 and -1. 307228753Smm * lzma of LZMA SDK option -d16. */ 308228753Smm case 0x00020000:/* lzma of LZMA SDK option -d17. */ 309228753Smm case 0x00040000:/* lzma of LZMA SDK option -d18. */ 310228753Smm case 0x00080000:/* lzma of XZ Utils option -2. 311228753Smm * lzma of LZMA SDK option -d19. */ 312228753Smm case 0x00100000:/* lzma of XZ Utils option -3. 313228753Smm * lzma of LZMA SDK option -d20. */ 314228753Smm case 0x00200000:/* lzma of XZ Utils option -4. 315228753Smm * lzma of LZMA SDK option -d21. */ 316228753Smm case 0x00400000:/* lzma of XZ Utils option -5. 317228753Smm * lzma of LZMA SDK option -d22. */ 318228753Smm case 0x00800000:/* lzma of XZ Utils option -6. 319228753Smm * lzma of LZMA SDK option -d23. */ 320228753Smm case 0x01000000:/* lzma of XZ Utils option -7. 321228753Smm * lzma of LZMA SDK option -d24. */ 322228753Smm case 0x02000000:/* lzma of XZ Utils option -8. 323228753Smm * lzma of LZMA SDK option -d25. */ 324228753Smm case 0x04000000:/* lzma of XZ Utils option -9. 325228753Smm * lzma of LZMA SDK option -d26. */ 326228753Smm case 0x08000000:/* lzma of LZMA SDK option -d27. */ 327228753Smm bits_checked += 32; 328228753Smm break; 329228753Smm default: 330228753Smm /* If a memory usage for encoding was not enough on 331228753Smm * the platform where LZMA stream was made, lzma of 332228753Smm * XZ Utils automatically decreased the dictionary 333228753Smm * size to enough memory for encoding by 1Mi bytes 334228753Smm * (1 << 20).*/ 335228753Smm if (dicsize <= 0x03F00000 && dicsize >= 0x00300000 && 336228753Smm (dicsize & ((1 << 20)-1)) == 0 && 337228753Smm bits_checked == 8 + 64) { 338228753Smm bits_checked += 32; 339228753Smm break; 340228753Smm } 341228753Smm /* Otherwise dictionary size is unlikely. But it is 342228753Smm * possible that someone makes lzma stream with 343228753Smm * liblzma/LZMA SDK in one's dictionary size. */ 344228753Smm return (0); 345228753Smm } 346228753Smm 347228753Smm /* TODO: The above test is still very weak. It would be 348228753Smm * good to do better. */ 349228753Smm 350228753Smm return (bits_checked); 351228753Smm} 352228753Smm 353231200Smmstatic int 354231200Smmlzip_has_member(struct archive_read_filter *filter) 355231200Smm{ 356231200Smm const unsigned char *buffer; 357231200Smm ssize_t avail; 358231200Smm int bits_checked; 359231200Smm int log2dic; 360231200Smm 361231200Smm buffer = __archive_read_filter_ahead(filter, 6, &avail); 362231200Smm if (buffer == NULL) 363231200Smm return (0); 364231200Smm 365231200Smm /* 366231200Smm * Verify Header Magic Bytes : 4C 5A 49 50 (`LZIP') 367231200Smm */ 368231200Smm bits_checked = 0; 369231200Smm if (memcmp(buffer, "LZIP", 4) != 0) 370231200Smm return (0); 371231200Smm bits_checked += 32; 372231200Smm 373231200Smm /* A version number must be 0 or 1 */ 374231200Smm if (buffer[4] != 0 && buffer[4] != 1) 375231200Smm return (0); 376231200Smm bits_checked += 8; 377231200Smm 378231200Smm /* Dictionary size. */ 379231200Smm log2dic = buffer[5] & 0x1f; 380231200Smm if (log2dic < 12 || log2dic > 27) 381231200Smm return (0); 382231200Smm bits_checked += 8; 383231200Smm 384231200Smm return (bits_checked); 385231200Smm} 386231200Smm 387231200Smmstatic int 388231200Smmlzip_bidder_bid(struct archive_read_filter_bidder *self, 389231200Smm struct archive_read_filter *filter) 390231200Smm{ 391231200Smm 392231200Smm (void)self; /* UNUSED */ 393231200Smm return (lzip_has_member(filter)); 394231200Smm} 395231200Smm 396228753Smm#if HAVE_LZMA_H && HAVE_LIBLZMA 397228753Smm 398228753Smm/* 399228753Smm * liblzma 4.999.7 and later support both lzma and xz streams. 400228753Smm */ 401228753Smmstatic int 402228753Smmxz_bidder_init(struct archive_read_filter *self) 403228753Smm{ 404248616Smm self->code = ARCHIVE_FILTER_XZ; 405228753Smm self->name = "xz"; 406228753Smm return (xz_lzma_bidder_init(self)); 407228753Smm} 408228753Smm 409228753Smmstatic int 410228753Smmlzma_bidder_init(struct archive_read_filter *self) 411228753Smm{ 412248616Smm self->code = ARCHIVE_FILTER_LZMA; 413228753Smm self->name = "lzma"; 414228753Smm return (xz_lzma_bidder_init(self)); 415228753Smm} 416228753Smm 417231200Smmstatic int 418231200Smmlzip_bidder_init(struct archive_read_filter *self) 419231200Smm{ 420248616Smm self->code = ARCHIVE_FILTER_LZIP; 421231200Smm self->name = "lzip"; 422231200Smm return (xz_lzma_bidder_init(self)); 423231200Smm} 424231200Smm 425228753Smm/* 426231200Smm * Set an error code and choose an error message 427231200Smm */ 428231200Smmstatic void 429231200Smmset_error(struct archive_read_filter *self, int ret) 430231200Smm{ 431231200Smm 432231200Smm switch (ret) { 433231200Smm case LZMA_STREAM_END: /* Found end of stream. */ 434231200Smm case LZMA_OK: /* Decompressor made some progress. */ 435231200Smm break; 436231200Smm case LZMA_MEM_ERROR: 437231200Smm archive_set_error(&self->archive->archive, ENOMEM, 438231200Smm "Lzma library error: Cannot allocate memory"); 439231200Smm break; 440231200Smm case LZMA_MEMLIMIT_ERROR: 441231200Smm archive_set_error(&self->archive->archive, ENOMEM, 442231200Smm "Lzma library error: Out of memory"); 443231200Smm break; 444231200Smm case LZMA_FORMAT_ERROR: 445231200Smm archive_set_error(&self->archive->archive, 446231200Smm ARCHIVE_ERRNO_MISC, 447231200Smm "Lzma library error: format not recognized"); 448231200Smm break; 449231200Smm case LZMA_OPTIONS_ERROR: 450231200Smm archive_set_error(&self->archive->archive, 451231200Smm ARCHIVE_ERRNO_MISC, 452231200Smm "Lzma library error: Invalid options"); 453231200Smm break; 454231200Smm case LZMA_DATA_ERROR: 455231200Smm archive_set_error(&self->archive->archive, 456231200Smm ARCHIVE_ERRNO_MISC, 457231200Smm "Lzma library error: Corrupted input data"); 458231200Smm break; 459231200Smm case LZMA_BUF_ERROR: 460231200Smm archive_set_error(&self->archive->archive, 461231200Smm ARCHIVE_ERRNO_MISC, 462231200Smm "Lzma library error: No progress is possible"); 463231200Smm break; 464231200Smm default: 465231200Smm /* Return an error. */ 466231200Smm archive_set_error(&self->archive->archive, 467231200Smm ARCHIVE_ERRNO_MISC, 468231200Smm "Lzma decompression failed: Unknown error"); 469231200Smm break; 470231200Smm } 471231200Smm} 472231200Smm 473231200Smm/* 474228753Smm * Setup the callbacks. 475228753Smm */ 476228753Smmstatic int 477228753Smmxz_lzma_bidder_init(struct archive_read_filter *self) 478228753Smm{ 479228753Smm static const size_t out_block_size = 64 * 1024; 480228753Smm void *out_block; 481228753Smm struct private_data *state; 482228753Smm int ret; 483228753Smm 484228753Smm state = (struct private_data *)calloc(sizeof(*state), 1); 485228753Smm out_block = (unsigned char *)malloc(out_block_size); 486228753Smm if (state == NULL || out_block == NULL) { 487228753Smm archive_set_error(&self->archive->archive, ENOMEM, 488228753Smm "Can't allocate data for xz decompression"); 489228753Smm free(out_block); 490228753Smm free(state); 491228753Smm return (ARCHIVE_FATAL); 492228753Smm } 493228753Smm 494228753Smm self->data = state; 495228753Smm state->out_block_size = out_block_size; 496228753Smm state->out_block = out_block; 497228753Smm self->read = xz_filter_read; 498228753Smm self->skip = NULL; /* not supported */ 499228753Smm self->close = xz_filter_close; 500228753Smm 501228753Smm state->stream.avail_in = 0; 502228753Smm 503228753Smm state->stream.next_out = state->out_block; 504228753Smm state->stream.avail_out = state->out_block_size; 505228753Smm 506231200Smm state->crc32 = 0; 507248616Smm if (self->code == ARCHIVE_FILTER_LZIP) { 508231200Smm /* 509231200Smm * We have to read a lzip header and use it to initialize 510231200Smm * compression library, thus we cannot initialize the 511231200Smm * library for lzip here. 512231200Smm */ 513231200Smm state->in_stream = 0; 514231200Smm return (ARCHIVE_OK); 515231200Smm } else 516231200Smm state->in_stream = 1; 517231200Smm 518231200Smm /* Initialize compression library. */ 519248616Smm if (self->code == ARCHIVE_FILTER_XZ) 520228753Smm ret = lzma_stream_decoder(&(state->stream), 521231200Smm LZMA_MEMLIMIT,/* memlimit */ 522228753Smm LZMA_CONCATENATED); 523228753Smm else 524228753Smm ret = lzma_alone_decoder(&(state->stream), 525231200Smm LZMA_MEMLIMIT);/* memlimit */ 526228753Smm 527228753Smm if (ret == LZMA_OK) 528228753Smm return (ARCHIVE_OK); 529228753Smm 530228753Smm /* Library setup failed: Choose an error message and clean up. */ 531231200Smm set_error(self, ret); 532228753Smm 533228753Smm free(state->out_block); 534228753Smm free(state); 535228753Smm self->data = NULL; 536228753Smm return (ARCHIVE_FATAL); 537228753Smm} 538228753Smm 539231200Smmstatic int 540231200Smmlzip_init(struct archive_read_filter *self) 541231200Smm{ 542231200Smm struct private_data *state; 543231200Smm const unsigned char *h; 544231200Smm lzma_filter filters[2]; 545231200Smm unsigned char props[5]; 546231200Smm ssize_t avail_in; 547231200Smm uint32_t dicsize; 548231200Smm int log2dic, ret; 549231200Smm 550231200Smm state = (struct private_data *)self->data; 551231200Smm h = __archive_read_filter_ahead(self->upstream, 6, &avail_in); 552231200Smm if (h == NULL) 553231200Smm return (ARCHIVE_FATAL); 554231200Smm 555231200Smm /* Get a version number. */ 556231200Smm state->lzip_ver = h[4]; 557231200Smm 558231200Smm /* 559231200Smm * Setup lzma property. 560231200Smm */ 561231200Smm props[0] = 0x5d; 562231200Smm 563231200Smm /* Get dictionary size. */ 564231200Smm log2dic = h[5] & 0x1f; 565231200Smm if (log2dic < 12 || log2dic > 27) 566231200Smm return (ARCHIVE_FATAL); 567231200Smm dicsize = 1U << log2dic; 568231200Smm if (log2dic > 12) 569231200Smm dicsize -= (dicsize / 16) * (h[5] >> 5); 570231200Smm archive_le32enc(props+1, dicsize); 571231200Smm 572231200Smm /* Consume lzip header. */ 573231200Smm __archive_read_filter_consume(self->upstream, 6); 574231200Smm state->member_in = 6; 575231200Smm 576231200Smm filters[0].id = LZMA_FILTER_LZMA1; 577231200Smm filters[0].options = NULL; 578231200Smm filters[1].id = LZMA_VLI_UNKNOWN; 579231200Smm filters[1].options = NULL; 580231200Smm 581231200Smm ret = lzma_properties_decode(&filters[0], NULL, props, sizeof(props)); 582231200Smm if (ret != LZMA_OK) { 583231200Smm set_error(self, ret); 584231200Smm return (ARCHIVE_FATAL); 585231200Smm } 586231200Smm ret = lzma_raw_decoder(&(state->stream), filters); 587231200Smm free(filters[0].options); 588231200Smm if (ret != LZMA_OK) { 589231200Smm set_error(self, ret); 590231200Smm return (ARCHIVE_FATAL); 591231200Smm } 592231200Smm return (ARCHIVE_OK); 593231200Smm} 594231200Smm 595231200Smmstatic int 596231200Smmlzip_tail(struct archive_read_filter *self) 597231200Smm{ 598231200Smm struct private_data *state; 599231200Smm const unsigned char *f; 600231200Smm ssize_t avail_in; 601231200Smm int tail; 602231200Smm 603231200Smm state = (struct private_data *)self->data; 604231200Smm if (state->lzip_ver == 0) 605231200Smm tail = 12; 606231200Smm else 607231200Smm tail = 20; 608231200Smm f = __archive_read_filter_ahead(self->upstream, tail, &avail_in); 609231200Smm if (f == NULL && avail_in < 0) 610231200Smm return (ARCHIVE_FATAL); 611302001Smm if (f == NULL || avail_in < tail) { 612231200Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 613231200Smm "Lzip: Remaining data is less bytes"); 614231200Smm return (ARCHIVE_FAILED); 615231200Smm } 616231200Smm 617231200Smm /* Check the crc32 value of the uncompressed data of the current 618231200Smm * member */ 619231200Smm if (state->crc32 != archive_le32dec(f)) { 620231200Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 621231200Smm "Lzip: CRC32 error"); 622231200Smm return (ARCHIVE_FAILED); 623231200Smm } 624231200Smm 625231200Smm /* Check the uncompressed size of the current member */ 626231200Smm if ((uint64_t)state->member_out != archive_le64dec(f + 4)) { 627231200Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 628231200Smm "Lzip: Uncompressed size error"); 629231200Smm return (ARCHIVE_FAILED); 630231200Smm } 631231200Smm 632231200Smm /* Check the total size of the current member */ 633231200Smm if (state->lzip_ver == 1 && 634231200Smm (uint64_t)state->member_in + tail != archive_le64dec(f + 12)) { 635231200Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 636231200Smm "Lzip: Member size error"); 637231200Smm return (ARCHIVE_FAILED); 638231200Smm } 639231200Smm __archive_read_filter_consume(self->upstream, tail); 640231200Smm 641231200Smm /* If current lzip data consists of multi member, try decompressing 642231200Smm * a next member. */ 643231200Smm if (lzip_has_member(self->upstream) != 0) { 644231200Smm state->in_stream = 0; 645231200Smm state->crc32 = 0; 646231200Smm state->member_out = 0; 647231200Smm state->member_in = 0; 648231200Smm state->eof = 0; 649231200Smm } 650231200Smm return (ARCHIVE_OK); 651231200Smm} 652231200Smm 653228753Smm/* 654228753Smm * Return the next block of decompressed data. 655228753Smm */ 656228753Smmstatic ssize_t 657228753Smmxz_filter_read(struct archive_read_filter *self, const void **p) 658228753Smm{ 659228753Smm struct private_data *state; 660228753Smm size_t decompressed; 661228753Smm ssize_t avail_in; 662228753Smm int ret; 663228753Smm 664228753Smm state = (struct private_data *)self->data; 665228753Smm 666228753Smm /* Empty our output buffer. */ 667228753Smm state->stream.next_out = state->out_block; 668228753Smm state->stream.avail_out = state->out_block_size; 669228753Smm 670228753Smm /* Try to fill the output buffer. */ 671228753Smm while (state->stream.avail_out > 0 && !state->eof) { 672231200Smm if (!state->in_stream) { 673231200Smm /* 674231200Smm * Initialize liblzma for lzip 675231200Smm */ 676231200Smm ret = lzip_init(self); 677231200Smm if (ret != ARCHIVE_OK) 678231200Smm return (ret); 679231200Smm state->in_stream = 1; 680231200Smm } 681228753Smm state->stream.next_in = 682228753Smm __archive_read_filter_ahead(self->upstream, 1, &avail_in); 683231200Smm if (state->stream.next_in == NULL && avail_in < 0) { 684231200Smm archive_set_error(&self->archive->archive, 685231200Smm ARCHIVE_ERRNO_MISC, 686231200Smm "truncated input"); 687228753Smm return (ARCHIVE_FATAL); 688231200Smm } 689228753Smm state->stream.avail_in = avail_in; 690228753Smm 691228753Smm /* Decompress as much as we can in one pass. */ 692228753Smm ret = lzma_code(&(state->stream), 693228753Smm (state->stream.avail_in == 0)? LZMA_FINISH: LZMA_RUN); 694228753Smm switch (ret) { 695228753Smm case LZMA_STREAM_END: /* Found end of stream. */ 696228753Smm state->eof = 1; 697228753Smm /* FALL THROUGH */ 698228753Smm case LZMA_OK: /* Decompressor made some progress. */ 699228753Smm __archive_read_filter_consume(self->upstream, 700228753Smm avail_in - state->stream.avail_in); 701231200Smm state->member_in += 702231200Smm avail_in - state->stream.avail_in; 703228753Smm break; 704228753Smm default: 705231200Smm set_error(self, ret); 706228753Smm return (ARCHIVE_FATAL); 707228753Smm } 708228753Smm } 709228753Smm 710228753Smm decompressed = state->stream.next_out - state->out_block; 711228753Smm state->total_out += decompressed; 712231200Smm state->member_out += decompressed; 713228753Smm if (decompressed == 0) 714228753Smm *p = NULL; 715231200Smm else { 716228753Smm *p = state->out_block; 717248616Smm if (self->code == ARCHIVE_FILTER_LZIP) { 718231200Smm state->crc32 = lzma_crc32(state->out_block, 719231200Smm decompressed, state->crc32); 720231200Smm if (state->eof) { 721231200Smm ret = lzip_tail(self); 722231200Smm if (ret != ARCHIVE_OK) 723231200Smm return (ret); 724231200Smm } 725231200Smm } 726231200Smm } 727228753Smm return (decompressed); 728228753Smm} 729228753Smm 730228753Smm/* 731228753Smm * Clean up the decompressor. 732228753Smm */ 733228753Smmstatic int 734228753Smmxz_filter_close(struct archive_read_filter *self) 735228753Smm{ 736228753Smm struct private_data *state; 737228753Smm 738228753Smm state = (struct private_data *)self->data; 739228753Smm lzma_end(&(state->stream)); 740228753Smm free(state->out_block); 741228753Smm free(state); 742228753Smm return (ARCHIVE_OK); 743228753Smm} 744228753Smm 745228753Smm#else 746228753Smm 747228753Smm/* 748228753Smm * 749228753Smm * If we have no suitable library on this system, we can't actually do 750228753Smm * the decompression. We can, however, still detect compressed 751228753Smm * archives and emit a useful message. 752228753Smm * 753228753Smm */ 754228753Smmstatic int 755228753Smmlzma_bidder_init(struct archive_read_filter *self) 756228753Smm{ 757228753Smm int r; 758228753Smm 759248616Smm r = __archive_read_program(self, "lzma -d -qq"); 760228753Smm /* Note: We set the format here even if __archive_read_program() 761228753Smm * above fails. We do, after all, know what the format is 762228753Smm * even if we weren't able to read it. */ 763248616Smm self->code = ARCHIVE_FILTER_LZMA; 764228753Smm self->name = "lzma"; 765228753Smm return (r); 766228753Smm} 767228753Smm 768228753Smmstatic int 769228753Smmxz_bidder_init(struct archive_read_filter *self) 770228753Smm{ 771228753Smm int r; 772228753Smm 773248616Smm r = __archive_read_program(self, "xz -d -qq"); 774228753Smm /* Note: We set the format here even if __archive_read_program() 775228753Smm * above fails. We do, after all, know what the format is 776228753Smm * even if we weren't able to read it. */ 777248616Smm self->code = ARCHIVE_FILTER_XZ; 778228753Smm self->name = "xz"; 779228753Smm return (r); 780228753Smm} 781228753Smm 782231200Smmstatic int 783231200Smmlzip_bidder_init(struct archive_read_filter *self) 784231200Smm{ 785231200Smm int r; 786228753Smm 787248616Smm r = __archive_read_program(self, "lzip -d -q"); 788231200Smm /* Note: We set the format here even if __archive_read_program() 789231200Smm * above fails. We do, after all, know what the format is 790231200Smm * even if we weren't able to read it. */ 791248616Smm self->code = ARCHIVE_FILTER_LZIP; 792231200Smm self->name = "lzip"; 793231200Smm return (r); 794231200Smm} 795231200Smm 796228753Smm#endif /* HAVE_LZMA_H */ 797