1231200Smm/*- 2299529Smm * Copyright (c) 2008-2014 Michihiro NAKAJIMA 3231200Smm * All rights reserved. 4231200Smm * 5231200Smm * Redistribution and use in source and binary forms, with or without 6231200Smm * modification, are permitted provided that the following conditions 7231200Smm * are met: 8231200Smm * 1. Redistributions of source code must retain the above copyright 9231200Smm * notice, this list of conditions and the following disclaimer. 10231200Smm * 2. Redistributions in binary form must reproduce the above copyright 11231200Smm * notice, this list of conditions and the following disclaimer in the 12231200Smm * documentation and/or other materials provided with the distribution. 13231200Smm * 14231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15231200Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16231200Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17231200Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18231200Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19231200Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20231200Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21231200Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22231200Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23231200Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24231200Smm */ 25231200Smm 26231200Smm#include "archive_platform.h" 27231200Smm 28231200Smm#ifdef HAVE_ERRNO_H 29231200Smm#include <errno.h> 30231200Smm#endif 31231200Smm#ifdef HAVE_LIMITS_H 32231200Smm#include <limits.h> 33231200Smm#endif 34231200Smm#ifdef HAVE_STDLIB_H 35231200Smm#include <stdlib.h> 36231200Smm#endif 37231200Smm#ifdef HAVE_STRING_H 38231200Smm#include <string.h> 39231200Smm#endif 40231200Smm 41231200Smm#include "archive.h" 42231200Smm#include "archive_entry.h" 43231200Smm#include "archive_entry_locale.h" 44231200Smm#include "archive_private.h" 45231200Smm#include "archive_read_private.h" 46231200Smm#include "archive_endian.h" 47231200Smm 48231200Smm 49231200Smm#define MAXMATCH 256 /* Maximum match length. */ 50231200Smm#define MINMATCH 3 /* Minimum match length. */ 51231200Smm/* 52231200Smm * Literal table format: 53231200Smm * +0 +256 +510 54231200Smm * +---------------+-------------------------+ 55231200Smm * | literal code | match length | 56231200Smm * | 0 ... 255 | MINMATCH ... MAXMATCH | 57231200Smm * +---------------+-------------------------+ 58231200Smm * <--- LT_BITLEN_SIZE ---> 59231200Smm */ 60231200Smm/* Literal table size. */ 61231200Smm#define LT_BITLEN_SIZE (UCHAR_MAX + 1 + MAXMATCH - MINMATCH + 1) 62231200Smm/* Position table size. 63231200Smm * Note: this used for both position table and pre literal table.*/ 64231200Smm#define PT_BITLEN_SIZE (3 + 16) 65231200Smm 66231200Smmstruct lzh_dec { 67231200Smm /* Decoding status. */ 68231200Smm int state; 69231200Smm 70231200Smm /* 71231200Smm * Window to see last 8Ki(lh5),32Ki(lh6),64Ki(lh7) bytes of decoded 72231200Smm * data. 73231200Smm */ 74231200Smm int w_size; 75231200Smm int w_mask; 76231200Smm /* Window buffer, which is a loop buffer. */ 77231200Smm unsigned char *w_buff; 78231200Smm /* The insert position to the window. */ 79231200Smm int w_pos; 80231200Smm /* The position where we can copy decoded code from the window. */ 81231200Smm int copy_pos; 82231200Smm /* The length how many bytes we can copy decoded code from 83231200Smm * the window. */ 84231200Smm int copy_len; 85231200Smm 86231200Smm /* 87231200Smm * Bit stream reader. 88231200Smm */ 89231200Smm struct lzh_br { 90231200Smm#define CACHE_TYPE uint64_t 91231200Smm#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) 92231200Smm /* Cache buffer. */ 93231200Smm CACHE_TYPE cache_buffer; 94231200Smm /* Indicates how many bits avail in cache_buffer. */ 95231200Smm int cache_avail; 96231200Smm } br; 97231200Smm 98231200Smm /* 99231200Smm * Huffman coding. 100231200Smm */ 101231200Smm struct huffman { 102231200Smm int len_size; 103231200Smm int len_avail; 104231200Smm int len_bits; 105231200Smm int freq[17]; 106231200Smm unsigned char *bitlen; 107231200Smm 108231200Smm /* 109231200Smm * Use a index table. It's faster than searching a huffman 110231200Smm * coding tree, which is a binary tree. But a use of a large 111231200Smm * index table causes L1 cache read miss many times. 112231200Smm */ 113231200Smm#define HTBL_BITS 10 114231200Smm int max_bits; 115231200Smm int shift_bits; 116231200Smm int tbl_bits; 117231200Smm int tree_used; 118231200Smm int tree_avail; 119231200Smm /* Direct access table. */ 120231200Smm uint16_t *tbl; 121231200Smm /* Binary tree table for extra bits over the direct access. */ 122231200Smm struct htree_t { 123231200Smm uint16_t left; 124231200Smm uint16_t right; 125231200Smm } *tree; 126231200Smm } lt, pt; 127231200Smm 128231200Smm int blocks_avail; 129231200Smm int pos_pt_len_size; 130231200Smm int pos_pt_len_bits; 131231200Smm int literal_pt_len_size; 132231200Smm int literal_pt_len_bits; 133231200Smm int reading_position; 134231200Smm int loop; 135231200Smm int error; 136231200Smm}; 137231200Smm 138231200Smmstruct lzh_stream { 139231200Smm const unsigned char *next_in; 140299529Smm int avail_in; 141231200Smm int64_t total_in; 142299529Smm const unsigned char *ref_ptr; 143299529Smm int avail_out; 144231200Smm int64_t total_out; 145231200Smm struct lzh_dec *ds; 146231200Smm}; 147231200Smm 148231200Smmstruct lha { 149231200Smm /* entry_bytes_remaining is the number of bytes we expect. */ 150231200Smm int64_t entry_offset; 151231200Smm int64_t entry_bytes_remaining; 152231200Smm int64_t entry_unconsumed; 153231200Smm uint16_t entry_crc_calculated; 154231200Smm 155231200Smm size_t header_size; /* header size */ 156231200Smm unsigned char level; /* header level */ 157231200Smm char method[3]; /* compress type */ 158231200Smm int64_t compsize; /* compressed data size */ 159231200Smm int64_t origsize; /* original file size */ 160231200Smm int setflag; 161231200Smm#define BIRTHTIME_IS_SET 1 162231200Smm#define ATIME_IS_SET 2 163231200Smm#define UNIX_MODE_IS_SET 4 164231200Smm#define CRC_IS_SET 8 165231200Smm time_t birthtime; 166231200Smm long birthtime_tv_nsec; 167231200Smm time_t mtime; 168231200Smm long mtime_tv_nsec; 169231200Smm time_t atime; 170231200Smm long atime_tv_nsec; 171231200Smm mode_t mode; 172231200Smm int64_t uid; 173231200Smm int64_t gid; 174231200Smm struct archive_string uname; 175231200Smm struct archive_string gname; 176231200Smm uint16_t header_crc; 177231200Smm uint16_t crc; 178231200Smm struct archive_string_conv *sconv; 179231200Smm struct archive_string_conv *opt_sconv; 180231200Smm 181231200Smm struct archive_string dirname; 182231200Smm struct archive_string filename; 183231200Smm struct archive_wstring ws; 184231200Smm 185231200Smm unsigned char dos_attr; 186231200Smm 187231200Smm /* Flag to mark progress that an archive was read their first header.*/ 188231200Smm char found_first_header; 189231200Smm /* Flag to mark that indicates an empty directory. */ 190231200Smm char directory; 191231200Smm 192231200Smm /* Flags to mark progress of decompression. */ 193231200Smm char decompress_init; 194231200Smm char end_of_entry; 195231200Smm char end_of_entry_cleanup; 196231200Smm char entry_is_compressed; 197231200Smm 198231200Smm char format_name[64]; 199231200Smm 200231200Smm struct lzh_stream strm; 201231200Smm}; 202231200Smm 203231200Smm/* 204231200Smm * LHA header common member offset. 205231200Smm */ 206231200Smm#define H_METHOD_OFFSET 2 /* Compress type. */ 207231200Smm#define H_ATTR_OFFSET 19 /* DOS attribute. */ 208231200Smm#define H_LEVEL_OFFSET 20 /* Header Level. */ 209231200Smm#define H_SIZE 22 /* Minimum header size. */ 210231200Smm 211231200Smmstatic int archive_read_format_lha_bid(struct archive_read *, int); 212231200Smmstatic int archive_read_format_lha_options(struct archive_read *, 213231200Smm const char *, const char *); 214231200Smmstatic int archive_read_format_lha_read_header(struct archive_read *, 215231200Smm struct archive_entry *); 216231200Smmstatic int archive_read_format_lha_read_data(struct archive_read *, 217231200Smm const void **, size_t *, int64_t *); 218231200Smmstatic int archive_read_format_lha_read_data_skip(struct archive_read *); 219231200Smmstatic int archive_read_format_lha_cleanup(struct archive_read *); 220231200Smm 221231200Smmstatic void lha_replace_path_separator(struct lha *, 222231200Smm struct archive_entry *); 223231200Smmstatic int lha_read_file_header_0(struct archive_read *, struct lha *); 224231200Smmstatic int lha_read_file_header_1(struct archive_read *, struct lha *); 225231200Smmstatic int lha_read_file_header_2(struct archive_read *, struct lha *); 226231200Smmstatic int lha_read_file_header_3(struct archive_read *, struct lha *); 227231200Smmstatic int lha_read_file_extended_header(struct archive_read *, 228231200Smm struct lha *, uint16_t *, int, size_t, size_t *); 229231200Smmstatic size_t lha_check_header_format(const void *); 230231200Smmstatic int lha_skip_sfx(struct archive_read *); 231231200Smmstatic time_t lha_dos_time(const unsigned char *); 232231200Smmstatic time_t lha_win_time(uint64_t, long *); 233231200Smmstatic unsigned char lha_calcsum(unsigned char, const void *, 234248616Smm int, size_t); 235231200Smmstatic int lha_parse_linkname(struct archive_string *, 236231200Smm struct archive_string *); 237231200Smmstatic int lha_read_data_none(struct archive_read *, const void **, 238231200Smm size_t *, int64_t *); 239231200Smmstatic int lha_read_data_lzh(struct archive_read *, const void **, 240231200Smm size_t *, int64_t *); 241299529Smmstatic void lha_crc16_init(void); 242231200Smmstatic uint16_t lha_crc16(uint16_t, const void *, size_t); 243231200Smmstatic int lzh_decode_init(struct lzh_stream *, const char *); 244231200Smmstatic void lzh_decode_free(struct lzh_stream *); 245231200Smmstatic int lzh_decode(struct lzh_stream *, int); 246231200Smmstatic int lzh_br_fillup(struct lzh_stream *, struct lzh_br *); 247231200Smmstatic int lzh_huffman_init(struct huffman *, size_t, int); 248231200Smmstatic void lzh_huffman_free(struct huffman *); 249231200Smmstatic int lzh_read_pt_bitlen(struct lzh_stream *, int start, int end); 250231200Smmstatic int lzh_make_fake_table(struct huffman *, uint16_t); 251231200Smmstatic int lzh_make_huffman_table(struct huffman *); 252232153Smmstatic inline int lzh_decode_huffman(struct huffman *, unsigned); 253231200Smmstatic int lzh_decode_huffman_tree(struct huffman *, unsigned, int); 254231200Smm 255231200Smm 256231200Smmint 257231200Smmarchive_read_support_format_lha(struct archive *_a) 258231200Smm{ 259231200Smm struct archive_read *a = (struct archive_read *)_a; 260231200Smm struct lha *lha; 261231200Smm int r; 262231200Smm 263231200Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 264231200Smm ARCHIVE_STATE_NEW, "archive_read_support_format_lha"); 265231200Smm 266231200Smm lha = (struct lha *)calloc(1, sizeof(*lha)); 267231200Smm if (lha == NULL) { 268231200Smm archive_set_error(&a->archive, ENOMEM, 269231200Smm "Can't allocate lha data"); 270231200Smm return (ARCHIVE_FATAL); 271231200Smm } 272231200Smm archive_string_init(&lha->ws); 273231200Smm 274231200Smm r = __archive_read_register_format(a, 275231200Smm lha, 276231200Smm "lha", 277231200Smm archive_read_format_lha_bid, 278231200Smm archive_read_format_lha_options, 279231200Smm archive_read_format_lha_read_header, 280231200Smm archive_read_format_lha_read_data, 281231200Smm archive_read_format_lha_read_data_skip, 282248616Smm NULL, 283299529Smm archive_read_format_lha_cleanup, 284299529Smm NULL, 285299529Smm NULL); 286231200Smm 287231200Smm if (r != ARCHIVE_OK) 288231200Smm free(lha); 289231200Smm return (ARCHIVE_OK); 290231200Smm} 291231200Smm 292231200Smmstatic size_t 293231200Smmlha_check_header_format(const void *h) 294231200Smm{ 295231200Smm const unsigned char *p = h; 296231200Smm size_t next_skip_bytes; 297231200Smm 298231200Smm switch (p[H_METHOD_OFFSET+3]) { 299231200Smm /* 300231200Smm * "-lh0-" ... "-lh7-" "-lhd-" 301231200Smm * "-lzs-" "-lz5-" 302231200Smm */ 303231200Smm case '0': case '1': case '2': case '3': 304231200Smm case '4': case '5': case '6': case '7': 305231200Smm case 'd': 306231200Smm case 's': 307231200Smm next_skip_bytes = 4; 308231200Smm 309231200Smm /* b0 == 0 means the end of an LHa archive file. */ 310231200Smm if (p[0] == 0) 311231200Smm break; 312231200Smm if (p[H_METHOD_OFFSET] != '-' || p[H_METHOD_OFFSET+1] != 'l' 313231200Smm || p[H_METHOD_OFFSET+4] != '-') 314231200Smm break; 315231200Smm 316231200Smm if (p[H_METHOD_OFFSET+2] == 'h') { 317231200Smm /* "-lh?-" */ 318231200Smm if (p[H_METHOD_OFFSET+3] == 's') 319231200Smm break; 320231200Smm if (p[H_LEVEL_OFFSET] == 0) 321231200Smm return (0); 322231200Smm if (p[H_LEVEL_OFFSET] <= 3 && p[H_ATTR_OFFSET] == 0x20) 323231200Smm return (0); 324231200Smm } 325231200Smm if (p[H_METHOD_OFFSET+2] == 'z') { 326231200Smm /* LArc extensions: -lzs-,-lz4- and -lz5- */ 327231200Smm if (p[H_LEVEL_OFFSET] != 0) 328231200Smm break; 329231200Smm if (p[H_METHOD_OFFSET+3] == 's' 330231200Smm || p[H_METHOD_OFFSET+3] == '4' 331231200Smm || p[H_METHOD_OFFSET+3] == '5') 332231200Smm return (0); 333231200Smm } 334231200Smm break; 335231200Smm case 'h': next_skip_bytes = 1; break; 336231200Smm case 'z': next_skip_bytes = 1; break; 337231200Smm case 'l': next_skip_bytes = 2; break; 338231200Smm case '-': next_skip_bytes = 3; break; 339231200Smm default : next_skip_bytes = 4; break; 340231200Smm } 341231200Smm 342231200Smm return (next_skip_bytes); 343231200Smm} 344231200Smm 345231200Smmstatic int 346231200Smmarchive_read_format_lha_bid(struct archive_read *a, int best_bid) 347231200Smm{ 348231200Smm const char *p; 349231200Smm const void *buff; 350231200Smm ssize_t bytes_avail, offset, window; 351231200Smm size_t next; 352231200Smm 353231200Smm /* If there's already a better bid than we can ever 354231200Smm make, don't bother testing. */ 355231200Smm if (best_bid > 30) 356231200Smm return (-1); 357231200Smm 358231200Smm if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) 359231200Smm return (-1); 360231200Smm 361231200Smm if (lha_check_header_format(p) == 0) 362231200Smm return (30); 363231200Smm 364231200Smm if (p[0] == 'M' && p[1] == 'Z') { 365231200Smm /* PE file */ 366231200Smm offset = 0; 367231200Smm window = 4096; 368231200Smm while (offset < (1024 * 20)) { 369231200Smm buff = __archive_read_ahead(a, offset + window, 370231200Smm &bytes_avail); 371231200Smm if (buff == NULL) { 372231200Smm /* Remaining bytes are less than window. */ 373231200Smm window >>= 1; 374231200Smm if (window < (H_SIZE + 3)) 375231200Smm return (0); 376231200Smm continue; 377231200Smm } 378231200Smm p = (const char *)buff + offset; 379231200Smm while (p + H_SIZE < (const char *)buff + bytes_avail) { 380231200Smm if ((next = lha_check_header_format(p)) == 0) 381231200Smm return (30); 382231200Smm p += next; 383231200Smm } 384231200Smm offset = p - (const char *)buff; 385231200Smm } 386231200Smm } 387231200Smm return (0); 388231200Smm} 389231200Smm 390231200Smmstatic int 391231200Smmarchive_read_format_lha_options(struct archive_read *a, 392231200Smm const char *key, const char *val) 393231200Smm{ 394231200Smm struct lha *lha; 395231200Smm int ret = ARCHIVE_FAILED; 396231200Smm 397231200Smm lha = (struct lha *)(a->format->data); 398231200Smm if (strcmp(key, "hdrcharset") == 0) { 399231200Smm if (val == NULL || val[0] == 0) 400231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 401231200Smm "lha: hdrcharset option needs a character-set name"); 402231200Smm else { 403231200Smm lha->opt_sconv = 404231200Smm archive_string_conversion_from_charset( 405231200Smm &a->archive, val, 0); 406231200Smm if (lha->opt_sconv != NULL) 407231200Smm ret = ARCHIVE_OK; 408231200Smm else 409231200Smm ret = ARCHIVE_FATAL; 410231200Smm } 411232153Smm return (ret); 412232153Smm } 413231200Smm 414232153Smm /* Note: The "warn" return is just to inform the options 415232153Smm * supervisor that we didn't handle it. It will generate 416232153Smm * a suitable error if no one used this option. */ 417232153Smm return (ARCHIVE_WARN); 418231200Smm} 419231200Smm 420231200Smmstatic int 421231200Smmlha_skip_sfx(struct archive_read *a) 422231200Smm{ 423231200Smm const void *h; 424231200Smm const char *p, *q; 425231200Smm size_t next, skip; 426231200Smm ssize_t bytes, window; 427231200Smm 428231200Smm window = 4096; 429231200Smm for (;;) { 430231200Smm h = __archive_read_ahead(a, window, &bytes); 431231200Smm if (h == NULL) { 432231200Smm /* Remaining bytes are less than window. */ 433231200Smm window >>= 1; 434231200Smm if (window < (H_SIZE + 3)) 435231200Smm goto fatal; 436231200Smm continue; 437231200Smm } 438231200Smm if (bytes < H_SIZE) 439231200Smm goto fatal; 440231200Smm p = h; 441231200Smm q = p + bytes; 442231200Smm 443231200Smm /* 444231200Smm * Scan ahead until we find something that looks 445231200Smm * like the lha header. 446231200Smm */ 447231200Smm while (p + H_SIZE < q) { 448231200Smm if ((next = lha_check_header_format(p)) == 0) { 449231200Smm skip = p - (const char *)h; 450231200Smm __archive_read_consume(a, skip); 451231200Smm return (ARCHIVE_OK); 452231200Smm } 453231200Smm p += next; 454231200Smm } 455231200Smm skip = p - (const char *)h; 456231200Smm __archive_read_consume(a, skip); 457231200Smm } 458231200Smmfatal: 459231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 460231200Smm "Couldn't find out LHa header"); 461231200Smm return (ARCHIVE_FATAL); 462231200Smm} 463231200Smm 464231200Smmstatic int 465231200Smmtruncated_error(struct archive_read *a) 466231200Smm{ 467231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 468231200Smm "Truncated LHa header"); 469231200Smm return (ARCHIVE_FATAL); 470231200Smm} 471231200Smm 472231200Smmstatic int 473231200Smmarchive_read_format_lha_read_header(struct archive_read *a, 474231200Smm struct archive_entry *entry) 475231200Smm{ 476231200Smm struct archive_string linkname; 477231200Smm struct archive_string pathname; 478231200Smm struct lha *lha; 479231200Smm const unsigned char *p; 480231200Smm const char *signature; 481231200Smm int err; 482231200Smm 483299529Smm lha_crc16_init(); 484299529Smm 485231200Smm a->archive.archive_format = ARCHIVE_FORMAT_LHA; 486231200Smm if (a->archive.archive_format_name == NULL) 487231200Smm a->archive.archive_format_name = "lha"; 488231200Smm 489231200Smm lha = (struct lha *)(a->format->data); 490231200Smm lha->decompress_init = 0; 491231200Smm lha->end_of_entry = 0; 492231200Smm lha->end_of_entry_cleanup = 0; 493231200Smm lha->entry_unconsumed = 0; 494231200Smm 495231200Smm if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) { 496231200Smm /* 497231200Smm * LHa archiver added 0 to the tail of its archive file as 498231200Smm * the mark of the end of the archive. 499231200Smm */ 500231200Smm signature = __archive_read_ahead(a, sizeof(signature[0]), NULL); 501231200Smm if (signature == NULL || signature[0] == 0) 502231200Smm return (ARCHIVE_EOF); 503231200Smm return (truncated_error(a)); 504231200Smm } 505231200Smm 506231200Smm signature = (const char *)p; 507231200Smm if (lha->found_first_header == 0 && 508231200Smm signature[0] == 'M' && signature[1] == 'Z') { 509231200Smm /* This is an executable? Must be self-extracting... */ 510231200Smm err = lha_skip_sfx(a); 511231200Smm if (err < ARCHIVE_WARN) 512231200Smm return (err); 513231200Smm 514231200Smm if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL) 515231200Smm return (truncated_error(a)); 516231200Smm signature = (const char *)p; 517231200Smm } 518231200Smm /* signature[0] == 0 means the end of an LHa archive file. */ 519231200Smm if (signature[0] == 0) 520231200Smm return (ARCHIVE_EOF); 521231200Smm 522231200Smm /* 523231200Smm * Check the header format and method type. 524231200Smm */ 525231200Smm if (lha_check_header_format(p) != 0) { 526231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 527231200Smm "Bad LHa file"); 528231200Smm return (ARCHIVE_FATAL); 529231200Smm } 530231200Smm 531231200Smm /* We've found the first header. */ 532231200Smm lha->found_first_header = 1; 533231200Smm /* Set a default value and common data */ 534231200Smm lha->header_size = 0; 535231200Smm lha->level = p[H_LEVEL_OFFSET]; 536231200Smm lha->method[0] = p[H_METHOD_OFFSET+1]; 537231200Smm lha->method[1] = p[H_METHOD_OFFSET+2]; 538231200Smm lha->method[2] = p[H_METHOD_OFFSET+3]; 539231200Smm if (memcmp(lha->method, "lhd", 3) == 0) 540231200Smm lha->directory = 1; 541231200Smm else 542231200Smm lha->directory = 0; 543231200Smm if (memcmp(lha->method, "lh0", 3) == 0 || 544231200Smm memcmp(lha->method, "lz4", 3) == 0) 545231200Smm lha->entry_is_compressed = 0; 546231200Smm else 547231200Smm lha->entry_is_compressed = 1; 548231200Smm 549231200Smm lha->compsize = 0; 550231200Smm lha->origsize = 0; 551231200Smm lha->setflag = 0; 552231200Smm lha->birthtime = 0; 553231200Smm lha->birthtime_tv_nsec = 0; 554231200Smm lha->mtime = 0; 555231200Smm lha->mtime_tv_nsec = 0; 556231200Smm lha->atime = 0; 557231200Smm lha->atime_tv_nsec = 0; 558231200Smm lha->mode = (lha->directory)? 0777 : 0666; 559231200Smm lha->uid = 0; 560231200Smm lha->gid = 0; 561231200Smm archive_string_empty(&lha->dirname); 562231200Smm archive_string_empty(&lha->filename); 563231200Smm lha->dos_attr = 0; 564231200Smm if (lha->opt_sconv != NULL) 565231200Smm lha->sconv = lha->opt_sconv; 566231200Smm else 567231200Smm lha->sconv = NULL; 568231200Smm 569231200Smm switch (p[H_LEVEL_OFFSET]) { 570231200Smm case 0: 571231200Smm err = lha_read_file_header_0(a, lha); 572231200Smm break; 573231200Smm case 1: 574231200Smm err = lha_read_file_header_1(a, lha); 575231200Smm break; 576231200Smm case 2: 577231200Smm err = lha_read_file_header_2(a, lha); 578231200Smm break; 579231200Smm case 3: 580231200Smm err = lha_read_file_header_3(a, lha); 581231200Smm break; 582231200Smm default: 583231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 584231200Smm "Unsupported LHa header level %d", p[H_LEVEL_OFFSET]); 585231200Smm err = ARCHIVE_FATAL; 586231200Smm break; 587231200Smm } 588231200Smm if (err < ARCHIVE_WARN) 589231200Smm return (err); 590231200Smm 591231200Smm 592231200Smm if (!lha->directory && archive_strlen(&lha->filename) == 0) 593231200Smm /* The filename has not been set */ 594231200Smm return (truncated_error(a)); 595231200Smm 596231200Smm /* 597231200Smm * Make a pathname from a dirname and a filename. 598231200Smm */ 599231200Smm archive_string_concat(&lha->dirname, &lha->filename); 600231200Smm archive_string_init(&pathname); 601231200Smm archive_string_init(&linkname); 602231200Smm archive_string_copy(&pathname, &lha->dirname); 603231200Smm 604231200Smm if ((lha->mode & AE_IFMT) == AE_IFLNK) { 605231200Smm /* 606231200Smm * Extract the symlink-name if it's included in the pathname. 607231200Smm */ 608231200Smm if (!lha_parse_linkname(&linkname, &pathname)) { 609231200Smm /* We couldn't get the symlink-name. */ 610231200Smm archive_set_error(&a->archive, 611231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 612231200Smm "Unknown symlink-name"); 613231200Smm archive_string_free(&pathname); 614231200Smm archive_string_free(&linkname); 615231200Smm return (ARCHIVE_FAILED); 616231200Smm } 617231200Smm } else { 618231200Smm /* 619231200Smm * Make sure a file-type is set. 620231200Smm * The mode has been overridden if it is in the extended data. 621231200Smm */ 622231200Smm lha->mode = (lha->mode & ~AE_IFMT) | 623231200Smm ((lha->directory)? AE_IFDIR: AE_IFREG); 624231200Smm } 625231200Smm if ((lha->setflag & UNIX_MODE_IS_SET) == 0 && 626231200Smm (lha->dos_attr & 1) != 0) 627231200Smm lha->mode &= ~(0222);/* read only. */ 628231200Smm 629231200Smm /* 630231200Smm * Set basic file parameters. 631231200Smm */ 632231200Smm if (archive_entry_copy_pathname_l(entry, pathname.s, 633231200Smm pathname.length, lha->sconv) != 0) { 634231200Smm if (errno == ENOMEM) { 635231200Smm archive_set_error(&a->archive, ENOMEM, 636231200Smm "Can't allocate memory for Pathname"); 637231200Smm return (ARCHIVE_FATAL); 638231200Smm } 639231200Smm archive_set_error(&a->archive, 640231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 641231200Smm "Pathname cannot be converted " 642231200Smm "from %s to current locale.", 643231200Smm archive_string_conversion_charset_name(lha->sconv)); 644231200Smm err = ARCHIVE_WARN; 645231200Smm } 646231200Smm archive_string_free(&pathname); 647231200Smm if (archive_strlen(&linkname) > 0) { 648231200Smm if (archive_entry_copy_symlink_l(entry, linkname.s, 649231200Smm linkname.length, lha->sconv) != 0) { 650231200Smm if (errno == ENOMEM) { 651231200Smm archive_set_error(&a->archive, ENOMEM, 652231200Smm "Can't allocate memory for Linkname"); 653231200Smm return (ARCHIVE_FATAL); 654231200Smm } 655231200Smm archive_set_error(&a->archive, 656231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 657231200Smm "Linkname cannot be converted " 658231200Smm "from %s to current locale.", 659231200Smm archive_string_conversion_charset_name(lha->sconv)); 660231200Smm err = ARCHIVE_WARN; 661231200Smm } 662231200Smm } else 663231200Smm archive_entry_set_symlink(entry, NULL); 664231200Smm archive_string_free(&linkname); 665231200Smm /* 666231200Smm * When a header level is 0, there is a possibility that 667231200Smm * a pathname and a symlink has '\' character, a directory 668231200Smm * separator in DOS/Windows. So we should convert it to '/'. 669231200Smm */ 670231200Smm if (p[H_LEVEL_OFFSET] == 0) 671231200Smm lha_replace_path_separator(lha, entry); 672231200Smm 673231200Smm archive_entry_set_mode(entry, lha->mode); 674231200Smm archive_entry_set_uid(entry, lha->uid); 675231200Smm archive_entry_set_gid(entry, lha->gid); 676231200Smm if (archive_strlen(&lha->uname) > 0) 677231200Smm archive_entry_set_uname(entry, lha->uname.s); 678231200Smm if (archive_strlen(&lha->gname) > 0) 679231200Smm archive_entry_set_gname(entry, lha->gname.s); 680231200Smm if (lha->setflag & BIRTHTIME_IS_SET) { 681231200Smm archive_entry_set_birthtime(entry, lha->birthtime, 682231200Smm lha->birthtime_tv_nsec); 683231200Smm archive_entry_set_ctime(entry, lha->birthtime, 684231200Smm lha->birthtime_tv_nsec); 685231200Smm } else { 686231200Smm archive_entry_unset_birthtime(entry); 687231200Smm archive_entry_unset_ctime(entry); 688231200Smm } 689231200Smm archive_entry_set_mtime(entry, lha->mtime, lha->mtime_tv_nsec); 690231200Smm if (lha->setflag & ATIME_IS_SET) 691231200Smm archive_entry_set_atime(entry, lha->atime, 692231200Smm lha->atime_tv_nsec); 693231200Smm else 694231200Smm archive_entry_unset_atime(entry); 695231200Smm if (lha->directory || archive_entry_symlink(entry) != NULL) 696231200Smm archive_entry_unset_size(entry); 697231200Smm else 698231200Smm archive_entry_set_size(entry, lha->origsize); 699231200Smm 700231200Smm /* 701231200Smm * Prepare variables used to read a file content. 702231200Smm */ 703231200Smm lha->entry_bytes_remaining = lha->compsize; 704231200Smm lha->entry_offset = 0; 705231200Smm lha->entry_crc_calculated = 0; 706231200Smm 707231200Smm /* 708231200Smm * This file does not have a content. 709231200Smm */ 710231200Smm if (lha->directory || lha->compsize == 0) 711231200Smm lha->end_of_entry = 1; 712231200Smm 713231200Smm sprintf(lha->format_name, "lha -%c%c%c-", 714231200Smm lha->method[0], lha->method[1], lha->method[2]); 715231200Smm a->archive.archive_format_name = lha->format_name; 716231200Smm 717231200Smm return (err); 718231200Smm} 719231200Smm 720231200Smm/* 721231200Smm * Replace a DOS path separator '\' by a character '/'. 722231200Smm * Some multi-byte character set have a character '\' in its second byte. 723231200Smm */ 724231200Smmstatic void 725231200Smmlha_replace_path_separator(struct lha *lha, struct archive_entry *entry) 726231200Smm{ 727231200Smm const wchar_t *wp; 728231200Smm size_t i; 729231200Smm 730231200Smm if ((wp = archive_entry_pathname_w(entry)) != NULL) { 731231200Smm archive_wstrcpy(&(lha->ws), wp); 732231200Smm for (i = 0; i < archive_strlen(&(lha->ws)); i++) { 733231200Smm if (lha->ws.s[i] == L'\\') 734231200Smm lha->ws.s[i] = L'/'; 735231200Smm } 736231200Smm archive_entry_copy_pathname_w(entry, lha->ws.s); 737231200Smm } 738231200Smm 739231200Smm if ((wp = archive_entry_symlink_w(entry)) != NULL) { 740231200Smm archive_wstrcpy(&(lha->ws), wp); 741231200Smm for (i = 0; i < archive_strlen(&(lha->ws)); i++) { 742231200Smm if (lha->ws.s[i] == L'\\') 743231200Smm lha->ws.s[i] = L'/'; 744231200Smm } 745231200Smm archive_entry_copy_symlink_w(entry, lha->ws.s); 746231200Smm } 747231200Smm} 748231200Smm 749231200Smm/* 750231200Smm * Header 0 format 751231200Smm * 752231200Smm * +0 +1 +2 +7 +11 753231200Smm * +---------------+----------+----------------+-------------------+ 754231200Smm * |header size(*1)|header sum|compression type|compressed size(*2)| 755231200Smm * +---------------+----------+----------------+-------------------+ 756231200Smm * <---------------------(*1)----------* 757231200Smm * 758231200Smm * +11 +15 +17 +19 +20 +21 759231200Smm * +-----------------+---------+---------+--------------+----------------+ 760231200Smm * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=0)| 761231200Smm * +-----------------+---------+---------+--------------+----------------+ 762231200Smm * *--------------------------------(*1)---------------------------------* 763231200Smm * 764231200Smm * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+2+(*4) 765231200Smm * +---------------+---------+----------+----------------+------------------+ 766231200Smm * |name length(*3)|file name|file CRC16|extra header(*4)| compressed data | 767231200Smm * +---------------+---------+----------+----------------+------------------+ 768231200Smm * <--(*3)-> <------(*2)------> 769231200Smm * *----------------------(*1)--------------------------> 770231200Smm * 771231200Smm */ 772231200Smm#define H0_HEADER_SIZE_OFFSET 0 773231200Smm#define H0_HEADER_SUM_OFFSET 1 774231200Smm#define H0_COMP_SIZE_OFFSET 7 775231200Smm#define H0_ORIG_SIZE_OFFSET 11 776231200Smm#define H0_DOS_TIME_OFFSET 15 777231200Smm#define H0_NAME_LEN_OFFSET 21 778231200Smm#define H0_FILE_NAME_OFFSET 22 779231200Smm#define H0_FIXED_SIZE 24 780231200Smmstatic int 781231200Smmlha_read_file_header_0(struct archive_read *a, struct lha *lha) 782231200Smm{ 783231200Smm const unsigned char *p; 784231200Smm int extdsize, namelen; 785231200Smm unsigned char headersum, sum_calculated; 786231200Smm 787231200Smm if ((p = __archive_read_ahead(a, H0_FIXED_SIZE, NULL)) == NULL) 788231200Smm return (truncated_error(a)); 789231200Smm lha->header_size = p[H0_HEADER_SIZE_OFFSET] + 2; 790231200Smm headersum = p[H0_HEADER_SUM_OFFSET]; 791231200Smm lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET); 792231200Smm lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET); 793231200Smm lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET); 794231200Smm namelen = p[H0_NAME_LEN_OFFSET]; 795231200Smm extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen; 796231200Smm if ((namelen > 221 || extdsize < 0) && extdsize != -2) { 797231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 798231200Smm "Invalid LHa header"); 799231200Smm return (ARCHIVE_FATAL); 800231200Smm } 801231200Smm if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) 802231200Smm return (truncated_error(a)); 803231200Smm 804231200Smm archive_strncpy(&lha->filename, p + H0_FILE_NAME_OFFSET, namelen); 805231200Smm /* When extdsize == -2, A CRC16 value is not present in the header. */ 806231200Smm if (extdsize >= 0) { 807231200Smm lha->crc = archive_le16dec(p + H0_FILE_NAME_OFFSET + namelen); 808231200Smm lha->setflag |= CRC_IS_SET; 809231200Smm } 810231200Smm sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); 811231200Smm 812231200Smm /* Read an extended header */ 813231200Smm if (extdsize > 0) { 814231200Smm /* This extended data is set by 'LHa for UNIX' only. 815231200Smm * Maybe fixed size. 816231200Smm */ 817231200Smm p += H0_FILE_NAME_OFFSET + namelen + 2; 818231200Smm if (p[0] == 'U' && extdsize == 12) { 819231200Smm /* p[1] is a minor version. */ 820231200Smm lha->mtime = archive_le32dec(&p[2]); 821231200Smm lha->mode = archive_le16dec(&p[6]); 822231200Smm lha->uid = archive_le16dec(&p[8]); 823231200Smm lha->gid = archive_le16dec(&p[10]); 824231200Smm lha->setflag |= UNIX_MODE_IS_SET; 825231200Smm } 826231200Smm } 827231200Smm __archive_read_consume(a, lha->header_size); 828231200Smm 829231200Smm if (sum_calculated != headersum) { 830231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 831231200Smm "LHa header sum error"); 832231200Smm return (ARCHIVE_FATAL); 833231200Smm } 834231200Smm 835231200Smm return (ARCHIVE_OK); 836231200Smm} 837231200Smm 838231200Smm/* 839231200Smm * Header 1 format 840231200Smm * 841231200Smm * +0 +1 +2 +7 +11 842231200Smm * +---------------+----------+----------------+-------------+ 843231200Smm * |header size(*1)|header sum|compression type|skip size(*2)| 844231200Smm * +---------------+----------+----------------+-------------+ 845231200Smm * <---------------(*1)----------* 846231200Smm * 847231200Smm * +11 +15 +17 +19 +20 +21 848231200Smm * +-----------------+---------+---------+--------------+----------------+ 849231200Smm * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=1)| 850231200Smm * +-----------------+---------+---------+--------------+----------------+ 851231200Smm * *-------------------------------(*1)----------------------------------* 852231200Smm * 853231200Smm * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+3 +22+(*3)+3+(*4) 854231200Smm * +---------------+---------+----------+-----------+-----------+ 855231200Smm * |name length(*3)|file name|file CRC16| creator |padding(*4)| 856231200Smm * +---------------+---------+----------+-----------+-----------+ 857231200Smm * <--(*3)-> 858231200Smm * *----------------------------(*1)----------------------------* 859231200Smm * 860231200Smm * +22+(*3)+3+(*4) +22+(*3)+3+(*4)+2 +22+(*3)+3+(*4)+2+(*5) 861231200Smm * +----------------+---------------------+------------------------+ 862231200Smm * |next header size| extended header(*5) | compressed data | 863231200Smm * +----------------+---------------------+------------------------+ 864231200Smm * *------(*1)-----> <--------------------(*2)--------------------> 865231200Smm */ 866231200Smm#define H1_HEADER_SIZE_OFFSET 0 867231200Smm#define H1_HEADER_SUM_OFFSET 1 868231200Smm#define H1_COMP_SIZE_OFFSET 7 869231200Smm#define H1_ORIG_SIZE_OFFSET 11 870231200Smm#define H1_DOS_TIME_OFFSET 15 871231200Smm#define H1_NAME_LEN_OFFSET 21 872231200Smm#define H1_FILE_NAME_OFFSET 22 873231200Smm#define H1_FIXED_SIZE 27 874231200Smmstatic int 875231200Smmlha_read_file_header_1(struct archive_read *a, struct lha *lha) 876231200Smm{ 877231200Smm const unsigned char *p; 878231200Smm size_t extdsize; 879231200Smm int i, err, err2; 880231200Smm int namelen, padding; 881231200Smm unsigned char headersum, sum_calculated; 882231200Smm 883231200Smm err = ARCHIVE_OK; 884231200Smm 885231200Smm if ((p = __archive_read_ahead(a, H1_FIXED_SIZE, NULL)) == NULL) 886231200Smm return (truncated_error(a)); 887231200Smm 888231200Smm lha->header_size = p[H1_HEADER_SIZE_OFFSET] + 2; 889231200Smm headersum = p[H1_HEADER_SUM_OFFSET]; 890231200Smm /* Note: An extended header size is included in a compsize. */ 891231200Smm lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET); 892231200Smm lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET); 893231200Smm lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET); 894231200Smm namelen = p[H1_NAME_LEN_OFFSET]; 895231200Smm /* Calculate a padding size. The result will be normally 0 only(?) */ 896231200Smm padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen; 897231200Smm 898231200Smm if (namelen > 230 || padding < 0) 899231200Smm goto invalid; 900231200Smm 901231200Smm if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) 902231200Smm return (truncated_error(a)); 903231200Smm 904231200Smm for (i = 0; i < namelen; i++) { 905231200Smm if (p[i + H1_FILE_NAME_OFFSET] == 0xff) 906231200Smm goto invalid;/* Invalid filename. */ 907231200Smm } 908231200Smm archive_strncpy(&lha->filename, p + H1_FILE_NAME_OFFSET, namelen); 909231200Smm lha->crc = archive_le16dec(p + H1_FILE_NAME_OFFSET + namelen); 910231200Smm lha->setflag |= CRC_IS_SET; 911231200Smm 912231200Smm sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); 913231200Smm /* Consume used bytes but not include `next header size' data 914231200Smm * since it will be consumed in lha_read_file_extended_header(). */ 915231200Smm __archive_read_consume(a, lha->header_size - 2); 916231200Smm 917231200Smm /* Read extended headers */ 918231200Smm err2 = lha_read_file_extended_header(a, lha, NULL, 2, 919238856Smm (size_t)(lha->compsize + 2), &extdsize); 920231200Smm if (err2 < ARCHIVE_WARN) 921231200Smm return (err2); 922231200Smm if (err2 < err) 923231200Smm err = err2; 924231200Smm /* Get a real compressed file size. */ 925231200Smm lha->compsize -= extdsize - 2; 926231200Smm 927231200Smm if (sum_calculated != headersum) { 928231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 929231200Smm "LHa header sum error"); 930231200Smm return (ARCHIVE_FATAL); 931231200Smm } 932231200Smm return (err); 933231200Smminvalid: 934231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 935231200Smm "Invalid LHa header"); 936231200Smm return (ARCHIVE_FATAL); 937231200Smm} 938231200Smm 939231200Smm/* 940231200Smm * Header 2 format 941231200Smm * 942231200Smm * +0 +2 +7 +11 +15 943231200Smm * +---------------+----------------+-------------------+-----------------+ 944231200Smm * |header size(*1)|compression type|compressed size(*2)|uncompressed size| 945231200Smm * +---------------+----------------+-------------------+-----------------+ 946231200Smm * <--------------------------------(*1)---------------------------------* 947231200Smm * 948231200Smm * +15 +19 +20 +21 +23 +24 949231200Smm * +-----------------+------------+----------------+----------+-----------+ 950231200Smm * |data/time(time_t)| 0x20 fixed |header level(=2)|file CRC16| creator | 951231200Smm * +-----------------+------------+----------------+----------+-----------+ 952231200Smm * *---------------------------------(*1)---------------------------------* 953231200Smm * 954231200Smm * +24 +26 +26+(*3) +26+(*3)+(*4) 955231200Smm * +----------------+-------------------+-------------+-------------------+ 956231200Smm * |next header size|extended header(*3)| padding(*4) | compressed data | 957231200Smm * +----------------+-------------------+-------------+-------------------+ 958231200Smm * *--------------------------(*1)-------------------> <------(*2)-------> 959231200Smm * 960231200Smm */ 961231200Smm#define H2_HEADER_SIZE_OFFSET 0 962231200Smm#define H2_COMP_SIZE_OFFSET 7 963231200Smm#define H2_ORIG_SIZE_OFFSET 11 964231200Smm#define H2_TIME_OFFSET 15 965231200Smm#define H2_CRC_OFFSET 21 966231200Smm#define H2_FIXED_SIZE 24 967231200Smmstatic int 968231200Smmlha_read_file_header_2(struct archive_read *a, struct lha *lha) 969231200Smm{ 970231200Smm const unsigned char *p; 971231200Smm size_t extdsize; 972231200Smm int err, padding; 973231200Smm uint16_t header_crc; 974231200Smm 975231200Smm if ((p = __archive_read_ahead(a, H2_FIXED_SIZE, NULL)) == NULL) 976231200Smm return (truncated_error(a)); 977231200Smm 978231200Smm lha->header_size =archive_le16dec(p + H2_HEADER_SIZE_OFFSET); 979231200Smm lha->compsize = archive_le32dec(p + H2_COMP_SIZE_OFFSET); 980231200Smm lha->origsize = archive_le32dec(p + H2_ORIG_SIZE_OFFSET); 981231200Smm lha->mtime = archive_le32dec(p + H2_TIME_OFFSET); 982231200Smm lha->crc = archive_le16dec(p + H2_CRC_OFFSET); 983231200Smm lha->setflag |= CRC_IS_SET; 984231200Smm 985231200Smm if (lha->header_size < H2_FIXED_SIZE) { 986231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 987231200Smm "Invalid LHa header size"); 988231200Smm return (ARCHIVE_FATAL); 989231200Smm } 990231200Smm 991231200Smm header_crc = lha_crc16(0, p, H2_FIXED_SIZE); 992231200Smm __archive_read_consume(a, H2_FIXED_SIZE); 993231200Smm 994231200Smm /* Read extended headers */ 995231200Smm err = lha_read_file_extended_header(a, lha, &header_crc, 2, 996231200Smm lha->header_size - H2_FIXED_SIZE, &extdsize); 997231200Smm if (err < ARCHIVE_WARN) 998231200Smm return (err); 999231200Smm 1000231200Smm /* Calculate a padding size. The result will be normally 0 or 1. */ 1001231200Smm padding = (int)lha->header_size - (int)(H2_FIXED_SIZE + extdsize); 1002231200Smm if (padding > 0) { 1003231200Smm if ((p = __archive_read_ahead(a, padding, NULL)) == NULL) 1004231200Smm return (truncated_error(a)); 1005231200Smm header_crc = lha_crc16(header_crc, p, padding); 1006231200Smm __archive_read_consume(a, padding); 1007231200Smm } 1008231200Smm 1009231200Smm if (header_crc != lha->header_crc) { 1010231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1011231200Smm "LHa header CRC error"); 1012231200Smm return (ARCHIVE_FATAL); 1013231200Smm } 1014231200Smm return (err); 1015231200Smm} 1016231200Smm 1017231200Smm/* 1018231200Smm * Header 3 format 1019231200Smm * 1020231200Smm * +0 +2 +7 +11 +15 1021231200Smm * +------------+----------------+-------------------+-----------------+ 1022231200Smm * | 0x04 fixed |compression type|compressed size(*2)|uncompressed size| 1023231200Smm * +------------+----------------+-------------------+-----------------+ 1024231200Smm * <-------------------------------(*1)-------------------------------* 1025231200Smm * 1026231200Smm * +15 +19 +20 +21 +23 +24 1027231200Smm * +-----------------+------------+----------------+----------+-----------+ 1028231200Smm * |date/time(time_t)| 0x20 fixed |header level(=3)|file CRC16| creator | 1029231200Smm * +-----------------+------------+----------------+----------+-----------+ 1030231200Smm * *--------------------------------(*1)----------------------------------* 1031231200Smm * 1032231200Smm * +24 +28 +32 +32+(*3) 1033231200Smm * +---------------+----------------+-------------------+-----------------+ 1034231200Smm * |header size(*1)|next header size|extended header(*3)| compressed data | 1035231200Smm * +---------------+----------------+-------------------+-----------------+ 1036231200Smm * *------------------------(*1)-----------------------> <------(*2)-----> 1037231200Smm * 1038231200Smm */ 1039231200Smm#define H3_FIELD_LEN_OFFSET 0 1040231200Smm#define H3_COMP_SIZE_OFFSET 7 1041231200Smm#define H3_ORIG_SIZE_OFFSET 11 1042231200Smm#define H3_TIME_OFFSET 15 1043231200Smm#define H3_CRC_OFFSET 21 1044231200Smm#define H3_HEADER_SIZE_OFFSET 24 1045231200Smm#define H3_FIXED_SIZE 28 1046231200Smmstatic int 1047231200Smmlha_read_file_header_3(struct archive_read *a, struct lha *lha) 1048231200Smm{ 1049231200Smm const unsigned char *p; 1050231200Smm size_t extdsize; 1051231200Smm int err; 1052231200Smm uint16_t header_crc; 1053231200Smm 1054231200Smm if ((p = __archive_read_ahead(a, H3_FIXED_SIZE, NULL)) == NULL) 1055231200Smm return (truncated_error(a)); 1056231200Smm 1057231200Smm if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4) 1058231200Smm goto invalid; 1059231200Smm lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET); 1060231200Smm lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET); 1061231200Smm lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET); 1062231200Smm lha->mtime = archive_le32dec(p + H3_TIME_OFFSET); 1063231200Smm lha->crc = archive_le16dec(p + H3_CRC_OFFSET); 1064231200Smm lha->setflag |= CRC_IS_SET; 1065231200Smm 1066231200Smm if (lha->header_size < H3_FIXED_SIZE + 4) 1067231200Smm goto invalid; 1068231200Smm header_crc = lha_crc16(0, p, H3_FIXED_SIZE); 1069231200Smm __archive_read_consume(a, H3_FIXED_SIZE); 1070231200Smm 1071231200Smm /* Read extended headers */ 1072231200Smm err = lha_read_file_extended_header(a, lha, &header_crc, 4, 1073231200Smm lha->header_size - H3_FIXED_SIZE, &extdsize); 1074231200Smm if (err < ARCHIVE_WARN) 1075231200Smm return (err); 1076231200Smm 1077231200Smm if (header_crc != lha->header_crc) { 1078231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1079231200Smm "LHa header CRC error"); 1080231200Smm return (ARCHIVE_FATAL); 1081231200Smm } 1082231200Smm return (err); 1083231200Smminvalid: 1084231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1085231200Smm "Invalid LHa header"); 1086231200Smm return (ARCHIVE_FATAL); 1087231200Smm} 1088231200Smm 1089231200Smm/* 1090231200Smm * Extended header format 1091231200Smm * 1092231200Smm * +0 +2 +3 -- used in header 1 and 2 1093231200Smm * +0 +4 +5 -- used in header 3 1094231200Smm * +--------------+---------+-------------------+--------------+-- 1095231200Smm * |ex-header size|header id| data |ex-header size| ....... 1096231200Smm * +--------------+---------+-------------------+--------------+-- 1097231200Smm * <-------------( ex-header size)------------> <-- next extended header --* 1098231200Smm * 1099231200Smm * If the ex-header size is zero, it is the make of the end of extended 1100231200Smm * headers. 1101231200Smm * 1102231200Smm */ 1103231200Smmstatic int 1104231200Smmlha_read_file_extended_header(struct archive_read *a, struct lha *lha, 1105231200Smm uint16_t *crc, int sizefield_length, size_t limitsize, size_t *total_size) 1106231200Smm{ 1107231200Smm const void *h; 1108231200Smm const unsigned char *extdheader; 1109231200Smm size_t extdsize; 1110231200Smm size_t datasize; 1111231200Smm unsigned int i; 1112231200Smm unsigned char extdtype; 1113231200Smm 1114231200Smm#define EXT_HEADER_CRC 0x00 /* Header CRC and information*/ 1115231200Smm#define EXT_FILENAME 0x01 /* Filename */ 1116231200Smm#define EXT_DIRECTORY 0x02 /* Directory name */ 1117231200Smm#define EXT_DOS_ATTR 0x40 /* MS-DOS attribute */ 1118231200Smm#define EXT_TIMESTAMP 0x41 /* Windows time stamp */ 1119231200Smm#define EXT_FILESIZE 0x42 /* Large file size */ 1120231200Smm#define EXT_TIMEZONE 0x43 /* Time zone */ 1121231200Smm#define EXT_UTF16_FILENAME 0x44 /* UTF-16 filename */ 1122231200Smm#define EXT_UTF16_DIRECTORY 0x45 /* UTF-16 directory name */ 1123231200Smm#define EXT_CODEPAGE 0x46 /* Codepage */ 1124231200Smm#define EXT_UNIX_MODE 0x50 /* File permission */ 1125231200Smm#define EXT_UNIX_GID_UID 0x51 /* gid,uid */ 1126231200Smm#define EXT_UNIX_GNAME 0x52 /* Group name */ 1127231200Smm#define EXT_UNIX_UNAME 0x53 /* User name */ 1128231200Smm#define EXT_UNIX_MTIME 0x54 /* Modified time */ 1129231200Smm#define EXT_OS2_NEW_ATTR 0x7f /* new attribute(OS/2 only) */ 1130231200Smm#define EXT_NEW_ATTR 0xff /* new attribute */ 1131231200Smm 1132231200Smm *total_size = sizefield_length; 1133231200Smm 1134231200Smm for (;;) { 1135231200Smm /* Read an extended header size. */ 1136231200Smm if ((h = 1137231200Smm __archive_read_ahead(a, sizefield_length, NULL)) == NULL) 1138231200Smm return (truncated_error(a)); 1139231200Smm /* Check if the size is the zero indicates the end of the 1140231200Smm * extended header. */ 1141231200Smm if (sizefield_length == sizeof(uint16_t)) 1142231200Smm extdsize = archive_le16dec(h); 1143231200Smm else 1144231200Smm extdsize = archive_le32dec(h); 1145231200Smm if (extdsize == 0) { 1146231200Smm /* End of extended header */ 1147231200Smm if (crc != NULL) 1148231200Smm *crc = lha_crc16(*crc, h, sizefield_length); 1149231200Smm __archive_read_consume(a, sizefield_length); 1150231200Smm return (ARCHIVE_OK); 1151231200Smm } 1152231200Smm 1153231200Smm /* Sanity check to the extended header size. */ 1154231200Smm if (((uint64_t)*total_size + extdsize) > 1155231200Smm (uint64_t)limitsize || 1156231200Smm extdsize <= (size_t)sizefield_length) 1157231200Smm goto invalid; 1158231200Smm 1159231200Smm /* Read the extended header. */ 1160231200Smm if ((h = __archive_read_ahead(a, extdsize, NULL)) == NULL) 1161231200Smm return (truncated_error(a)); 1162231200Smm *total_size += extdsize; 1163231200Smm 1164231200Smm extdheader = (const unsigned char *)h; 1165231200Smm /* Get the extended header type. */ 1166231200Smm extdtype = extdheader[sizefield_length]; 1167231200Smm /* Calculate an extended data size. */ 1168231200Smm datasize = extdsize - (1 + sizefield_length); 1169231200Smm /* Skip an extended header size field and type field. */ 1170231200Smm extdheader += sizefield_length + 1; 1171231200Smm 1172231200Smm if (crc != NULL && extdtype != EXT_HEADER_CRC) 1173231200Smm *crc = lha_crc16(*crc, h, extdsize); 1174231200Smm switch (extdtype) { 1175231200Smm case EXT_HEADER_CRC: 1176231200Smm /* We only use a header CRC. Following data will not 1177231200Smm * be used. */ 1178231200Smm if (datasize >= 2) { 1179231200Smm lha->header_crc = archive_le16dec(extdheader); 1180231200Smm if (crc != NULL) { 1181231200Smm static const char zeros[2] = {0, 0}; 1182231200Smm *crc = lha_crc16(*crc, h, 1183231200Smm extdsize - datasize); 1184231200Smm /* CRC value itself as zero */ 1185231200Smm *crc = lha_crc16(*crc, zeros, 2); 1186231200Smm *crc = lha_crc16(*crc, 1187231200Smm extdheader+2, datasize - 2); 1188231200Smm } 1189231200Smm } 1190231200Smm break; 1191231200Smm case EXT_FILENAME: 1192231200Smm if (datasize == 0) { 1193231200Smm /* maybe directory header */ 1194231200Smm archive_string_empty(&lha->filename); 1195231200Smm break; 1196231200Smm } 1197299529Smm if (extdheader[0] == '\0') 1198299529Smm goto invalid; 1199231200Smm archive_strncpy(&lha->filename, 1200231200Smm (const char *)extdheader, datasize); 1201231200Smm break; 1202231200Smm case EXT_DIRECTORY: 1203299529Smm if (datasize == 0 || extdheader[0] == '\0') 1204231200Smm /* no directory name data. exit this case. */ 1205299529Smm goto invalid; 1206231200Smm 1207231200Smm archive_strncpy(&lha->dirname, 1208231200Smm (const char *)extdheader, datasize); 1209231200Smm /* 1210231200Smm * Convert directory delimiter from 0xFF 1211231200Smm * to '/' for local system. 1212231200Smm */ 1213231200Smm for (i = 0; i < lha->dirname.length; i++) { 1214231200Smm if ((unsigned char)lha->dirname.s[i] == 0xFF) 1215231200Smm lha->dirname.s[i] = '/'; 1216231200Smm } 1217231200Smm /* Is last character directory separator? */ 1218231200Smm if (lha->dirname.s[lha->dirname.length-1] != '/') 1219231200Smm /* invalid directory data */ 1220231200Smm goto invalid; 1221231200Smm break; 1222231200Smm case EXT_DOS_ATTR: 1223231200Smm if (datasize == 2) 1224231200Smm lha->dos_attr = (unsigned char) 1225231200Smm (archive_le16dec(extdheader) & 0xff); 1226231200Smm break; 1227231200Smm case EXT_TIMESTAMP: 1228231200Smm if (datasize == (sizeof(uint64_t) * 3)) { 1229231200Smm lha->birthtime = lha_win_time( 1230231200Smm archive_le64dec(extdheader), 1231231200Smm &lha->birthtime_tv_nsec); 1232231200Smm extdheader += sizeof(uint64_t); 1233231200Smm lha->mtime = lha_win_time( 1234231200Smm archive_le64dec(extdheader), 1235231200Smm &lha->mtime_tv_nsec); 1236231200Smm extdheader += sizeof(uint64_t); 1237231200Smm lha->atime = lha_win_time( 1238231200Smm archive_le64dec(extdheader), 1239231200Smm &lha->atime_tv_nsec); 1240231200Smm lha->setflag |= BIRTHTIME_IS_SET | 1241231200Smm ATIME_IS_SET; 1242231200Smm } 1243231200Smm break; 1244231200Smm case EXT_FILESIZE: 1245231200Smm if (datasize == sizeof(uint64_t) * 2) { 1246231200Smm lha->compsize = archive_le64dec(extdheader); 1247231200Smm extdheader += sizeof(uint64_t); 1248231200Smm lha->origsize = archive_le64dec(extdheader); 1249231200Smm } 1250231200Smm break; 1251231200Smm case EXT_CODEPAGE: 1252231200Smm /* Get an archived filename charset from codepage. 1253231200Smm * This overwrites the charset specified by 1254231200Smm * hdrcharset option. */ 1255231200Smm if (datasize == sizeof(uint32_t)) { 1256231200Smm struct archive_string cp; 1257231200Smm const char *charset; 1258231200Smm 1259231200Smm archive_string_init(&cp); 1260231200Smm switch (archive_le32dec(extdheader)) { 1261231200Smm case 65001: /* UTF-8 */ 1262231200Smm charset = "UTF-8"; 1263231200Smm break; 1264231200Smm default: 1265231200Smm archive_string_sprintf(&cp, "CP%d", 1266231200Smm (int)archive_le32dec(extdheader)); 1267231200Smm charset = cp.s; 1268231200Smm break; 1269231200Smm } 1270231200Smm lha->sconv = 1271231200Smm archive_string_conversion_from_charset( 1272231200Smm &(a->archive), charset, 1); 1273231200Smm archive_string_free(&cp); 1274231200Smm if (lha->sconv == NULL) 1275231200Smm return (ARCHIVE_FATAL); 1276231200Smm } 1277231200Smm break; 1278231200Smm case EXT_UNIX_MODE: 1279231200Smm if (datasize == sizeof(uint16_t)) { 1280231200Smm lha->mode = archive_le16dec(extdheader); 1281231200Smm lha->setflag |= UNIX_MODE_IS_SET; 1282231200Smm } 1283231200Smm break; 1284231200Smm case EXT_UNIX_GID_UID: 1285231200Smm if (datasize == (sizeof(uint16_t) * 2)) { 1286231200Smm lha->gid = archive_le16dec(extdheader); 1287231200Smm lha->uid = archive_le16dec(extdheader+2); 1288231200Smm } 1289231200Smm break; 1290231200Smm case EXT_UNIX_GNAME: 1291231200Smm if (datasize > 0) 1292231200Smm archive_strncpy(&lha->gname, 1293231200Smm (const char *)extdheader, datasize); 1294231200Smm break; 1295231200Smm case EXT_UNIX_UNAME: 1296231200Smm if (datasize > 0) 1297231200Smm archive_strncpy(&lha->uname, 1298231200Smm (const char *)extdheader, datasize); 1299231200Smm break; 1300231200Smm case EXT_UNIX_MTIME: 1301231200Smm if (datasize == sizeof(uint32_t)) 1302231200Smm lha->mtime = archive_le32dec(extdheader); 1303231200Smm break; 1304231200Smm case EXT_OS2_NEW_ATTR: 1305231200Smm /* This extended header is OS/2 depend. */ 1306231200Smm if (datasize == 16) { 1307231200Smm lha->dos_attr = (unsigned char) 1308231200Smm (archive_le16dec(extdheader) & 0xff); 1309231200Smm lha->mode = archive_le16dec(extdheader+2); 1310231200Smm lha->gid = archive_le16dec(extdheader+4); 1311231200Smm lha->uid = archive_le16dec(extdheader+6); 1312231200Smm lha->birthtime = archive_le32dec(extdheader+8); 1313231200Smm lha->atime = archive_le32dec(extdheader+12); 1314231200Smm lha->setflag |= UNIX_MODE_IS_SET 1315231200Smm | BIRTHTIME_IS_SET | ATIME_IS_SET; 1316231200Smm } 1317231200Smm break; 1318231200Smm case EXT_NEW_ATTR: 1319231200Smm if (datasize == 20) { 1320231200Smm lha->mode = (mode_t)archive_le32dec(extdheader); 1321231200Smm lha->gid = archive_le32dec(extdheader+4); 1322231200Smm lha->uid = archive_le32dec(extdheader+8); 1323231200Smm lha->birthtime = archive_le32dec(extdheader+12); 1324231200Smm lha->atime = archive_le32dec(extdheader+16); 1325231200Smm lha->setflag |= UNIX_MODE_IS_SET 1326231200Smm | BIRTHTIME_IS_SET | ATIME_IS_SET; 1327231200Smm } 1328231200Smm break; 1329231200Smm case EXT_TIMEZONE: /* Not supported */ 1330231200Smm case EXT_UTF16_FILENAME: /* Not supported */ 1331231200Smm case EXT_UTF16_DIRECTORY: /* Not supported */ 1332231200Smm default: 1333231200Smm break; 1334231200Smm } 1335231200Smm 1336231200Smm __archive_read_consume(a, extdsize); 1337231200Smm } 1338231200Smminvalid: 1339231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1340231200Smm "Invalid extended LHa header"); 1341231200Smm return (ARCHIVE_FATAL); 1342231200Smm} 1343231200Smm 1344231200Smmstatic int 1345299529Smmlha_end_of_entry(struct archive_read *a) 1346299529Smm{ 1347299529Smm struct lha *lha = (struct lha *)(a->format->data); 1348299529Smm int r = ARCHIVE_EOF; 1349299529Smm 1350299529Smm if (!lha->end_of_entry_cleanup) { 1351299529Smm if ((lha->setflag & CRC_IS_SET) && 1352299529Smm lha->crc != lha->entry_crc_calculated) { 1353299529Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1354299529Smm "LHa data CRC error"); 1355299529Smm r = ARCHIVE_WARN; 1356299529Smm } 1357299529Smm 1358299529Smm /* End-of-entry cleanup done. */ 1359299529Smm lha->end_of_entry_cleanup = 1; 1360299529Smm } 1361299529Smm return (r); 1362299529Smm} 1363299529Smm 1364299529Smmstatic int 1365231200Smmarchive_read_format_lha_read_data(struct archive_read *a, 1366231200Smm const void **buff, size_t *size, int64_t *offset) 1367231200Smm{ 1368231200Smm struct lha *lha = (struct lha *)(a->format->data); 1369231200Smm int r; 1370231200Smm 1371231200Smm if (lha->entry_unconsumed) { 1372231200Smm /* Consume as much as the decompressor actually used. */ 1373231200Smm __archive_read_consume(a, lha->entry_unconsumed); 1374231200Smm lha->entry_unconsumed = 0; 1375231200Smm } 1376231200Smm if (lha->end_of_entry) { 1377231200Smm *offset = lha->entry_offset; 1378231200Smm *size = 0; 1379231200Smm *buff = NULL; 1380299529Smm return (lha_end_of_entry(a)); 1381231200Smm } 1382231200Smm 1383231200Smm if (lha->entry_is_compressed) 1384231200Smm r = lha_read_data_lzh(a, buff, size, offset); 1385231200Smm else 1386231200Smm /* No compression. */ 1387231200Smm r = lha_read_data_none(a, buff, size, offset); 1388231200Smm return (r); 1389231200Smm} 1390231200Smm 1391231200Smm/* 1392231200Smm * Read a file content in no compression. 1393231200Smm * 1394231200Smm * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets 1395231200Smm * lha->end_of_entry if it consumes all of the data. 1396231200Smm */ 1397231200Smmstatic int 1398231200Smmlha_read_data_none(struct archive_read *a, const void **buff, 1399231200Smm size_t *size, int64_t *offset) 1400231200Smm{ 1401231200Smm struct lha *lha = (struct lha *)(a->format->data); 1402231200Smm ssize_t bytes_avail; 1403231200Smm 1404231200Smm if (lha->entry_bytes_remaining == 0) { 1405231200Smm *buff = NULL; 1406231200Smm *size = 0; 1407231200Smm *offset = lha->entry_offset; 1408231200Smm lha->end_of_entry = 1; 1409231200Smm return (ARCHIVE_OK); 1410231200Smm } 1411231200Smm /* 1412231200Smm * Note: '1' here is a performance optimization. 1413231200Smm * Recall that the decompression layer returns a count of 1414231200Smm * available bytes; asking for more than that forces the 1415231200Smm * decompressor to combine reads by copying data. 1416231200Smm */ 1417231200Smm *buff = __archive_read_ahead(a, 1, &bytes_avail); 1418231200Smm if (bytes_avail <= 0) { 1419231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1420231200Smm "Truncated LHa file data"); 1421231200Smm return (ARCHIVE_FATAL); 1422231200Smm } 1423231200Smm if (bytes_avail > lha->entry_bytes_remaining) 1424238856Smm bytes_avail = (ssize_t)lha->entry_bytes_remaining; 1425231200Smm lha->entry_crc_calculated = 1426231200Smm lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail); 1427231200Smm *size = bytes_avail; 1428231200Smm *offset = lha->entry_offset; 1429231200Smm lha->entry_offset += bytes_avail; 1430231200Smm lha->entry_bytes_remaining -= bytes_avail; 1431231200Smm if (lha->entry_bytes_remaining == 0) 1432231200Smm lha->end_of_entry = 1; 1433231200Smm lha->entry_unconsumed = bytes_avail; 1434231200Smm return (ARCHIVE_OK); 1435231200Smm} 1436231200Smm 1437231200Smm/* 1438231200Smm * Read a file content in LZHUFF encoding. 1439231200Smm * 1440231200Smm * Returns ARCHIVE_OK if successful, returns ARCHIVE_WARN if compression is 1441231200Smm * unsupported, ARCHIVE_FATAL otherwise, sets lha->end_of_entry if it consumes 1442231200Smm * all of the data. 1443231200Smm */ 1444231200Smmstatic int 1445231200Smmlha_read_data_lzh(struct archive_read *a, const void **buff, 1446231200Smm size_t *size, int64_t *offset) 1447231200Smm{ 1448231200Smm struct lha *lha = (struct lha *)(a->format->data); 1449231200Smm ssize_t bytes_avail; 1450231200Smm int r; 1451231200Smm 1452231200Smm /* If we haven't yet read any data, initialize the decompressor. */ 1453231200Smm if (!lha->decompress_init) { 1454231200Smm r = lzh_decode_init(&(lha->strm), lha->method); 1455231200Smm switch (r) { 1456231200Smm case ARCHIVE_OK: 1457231200Smm break; 1458231200Smm case ARCHIVE_FAILED: 1459231200Smm /* Unsupported compression. */ 1460231200Smm *buff = NULL; 1461231200Smm *size = 0; 1462231200Smm *offset = 0; 1463231200Smm archive_set_error(&a->archive, 1464231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 1465231200Smm "Unsupported lzh compression method -%c%c%c-", 1466231200Smm lha->method[0], lha->method[1], lha->method[2]); 1467231200Smm /* We know compressed size; just skip it. */ 1468231200Smm archive_read_format_lha_read_data_skip(a); 1469231200Smm return (ARCHIVE_WARN); 1470231200Smm default: 1471231200Smm archive_set_error(&a->archive, ENOMEM, 1472231200Smm "Couldn't allocate memory " 1473231200Smm "for lzh decompression"); 1474231200Smm return (ARCHIVE_FATAL); 1475231200Smm } 1476231200Smm /* We've initialized decompression for this stream. */ 1477231200Smm lha->decompress_init = 1; 1478231200Smm lha->strm.avail_out = 0; 1479231200Smm lha->strm.total_out = 0; 1480231200Smm } 1481231200Smm 1482231200Smm /* 1483231200Smm * Note: '1' here is a performance optimization. 1484231200Smm * Recall that the decompression layer returns a count of 1485231200Smm * available bytes; asking for more than that forces the 1486231200Smm * decompressor to combine reads by copying data. 1487231200Smm */ 1488231200Smm lha->strm.next_in = __archive_read_ahead(a, 1, &bytes_avail); 1489231200Smm if (bytes_avail <= 0) { 1490231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1491231200Smm "Truncated LHa file body"); 1492231200Smm return (ARCHIVE_FATAL); 1493231200Smm } 1494231200Smm if (bytes_avail > lha->entry_bytes_remaining) 1495238856Smm bytes_avail = (ssize_t)lha->entry_bytes_remaining; 1496231200Smm 1497299529Smm lha->strm.avail_in = (int)bytes_avail; 1498231200Smm lha->strm.total_in = 0; 1499299529Smm lha->strm.avail_out = 0; 1500231200Smm 1501231200Smm r = lzh_decode(&(lha->strm), bytes_avail == lha->entry_bytes_remaining); 1502231200Smm switch (r) { 1503231200Smm case ARCHIVE_OK: 1504231200Smm break; 1505231200Smm case ARCHIVE_EOF: 1506231200Smm lha->end_of_entry = 1; 1507231200Smm break; 1508231200Smm default: 1509231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1510231200Smm "Bad lzh data"); 1511231200Smm return (ARCHIVE_FAILED); 1512231200Smm } 1513231200Smm lha->entry_unconsumed = lha->strm.total_in; 1514231200Smm lha->entry_bytes_remaining -= lha->strm.total_in; 1515231200Smm 1516299529Smm if (lha->strm.avail_out) { 1517231200Smm *offset = lha->entry_offset; 1518299529Smm *size = lha->strm.avail_out; 1519299529Smm *buff = lha->strm.ref_ptr; 1520231200Smm lha->entry_crc_calculated = 1521231200Smm lha_crc16(lha->entry_crc_calculated, *buff, *size); 1522231200Smm lha->entry_offset += *size; 1523231200Smm } else { 1524231200Smm *offset = lha->entry_offset; 1525231200Smm *size = 0; 1526231200Smm *buff = NULL; 1527299529Smm if (lha->end_of_entry) 1528299529Smm return (lha_end_of_entry(a)); 1529231200Smm } 1530231200Smm return (ARCHIVE_OK); 1531231200Smm} 1532231200Smm 1533231200Smm/* 1534231200Smm * Skip a file content. 1535231200Smm */ 1536231200Smmstatic int 1537231200Smmarchive_read_format_lha_read_data_skip(struct archive_read *a) 1538231200Smm{ 1539231200Smm struct lha *lha; 1540238856Smm int64_t bytes_skipped; 1541231200Smm 1542231200Smm lha = (struct lha *)(a->format->data); 1543231200Smm 1544231200Smm if (lha->entry_unconsumed) { 1545231200Smm /* Consume as much as the decompressor actually used. */ 1546231200Smm __archive_read_consume(a, lha->entry_unconsumed); 1547231200Smm lha->entry_unconsumed = 0; 1548231200Smm } 1549231200Smm 1550231200Smm /* if we've already read to end of data, we're done. */ 1551231200Smm if (lha->end_of_entry_cleanup) 1552231200Smm return (ARCHIVE_OK); 1553231200Smm 1554231200Smm /* 1555231200Smm * If the length is at the beginning, we can skip the 1556231200Smm * compressed data much more quickly. 1557231200Smm */ 1558231200Smm bytes_skipped = __archive_read_consume(a, lha->entry_bytes_remaining); 1559231200Smm if (bytes_skipped < 0) 1560231200Smm return (ARCHIVE_FATAL); 1561231200Smm 1562231200Smm /* This entry is finished and done. */ 1563231200Smm lha->end_of_entry_cleanup = lha->end_of_entry = 1; 1564231200Smm return (ARCHIVE_OK); 1565231200Smm} 1566231200Smm 1567231200Smmstatic int 1568231200Smmarchive_read_format_lha_cleanup(struct archive_read *a) 1569231200Smm{ 1570231200Smm struct lha *lha = (struct lha *)(a->format->data); 1571231200Smm 1572231200Smm lzh_decode_free(&(lha->strm)); 1573231200Smm archive_string_free(&(lha->dirname)); 1574231200Smm archive_string_free(&(lha->filename)); 1575231200Smm archive_string_free(&(lha->uname)); 1576231200Smm archive_string_free(&(lha->gname)); 1577231200Smm archive_wstring_free(&(lha->ws)); 1578231200Smm free(lha); 1579231200Smm (a->format->data) = NULL; 1580231200Smm return (ARCHIVE_OK); 1581231200Smm} 1582231200Smm 1583231200Smm/* 1584231200Smm * 'LHa for UNIX' utility has archived a symbolic-link name after 1585231200Smm * a pathname with '|' character. 1586231200Smm * This function extracts the symbolic-link name from the pathname. 1587231200Smm * 1588231200Smm * example. 1589231200Smm * 1. a symbolic-name is 'aaa/bb/cc' 1590231200Smm * 2. a filename is 'xxx/bbb' 1591231200Smm * then a archived pathname is 'xxx/bbb|aaa/bb/cc' 1592231200Smm */ 1593231200Smmstatic int 1594231200Smmlha_parse_linkname(struct archive_string *linkname, 1595231200Smm struct archive_string *pathname) 1596231200Smm{ 1597231200Smm char * linkptr; 1598248616Smm size_t symlen; 1599231200Smm 1600231200Smm linkptr = strchr(pathname->s, '|'); 1601231200Smm if (linkptr != NULL) { 1602231200Smm symlen = strlen(linkptr + 1); 1603231200Smm archive_strncpy(linkname, linkptr+1, symlen); 1604231200Smm 1605231200Smm *linkptr = 0; 1606231200Smm pathname->length = strlen(pathname->s); 1607231200Smm 1608231200Smm return (1); 1609231200Smm } 1610231200Smm return (0); 1611231200Smm} 1612231200Smm 1613231200Smm/* Convert an MSDOS-style date/time into Unix-style time. */ 1614231200Smmstatic time_t 1615231200Smmlha_dos_time(const unsigned char *p) 1616231200Smm{ 1617231200Smm int msTime, msDate; 1618231200Smm struct tm ts; 1619231200Smm 1620231200Smm msTime = archive_le16dec(p); 1621231200Smm msDate = archive_le16dec(p+2); 1622231200Smm 1623231200Smm memset(&ts, 0, sizeof(ts)); 1624231200Smm ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ 1625231200Smm ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ 1626231200Smm ts.tm_mday = msDate & 0x1f; /* Day of month. */ 1627231200Smm ts.tm_hour = (msTime >> 11) & 0x1f; 1628231200Smm ts.tm_min = (msTime >> 5) & 0x3f; 1629231200Smm ts.tm_sec = (msTime << 1) & 0x3e; 1630231200Smm ts.tm_isdst = -1; 1631231200Smm return (mktime(&ts)); 1632231200Smm} 1633231200Smm 1634231200Smm/* Convert an MS-Windows-style date/time into Unix-style time. */ 1635231200Smmstatic time_t 1636231200Smmlha_win_time(uint64_t wintime, long *ns) 1637231200Smm{ 1638231200Smm#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) 1639231200Smm 1640231200Smm if (wintime >= EPOC_TIME) { 1641231200Smm wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */ 1642231200Smm if (ns != NULL) 1643231200Smm *ns = (long)(wintime % 10000000) * 100; 1644231200Smm return (wintime / 10000000); 1645231200Smm } else { 1646231200Smm if (ns != NULL) 1647231200Smm *ns = 0; 1648231200Smm return (0); 1649231200Smm } 1650231200Smm} 1651231200Smm 1652231200Smmstatic unsigned char 1653248616Smmlha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) 1654231200Smm{ 1655231200Smm unsigned char const *p = (unsigned char const *)pp; 1656231200Smm 1657231200Smm p += offset; 1658248616Smm for (;size > 0; --size) 1659231200Smm sum += *p++; 1660231200Smm return (sum); 1661231200Smm} 1662231200Smm 1663299529Smmstatic uint16_t crc16tbl[2][256]; 1664299529Smmstatic void 1665299529Smmlha_crc16_init(void) 1666299529Smm{ 1667299529Smm unsigned int i; 1668299529Smm static int crc16init = 0; 1669231200Smm 1670299529Smm if (crc16init) 1671299529Smm return; 1672299529Smm crc16init = 1; 1673299529Smm 1674299529Smm for (i = 0; i < 256; i++) { 1675299529Smm unsigned int j; 1676299529Smm uint16_t crc = (uint16_t)i; 1677299529Smm for (j = 8; j; j--) 1678299529Smm crc = (crc >> 1) ^ ((crc & 1) * 0xA001); 1679299529Smm crc16tbl[0][i] = crc; 1680299529Smm } 1681299529Smm 1682299529Smm for (i = 0; i < 256; i++) { 1683299529Smm crc16tbl[1][i] = (crc16tbl[0][i] >> 8) 1684299529Smm ^ crc16tbl[0][crc16tbl[0][i] & 0xff]; 1685299529Smm } 1686299529Smm} 1687299529Smm 1688231200Smmstatic uint16_t 1689231200Smmlha_crc16(uint16_t crc, const void *pp, size_t len) 1690231200Smm{ 1691299529Smm const unsigned char *p = (const unsigned char *)pp; 1692299529Smm const uint16_t *buff; 1693299529Smm const union { 1694299529Smm uint32_t i; 1695299529Smm char c[4]; 1696299529Smm } u = { 0x01020304 }; 1697231200Smm 1698299529Smm if (len == 0) 1699299529Smm return crc; 1700299529Smm 1701299529Smm /* Process unaligned address. */ 1702299529Smm if (((uintptr_t)p) & (uintptr_t)0x1) { 1703299529Smm crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff]; 1704299529Smm len--; 1705231200Smm } 1706299529Smm buff = (const uint16_t *)p; 1707299529Smm /* 1708299529Smm * Modern C compiler such as GCC does not unroll automatically yet 1709299529Smm * without unrolling pragma, and Clang is so. So we should 1710299529Smm * unroll this loop for its performance. 1711299529Smm */ 1712299529Smm for (;len >= 8; len -= 8) { 1713299529Smm /* This if statement expects compiler optimization will 1714299529Smm * remove the stament which will not be executed. */ 1715302075Smm#undef bswap16 1716299529Smm#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */ 1717299529Smm# define bswap16(x) _byteswap_ushort(x) 1718305313Smm#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) 1719305313Smm/* GCC 4.8 and later has __builtin_bswap16() */ 1720299529Smm# define bswap16(x) __builtin_bswap16(x) 1721305313Smm#elif defined(__clang__) 1722305313Smm/* All clang versions have __builtin_bswap16() */ 1723305313Smm# define bswap16(x) __builtin_bswap16(x) 1724299529Smm#else 1725299529Smm# define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8)) 1726299529Smm#endif 1727299529Smm#define CRC16W do { \ 1728299529Smm if(u.c[0] == 1) { /* Big endian */ \ 1729299529Smm crc ^= bswap16(*buff); buff++; \ 1730299529Smm } else \ 1731299529Smm crc ^= *buff++; \ 1732299529Smm crc = crc16tbl[1][crc & 0xff] ^ crc16tbl[0][crc >> 8];\ 1733299529Smm} while (0) 1734299529Smm CRC16W; 1735299529Smm CRC16W; 1736299529Smm CRC16W; 1737299529Smm CRC16W; 1738299529Smm#undef CRC16W 1739299529Smm#undef bswap16 1740231200Smm } 1741299529Smm 1742299529Smm p = (const unsigned char *)buff; 1743299529Smm for (;len; len--) { 1744299529Smm crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff]; 1745299529Smm } 1746299529Smm return crc; 1747231200Smm} 1748231200Smm 1749231200Smm/* 1750231200Smm * Initialize LZHUF decoder. 1751231200Smm * 1752231200Smm * Returns ARCHIVE_OK if initialization was successful. 1753231200Smm * Returns ARCHIVE_FAILED if method is unsupported. 1754231200Smm * Returns ARCHIVE_FATAL if initialization failed; memory allocation 1755231200Smm * error occurred. 1756231200Smm */ 1757231200Smmstatic int 1758231200Smmlzh_decode_init(struct lzh_stream *strm, const char *method) 1759231200Smm{ 1760231200Smm struct lzh_dec *ds; 1761231200Smm int w_bits, w_size; 1762231200Smm 1763231200Smm if (strm->ds == NULL) { 1764231200Smm strm->ds = calloc(1, sizeof(*strm->ds)); 1765231200Smm if (strm->ds == NULL) 1766231200Smm return (ARCHIVE_FATAL); 1767231200Smm } 1768231200Smm ds = strm->ds; 1769231200Smm ds->error = ARCHIVE_FAILED; 1770231200Smm if (method == NULL || method[0] != 'l' || method[1] != 'h') 1771231200Smm return (ARCHIVE_FAILED); 1772231200Smm switch (method[2]) { 1773231200Smm case '5': 1774231200Smm w_bits = 13;/* 8KiB for window */ 1775231200Smm break; 1776231200Smm case '6': 1777231200Smm w_bits = 15;/* 32KiB for window */ 1778231200Smm break; 1779231200Smm case '7': 1780231200Smm w_bits = 16;/* 64KiB for window */ 1781231200Smm break; 1782231200Smm default: 1783231200Smm return (ARCHIVE_FAILED);/* Not supported. */ 1784231200Smm } 1785231200Smm ds->error = ARCHIVE_FATAL; 1786299529Smm /* Expand a window size up to 128 KiB for decompressing process 1787299529Smm * performance whatever its original window size is. */ 1788299529Smm ds->w_size = 1U << 17; 1789231200Smm ds->w_mask = ds->w_size -1; 1790299529Smm if (ds->w_buff == NULL) { 1791231200Smm ds->w_buff = malloc(ds->w_size); 1792231200Smm if (ds->w_buff == NULL) 1793231200Smm return (ARCHIVE_FATAL); 1794231200Smm } 1795299529Smm w_size = 1U << w_bits; 1796299529Smm memset(ds->w_buff + ds->w_size - w_size, 0x20, w_size); 1797231200Smm ds->w_pos = 0; 1798231200Smm ds->state = 0; 1799231200Smm ds->pos_pt_len_size = w_bits + 1; 1800231200Smm ds->pos_pt_len_bits = (w_bits == 15 || w_bits == 16)? 5: 4; 1801231200Smm ds->literal_pt_len_size = PT_BITLEN_SIZE; 1802231200Smm ds->literal_pt_len_bits = 5; 1803231200Smm ds->br.cache_buffer = 0; 1804231200Smm ds->br.cache_avail = 0; 1805231200Smm 1806231200Smm if (lzh_huffman_init(&(ds->lt), LT_BITLEN_SIZE, 16) 1807231200Smm != ARCHIVE_OK) 1808231200Smm return (ARCHIVE_FATAL); 1809231200Smm ds->lt.len_bits = 9; 1810231200Smm if (lzh_huffman_init(&(ds->pt), PT_BITLEN_SIZE, 16) 1811231200Smm != ARCHIVE_OK) 1812231200Smm return (ARCHIVE_FATAL); 1813231200Smm ds->error = 0; 1814231200Smm 1815231200Smm return (ARCHIVE_OK); 1816231200Smm} 1817231200Smm 1818231200Smm/* 1819231200Smm * Release LZHUF decoder. 1820231200Smm */ 1821231200Smmstatic void 1822231200Smmlzh_decode_free(struct lzh_stream *strm) 1823231200Smm{ 1824231200Smm 1825231200Smm if (strm->ds == NULL) 1826231200Smm return; 1827231200Smm free(strm->ds->w_buff); 1828231200Smm lzh_huffman_free(&(strm->ds->lt)); 1829231200Smm lzh_huffman_free(&(strm->ds->pt)); 1830231200Smm free(strm->ds); 1831231200Smm strm->ds = NULL; 1832231200Smm} 1833231200Smm 1834231200Smm/* 1835231200Smm * Bit stream reader. 1836231200Smm */ 1837231200Smm/* Check that the cache buffer has enough bits. */ 1838231200Smm#define lzh_br_has(br, n) ((br)->cache_avail >= n) 1839231200Smm/* Get compressed data by bit. */ 1840231200Smm#define lzh_br_bits(br, n) \ 1841231200Smm (((uint16_t)((br)->cache_buffer >> \ 1842231200Smm ((br)->cache_avail - (n)))) & cache_masks[n]) 1843231200Smm#define lzh_br_bits_forced(br, n) \ 1844231200Smm (((uint16_t)((br)->cache_buffer << \ 1845231200Smm ((n) - (br)->cache_avail))) & cache_masks[n]) 1846231200Smm/* Read ahead to make sure the cache buffer has enough compressed data we 1847231200Smm * will use. 1848231200Smm * True : completed, there is enough data in the cache buffer. 1849231200Smm * False : we met that strm->next_in is empty, we have to get following 1850231200Smm * bytes. */ 1851231200Smm#define lzh_br_read_ahead_0(strm, br, n) \ 1852231200Smm (lzh_br_has(br, (n)) || lzh_br_fillup(strm, br)) 1853231200Smm/* True : the cache buffer has some bits as much as we need. 1854231200Smm * False : there are no enough bits in the cache buffer to be used, 1855231200Smm * we have to get following bytes if we could. */ 1856231200Smm#define lzh_br_read_ahead(strm, br, n) \ 1857231200Smm (lzh_br_read_ahead_0((strm), (br), (n)) || lzh_br_has((br), (n))) 1858231200Smm 1859231200Smm/* Notify how many bits we consumed. */ 1860231200Smm#define lzh_br_consume(br, n) ((br)->cache_avail -= (n)) 1861231200Smm#define lzh_br_unconsume(br, n) ((br)->cache_avail += (n)) 1862231200Smm 1863231200Smmstatic const uint16_t cache_masks[] = { 1864231200Smm 0x0000, 0x0001, 0x0003, 0x0007, 1865231200Smm 0x000F, 0x001F, 0x003F, 0x007F, 1866231200Smm 0x00FF, 0x01FF, 0x03FF, 0x07FF, 1867231200Smm 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 1868231200Smm 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF 1869231200Smm}; 1870231200Smm 1871231200Smm/* 1872231200Smm * Shift away used bits in the cache data and fill it up with following bits. 1873231200Smm * Call this when cache buffer does not have enough bits you need. 1874231200Smm * 1875231200Smm * Returns 1 if the cache buffer is full. 1876231200Smm * Returns 0 if the cache buffer is not full; input buffer is empty. 1877231200Smm */ 1878231200Smmstatic int 1879231200Smmlzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br) 1880231200Smm{ 1881231200Smm int n = CACHE_BITS - br->cache_avail; 1882231200Smm 1883231200Smm for (;;) { 1884299529Smm const int x = n >> 3; 1885299529Smm if (strm->avail_in >= x) { 1886299529Smm switch (x) { 1887299529Smm case 8: 1888231200Smm br->cache_buffer = 1889231200Smm ((uint64_t)strm->next_in[0]) << 56 | 1890231200Smm ((uint64_t)strm->next_in[1]) << 48 | 1891231200Smm ((uint64_t)strm->next_in[2]) << 40 | 1892231200Smm ((uint64_t)strm->next_in[3]) << 32 | 1893231200Smm ((uint32_t)strm->next_in[4]) << 24 | 1894231200Smm ((uint32_t)strm->next_in[5]) << 16 | 1895231200Smm ((uint32_t)strm->next_in[6]) << 8 | 1896231200Smm (uint32_t)strm->next_in[7]; 1897231200Smm strm->next_in += 8; 1898231200Smm strm->avail_in -= 8; 1899231200Smm br->cache_avail += 8 * 8; 1900231200Smm return (1); 1901299529Smm case 7: 1902231200Smm br->cache_buffer = 1903231200Smm (br->cache_buffer << 56) | 1904231200Smm ((uint64_t)strm->next_in[0]) << 48 | 1905231200Smm ((uint64_t)strm->next_in[1]) << 40 | 1906231200Smm ((uint64_t)strm->next_in[2]) << 32 | 1907231200Smm ((uint32_t)strm->next_in[3]) << 24 | 1908231200Smm ((uint32_t)strm->next_in[4]) << 16 | 1909231200Smm ((uint32_t)strm->next_in[5]) << 8 | 1910231200Smm (uint32_t)strm->next_in[6]; 1911231200Smm strm->next_in += 7; 1912231200Smm strm->avail_in -= 7; 1913231200Smm br->cache_avail += 7 * 8; 1914231200Smm return (1); 1915299529Smm case 6: 1916231200Smm br->cache_buffer = 1917231200Smm (br->cache_buffer << 48) | 1918231200Smm ((uint64_t)strm->next_in[0]) << 40 | 1919231200Smm ((uint64_t)strm->next_in[1]) << 32 | 1920231200Smm ((uint32_t)strm->next_in[2]) << 24 | 1921231200Smm ((uint32_t)strm->next_in[3]) << 16 | 1922231200Smm ((uint32_t)strm->next_in[4]) << 8 | 1923231200Smm (uint32_t)strm->next_in[5]; 1924231200Smm strm->next_in += 6; 1925231200Smm strm->avail_in -= 6; 1926231200Smm br->cache_avail += 6 * 8; 1927231200Smm return (1); 1928299529Smm case 0: 1929299529Smm /* We have enough compressed data in 1930299529Smm * the cache buffer.*/ 1931299529Smm return (1); 1932299529Smm default: 1933299529Smm break; 1934231200Smm } 1935231200Smm } 1936231200Smm if (strm->avail_in == 0) { 1937231200Smm /* There is not enough compressed data to fill up the 1938231200Smm * cache buffer. */ 1939231200Smm return (0); 1940231200Smm } 1941231200Smm br->cache_buffer = 1942231200Smm (br->cache_buffer << 8) | *strm->next_in++; 1943231200Smm strm->avail_in--; 1944231200Smm br->cache_avail += 8; 1945231200Smm n -= 8; 1946231200Smm } 1947231200Smm} 1948231200Smm 1949231200Smm/* 1950231200Smm * Decode LZHUF. 1951231200Smm * 1952231200Smm * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty. 1953231200Smm * Please set available buffer and call this function again. 1954231200Smm * 2. Returns ARCHIVE_EOF if decompression has been completed. 1955231200Smm * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data 1956231200Smm * is broken or you do not set 'last' flag properly. 1957231200Smm * 4. 'last' flag is very important, you must set 1 to the flag if there 1958231200Smm * is no input data. The lha compressed data format does not provide how 1959231200Smm * to know the compressed data is really finished. 1960231200Smm * Note: lha command utility check if the total size of output bytes is 1961231200Smm * reached the uncompressed size recorded in its header. it does not mind 1962231200Smm * that the decoding process is properly finished. 1963231200Smm * GNU ZIP can decompress another compressed file made by SCO LZH compress. 1964231200Smm * it handles EOF as null to fill read buffer with zero until the decoding 1965231200Smm * process meet 2 bytes of zeros at reading a size of a next chunk, so the 1966231200Smm * zeros are treated as the mark of the end of the data although the zeros 1967231200Smm * is dummy, not the file data. 1968231200Smm */ 1969231200Smmstatic int lzh_read_blocks(struct lzh_stream *, int); 1970231200Smmstatic int lzh_decode_blocks(struct lzh_stream *, int); 1971231200Smm#define ST_RD_BLOCK 0 1972231200Smm#define ST_RD_PT_1 1 1973231200Smm#define ST_RD_PT_2 2 1974231200Smm#define ST_RD_PT_3 3 1975231200Smm#define ST_RD_PT_4 4 1976231200Smm#define ST_RD_LITERAL_1 5 1977231200Smm#define ST_RD_LITERAL_2 6 1978231200Smm#define ST_RD_LITERAL_3 7 1979231200Smm#define ST_RD_POS_DATA_1 8 1980231200Smm#define ST_GET_LITERAL 9 1981231200Smm#define ST_GET_POS_1 10 1982231200Smm#define ST_GET_POS_2 11 1983231200Smm#define ST_COPY_DATA 12 1984231200Smm 1985231200Smmstatic int 1986231200Smmlzh_decode(struct lzh_stream *strm, int last) 1987231200Smm{ 1988231200Smm struct lzh_dec *ds = strm->ds; 1989299529Smm int avail_in; 1990231200Smm int r; 1991231200Smm 1992231200Smm if (ds->error) 1993231200Smm return (ds->error); 1994231200Smm 1995231200Smm avail_in = strm->avail_in; 1996231200Smm do { 1997231200Smm if (ds->state < ST_GET_LITERAL) 1998231200Smm r = lzh_read_blocks(strm, last); 1999231200Smm else 2000231200Smm r = lzh_decode_blocks(strm, last); 2001231200Smm } while (r == 100); 2002231200Smm strm->total_in += avail_in - strm->avail_in; 2003231200Smm return (r); 2004231200Smm} 2005231200Smm 2006299529Smmstatic void 2007299529Smmlzh_emit_window(struct lzh_stream *strm, size_t s) 2008231200Smm{ 2009299529Smm strm->ref_ptr = strm->ds->w_buff; 2010299529Smm strm->avail_out = (int)s; 2011299529Smm strm->total_out += s; 2012231200Smm} 2013231200Smm 2014231200Smmstatic int 2015231200Smmlzh_read_blocks(struct lzh_stream *strm, int last) 2016231200Smm{ 2017231200Smm struct lzh_dec *ds = strm->ds; 2018231200Smm struct lzh_br *br = &(ds->br); 2019231200Smm int c = 0, i; 2020231200Smm unsigned rbits; 2021231200Smm 2022231200Smm for (;;) { 2023231200Smm switch (ds->state) { 2024231200Smm case ST_RD_BLOCK: 2025231200Smm /* 2026231200Smm * Read a block number indicates how many blocks 2027231200Smm * we will handle. The block is composed of a 2028231200Smm * literal and a match, sometimes a literal only 2029231200Smm * in particular, there are no reference data at 2030231200Smm * the beginning of the decompression. 2031231200Smm */ 2032231200Smm if (!lzh_br_read_ahead_0(strm, br, 16)) { 2033231200Smm if (!last) 2034231200Smm /* We need following data. */ 2035231200Smm return (ARCHIVE_OK); 2036231200Smm if (lzh_br_has(br, 8)) { 2037231200Smm /* 2038231200Smm * It seems there are extra bits. 2039231200Smm * 1. Compressed data is broken. 2040231200Smm * 2. `last' flag does not properly 2041231200Smm * set. 2042231200Smm */ 2043231200Smm goto failed; 2044231200Smm } 2045231200Smm if (ds->w_pos > 0) { 2046299529Smm lzh_emit_window(strm, ds->w_pos); 2047299529Smm ds->w_pos = 0; 2048299529Smm return (ARCHIVE_OK); 2049231200Smm } 2050231200Smm /* End of compressed data; we have completely 2051231200Smm * handled all compressed data. */ 2052231200Smm return (ARCHIVE_EOF); 2053231200Smm } 2054231200Smm ds->blocks_avail = lzh_br_bits(br, 16); 2055231200Smm if (ds->blocks_avail == 0) 2056231200Smm goto failed; 2057231200Smm lzh_br_consume(br, 16); 2058231200Smm /* 2059231200Smm * Read a literal table compressed in huffman 2060231200Smm * coding. 2061231200Smm */ 2062231200Smm ds->pt.len_size = ds->literal_pt_len_size; 2063231200Smm ds->pt.len_bits = ds->literal_pt_len_bits; 2064231200Smm ds->reading_position = 0; 2065231200Smm /* FALL THROUGH */ 2066231200Smm case ST_RD_PT_1: 2067231200Smm /* Note: ST_RD_PT_1, ST_RD_PT_2 and ST_RD_PT_4 are 2068231200Smm * used in reading both a literal table and a 2069231200Smm * position table. */ 2070231200Smm if (!lzh_br_read_ahead(strm, br, ds->pt.len_bits)) { 2071231200Smm if (last) 2072231200Smm goto failed;/* Truncated data. */ 2073231200Smm ds->state = ST_RD_PT_1; 2074231200Smm return (ARCHIVE_OK); 2075231200Smm } 2076231200Smm ds->pt.len_avail = lzh_br_bits(br, ds->pt.len_bits); 2077231200Smm lzh_br_consume(br, ds->pt.len_bits); 2078231200Smm /* FALL THROUGH */ 2079231200Smm case ST_RD_PT_2: 2080231200Smm if (ds->pt.len_avail == 0) { 2081231200Smm /* There is no bitlen. */ 2082231200Smm if (!lzh_br_read_ahead(strm, br, 2083231200Smm ds->pt.len_bits)) { 2084231200Smm if (last) 2085231200Smm goto failed;/* Truncated data.*/ 2086231200Smm ds->state = ST_RD_PT_2; 2087231200Smm return (ARCHIVE_OK); 2088231200Smm } 2089231200Smm if (!lzh_make_fake_table(&(ds->pt), 2090231200Smm lzh_br_bits(br, ds->pt.len_bits))) 2091231200Smm goto failed;/* Invalid data. */ 2092231200Smm lzh_br_consume(br, ds->pt.len_bits); 2093231200Smm if (ds->reading_position) 2094231200Smm ds->state = ST_GET_LITERAL; 2095231200Smm else 2096231200Smm ds->state = ST_RD_LITERAL_1; 2097231200Smm break; 2098231200Smm } else if (ds->pt.len_avail > ds->pt.len_size) 2099231200Smm goto failed;/* Invalid data. */ 2100231200Smm ds->loop = 0; 2101231200Smm memset(ds->pt.freq, 0, sizeof(ds->pt.freq)); 2102231200Smm if (ds->pt.len_avail < 3 || 2103231200Smm ds->pt.len_size == ds->pos_pt_len_size) { 2104231200Smm ds->state = ST_RD_PT_4; 2105231200Smm break; 2106231200Smm } 2107231200Smm /* FALL THROUGH */ 2108231200Smm case ST_RD_PT_3: 2109231200Smm ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 3); 2110231200Smm if (ds->loop < 3) { 2111231200Smm if (ds->loop < 0 || last) 2112231200Smm goto failed;/* Invalid data. */ 2113231200Smm /* Not completed, get following data. */ 2114231200Smm ds->state = ST_RD_PT_3; 2115231200Smm return (ARCHIVE_OK); 2116231200Smm } 2117231200Smm /* There are some null in bitlen of the literal. */ 2118231200Smm if (!lzh_br_read_ahead(strm, br, 2)) { 2119231200Smm if (last) 2120231200Smm goto failed;/* Truncated data. */ 2121231200Smm ds->state = ST_RD_PT_3; 2122231200Smm return (ARCHIVE_OK); 2123231200Smm } 2124231200Smm c = lzh_br_bits(br, 2); 2125231200Smm lzh_br_consume(br, 2); 2126231200Smm if (c > ds->pt.len_avail - 3) 2127231200Smm goto failed;/* Invalid data. */ 2128231200Smm for (i = 3; c-- > 0 ;) 2129231200Smm ds->pt.bitlen[i++] = 0; 2130231200Smm ds->loop = i; 2131231200Smm /* FALL THROUGH */ 2132231200Smm case ST_RD_PT_4: 2133231200Smm ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 2134231200Smm ds->pt.len_avail); 2135231200Smm if (ds->loop < ds->pt.len_avail) { 2136231200Smm if (ds->loop < 0 || last) 2137231200Smm goto failed;/* Invalid data. */ 2138231200Smm /* Not completed, get following data. */ 2139231200Smm ds->state = ST_RD_PT_4; 2140231200Smm return (ARCHIVE_OK); 2141231200Smm } 2142231200Smm if (!lzh_make_huffman_table(&(ds->pt))) 2143231200Smm goto failed;/* Invalid data */ 2144231200Smm if (ds->reading_position) { 2145231200Smm ds->state = ST_GET_LITERAL; 2146231200Smm break; 2147231200Smm } 2148231200Smm /* FALL THROUGH */ 2149231200Smm case ST_RD_LITERAL_1: 2150231200Smm if (!lzh_br_read_ahead(strm, br, ds->lt.len_bits)) { 2151231200Smm if (last) 2152231200Smm goto failed;/* Truncated data. */ 2153231200Smm ds->state = ST_RD_LITERAL_1; 2154231200Smm return (ARCHIVE_OK); 2155231200Smm } 2156231200Smm ds->lt.len_avail = lzh_br_bits(br, ds->lt.len_bits); 2157231200Smm lzh_br_consume(br, ds->lt.len_bits); 2158231200Smm /* FALL THROUGH */ 2159231200Smm case ST_RD_LITERAL_2: 2160231200Smm if (ds->lt.len_avail == 0) { 2161231200Smm /* There is no bitlen. */ 2162231200Smm if (!lzh_br_read_ahead(strm, br, 2163231200Smm ds->lt.len_bits)) { 2164231200Smm if (last) 2165231200Smm goto failed;/* Truncated data.*/ 2166231200Smm ds->state = ST_RD_LITERAL_2; 2167231200Smm return (ARCHIVE_OK); 2168231200Smm } 2169231200Smm if (!lzh_make_fake_table(&(ds->lt), 2170231200Smm lzh_br_bits(br, ds->lt.len_bits))) 2171231200Smm goto failed;/* Invalid data */ 2172231200Smm lzh_br_consume(br, ds->lt.len_bits); 2173231200Smm ds->state = ST_RD_POS_DATA_1; 2174231200Smm break; 2175231200Smm } else if (ds->lt.len_avail > ds->lt.len_size) 2176231200Smm goto failed;/* Invalid data */ 2177231200Smm ds->loop = 0; 2178231200Smm memset(ds->lt.freq, 0, sizeof(ds->lt.freq)); 2179231200Smm /* FALL THROUGH */ 2180231200Smm case ST_RD_LITERAL_3: 2181231200Smm i = ds->loop; 2182231200Smm while (i < ds->lt.len_avail) { 2183231200Smm if (!lzh_br_read_ahead(strm, br, 2184231200Smm ds->pt.max_bits)) { 2185231200Smm if (last) 2186231200Smm goto failed;/* Truncated data.*/ 2187231200Smm ds->loop = i; 2188231200Smm ds->state = ST_RD_LITERAL_3; 2189231200Smm return (ARCHIVE_OK); 2190231200Smm } 2191231200Smm rbits = lzh_br_bits(br, ds->pt.max_bits); 2192231200Smm c = lzh_decode_huffman(&(ds->pt), rbits); 2193231200Smm if (c > 2) { 2194231200Smm /* Note: 'c' will never be more than 2195231200Smm * eighteen since it's limited by 2196231200Smm * PT_BITLEN_SIZE, which is being set 2197231200Smm * to ds->pt.len_size through 2198231200Smm * ds->literal_pt_len_size. */ 2199231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2200231200Smm c -= 2; 2201231200Smm ds->lt.freq[c]++; 2202231200Smm ds->lt.bitlen[i++] = c; 2203231200Smm } else if (c == 0) { 2204231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2205231200Smm ds->lt.bitlen[i++] = 0; 2206231200Smm } else { 2207231200Smm /* c == 1 or c == 2 */ 2208231200Smm int n = (c == 1)?4:9; 2209231200Smm if (!lzh_br_read_ahead(strm, br, 2210231200Smm ds->pt.bitlen[c] + n)) { 2211231200Smm if (last) /* Truncated data. */ 2212231200Smm goto failed; 2213231200Smm ds->loop = i; 2214231200Smm ds->state = ST_RD_LITERAL_3; 2215231200Smm return (ARCHIVE_OK); 2216231200Smm } 2217231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2218231200Smm c = lzh_br_bits(br, n); 2219231200Smm lzh_br_consume(br, n); 2220231200Smm c += (n == 4)?3:20; 2221231200Smm if (i + c > ds->lt.len_avail) 2222231200Smm goto failed;/* Invalid data */ 2223231200Smm memset(&(ds->lt.bitlen[i]), 0, c); 2224231200Smm i += c; 2225231200Smm } 2226231200Smm } 2227231200Smm if (i > ds->lt.len_avail || 2228231200Smm !lzh_make_huffman_table(&(ds->lt))) 2229231200Smm goto failed;/* Invalid data */ 2230231200Smm /* FALL THROUGH */ 2231231200Smm case ST_RD_POS_DATA_1: 2232231200Smm /* 2233231200Smm * Read a position table compressed in huffman 2234231200Smm * coding. 2235231200Smm */ 2236231200Smm ds->pt.len_size = ds->pos_pt_len_size; 2237231200Smm ds->pt.len_bits = ds->pos_pt_len_bits; 2238231200Smm ds->reading_position = 1; 2239231200Smm ds->state = ST_RD_PT_1; 2240231200Smm break; 2241231200Smm case ST_GET_LITERAL: 2242231200Smm return (100); 2243231200Smm } 2244231200Smm } 2245231200Smmfailed: 2246231200Smm return (ds->error = ARCHIVE_FAILED); 2247231200Smm} 2248231200Smm 2249231200Smmstatic int 2250231200Smmlzh_decode_blocks(struct lzh_stream *strm, int last) 2251231200Smm{ 2252231200Smm struct lzh_dec *ds = strm->ds; 2253231200Smm struct lzh_br bre = ds->br; 2254231200Smm struct huffman *lt = &(ds->lt); 2255231200Smm struct huffman *pt = &(ds->pt); 2256231200Smm unsigned char *w_buff = ds->w_buff; 2257231200Smm unsigned char *lt_bitlen = lt->bitlen; 2258231200Smm unsigned char *pt_bitlen = pt->bitlen; 2259231200Smm int blocks_avail = ds->blocks_avail, c = 0; 2260231200Smm int copy_len = ds->copy_len, copy_pos = ds->copy_pos; 2261231200Smm int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size; 2262231200Smm int lt_max_bits = lt->max_bits, pt_max_bits = pt->max_bits; 2263231200Smm int state = ds->state; 2264231200Smm 2265231200Smm for (;;) { 2266231200Smm switch (state) { 2267231200Smm case ST_GET_LITERAL: 2268231200Smm for (;;) { 2269231200Smm if (blocks_avail == 0) { 2270231200Smm /* We have decoded all blocks. 2271231200Smm * Let's handle next blocks. */ 2272231200Smm ds->state = ST_RD_BLOCK; 2273231200Smm ds->br = bre; 2274231200Smm ds->blocks_avail = 0; 2275231200Smm ds->w_pos = w_pos; 2276231200Smm ds->copy_pos = 0; 2277231200Smm return (100); 2278231200Smm } 2279231200Smm 2280231200Smm /* lzh_br_read_ahead() always try to fill the 2281231200Smm * cache buffer up. In specific situation we 2282231200Smm * are close to the end of the data, the cache 2283231200Smm * buffer will not be full and thus we have to 2284231200Smm * determine if the cache buffer has some bits 2285231200Smm * as much as we need after lzh_br_read_ahead() 2286231200Smm * failed. */ 2287231200Smm if (!lzh_br_read_ahead(strm, &bre, 2288231200Smm lt_max_bits)) { 2289231200Smm if (!last) 2290231200Smm goto next_data; 2291231200Smm /* Remaining bits are less than 2292231200Smm * maximum bits(lt.max_bits) but maybe 2293231200Smm * it still remains as much as we need, 2294231200Smm * so we should try to use it with 2295231200Smm * dummy bits. */ 2296231200Smm c = lzh_decode_huffman(lt, 2297231200Smm lzh_br_bits_forced(&bre, 2298231200Smm lt_max_bits)); 2299231200Smm lzh_br_consume(&bre, lt_bitlen[c]); 2300231200Smm if (!lzh_br_has(&bre, 0)) 2301231200Smm goto failed;/* Over read. */ 2302231200Smm } else { 2303231200Smm c = lzh_decode_huffman(lt, 2304231200Smm lzh_br_bits(&bre, lt_max_bits)); 2305231200Smm lzh_br_consume(&bre, lt_bitlen[c]); 2306231200Smm } 2307231200Smm blocks_avail--; 2308231200Smm if (c > UCHAR_MAX) 2309231200Smm /* Current block is a match data. */ 2310231200Smm break; 2311231200Smm /* 2312231200Smm * 'c' is exactly a literal code. 2313231200Smm */ 2314231200Smm /* Save a decoded code to reference it 2315231200Smm * afterward. */ 2316231200Smm w_buff[w_pos] = c; 2317231200Smm if (++w_pos >= w_size) { 2318231200Smm w_pos = 0; 2319299529Smm lzh_emit_window(strm, w_size); 2320299529Smm goto next_data; 2321231200Smm } 2322231200Smm } 2323231200Smm /* 'c' is the length of a match pattern we have 2324231200Smm * already extracted, which has be stored in 2325231200Smm * window(ds->w_buff). */ 2326231200Smm copy_len = c - (UCHAR_MAX + 1) + MINMATCH; 2327231200Smm /* FALL THROUGH */ 2328231200Smm case ST_GET_POS_1: 2329231200Smm /* 2330231200Smm * Get a reference position. 2331231200Smm */ 2332231200Smm if (!lzh_br_read_ahead(strm, &bre, pt_max_bits)) { 2333231200Smm if (!last) { 2334231200Smm state = ST_GET_POS_1; 2335231200Smm ds->copy_len = copy_len; 2336231200Smm goto next_data; 2337231200Smm } 2338231200Smm copy_pos = lzh_decode_huffman(pt, 2339231200Smm lzh_br_bits_forced(&bre, pt_max_bits)); 2340231200Smm lzh_br_consume(&bre, pt_bitlen[copy_pos]); 2341231200Smm if (!lzh_br_has(&bre, 0)) 2342231200Smm goto failed;/* Over read. */ 2343231200Smm } else { 2344231200Smm copy_pos = lzh_decode_huffman(pt, 2345231200Smm lzh_br_bits(&bre, pt_max_bits)); 2346231200Smm lzh_br_consume(&bre, pt_bitlen[copy_pos]); 2347231200Smm } 2348231200Smm /* FALL THROUGH */ 2349231200Smm case ST_GET_POS_2: 2350231200Smm if (copy_pos > 1) { 2351231200Smm /* We need an additional adjustment number to 2352231200Smm * the position. */ 2353231200Smm int p = copy_pos - 1; 2354231200Smm if (!lzh_br_read_ahead(strm, &bre, p)) { 2355231200Smm if (last) 2356231200Smm goto failed;/* Truncated data.*/ 2357231200Smm state = ST_GET_POS_2; 2358231200Smm ds->copy_len = copy_len; 2359231200Smm ds->copy_pos = copy_pos; 2360231200Smm goto next_data; 2361231200Smm } 2362231200Smm copy_pos = (1 << p) + lzh_br_bits(&bre, p); 2363231200Smm lzh_br_consume(&bre, p); 2364231200Smm } 2365231200Smm /* The position is actually a distance from the last 2366231200Smm * code we had extracted and thus we have to convert 2367231200Smm * it to a position of the window. */ 2368231200Smm copy_pos = (w_pos - copy_pos - 1) & w_mask; 2369231200Smm /* FALL THROUGH */ 2370231200Smm case ST_COPY_DATA: 2371231200Smm /* 2372231200Smm * Copy `copy_len' bytes as extracted data from 2373231200Smm * the window into the output buffer. 2374231200Smm */ 2375231200Smm for (;;) { 2376231200Smm int l; 2377231200Smm 2378231200Smm l = copy_len; 2379231200Smm if (copy_pos > w_pos) { 2380231200Smm if (l > w_size - copy_pos) 2381231200Smm l = w_size - copy_pos; 2382231200Smm } else { 2383231200Smm if (l > w_size - w_pos) 2384231200Smm l = w_size - w_pos; 2385231200Smm } 2386231200Smm if ((copy_pos + l < w_pos) 2387231200Smm || (w_pos + l < copy_pos)) { 2388231200Smm /* No overlap. */ 2389231200Smm memcpy(w_buff + w_pos, 2390231200Smm w_buff + copy_pos, l); 2391231200Smm } else { 2392231200Smm const unsigned char *s; 2393231200Smm unsigned char *d; 2394231200Smm int li; 2395231200Smm 2396231200Smm d = w_buff + w_pos; 2397231200Smm s = w_buff + copy_pos; 2398299529Smm for (li = 0; li < l-1;) { 2399299529Smm d[li] = s[li];li++; 2400299529Smm d[li] = s[li];li++; 2401299529Smm } 2402299529Smm if (li < l) 2403231200Smm d[li] = s[li]; 2404231200Smm } 2405299529Smm w_pos += l; 2406299529Smm if (w_pos == w_size) { 2407299529Smm w_pos = 0; 2408299529Smm lzh_emit_window(strm, w_size); 2409299529Smm if (copy_len <= l) 2410299529Smm state = ST_GET_LITERAL; 2411299529Smm else { 2412299529Smm state = ST_COPY_DATA; 2413299529Smm ds->copy_len = copy_len - l; 2414299529Smm ds->copy_pos = 2415299529Smm (copy_pos + l) & w_mask; 2416231200Smm } 2417299529Smm goto next_data; 2418231200Smm } 2419231200Smm if (copy_len <= l) 2420231200Smm /* A copy of current pattern ended. */ 2421231200Smm break; 2422231200Smm copy_len -= l; 2423231200Smm copy_pos = (copy_pos + l) & w_mask; 2424231200Smm } 2425231200Smm state = ST_GET_LITERAL; 2426231200Smm break; 2427231200Smm } 2428231200Smm } 2429231200Smmfailed: 2430231200Smm return (ds->error = ARCHIVE_FAILED); 2431231200Smmnext_data: 2432231200Smm ds->br = bre; 2433231200Smm ds->blocks_avail = blocks_avail; 2434231200Smm ds->state = state; 2435231200Smm ds->w_pos = w_pos; 2436231200Smm return (ARCHIVE_OK); 2437231200Smm} 2438231200Smm 2439231200Smmstatic int 2440231200Smmlzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) 2441231200Smm{ 2442231200Smm int bits; 2443231200Smm 2444231200Smm if (hf->bitlen == NULL) { 2445231200Smm hf->bitlen = malloc(len_size * sizeof(hf->bitlen[0])); 2446231200Smm if (hf->bitlen == NULL) 2447231200Smm return (ARCHIVE_FATAL); 2448231200Smm } 2449231200Smm if (hf->tbl == NULL) { 2450231200Smm if (tbl_bits < HTBL_BITS) 2451231200Smm bits = tbl_bits; 2452231200Smm else 2453231200Smm bits = HTBL_BITS; 2454248616Smm hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0])); 2455231200Smm if (hf->tbl == NULL) 2456231200Smm return (ARCHIVE_FATAL); 2457231200Smm } 2458231200Smm if (hf->tree == NULL && tbl_bits > HTBL_BITS) { 2459231200Smm hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4); 2460231200Smm hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0])); 2461231200Smm if (hf->tree == NULL) 2462231200Smm return (ARCHIVE_FATAL); 2463231200Smm } 2464248616Smm hf->len_size = (int)len_size; 2465231200Smm hf->tbl_bits = tbl_bits; 2466231200Smm return (ARCHIVE_OK); 2467231200Smm} 2468231200Smm 2469231200Smmstatic void 2470231200Smmlzh_huffman_free(struct huffman *hf) 2471231200Smm{ 2472231200Smm free(hf->bitlen); 2473231200Smm free(hf->tbl); 2474231200Smm free(hf->tree); 2475231200Smm} 2476231200Smm 2477299529Smmstatic char bitlen_tbl[0x400] = { 2478299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2479299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2480299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2481299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2482299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2483299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2484299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2485299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2486299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2487299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2488299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2489299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2490299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2491299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2492299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2493299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2494299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2495299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2496299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2497299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2498299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2499299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2500299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2501299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2502299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2503299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2504299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2505299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2506299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2507299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2508299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2509299529Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2510299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2511299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2512299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2513299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2514299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2515299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2516299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2517299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2518299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2519299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2520299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2521299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2522299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2523299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2524299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2525299529Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2526299529Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2527299529Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2528299529Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2529299529Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2530299529Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2531299529Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2532299529Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2533299529Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2534299529Smm 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2535299529Smm 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2536299529Smm 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2537299529Smm 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2538299529Smm 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2539299529Smm 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2540299529Smm 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2541299529Smm 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 0 2542299529Smm}; 2543231200Smmstatic int 2544231200Smmlzh_read_pt_bitlen(struct lzh_stream *strm, int start, int end) 2545231200Smm{ 2546231200Smm struct lzh_dec *ds = strm->ds; 2547299529Smm struct lzh_br *br = &(ds->br); 2548231200Smm int c, i; 2549231200Smm 2550299529Smm for (i = start; i < end; ) { 2551231200Smm /* 2552231200Smm * bit pattern the number we need 2553231200Smm * 000 -> 0 2554231200Smm * 001 -> 1 2555231200Smm * 010 -> 2 2556231200Smm * ... 2557231200Smm * 110 -> 6 2558231200Smm * 1110 -> 7 2559231200Smm * 11110 -> 8 2560231200Smm * ... 2561231200Smm * 1111111111110 -> 16 2562231200Smm */ 2563231200Smm if (!lzh_br_read_ahead(strm, br, 3)) 2564231200Smm return (i); 2565231200Smm if ((c = lzh_br_bits(br, 3)) == 7) { 2566231200Smm if (!lzh_br_read_ahead(strm, br, 13)) 2567231200Smm return (i); 2568299529Smm c = bitlen_tbl[lzh_br_bits(br, 13) & 0x3FF]; 2569299529Smm if (c) 2570299529Smm lzh_br_consume(br, c - 3); 2571299529Smm else 2572231200Smm return (-1);/* Invalid data. */ 2573231200Smm } else 2574231200Smm lzh_br_consume(br, 3); 2575231200Smm ds->pt.bitlen[i++] = c; 2576231200Smm ds->pt.freq[c]++; 2577231200Smm } 2578231200Smm return (i); 2579231200Smm} 2580231200Smm 2581231200Smmstatic int 2582231200Smmlzh_make_fake_table(struct huffman *hf, uint16_t c) 2583231200Smm{ 2584231200Smm if (c >= hf->len_size) 2585231200Smm return (0); 2586231200Smm hf->tbl[0] = c; 2587231200Smm hf->max_bits = 0; 2588231200Smm hf->shift_bits = 0; 2589231200Smm hf->bitlen[hf->tbl[0]] = 0; 2590231200Smm return (1); 2591231200Smm} 2592231200Smm 2593231200Smm/* 2594231200Smm * Make a huffman coding table. 2595231200Smm */ 2596231200Smmstatic int 2597231200Smmlzh_make_huffman_table(struct huffman *hf) 2598231200Smm{ 2599231200Smm uint16_t *tbl; 2600231200Smm const unsigned char *bitlen; 2601231200Smm int bitptn[17], weight[17]; 2602231200Smm int i, maxbits = 0, ptn, tbl_size, w; 2603231200Smm int diffbits, len_avail; 2604231200Smm 2605231200Smm /* 2606231200Smm * Initialize bit patterns. 2607231200Smm */ 2608231200Smm ptn = 0; 2609231200Smm for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) { 2610231200Smm bitptn[i] = ptn; 2611231200Smm weight[i] = w; 2612231200Smm if (hf->freq[i]) { 2613231200Smm ptn += hf->freq[i] * w; 2614231200Smm maxbits = i; 2615231200Smm } 2616231200Smm } 2617231200Smm if (ptn != 0x10000 || maxbits > hf->tbl_bits) 2618231200Smm return (0);/* Invalid */ 2619231200Smm 2620231200Smm hf->max_bits = maxbits; 2621231200Smm 2622231200Smm /* 2623231200Smm * Cut out extra bits which we won't house in the table. 2624231200Smm * This preparation reduces the same calculation in the for-loop 2625231200Smm * making the table. 2626231200Smm */ 2627231200Smm if (maxbits < 16) { 2628231200Smm int ebits = 16 - maxbits; 2629231200Smm for (i = 1; i <= maxbits; i++) { 2630231200Smm bitptn[i] >>= ebits; 2631231200Smm weight[i] >>= ebits; 2632231200Smm } 2633231200Smm } 2634231200Smm if (maxbits > HTBL_BITS) { 2635299529Smm unsigned htbl_max; 2636231200Smm uint16_t *p; 2637231200Smm 2638231200Smm diffbits = maxbits - HTBL_BITS; 2639231200Smm for (i = 1; i <= HTBL_BITS; i++) { 2640231200Smm bitptn[i] >>= diffbits; 2641231200Smm weight[i] >>= diffbits; 2642231200Smm } 2643231200Smm htbl_max = bitptn[HTBL_BITS] + 2644231200Smm weight[HTBL_BITS] * hf->freq[HTBL_BITS]; 2645231200Smm p = &(hf->tbl[htbl_max]); 2646231200Smm while (p < &hf->tbl[1U<<HTBL_BITS]) 2647231200Smm *p++ = 0; 2648231200Smm } else 2649231200Smm diffbits = 0; 2650231200Smm hf->shift_bits = diffbits; 2651231200Smm 2652231200Smm /* 2653231200Smm * Make the table. 2654231200Smm */ 2655231200Smm tbl_size = 1 << HTBL_BITS; 2656231200Smm tbl = hf->tbl; 2657231200Smm bitlen = hf->bitlen; 2658231200Smm len_avail = hf->len_avail; 2659231200Smm hf->tree_used = 0; 2660231200Smm for (i = 0; i < len_avail; i++) { 2661231200Smm uint16_t *p; 2662231200Smm int len, cnt; 2663231200Smm uint16_t bit; 2664231200Smm int extlen; 2665231200Smm struct htree_t *ht; 2666231200Smm 2667231200Smm if (bitlen[i] == 0) 2668231200Smm continue; 2669231200Smm /* Get a bit pattern */ 2670231200Smm len = bitlen[i]; 2671231200Smm ptn = bitptn[len]; 2672231200Smm cnt = weight[len]; 2673231200Smm if (len <= HTBL_BITS) { 2674231200Smm /* Calculate next bit pattern */ 2675231200Smm if ((bitptn[len] = ptn + cnt) > tbl_size) 2676231200Smm return (0);/* Invalid */ 2677231200Smm /* Update the table */ 2678231200Smm p = &(tbl[ptn]); 2679299529Smm if (cnt > 7) { 2680299529Smm uint16_t *pc; 2681299529Smm 2682299529Smm cnt -= 8; 2683299529Smm pc = &p[cnt]; 2684299529Smm pc[0] = (uint16_t)i; 2685299529Smm pc[1] = (uint16_t)i; 2686299529Smm pc[2] = (uint16_t)i; 2687299529Smm pc[3] = (uint16_t)i; 2688299529Smm pc[4] = (uint16_t)i; 2689299529Smm pc[5] = (uint16_t)i; 2690299529Smm pc[6] = (uint16_t)i; 2691299529Smm pc[7] = (uint16_t)i; 2692299529Smm if (cnt > 7) { 2693299529Smm cnt -= 8; 2694299529Smm memcpy(&p[cnt], pc, 2695299529Smm 8 * sizeof(uint16_t)); 2696299529Smm pc = &p[cnt]; 2697299529Smm while (cnt > 15) { 2698299529Smm cnt -= 16; 2699299529Smm memcpy(&p[cnt], pc, 2700299529Smm 16 * sizeof(uint16_t)); 2701299529Smm } 2702299529Smm } 2703299529Smm if (cnt) 2704299529Smm memcpy(p, pc, cnt * sizeof(uint16_t)); 2705299529Smm } else { 2706299529Smm while (cnt > 1) { 2707299529Smm p[--cnt] = (uint16_t)i; 2708299529Smm p[--cnt] = (uint16_t)i; 2709299529Smm } 2710299529Smm if (cnt) 2711299529Smm p[--cnt] = (uint16_t)i; 2712299529Smm } 2713231200Smm continue; 2714231200Smm } 2715231200Smm 2716231200Smm /* 2717231200Smm * A bit length is too big to be housed to a direct table, 2718231200Smm * so we use a tree model for its extra bits. 2719231200Smm */ 2720231200Smm bitptn[len] = ptn + cnt; 2721231200Smm bit = 1U << (diffbits -1); 2722231200Smm extlen = len - HTBL_BITS; 2723231200Smm 2724231200Smm p = &(tbl[ptn >> diffbits]); 2725231200Smm if (*p == 0) { 2726231200Smm *p = len_avail + hf->tree_used; 2727231200Smm ht = &(hf->tree[hf->tree_used++]); 2728231200Smm if (hf->tree_used > hf->tree_avail) 2729231200Smm return (0);/* Invalid */ 2730231200Smm ht->left = 0; 2731231200Smm ht->right = 0; 2732231200Smm } else { 2733231200Smm if (*p < len_avail || 2734231200Smm *p >= (len_avail + hf->tree_used)) 2735231200Smm return (0);/* Invalid */ 2736231200Smm ht = &(hf->tree[*p - len_avail]); 2737231200Smm } 2738231200Smm while (--extlen > 0) { 2739231200Smm if (ptn & bit) { 2740231200Smm if (ht->left < len_avail) { 2741231200Smm ht->left = len_avail + hf->tree_used; 2742231200Smm ht = &(hf->tree[hf->tree_used++]); 2743231200Smm if (hf->tree_used > hf->tree_avail) 2744231200Smm return (0);/* Invalid */ 2745231200Smm ht->left = 0; 2746231200Smm ht->right = 0; 2747231200Smm } else { 2748231200Smm ht = &(hf->tree[ht->left - len_avail]); 2749231200Smm } 2750231200Smm } else { 2751231200Smm if (ht->right < len_avail) { 2752231200Smm ht->right = len_avail + hf->tree_used; 2753231200Smm ht = &(hf->tree[hf->tree_used++]); 2754231200Smm if (hf->tree_used > hf->tree_avail) 2755231200Smm return (0);/* Invalid */ 2756231200Smm ht->left = 0; 2757231200Smm ht->right = 0; 2758231200Smm } else { 2759231200Smm ht = &(hf->tree[ht->right - len_avail]); 2760231200Smm } 2761231200Smm } 2762231200Smm bit >>= 1; 2763231200Smm } 2764231200Smm if (ptn & bit) { 2765231200Smm if (ht->left != 0) 2766231200Smm return (0);/* Invalid */ 2767231200Smm ht->left = (uint16_t)i; 2768231200Smm } else { 2769231200Smm if (ht->right != 0) 2770231200Smm return (0);/* Invalid */ 2771231200Smm ht->right = (uint16_t)i; 2772231200Smm } 2773231200Smm } 2774231200Smm return (1); 2775231200Smm} 2776231200Smm 2777231200Smmstatic int 2778231200Smmlzh_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c) 2779231200Smm{ 2780231200Smm struct htree_t *ht; 2781231200Smm int extlen; 2782231200Smm 2783231200Smm ht = hf->tree; 2784231200Smm extlen = hf->shift_bits; 2785231200Smm while (c >= hf->len_avail) { 2786231200Smm c -= hf->len_avail; 2787231200Smm if (extlen-- <= 0 || c >= hf->tree_used) 2788231200Smm return (0); 2789231200Smm if (rbits & (1U << extlen)) 2790231200Smm c = ht[c].left; 2791231200Smm else 2792231200Smm c = ht[c].right; 2793231200Smm } 2794231200Smm return (c); 2795231200Smm} 2796231200Smm 2797231200Smmstatic inline int 2798231200Smmlzh_decode_huffman(struct huffman *hf, unsigned rbits) 2799231200Smm{ 2800231200Smm int c; 2801231200Smm /* 2802231200Smm * At first search an index table for a bit pattern. 2803231200Smm * If it fails, search a huffman tree for. 2804231200Smm */ 2805231200Smm c = hf->tbl[rbits >> hf->shift_bits]; 2806299529Smm if (c < hf->len_avail || hf->len_avail == 0) 2807231200Smm return (c); 2808231200Smm /* This bit pattern needs to be found out at a huffman tree. */ 2809231200Smm return (lzh_decode_huffman_tree(hf, rbits, c)); 2810231200Smm} 2811231200Smm 2812