1231200Smm/*- 2302001Smm * 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; 140302001Smm int avail_in; 141231200Smm int64_t total_in; 142302001Smm const unsigned char *ref_ptr; 143302001Smm 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; 178358090Smm /* dirname and filename could be in different codepages */ 179358090Smm struct archive_string_conv *sconv_dir; 180358090Smm struct archive_string_conv *sconv_fname; 181231200Smm struct archive_string_conv *opt_sconv; 182231200Smm 183231200Smm struct archive_string dirname; 184231200Smm struct archive_string filename; 185231200Smm struct archive_wstring ws; 186231200Smm 187231200Smm unsigned char dos_attr; 188231200Smm 189231200Smm /* Flag to mark progress that an archive was read their first header.*/ 190231200Smm char found_first_header; 191231200Smm /* Flag to mark that indicates an empty directory. */ 192231200Smm char directory; 193231200Smm 194231200Smm /* Flags to mark progress of decompression. */ 195231200Smm char decompress_init; 196231200Smm char end_of_entry; 197231200Smm char end_of_entry_cleanup; 198231200Smm char entry_is_compressed; 199231200Smm 200231200Smm char format_name[64]; 201231200Smm 202231200Smm struct lzh_stream strm; 203231200Smm}; 204231200Smm 205231200Smm/* 206231200Smm * LHA header common member offset. 207231200Smm */ 208231200Smm#define H_METHOD_OFFSET 2 /* Compress type. */ 209231200Smm#define H_ATTR_OFFSET 19 /* DOS attribute. */ 210231200Smm#define H_LEVEL_OFFSET 20 /* Header Level. */ 211231200Smm#define H_SIZE 22 /* Minimum header size. */ 212231200Smm 213231200Smmstatic int archive_read_format_lha_bid(struct archive_read *, int); 214231200Smmstatic int archive_read_format_lha_options(struct archive_read *, 215231200Smm const char *, const char *); 216231200Smmstatic int archive_read_format_lha_read_header(struct archive_read *, 217231200Smm struct archive_entry *); 218231200Smmstatic int archive_read_format_lha_read_data(struct archive_read *, 219231200Smm const void **, size_t *, int64_t *); 220231200Smmstatic int archive_read_format_lha_read_data_skip(struct archive_read *); 221231200Smmstatic int archive_read_format_lha_cleanup(struct archive_read *); 222231200Smm 223231200Smmstatic void lha_replace_path_separator(struct lha *, 224231200Smm struct archive_entry *); 225231200Smmstatic int lha_read_file_header_0(struct archive_read *, struct lha *); 226231200Smmstatic int lha_read_file_header_1(struct archive_read *, struct lha *); 227231200Smmstatic int lha_read_file_header_2(struct archive_read *, struct lha *); 228231200Smmstatic int lha_read_file_header_3(struct archive_read *, struct lha *); 229231200Smmstatic int lha_read_file_extended_header(struct archive_read *, 230231200Smm struct lha *, uint16_t *, int, size_t, size_t *); 231231200Smmstatic size_t lha_check_header_format(const void *); 232231200Smmstatic int lha_skip_sfx(struct archive_read *); 233231200Smmstatic time_t lha_dos_time(const unsigned char *); 234231200Smmstatic time_t lha_win_time(uint64_t, long *); 235231200Smmstatic unsigned char lha_calcsum(unsigned char, const void *, 236248616Smm int, size_t); 237358090Smmstatic int lha_parse_linkname(struct archive_wstring *, 238358090Smm struct archive_wstring *); 239231200Smmstatic int lha_read_data_none(struct archive_read *, const void **, 240231200Smm size_t *, int64_t *); 241231200Smmstatic int lha_read_data_lzh(struct archive_read *, const void **, 242231200Smm size_t *, int64_t *); 243302001Smmstatic void lha_crc16_init(void); 244231200Smmstatic uint16_t lha_crc16(uint16_t, const void *, size_t); 245231200Smmstatic int lzh_decode_init(struct lzh_stream *, const char *); 246231200Smmstatic void lzh_decode_free(struct lzh_stream *); 247231200Smmstatic int lzh_decode(struct lzh_stream *, int); 248231200Smmstatic int lzh_br_fillup(struct lzh_stream *, struct lzh_br *); 249231200Smmstatic int lzh_huffman_init(struct huffman *, size_t, int); 250231200Smmstatic void lzh_huffman_free(struct huffman *); 251231200Smmstatic int lzh_read_pt_bitlen(struct lzh_stream *, int start, int end); 252231200Smmstatic int lzh_make_fake_table(struct huffman *, uint16_t); 253231200Smmstatic int lzh_make_huffman_table(struct huffman *); 254232153Smmstatic inline int lzh_decode_huffman(struct huffman *, unsigned); 255231200Smmstatic int lzh_decode_huffman_tree(struct huffman *, unsigned, int); 256231200Smm 257231200Smm 258231200Smmint 259231200Smmarchive_read_support_format_lha(struct archive *_a) 260231200Smm{ 261231200Smm struct archive_read *a = (struct archive_read *)_a; 262231200Smm struct lha *lha; 263231200Smm int r; 264231200Smm 265231200Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 266231200Smm ARCHIVE_STATE_NEW, "archive_read_support_format_lha"); 267231200Smm 268231200Smm lha = (struct lha *)calloc(1, sizeof(*lha)); 269231200Smm if (lha == NULL) { 270231200Smm archive_set_error(&a->archive, ENOMEM, 271231200Smm "Can't allocate lha data"); 272231200Smm return (ARCHIVE_FATAL); 273231200Smm } 274231200Smm archive_string_init(&lha->ws); 275231200Smm 276231200Smm r = __archive_read_register_format(a, 277231200Smm lha, 278231200Smm "lha", 279231200Smm archive_read_format_lha_bid, 280231200Smm archive_read_format_lha_options, 281231200Smm archive_read_format_lha_read_header, 282231200Smm archive_read_format_lha_read_data, 283231200Smm archive_read_format_lha_read_data_skip, 284248616Smm NULL, 285302001Smm archive_read_format_lha_cleanup, 286302001Smm NULL, 287302001Smm NULL); 288231200Smm 289231200Smm if (r != ARCHIVE_OK) 290231200Smm free(lha); 291231200Smm return (ARCHIVE_OK); 292231200Smm} 293231200Smm 294231200Smmstatic size_t 295231200Smmlha_check_header_format(const void *h) 296231200Smm{ 297231200Smm const unsigned char *p = h; 298231200Smm size_t next_skip_bytes; 299231200Smm 300231200Smm switch (p[H_METHOD_OFFSET+3]) { 301231200Smm /* 302231200Smm * "-lh0-" ... "-lh7-" "-lhd-" 303231200Smm * "-lzs-" "-lz5-" 304231200Smm */ 305231200Smm case '0': case '1': case '2': case '3': 306231200Smm case '4': case '5': case '6': case '7': 307231200Smm case 'd': 308231200Smm case 's': 309231200Smm next_skip_bytes = 4; 310231200Smm 311231200Smm /* b0 == 0 means the end of an LHa archive file. */ 312231200Smm if (p[0] == 0) 313231200Smm break; 314231200Smm if (p[H_METHOD_OFFSET] != '-' || p[H_METHOD_OFFSET+1] != 'l' 315231200Smm || p[H_METHOD_OFFSET+4] != '-') 316231200Smm break; 317231200Smm 318231200Smm if (p[H_METHOD_OFFSET+2] == 'h') { 319231200Smm /* "-lh?-" */ 320231200Smm if (p[H_METHOD_OFFSET+3] == 's') 321231200Smm break; 322231200Smm if (p[H_LEVEL_OFFSET] == 0) 323231200Smm return (0); 324231200Smm if (p[H_LEVEL_OFFSET] <= 3 && p[H_ATTR_OFFSET] == 0x20) 325231200Smm return (0); 326231200Smm } 327231200Smm if (p[H_METHOD_OFFSET+2] == 'z') { 328231200Smm /* LArc extensions: -lzs-,-lz4- and -lz5- */ 329231200Smm if (p[H_LEVEL_OFFSET] != 0) 330231200Smm break; 331231200Smm if (p[H_METHOD_OFFSET+3] == 's' 332231200Smm || p[H_METHOD_OFFSET+3] == '4' 333231200Smm || p[H_METHOD_OFFSET+3] == '5') 334231200Smm return (0); 335231200Smm } 336231200Smm break; 337231200Smm case 'h': next_skip_bytes = 1; break; 338231200Smm case 'z': next_skip_bytes = 1; break; 339231200Smm case 'l': next_skip_bytes = 2; break; 340231200Smm case '-': next_skip_bytes = 3; break; 341231200Smm default : next_skip_bytes = 4; break; 342231200Smm } 343231200Smm 344231200Smm return (next_skip_bytes); 345231200Smm} 346231200Smm 347231200Smmstatic int 348231200Smmarchive_read_format_lha_bid(struct archive_read *a, int best_bid) 349231200Smm{ 350231200Smm const char *p; 351231200Smm const void *buff; 352231200Smm ssize_t bytes_avail, offset, window; 353231200Smm size_t next; 354231200Smm 355231200Smm /* If there's already a better bid than we can ever 356231200Smm make, don't bother testing. */ 357231200Smm if (best_bid > 30) 358231200Smm return (-1); 359231200Smm 360231200Smm if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) 361231200Smm return (-1); 362231200Smm 363231200Smm if (lha_check_header_format(p) == 0) 364231200Smm return (30); 365231200Smm 366231200Smm if (p[0] == 'M' && p[1] == 'Z') { 367231200Smm /* PE file */ 368231200Smm offset = 0; 369231200Smm window = 4096; 370231200Smm while (offset < (1024 * 20)) { 371231200Smm buff = __archive_read_ahead(a, offset + window, 372231200Smm &bytes_avail); 373231200Smm if (buff == NULL) { 374231200Smm /* Remaining bytes are less than window. */ 375231200Smm window >>= 1; 376231200Smm if (window < (H_SIZE + 3)) 377231200Smm return (0); 378231200Smm continue; 379231200Smm } 380231200Smm p = (const char *)buff + offset; 381231200Smm while (p + H_SIZE < (const char *)buff + bytes_avail) { 382231200Smm if ((next = lha_check_header_format(p)) == 0) 383231200Smm return (30); 384231200Smm p += next; 385231200Smm } 386231200Smm offset = p - (const char *)buff; 387231200Smm } 388231200Smm } 389231200Smm return (0); 390231200Smm} 391231200Smm 392231200Smmstatic int 393231200Smmarchive_read_format_lha_options(struct archive_read *a, 394231200Smm const char *key, const char *val) 395231200Smm{ 396231200Smm struct lha *lha; 397231200Smm int ret = ARCHIVE_FAILED; 398231200Smm 399231200Smm lha = (struct lha *)(a->format->data); 400231200Smm if (strcmp(key, "hdrcharset") == 0) { 401231200Smm if (val == NULL || val[0] == 0) 402231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 403231200Smm "lha: hdrcharset option needs a character-set name"); 404231200Smm else { 405231200Smm lha->opt_sconv = 406231200Smm archive_string_conversion_from_charset( 407231200Smm &a->archive, val, 0); 408231200Smm if (lha->opt_sconv != NULL) 409231200Smm ret = ARCHIVE_OK; 410231200Smm else 411231200Smm ret = ARCHIVE_FATAL; 412231200Smm } 413232153Smm return (ret); 414232153Smm } 415231200Smm 416232153Smm /* Note: The "warn" return is just to inform the options 417232153Smm * supervisor that we didn't handle it. It will generate 418232153Smm * a suitable error if no one used this option. */ 419232153Smm return (ARCHIVE_WARN); 420231200Smm} 421231200Smm 422231200Smmstatic int 423231200Smmlha_skip_sfx(struct archive_read *a) 424231200Smm{ 425231200Smm const void *h; 426231200Smm const char *p, *q; 427231200Smm size_t next, skip; 428231200Smm ssize_t bytes, window; 429231200Smm 430231200Smm window = 4096; 431231200Smm for (;;) { 432231200Smm h = __archive_read_ahead(a, window, &bytes); 433231200Smm if (h == NULL) { 434231200Smm /* Remaining bytes are less than window. */ 435231200Smm window >>= 1; 436231200Smm if (window < (H_SIZE + 3)) 437231200Smm goto fatal; 438231200Smm continue; 439231200Smm } 440231200Smm if (bytes < H_SIZE) 441231200Smm goto fatal; 442231200Smm p = h; 443231200Smm q = p + bytes; 444231200Smm 445231200Smm /* 446231200Smm * Scan ahead until we find something that looks 447231200Smm * like the lha header. 448231200Smm */ 449231200Smm while (p + H_SIZE < q) { 450231200Smm if ((next = lha_check_header_format(p)) == 0) { 451231200Smm skip = p - (const char *)h; 452231200Smm __archive_read_consume(a, skip); 453231200Smm return (ARCHIVE_OK); 454231200Smm } 455231200Smm p += next; 456231200Smm } 457231200Smm skip = p - (const char *)h; 458231200Smm __archive_read_consume(a, skip); 459231200Smm } 460231200Smmfatal: 461231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 462231200Smm "Couldn't find out LHa header"); 463231200Smm return (ARCHIVE_FATAL); 464231200Smm} 465231200Smm 466231200Smmstatic int 467231200Smmtruncated_error(struct archive_read *a) 468231200Smm{ 469231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 470231200Smm "Truncated LHa header"); 471231200Smm return (ARCHIVE_FATAL); 472231200Smm} 473231200Smm 474231200Smmstatic int 475231200Smmarchive_read_format_lha_read_header(struct archive_read *a, 476231200Smm struct archive_entry *entry) 477231200Smm{ 478358090Smm struct archive_wstring linkname; 479358090Smm struct archive_wstring pathname; 480231200Smm struct lha *lha; 481231200Smm const unsigned char *p; 482231200Smm const char *signature; 483231200Smm int err; 484358090Smm struct archive_mstring conv_buffer; 485358090Smm const wchar_t *conv_buffer_p; 486358090Smm 487302001Smm lha_crc16_init(); 488302001Smm 489231200Smm a->archive.archive_format = ARCHIVE_FORMAT_LHA; 490231200Smm if (a->archive.archive_format_name == NULL) 491231200Smm a->archive.archive_format_name = "lha"; 492231200Smm 493231200Smm lha = (struct lha *)(a->format->data); 494231200Smm lha->decompress_init = 0; 495231200Smm lha->end_of_entry = 0; 496231200Smm lha->end_of_entry_cleanup = 0; 497231200Smm lha->entry_unconsumed = 0; 498231200Smm 499231200Smm if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) { 500231200Smm /* 501231200Smm * LHa archiver added 0 to the tail of its archive file as 502231200Smm * the mark of the end of the archive. 503231200Smm */ 504231200Smm signature = __archive_read_ahead(a, sizeof(signature[0]), NULL); 505231200Smm if (signature == NULL || signature[0] == 0) 506231200Smm return (ARCHIVE_EOF); 507231200Smm return (truncated_error(a)); 508231200Smm } 509231200Smm 510231200Smm signature = (const char *)p; 511231200Smm if (lha->found_first_header == 0 && 512231200Smm signature[0] == 'M' && signature[1] == 'Z') { 513231200Smm /* This is an executable? Must be self-extracting... */ 514231200Smm err = lha_skip_sfx(a); 515231200Smm if (err < ARCHIVE_WARN) 516231200Smm return (err); 517231200Smm 518231200Smm if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL) 519231200Smm return (truncated_error(a)); 520231200Smm signature = (const char *)p; 521231200Smm } 522231200Smm /* signature[0] == 0 means the end of an LHa archive file. */ 523231200Smm if (signature[0] == 0) 524231200Smm return (ARCHIVE_EOF); 525231200Smm 526231200Smm /* 527231200Smm * Check the header format and method type. 528231200Smm */ 529231200Smm if (lha_check_header_format(p) != 0) { 530231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 531231200Smm "Bad LHa file"); 532231200Smm return (ARCHIVE_FATAL); 533231200Smm } 534231200Smm 535231200Smm /* We've found the first header. */ 536231200Smm lha->found_first_header = 1; 537231200Smm /* Set a default value and common data */ 538231200Smm lha->header_size = 0; 539231200Smm lha->level = p[H_LEVEL_OFFSET]; 540231200Smm lha->method[0] = p[H_METHOD_OFFSET+1]; 541231200Smm lha->method[1] = p[H_METHOD_OFFSET+2]; 542231200Smm lha->method[2] = p[H_METHOD_OFFSET+3]; 543231200Smm if (memcmp(lha->method, "lhd", 3) == 0) 544231200Smm lha->directory = 1; 545231200Smm else 546231200Smm lha->directory = 0; 547231200Smm if (memcmp(lha->method, "lh0", 3) == 0 || 548231200Smm memcmp(lha->method, "lz4", 3) == 0) 549231200Smm lha->entry_is_compressed = 0; 550231200Smm else 551231200Smm lha->entry_is_compressed = 1; 552231200Smm 553231200Smm lha->compsize = 0; 554231200Smm lha->origsize = 0; 555231200Smm lha->setflag = 0; 556231200Smm lha->birthtime = 0; 557231200Smm lha->birthtime_tv_nsec = 0; 558231200Smm lha->mtime = 0; 559231200Smm lha->mtime_tv_nsec = 0; 560231200Smm lha->atime = 0; 561231200Smm lha->atime_tv_nsec = 0; 562231200Smm lha->mode = (lha->directory)? 0777 : 0666; 563231200Smm lha->uid = 0; 564231200Smm lha->gid = 0; 565231200Smm archive_string_empty(&lha->dirname); 566231200Smm archive_string_empty(&lha->filename); 567231200Smm lha->dos_attr = 0; 568358090Smm if (lha->opt_sconv != NULL) { 569358090Smm lha->sconv_dir = lha->opt_sconv; 570358090Smm lha->sconv_fname = lha->opt_sconv; 571358090Smm } else { 572358090Smm lha->sconv_dir = NULL; 573358090Smm lha->sconv_fname = NULL; 574358090Smm } 575231200Smm 576231200Smm switch (p[H_LEVEL_OFFSET]) { 577231200Smm case 0: 578231200Smm err = lha_read_file_header_0(a, lha); 579231200Smm break; 580231200Smm case 1: 581231200Smm err = lha_read_file_header_1(a, lha); 582231200Smm break; 583231200Smm case 2: 584231200Smm err = lha_read_file_header_2(a, lha); 585231200Smm break; 586231200Smm case 3: 587231200Smm err = lha_read_file_header_3(a, lha); 588231200Smm break; 589231200Smm default: 590231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 591231200Smm "Unsupported LHa header level %d", p[H_LEVEL_OFFSET]); 592231200Smm err = ARCHIVE_FATAL; 593231200Smm break; 594231200Smm } 595231200Smm if (err < ARCHIVE_WARN) 596231200Smm return (err); 597231200Smm 598231200Smm 599231200Smm if (!lha->directory && archive_strlen(&lha->filename) == 0) 600231200Smm /* The filename has not been set */ 601231200Smm return (truncated_error(a)); 602231200Smm 603231200Smm /* 604358090Smm * Make a pathname from a dirname and a filename, after converting to Unicode. 605358090Smm * This is because codepages might differ between dirname and filename. 606358090Smm */ 607231200Smm archive_string_init(&pathname); 608231200Smm archive_string_init(&linkname); 609358090Smm archive_string_init(&conv_buffer.aes_mbs); 610358090Smm archive_string_init(&conv_buffer.aes_mbs_in_locale); 611358090Smm archive_string_init(&conv_buffer.aes_utf8); 612358090Smm archive_string_init(&conv_buffer.aes_wcs); 613358090Smm if (0 != archive_mstring_copy_mbs_len_l(&conv_buffer, lha->dirname.s, lha->dirname.length, lha->sconv_dir)) { 614358090Smm archive_set_error(&a->archive, 615358090Smm ARCHIVE_ERRNO_FILE_FORMAT, 616358090Smm "Pathname cannot be converted " 617358090Smm "from %s to Unicode.", 618358090Smm archive_string_conversion_charset_name(lha->sconv_dir)); 619358090Smm err = ARCHIVE_FATAL; 620358090Smm } else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p)) 621358090Smm err = ARCHIVE_FATAL; 622358090Smm if (err == ARCHIVE_FATAL) { 623358090Smm archive_mstring_clean(&conv_buffer); 624358090Smm archive_wstring_free(&pathname); 625358090Smm archive_wstring_free(&linkname); 626358090Smm return (err); 627358090Smm } 628358090Smm archive_wstring_copy(&pathname, &conv_buffer.aes_wcs); 629231200Smm 630358090Smm archive_string_empty(&conv_buffer.aes_mbs); 631358090Smm archive_string_empty(&conv_buffer.aes_mbs_in_locale); 632358090Smm archive_string_empty(&conv_buffer.aes_utf8); 633358090Smm archive_wstring_empty(&conv_buffer.aes_wcs); 634358090Smm if (0 != archive_mstring_copy_mbs_len_l(&conv_buffer, lha->filename.s, lha->filename.length, lha->sconv_fname)) { 635358090Smm archive_set_error(&a->archive, 636358090Smm ARCHIVE_ERRNO_FILE_FORMAT, 637358090Smm "Pathname cannot be converted " 638358090Smm "from %s to Unicode.", 639358090Smm archive_string_conversion_charset_name(lha->sconv_fname)); 640358090Smm err = ARCHIVE_FATAL; 641358090Smm } 642358090Smm else if (0 != archive_mstring_get_wcs(&a->archive, &conv_buffer, &conv_buffer_p)) 643358090Smm err = ARCHIVE_FATAL; 644358090Smm if (err == ARCHIVE_FATAL) { 645358090Smm archive_mstring_clean(&conv_buffer); 646358090Smm archive_wstring_free(&pathname); 647358090Smm archive_wstring_free(&linkname); 648358090Smm return (err); 649358090Smm } 650358090Smm archive_wstring_concat(&pathname, &conv_buffer.aes_wcs); 651358090Smm archive_mstring_clean(&conv_buffer); 652358090Smm 653231200Smm if ((lha->mode & AE_IFMT) == AE_IFLNK) { 654231200Smm /* 655231200Smm * Extract the symlink-name if it's included in the pathname. 656231200Smm */ 657231200Smm if (!lha_parse_linkname(&linkname, &pathname)) { 658231200Smm /* We couldn't get the symlink-name. */ 659231200Smm archive_set_error(&a->archive, 660231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 661231200Smm "Unknown symlink-name"); 662358090Smm archive_wstring_free(&pathname); 663358090Smm archive_wstring_free(&linkname); 664231200Smm return (ARCHIVE_FAILED); 665231200Smm } 666231200Smm } else { 667231200Smm /* 668231200Smm * Make sure a file-type is set. 669231200Smm * The mode has been overridden if it is in the extended data. 670231200Smm */ 671231200Smm lha->mode = (lha->mode & ~AE_IFMT) | 672231200Smm ((lha->directory)? AE_IFDIR: AE_IFREG); 673231200Smm } 674231200Smm if ((lha->setflag & UNIX_MODE_IS_SET) == 0 && 675231200Smm (lha->dos_attr & 1) != 0) 676231200Smm lha->mode &= ~(0222);/* read only. */ 677231200Smm 678231200Smm /* 679231200Smm * Set basic file parameters. 680231200Smm */ 681358090Smm archive_entry_copy_pathname_w(entry, pathname.s); 682358090Smm archive_wstring_free(&pathname); 683231200Smm if (archive_strlen(&linkname) > 0) { 684358090Smm archive_entry_copy_symlink_w(entry, linkname.s); 685231200Smm } else 686231200Smm archive_entry_set_symlink(entry, NULL); 687358090Smm archive_wstring_free(&linkname); 688231200Smm /* 689231200Smm * When a header level is 0, there is a possibility that 690231200Smm * a pathname and a symlink has '\' character, a directory 691231200Smm * separator in DOS/Windows. So we should convert it to '/'. 692231200Smm */ 693231200Smm if (p[H_LEVEL_OFFSET] == 0) 694231200Smm lha_replace_path_separator(lha, entry); 695231200Smm 696231200Smm archive_entry_set_mode(entry, lha->mode); 697231200Smm archive_entry_set_uid(entry, lha->uid); 698231200Smm archive_entry_set_gid(entry, lha->gid); 699231200Smm if (archive_strlen(&lha->uname) > 0) 700231200Smm archive_entry_set_uname(entry, lha->uname.s); 701231200Smm if (archive_strlen(&lha->gname) > 0) 702231200Smm archive_entry_set_gname(entry, lha->gname.s); 703231200Smm if (lha->setflag & BIRTHTIME_IS_SET) { 704231200Smm archive_entry_set_birthtime(entry, lha->birthtime, 705231200Smm lha->birthtime_tv_nsec); 706231200Smm archive_entry_set_ctime(entry, lha->birthtime, 707231200Smm lha->birthtime_tv_nsec); 708231200Smm } else { 709231200Smm archive_entry_unset_birthtime(entry); 710231200Smm archive_entry_unset_ctime(entry); 711231200Smm } 712231200Smm archive_entry_set_mtime(entry, lha->mtime, lha->mtime_tv_nsec); 713231200Smm if (lha->setflag & ATIME_IS_SET) 714231200Smm archive_entry_set_atime(entry, lha->atime, 715231200Smm lha->atime_tv_nsec); 716231200Smm else 717231200Smm archive_entry_unset_atime(entry); 718231200Smm if (lha->directory || archive_entry_symlink(entry) != NULL) 719231200Smm archive_entry_unset_size(entry); 720231200Smm else 721231200Smm archive_entry_set_size(entry, lha->origsize); 722231200Smm 723231200Smm /* 724231200Smm * Prepare variables used to read a file content. 725231200Smm */ 726231200Smm lha->entry_bytes_remaining = lha->compsize; 727337352Smm if (lha->entry_bytes_remaining < 0) { 728337352Smm archive_set_error(&a->archive, 729337352Smm ARCHIVE_ERRNO_FILE_FORMAT, 730337352Smm "Invalid LHa entry size"); 731337352Smm return (ARCHIVE_FATAL); 732337352Smm } 733231200Smm lha->entry_offset = 0; 734231200Smm lha->entry_crc_calculated = 0; 735231200Smm 736231200Smm /* 737231200Smm * This file does not have a content. 738231200Smm */ 739231200Smm if (lha->directory || lha->compsize == 0) 740231200Smm lha->end_of_entry = 1; 741231200Smm 742231200Smm sprintf(lha->format_name, "lha -%c%c%c-", 743231200Smm lha->method[0], lha->method[1], lha->method[2]); 744231200Smm a->archive.archive_format_name = lha->format_name; 745231200Smm 746231200Smm return (err); 747231200Smm} 748231200Smm 749231200Smm/* 750231200Smm * Replace a DOS path separator '\' by a character '/'. 751231200Smm * Some multi-byte character set have a character '\' in its second byte. 752231200Smm */ 753231200Smmstatic void 754231200Smmlha_replace_path_separator(struct lha *lha, struct archive_entry *entry) 755231200Smm{ 756231200Smm const wchar_t *wp; 757231200Smm size_t i; 758231200Smm 759231200Smm if ((wp = archive_entry_pathname_w(entry)) != NULL) { 760231200Smm archive_wstrcpy(&(lha->ws), wp); 761231200Smm for (i = 0; i < archive_strlen(&(lha->ws)); i++) { 762231200Smm if (lha->ws.s[i] == L'\\') 763231200Smm lha->ws.s[i] = L'/'; 764231200Smm } 765231200Smm archive_entry_copy_pathname_w(entry, lha->ws.s); 766231200Smm } 767231200Smm 768231200Smm if ((wp = archive_entry_symlink_w(entry)) != NULL) { 769231200Smm archive_wstrcpy(&(lha->ws), wp); 770231200Smm for (i = 0; i < archive_strlen(&(lha->ws)); i++) { 771231200Smm if (lha->ws.s[i] == L'\\') 772231200Smm lha->ws.s[i] = L'/'; 773231200Smm } 774231200Smm archive_entry_copy_symlink_w(entry, lha->ws.s); 775231200Smm } 776231200Smm} 777231200Smm 778231200Smm/* 779231200Smm * Header 0 format 780231200Smm * 781231200Smm * +0 +1 +2 +7 +11 782231200Smm * +---------------+----------+----------------+-------------------+ 783231200Smm * |header size(*1)|header sum|compression type|compressed size(*2)| 784231200Smm * +---------------+----------+----------------+-------------------+ 785231200Smm * <---------------------(*1)----------* 786231200Smm * 787231200Smm * +11 +15 +17 +19 +20 +21 788231200Smm * +-----------------+---------+---------+--------------+----------------+ 789231200Smm * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=0)| 790231200Smm * +-----------------+---------+---------+--------------+----------------+ 791231200Smm * *--------------------------------(*1)---------------------------------* 792231200Smm * 793231200Smm * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+2+(*4) 794231200Smm * +---------------+---------+----------+----------------+------------------+ 795231200Smm * |name length(*3)|file name|file CRC16|extra header(*4)| compressed data | 796231200Smm * +---------------+---------+----------+----------------+------------------+ 797231200Smm * <--(*3)-> <------(*2)------> 798231200Smm * *----------------------(*1)--------------------------> 799231200Smm * 800231200Smm */ 801231200Smm#define H0_HEADER_SIZE_OFFSET 0 802231200Smm#define H0_HEADER_SUM_OFFSET 1 803231200Smm#define H0_COMP_SIZE_OFFSET 7 804231200Smm#define H0_ORIG_SIZE_OFFSET 11 805231200Smm#define H0_DOS_TIME_OFFSET 15 806231200Smm#define H0_NAME_LEN_OFFSET 21 807231200Smm#define H0_FILE_NAME_OFFSET 22 808231200Smm#define H0_FIXED_SIZE 24 809231200Smmstatic int 810231200Smmlha_read_file_header_0(struct archive_read *a, struct lha *lha) 811231200Smm{ 812231200Smm const unsigned char *p; 813231200Smm int extdsize, namelen; 814231200Smm unsigned char headersum, sum_calculated; 815231200Smm 816231200Smm if ((p = __archive_read_ahead(a, H0_FIXED_SIZE, NULL)) == NULL) 817231200Smm return (truncated_error(a)); 818231200Smm lha->header_size = p[H0_HEADER_SIZE_OFFSET] + 2; 819231200Smm headersum = p[H0_HEADER_SUM_OFFSET]; 820231200Smm lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET); 821231200Smm lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET); 822231200Smm lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET); 823231200Smm namelen = p[H0_NAME_LEN_OFFSET]; 824231200Smm extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen; 825231200Smm if ((namelen > 221 || extdsize < 0) && extdsize != -2) { 826231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 827231200Smm "Invalid LHa header"); 828231200Smm return (ARCHIVE_FATAL); 829231200Smm } 830231200Smm if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) 831231200Smm return (truncated_error(a)); 832231200Smm 833231200Smm archive_strncpy(&lha->filename, p + H0_FILE_NAME_OFFSET, namelen); 834231200Smm /* When extdsize == -2, A CRC16 value is not present in the header. */ 835231200Smm if (extdsize >= 0) { 836231200Smm lha->crc = archive_le16dec(p + H0_FILE_NAME_OFFSET + namelen); 837231200Smm lha->setflag |= CRC_IS_SET; 838231200Smm } 839231200Smm sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); 840231200Smm 841231200Smm /* Read an extended header */ 842231200Smm if (extdsize > 0) { 843231200Smm /* This extended data is set by 'LHa for UNIX' only. 844231200Smm * Maybe fixed size. 845231200Smm */ 846231200Smm p += H0_FILE_NAME_OFFSET + namelen + 2; 847231200Smm if (p[0] == 'U' && extdsize == 12) { 848231200Smm /* p[1] is a minor version. */ 849231200Smm lha->mtime = archive_le32dec(&p[2]); 850231200Smm lha->mode = archive_le16dec(&p[6]); 851231200Smm lha->uid = archive_le16dec(&p[8]); 852231200Smm lha->gid = archive_le16dec(&p[10]); 853231200Smm lha->setflag |= UNIX_MODE_IS_SET; 854231200Smm } 855231200Smm } 856231200Smm __archive_read_consume(a, lha->header_size); 857231200Smm 858231200Smm if (sum_calculated != headersum) { 859231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 860231200Smm "LHa header sum error"); 861231200Smm return (ARCHIVE_FATAL); 862231200Smm } 863231200Smm 864231200Smm return (ARCHIVE_OK); 865231200Smm} 866231200Smm 867231200Smm/* 868231200Smm * Header 1 format 869231200Smm * 870231200Smm * +0 +1 +2 +7 +11 871231200Smm * +---------------+----------+----------------+-------------+ 872231200Smm * |header size(*1)|header sum|compression type|skip size(*2)| 873231200Smm * +---------------+----------+----------------+-------------+ 874231200Smm * <---------------(*1)----------* 875231200Smm * 876231200Smm * +11 +15 +17 +19 +20 +21 877231200Smm * +-----------------+---------+---------+--------------+----------------+ 878231200Smm * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=1)| 879231200Smm * +-----------------+---------+---------+--------------+----------------+ 880231200Smm * *-------------------------------(*1)----------------------------------* 881231200Smm * 882231200Smm * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+3 +22+(*3)+3+(*4) 883231200Smm * +---------------+---------+----------+-----------+-----------+ 884231200Smm * |name length(*3)|file name|file CRC16| creator |padding(*4)| 885231200Smm * +---------------+---------+----------+-----------+-----------+ 886231200Smm * <--(*3)-> 887231200Smm * *----------------------------(*1)----------------------------* 888231200Smm * 889231200Smm * +22+(*3)+3+(*4) +22+(*3)+3+(*4)+2 +22+(*3)+3+(*4)+2+(*5) 890231200Smm * +----------------+---------------------+------------------------+ 891231200Smm * |next header size| extended header(*5) | compressed data | 892231200Smm * +----------------+---------------------+------------------------+ 893231200Smm * *------(*1)-----> <--------------------(*2)--------------------> 894231200Smm */ 895231200Smm#define H1_HEADER_SIZE_OFFSET 0 896231200Smm#define H1_HEADER_SUM_OFFSET 1 897231200Smm#define H1_COMP_SIZE_OFFSET 7 898231200Smm#define H1_ORIG_SIZE_OFFSET 11 899231200Smm#define H1_DOS_TIME_OFFSET 15 900231200Smm#define H1_NAME_LEN_OFFSET 21 901231200Smm#define H1_FILE_NAME_OFFSET 22 902231200Smm#define H1_FIXED_SIZE 27 903231200Smmstatic int 904231200Smmlha_read_file_header_1(struct archive_read *a, struct lha *lha) 905231200Smm{ 906231200Smm const unsigned char *p; 907231200Smm size_t extdsize; 908231200Smm int i, err, err2; 909231200Smm int namelen, padding; 910231200Smm unsigned char headersum, sum_calculated; 911231200Smm 912231200Smm err = ARCHIVE_OK; 913231200Smm 914231200Smm if ((p = __archive_read_ahead(a, H1_FIXED_SIZE, NULL)) == NULL) 915231200Smm return (truncated_error(a)); 916231200Smm 917231200Smm lha->header_size = p[H1_HEADER_SIZE_OFFSET] + 2; 918231200Smm headersum = p[H1_HEADER_SUM_OFFSET]; 919231200Smm /* Note: An extended header size is included in a compsize. */ 920231200Smm lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET); 921231200Smm lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET); 922231200Smm lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET); 923231200Smm namelen = p[H1_NAME_LEN_OFFSET]; 924231200Smm /* Calculate a padding size. The result will be normally 0 only(?) */ 925231200Smm padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen; 926231200Smm 927231200Smm if (namelen > 230 || padding < 0) 928231200Smm goto invalid; 929231200Smm 930231200Smm if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) 931231200Smm return (truncated_error(a)); 932231200Smm 933231200Smm for (i = 0; i < namelen; i++) { 934231200Smm if (p[i + H1_FILE_NAME_OFFSET] == 0xff) 935231200Smm goto invalid;/* Invalid filename. */ 936231200Smm } 937231200Smm archive_strncpy(&lha->filename, p + H1_FILE_NAME_OFFSET, namelen); 938231200Smm lha->crc = archive_le16dec(p + H1_FILE_NAME_OFFSET + namelen); 939231200Smm lha->setflag |= CRC_IS_SET; 940231200Smm 941231200Smm sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); 942231200Smm /* Consume used bytes but not include `next header size' data 943231200Smm * since it will be consumed in lha_read_file_extended_header(). */ 944231200Smm __archive_read_consume(a, lha->header_size - 2); 945231200Smm 946231200Smm /* Read extended headers */ 947231200Smm err2 = lha_read_file_extended_header(a, lha, NULL, 2, 948238856Smm (size_t)(lha->compsize + 2), &extdsize); 949231200Smm if (err2 < ARCHIVE_WARN) 950231200Smm return (err2); 951231200Smm if (err2 < err) 952231200Smm err = err2; 953231200Smm /* Get a real compressed file size. */ 954231200Smm lha->compsize -= extdsize - 2; 955231200Smm 956313571Smm if (lha->compsize < 0) 957313571Smm goto invalid; /* Invalid compressed file size */ 958313571Smm 959231200Smm if (sum_calculated != headersum) { 960231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 961231200Smm "LHa header sum error"); 962231200Smm return (ARCHIVE_FATAL); 963231200Smm } 964231200Smm return (err); 965231200Smminvalid: 966231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 967231200Smm "Invalid LHa header"); 968231200Smm return (ARCHIVE_FATAL); 969231200Smm} 970231200Smm 971231200Smm/* 972231200Smm * Header 2 format 973231200Smm * 974231200Smm * +0 +2 +7 +11 +15 975231200Smm * +---------------+----------------+-------------------+-----------------+ 976231200Smm * |header size(*1)|compression type|compressed size(*2)|uncompressed size| 977231200Smm * +---------------+----------------+-------------------+-----------------+ 978231200Smm * <--------------------------------(*1)---------------------------------* 979231200Smm * 980231200Smm * +15 +19 +20 +21 +23 +24 981231200Smm * +-----------------+------------+----------------+----------+-----------+ 982231200Smm * |data/time(time_t)| 0x20 fixed |header level(=2)|file CRC16| creator | 983231200Smm * +-----------------+------------+----------------+----------+-----------+ 984231200Smm * *---------------------------------(*1)---------------------------------* 985231200Smm * 986231200Smm * +24 +26 +26+(*3) +26+(*3)+(*4) 987231200Smm * +----------------+-------------------+-------------+-------------------+ 988231200Smm * |next header size|extended header(*3)| padding(*4) | compressed data | 989231200Smm * +----------------+-------------------+-------------+-------------------+ 990231200Smm * *--------------------------(*1)-------------------> <------(*2)-------> 991231200Smm * 992231200Smm */ 993231200Smm#define H2_HEADER_SIZE_OFFSET 0 994231200Smm#define H2_COMP_SIZE_OFFSET 7 995231200Smm#define H2_ORIG_SIZE_OFFSET 11 996231200Smm#define H2_TIME_OFFSET 15 997231200Smm#define H2_CRC_OFFSET 21 998231200Smm#define H2_FIXED_SIZE 24 999231200Smmstatic int 1000231200Smmlha_read_file_header_2(struct archive_read *a, struct lha *lha) 1001231200Smm{ 1002231200Smm const unsigned char *p; 1003231200Smm size_t extdsize; 1004231200Smm int err, padding; 1005231200Smm uint16_t header_crc; 1006231200Smm 1007231200Smm if ((p = __archive_read_ahead(a, H2_FIXED_SIZE, NULL)) == NULL) 1008231200Smm return (truncated_error(a)); 1009231200Smm 1010231200Smm lha->header_size =archive_le16dec(p + H2_HEADER_SIZE_OFFSET); 1011231200Smm lha->compsize = archive_le32dec(p + H2_COMP_SIZE_OFFSET); 1012231200Smm lha->origsize = archive_le32dec(p + H2_ORIG_SIZE_OFFSET); 1013231200Smm lha->mtime = archive_le32dec(p + H2_TIME_OFFSET); 1014231200Smm lha->crc = archive_le16dec(p + H2_CRC_OFFSET); 1015231200Smm lha->setflag |= CRC_IS_SET; 1016231200Smm 1017231200Smm if (lha->header_size < H2_FIXED_SIZE) { 1018231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1019231200Smm "Invalid LHa header size"); 1020231200Smm return (ARCHIVE_FATAL); 1021231200Smm } 1022231200Smm 1023231200Smm header_crc = lha_crc16(0, p, H2_FIXED_SIZE); 1024231200Smm __archive_read_consume(a, H2_FIXED_SIZE); 1025231200Smm 1026231200Smm /* Read extended headers */ 1027231200Smm err = lha_read_file_extended_header(a, lha, &header_crc, 2, 1028231200Smm lha->header_size - H2_FIXED_SIZE, &extdsize); 1029231200Smm if (err < ARCHIVE_WARN) 1030231200Smm return (err); 1031231200Smm 1032231200Smm /* Calculate a padding size. The result will be normally 0 or 1. */ 1033231200Smm padding = (int)lha->header_size - (int)(H2_FIXED_SIZE + extdsize); 1034231200Smm if (padding > 0) { 1035231200Smm if ((p = __archive_read_ahead(a, padding, NULL)) == NULL) 1036231200Smm return (truncated_error(a)); 1037231200Smm header_crc = lha_crc16(header_crc, p, padding); 1038231200Smm __archive_read_consume(a, padding); 1039231200Smm } 1040231200Smm 1041231200Smm if (header_crc != lha->header_crc) { 1042231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1043231200Smm "LHa header CRC error"); 1044231200Smm return (ARCHIVE_FATAL); 1045231200Smm } 1046231200Smm return (err); 1047231200Smm} 1048231200Smm 1049231200Smm/* 1050231200Smm * Header 3 format 1051231200Smm * 1052231200Smm * +0 +2 +7 +11 +15 1053231200Smm * +------------+----------------+-------------------+-----------------+ 1054231200Smm * | 0x04 fixed |compression type|compressed size(*2)|uncompressed size| 1055231200Smm * +------------+----------------+-------------------+-----------------+ 1056231200Smm * <-------------------------------(*1)-------------------------------* 1057231200Smm * 1058231200Smm * +15 +19 +20 +21 +23 +24 1059231200Smm * +-----------------+------------+----------------+----------+-----------+ 1060231200Smm * |date/time(time_t)| 0x20 fixed |header level(=3)|file CRC16| creator | 1061231200Smm * +-----------------+------------+----------------+----------+-----------+ 1062231200Smm * *--------------------------------(*1)----------------------------------* 1063231200Smm * 1064231200Smm * +24 +28 +32 +32+(*3) 1065231200Smm * +---------------+----------------+-------------------+-----------------+ 1066231200Smm * |header size(*1)|next header size|extended header(*3)| compressed data | 1067231200Smm * +---------------+----------------+-------------------+-----------------+ 1068231200Smm * *------------------------(*1)-----------------------> <------(*2)-----> 1069231200Smm * 1070231200Smm */ 1071231200Smm#define H3_FIELD_LEN_OFFSET 0 1072231200Smm#define H3_COMP_SIZE_OFFSET 7 1073231200Smm#define H3_ORIG_SIZE_OFFSET 11 1074231200Smm#define H3_TIME_OFFSET 15 1075231200Smm#define H3_CRC_OFFSET 21 1076231200Smm#define H3_HEADER_SIZE_OFFSET 24 1077231200Smm#define H3_FIXED_SIZE 28 1078231200Smmstatic int 1079231200Smmlha_read_file_header_3(struct archive_read *a, struct lha *lha) 1080231200Smm{ 1081231200Smm const unsigned char *p; 1082231200Smm size_t extdsize; 1083231200Smm int err; 1084231200Smm uint16_t header_crc; 1085231200Smm 1086231200Smm if ((p = __archive_read_ahead(a, H3_FIXED_SIZE, NULL)) == NULL) 1087231200Smm return (truncated_error(a)); 1088231200Smm 1089231200Smm if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4) 1090231200Smm goto invalid; 1091231200Smm lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET); 1092231200Smm lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET); 1093231200Smm lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET); 1094231200Smm lha->mtime = archive_le32dec(p + H3_TIME_OFFSET); 1095231200Smm lha->crc = archive_le16dec(p + H3_CRC_OFFSET); 1096231200Smm lha->setflag |= CRC_IS_SET; 1097231200Smm 1098231200Smm if (lha->header_size < H3_FIXED_SIZE + 4) 1099231200Smm goto invalid; 1100231200Smm header_crc = lha_crc16(0, p, H3_FIXED_SIZE); 1101231200Smm __archive_read_consume(a, H3_FIXED_SIZE); 1102231200Smm 1103231200Smm /* Read extended headers */ 1104231200Smm err = lha_read_file_extended_header(a, lha, &header_crc, 4, 1105231200Smm lha->header_size - H3_FIXED_SIZE, &extdsize); 1106231200Smm if (err < ARCHIVE_WARN) 1107231200Smm return (err); 1108231200Smm 1109231200Smm if (header_crc != lha->header_crc) { 1110231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1111231200Smm "LHa header CRC error"); 1112231200Smm return (ARCHIVE_FATAL); 1113231200Smm } 1114231200Smm return (err); 1115231200Smminvalid: 1116231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1117231200Smm "Invalid LHa header"); 1118231200Smm return (ARCHIVE_FATAL); 1119231200Smm} 1120231200Smm 1121231200Smm/* 1122231200Smm * Extended header format 1123231200Smm * 1124231200Smm * +0 +2 +3 -- used in header 1 and 2 1125231200Smm * +0 +4 +5 -- used in header 3 1126231200Smm * +--------------+---------+-------------------+--------------+-- 1127231200Smm * |ex-header size|header id| data |ex-header size| ....... 1128231200Smm * +--------------+---------+-------------------+--------------+-- 1129231200Smm * <-------------( ex-header size)------------> <-- next extended header --* 1130231200Smm * 1131231200Smm * If the ex-header size is zero, it is the make of the end of extended 1132231200Smm * headers. 1133231200Smm * 1134231200Smm */ 1135231200Smmstatic int 1136231200Smmlha_read_file_extended_header(struct archive_read *a, struct lha *lha, 1137231200Smm uint16_t *crc, int sizefield_length, size_t limitsize, size_t *total_size) 1138231200Smm{ 1139231200Smm const void *h; 1140231200Smm const unsigned char *extdheader; 1141231200Smm size_t extdsize; 1142231200Smm size_t datasize; 1143231200Smm unsigned int i; 1144231200Smm unsigned char extdtype; 1145231200Smm 1146231200Smm#define EXT_HEADER_CRC 0x00 /* Header CRC and information*/ 1147231200Smm#define EXT_FILENAME 0x01 /* Filename */ 1148231200Smm#define EXT_DIRECTORY 0x02 /* Directory name */ 1149231200Smm#define EXT_DOS_ATTR 0x40 /* MS-DOS attribute */ 1150231200Smm#define EXT_TIMESTAMP 0x41 /* Windows time stamp */ 1151231200Smm#define EXT_FILESIZE 0x42 /* Large file size */ 1152231200Smm#define EXT_TIMEZONE 0x43 /* Time zone */ 1153231200Smm#define EXT_UTF16_FILENAME 0x44 /* UTF-16 filename */ 1154231200Smm#define EXT_UTF16_DIRECTORY 0x45 /* UTF-16 directory name */ 1155231200Smm#define EXT_CODEPAGE 0x46 /* Codepage */ 1156231200Smm#define EXT_UNIX_MODE 0x50 /* File permission */ 1157231200Smm#define EXT_UNIX_GID_UID 0x51 /* gid,uid */ 1158231200Smm#define EXT_UNIX_GNAME 0x52 /* Group name */ 1159231200Smm#define EXT_UNIX_UNAME 0x53 /* User name */ 1160231200Smm#define EXT_UNIX_MTIME 0x54 /* Modified time */ 1161231200Smm#define EXT_OS2_NEW_ATTR 0x7f /* new attribute(OS/2 only) */ 1162231200Smm#define EXT_NEW_ATTR 0xff /* new attribute */ 1163231200Smm 1164231200Smm *total_size = sizefield_length; 1165231200Smm 1166231200Smm for (;;) { 1167231200Smm /* Read an extended header size. */ 1168231200Smm if ((h = 1169231200Smm __archive_read_ahead(a, sizefield_length, NULL)) == NULL) 1170231200Smm return (truncated_error(a)); 1171231200Smm /* Check if the size is the zero indicates the end of the 1172231200Smm * extended header. */ 1173231200Smm if (sizefield_length == sizeof(uint16_t)) 1174231200Smm extdsize = archive_le16dec(h); 1175231200Smm else 1176231200Smm extdsize = archive_le32dec(h); 1177231200Smm if (extdsize == 0) { 1178231200Smm /* End of extended header */ 1179231200Smm if (crc != NULL) 1180231200Smm *crc = lha_crc16(*crc, h, sizefield_length); 1181231200Smm __archive_read_consume(a, sizefield_length); 1182231200Smm return (ARCHIVE_OK); 1183231200Smm } 1184231200Smm 1185231200Smm /* Sanity check to the extended header size. */ 1186231200Smm if (((uint64_t)*total_size + extdsize) > 1187231200Smm (uint64_t)limitsize || 1188231200Smm extdsize <= (size_t)sizefield_length) 1189231200Smm goto invalid; 1190231200Smm 1191231200Smm /* Read the extended header. */ 1192231200Smm if ((h = __archive_read_ahead(a, extdsize, NULL)) == NULL) 1193231200Smm return (truncated_error(a)); 1194231200Smm *total_size += extdsize; 1195231200Smm 1196231200Smm extdheader = (const unsigned char *)h; 1197231200Smm /* Get the extended header type. */ 1198231200Smm extdtype = extdheader[sizefield_length]; 1199231200Smm /* Calculate an extended data size. */ 1200231200Smm datasize = extdsize - (1 + sizefield_length); 1201231200Smm /* Skip an extended header size field and type field. */ 1202231200Smm extdheader += sizefield_length + 1; 1203231200Smm 1204231200Smm if (crc != NULL && extdtype != EXT_HEADER_CRC) 1205231200Smm *crc = lha_crc16(*crc, h, extdsize); 1206231200Smm switch (extdtype) { 1207231200Smm case EXT_HEADER_CRC: 1208231200Smm /* We only use a header CRC. Following data will not 1209231200Smm * be used. */ 1210231200Smm if (datasize >= 2) { 1211231200Smm lha->header_crc = archive_le16dec(extdheader); 1212231200Smm if (crc != NULL) { 1213231200Smm static const char zeros[2] = {0, 0}; 1214231200Smm *crc = lha_crc16(*crc, h, 1215231200Smm extdsize - datasize); 1216231200Smm /* CRC value itself as zero */ 1217231200Smm *crc = lha_crc16(*crc, zeros, 2); 1218231200Smm *crc = lha_crc16(*crc, 1219231200Smm extdheader+2, datasize - 2); 1220231200Smm } 1221231200Smm } 1222231200Smm break; 1223231200Smm case EXT_FILENAME: 1224231200Smm if (datasize == 0) { 1225231200Smm /* maybe directory header */ 1226231200Smm archive_string_empty(&lha->filename); 1227231200Smm break; 1228231200Smm } 1229302001Smm if (extdheader[0] == '\0') 1230302001Smm goto invalid; 1231231200Smm archive_strncpy(&lha->filename, 1232231200Smm (const char *)extdheader, datasize); 1233231200Smm break; 1234358090Smm case EXT_UTF16_FILENAME: 1235358090Smm if (datasize == 0) { 1236358090Smm /* maybe directory header */ 1237358090Smm archive_string_empty(&lha->filename); 1238358090Smm break; 1239358090Smm } else if (datasize & 1) { 1240358090Smm /* UTF-16 characters take always 2 or 4 bytes */ 1241358090Smm goto invalid; 1242358090Smm } 1243358090Smm if (extdheader[0] == '\0') 1244358090Smm goto invalid; 1245358090Smm archive_string_empty(&lha->filename); 1246358090Smm archive_array_append(&lha->filename, 1247358090Smm (const char *)extdheader, datasize); 1248358090Smm /* Setup a string conversion for a filename. */ 1249358090Smm lha->sconv_fname = 1250358090Smm archive_string_conversion_from_charset(&a->archive, 1251358090Smm "UTF-16LE", 1); 1252358090Smm if (lha->sconv_fname == NULL) 1253358090Smm return (ARCHIVE_FATAL); 1254358090Smm break; 1255231200Smm case EXT_DIRECTORY: 1256302001Smm if (datasize == 0 || extdheader[0] == '\0') 1257231200Smm /* no directory name data. exit this case. */ 1258302001Smm goto invalid; 1259231200Smm 1260231200Smm archive_strncpy(&lha->dirname, 1261231200Smm (const char *)extdheader, datasize); 1262231200Smm /* 1263231200Smm * Convert directory delimiter from 0xFF 1264231200Smm * to '/' for local system. 1265231200Smm */ 1266231200Smm for (i = 0; i < lha->dirname.length; i++) { 1267231200Smm if ((unsigned char)lha->dirname.s[i] == 0xFF) 1268231200Smm lha->dirname.s[i] = '/'; 1269231200Smm } 1270231200Smm /* Is last character directory separator? */ 1271231200Smm if (lha->dirname.s[lha->dirname.length-1] != '/') 1272231200Smm /* invalid directory data */ 1273231200Smm goto invalid; 1274231200Smm break; 1275358090Smm case EXT_UTF16_DIRECTORY: 1276358090Smm /* UTF-16 characters take always 2 or 4 bytes */ 1277358090Smm if (datasize == 0 || (datasize & 1) || 1278358090Smm extdheader[0] == '\0') { 1279358090Smm /* no directory name data. exit this case. */ 1280358090Smm goto invalid; 1281358090Smm } 1282358090Smm 1283358090Smm archive_string_empty(&lha->dirname); 1284358090Smm archive_array_append(&lha->dirname, 1285358090Smm (const char *)extdheader, datasize); 1286358090Smm lha->sconv_dir = 1287358090Smm archive_string_conversion_from_charset(&a->archive, 1288358090Smm "UTF-16LE", 1); 1289358090Smm if (lha->sconv_dir == NULL) 1290358090Smm return (ARCHIVE_FATAL); 1291358090Smm else { 1292358090Smm /* 1293358090Smm * Convert directory delimiter from 0xFFFF 1294358090Smm * to '/' for local system. 1295358090Smm */ 1296358090Smm uint16_t dirSep; 1297358090Smm uint16_t d = 1; 1298358090Smm if (archive_be16dec(&d) == 1) 1299358090Smm dirSep = 0x2F00; 1300358090Smm else 1301358090Smm dirSep = 0x002F; 1302358090Smm 1303358090Smm /* UTF-16LE character */ 1304358090Smm uint16_t *utf16name = 1305358090Smm (uint16_t *)lha->dirname.s; 1306358090Smm for (i = 0; i < lha->dirname.length / 2; i++) { 1307358090Smm if (utf16name[i] == 0xFFFF) { 1308358090Smm utf16name[i] = dirSep; 1309358090Smm } 1310358090Smm } 1311358090Smm /* Is last character directory separator? */ 1312358090Smm if (utf16name[lha->dirname.length / 2 - 1] != 1313358090Smm dirSep) { 1314358090Smm /* invalid directory data */ 1315358090Smm goto invalid; 1316358090Smm } 1317358090Smm } 1318358090Smm break; 1319231200Smm case EXT_DOS_ATTR: 1320231200Smm if (datasize == 2) 1321231200Smm lha->dos_attr = (unsigned char) 1322231200Smm (archive_le16dec(extdheader) & 0xff); 1323231200Smm break; 1324231200Smm case EXT_TIMESTAMP: 1325231200Smm if (datasize == (sizeof(uint64_t) * 3)) { 1326231200Smm lha->birthtime = lha_win_time( 1327231200Smm archive_le64dec(extdheader), 1328231200Smm &lha->birthtime_tv_nsec); 1329231200Smm extdheader += sizeof(uint64_t); 1330231200Smm lha->mtime = lha_win_time( 1331231200Smm archive_le64dec(extdheader), 1332231200Smm &lha->mtime_tv_nsec); 1333231200Smm extdheader += sizeof(uint64_t); 1334231200Smm lha->atime = lha_win_time( 1335231200Smm archive_le64dec(extdheader), 1336231200Smm &lha->atime_tv_nsec); 1337231200Smm lha->setflag |= BIRTHTIME_IS_SET | 1338231200Smm ATIME_IS_SET; 1339231200Smm } 1340231200Smm break; 1341231200Smm case EXT_FILESIZE: 1342231200Smm if (datasize == sizeof(uint64_t) * 2) { 1343231200Smm lha->compsize = archive_le64dec(extdheader); 1344231200Smm extdheader += sizeof(uint64_t); 1345231200Smm lha->origsize = archive_le64dec(extdheader); 1346231200Smm } 1347231200Smm break; 1348231200Smm case EXT_CODEPAGE: 1349231200Smm /* Get an archived filename charset from codepage. 1350231200Smm * This overwrites the charset specified by 1351231200Smm * hdrcharset option. */ 1352231200Smm if (datasize == sizeof(uint32_t)) { 1353231200Smm struct archive_string cp; 1354231200Smm const char *charset; 1355231200Smm 1356231200Smm archive_string_init(&cp); 1357231200Smm switch (archive_le32dec(extdheader)) { 1358231200Smm case 65001: /* UTF-8 */ 1359231200Smm charset = "UTF-8"; 1360231200Smm break; 1361231200Smm default: 1362231200Smm archive_string_sprintf(&cp, "CP%d", 1363231200Smm (int)archive_le32dec(extdheader)); 1364231200Smm charset = cp.s; 1365231200Smm break; 1366231200Smm } 1367358090Smm lha->sconv_dir = 1368231200Smm archive_string_conversion_from_charset( 1369231200Smm &(a->archive), charset, 1); 1370358090Smm lha->sconv_fname = 1371358090Smm archive_string_conversion_from_charset( 1372358090Smm &(a->archive), charset, 1); 1373231200Smm archive_string_free(&cp); 1374358090Smm if (lha->sconv_dir == NULL) 1375231200Smm return (ARCHIVE_FATAL); 1376358090Smm if (lha->sconv_fname == NULL) 1377358090Smm return (ARCHIVE_FATAL); 1378231200Smm } 1379231200Smm break; 1380231200Smm case EXT_UNIX_MODE: 1381231200Smm if (datasize == sizeof(uint16_t)) { 1382231200Smm lha->mode = archive_le16dec(extdheader); 1383231200Smm lha->setflag |= UNIX_MODE_IS_SET; 1384231200Smm } 1385231200Smm break; 1386231200Smm case EXT_UNIX_GID_UID: 1387231200Smm if (datasize == (sizeof(uint16_t) * 2)) { 1388231200Smm lha->gid = archive_le16dec(extdheader); 1389231200Smm lha->uid = archive_le16dec(extdheader+2); 1390231200Smm } 1391231200Smm break; 1392231200Smm case EXT_UNIX_GNAME: 1393231200Smm if (datasize > 0) 1394231200Smm archive_strncpy(&lha->gname, 1395231200Smm (const char *)extdheader, datasize); 1396231200Smm break; 1397231200Smm case EXT_UNIX_UNAME: 1398231200Smm if (datasize > 0) 1399231200Smm archive_strncpy(&lha->uname, 1400231200Smm (const char *)extdheader, datasize); 1401231200Smm break; 1402231200Smm case EXT_UNIX_MTIME: 1403231200Smm if (datasize == sizeof(uint32_t)) 1404231200Smm lha->mtime = archive_le32dec(extdheader); 1405231200Smm break; 1406231200Smm case EXT_OS2_NEW_ATTR: 1407231200Smm /* This extended header is OS/2 depend. */ 1408231200Smm if (datasize == 16) { 1409231200Smm lha->dos_attr = (unsigned char) 1410231200Smm (archive_le16dec(extdheader) & 0xff); 1411231200Smm lha->mode = archive_le16dec(extdheader+2); 1412231200Smm lha->gid = archive_le16dec(extdheader+4); 1413231200Smm lha->uid = archive_le16dec(extdheader+6); 1414231200Smm lha->birthtime = archive_le32dec(extdheader+8); 1415231200Smm lha->atime = archive_le32dec(extdheader+12); 1416231200Smm lha->setflag |= UNIX_MODE_IS_SET 1417231200Smm | BIRTHTIME_IS_SET | ATIME_IS_SET; 1418231200Smm } 1419231200Smm break; 1420231200Smm case EXT_NEW_ATTR: 1421231200Smm if (datasize == 20) { 1422231200Smm lha->mode = (mode_t)archive_le32dec(extdheader); 1423231200Smm lha->gid = archive_le32dec(extdheader+4); 1424231200Smm lha->uid = archive_le32dec(extdheader+8); 1425231200Smm lha->birthtime = archive_le32dec(extdheader+12); 1426231200Smm lha->atime = archive_le32dec(extdheader+16); 1427231200Smm lha->setflag |= UNIX_MODE_IS_SET 1428231200Smm | BIRTHTIME_IS_SET | ATIME_IS_SET; 1429231200Smm } 1430231200Smm break; 1431231200Smm case EXT_TIMEZONE: /* Not supported */ 1432358090Smm break; 1433231200Smm default: 1434231200Smm break; 1435231200Smm } 1436231200Smm 1437231200Smm __archive_read_consume(a, extdsize); 1438231200Smm } 1439231200Smminvalid: 1440231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1441231200Smm "Invalid extended LHa header"); 1442231200Smm return (ARCHIVE_FATAL); 1443231200Smm} 1444231200Smm 1445231200Smmstatic int 1446302001Smmlha_end_of_entry(struct archive_read *a) 1447302001Smm{ 1448302001Smm struct lha *lha = (struct lha *)(a->format->data); 1449302001Smm int r = ARCHIVE_EOF; 1450302001Smm 1451302001Smm if (!lha->end_of_entry_cleanup) { 1452302001Smm if ((lha->setflag & CRC_IS_SET) && 1453302001Smm lha->crc != lha->entry_crc_calculated) { 1454302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1455302001Smm "LHa data CRC error"); 1456302001Smm r = ARCHIVE_WARN; 1457302001Smm } 1458302001Smm 1459302001Smm /* End-of-entry cleanup done. */ 1460302001Smm lha->end_of_entry_cleanup = 1; 1461302001Smm } 1462302001Smm return (r); 1463302001Smm} 1464302001Smm 1465302001Smmstatic int 1466231200Smmarchive_read_format_lha_read_data(struct archive_read *a, 1467231200Smm const void **buff, size_t *size, int64_t *offset) 1468231200Smm{ 1469231200Smm struct lha *lha = (struct lha *)(a->format->data); 1470231200Smm int r; 1471231200Smm 1472231200Smm if (lha->entry_unconsumed) { 1473231200Smm /* Consume as much as the decompressor actually used. */ 1474231200Smm __archive_read_consume(a, lha->entry_unconsumed); 1475231200Smm lha->entry_unconsumed = 0; 1476231200Smm } 1477231200Smm if (lha->end_of_entry) { 1478231200Smm *offset = lha->entry_offset; 1479231200Smm *size = 0; 1480231200Smm *buff = NULL; 1481302001Smm return (lha_end_of_entry(a)); 1482231200Smm } 1483231200Smm 1484231200Smm if (lha->entry_is_compressed) 1485231200Smm r = lha_read_data_lzh(a, buff, size, offset); 1486231200Smm else 1487231200Smm /* No compression. */ 1488231200Smm r = lha_read_data_none(a, buff, size, offset); 1489231200Smm return (r); 1490231200Smm} 1491231200Smm 1492231200Smm/* 1493231200Smm * Read a file content in no compression. 1494231200Smm * 1495231200Smm * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets 1496231200Smm * lha->end_of_entry if it consumes all of the data. 1497231200Smm */ 1498231200Smmstatic int 1499231200Smmlha_read_data_none(struct archive_read *a, const void **buff, 1500231200Smm size_t *size, int64_t *offset) 1501231200Smm{ 1502231200Smm struct lha *lha = (struct lha *)(a->format->data); 1503231200Smm ssize_t bytes_avail; 1504231200Smm 1505231200Smm if (lha->entry_bytes_remaining == 0) { 1506231200Smm *buff = NULL; 1507231200Smm *size = 0; 1508231200Smm *offset = lha->entry_offset; 1509231200Smm lha->end_of_entry = 1; 1510231200Smm return (ARCHIVE_OK); 1511231200Smm } 1512231200Smm /* 1513231200Smm * Note: '1' here is a performance optimization. 1514231200Smm * Recall that the decompression layer returns a count of 1515231200Smm * available bytes; asking for more than that forces the 1516231200Smm * decompressor to combine reads by copying data. 1517231200Smm */ 1518231200Smm *buff = __archive_read_ahead(a, 1, &bytes_avail); 1519231200Smm if (bytes_avail <= 0) { 1520231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1521231200Smm "Truncated LHa file data"); 1522231200Smm return (ARCHIVE_FATAL); 1523231200Smm } 1524231200Smm if (bytes_avail > lha->entry_bytes_remaining) 1525238856Smm bytes_avail = (ssize_t)lha->entry_bytes_remaining; 1526231200Smm lha->entry_crc_calculated = 1527231200Smm lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail); 1528231200Smm *size = bytes_avail; 1529231200Smm *offset = lha->entry_offset; 1530231200Smm lha->entry_offset += bytes_avail; 1531231200Smm lha->entry_bytes_remaining -= bytes_avail; 1532231200Smm if (lha->entry_bytes_remaining == 0) 1533231200Smm lha->end_of_entry = 1; 1534231200Smm lha->entry_unconsumed = bytes_avail; 1535231200Smm return (ARCHIVE_OK); 1536231200Smm} 1537231200Smm 1538231200Smm/* 1539231200Smm * Read a file content in LZHUFF encoding. 1540231200Smm * 1541231200Smm * Returns ARCHIVE_OK if successful, returns ARCHIVE_WARN if compression is 1542231200Smm * unsupported, ARCHIVE_FATAL otherwise, sets lha->end_of_entry if it consumes 1543231200Smm * all of the data. 1544231200Smm */ 1545231200Smmstatic int 1546231200Smmlha_read_data_lzh(struct archive_read *a, const void **buff, 1547231200Smm size_t *size, int64_t *offset) 1548231200Smm{ 1549231200Smm struct lha *lha = (struct lha *)(a->format->data); 1550231200Smm ssize_t bytes_avail; 1551231200Smm int r; 1552231200Smm 1553231200Smm /* If we haven't yet read any data, initialize the decompressor. */ 1554231200Smm if (!lha->decompress_init) { 1555231200Smm r = lzh_decode_init(&(lha->strm), lha->method); 1556231200Smm switch (r) { 1557231200Smm case ARCHIVE_OK: 1558231200Smm break; 1559231200Smm case ARCHIVE_FAILED: 1560231200Smm /* Unsupported compression. */ 1561231200Smm *buff = NULL; 1562231200Smm *size = 0; 1563231200Smm *offset = 0; 1564231200Smm archive_set_error(&a->archive, 1565231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 1566231200Smm "Unsupported lzh compression method -%c%c%c-", 1567231200Smm lha->method[0], lha->method[1], lha->method[2]); 1568231200Smm /* We know compressed size; just skip it. */ 1569231200Smm archive_read_format_lha_read_data_skip(a); 1570231200Smm return (ARCHIVE_WARN); 1571231200Smm default: 1572231200Smm archive_set_error(&a->archive, ENOMEM, 1573231200Smm "Couldn't allocate memory " 1574231200Smm "for lzh decompression"); 1575231200Smm return (ARCHIVE_FATAL); 1576231200Smm } 1577231200Smm /* We've initialized decompression for this stream. */ 1578231200Smm lha->decompress_init = 1; 1579231200Smm lha->strm.avail_out = 0; 1580231200Smm lha->strm.total_out = 0; 1581231200Smm } 1582231200Smm 1583231200Smm /* 1584231200Smm * Note: '1' here is a performance optimization. 1585231200Smm * Recall that the decompression layer returns a count of 1586231200Smm * available bytes; asking for more than that forces the 1587231200Smm * decompressor to combine reads by copying data. 1588231200Smm */ 1589231200Smm lha->strm.next_in = __archive_read_ahead(a, 1, &bytes_avail); 1590231200Smm if (bytes_avail <= 0) { 1591231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1592231200Smm "Truncated LHa file body"); 1593231200Smm return (ARCHIVE_FATAL); 1594231200Smm } 1595231200Smm if (bytes_avail > lha->entry_bytes_remaining) 1596238856Smm bytes_avail = (ssize_t)lha->entry_bytes_remaining; 1597231200Smm 1598302001Smm lha->strm.avail_in = (int)bytes_avail; 1599231200Smm lha->strm.total_in = 0; 1600302001Smm lha->strm.avail_out = 0; 1601231200Smm 1602231200Smm r = lzh_decode(&(lha->strm), bytes_avail == lha->entry_bytes_remaining); 1603231200Smm switch (r) { 1604231200Smm case ARCHIVE_OK: 1605231200Smm break; 1606231200Smm case ARCHIVE_EOF: 1607231200Smm lha->end_of_entry = 1; 1608231200Smm break; 1609231200Smm default: 1610231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1611231200Smm "Bad lzh data"); 1612231200Smm return (ARCHIVE_FAILED); 1613231200Smm } 1614231200Smm lha->entry_unconsumed = lha->strm.total_in; 1615231200Smm lha->entry_bytes_remaining -= lha->strm.total_in; 1616231200Smm 1617302001Smm if (lha->strm.avail_out) { 1618231200Smm *offset = lha->entry_offset; 1619302001Smm *size = lha->strm.avail_out; 1620302001Smm *buff = lha->strm.ref_ptr; 1621231200Smm lha->entry_crc_calculated = 1622231200Smm lha_crc16(lha->entry_crc_calculated, *buff, *size); 1623231200Smm lha->entry_offset += *size; 1624231200Smm } else { 1625231200Smm *offset = lha->entry_offset; 1626231200Smm *size = 0; 1627231200Smm *buff = NULL; 1628302001Smm if (lha->end_of_entry) 1629302001Smm return (lha_end_of_entry(a)); 1630231200Smm } 1631231200Smm return (ARCHIVE_OK); 1632231200Smm} 1633231200Smm 1634231200Smm/* 1635231200Smm * Skip a file content. 1636231200Smm */ 1637231200Smmstatic int 1638231200Smmarchive_read_format_lha_read_data_skip(struct archive_read *a) 1639231200Smm{ 1640231200Smm struct lha *lha; 1641238856Smm int64_t bytes_skipped; 1642231200Smm 1643231200Smm lha = (struct lha *)(a->format->data); 1644231200Smm 1645231200Smm if (lha->entry_unconsumed) { 1646231200Smm /* Consume as much as the decompressor actually used. */ 1647231200Smm __archive_read_consume(a, lha->entry_unconsumed); 1648231200Smm lha->entry_unconsumed = 0; 1649231200Smm } 1650231200Smm 1651231200Smm /* if we've already read to end of data, we're done. */ 1652231200Smm if (lha->end_of_entry_cleanup) 1653231200Smm return (ARCHIVE_OK); 1654231200Smm 1655231200Smm /* 1656231200Smm * If the length is at the beginning, we can skip the 1657231200Smm * compressed data much more quickly. 1658231200Smm */ 1659231200Smm bytes_skipped = __archive_read_consume(a, lha->entry_bytes_remaining); 1660231200Smm if (bytes_skipped < 0) 1661231200Smm return (ARCHIVE_FATAL); 1662231200Smm 1663231200Smm /* This entry is finished and done. */ 1664231200Smm lha->end_of_entry_cleanup = lha->end_of_entry = 1; 1665231200Smm return (ARCHIVE_OK); 1666231200Smm} 1667231200Smm 1668231200Smmstatic int 1669231200Smmarchive_read_format_lha_cleanup(struct archive_read *a) 1670231200Smm{ 1671231200Smm struct lha *lha = (struct lha *)(a->format->data); 1672231200Smm 1673231200Smm lzh_decode_free(&(lha->strm)); 1674231200Smm archive_string_free(&(lha->dirname)); 1675231200Smm archive_string_free(&(lha->filename)); 1676231200Smm archive_string_free(&(lha->uname)); 1677231200Smm archive_string_free(&(lha->gname)); 1678231200Smm archive_wstring_free(&(lha->ws)); 1679231200Smm free(lha); 1680231200Smm (a->format->data) = NULL; 1681231200Smm return (ARCHIVE_OK); 1682231200Smm} 1683231200Smm 1684231200Smm/* 1685231200Smm * 'LHa for UNIX' utility has archived a symbolic-link name after 1686231200Smm * a pathname with '|' character. 1687231200Smm * This function extracts the symbolic-link name from the pathname. 1688231200Smm * 1689231200Smm * example. 1690231200Smm * 1. a symbolic-name is 'aaa/bb/cc' 1691231200Smm * 2. a filename is 'xxx/bbb' 1692231200Smm * then a archived pathname is 'xxx/bbb|aaa/bb/cc' 1693231200Smm */ 1694231200Smmstatic int 1695358090Smmlha_parse_linkname(struct archive_wstring *linkname, 1696358090Smm struct archive_wstring *pathname) 1697231200Smm{ 1698358090Smm wchar_t * linkptr; 1699248616Smm size_t symlen; 1700231200Smm 1701358090Smm linkptr = wcschr(pathname->s, L'|'); 1702231200Smm if (linkptr != NULL) { 1703358090Smm symlen = wcslen(linkptr + 1); 1704358090Smm archive_wstrncpy(linkname, linkptr+1, symlen); 1705231200Smm 1706231200Smm *linkptr = 0; 1707358090Smm pathname->length = wcslen(pathname->s); 1708231200Smm 1709231200Smm return (1); 1710231200Smm } 1711231200Smm return (0); 1712231200Smm} 1713231200Smm 1714231200Smm/* Convert an MSDOS-style date/time into Unix-style time. */ 1715231200Smmstatic time_t 1716231200Smmlha_dos_time(const unsigned char *p) 1717231200Smm{ 1718231200Smm int msTime, msDate; 1719231200Smm struct tm ts; 1720231200Smm 1721231200Smm msTime = archive_le16dec(p); 1722231200Smm msDate = archive_le16dec(p+2); 1723231200Smm 1724231200Smm memset(&ts, 0, sizeof(ts)); 1725231200Smm ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ 1726231200Smm ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ 1727231200Smm ts.tm_mday = msDate & 0x1f; /* Day of month. */ 1728231200Smm ts.tm_hour = (msTime >> 11) & 0x1f; 1729231200Smm ts.tm_min = (msTime >> 5) & 0x3f; 1730231200Smm ts.tm_sec = (msTime << 1) & 0x3e; 1731231200Smm ts.tm_isdst = -1; 1732231200Smm return (mktime(&ts)); 1733231200Smm} 1734231200Smm 1735231200Smm/* Convert an MS-Windows-style date/time into Unix-style time. */ 1736231200Smmstatic time_t 1737231200Smmlha_win_time(uint64_t wintime, long *ns) 1738231200Smm{ 1739231200Smm#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) 1740231200Smm 1741231200Smm if (wintime >= EPOC_TIME) { 1742231200Smm wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */ 1743231200Smm if (ns != NULL) 1744231200Smm *ns = (long)(wintime % 10000000) * 100; 1745231200Smm return (wintime / 10000000); 1746231200Smm } else { 1747231200Smm if (ns != NULL) 1748231200Smm *ns = 0; 1749231200Smm return (0); 1750231200Smm } 1751231200Smm} 1752231200Smm 1753231200Smmstatic unsigned char 1754248616Smmlha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) 1755231200Smm{ 1756231200Smm unsigned char const *p = (unsigned char const *)pp; 1757231200Smm 1758231200Smm p += offset; 1759248616Smm for (;size > 0; --size) 1760231200Smm sum += *p++; 1761231200Smm return (sum); 1762231200Smm} 1763231200Smm 1764302001Smmstatic uint16_t crc16tbl[2][256]; 1765302001Smmstatic void 1766302001Smmlha_crc16_init(void) 1767302001Smm{ 1768302001Smm unsigned int i; 1769302001Smm static int crc16init = 0; 1770231200Smm 1771302001Smm if (crc16init) 1772302001Smm return; 1773302001Smm crc16init = 1; 1774302001Smm 1775302001Smm for (i = 0; i < 256; i++) { 1776302001Smm unsigned int j; 1777302001Smm uint16_t crc = (uint16_t)i; 1778302001Smm for (j = 8; j; j--) 1779302001Smm crc = (crc >> 1) ^ ((crc & 1) * 0xA001); 1780302001Smm crc16tbl[0][i] = crc; 1781302001Smm } 1782302001Smm 1783302001Smm for (i = 0; i < 256; i++) { 1784302001Smm crc16tbl[1][i] = (crc16tbl[0][i] >> 8) 1785302001Smm ^ crc16tbl[0][crc16tbl[0][i] & 0xff]; 1786302001Smm } 1787302001Smm} 1788302001Smm 1789231200Smmstatic uint16_t 1790231200Smmlha_crc16(uint16_t crc, const void *pp, size_t len) 1791231200Smm{ 1792302001Smm const unsigned char *p = (const unsigned char *)pp; 1793302001Smm const uint16_t *buff; 1794302001Smm const union { 1795302001Smm uint32_t i; 1796302001Smm char c[4]; 1797302001Smm } u = { 0x01020304 }; 1798231200Smm 1799302001Smm if (len == 0) 1800302001Smm return crc; 1801302001Smm 1802302001Smm /* Process unaligned address. */ 1803302001Smm if (((uintptr_t)p) & (uintptr_t)0x1) { 1804302001Smm crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff]; 1805302001Smm len--; 1806231200Smm } 1807302001Smm buff = (const uint16_t *)p; 1808302001Smm /* 1809302001Smm * Modern C compiler such as GCC does not unroll automatically yet 1810302001Smm * without unrolling pragma, and Clang is so. So we should 1811302001Smm * unroll this loop for its performance. 1812302001Smm */ 1813302001Smm for (;len >= 8; len -= 8) { 1814302001Smm /* This if statement expects compiler optimization will 1815313571Smm * remove the statement which will not be executed. */ 1816302295Smm#undef bswap16 1817302001Smm#if defined(_MSC_VER) && _MSC_VER >= 1400 /* Visual Studio */ 1818302001Smm# define bswap16(x) _byteswap_ushort(x) 1819305192Smm#elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ > 4) 1820305192Smm/* GCC 4.8 and later has __builtin_bswap16() */ 1821302001Smm# define bswap16(x) __builtin_bswap16(x) 1822305192Smm#elif defined(__clang__) 1823305192Smm/* All clang versions have __builtin_bswap16() */ 1824305192Smm# define bswap16(x) __builtin_bswap16(x) 1825302001Smm#else 1826302001Smm# define bswap16(x) ((((x) >> 8) & 0xff) | ((x) << 8)) 1827302001Smm#endif 1828302001Smm#define CRC16W do { \ 1829302001Smm if(u.c[0] == 1) { /* Big endian */ \ 1830302001Smm crc ^= bswap16(*buff); buff++; \ 1831302001Smm } else \ 1832302001Smm crc ^= *buff++; \ 1833302001Smm crc = crc16tbl[1][crc & 0xff] ^ crc16tbl[0][crc >> 8];\ 1834302001Smm} while (0) 1835302001Smm CRC16W; 1836302001Smm CRC16W; 1837302001Smm CRC16W; 1838302001Smm CRC16W; 1839302001Smm#undef CRC16W 1840302001Smm#undef bswap16 1841231200Smm } 1842302001Smm 1843302001Smm p = (const unsigned char *)buff; 1844302001Smm for (;len; len--) { 1845302001Smm crc = (crc >> 8) ^ crc16tbl[0][(crc ^ *p++) & 0xff]; 1846302001Smm } 1847302001Smm return crc; 1848231200Smm} 1849231200Smm 1850231200Smm/* 1851231200Smm * Initialize LZHUF decoder. 1852231200Smm * 1853231200Smm * Returns ARCHIVE_OK if initialization was successful. 1854231200Smm * Returns ARCHIVE_FAILED if method is unsupported. 1855231200Smm * Returns ARCHIVE_FATAL if initialization failed; memory allocation 1856231200Smm * error occurred. 1857231200Smm */ 1858231200Smmstatic int 1859231200Smmlzh_decode_init(struct lzh_stream *strm, const char *method) 1860231200Smm{ 1861231200Smm struct lzh_dec *ds; 1862231200Smm int w_bits, w_size; 1863231200Smm 1864231200Smm if (strm->ds == NULL) { 1865231200Smm strm->ds = calloc(1, sizeof(*strm->ds)); 1866231200Smm if (strm->ds == NULL) 1867231200Smm return (ARCHIVE_FATAL); 1868231200Smm } 1869231200Smm ds = strm->ds; 1870231200Smm ds->error = ARCHIVE_FAILED; 1871231200Smm if (method == NULL || method[0] != 'l' || method[1] != 'h') 1872231200Smm return (ARCHIVE_FAILED); 1873231200Smm switch (method[2]) { 1874231200Smm case '5': 1875231200Smm w_bits = 13;/* 8KiB for window */ 1876231200Smm break; 1877231200Smm case '6': 1878231200Smm w_bits = 15;/* 32KiB for window */ 1879231200Smm break; 1880231200Smm case '7': 1881231200Smm w_bits = 16;/* 64KiB for window */ 1882231200Smm break; 1883231200Smm default: 1884231200Smm return (ARCHIVE_FAILED);/* Not supported. */ 1885231200Smm } 1886231200Smm ds->error = ARCHIVE_FATAL; 1887302001Smm /* Expand a window size up to 128 KiB for decompressing process 1888302001Smm * performance whatever its original window size is. */ 1889302001Smm ds->w_size = 1U << 17; 1890231200Smm ds->w_mask = ds->w_size -1; 1891302001Smm if (ds->w_buff == NULL) { 1892231200Smm ds->w_buff = malloc(ds->w_size); 1893231200Smm if (ds->w_buff == NULL) 1894231200Smm return (ARCHIVE_FATAL); 1895231200Smm } 1896302001Smm w_size = 1U << w_bits; 1897302001Smm memset(ds->w_buff + ds->w_size - w_size, 0x20, w_size); 1898231200Smm ds->w_pos = 0; 1899231200Smm ds->state = 0; 1900231200Smm ds->pos_pt_len_size = w_bits + 1; 1901231200Smm ds->pos_pt_len_bits = (w_bits == 15 || w_bits == 16)? 5: 4; 1902231200Smm ds->literal_pt_len_size = PT_BITLEN_SIZE; 1903231200Smm ds->literal_pt_len_bits = 5; 1904231200Smm ds->br.cache_buffer = 0; 1905231200Smm ds->br.cache_avail = 0; 1906231200Smm 1907231200Smm if (lzh_huffman_init(&(ds->lt), LT_BITLEN_SIZE, 16) 1908231200Smm != ARCHIVE_OK) 1909231200Smm return (ARCHIVE_FATAL); 1910231200Smm ds->lt.len_bits = 9; 1911231200Smm if (lzh_huffman_init(&(ds->pt), PT_BITLEN_SIZE, 16) 1912231200Smm != ARCHIVE_OK) 1913231200Smm return (ARCHIVE_FATAL); 1914231200Smm ds->error = 0; 1915231200Smm 1916231200Smm return (ARCHIVE_OK); 1917231200Smm} 1918231200Smm 1919231200Smm/* 1920231200Smm * Release LZHUF decoder. 1921231200Smm */ 1922231200Smmstatic void 1923231200Smmlzh_decode_free(struct lzh_stream *strm) 1924231200Smm{ 1925231200Smm 1926231200Smm if (strm->ds == NULL) 1927231200Smm return; 1928231200Smm free(strm->ds->w_buff); 1929231200Smm lzh_huffman_free(&(strm->ds->lt)); 1930231200Smm lzh_huffman_free(&(strm->ds->pt)); 1931231200Smm free(strm->ds); 1932231200Smm strm->ds = NULL; 1933231200Smm} 1934231200Smm 1935231200Smm/* 1936231200Smm * Bit stream reader. 1937231200Smm */ 1938231200Smm/* Check that the cache buffer has enough bits. */ 1939231200Smm#define lzh_br_has(br, n) ((br)->cache_avail >= n) 1940231200Smm/* Get compressed data by bit. */ 1941231200Smm#define lzh_br_bits(br, n) \ 1942231200Smm (((uint16_t)((br)->cache_buffer >> \ 1943231200Smm ((br)->cache_avail - (n)))) & cache_masks[n]) 1944231200Smm#define lzh_br_bits_forced(br, n) \ 1945231200Smm (((uint16_t)((br)->cache_buffer << \ 1946231200Smm ((n) - (br)->cache_avail))) & cache_masks[n]) 1947231200Smm/* Read ahead to make sure the cache buffer has enough compressed data we 1948231200Smm * will use. 1949231200Smm * True : completed, there is enough data in the cache buffer. 1950231200Smm * False : we met that strm->next_in is empty, we have to get following 1951231200Smm * bytes. */ 1952231200Smm#define lzh_br_read_ahead_0(strm, br, n) \ 1953231200Smm (lzh_br_has(br, (n)) || lzh_br_fillup(strm, br)) 1954231200Smm/* True : the cache buffer has some bits as much as we need. 1955231200Smm * False : there are no enough bits in the cache buffer to be used, 1956231200Smm * we have to get following bytes if we could. */ 1957231200Smm#define lzh_br_read_ahead(strm, br, n) \ 1958231200Smm (lzh_br_read_ahead_0((strm), (br), (n)) || lzh_br_has((br), (n))) 1959231200Smm 1960231200Smm/* Notify how many bits we consumed. */ 1961231200Smm#define lzh_br_consume(br, n) ((br)->cache_avail -= (n)) 1962231200Smm#define lzh_br_unconsume(br, n) ((br)->cache_avail += (n)) 1963231200Smm 1964231200Smmstatic const uint16_t cache_masks[] = { 1965231200Smm 0x0000, 0x0001, 0x0003, 0x0007, 1966231200Smm 0x000F, 0x001F, 0x003F, 0x007F, 1967231200Smm 0x00FF, 0x01FF, 0x03FF, 0x07FF, 1968231200Smm 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 1969231200Smm 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF 1970231200Smm}; 1971231200Smm 1972231200Smm/* 1973231200Smm * Shift away used bits in the cache data and fill it up with following bits. 1974231200Smm * Call this when cache buffer does not have enough bits you need. 1975231200Smm * 1976231200Smm * Returns 1 if the cache buffer is full. 1977231200Smm * Returns 0 if the cache buffer is not full; input buffer is empty. 1978231200Smm */ 1979231200Smmstatic int 1980231200Smmlzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br) 1981231200Smm{ 1982231200Smm int n = CACHE_BITS - br->cache_avail; 1983231200Smm 1984231200Smm for (;;) { 1985302001Smm const int x = n >> 3; 1986302001Smm if (strm->avail_in >= x) { 1987302001Smm switch (x) { 1988302001Smm case 8: 1989231200Smm br->cache_buffer = 1990231200Smm ((uint64_t)strm->next_in[0]) << 56 | 1991231200Smm ((uint64_t)strm->next_in[1]) << 48 | 1992231200Smm ((uint64_t)strm->next_in[2]) << 40 | 1993231200Smm ((uint64_t)strm->next_in[3]) << 32 | 1994231200Smm ((uint32_t)strm->next_in[4]) << 24 | 1995231200Smm ((uint32_t)strm->next_in[5]) << 16 | 1996231200Smm ((uint32_t)strm->next_in[6]) << 8 | 1997231200Smm (uint32_t)strm->next_in[7]; 1998231200Smm strm->next_in += 8; 1999231200Smm strm->avail_in -= 8; 2000231200Smm br->cache_avail += 8 * 8; 2001231200Smm return (1); 2002302001Smm case 7: 2003231200Smm br->cache_buffer = 2004231200Smm (br->cache_buffer << 56) | 2005231200Smm ((uint64_t)strm->next_in[0]) << 48 | 2006231200Smm ((uint64_t)strm->next_in[1]) << 40 | 2007231200Smm ((uint64_t)strm->next_in[2]) << 32 | 2008231200Smm ((uint32_t)strm->next_in[3]) << 24 | 2009231200Smm ((uint32_t)strm->next_in[4]) << 16 | 2010231200Smm ((uint32_t)strm->next_in[5]) << 8 | 2011231200Smm (uint32_t)strm->next_in[6]; 2012231200Smm strm->next_in += 7; 2013231200Smm strm->avail_in -= 7; 2014231200Smm br->cache_avail += 7 * 8; 2015231200Smm return (1); 2016302001Smm case 6: 2017231200Smm br->cache_buffer = 2018231200Smm (br->cache_buffer << 48) | 2019231200Smm ((uint64_t)strm->next_in[0]) << 40 | 2020231200Smm ((uint64_t)strm->next_in[1]) << 32 | 2021231200Smm ((uint32_t)strm->next_in[2]) << 24 | 2022231200Smm ((uint32_t)strm->next_in[3]) << 16 | 2023231200Smm ((uint32_t)strm->next_in[4]) << 8 | 2024231200Smm (uint32_t)strm->next_in[5]; 2025231200Smm strm->next_in += 6; 2026231200Smm strm->avail_in -= 6; 2027231200Smm br->cache_avail += 6 * 8; 2028231200Smm return (1); 2029302001Smm case 0: 2030302001Smm /* We have enough compressed data in 2031302001Smm * the cache buffer.*/ 2032302001Smm return (1); 2033302001Smm default: 2034302001Smm break; 2035231200Smm } 2036231200Smm } 2037231200Smm if (strm->avail_in == 0) { 2038231200Smm /* There is not enough compressed data to fill up the 2039231200Smm * cache buffer. */ 2040231200Smm return (0); 2041231200Smm } 2042231200Smm br->cache_buffer = 2043231200Smm (br->cache_buffer << 8) | *strm->next_in++; 2044231200Smm strm->avail_in--; 2045231200Smm br->cache_avail += 8; 2046231200Smm n -= 8; 2047231200Smm } 2048231200Smm} 2049231200Smm 2050231200Smm/* 2051231200Smm * Decode LZHUF. 2052231200Smm * 2053231200Smm * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty. 2054231200Smm * Please set available buffer and call this function again. 2055231200Smm * 2. Returns ARCHIVE_EOF if decompression has been completed. 2056231200Smm * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data 2057231200Smm * is broken or you do not set 'last' flag properly. 2058231200Smm * 4. 'last' flag is very important, you must set 1 to the flag if there 2059231200Smm * is no input data. The lha compressed data format does not provide how 2060231200Smm * to know the compressed data is really finished. 2061231200Smm * Note: lha command utility check if the total size of output bytes is 2062231200Smm * reached the uncompressed size recorded in its header. it does not mind 2063231200Smm * that the decoding process is properly finished. 2064231200Smm * GNU ZIP can decompress another compressed file made by SCO LZH compress. 2065231200Smm * it handles EOF as null to fill read buffer with zero until the decoding 2066231200Smm * process meet 2 bytes of zeros at reading a size of a next chunk, so the 2067231200Smm * zeros are treated as the mark of the end of the data although the zeros 2068231200Smm * is dummy, not the file data. 2069231200Smm */ 2070231200Smmstatic int lzh_read_blocks(struct lzh_stream *, int); 2071231200Smmstatic int lzh_decode_blocks(struct lzh_stream *, int); 2072231200Smm#define ST_RD_BLOCK 0 2073231200Smm#define ST_RD_PT_1 1 2074231200Smm#define ST_RD_PT_2 2 2075231200Smm#define ST_RD_PT_3 3 2076231200Smm#define ST_RD_PT_4 4 2077231200Smm#define ST_RD_LITERAL_1 5 2078231200Smm#define ST_RD_LITERAL_2 6 2079231200Smm#define ST_RD_LITERAL_3 7 2080231200Smm#define ST_RD_POS_DATA_1 8 2081231200Smm#define ST_GET_LITERAL 9 2082231200Smm#define ST_GET_POS_1 10 2083231200Smm#define ST_GET_POS_2 11 2084231200Smm#define ST_COPY_DATA 12 2085231200Smm 2086231200Smmstatic int 2087231200Smmlzh_decode(struct lzh_stream *strm, int last) 2088231200Smm{ 2089231200Smm struct lzh_dec *ds = strm->ds; 2090302001Smm int avail_in; 2091231200Smm int r; 2092231200Smm 2093231200Smm if (ds->error) 2094231200Smm return (ds->error); 2095231200Smm 2096231200Smm avail_in = strm->avail_in; 2097231200Smm do { 2098231200Smm if (ds->state < ST_GET_LITERAL) 2099231200Smm r = lzh_read_blocks(strm, last); 2100231200Smm else 2101231200Smm r = lzh_decode_blocks(strm, last); 2102231200Smm } while (r == 100); 2103231200Smm strm->total_in += avail_in - strm->avail_in; 2104231200Smm return (r); 2105231200Smm} 2106231200Smm 2107302001Smmstatic void 2108302001Smmlzh_emit_window(struct lzh_stream *strm, size_t s) 2109231200Smm{ 2110302001Smm strm->ref_ptr = strm->ds->w_buff; 2111302001Smm strm->avail_out = (int)s; 2112302001Smm strm->total_out += s; 2113231200Smm} 2114231200Smm 2115231200Smmstatic int 2116231200Smmlzh_read_blocks(struct lzh_stream *strm, int last) 2117231200Smm{ 2118231200Smm struct lzh_dec *ds = strm->ds; 2119231200Smm struct lzh_br *br = &(ds->br); 2120231200Smm int c = 0, i; 2121231200Smm unsigned rbits; 2122231200Smm 2123231200Smm for (;;) { 2124231200Smm switch (ds->state) { 2125231200Smm case ST_RD_BLOCK: 2126231200Smm /* 2127231200Smm * Read a block number indicates how many blocks 2128231200Smm * we will handle. The block is composed of a 2129231200Smm * literal and a match, sometimes a literal only 2130231200Smm * in particular, there are no reference data at 2131231200Smm * the beginning of the decompression. 2132231200Smm */ 2133231200Smm if (!lzh_br_read_ahead_0(strm, br, 16)) { 2134231200Smm if (!last) 2135231200Smm /* We need following data. */ 2136231200Smm return (ARCHIVE_OK); 2137231200Smm if (lzh_br_has(br, 8)) { 2138231200Smm /* 2139231200Smm * It seems there are extra bits. 2140231200Smm * 1. Compressed data is broken. 2141231200Smm * 2. `last' flag does not properly 2142231200Smm * set. 2143231200Smm */ 2144231200Smm goto failed; 2145231200Smm } 2146231200Smm if (ds->w_pos > 0) { 2147302001Smm lzh_emit_window(strm, ds->w_pos); 2148302001Smm ds->w_pos = 0; 2149302001Smm return (ARCHIVE_OK); 2150231200Smm } 2151231200Smm /* End of compressed data; we have completely 2152231200Smm * handled all compressed data. */ 2153231200Smm return (ARCHIVE_EOF); 2154231200Smm } 2155231200Smm ds->blocks_avail = lzh_br_bits(br, 16); 2156231200Smm if (ds->blocks_avail == 0) 2157231200Smm goto failed; 2158231200Smm lzh_br_consume(br, 16); 2159231200Smm /* 2160231200Smm * Read a literal table compressed in huffman 2161231200Smm * coding. 2162231200Smm */ 2163231200Smm ds->pt.len_size = ds->literal_pt_len_size; 2164231200Smm ds->pt.len_bits = ds->literal_pt_len_bits; 2165231200Smm ds->reading_position = 0; 2166231200Smm /* FALL THROUGH */ 2167231200Smm case ST_RD_PT_1: 2168231200Smm /* Note: ST_RD_PT_1, ST_RD_PT_2 and ST_RD_PT_4 are 2169231200Smm * used in reading both a literal table and a 2170231200Smm * position table. */ 2171231200Smm if (!lzh_br_read_ahead(strm, br, ds->pt.len_bits)) { 2172231200Smm if (last) 2173231200Smm goto failed;/* Truncated data. */ 2174231200Smm ds->state = ST_RD_PT_1; 2175231200Smm return (ARCHIVE_OK); 2176231200Smm } 2177231200Smm ds->pt.len_avail = lzh_br_bits(br, ds->pt.len_bits); 2178231200Smm lzh_br_consume(br, ds->pt.len_bits); 2179231200Smm /* FALL THROUGH */ 2180231200Smm case ST_RD_PT_2: 2181231200Smm if (ds->pt.len_avail == 0) { 2182231200Smm /* There is no bitlen. */ 2183231200Smm if (!lzh_br_read_ahead(strm, br, 2184231200Smm ds->pt.len_bits)) { 2185231200Smm if (last) 2186231200Smm goto failed;/* Truncated data.*/ 2187231200Smm ds->state = ST_RD_PT_2; 2188231200Smm return (ARCHIVE_OK); 2189231200Smm } 2190231200Smm if (!lzh_make_fake_table(&(ds->pt), 2191231200Smm lzh_br_bits(br, ds->pt.len_bits))) 2192231200Smm goto failed;/* Invalid data. */ 2193231200Smm lzh_br_consume(br, ds->pt.len_bits); 2194231200Smm if (ds->reading_position) 2195231200Smm ds->state = ST_GET_LITERAL; 2196231200Smm else 2197231200Smm ds->state = ST_RD_LITERAL_1; 2198231200Smm break; 2199231200Smm } else if (ds->pt.len_avail > ds->pt.len_size) 2200231200Smm goto failed;/* Invalid data. */ 2201231200Smm ds->loop = 0; 2202231200Smm memset(ds->pt.freq, 0, sizeof(ds->pt.freq)); 2203231200Smm if (ds->pt.len_avail < 3 || 2204231200Smm ds->pt.len_size == ds->pos_pt_len_size) { 2205231200Smm ds->state = ST_RD_PT_4; 2206231200Smm break; 2207231200Smm } 2208231200Smm /* FALL THROUGH */ 2209231200Smm case ST_RD_PT_3: 2210231200Smm ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 3); 2211231200Smm if (ds->loop < 3) { 2212231200Smm if (ds->loop < 0 || last) 2213231200Smm goto failed;/* Invalid data. */ 2214231200Smm /* Not completed, get following data. */ 2215231200Smm ds->state = ST_RD_PT_3; 2216231200Smm return (ARCHIVE_OK); 2217231200Smm } 2218231200Smm /* There are some null in bitlen of the literal. */ 2219231200Smm if (!lzh_br_read_ahead(strm, br, 2)) { 2220231200Smm if (last) 2221231200Smm goto failed;/* Truncated data. */ 2222231200Smm ds->state = ST_RD_PT_3; 2223231200Smm return (ARCHIVE_OK); 2224231200Smm } 2225231200Smm c = lzh_br_bits(br, 2); 2226231200Smm lzh_br_consume(br, 2); 2227231200Smm if (c > ds->pt.len_avail - 3) 2228231200Smm goto failed;/* Invalid data. */ 2229231200Smm for (i = 3; c-- > 0 ;) 2230231200Smm ds->pt.bitlen[i++] = 0; 2231231200Smm ds->loop = i; 2232231200Smm /* FALL THROUGH */ 2233231200Smm case ST_RD_PT_4: 2234231200Smm ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 2235231200Smm ds->pt.len_avail); 2236231200Smm if (ds->loop < ds->pt.len_avail) { 2237231200Smm if (ds->loop < 0 || last) 2238231200Smm goto failed;/* Invalid data. */ 2239231200Smm /* Not completed, get following data. */ 2240231200Smm ds->state = ST_RD_PT_4; 2241231200Smm return (ARCHIVE_OK); 2242231200Smm } 2243231200Smm if (!lzh_make_huffman_table(&(ds->pt))) 2244231200Smm goto failed;/* Invalid data */ 2245231200Smm if (ds->reading_position) { 2246231200Smm ds->state = ST_GET_LITERAL; 2247231200Smm break; 2248231200Smm } 2249231200Smm /* FALL THROUGH */ 2250231200Smm case ST_RD_LITERAL_1: 2251231200Smm if (!lzh_br_read_ahead(strm, br, ds->lt.len_bits)) { 2252231200Smm if (last) 2253231200Smm goto failed;/* Truncated data. */ 2254231200Smm ds->state = ST_RD_LITERAL_1; 2255231200Smm return (ARCHIVE_OK); 2256231200Smm } 2257231200Smm ds->lt.len_avail = lzh_br_bits(br, ds->lt.len_bits); 2258231200Smm lzh_br_consume(br, ds->lt.len_bits); 2259231200Smm /* FALL THROUGH */ 2260231200Smm case ST_RD_LITERAL_2: 2261231200Smm if (ds->lt.len_avail == 0) { 2262231200Smm /* There is no bitlen. */ 2263231200Smm if (!lzh_br_read_ahead(strm, br, 2264231200Smm ds->lt.len_bits)) { 2265231200Smm if (last) 2266231200Smm goto failed;/* Truncated data.*/ 2267231200Smm ds->state = ST_RD_LITERAL_2; 2268231200Smm return (ARCHIVE_OK); 2269231200Smm } 2270231200Smm if (!lzh_make_fake_table(&(ds->lt), 2271231200Smm lzh_br_bits(br, ds->lt.len_bits))) 2272231200Smm goto failed;/* Invalid data */ 2273231200Smm lzh_br_consume(br, ds->lt.len_bits); 2274231200Smm ds->state = ST_RD_POS_DATA_1; 2275231200Smm break; 2276231200Smm } else if (ds->lt.len_avail > ds->lt.len_size) 2277231200Smm goto failed;/* Invalid data */ 2278231200Smm ds->loop = 0; 2279231200Smm memset(ds->lt.freq, 0, sizeof(ds->lt.freq)); 2280231200Smm /* FALL THROUGH */ 2281231200Smm case ST_RD_LITERAL_3: 2282231200Smm i = ds->loop; 2283231200Smm while (i < ds->lt.len_avail) { 2284231200Smm if (!lzh_br_read_ahead(strm, br, 2285231200Smm ds->pt.max_bits)) { 2286231200Smm if (last) 2287231200Smm goto failed;/* Truncated data.*/ 2288231200Smm ds->loop = i; 2289231200Smm ds->state = ST_RD_LITERAL_3; 2290231200Smm return (ARCHIVE_OK); 2291231200Smm } 2292231200Smm rbits = lzh_br_bits(br, ds->pt.max_bits); 2293231200Smm c = lzh_decode_huffman(&(ds->pt), rbits); 2294231200Smm if (c > 2) { 2295231200Smm /* Note: 'c' will never be more than 2296231200Smm * eighteen since it's limited by 2297231200Smm * PT_BITLEN_SIZE, which is being set 2298231200Smm * to ds->pt.len_size through 2299231200Smm * ds->literal_pt_len_size. */ 2300231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2301231200Smm c -= 2; 2302231200Smm ds->lt.freq[c]++; 2303231200Smm ds->lt.bitlen[i++] = c; 2304231200Smm } else if (c == 0) { 2305231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2306231200Smm ds->lt.bitlen[i++] = 0; 2307231200Smm } else { 2308231200Smm /* c == 1 or c == 2 */ 2309231200Smm int n = (c == 1)?4:9; 2310231200Smm if (!lzh_br_read_ahead(strm, br, 2311231200Smm ds->pt.bitlen[c] + n)) { 2312231200Smm if (last) /* Truncated data. */ 2313231200Smm goto failed; 2314231200Smm ds->loop = i; 2315231200Smm ds->state = ST_RD_LITERAL_3; 2316231200Smm return (ARCHIVE_OK); 2317231200Smm } 2318231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2319231200Smm c = lzh_br_bits(br, n); 2320231200Smm lzh_br_consume(br, n); 2321231200Smm c += (n == 4)?3:20; 2322231200Smm if (i + c > ds->lt.len_avail) 2323231200Smm goto failed;/* Invalid data */ 2324231200Smm memset(&(ds->lt.bitlen[i]), 0, c); 2325231200Smm i += c; 2326231200Smm } 2327231200Smm } 2328231200Smm if (i > ds->lt.len_avail || 2329231200Smm !lzh_make_huffman_table(&(ds->lt))) 2330231200Smm goto failed;/* Invalid data */ 2331231200Smm /* FALL THROUGH */ 2332231200Smm case ST_RD_POS_DATA_1: 2333231200Smm /* 2334231200Smm * Read a position table compressed in huffman 2335231200Smm * coding. 2336231200Smm */ 2337231200Smm ds->pt.len_size = ds->pos_pt_len_size; 2338231200Smm ds->pt.len_bits = ds->pos_pt_len_bits; 2339231200Smm ds->reading_position = 1; 2340231200Smm ds->state = ST_RD_PT_1; 2341231200Smm break; 2342231200Smm case ST_GET_LITERAL: 2343231200Smm return (100); 2344231200Smm } 2345231200Smm } 2346231200Smmfailed: 2347231200Smm return (ds->error = ARCHIVE_FAILED); 2348231200Smm} 2349231200Smm 2350231200Smmstatic int 2351231200Smmlzh_decode_blocks(struct lzh_stream *strm, int last) 2352231200Smm{ 2353231200Smm struct lzh_dec *ds = strm->ds; 2354231200Smm struct lzh_br bre = ds->br; 2355231200Smm struct huffman *lt = &(ds->lt); 2356231200Smm struct huffman *pt = &(ds->pt); 2357231200Smm unsigned char *w_buff = ds->w_buff; 2358231200Smm unsigned char *lt_bitlen = lt->bitlen; 2359231200Smm unsigned char *pt_bitlen = pt->bitlen; 2360231200Smm int blocks_avail = ds->blocks_avail, c = 0; 2361231200Smm int copy_len = ds->copy_len, copy_pos = ds->copy_pos; 2362231200Smm int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size; 2363231200Smm int lt_max_bits = lt->max_bits, pt_max_bits = pt->max_bits; 2364231200Smm int state = ds->state; 2365231200Smm 2366231200Smm for (;;) { 2367231200Smm switch (state) { 2368231200Smm case ST_GET_LITERAL: 2369231200Smm for (;;) { 2370231200Smm if (blocks_avail == 0) { 2371231200Smm /* We have decoded all blocks. 2372231200Smm * Let's handle next blocks. */ 2373231200Smm ds->state = ST_RD_BLOCK; 2374231200Smm ds->br = bre; 2375231200Smm ds->blocks_avail = 0; 2376231200Smm ds->w_pos = w_pos; 2377231200Smm ds->copy_pos = 0; 2378231200Smm return (100); 2379231200Smm } 2380231200Smm 2381231200Smm /* lzh_br_read_ahead() always try to fill the 2382231200Smm * cache buffer up. In specific situation we 2383231200Smm * are close to the end of the data, the cache 2384231200Smm * buffer will not be full and thus we have to 2385231200Smm * determine if the cache buffer has some bits 2386231200Smm * as much as we need after lzh_br_read_ahead() 2387231200Smm * failed. */ 2388231200Smm if (!lzh_br_read_ahead(strm, &bre, 2389231200Smm lt_max_bits)) { 2390231200Smm if (!last) 2391231200Smm goto next_data; 2392231200Smm /* Remaining bits are less than 2393231200Smm * maximum bits(lt.max_bits) but maybe 2394231200Smm * it still remains as much as we need, 2395231200Smm * so we should try to use it with 2396231200Smm * dummy bits. */ 2397231200Smm c = lzh_decode_huffman(lt, 2398231200Smm lzh_br_bits_forced(&bre, 2399231200Smm lt_max_bits)); 2400231200Smm lzh_br_consume(&bre, lt_bitlen[c]); 2401231200Smm if (!lzh_br_has(&bre, 0)) 2402231200Smm goto failed;/* Over read. */ 2403231200Smm } else { 2404231200Smm c = lzh_decode_huffman(lt, 2405231200Smm lzh_br_bits(&bre, lt_max_bits)); 2406231200Smm lzh_br_consume(&bre, lt_bitlen[c]); 2407231200Smm } 2408231200Smm blocks_avail--; 2409231200Smm if (c > UCHAR_MAX) 2410231200Smm /* Current block is a match data. */ 2411231200Smm break; 2412231200Smm /* 2413231200Smm * 'c' is exactly a literal code. 2414231200Smm */ 2415231200Smm /* Save a decoded code to reference it 2416231200Smm * afterward. */ 2417231200Smm w_buff[w_pos] = c; 2418231200Smm if (++w_pos >= w_size) { 2419231200Smm w_pos = 0; 2420302001Smm lzh_emit_window(strm, w_size); 2421302001Smm goto next_data; 2422231200Smm } 2423231200Smm } 2424231200Smm /* 'c' is the length of a match pattern we have 2425231200Smm * already extracted, which has be stored in 2426231200Smm * window(ds->w_buff). */ 2427231200Smm copy_len = c - (UCHAR_MAX + 1) + MINMATCH; 2428231200Smm /* FALL THROUGH */ 2429231200Smm case ST_GET_POS_1: 2430231200Smm /* 2431231200Smm * Get a reference position. 2432231200Smm */ 2433231200Smm if (!lzh_br_read_ahead(strm, &bre, pt_max_bits)) { 2434231200Smm if (!last) { 2435231200Smm state = ST_GET_POS_1; 2436231200Smm ds->copy_len = copy_len; 2437231200Smm goto next_data; 2438231200Smm } 2439231200Smm copy_pos = lzh_decode_huffman(pt, 2440231200Smm lzh_br_bits_forced(&bre, pt_max_bits)); 2441231200Smm lzh_br_consume(&bre, pt_bitlen[copy_pos]); 2442231200Smm if (!lzh_br_has(&bre, 0)) 2443231200Smm goto failed;/* Over read. */ 2444231200Smm } else { 2445231200Smm copy_pos = lzh_decode_huffman(pt, 2446231200Smm lzh_br_bits(&bre, pt_max_bits)); 2447231200Smm lzh_br_consume(&bre, pt_bitlen[copy_pos]); 2448231200Smm } 2449231200Smm /* FALL THROUGH */ 2450231200Smm case ST_GET_POS_2: 2451231200Smm if (copy_pos > 1) { 2452231200Smm /* We need an additional adjustment number to 2453231200Smm * the position. */ 2454231200Smm int p = copy_pos - 1; 2455231200Smm if (!lzh_br_read_ahead(strm, &bre, p)) { 2456231200Smm if (last) 2457231200Smm goto failed;/* Truncated data.*/ 2458231200Smm state = ST_GET_POS_2; 2459231200Smm ds->copy_len = copy_len; 2460231200Smm ds->copy_pos = copy_pos; 2461231200Smm goto next_data; 2462231200Smm } 2463231200Smm copy_pos = (1 << p) + lzh_br_bits(&bre, p); 2464231200Smm lzh_br_consume(&bre, p); 2465231200Smm } 2466231200Smm /* The position is actually a distance from the last 2467231200Smm * code we had extracted and thus we have to convert 2468231200Smm * it to a position of the window. */ 2469231200Smm copy_pos = (w_pos - copy_pos - 1) & w_mask; 2470231200Smm /* FALL THROUGH */ 2471231200Smm case ST_COPY_DATA: 2472231200Smm /* 2473231200Smm * Copy `copy_len' bytes as extracted data from 2474231200Smm * the window into the output buffer. 2475231200Smm */ 2476231200Smm for (;;) { 2477231200Smm int l; 2478231200Smm 2479231200Smm l = copy_len; 2480231200Smm if (copy_pos > w_pos) { 2481231200Smm if (l > w_size - copy_pos) 2482231200Smm l = w_size - copy_pos; 2483231200Smm } else { 2484231200Smm if (l > w_size - w_pos) 2485231200Smm l = w_size - w_pos; 2486231200Smm } 2487231200Smm if ((copy_pos + l < w_pos) 2488231200Smm || (w_pos + l < copy_pos)) { 2489231200Smm /* No overlap. */ 2490231200Smm memcpy(w_buff + w_pos, 2491231200Smm w_buff + copy_pos, l); 2492231200Smm } else { 2493231200Smm const unsigned char *s; 2494231200Smm unsigned char *d; 2495231200Smm int li; 2496231200Smm 2497231200Smm d = w_buff + w_pos; 2498231200Smm s = w_buff + copy_pos; 2499302001Smm for (li = 0; li < l-1;) { 2500302001Smm d[li] = s[li];li++; 2501302001Smm d[li] = s[li];li++; 2502302001Smm } 2503302001Smm if (li < l) 2504231200Smm d[li] = s[li]; 2505231200Smm } 2506302001Smm w_pos += l; 2507302001Smm if (w_pos == w_size) { 2508302001Smm w_pos = 0; 2509302001Smm lzh_emit_window(strm, w_size); 2510302001Smm if (copy_len <= l) 2511302001Smm state = ST_GET_LITERAL; 2512302001Smm else { 2513302001Smm state = ST_COPY_DATA; 2514302001Smm ds->copy_len = copy_len - l; 2515302001Smm ds->copy_pos = 2516302001Smm (copy_pos + l) & w_mask; 2517231200Smm } 2518302001Smm goto next_data; 2519231200Smm } 2520231200Smm if (copy_len <= l) 2521231200Smm /* A copy of current pattern ended. */ 2522231200Smm break; 2523231200Smm copy_len -= l; 2524231200Smm copy_pos = (copy_pos + l) & w_mask; 2525231200Smm } 2526231200Smm state = ST_GET_LITERAL; 2527231200Smm break; 2528231200Smm } 2529231200Smm } 2530231200Smmfailed: 2531231200Smm return (ds->error = ARCHIVE_FAILED); 2532231200Smmnext_data: 2533231200Smm ds->br = bre; 2534231200Smm ds->blocks_avail = blocks_avail; 2535231200Smm ds->state = state; 2536231200Smm ds->w_pos = w_pos; 2537231200Smm return (ARCHIVE_OK); 2538231200Smm} 2539231200Smm 2540231200Smmstatic int 2541231200Smmlzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) 2542231200Smm{ 2543231200Smm int bits; 2544231200Smm 2545231200Smm if (hf->bitlen == NULL) { 2546231200Smm hf->bitlen = malloc(len_size * sizeof(hf->bitlen[0])); 2547231200Smm if (hf->bitlen == NULL) 2548231200Smm return (ARCHIVE_FATAL); 2549231200Smm } 2550231200Smm if (hf->tbl == NULL) { 2551231200Smm if (tbl_bits < HTBL_BITS) 2552231200Smm bits = tbl_bits; 2553231200Smm else 2554231200Smm bits = HTBL_BITS; 2555248616Smm hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0])); 2556231200Smm if (hf->tbl == NULL) 2557231200Smm return (ARCHIVE_FATAL); 2558231200Smm } 2559231200Smm if (hf->tree == NULL && tbl_bits > HTBL_BITS) { 2560231200Smm hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4); 2561231200Smm hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0])); 2562231200Smm if (hf->tree == NULL) 2563231200Smm return (ARCHIVE_FATAL); 2564231200Smm } 2565248616Smm hf->len_size = (int)len_size; 2566231200Smm hf->tbl_bits = tbl_bits; 2567231200Smm return (ARCHIVE_OK); 2568231200Smm} 2569231200Smm 2570231200Smmstatic void 2571231200Smmlzh_huffman_free(struct huffman *hf) 2572231200Smm{ 2573231200Smm free(hf->bitlen); 2574231200Smm free(hf->tbl); 2575231200Smm free(hf->tree); 2576231200Smm} 2577231200Smm 2578316338Smmstatic const char bitlen_tbl[0x400] = { 2579302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2580302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2581302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2582302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2583302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2584302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2585302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2586302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2587302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2588302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2589302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2590302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2591302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2592302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2593302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2594302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2595302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2596302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2597302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2598302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2599302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2600302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2601302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2602302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2603302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2604302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2605302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2606302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2607302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2608302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2609302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2610302001Smm 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2611302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2612302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2613302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2614302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2615302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2616302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2617302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2618302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2619302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2620302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2621302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2622302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2623302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2624302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2625302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2626302001Smm 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2627302001Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2628302001Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2629302001Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2630302001Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2631302001Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2632302001Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2633302001Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2634302001Smm 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2635302001Smm 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2636302001Smm 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2637302001Smm 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2638302001Smm 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2639302001Smm 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2640302001Smm 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2641302001Smm 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2642302001Smm 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 16, 0 2643302001Smm}; 2644231200Smmstatic int 2645231200Smmlzh_read_pt_bitlen(struct lzh_stream *strm, int start, int end) 2646231200Smm{ 2647231200Smm struct lzh_dec *ds = strm->ds; 2648302001Smm struct lzh_br *br = &(ds->br); 2649231200Smm int c, i; 2650231200Smm 2651302001Smm for (i = start; i < end; ) { 2652231200Smm /* 2653231200Smm * bit pattern the number we need 2654231200Smm * 000 -> 0 2655231200Smm * 001 -> 1 2656231200Smm * 010 -> 2 2657231200Smm * ... 2658231200Smm * 110 -> 6 2659231200Smm * 1110 -> 7 2660231200Smm * 11110 -> 8 2661231200Smm * ... 2662231200Smm * 1111111111110 -> 16 2663231200Smm */ 2664231200Smm if (!lzh_br_read_ahead(strm, br, 3)) 2665231200Smm return (i); 2666231200Smm if ((c = lzh_br_bits(br, 3)) == 7) { 2667231200Smm if (!lzh_br_read_ahead(strm, br, 13)) 2668231200Smm return (i); 2669302001Smm c = bitlen_tbl[lzh_br_bits(br, 13) & 0x3FF]; 2670302001Smm if (c) 2671302001Smm lzh_br_consume(br, c - 3); 2672302001Smm else 2673231200Smm return (-1);/* Invalid data. */ 2674231200Smm } else 2675231200Smm lzh_br_consume(br, 3); 2676231200Smm ds->pt.bitlen[i++] = c; 2677231200Smm ds->pt.freq[c]++; 2678231200Smm } 2679231200Smm return (i); 2680231200Smm} 2681231200Smm 2682231200Smmstatic int 2683231200Smmlzh_make_fake_table(struct huffman *hf, uint16_t c) 2684231200Smm{ 2685231200Smm if (c >= hf->len_size) 2686231200Smm return (0); 2687231200Smm hf->tbl[0] = c; 2688231200Smm hf->max_bits = 0; 2689231200Smm hf->shift_bits = 0; 2690231200Smm hf->bitlen[hf->tbl[0]] = 0; 2691231200Smm return (1); 2692231200Smm} 2693231200Smm 2694231200Smm/* 2695231200Smm * Make a huffman coding table. 2696231200Smm */ 2697231200Smmstatic int 2698231200Smmlzh_make_huffman_table(struct huffman *hf) 2699231200Smm{ 2700231200Smm uint16_t *tbl; 2701231200Smm const unsigned char *bitlen; 2702231200Smm int bitptn[17], weight[17]; 2703231200Smm int i, maxbits = 0, ptn, tbl_size, w; 2704231200Smm int diffbits, len_avail; 2705231200Smm 2706231200Smm /* 2707231200Smm * Initialize bit patterns. 2708231200Smm */ 2709231200Smm ptn = 0; 2710231200Smm for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) { 2711231200Smm bitptn[i] = ptn; 2712231200Smm weight[i] = w; 2713231200Smm if (hf->freq[i]) { 2714231200Smm ptn += hf->freq[i] * w; 2715231200Smm maxbits = i; 2716231200Smm } 2717231200Smm } 2718231200Smm if (ptn != 0x10000 || maxbits > hf->tbl_bits) 2719231200Smm return (0);/* Invalid */ 2720231200Smm 2721231200Smm hf->max_bits = maxbits; 2722231200Smm 2723231200Smm /* 2724231200Smm * Cut out extra bits which we won't house in the table. 2725231200Smm * This preparation reduces the same calculation in the for-loop 2726231200Smm * making the table. 2727231200Smm */ 2728231200Smm if (maxbits < 16) { 2729231200Smm int ebits = 16 - maxbits; 2730231200Smm for (i = 1; i <= maxbits; i++) { 2731231200Smm bitptn[i] >>= ebits; 2732231200Smm weight[i] >>= ebits; 2733231200Smm } 2734231200Smm } 2735231200Smm if (maxbits > HTBL_BITS) { 2736302001Smm unsigned htbl_max; 2737231200Smm uint16_t *p; 2738231200Smm 2739231200Smm diffbits = maxbits - HTBL_BITS; 2740231200Smm for (i = 1; i <= HTBL_BITS; i++) { 2741231200Smm bitptn[i] >>= diffbits; 2742231200Smm weight[i] >>= diffbits; 2743231200Smm } 2744231200Smm htbl_max = bitptn[HTBL_BITS] + 2745231200Smm weight[HTBL_BITS] * hf->freq[HTBL_BITS]; 2746231200Smm p = &(hf->tbl[htbl_max]); 2747231200Smm while (p < &hf->tbl[1U<<HTBL_BITS]) 2748231200Smm *p++ = 0; 2749231200Smm } else 2750231200Smm diffbits = 0; 2751231200Smm hf->shift_bits = diffbits; 2752231200Smm 2753231200Smm /* 2754231200Smm * Make the table. 2755231200Smm */ 2756231200Smm tbl_size = 1 << HTBL_BITS; 2757231200Smm tbl = hf->tbl; 2758231200Smm bitlen = hf->bitlen; 2759231200Smm len_avail = hf->len_avail; 2760231200Smm hf->tree_used = 0; 2761231200Smm for (i = 0; i < len_avail; i++) { 2762231200Smm uint16_t *p; 2763231200Smm int len, cnt; 2764231200Smm uint16_t bit; 2765231200Smm int extlen; 2766231200Smm struct htree_t *ht; 2767231200Smm 2768231200Smm if (bitlen[i] == 0) 2769231200Smm continue; 2770231200Smm /* Get a bit pattern */ 2771231200Smm len = bitlen[i]; 2772231200Smm ptn = bitptn[len]; 2773231200Smm cnt = weight[len]; 2774231200Smm if (len <= HTBL_BITS) { 2775231200Smm /* Calculate next bit pattern */ 2776231200Smm if ((bitptn[len] = ptn + cnt) > tbl_size) 2777231200Smm return (0);/* Invalid */ 2778231200Smm /* Update the table */ 2779231200Smm p = &(tbl[ptn]); 2780302001Smm if (cnt > 7) { 2781302001Smm uint16_t *pc; 2782302001Smm 2783302001Smm cnt -= 8; 2784302001Smm pc = &p[cnt]; 2785302001Smm pc[0] = (uint16_t)i; 2786302001Smm pc[1] = (uint16_t)i; 2787302001Smm pc[2] = (uint16_t)i; 2788302001Smm pc[3] = (uint16_t)i; 2789302001Smm pc[4] = (uint16_t)i; 2790302001Smm pc[5] = (uint16_t)i; 2791302001Smm pc[6] = (uint16_t)i; 2792302001Smm pc[7] = (uint16_t)i; 2793302001Smm if (cnt > 7) { 2794302001Smm cnt -= 8; 2795302001Smm memcpy(&p[cnt], pc, 2796302001Smm 8 * sizeof(uint16_t)); 2797302001Smm pc = &p[cnt]; 2798302001Smm while (cnt > 15) { 2799302001Smm cnt -= 16; 2800302001Smm memcpy(&p[cnt], pc, 2801302001Smm 16 * sizeof(uint16_t)); 2802302001Smm } 2803302001Smm } 2804302001Smm if (cnt) 2805302001Smm memcpy(p, pc, cnt * sizeof(uint16_t)); 2806302001Smm } else { 2807302001Smm while (cnt > 1) { 2808302001Smm p[--cnt] = (uint16_t)i; 2809302001Smm p[--cnt] = (uint16_t)i; 2810302001Smm } 2811302001Smm if (cnt) 2812302001Smm p[--cnt] = (uint16_t)i; 2813302001Smm } 2814231200Smm continue; 2815231200Smm } 2816231200Smm 2817231200Smm /* 2818231200Smm * A bit length is too big to be housed to a direct table, 2819231200Smm * so we use a tree model for its extra bits. 2820231200Smm */ 2821231200Smm bitptn[len] = ptn + cnt; 2822231200Smm bit = 1U << (diffbits -1); 2823231200Smm extlen = len - HTBL_BITS; 2824231200Smm 2825231200Smm p = &(tbl[ptn >> diffbits]); 2826231200Smm if (*p == 0) { 2827231200Smm *p = len_avail + hf->tree_used; 2828231200Smm ht = &(hf->tree[hf->tree_used++]); 2829231200Smm if (hf->tree_used > hf->tree_avail) 2830231200Smm return (0);/* Invalid */ 2831231200Smm ht->left = 0; 2832231200Smm ht->right = 0; 2833231200Smm } else { 2834231200Smm if (*p < len_avail || 2835231200Smm *p >= (len_avail + hf->tree_used)) 2836231200Smm return (0);/* Invalid */ 2837231200Smm ht = &(hf->tree[*p - len_avail]); 2838231200Smm } 2839231200Smm while (--extlen > 0) { 2840231200Smm if (ptn & bit) { 2841231200Smm if (ht->left < len_avail) { 2842231200Smm ht->left = len_avail + hf->tree_used; 2843231200Smm ht = &(hf->tree[hf->tree_used++]); 2844231200Smm if (hf->tree_used > hf->tree_avail) 2845231200Smm return (0);/* Invalid */ 2846231200Smm ht->left = 0; 2847231200Smm ht->right = 0; 2848231200Smm } else { 2849231200Smm ht = &(hf->tree[ht->left - len_avail]); 2850231200Smm } 2851231200Smm } else { 2852231200Smm if (ht->right < len_avail) { 2853231200Smm ht->right = len_avail + hf->tree_used; 2854231200Smm ht = &(hf->tree[hf->tree_used++]); 2855231200Smm if (hf->tree_used > hf->tree_avail) 2856231200Smm return (0);/* Invalid */ 2857231200Smm ht->left = 0; 2858231200Smm ht->right = 0; 2859231200Smm } else { 2860231200Smm ht = &(hf->tree[ht->right - len_avail]); 2861231200Smm } 2862231200Smm } 2863231200Smm bit >>= 1; 2864231200Smm } 2865231200Smm if (ptn & bit) { 2866231200Smm if (ht->left != 0) 2867231200Smm return (0);/* Invalid */ 2868231200Smm ht->left = (uint16_t)i; 2869231200Smm } else { 2870231200Smm if (ht->right != 0) 2871231200Smm return (0);/* Invalid */ 2872231200Smm ht->right = (uint16_t)i; 2873231200Smm } 2874231200Smm } 2875231200Smm return (1); 2876231200Smm} 2877231200Smm 2878231200Smmstatic int 2879231200Smmlzh_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c) 2880231200Smm{ 2881231200Smm struct htree_t *ht; 2882231200Smm int extlen; 2883231200Smm 2884231200Smm ht = hf->tree; 2885231200Smm extlen = hf->shift_bits; 2886231200Smm while (c >= hf->len_avail) { 2887231200Smm c -= hf->len_avail; 2888231200Smm if (extlen-- <= 0 || c >= hf->tree_used) 2889231200Smm return (0); 2890231200Smm if (rbits & (1U << extlen)) 2891231200Smm c = ht[c].left; 2892231200Smm else 2893231200Smm c = ht[c].right; 2894231200Smm } 2895231200Smm return (c); 2896231200Smm} 2897231200Smm 2898231200Smmstatic inline int 2899231200Smmlzh_decode_huffman(struct huffman *hf, unsigned rbits) 2900231200Smm{ 2901231200Smm int c; 2902231200Smm /* 2903231200Smm * At first search an index table for a bit pattern. 2904231200Smm * If it fails, search a huffman tree for. 2905231200Smm */ 2906231200Smm c = hf->tbl[rbits >> hf->shift_bits]; 2907302001Smm if (c < hf->len_avail || hf->len_avail == 0) 2908231200Smm return (c); 2909231200Smm /* This bit pattern needs to be found out at a huffman tree. */ 2910231200Smm return (lzh_decode_huffman_tree(hf, rbits, c)); 2911231200Smm} 2912231200Smm 2913