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++; 245248590Smm if (method == 1 && level == 0) level = 3; 246248590Smm if (method == 2 && level == 0) level = 1; 247248590Smm if (method == 3 && level == 0) level = 9; 248248590Smm if (level < 1 && level > 9) { 249248590Smm archive_set_error(&self->archive->archive, 250248590Smm ARCHIVE_ERRNO_MISC, "Invalid level"); 251248590Smm return (ARCHIVE_FAILED); 252248590Smm } 253248590Smm } 254248590Smm 255248590Smm flags = archive_be32dec(p); p += 4; 256248590Smm 257248590Smm if (flags & FILTER) 258248590Smm p += 4; /* Skip filter */ 259248590Smm p += 4; /* Skip mode */ 260248590Smm if (version >= 0x940) 261248590Smm p += 8; /* Skip mtime */ 262248590Smm else 263248590Smm p += 4; /* Skip mtime */ 264248590Smm len = *p++; /* Read filename length */ 265248590Smm len += p - _p; 266248590Smm /* Make sure we have all bytes we need to calculate checksum. */ 267248590Smm p = __archive_read_filter_ahead(self->upstream, len + 4, NULL); 268248590Smm if (p == NULL) 269248590Smm goto truncated; 270248590Smm if (flags & CRC32_HEADER) 271248590Smm checksum = crc32(crc32(0, NULL, 0), p, len); 272248590Smm else 273248590Smm checksum = adler32(adler32(0, NULL, 0), p, len); 274248590Smm if (archive_be32dec(p + len) != checksum) 275248590Smm goto corrupted; 276248590Smm __archive_read_filter_consume(self->upstream, len + 4); 277248590Smm if (flags & EXTRA_FIELD) { 278248590Smm /* Skip extra field */ 279248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 280248590Smm if (p == NULL) 281248590Smm goto truncated; 282248590Smm len = archive_be32dec(p); 283248590Smm __archive_read_filter_consume(self->upstream, len + 4 + 4); 284248590Smm } 285248590Smm state->flags = flags; 286248590Smm state->in_stream = 1; 287248590Smm return (ARCHIVE_OK); 288248590Smmtruncated: 289248590Smm archive_set_error(&self->archive->archive, 290248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 291248590Smm return (ARCHIVE_FAILED); 292248590Smmcorrupted: 293248590Smm archive_set_error(&self->archive->archive, 294248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); 295248590Smm return (ARCHIVE_FAILED); 296248590Smm} 297248590Smm 298248590Smmstatic int 299248590Smmconsume_block_info(struct archive_read_filter *self) 300248590Smm{ 301248590Smm struct read_lzop *state = (struct read_lzop *)self->data; 302248590Smm const unsigned char *p; 303248590Smm unsigned flags = state->flags; 304248590Smm 305248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 306248590Smm if (p == NULL) 307248590Smm goto truncated; 308248590Smm state->uncompressed_size = archive_be32dec(p); 309248590Smm __archive_read_filter_consume(self->upstream, 4); 310248590Smm if (state->uncompressed_size == 0) 311248590Smm return (ARCHIVE_EOF); 312248590Smm if (state->uncompressed_size > MAX_BLOCK_SIZE) 313248590Smm goto corrupted; 314248590Smm 315248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 316248590Smm if (p == NULL) 317248590Smm goto truncated; 318248590Smm state->compressed_size = archive_be32dec(p); 319248590Smm __archive_read_filter_consume(self->upstream, 4); 320248590Smm if (state->compressed_size > state->uncompressed_size) 321248590Smm goto corrupted; 322248590Smm 323248590Smm if (flags & (CRC32_UNCOMPRESSED | ADLER32_UNCOMPRESSED)) { 324248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 325248590Smm if (p == NULL) 326248590Smm goto truncated; 327248590Smm state->compressed_cksum = state->uncompressed_cksum = 328248590Smm archive_be32dec(p); 329248590Smm __archive_read_filter_consume(self->upstream, 4); 330248590Smm } 331248590Smm if ((flags & (CRC32_COMPRESSED | ADLER32_COMPRESSED)) && 332248590Smm state->compressed_size < state->uncompressed_size) { 333248590Smm p = __archive_read_filter_ahead(self->upstream, 4, NULL); 334248590Smm if (p == NULL) 335248590Smm goto truncated; 336248590Smm state->compressed_cksum = archive_be32dec(p); 337248590Smm __archive_read_filter_consume(self->upstream, 4); 338248590Smm } 339248590Smm return (ARCHIVE_OK); 340248590Smmtruncated: 341248590Smm archive_set_error(&self->archive->archive, 342248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 343248590Smm return (ARCHIVE_FAILED); 344248590Smmcorrupted: 345248590Smm archive_set_error(&self->archive->archive, 346248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Corrupted lzop header"); 347248590Smm return (ARCHIVE_FAILED); 348248590Smm} 349248590Smm 350248590Smmstatic ssize_t 351248590Smmlzop_filter_read(struct archive_read_filter *self, const void **p) 352248590Smm{ 353248590Smm struct read_lzop *state = (struct read_lzop *)self->data; 354248590Smm const void *b; 355248590Smm lzo_uint out_size; 356248590Smm uint32_t cksum; 357248590Smm int ret, r; 358248590Smm 359248590Smm if (state->unconsumed_bytes) { 360248590Smm __archive_read_filter_consume(self->upstream, 361248590Smm state->unconsumed_bytes); 362248590Smm state->unconsumed_bytes = 0; 363248590Smm } 364248590Smm if (state->eof) 365248590Smm return (0); 366248590Smm 367248590Smm for (;;) { 368248590Smm if (!state->in_stream) { 369248590Smm ret = consume_header(self); 370248590Smm if (ret < ARCHIVE_OK) 371248590Smm return (ret); 372248590Smm if (ret == ARCHIVE_EOF) { 373248590Smm state->eof = 1; 374248590Smm return (0); 375248590Smm } 376248590Smm } 377248590Smm ret = consume_block_info(self); 378248590Smm if (ret < ARCHIVE_OK) 379248590Smm return (ret); 380248590Smm if (ret == ARCHIVE_EOF) 381248590Smm state->in_stream = 0; 382248590Smm else 383248590Smm break; 384248590Smm } 385248590Smm 386248590Smm if (state->out_block == NULL || 387248590Smm state->out_block_size < state->uncompressed_size) { 388248590Smm void *new_block; 389248590Smm 390248590Smm new_block = realloc(state->out_block, state->uncompressed_size); 391248590Smm if (new_block == NULL) { 392248590Smm archive_set_error(&self->archive->archive, ENOMEM, 393248590Smm "Can't allocate data for lzop decompression"); 394248590Smm return (ARCHIVE_FATAL); 395248590Smm } 396248590Smm state->out_block = new_block; 397248590Smm state->out_block_size = state->uncompressed_size; 398248590Smm } 399248590Smm 400248590Smm b = __archive_read_filter_ahead(self->upstream, 401248590Smm state->compressed_size, NULL); 402248590Smm if (b == NULL) { 403248590Smm archive_set_error(&self->archive->archive, 404248590Smm ARCHIVE_ERRNO_FILE_FORMAT, "Truncated lzop data"); 405248590Smm return (ARCHIVE_FATAL); 406248590Smm } 407248590Smm if (state->flags & CRC32_COMPRESSED) 408248590Smm cksum = crc32(crc32(0, NULL, 0), b, state->compressed_size); 409248590Smm else if (state->flags & ADLER32_COMPRESSED) 410248590Smm cksum = adler32(adler32(0, NULL, 0), b, state->compressed_size); 411248590Smm else 412248590Smm cksum = state->compressed_cksum; 413248590Smm if (cksum != state->compressed_cksum) { 414248590Smm archive_set_error(&self->archive->archive, 415248590Smm ARCHIVE_ERRNO_MISC, "Corrupted data"); 416248590Smm return (ARCHIVE_FATAL); 417248590Smm } 418248590Smm 419248590Smm /* 420248590Smm * If the both uncompressed size and compressed size are the same, 421248590Smm * we do not decompress this block. 422248590Smm */ 423248590Smm if (state->uncompressed_size == state->compressed_size) { 424248590Smm *p = b; 425248590Smm state->total_out += state->compressed_size; 426248590Smm state->unconsumed_bytes = state->compressed_size; 427248590Smm return ((ssize_t)state->uncompressed_size); 428248590Smm } 429248590Smm 430248590Smm /* 431248590Smm * Drive lzo uncompresison. 432248590Smm */ 433248590Smm out_size = (lzo_uint)state->uncompressed_size; 434248590Smm r = lzo1x_decompress_safe(b, (lzo_uint)state->compressed_size, 435248590Smm state->out_block, &out_size, NULL); 436248590Smm switch (r) { 437248590Smm case LZO_E_OK: 438248590Smm if (out_size == state->uncompressed_size) 439248590Smm break; 440248590Smm archive_set_error(&self->archive->archive, 441248590Smm ARCHIVE_ERRNO_MISC, "Corrupted data"); 442248590Smm return (ARCHIVE_FATAL); 443248590Smm case LZO_E_OUT_OF_MEMORY: 444248590Smm archive_set_error(&self->archive->archive, ENOMEM, 445248590Smm "lzop decompression failed: out of memory"); 446248590Smm return (ARCHIVE_FATAL); 447248590Smm default: 448248590Smm archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, 449248590Smm "lzop decompression failed: %d", r); 450248590Smm return (ARCHIVE_FATAL); 451248590Smm } 452248590Smm 453248590Smm if (state->flags & CRC32_UNCOMPRESSED) 454248590Smm cksum = crc32(crc32(0, NULL, 0), state->out_block, 455248590Smm state->uncompressed_size); 456248590Smm else if (state->flags & ADLER32_UNCOMPRESSED) 457248590Smm cksum = adler32(adler32(0, NULL, 0), state->out_block, 458248590Smm state->uncompressed_size); 459248590Smm else 460248590Smm cksum = state->uncompressed_cksum; 461248590Smm if (cksum != state->uncompressed_cksum) { 462248590Smm archive_set_error(&self->archive->archive, 463248590Smm ARCHIVE_ERRNO_MISC, "Corrupted data"); 464248590Smm return (ARCHIVE_FATAL); 465248590Smm } 466248590Smm 467248590Smm __archive_read_filter_consume(self->upstream, state->compressed_size); 468248590Smm *p = state->out_block; 469248590Smm state->total_out += out_size; 470248590Smm return ((ssize_t)out_size); 471248590Smm} 472248590Smm 473248590Smm/* 474248590Smm * Clean up the decompressor. 475248590Smm */ 476248590Smmstatic int 477248590Smmlzop_filter_close(struct archive_read_filter *self) 478248590Smm{ 479248590Smm struct read_lzop *state = (struct read_lzop *)self->data; 480248590Smm 481248590Smm free(state->out_block); 482248590Smm free(state); 483248590Smm return (ARCHIVE_OK); 484248590Smm} 485248590Smm 486248590Smm#endif 487