1248590Smm/*- 2248590Smm * Copyright (c) 2003-2007 Tim Kientzle 3248590Smm * Copyright (c) 2012 Michihiro NAKAJIMA 4248590Smm * All rights reserved. 5248590Smm * 6248590Smm * Redistribution and use in source and binary forms, with or without 7248590Smm * modification, are permitted provided that the following conditions 8248590Smm * are met: 9248590Smm * 1. Redistributions of source code must retain the above copyright 10248590Smm * notice, this list of conditions and the following disclaimer. 11248590Smm * 2. Redistributions in binary form must reproduce the above copyright 12248590Smm * notice, this list of conditions and the following disclaimer in the 13248590Smm * documentation and/or other materials provided with the distribution. 14248590Smm * 15248590Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16248590Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17248590Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18248590Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19248590Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20248590Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21248590Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22248590Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23248590Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24248590Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25248590Smm */ 26248590Smm 27248590Smm#include "archive_platform.h" 28248590Smm 29248590Smm__FBSDID("$FreeBSD$"); 30248590Smm 31248590Smm#ifdef HAVE_UNISTD_H 32248590Smm#include <unistd.h> 33248590Smm#endif 34248590Smm#ifdef HAVE_ERRNO_H 35248590Smm#include <errno.h> 36248590Smm#endif 37248590Smm#ifdef HAVE_STDLIB_H 38248590Smm#include <stdlib.h> 39248590Smm#endif 40248590Smm#ifdef HAVE_STRING_H 41248590Smm#include <string.h> 42248590Smm#endif 43248590Smm#ifdef HAVE_UNISTD_H 44248590Smm#include <unistd.h> 45248590Smm#endif 46248590Smm#ifdef HAVE_LZO_LZOCONF_H 47248590Smm#include <lzo/lzoconf.h> 48248590Smm#endif 49248590Smm#ifdef HAVE_LZO_LZO1X_H 50248590Smm#include <lzo/lzo1x.h> 51248590Smm#endif 52248590Smm#ifdef HAVE_ZLIB_H 53248590Smm#include <zlib.h> /* for crc32 and adler32 */ 54248590Smm#endif 55248590Smm 56248590Smm#include "archive.h" 57248590Smm#if !defined(HAVE_ZLIB_H) &&\ 58248590Smm defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) 59248590Smm#include "archive_crc32.h" 60248590Smm#endif 61248590Smm#include "archive_endian.h" 62248590Smm#include "archive_private.h" 63248590Smm#include "archive_read_private.h" 64248590Smm 65248590Smm#ifndef HAVE_ZLIB_H 66248590Smm#define adler32 lzo_adler32 67248590Smm#endif 68248590Smm 69248590Smm#define LZOP_HEADER_MAGIC "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a" 70248590Smm#define LZOP_HEADER_MAGIC_LEN 9 71248590Smm 72248590Smm#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) 73248590Smmstruct read_lzop { 74248590Smm unsigned char *out_block; 75248590Smm size_t out_block_size; 76248590Smm int64_t total_out; 77248590Smm int flags; 78248590Smm uint32_t compressed_cksum; 79248590Smm uint32_t uncompressed_cksum; 80248590Smm size_t compressed_size; 81248590Smm size_t uncompressed_size; 82248590Smm size_t unconsumed_bytes; 83248590Smm char in_stream; 84248590Smm char eof; /* True = found end of compressed data. */ 85248590Smm}; 86248590Smm 87248590Smm#define FILTER 0x0800 88248590Smm#define CRC32_HEADER 0x1000 89248590Smm#define EXTRA_FIELD 0x0040 90248590Smm#define ADLER32_UNCOMPRESSED 0x0001 91248590Smm#define ADLER32_COMPRESSED 0x0002 92248590Smm#define CRC32_UNCOMPRESSED 0x0100 93248590Smm#define CRC32_COMPRESSED 0x0200 94248590Smm#define MAX_BLOCK_SIZE (64 * 1024 * 1024) 95248590Smm 96248590Smmstatic ssize_t lzop_filter_read(struct archive_read_filter *, const void **); 97248590Smmstatic int lzop_filter_close(struct archive_read_filter *); 98248590Smm#endif 99248590Smm 100248590Smmstatic int lzop_bidder_bid(struct archive_read_filter_bidder *, 101248590Smm struct archive_read_filter *); 102248590Smmstatic int lzop_bidder_init(struct archive_read_filter *); 103248590Smm 104248590Smmint 105248590Smmarchive_read_support_filter_lzop(struct archive *_a) 106248590Smm{ 107248590Smm struct archive_read *a = (struct archive_read *)_a; 108248590Smm struct archive_read_filter_bidder *reader; 109248590Smm 110248590Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 111248590Smm ARCHIVE_STATE_NEW, "archive_read_support_filter_lzop"); 112248590Smm 113248590Smm if (__archive_read_get_bidder(a, &reader) != ARCHIVE_OK) 114248590Smm return (ARCHIVE_FATAL); 115248590Smm 116248590Smm reader->data = NULL; 117248590Smm reader->bid = lzop_bidder_bid; 118248590Smm reader->init = lzop_bidder_init; 119248590Smm reader->options = NULL; 120248590Smm reader->free = NULL; 121248590Smm /* Signal the extent of lzop support with the return value here. */ 122248590Smm#if defined(HAVE_LZO_LZOCONF_H) && defined(HAVE_LZO_LZO1X_H) 123248590Smm return (ARCHIVE_OK); 124248590Smm#else 125248590Smm /* Return ARCHIVE_WARN since this always uses an external program. */ 126248590Smm archive_set_error(_a, ARCHIVE_ERRNO_MISC, 127248590Smm "Using external lzop program for lzop decompression"); 128248590Smm return (ARCHIVE_WARN); 129248590Smm#endif 130248590Smm} 131248590Smm 132248590Smm/* 133248590Smm * Bidder just verifies the header and returns the number of verified bits. 134248590Smm */ 135248590Smmstatic int 136248590Smmlzop_bidder_bid(struct archive_read_filter_bidder *self, 137248590Smm struct archive_read_filter *filter) 138248590Smm{ 139248590Smm const unsigned char *p; 140248590Smm ssize_t avail; 141248590Smm 142248590Smm (void)self; /* UNUSED */ 143248590Smm 144248590Smm p = __archive_read_filter_ahead(filter, LZOP_HEADER_MAGIC_LEN, &avail); 145248590Smm if (p == NULL || avail == 0) 146248590Smm return (0); 147248590Smm 148248590Smm if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) 149248590Smm return (0); 150248590Smm 151248590Smm return (LZOP_HEADER_MAGIC_LEN * 8); 152248590Smm} 153248590Smm 154248590Smm#if !defined(HAVE_LZO_LZOCONF_H) || !defined(HAVE_LZO_LZO1X_H) 155248590Smm/* 156248590Smm * If we don't have the library on this system, we can't do the 157248590Smm * decompression directly. We can, however, try to run "lzop -d" 158248590Smm * in case that's available. 159248590Smm */ 160248590Smmstatic int 161248590Smmlzop_bidder_init(struct archive_read_filter *self) 162248590Smm{ 163248590Smm int r; 164248590Smm 165248590Smm r = __archive_read_program(self, "lzop -d"); 166248590Smm /* Note: We set the format here even if __archive_read_program() 167248590Smm * above fails. We do, after all, know what the format is 168248590Smm * even if we weren't able to read it. */ 169248590Smm self->code = ARCHIVE_FILTER_LZOP; 170248590Smm self->name = "lzop"; 171248590Smm return (r); 172248590Smm} 173248590Smm#else 174248590Smm/* 175248590Smm * Initialize the filter object. 176248590Smm */ 177248590Smmstatic int 178248590Smmlzop_bidder_init(struct archive_read_filter *self) 179248590Smm{ 180248590Smm struct read_lzop *state; 181248590Smm 182248590Smm self->code = ARCHIVE_FILTER_LZOP; 183248590Smm self->name = "lzop"; 184248590Smm 185248590Smm state = (struct read_lzop *)calloc(sizeof(*state), 1); 186248590Smm if (state == NULL) { 187248590Smm archive_set_error(&self->archive->archive, ENOMEM, 188248590Smm "Can't allocate data for lzop decompression"); 189248590Smm return (ARCHIVE_FATAL); 190248590Smm } 191248590Smm 192248590Smm self->data = state; 193248590Smm self->read = lzop_filter_read; 194248590Smm self->skip = NULL; /* not supported */ 195248590Smm self->close = lzop_filter_close; 196248590Smm 197248590Smm return (ARCHIVE_OK); 198248590Smm} 199248590Smm 200248590Smmstatic int 201248590Smmconsume_header(struct archive_read_filter *self) 202248590Smm{ 203248590Smm struct read_lzop *state = (struct read_lzop *)self->data; 204248590Smm const unsigned char *p, *_p; 205248590Smm unsigned checksum, flags, len, method, version; 206248590Smm 207248590Smm /* 208248590Smm * Check LZOP magic code. 209248590Smm */ 210248590Smm p = __archive_read_filter_ahead(self->upstream, 211248590Smm LZOP_HEADER_MAGIC_LEN, NULL); 212248590Smm if (p == NULL) 213248590Smm return (ARCHIVE_EOF); 214248590Smm 215248590Smm if (memcmp(p, LZOP_HEADER_MAGIC, LZOP_HEADER_MAGIC_LEN)) 216248590Smm return (ARCHIVE_EOF); 217248590Smm __archive_read_filter_consume(self->upstream, 218248590Smm LZOP_HEADER_MAGIC_LEN); 219248590Smm 220248590Smm p = __archive_read_filter_ahead(self->upstream, 29, NULL); 221248590Smm if (p == NULL) 222248590Smm goto truncated; 223248590Smm _p = p; 224248590Smm version = archive_be16dec(p); 225248590Smm p += 4;/* version(2 bytes) + library version(2 bytes) */ 226248590Smm 227248590Smm if (version >= 0x940) { 228248590Smm unsigned reqversion = archive_be16dec(p); p += 2; 229248590Smm if (reqversion < 0x900) { 230248590Smm archive_set_error(&self->archive->archive, 231248590Smm ARCHIVE_ERRNO_MISC, "Invalid required version"); 232248590Smm return (ARCHIVE_FAILED); 233248590Smm } 234248590Smm } 235248590Smm 236248590Smm method = *p++; 237248590Smm if (method < 1 || method > 3) { 238248590Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 239248590Smm "Unsupported method"); 240248590Smm return (ARCHIVE_FAILED); 241248590Smm } 242248590Smm 243248590Smm if (version >= 0x940) { 244248590Smm unsigned level = *p++; 245302001Smm#if 0 246302001Smm unsigned default_level[] = {0, 3, 1, 9}; 247302001Smm#endif 248302001Smm if (level == 0) 249302001Smm /* Method is 1..3 here due to check above. */ 250302001Smm#if 0 /* Avoid an error Clang Static Analyzer claims 251302001Smm "Value stored to 'level' is never read". */ 252302001Smm level = default_level[method]; 253302001Smm#else 254302001Smm ;/* NOP */ 255302001Smm#endif 256302001Smm else if (level > 9) { 257248590Smm archive_set_error(&self->archive->archive, 258248590Smm ARCHIVE_ERRNO_MISC, "Invalid level"); 259248590Smm return (ARCHIVE_FAILED); 260248590Smm } 261248590Smm } 262248590Smm 263248590Smm flags = archive_be32dec(p); p += 4; 264248590Smm 265248590Smm if (flags & FILTER) 266248590Smm p += 4; /* Skip filter */ 267248590Smm p += 4; /* Skip mode */ 268248590Smm if (version >= 0x940) 269248590Smm p += 8; /* Skip mtime */ 270248590Smm else 271248590Smm p += 4; /* Skip mtime */ 272248590Smm len = *p++; /* Read filename length */ 273248590Smm len += p - _p; 274248590Smm /* Make sure we have all bytes we need to calculate checksum. */ 275248590Smm p = __archive_read_filter_ahead(self->upstream, len + 4, NULL); 276248590Smm if (p == NULL) 277248590Smm goto truncated; 278248590Smm if (flags & CRC32_HEADER) 279248590Smm checksum = crc32(crc32(0, NULL, 0), p, len); 280248590Smm else 281248590Smm checksum = adler32(adler32(0, NULL, 0), p, len); 282248590Smm if (archive_be32dec(p + len) != checksum) 283248590Smm goto corrupted; 284248590Smm __archive_read_filter_consume(self->upstream, len + 4); 285248590Smm if (flags & EXTRA_FIELD) { 286248590Smm /* Skip extra field */ 287248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 288248590Smm if (p == NULL) 289248590Smm goto truncated; 290248590Smm len = archive_be32dec(p); 291248590Smm __archive_read_filter_consume(self->upstream, len + 4 + 4); 292248590Smm } 293248590Smm state->flags = flags; 294248590Smm state->in_stream = 1; 295248590Smm return (ARCHIVE_OK); 296248590Smmtruncated: 297248590Smm archive_set_error(&self->archive->archive, 298248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 299248590Smm return (ARCHIVE_FAILED); 300248590Smmcorrupted: 301248590Smm archive_set_error(&self->archive->archive, 302248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); 303248590Smm return (ARCHIVE_FAILED); 304248590Smm} 305248590Smm 306248590Smmstatic int 307248590Smmconsume_block_info(struct archive_read_filter *self) 308248590Smm{ 309248590Smm struct read_lzop *state = (struct read_lzop *)self->data; 310248590Smm const unsigned char *p; 311248590Smm unsigned flags = state->flags; 312248590Smm 313248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 314248590Smm if (p == NULL) 315248590Smm goto truncated; 316248590Smm state->uncompressed_size = archive_be32dec(p); 317248590Smm __archive_read_filter_consume(self->upstream, 4); 318248590Smm if (state->uncompressed_size == 0) 319248590Smm return (ARCHIVE_EOF); 320248590Smm if (state->uncompressed_size > MAX_BLOCK_SIZE) 321248590Smm goto corrupted; 322248590Smm 323248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 324248590Smm if (p == NULL) 325248590Smm goto truncated; 326248590Smm state->compressed_size = archive_be32dec(p); 327248590Smm __archive_read_filter_consume(self->upstream, 4); 328248590Smm if (state->compressed_size > state->uncompressed_size) 329248590Smm goto corrupted; 330248590Smm 331248590Smm if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) { 332248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 333248590Smm if (p == NULL) 334248590Smm goto truncated; 335248590Smm state->compressed_cksum = state->uncompressed_cksum = 336248590Smm archive_be32dec(p); 337248590Smm __archive_read_filter_consume(self->upstream, 4); 338248590Smm } 339248590Smm if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) && 340248590Smm state->compressed_size < state->uncompressed_size) { 341248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 342248590Smm if (p == NULL) 343248590Smm goto truncated; 344248590Smm state->compressed_cksum = archive_be32dec(p); 345248590Smm __archive_read_filter_consume(self->upstream, 4); 346248590Smm } 347248590Smm return (ARCHIVE_OK); 348248590Smmtruncated: 349248590Smm archive_set_error(&self->archive->archive, 350248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 351248590Smm return (ARCHIVE_FAILED); 352248590Smmcorrupted: 353248590Smm archive_set_error(&self->archive->archive, 354248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); 355248590Smm return (ARCHIVE_FAILED); 356248590Smm} 357248590Smm 358248590Smmstatic ssize_t 359248590Smmlzop_filter_read(struct archive_read_filter *self, const void **p) 360248590Smm{ 361248590Smm struct read_lzop *state = (struct read_lzop *)self->data; 362248590Smm const void *b; 363248590Smm lzo_uint out_size; 364248590Smm uint32_t cksum; 365248590Smm int ret, r; 366248590Smm 367248590Smm if (state->unconsumed_bytes) { 368248590Smm __archive_read_filter_consume(self->upstream, 369248590Smm state->unconsumed_bytes); 370248590Smm state->unconsumed_bytes = 0; 371248590Smm } 372248590Smm if (state->eof) 373248590Smm return (0); 374248590Smm 375248590Smm for (;;) { 376248590Smm if (!state->in_stream) { 377248590Smm ret = consume_header(self); 378248590Smm if (ret < ARCHIVE_OK) 379248590Smm return (ret); 380248590Smm if (ret == ARCHIVE_EOF) { 381248590Smm state->eof = 1; 382248590Smm return (0); 383248590Smm } 384248590Smm } 385248590Smm ret = consume_block_info(self); 386248590Smm if (ret < ARCHIVE_OK) 387248590Smm return (ret); 388248590Smm if (ret == ARCHIVE_EOF) 389248590Smm state->in_stream = 0; 390248590Smm else 391248590Smm break; 392248590Smm } 393248590Smm 394248590Smm if (state->out_block == NULL || 395248590Smm state->out_block_size < state->uncompressed_size) { 396248590Smm void *new_block; 397248590Smm 398248590Smm new_block = realloc(state->out_block, state->uncompressed_size); 399248590Smm if (new_block == NULL) { 400248590Smm archive_set_error(&self->archive->archive, ENOMEM, 401248590Smm "Can't allocate data for lzop decompression"); 402248590Smm return (ARCHIVE_FATAL); 403248590Smm } 404248590Smm state->out_block = new_block; 405248590Smm state->out_block_size = state->uncompressed_size; 406248590Smm } 407248590Smm 408248590Smm b = __archive_read_filter_ahead(self->upstream, 409248590Smm state->compressed_size, NULL); 410248590Smm if (b == NULL) { 411248590Smm archive_set_error(&self->archive->archive, 412248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 413248590Smm return (ARCHIVE_FATAL); 414248590Smm } 415248590Smm if (state->flags & CRC32_COMPRESSED) 416248590Smm cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size); 417248590Smm else if (state->flags & ADLER32_COMPRESSED) 418248590Smm cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size); 419248590Smm else 420248590Smm cksum = state->compressed_cksum; 421248590Smm if (cksum != state->compressed_cksum) { 422248590Smm archive_set_error(&self->archive->archive, 423248590Smm ARCHIVE_ERRNO_MISC, "Corrupted data"); 424248590Smm return (ARCHIVE_FATAL); 425248590Smm } 426248590Smm 427248590Smm /* 428248590Smm * If the both uncompressed size and compressed size are the same, 429248590Smm * we do not decompress this block. 430248590Smm */ 431248590Smm if (state->uncompressed_size == state->compressed_size) { 432248590Smm *p = b; 433248590Smm state->total_out += state->compressed_size; 434248590Smm state->unconsumed_bytes = state->compressed_size; 435248590Smm return ((ssize_t)state->uncompressed_size); 436248590Smm } 437248590Smm 438248590Smm /* 439313571Smm * Drive lzo uncompression. 440248590Smm */ 441248590Smm out_size = (lzo_uint)state->uncompressed_size; 442248590Smm r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, 443248590Smm state->out_block, &out_size, NULL); 444248590Smm switch (r) { 445248590Smm case LZO_E_OK: 446248590Smm if (out_size == state->uncompressed_size) 447248590Smm break; 448248590Smm archive_set_error(&self->archive->archive, 449248590Smm ARCHIVE_ERRNO_MISC, "Corrupted data"); 450248590Smm return (ARCHIVE_FATAL); 451248590Smm case LZO_E_OUT_OF_MEMORY: 452248590Smm archive_set_error(&self->archive->archive, ENOMEM, 453248590Smm "lzop decompression failed: out of memory"); 454248590Smm return (ARCHIVE_FATAL); 455248590Smm default: 456248590Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 457248590Smm "lzop decompression failed: %d", r); 458248590Smm return (ARCHIVE_FATAL); 459248590Smm } 460248590Smm 461248590Smm if (state->flags & CRC32_UNCOMPRESSED) 462248590Smm cksum = crc32(crc32(0, NULL, 0), state->out_block, 463248590Smm state->uncompressed_size); 464248590Smm else if (state->flags & ADLER32_UNCOMPRESSED) 465248590Smm cksum = adler32(adler32(0, NULL, 0), state->out_block, 466248590Smm state->uncompressed_size); 467248590Smm else 468248590Smm cksum = state->uncompressed_cksum; 469248590Smm if (cksum != state->uncompressed_cksum) { 470248590Smm archive_set_error(&self->archive->archive, 471248590Smm ARCHIVE_ERRNO_MISC, "Corrupted data"); 472248590Smm return (ARCHIVE_FATAL); 473248590Smm } 474248590Smm 475248590Smm __archive_read_filter_consume(self->upstream, state->compressed_size); 476248590Smm *p = state->out_block; 477248590Smm state->total_out += out_size; 478248590Smm return ((ssize_t)out_size); 479248590Smm} 480248590Smm 481248590Smm/* 482248590Smm * Clean up the decompressor. 483248590Smm */ 484248590Smmstatic int 485248590Smmlzop_filter_close(struct archive_read_filter *self) 486248590Smm{ 487248590Smm struct read_lzop *state = (struct read_lzop *)self->data; 488248590Smm 489248590Smm free(state->out_block); 490248590Smm free(state); 491248590Smm return (ARCHIVE_OK); 492248590Smm} 493248590Smm 494248590Smm#endif 495