1231200Smm/*- 2232153Smm * Copyright (c) 2008-2012 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 /* The remaining bytes that we have not copied decoded data from 86231200Smm * the window to an output buffer. */ 87231200Smm int w_remaining; 88231200Smm 89231200Smm /* 90231200Smm * Bit stream reader. 91231200Smm */ 92231200Smm struct lzh_br { 93231200Smm#define CACHE_TYPE uint64_t 94231200Smm#define CACHE_BITS (8 * sizeof(CACHE_TYPE)) 95231200Smm /* Cache buffer. */ 96231200Smm CACHE_TYPE cache_buffer; 97231200Smm /* Indicates how many bits avail in cache_buffer. */ 98231200Smm int cache_avail; 99231200Smm } br; 100231200Smm 101231200Smm /* 102231200Smm * Huffman coding. 103231200Smm */ 104231200Smm struct huffman { 105231200Smm int len_size; 106231200Smm int len_avail; 107231200Smm int len_bits; 108231200Smm int freq[17]; 109231200Smm unsigned char *bitlen; 110231200Smm 111231200Smm /* 112231200Smm * Use a index table. It's faster than searching a huffman 113231200Smm * coding tree, which is a binary tree. But a use of a large 114231200Smm * index table causes L1 cache read miss many times. 115231200Smm */ 116231200Smm#define HTBL_BITS 10 117231200Smm int max_bits; 118231200Smm int shift_bits; 119231200Smm int tbl_bits; 120231200Smm int tree_used; 121231200Smm int tree_avail; 122231200Smm /* Direct access table. */ 123231200Smm uint16_t *tbl; 124231200Smm /* Binary tree table for extra bits over the direct access. */ 125231200Smm struct htree_t { 126231200Smm uint16_t left; 127231200Smm uint16_t right; 128231200Smm } *tree; 129231200Smm } lt, pt; 130231200Smm 131231200Smm int blocks_avail; 132231200Smm int pos_pt_len_size; 133231200Smm int pos_pt_len_bits; 134231200Smm int literal_pt_len_size; 135231200Smm int literal_pt_len_bits; 136231200Smm int reading_position; 137231200Smm int loop; 138231200Smm int error; 139231200Smm}; 140231200Smm 141231200Smmstruct lzh_stream { 142231200Smm const unsigned char *next_in; 143231200Smm int64_t avail_in; 144231200Smm int64_t total_in; 145231200Smm unsigned char *next_out; 146231200Smm int64_t avail_out; 147231200Smm int64_t total_out; 148231200Smm struct lzh_dec *ds; 149231200Smm}; 150231200Smm 151231200Smmstruct lha { 152231200Smm /* entry_bytes_remaining is the number of bytes we expect. */ 153231200Smm int64_t entry_offset; 154231200Smm int64_t entry_bytes_remaining; 155231200Smm int64_t entry_unconsumed; 156231200Smm uint16_t entry_crc_calculated; 157231200Smm 158231200Smm size_t header_size; /* header size */ 159231200Smm unsigned char level; /* header level */ 160231200Smm char method[3]; /* compress type */ 161231200Smm int64_t compsize; /* compressed data size */ 162231200Smm int64_t origsize; /* original file size */ 163231200Smm int setflag; 164231200Smm#define BIRTHTIME_IS_SET 1 165231200Smm#define ATIME_IS_SET 2 166231200Smm#define UNIX_MODE_IS_SET 4 167231200Smm#define CRC_IS_SET 8 168231200Smm time_t birthtime; 169231200Smm long birthtime_tv_nsec; 170231200Smm time_t mtime; 171231200Smm long mtime_tv_nsec; 172231200Smm time_t atime; 173231200Smm long atime_tv_nsec; 174231200Smm mode_t mode; 175231200Smm int64_t uid; 176231200Smm int64_t gid; 177231200Smm struct archive_string uname; 178231200Smm struct archive_string gname; 179231200Smm uint16_t header_crc; 180231200Smm uint16_t crc; 181231200Smm struct archive_string_conv *sconv; 182231200Smm struct archive_string_conv *opt_sconv; 183231200Smm 184231200Smm struct archive_string dirname; 185231200Smm struct archive_string filename; 186231200Smm struct archive_wstring ws; 187231200Smm 188231200Smm unsigned char dos_attr; 189231200Smm 190231200Smm /* Flag to mark progress that an archive was read their first header.*/ 191231200Smm char found_first_header; 192231200Smm /* Flag to mark that indicates an empty directory. */ 193231200Smm char directory; 194231200Smm 195231200Smm /* Flags to mark progress of decompression. */ 196231200Smm char decompress_init; 197231200Smm char end_of_entry; 198231200Smm char end_of_entry_cleanup; 199231200Smm char entry_is_compressed; 200231200Smm 201231200Smm unsigned char *uncompressed_buffer; 202231200Smm size_t uncompressed_buffer_size; 203231200Smm 204231200Smm char format_name[64]; 205231200Smm 206231200Smm struct lzh_stream strm; 207231200Smm}; 208231200Smm 209231200Smm/* 210231200Smm * LHA header common member offset. 211231200Smm */ 212231200Smm#define H_METHOD_OFFSET 2 /* Compress type. */ 213231200Smm#define H_ATTR_OFFSET 19 /* DOS attribute. */ 214231200Smm#define H_LEVEL_OFFSET 20 /* Header Level. */ 215231200Smm#define H_SIZE 22 /* Minimum header size. */ 216231200Smm 217231200Smmstatic const uint16_t crc16tbl[256] = { 218231200Smm 0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241, 219231200Smm 0xC601,0x06C0,0x0780,0xC741,0x0500,0xC5C1,0xC481,0x0440, 220231200Smm 0xCC01,0x0CC0,0x0D80,0xCD41,0x0F00,0xCFC1,0xCE81,0x0E40, 221231200Smm 0x0A00,0xCAC1,0xCB81,0x0B40,0xC901,0x09C0,0x0880,0xC841, 222231200Smm 0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40, 223231200Smm 0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41, 224231200Smm 0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641, 225231200Smm 0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040, 226231200Smm 0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240, 227231200Smm 0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441, 228231200Smm 0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41, 229231200Smm 0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840, 230231200Smm 0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41, 231231200Smm 0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40, 232231200Smm 0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640, 233231200Smm 0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041, 234231200Smm 0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240, 235231200Smm 0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441, 236231200Smm 0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41, 237231200Smm 0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840, 238231200Smm 0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41, 239231200Smm 0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40, 240231200Smm 0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640, 241231200Smm 0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041, 242231200Smm 0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241, 243231200Smm 0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440, 244231200Smm 0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40, 245231200Smm 0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841, 246231200Smm 0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40, 247231200Smm 0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41, 248231200Smm 0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641, 249231200Smm 0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040 250231200Smm}; 251231200Smm 252231200Smmstatic int archive_read_format_lha_bid(struct archive_read *, int); 253231200Smmstatic int archive_read_format_lha_options(struct archive_read *, 254231200Smm const char *, const char *); 255231200Smmstatic int archive_read_format_lha_read_header(struct archive_read *, 256231200Smm struct archive_entry *); 257231200Smmstatic int archive_read_format_lha_read_data(struct archive_read *, 258231200Smm const void **, size_t *, int64_t *); 259231200Smmstatic int archive_read_format_lha_read_data_skip(struct archive_read *); 260231200Smmstatic int archive_read_format_lha_cleanup(struct archive_read *); 261231200Smm 262231200Smmstatic void lha_replace_path_separator(struct lha *, 263231200Smm struct archive_entry *); 264231200Smmstatic int lha_read_file_header_0(struct archive_read *, struct lha *); 265231200Smmstatic int lha_read_file_header_1(struct archive_read *, struct lha *); 266231200Smmstatic int lha_read_file_header_2(struct archive_read *, struct lha *); 267231200Smmstatic int lha_read_file_header_3(struct archive_read *, struct lha *); 268231200Smmstatic int lha_read_file_extended_header(struct archive_read *, 269231200Smm struct lha *, uint16_t *, int, size_t, size_t *); 270231200Smmstatic size_t lha_check_header_format(const void *); 271231200Smmstatic int lha_skip_sfx(struct archive_read *); 272231200Smmstatic time_t lha_dos_time(const unsigned char *); 273231200Smmstatic time_t lha_win_time(uint64_t, long *); 274231200Smmstatic unsigned char lha_calcsum(unsigned char, const void *, 275248616Smm int, size_t); 276231200Smmstatic int lha_parse_linkname(struct archive_string *, 277231200Smm struct archive_string *); 278231200Smmstatic int lha_read_data_none(struct archive_read *, const void **, 279231200Smm size_t *, int64_t *); 280231200Smmstatic int lha_read_data_lzh(struct archive_read *, const void **, 281231200Smm size_t *, int64_t *); 282231200Smmstatic uint16_t lha_crc16(uint16_t, const void *, size_t); 283231200Smmstatic int lzh_decode_init(struct lzh_stream *, const char *); 284231200Smmstatic void lzh_decode_free(struct lzh_stream *); 285231200Smmstatic int lzh_decode(struct lzh_stream *, int); 286231200Smmstatic int lzh_br_fillup(struct lzh_stream *, struct lzh_br *); 287231200Smmstatic int lzh_huffman_init(struct huffman *, size_t, int); 288231200Smmstatic void lzh_huffman_free(struct huffman *); 289231200Smmstatic int lzh_read_pt_bitlen(struct lzh_stream *, int start, int end); 290231200Smmstatic int lzh_make_fake_table(struct huffman *, uint16_t); 291231200Smmstatic int lzh_make_huffman_table(struct huffman *); 292232153Smmstatic inline int lzh_decode_huffman(struct huffman *, unsigned); 293231200Smmstatic int lzh_decode_huffman_tree(struct huffman *, unsigned, int); 294231200Smm 295231200Smm 296231200Smmint 297231200Smmarchive_read_support_format_lha(struct archive *_a) 298231200Smm{ 299231200Smm struct archive_read *a = (struct archive_read *)_a; 300231200Smm struct lha *lha; 301231200Smm int r; 302231200Smm 303231200Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 304231200Smm ARCHIVE_STATE_NEW, "archive_read_support_format_lha"); 305231200Smm 306231200Smm lha = (struct lha *)calloc(1, sizeof(*lha)); 307231200Smm if (lha == NULL) { 308231200Smm archive_set_error(&a->archive, ENOMEM, 309231200Smm "Can't allocate lha data"); 310231200Smm return (ARCHIVE_FATAL); 311231200Smm } 312231200Smm archive_string_init(&lha->ws); 313231200Smm 314231200Smm r = __archive_read_register_format(a, 315231200Smm lha, 316231200Smm "lha", 317231200Smm archive_read_format_lha_bid, 318231200Smm archive_read_format_lha_options, 319231200Smm archive_read_format_lha_read_header, 320231200Smm archive_read_format_lha_read_data, 321231200Smm archive_read_format_lha_read_data_skip, 322248616Smm NULL, 323231200Smm archive_read_format_lha_cleanup); 324231200Smm 325231200Smm if (r != ARCHIVE_OK) 326231200Smm free(lha); 327231200Smm return (ARCHIVE_OK); 328231200Smm} 329231200Smm 330231200Smmstatic size_t 331231200Smmlha_check_header_format(const void *h) 332231200Smm{ 333231200Smm const unsigned char *p = h; 334231200Smm size_t next_skip_bytes; 335231200Smm 336231200Smm switch (p[H_METHOD_OFFSET+3]) { 337231200Smm /* 338231200Smm * "-lh0-" ... "-lh7-" "-lhd-" 339231200Smm * "-lzs-" "-lz5-" 340231200Smm */ 341231200Smm case '0': case '1': case '2': case '3': 342231200Smm case '4': case '5': case '6': case '7': 343231200Smm case 'd': 344231200Smm case 's': 345231200Smm next_skip_bytes = 4; 346231200Smm 347231200Smm /* b0 == 0 means the end of an LHa archive file. */ 348231200Smm if (p[0] == 0) 349231200Smm break; 350231200Smm if (p[H_METHOD_OFFSET] != '-' || p[H_METHOD_OFFSET+1] != 'l' 351231200Smm || p[H_METHOD_OFFSET+4] != '-') 352231200Smm break; 353231200Smm 354231200Smm if (p[H_METHOD_OFFSET+2] == 'h') { 355231200Smm /* "-lh?-" */ 356231200Smm if (p[H_METHOD_OFFSET+3] == 's') 357231200Smm break; 358231200Smm if (p[H_LEVEL_OFFSET] == 0) 359231200Smm return (0); 360231200Smm if (p[H_LEVEL_OFFSET] <= 3 && p[H_ATTR_OFFSET] == 0x20) 361231200Smm return (0); 362231200Smm } 363231200Smm if (p[H_METHOD_OFFSET+2] == 'z') { 364231200Smm /* LArc extensions: -lzs-,-lz4- and -lz5- */ 365231200Smm if (p[H_LEVEL_OFFSET] != 0) 366231200Smm break; 367231200Smm if (p[H_METHOD_OFFSET+3] == 's' 368231200Smm || p[H_METHOD_OFFSET+3] == '4' 369231200Smm || p[H_METHOD_OFFSET+3] == '5') 370231200Smm return (0); 371231200Smm } 372231200Smm break; 373231200Smm case 'h': next_skip_bytes = 1; break; 374231200Smm case 'z': next_skip_bytes = 1; break; 375231200Smm case 'l': next_skip_bytes = 2; break; 376231200Smm case '-': next_skip_bytes = 3; break; 377231200Smm default : next_skip_bytes = 4; break; 378231200Smm } 379231200Smm 380231200Smm return (next_skip_bytes); 381231200Smm} 382231200Smm 383231200Smmstatic int 384231200Smmarchive_read_format_lha_bid(struct archive_read *a, int best_bid) 385231200Smm{ 386231200Smm const char *p; 387231200Smm const void *buff; 388231200Smm ssize_t bytes_avail, offset, window; 389231200Smm size_t next; 390231200Smm 391231200Smm /* If there's already a better bid than we can ever 392231200Smm make, don't bother testing. */ 393231200Smm if (best_bid > 30) 394231200Smm return (-1); 395231200Smm 396231200Smm if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) 397231200Smm return (-1); 398231200Smm 399231200Smm if (lha_check_header_format(p) == 0) 400231200Smm return (30); 401231200Smm 402231200Smm if (p[0] == 'M' && p[1] == 'Z') { 403231200Smm /* PE file */ 404231200Smm offset = 0; 405231200Smm window = 4096; 406231200Smm while (offset < (1024 * 20)) { 407231200Smm buff = __archive_read_ahead(a, offset + window, 408231200Smm &bytes_avail); 409231200Smm if (buff == NULL) { 410231200Smm /* Remaining bytes are less than window. */ 411231200Smm window >>= 1; 412231200Smm if (window < (H_SIZE + 3)) 413231200Smm return (0); 414231200Smm continue; 415231200Smm } 416231200Smm p = (const char *)buff + offset; 417231200Smm while (p + H_SIZE < (const char *)buff + bytes_avail) { 418231200Smm if ((next = lha_check_header_format(p)) == 0) 419231200Smm return (30); 420231200Smm p += next; 421231200Smm } 422231200Smm offset = p - (const char *)buff; 423231200Smm } 424231200Smm } 425231200Smm return (0); 426231200Smm} 427231200Smm 428231200Smmstatic int 429231200Smmarchive_read_format_lha_options(struct archive_read *a, 430231200Smm const char *key, const char *val) 431231200Smm{ 432231200Smm struct lha *lha; 433231200Smm int ret = ARCHIVE_FAILED; 434231200Smm 435231200Smm lha = (struct lha *)(a->format->data); 436231200Smm if (strcmp(key, "hdrcharset") == 0) { 437231200Smm if (val == NULL || val[0] == 0) 438231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 439231200Smm "lha: hdrcharset option needs a character-set name"); 440231200Smm else { 441231200Smm lha->opt_sconv = 442231200Smm archive_string_conversion_from_charset( 443231200Smm &a->archive, val, 0); 444231200Smm if (lha->opt_sconv != NULL) 445231200Smm ret = ARCHIVE_OK; 446231200Smm else 447231200Smm ret = ARCHIVE_FATAL; 448231200Smm } 449232153Smm return (ret); 450232153Smm } 451231200Smm 452232153Smm /* Note: The "warn" return is just to inform the options 453232153Smm * supervisor that we didn't handle it. It will generate 454232153Smm * a suitable error if no one used this option. */ 455232153Smm return (ARCHIVE_WARN); 456231200Smm} 457231200Smm 458231200Smmstatic int 459231200Smmlha_skip_sfx(struct archive_read *a) 460231200Smm{ 461231200Smm const void *h; 462231200Smm const char *p, *q; 463231200Smm size_t next, skip; 464231200Smm ssize_t bytes, window; 465231200Smm 466231200Smm window = 4096; 467231200Smm for (;;) { 468231200Smm h = __archive_read_ahead(a, window, &bytes); 469231200Smm if (h == NULL) { 470231200Smm /* Remaining bytes are less than window. */ 471231200Smm window >>= 1; 472231200Smm if (window < (H_SIZE + 3)) 473231200Smm goto fatal; 474231200Smm continue; 475231200Smm } 476231200Smm if (bytes < H_SIZE) 477231200Smm goto fatal; 478231200Smm p = h; 479231200Smm q = p + bytes; 480231200Smm 481231200Smm /* 482231200Smm * Scan ahead until we find something that looks 483231200Smm * like the lha header. 484231200Smm */ 485231200Smm while (p + H_SIZE < q) { 486231200Smm if ((next = lha_check_header_format(p)) == 0) { 487231200Smm skip = p - (const char *)h; 488231200Smm __archive_read_consume(a, skip); 489231200Smm return (ARCHIVE_OK); 490231200Smm } 491231200Smm p += next; 492231200Smm } 493231200Smm skip = p - (const char *)h; 494231200Smm __archive_read_consume(a, skip); 495231200Smm } 496231200Smmfatal: 497231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 498231200Smm "Couldn't find out LHa header"); 499231200Smm return (ARCHIVE_FATAL); 500231200Smm} 501231200Smm 502231200Smmstatic int 503231200Smmtruncated_error(struct archive_read *a) 504231200Smm{ 505231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 506231200Smm "Truncated LHa header"); 507231200Smm return (ARCHIVE_FATAL); 508231200Smm} 509231200Smm 510231200Smmstatic int 511231200Smmarchive_read_format_lha_read_header(struct archive_read *a, 512231200Smm struct archive_entry *entry) 513231200Smm{ 514231200Smm struct archive_string linkname; 515231200Smm struct archive_string pathname; 516231200Smm struct lha *lha; 517231200Smm const unsigned char *p; 518231200Smm const char *signature; 519231200Smm int err; 520231200Smm 521231200Smm a->archive.archive_format = ARCHIVE_FORMAT_LHA; 522231200Smm if (a->archive.archive_format_name == NULL) 523231200Smm a->archive.archive_format_name = "lha"; 524231200Smm 525231200Smm lha = (struct lha *)(a->format->data); 526231200Smm lha->decompress_init = 0; 527231200Smm lha->end_of_entry = 0; 528231200Smm lha->end_of_entry_cleanup = 0; 529231200Smm lha->entry_unconsumed = 0; 530231200Smm 531231200Smm if ((p = __archive_read_ahead(a, H_SIZE, NULL)) == NULL) { 532231200Smm /* 533231200Smm * LHa archiver added 0 to the tail of its archive file as 534231200Smm * the mark of the end of the archive. 535231200Smm */ 536231200Smm signature = __archive_read_ahead(a, sizeof(signature[0]), NULL); 537231200Smm if (signature == NULL || signature[0] == 0) 538231200Smm return (ARCHIVE_EOF); 539231200Smm return (truncated_error(a)); 540231200Smm } 541231200Smm 542231200Smm signature = (const char *)p; 543231200Smm if (lha->found_first_header == 0 && 544231200Smm signature[0] == 'M' && signature[1] == 'Z') { 545231200Smm /* This is an executable? Must be self-extracting... */ 546231200Smm err = lha_skip_sfx(a); 547231200Smm if (err < ARCHIVE_WARN) 548231200Smm return (err); 549231200Smm 550231200Smm if ((p = __archive_read_ahead(a, sizeof(*p), NULL)) == NULL) 551231200Smm return (truncated_error(a)); 552231200Smm signature = (const char *)p; 553231200Smm } 554231200Smm /* signature[0] == 0 means the end of an LHa archive file. */ 555231200Smm if (signature[0] == 0) 556231200Smm return (ARCHIVE_EOF); 557231200Smm 558231200Smm /* 559231200Smm * Check the header format and method type. 560231200Smm */ 561231200Smm if (lha_check_header_format(p) != 0) { 562231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 563231200Smm "Bad LHa file"); 564231200Smm return (ARCHIVE_FATAL); 565231200Smm } 566231200Smm 567231200Smm /* We've found the first header. */ 568231200Smm lha->found_first_header = 1; 569231200Smm /* Set a default value and common data */ 570231200Smm lha->header_size = 0; 571231200Smm lha->level = p[H_LEVEL_OFFSET]; 572231200Smm lha->method[0] = p[H_METHOD_OFFSET+1]; 573231200Smm lha->method[1] = p[H_METHOD_OFFSET+2]; 574231200Smm lha->method[2] = p[H_METHOD_OFFSET+3]; 575231200Smm if (memcmp(lha->method, "lhd", 3) == 0) 576231200Smm lha->directory = 1; 577231200Smm else 578231200Smm lha->directory = 0; 579231200Smm if (memcmp(lha->method, "lh0", 3) == 0 || 580231200Smm memcmp(lha->method, "lz4", 3) == 0) 581231200Smm lha->entry_is_compressed = 0; 582231200Smm else 583231200Smm lha->entry_is_compressed = 1; 584231200Smm 585231200Smm lha->compsize = 0; 586231200Smm lha->origsize = 0; 587231200Smm lha->setflag = 0; 588231200Smm lha->birthtime = 0; 589231200Smm lha->birthtime_tv_nsec = 0; 590231200Smm lha->mtime = 0; 591231200Smm lha->mtime_tv_nsec = 0; 592231200Smm lha->atime = 0; 593231200Smm lha->atime_tv_nsec = 0; 594231200Smm lha->mode = (lha->directory)? 0777 : 0666; 595231200Smm lha->uid = 0; 596231200Smm lha->gid = 0; 597231200Smm archive_string_empty(&lha->dirname); 598231200Smm archive_string_empty(&lha->filename); 599231200Smm lha->dos_attr = 0; 600231200Smm if (lha->opt_sconv != NULL) 601231200Smm lha->sconv = lha->opt_sconv; 602231200Smm else 603231200Smm lha->sconv = NULL; 604231200Smm 605231200Smm switch (p[H_LEVEL_OFFSET]) { 606231200Smm case 0: 607231200Smm err = lha_read_file_header_0(a, lha); 608231200Smm break; 609231200Smm case 1: 610231200Smm err = lha_read_file_header_1(a, lha); 611231200Smm break; 612231200Smm case 2: 613231200Smm err = lha_read_file_header_2(a, lha); 614231200Smm break; 615231200Smm case 3: 616231200Smm err = lha_read_file_header_3(a, lha); 617231200Smm break; 618231200Smm default: 619231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 620231200Smm "Unsupported LHa header level %d", p[H_LEVEL_OFFSET]); 621231200Smm err = ARCHIVE_FATAL; 622231200Smm break; 623231200Smm } 624231200Smm if (err < ARCHIVE_WARN) 625231200Smm return (err); 626231200Smm 627231200Smm 628231200Smm if (!lha->directory && archive_strlen(&lha->filename) == 0) 629231200Smm /* The filename has not been set */ 630231200Smm return (truncated_error(a)); 631231200Smm 632231200Smm /* 633231200Smm * Make a pathname from a dirname and a filename. 634231200Smm */ 635231200Smm archive_string_concat(&lha->dirname, &lha->filename); 636231200Smm archive_string_init(&pathname); 637231200Smm archive_string_init(&linkname); 638231200Smm archive_string_copy(&pathname, &lha->dirname); 639231200Smm 640231200Smm if ((lha->mode & AE_IFMT) == AE_IFLNK) { 641231200Smm /* 642231200Smm * Extract the symlink-name if it's included in the pathname. 643231200Smm */ 644231200Smm if (!lha_parse_linkname(&linkname, &pathname)) { 645231200Smm /* We couldn't get the symlink-name. */ 646231200Smm archive_set_error(&a->archive, 647231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 648231200Smm "Unknown symlink-name"); 649231200Smm archive_string_free(&pathname); 650231200Smm archive_string_free(&linkname); 651231200Smm return (ARCHIVE_FAILED); 652231200Smm } 653231200Smm } else { 654231200Smm /* 655231200Smm * Make sure a file-type is set. 656231200Smm * The mode has been overridden if it is in the extended data. 657231200Smm */ 658231200Smm lha->mode = (lha->mode & ~AE_IFMT) | 659231200Smm ((lha->directory)? AE_IFDIR: AE_IFREG); 660231200Smm } 661231200Smm if ((lha->setflag & UNIX_MODE_IS_SET) == 0 && 662231200Smm (lha->dos_attr & 1) != 0) 663231200Smm lha->mode &= ~(0222);/* read only. */ 664231200Smm 665231200Smm /* 666231200Smm * Set basic file parameters. 667231200Smm */ 668231200Smm if (archive_entry_copy_pathname_l(entry, pathname.s, 669231200Smm pathname.length, lha->sconv) != 0) { 670231200Smm if (errno == ENOMEM) { 671231200Smm archive_set_error(&a->archive, ENOMEM, 672231200Smm "Can't allocate memory for Pathname"); 673231200Smm return (ARCHIVE_FATAL); 674231200Smm } 675231200Smm archive_set_error(&a->archive, 676231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 677231200Smm "Pathname cannot be converted " 678231200Smm "from %s to current locale.", 679231200Smm archive_string_conversion_charset_name(lha->sconv)); 680231200Smm err = ARCHIVE_WARN; 681231200Smm } 682231200Smm archive_string_free(&pathname); 683231200Smm if (archive_strlen(&linkname) > 0) { 684231200Smm if (archive_entry_copy_symlink_l(entry, linkname.s, 685231200Smm linkname.length, lha->sconv) != 0) { 686231200Smm if (errno == ENOMEM) { 687231200Smm archive_set_error(&a->archive, ENOMEM, 688231200Smm "Can't allocate memory for Linkname"); 689231200Smm return (ARCHIVE_FATAL); 690231200Smm } 691231200Smm archive_set_error(&a->archive, 692231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 693231200Smm "Linkname cannot be converted " 694231200Smm "from %s to current locale.", 695231200Smm archive_string_conversion_charset_name(lha->sconv)); 696231200Smm err = ARCHIVE_WARN; 697231200Smm } 698231200Smm } else 699231200Smm archive_entry_set_symlink(entry, NULL); 700231200Smm archive_string_free(&linkname); 701231200Smm /* 702231200Smm * When a header level is 0, there is a possibility that 703231200Smm * a pathname and a symlink has '\' character, a directory 704231200Smm * separator in DOS/Windows. So we should convert it to '/'. 705231200Smm */ 706231200Smm if (p[H_LEVEL_OFFSET] == 0) 707231200Smm lha_replace_path_separator(lha, entry); 708231200Smm 709231200Smm archive_entry_set_mode(entry, lha->mode); 710231200Smm archive_entry_set_uid(entry, lha->uid); 711231200Smm archive_entry_set_gid(entry, lha->gid); 712231200Smm if (archive_strlen(&lha->uname) > 0) 713231200Smm archive_entry_set_uname(entry, lha->uname.s); 714231200Smm if (archive_strlen(&lha->gname) > 0) 715231200Smm archive_entry_set_gname(entry, lha->gname.s); 716231200Smm if (lha->setflag & BIRTHTIME_IS_SET) { 717231200Smm archive_entry_set_birthtime(entry, lha->birthtime, 718231200Smm lha->birthtime_tv_nsec); 719231200Smm archive_entry_set_ctime(entry, lha->birthtime, 720231200Smm lha->birthtime_tv_nsec); 721231200Smm } else { 722231200Smm archive_entry_unset_birthtime(entry); 723231200Smm archive_entry_unset_ctime(entry); 724231200Smm } 725231200Smm archive_entry_set_mtime(entry, lha->mtime, lha->mtime_tv_nsec); 726231200Smm if (lha->setflag & ATIME_IS_SET) 727231200Smm archive_entry_set_atime(entry, lha->atime, 728231200Smm lha->atime_tv_nsec); 729231200Smm else 730231200Smm archive_entry_unset_atime(entry); 731231200Smm if (lha->directory || archive_entry_symlink(entry) != NULL) 732231200Smm archive_entry_unset_size(entry); 733231200Smm else 734231200Smm archive_entry_set_size(entry, lha->origsize); 735231200Smm 736231200Smm /* 737231200Smm * Prepare variables used to read a file content. 738231200Smm */ 739231200Smm lha->entry_bytes_remaining = lha->compsize; 740231200Smm lha->entry_offset = 0; 741231200Smm lha->entry_crc_calculated = 0; 742231200Smm 743231200Smm /* 744231200Smm * This file does not have a content. 745231200Smm */ 746231200Smm if (lha->directory || lha->compsize == 0) 747231200Smm lha->end_of_entry = 1; 748231200Smm 749231200Smm sprintf(lha->format_name, "lha -%c%c%c-", 750231200Smm lha->method[0], lha->method[1], lha->method[2]); 751231200Smm a->archive.archive_format_name = lha->format_name; 752231200Smm 753231200Smm return (err); 754231200Smm} 755231200Smm 756231200Smm/* 757231200Smm * Replace a DOS path separator '\' by a character '/'. 758231200Smm * Some multi-byte character set have a character '\' in its second byte. 759231200Smm */ 760231200Smmstatic void 761231200Smmlha_replace_path_separator(struct lha *lha, struct archive_entry *entry) 762231200Smm{ 763231200Smm const wchar_t *wp; 764231200Smm size_t i; 765231200Smm 766231200Smm if ((wp = archive_entry_pathname_w(entry)) != NULL) { 767231200Smm archive_wstrcpy(&(lha->ws), wp); 768231200Smm for (i = 0; i < archive_strlen(&(lha->ws)); i++) { 769231200Smm if (lha->ws.s[i] == L'\\') 770231200Smm lha->ws.s[i] = L'/'; 771231200Smm } 772231200Smm archive_entry_copy_pathname_w(entry, lha->ws.s); 773231200Smm } 774231200Smm 775231200Smm if ((wp = archive_entry_symlink_w(entry)) != NULL) { 776231200Smm archive_wstrcpy(&(lha->ws), wp); 777231200Smm for (i = 0; i < archive_strlen(&(lha->ws)); i++) { 778231200Smm if (lha->ws.s[i] == L'\\') 779231200Smm lha->ws.s[i] = L'/'; 780231200Smm } 781231200Smm archive_entry_copy_symlink_w(entry, lha->ws.s); 782231200Smm } 783231200Smm} 784231200Smm 785231200Smm/* 786231200Smm * Header 0 format 787231200Smm * 788231200Smm * +0 +1 +2 +7 +11 789231200Smm * +---------------+----------+----------------+-------------------+ 790231200Smm * |header size(*1)|header sum|compression type|compressed size(*2)| 791231200Smm * +---------------+----------+----------------+-------------------+ 792231200Smm * <---------------------(*1)----------* 793231200Smm * 794231200Smm * +11 +15 +17 +19 +20 +21 795231200Smm * +-----------------+---------+---------+--------------+----------------+ 796231200Smm * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=0)| 797231200Smm * +-----------------+---------+---------+--------------+----------------+ 798231200Smm * *--------------------------------(*1)---------------------------------* 799231200Smm * 800231200Smm * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+2+(*4) 801231200Smm * +---------------+---------+----------+----------------+------------------+ 802231200Smm * |name length(*3)|file name|file CRC16|extra header(*4)| compressed data | 803231200Smm * +---------------+---------+----------+----------------+------------------+ 804231200Smm * <--(*3)-> <------(*2)------> 805231200Smm * *----------------------(*1)--------------------------> 806231200Smm * 807231200Smm */ 808231200Smm#define H0_HEADER_SIZE_OFFSET 0 809231200Smm#define H0_HEADER_SUM_OFFSET 1 810231200Smm#define H0_COMP_SIZE_OFFSET 7 811231200Smm#define H0_ORIG_SIZE_OFFSET 11 812231200Smm#define H0_DOS_TIME_OFFSET 15 813231200Smm#define H0_NAME_LEN_OFFSET 21 814231200Smm#define H0_FILE_NAME_OFFSET 22 815231200Smm#define H0_FIXED_SIZE 24 816231200Smmstatic int 817231200Smmlha_read_file_header_0(struct archive_read *a, struct lha *lha) 818231200Smm{ 819231200Smm const unsigned char *p; 820231200Smm int extdsize, namelen; 821231200Smm unsigned char headersum, sum_calculated; 822231200Smm 823231200Smm if ((p = __archive_read_ahead(a, H0_FIXED_SIZE, NULL)) == NULL) 824231200Smm return (truncated_error(a)); 825231200Smm lha->header_size = p[H0_HEADER_SIZE_OFFSET] + 2; 826231200Smm headersum = p[H0_HEADER_SUM_OFFSET]; 827231200Smm lha->compsize = archive_le32dec(p + H0_COMP_SIZE_OFFSET); 828231200Smm lha->origsize = archive_le32dec(p + H0_ORIG_SIZE_OFFSET); 829231200Smm lha->mtime = lha_dos_time(p + H0_DOS_TIME_OFFSET); 830231200Smm namelen = p[H0_NAME_LEN_OFFSET]; 831231200Smm extdsize = (int)lha->header_size - H0_FIXED_SIZE - namelen; 832231200Smm if ((namelen > 221 || extdsize < 0) && extdsize != -2) { 833231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 834231200Smm "Invalid LHa header"); 835231200Smm return (ARCHIVE_FATAL); 836231200Smm } 837231200Smm if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) 838231200Smm return (truncated_error(a)); 839231200Smm 840231200Smm archive_strncpy(&lha->filename, p + H0_FILE_NAME_OFFSET, namelen); 841231200Smm /* When extdsize == -2, A CRC16 value is not present in the header. */ 842231200Smm if (extdsize >= 0) { 843231200Smm lha->crc = archive_le16dec(p + H0_FILE_NAME_OFFSET + namelen); 844231200Smm lha->setflag |= CRC_IS_SET; 845231200Smm } 846231200Smm sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); 847231200Smm 848231200Smm /* Read an extended header */ 849231200Smm if (extdsize > 0) { 850231200Smm /* This extended data is set by 'LHa for UNIX' only. 851231200Smm * Maybe fixed size. 852231200Smm */ 853231200Smm p += H0_FILE_NAME_OFFSET + namelen + 2; 854231200Smm if (p[0] == 'U' && extdsize == 12) { 855231200Smm /* p[1] is a minor version. */ 856231200Smm lha->mtime = archive_le32dec(&p[2]); 857231200Smm lha->mode = archive_le16dec(&p[6]); 858231200Smm lha->uid = archive_le16dec(&p[8]); 859231200Smm lha->gid = archive_le16dec(&p[10]); 860231200Smm lha->setflag |= UNIX_MODE_IS_SET; 861231200Smm } 862231200Smm } 863231200Smm __archive_read_consume(a, lha->header_size); 864231200Smm 865231200Smm if (sum_calculated != headersum) { 866231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 867231200Smm "LHa header sum error"); 868231200Smm return (ARCHIVE_FATAL); 869231200Smm } 870231200Smm 871231200Smm return (ARCHIVE_OK); 872231200Smm} 873231200Smm 874231200Smm/* 875231200Smm * Header 1 format 876231200Smm * 877231200Smm * +0 +1 +2 +7 +11 878231200Smm * +---------------+----------+----------------+-------------+ 879231200Smm * |header size(*1)|header sum|compression type|skip size(*2)| 880231200Smm * +---------------+----------+----------------+-------------+ 881231200Smm * <---------------(*1)----------* 882231200Smm * 883231200Smm * +11 +15 +17 +19 +20 +21 884231200Smm * +-----------------+---------+---------+--------------+----------------+ 885231200Smm * |uncompressed size|time(DOS)|date(DOS)|attribute(DOS)|header level(=1)| 886231200Smm * +-----------------+---------+---------+--------------+----------------+ 887231200Smm * *-------------------------------(*1)----------------------------------* 888231200Smm * 889231200Smm * +21 +22 +22+(*3) +22+(*3)+2 +22+(*3)+3 +22+(*3)+3+(*4) 890231200Smm * +---------------+---------+----------+-----------+-----------+ 891231200Smm * |name length(*3)|file name|file CRC16| creator |padding(*4)| 892231200Smm * +---------------+---------+----------+-----------+-----------+ 893231200Smm * <--(*3)-> 894231200Smm * *----------------------------(*1)----------------------------* 895231200Smm * 896231200Smm * +22+(*3)+3+(*4) +22+(*3)+3+(*4)+2 +22+(*3)+3+(*4)+2+(*5) 897231200Smm * +----------------+---------------------+------------------------+ 898231200Smm * |next header size| extended header(*5) | compressed data | 899231200Smm * +----------------+---------------------+------------------------+ 900231200Smm * *------(*1)-----> <--------------------(*2)--------------------> 901231200Smm */ 902231200Smm#define H1_HEADER_SIZE_OFFSET 0 903231200Smm#define H1_HEADER_SUM_OFFSET 1 904231200Smm#define H1_COMP_SIZE_OFFSET 7 905231200Smm#define H1_ORIG_SIZE_OFFSET 11 906231200Smm#define H1_DOS_TIME_OFFSET 15 907231200Smm#define H1_NAME_LEN_OFFSET 21 908231200Smm#define H1_FILE_NAME_OFFSET 22 909231200Smm#define H1_FIXED_SIZE 27 910231200Smmstatic int 911231200Smmlha_read_file_header_1(struct archive_read *a, struct lha *lha) 912231200Smm{ 913231200Smm const unsigned char *p; 914231200Smm size_t extdsize; 915231200Smm int i, err, err2; 916231200Smm int namelen, padding; 917231200Smm unsigned char headersum, sum_calculated; 918231200Smm 919231200Smm err = ARCHIVE_OK; 920231200Smm 921231200Smm if ((p = __archive_read_ahead(a, H1_FIXED_SIZE, NULL)) == NULL) 922231200Smm return (truncated_error(a)); 923231200Smm 924231200Smm lha->header_size = p[H1_HEADER_SIZE_OFFSET] + 2; 925231200Smm headersum = p[H1_HEADER_SUM_OFFSET]; 926231200Smm /* Note: An extended header size is included in a compsize. */ 927231200Smm lha->compsize = archive_le32dec(p + H1_COMP_SIZE_OFFSET); 928231200Smm lha->origsize = archive_le32dec(p + H1_ORIG_SIZE_OFFSET); 929231200Smm lha->mtime = lha_dos_time(p + H1_DOS_TIME_OFFSET); 930231200Smm namelen = p[H1_NAME_LEN_OFFSET]; 931231200Smm /* Calculate a padding size. The result will be normally 0 only(?) */ 932231200Smm padding = ((int)lha->header_size) - H1_FIXED_SIZE - namelen; 933231200Smm 934231200Smm if (namelen > 230 || padding < 0) 935231200Smm goto invalid; 936231200Smm 937231200Smm if ((p = __archive_read_ahead(a, lha->header_size, NULL)) == NULL) 938231200Smm return (truncated_error(a)); 939231200Smm 940231200Smm for (i = 0; i < namelen; i++) { 941231200Smm if (p[i + H1_FILE_NAME_OFFSET] == 0xff) 942231200Smm goto invalid;/* Invalid filename. */ 943231200Smm } 944231200Smm archive_strncpy(&lha->filename, p + H1_FILE_NAME_OFFSET, namelen); 945231200Smm lha->crc = archive_le16dec(p + H1_FILE_NAME_OFFSET + namelen); 946231200Smm lha->setflag |= CRC_IS_SET; 947231200Smm 948231200Smm sum_calculated = lha_calcsum(0, p, 2, lha->header_size - 2); 949231200Smm /* Consume used bytes but not include `next header size' data 950231200Smm * since it will be consumed in lha_read_file_extended_header(). */ 951231200Smm __archive_read_consume(a, lha->header_size - 2); 952231200Smm 953231200Smm /* Read extended headers */ 954231200Smm err2 = lha_read_file_extended_header(a, lha, NULL, 2, 955238856Smm (size_t)(lha->compsize + 2), &extdsize); 956231200Smm if (err2 < ARCHIVE_WARN) 957231200Smm return (err2); 958231200Smm if (err2 < err) 959231200Smm err = err2; 960231200Smm /* Get a real compressed file size. */ 961231200Smm lha->compsize -= extdsize - 2; 962231200Smm 963231200Smm if (sum_calculated != headersum) { 964231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 965231200Smm "LHa header sum error"); 966231200Smm return (ARCHIVE_FATAL); 967231200Smm } 968231200Smm return (err); 969231200Smminvalid: 970231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 971231200Smm "Invalid LHa header"); 972231200Smm return (ARCHIVE_FATAL); 973231200Smm} 974231200Smm 975231200Smm/* 976231200Smm * Header 2 format 977231200Smm * 978231200Smm * +0 +2 +7 +11 +15 979231200Smm * +---------------+----------------+-------------------+-----------------+ 980231200Smm * |header size(*1)|compression type|compressed size(*2)|uncompressed size| 981231200Smm * +---------------+----------------+-------------------+-----------------+ 982231200Smm * <--------------------------------(*1)---------------------------------* 983231200Smm * 984231200Smm * +15 +19 +20 +21 +23 +24 985231200Smm * +-----------------+------------+----------------+----------+-----------+ 986231200Smm * |data/time(time_t)| 0x20 fixed |header level(=2)|file CRC16| creator | 987231200Smm * +-----------------+------------+----------------+----------+-----------+ 988231200Smm * *---------------------------------(*1)---------------------------------* 989231200Smm * 990231200Smm * +24 +26 +26+(*3) +26+(*3)+(*4) 991231200Smm * +----------------+-------------------+-------------+-------------------+ 992231200Smm * |next header size|extended header(*3)| padding(*4) | compressed data | 993231200Smm * +----------------+-------------------+-------------+-------------------+ 994231200Smm * *--------------------------(*1)-------------------> <------(*2)-------> 995231200Smm * 996231200Smm */ 997231200Smm#define H2_HEADER_SIZE_OFFSET 0 998231200Smm#define H2_COMP_SIZE_OFFSET 7 999231200Smm#define H2_ORIG_SIZE_OFFSET 11 1000231200Smm#define H2_TIME_OFFSET 15 1001231200Smm#define H2_CRC_OFFSET 21 1002231200Smm#define H2_FIXED_SIZE 24 1003231200Smmstatic int 1004231200Smmlha_read_file_header_2(struct archive_read *a, struct lha *lha) 1005231200Smm{ 1006231200Smm const unsigned char *p; 1007231200Smm size_t extdsize; 1008231200Smm int err, padding; 1009231200Smm uint16_t header_crc; 1010231200Smm 1011231200Smm if ((p = __archive_read_ahead(a, H2_FIXED_SIZE, NULL)) == NULL) 1012231200Smm return (truncated_error(a)); 1013231200Smm 1014231200Smm lha->header_size =archive_le16dec(p + H2_HEADER_SIZE_OFFSET); 1015231200Smm lha->compsize = archive_le32dec(p + H2_COMP_SIZE_OFFSET); 1016231200Smm lha->origsize = archive_le32dec(p + H2_ORIG_SIZE_OFFSET); 1017231200Smm lha->mtime = archive_le32dec(p + H2_TIME_OFFSET); 1018231200Smm lha->crc = archive_le16dec(p + H2_CRC_OFFSET); 1019231200Smm lha->setflag |= CRC_IS_SET; 1020231200Smm 1021231200Smm if (lha->header_size < H2_FIXED_SIZE) { 1022231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1023231200Smm "Invalid LHa header size"); 1024231200Smm return (ARCHIVE_FATAL); 1025231200Smm } 1026231200Smm 1027231200Smm header_crc = lha_crc16(0, p, H2_FIXED_SIZE); 1028231200Smm __archive_read_consume(a, H2_FIXED_SIZE); 1029231200Smm 1030231200Smm /* Read extended headers */ 1031231200Smm err = lha_read_file_extended_header(a, lha, &header_crc, 2, 1032231200Smm lha->header_size - H2_FIXED_SIZE, &extdsize); 1033231200Smm if (err < ARCHIVE_WARN) 1034231200Smm return (err); 1035231200Smm 1036231200Smm /* Calculate a padding size. The result will be normally 0 or 1. */ 1037231200Smm padding = (int)lha->header_size - (int)(H2_FIXED_SIZE + extdsize); 1038231200Smm if (padding > 0) { 1039231200Smm if ((p = __archive_read_ahead(a, padding, NULL)) == NULL) 1040231200Smm return (truncated_error(a)); 1041231200Smm header_crc = lha_crc16(header_crc, p, padding); 1042231200Smm __archive_read_consume(a, padding); 1043231200Smm } 1044231200Smm 1045231200Smm if (header_crc != lha->header_crc) { 1046231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1047231200Smm "LHa header CRC error"); 1048231200Smm return (ARCHIVE_FATAL); 1049231200Smm } 1050231200Smm return (err); 1051231200Smm} 1052231200Smm 1053231200Smm/* 1054231200Smm * Header 3 format 1055231200Smm * 1056231200Smm * +0 +2 +7 +11 +15 1057231200Smm * +------------+----------------+-------------------+-----------------+ 1058231200Smm * | 0x04 fixed |compression type|compressed size(*2)|uncompressed size| 1059231200Smm * +------------+----------------+-------------------+-----------------+ 1060231200Smm * <-------------------------------(*1)-------------------------------* 1061231200Smm * 1062231200Smm * +15 +19 +20 +21 +23 +24 1063231200Smm * +-----------------+------------+----------------+----------+-----------+ 1064231200Smm * |date/time(time_t)| 0x20 fixed |header level(=3)|file CRC16| creator | 1065231200Smm * +-----------------+------------+----------------+----------+-----------+ 1066231200Smm * *--------------------------------(*1)----------------------------------* 1067231200Smm * 1068231200Smm * +24 +28 +32 +32+(*3) 1069231200Smm * +---------------+----------------+-------------------+-----------------+ 1070231200Smm * |header size(*1)|next header size|extended header(*3)| compressed data | 1071231200Smm * +---------------+----------------+-------------------+-----------------+ 1072231200Smm * *------------------------(*1)-----------------------> <------(*2)-----> 1073231200Smm * 1074231200Smm */ 1075231200Smm#define H3_FIELD_LEN_OFFSET 0 1076231200Smm#define H3_COMP_SIZE_OFFSET 7 1077231200Smm#define H3_ORIG_SIZE_OFFSET 11 1078231200Smm#define H3_TIME_OFFSET 15 1079231200Smm#define H3_CRC_OFFSET 21 1080231200Smm#define H3_HEADER_SIZE_OFFSET 24 1081231200Smm#define H3_FIXED_SIZE 28 1082231200Smmstatic int 1083231200Smmlha_read_file_header_3(struct archive_read *a, struct lha *lha) 1084231200Smm{ 1085231200Smm const unsigned char *p; 1086231200Smm size_t extdsize; 1087231200Smm int err; 1088231200Smm uint16_t header_crc; 1089231200Smm 1090231200Smm if ((p = __archive_read_ahead(a, H3_FIXED_SIZE, NULL)) == NULL) 1091231200Smm return (truncated_error(a)); 1092231200Smm 1093231200Smm if (archive_le16dec(p + H3_FIELD_LEN_OFFSET) != 4) 1094231200Smm goto invalid; 1095231200Smm lha->header_size =archive_le32dec(p + H3_HEADER_SIZE_OFFSET); 1096231200Smm lha->compsize = archive_le32dec(p + H3_COMP_SIZE_OFFSET); 1097231200Smm lha->origsize = archive_le32dec(p + H3_ORIG_SIZE_OFFSET); 1098231200Smm lha->mtime = archive_le32dec(p + H3_TIME_OFFSET); 1099231200Smm lha->crc = archive_le16dec(p + H3_CRC_OFFSET); 1100231200Smm lha->setflag |= CRC_IS_SET; 1101231200Smm 1102231200Smm if (lha->header_size < H3_FIXED_SIZE + 4) 1103231200Smm goto invalid; 1104231200Smm header_crc = lha_crc16(0, p, H3_FIXED_SIZE); 1105231200Smm __archive_read_consume(a, H3_FIXED_SIZE); 1106231200Smm 1107231200Smm /* Read extended headers */ 1108231200Smm err = lha_read_file_extended_header(a, lha, &header_crc, 4, 1109231200Smm lha->header_size - H3_FIXED_SIZE, &extdsize); 1110231200Smm if (err < ARCHIVE_WARN) 1111231200Smm return (err); 1112231200Smm 1113231200Smm if (header_crc != lha->header_crc) { 1114231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1115231200Smm "LHa header CRC error"); 1116231200Smm return (ARCHIVE_FATAL); 1117231200Smm } 1118231200Smm return (err); 1119231200Smminvalid: 1120231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1121231200Smm "Invalid LHa header"); 1122231200Smm return (ARCHIVE_FATAL); 1123231200Smm} 1124231200Smm 1125231200Smm/* 1126231200Smm * Extended header format 1127231200Smm * 1128231200Smm * +0 +2 +3 -- used in header 1 and 2 1129231200Smm * +0 +4 +5 -- used in header 3 1130231200Smm * +--------------+---------+-------------------+--------------+-- 1131231200Smm * |ex-header size|header id| data |ex-header size| ....... 1132231200Smm * +--------------+---------+-------------------+--------------+-- 1133231200Smm * <-------------( ex-header size)------------> <-- next extended header --* 1134231200Smm * 1135231200Smm * If the ex-header size is zero, it is the make of the end of extended 1136231200Smm * headers. 1137231200Smm * 1138231200Smm */ 1139231200Smmstatic int 1140231200Smmlha_read_file_extended_header(struct archive_read *a, struct lha *lha, 1141231200Smm uint16_t *crc, int sizefield_length, size_t limitsize, size_t *total_size) 1142231200Smm{ 1143231200Smm const void *h; 1144231200Smm const unsigned char *extdheader; 1145231200Smm size_t extdsize; 1146231200Smm size_t datasize; 1147231200Smm unsigned int i; 1148231200Smm unsigned char extdtype; 1149231200Smm 1150231200Smm#define EXT_HEADER_CRC 0x00 /* Header CRC and information*/ 1151231200Smm#define EXT_FILENAME 0x01 /* Filename */ 1152231200Smm#define EXT_DIRECTORY 0x02 /* Directory name */ 1153231200Smm#define EXT_DOS_ATTR 0x40 /* MS-DOS attribute */ 1154231200Smm#define EXT_TIMESTAMP 0x41 /* Windows time stamp */ 1155231200Smm#define EXT_FILESIZE 0x42 /* Large file size */ 1156231200Smm#define EXT_TIMEZONE 0x43 /* Time zone */ 1157231200Smm#define EXT_UTF16_FILENAME 0x44 /* UTF-16 filename */ 1158231200Smm#define EXT_UTF16_DIRECTORY 0x45 /* UTF-16 directory name */ 1159231200Smm#define EXT_CODEPAGE 0x46 /* Codepage */ 1160231200Smm#define EXT_UNIX_MODE 0x50 /* File permission */ 1161231200Smm#define EXT_UNIX_GID_UID 0x51 /* gid,uid */ 1162231200Smm#define EXT_UNIX_GNAME 0x52 /* Group name */ 1163231200Smm#define EXT_UNIX_UNAME 0x53 /* User name */ 1164231200Smm#define EXT_UNIX_MTIME 0x54 /* Modified time */ 1165231200Smm#define EXT_OS2_NEW_ATTR 0x7f /* new attribute(OS/2 only) */ 1166231200Smm#define EXT_NEW_ATTR 0xff /* new attribute */ 1167231200Smm 1168231200Smm *total_size = sizefield_length; 1169231200Smm 1170231200Smm for (;;) { 1171231200Smm /* Read an extended header size. */ 1172231200Smm if ((h = 1173231200Smm __archive_read_ahead(a, sizefield_length, NULL)) == NULL) 1174231200Smm return (truncated_error(a)); 1175231200Smm /* Check if the size is the zero indicates the end of the 1176231200Smm * extended header. */ 1177231200Smm if (sizefield_length == sizeof(uint16_t)) 1178231200Smm extdsize = archive_le16dec(h); 1179231200Smm else 1180231200Smm extdsize = archive_le32dec(h); 1181231200Smm if (extdsize == 0) { 1182231200Smm /* End of extended header */ 1183231200Smm if (crc != NULL) 1184231200Smm *crc = lha_crc16(*crc, h, sizefield_length); 1185231200Smm __archive_read_consume(a, sizefield_length); 1186231200Smm return (ARCHIVE_OK); 1187231200Smm } 1188231200Smm 1189231200Smm /* Sanity check to the extended header size. */ 1190231200Smm if (((uint64_t)*total_size + extdsize) > 1191231200Smm (uint64_t)limitsize || 1192231200Smm extdsize <= (size_t)sizefield_length) 1193231200Smm goto invalid; 1194231200Smm 1195231200Smm /* Read the extended header. */ 1196231200Smm if ((h = __archive_read_ahead(a, extdsize, NULL)) == NULL) 1197231200Smm return (truncated_error(a)); 1198231200Smm *total_size += extdsize; 1199231200Smm 1200231200Smm extdheader = (const unsigned char *)h; 1201231200Smm /* Get the extended header type. */ 1202231200Smm extdtype = extdheader[sizefield_length]; 1203231200Smm /* Calculate an extended data size. */ 1204231200Smm datasize = extdsize - (1 + sizefield_length); 1205231200Smm /* Skip an extended header size field and type field. */ 1206231200Smm extdheader += sizefield_length + 1; 1207231200Smm 1208231200Smm if (crc != NULL && extdtype != EXT_HEADER_CRC) 1209231200Smm *crc = lha_crc16(*crc, h, extdsize); 1210231200Smm switch (extdtype) { 1211231200Smm case EXT_HEADER_CRC: 1212231200Smm /* We only use a header CRC. Following data will not 1213231200Smm * be used. */ 1214231200Smm if (datasize >= 2) { 1215231200Smm lha->header_crc = archive_le16dec(extdheader); 1216231200Smm if (crc != NULL) { 1217231200Smm static const char zeros[2] = {0, 0}; 1218231200Smm *crc = lha_crc16(*crc, h, 1219231200Smm extdsize - datasize); 1220231200Smm /* CRC value itself as zero */ 1221231200Smm *crc = lha_crc16(*crc, zeros, 2); 1222231200Smm *crc = lha_crc16(*crc, 1223231200Smm extdheader+2, datasize - 2); 1224231200Smm } 1225231200Smm } 1226231200Smm break; 1227231200Smm case EXT_FILENAME: 1228231200Smm if (datasize == 0) { 1229231200Smm /* maybe directory header */ 1230231200Smm archive_string_empty(&lha->filename); 1231231200Smm break; 1232231200Smm } 1233231200Smm archive_strncpy(&lha->filename, 1234231200Smm (const char *)extdheader, datasize); 1235231200Smm break; 1236231200Smm case EXT_DIRECTORY: 1237231200Smm if (datasize == 0) 1238231200Smm /* no directory name data. exit this case. */ 1239231200Smm break; 1240231200Smm 1241231200Smm archive_strncpy(&lha->dirname, 1242231200Smm (const char *)extdheader, datasize); 1243231200Smm /* 1244231200Smm * Convert directory delimiter from 0xFF 1245231200Smm * to '/' for local system. 1246231200Smm */ 1247231200Smm for (i = 0; i < lha->dirname.length; i++) { 1248231200Smm if ((unsigned char)lha->dirname.s[i] == 0xFF) 1249231200Smm lha->dirname.s[i] = '/'; 1250231200Smm } 1251231200Smm /* Is last character directory separator? */ 1252231200Smm if (lha->dirname.s[lha->dirname.length-1] != '/') 1253231200Smm /* invalid directory data */ 1254231200Smm goto invalid; 1255231200Smm break; 1256231200Smm case EXT_DOS_ATTR: 1257231200Smm if (datasize == 2) 1258231200Smm lha->dos_attr = (unsigned char) 1259231200Smm (archive_le16dec(extdheader) & 0xff); 1260231200Smm break; 1261231200Smm case EXT_TIMESTAMP: 1262231200Smm if (datasize == (sizeof(uint64_t) * 3)) { 1263231200Smm lha->birthtime = lha_win_time( 1264231200Smm archive_le64dec(extdheader), 1265231200Smm &lha->birthtime_tv_nsec); 1266231200Smm extdheader += sizeof(uint64_t); 1267231200Smm lha->mtime = lha_win_time( 1268231200Smm archive_le64dec(extdheader), 1269231200Smm &lha->mtime_tv_nsec); 1270231200Smm extdheader += sizeof(uint64_t); 1271231200Smm lha->atime = lha_win_time( 1272231200Smm archive_le64dec(extdheader), 1273231200Smm &lha->atime_tv_nsec); 1274231200Smm lha->setflag |= BIRTHTIME_IS_SET | 1275231200Smm ATIME_IS_SET; 1276231200Smm } 1277231200Smm break; 1278231200Smm case EXT_FILESIZE: 1279231200Smm if (datasize == sizeof(uint64_t) * 2) { 1280231200Smm lha->compsize = archive_le64dec(extdheader); 1281231200Smm extdheader += sizeof(uint64_t); 1282231200Smm lha->origsize = archive_le64dec(extdheader); 1283231200Smm } 1284231200Smm break; 1285231200Smm case EXT_CODEPAGE: 1286231200Smm /* Get an archived filename charset from codepage. 1287231200Smm * This overwrites the charset specified by 1288231200Smm * hdrcharset option. */ 1289231200Smm if (datasize == sizeof(uint32_t)) { 1290231200Smm struct archive_string cp; 1291231200Smm const char *charset; 1292231200Smm 1293231200Smm archive_string_init(&cp); 1294231200Smm switch (archive_le32dec(extdheader)) { 1295231200Smm case 65001: /* UTF-8 */ 1296231200Smm charset = "UTF-8"; 1297231200Smm break; 1298231200Smm default: 1299231200Smm archive_string_sprintf(&cp, "CP%d", 1300231200Smm (int)archive_le32dec(extdheader)); 1301231200Smm charset = cp.s; 1302231200Smm break; 1303231200Smm } 1304231200Smm lha->sconv = 1305231200Smm archive_string_conversion_from_charset( 1306231200Smm &(a->archive), charset, 1); 1307231200Smm archive_string_free(&cp); 1308231200Smm if (lha->sconv == NULL) 1309231200Smm return (ARCHIVE_FATAL); 1310231200Smm } 1311231200Smm break; 1312231200Smm case EXT_UNIX_MODE: 1313231200Smm if (datasize == sizeof(uint16_t)) { 1314231200Smm lha->mode = archive_le16dec(extdheader); 1315231200Smm lha->setflag |= UNIX_MODE_IS_SET; 1316231200Smm } 1317231200Smm break; 1318231200Smm case EXT_UNIX_GID_UID: 1319231200Smm if (datasize == (sizeof(uint16_t) * 2)) { 1320231200Smm lha->gid = archive_le16dec(extdheader); 1321231200Smm lha->uid = archive_le16dec(extdheader+2); 1322231200Smm } 1323231200Smm break; 1324231200Smm case EXT_UNIX_GNAME: 1325231200Smm if (datasize > 0) 1326231200Smm archive_strncpy(&lha->gname, 1327231200Smm (const char *)extdheader, datasize); 1328231200Smm break; 1329231200Smm case EXT_UNIX_UNAME: 1330231200Smm if (datasize > 0) 1331231200Smm archive_strncpy(&lha->uname, 1332231200Smm (const char *)extdheader, datasize); 1333231200Smm break; 1334231200Smm case EXT_UNIX_MTIME: 1335231200Smm if (datasize == sizeof(uint32_t)) 1336231200Smm lha->mtime = archive_le32dec(extdheader); 1337231200Smm break; 1338231200Smm case EXT_OS2_NEW_ATTR: 1339231200Smm /* This extended header is OS/2 depend. */ 1340231200Smm if (datasize == 16) { 1341231200Smm lha->dos_attr = (unsigned char) 1342231200Smm (archive_le16dec(extdheader) & 0xff); 1343231200Smm lha->mode = archive_le16dec(extdheader+2); 1344231200Smm lha->gid = archive_le16dec(extdheader+4); 1345231200Smm lha->uid = archive_le16dec(extdheader+6); 1346231200Smm lha->birthtime = archive_le32dec(extdheader+8); 1347231200Smm lha->atime = archive_le32dec(extdheader+12); 1348231200Smm lha->setflag |= UNIX_MODE_IS_SET 1349231200Smm | BIRTHTIME_IS_SET | ATIME_IS_SET; 1350231200Smm } 1351231200Smm break; 1352231200Smm case EXT_NEW_ATTR: 1353231200Smm if (datasize == 20) { 1354231200Smm lha->mode = (mode_t)archive_le32dec(extdheader); 1355231200Smm lha->gid = archive_le32dec(extdheader+4); 1356231200Smm lha->uid = archive_le32dec(extdheader+8); 1357231200Smm lha->birthtime = archive_le32dec(extdheader+12); 1358231200Smm lha->atime = archive_le32dec(extdheader+16); 1359231200Smm lha->setflag |= UNIX_MODE_IS_SET 1360231200Smm | BIRTHTIME_IS_SET | ATIME_IS_SET; 1361231200Smm } 1362231200Smm break; 1363231200Smm case EXT_TIMEZONE: /* Not supported */ 1364231200Smm case EXT_UTF16_FILENAME: /* Not supported */ 1365231200Smm case EXT_UTF16_DIRECTORY: /* Not supported */ 1366231200Smm default: 1367231200Smm break; 1368231200Smm } 1369231200Smm 1370231200Smm __archive_read_consume(a, extdsize); 1371231200Smm } 1372231200Smminvalid: 1373231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1374231200Smm "Invalid extended LHa header"); 1375231200Smm return (ARCHIVE_FATAL); 1376231200Smm} 1377231200Smm 1378231200Smmstatic int 1379231200Smmarchive_read_format_lha_read_data(struct archive_read *a, 1380231200Smm const void **buff, size_t *size, int64_t *offset) 1381231200Smm{ 1382231200Smm struct lha *lha = (struct lha *)(a->format->data); 1383231200Smm int r; 1384231200Smm 1385231200Smm if (lha->entry_unconsumed) { 1386231200Smm /* Consume as much as the decompressor actually used. */ 1387231200Smm __archive_read_consume(a, lha->entry_unconsumed); 1388231200Smm lha->entry_unconsumed = 0; 1389231200Smm } 1390231200Smm if (lha->end_of_entry) { 1391231200Smm if (!lha->end_of_entry_cleanup) { 1392231200Smm if ((lha->setflag & CRC_IS_SET) && 1393231200Smm lha->crc != lha->entry_crc_calculated) { 1394231200Smm archive_set_error(&a->archive, 1395231200Smm ARCHIVE_ERRNO_MISC, 1396231200Smm "LHa data CRC error"); 1397231200Smm return (ARCHIVE_WARN); 1398231200Smm } 1399231200Smm 1400231200Smm /* End-of-entry cleanup done. */ 1401231200Smm lha->end_of_entry_cleanup = 1; 1402231200Smm } 1403231200Smm *offset = lha->entry_offset; 1404231200Smm *size = 0; 1405231200Smm *buff = NULL; 1406231200Smm return (ARCHIVE_EOF); 1407231200Smm } 1408231200Smm 1409231200Smm if (lha->entry_is_compressed) 1410231200Smm r = lha_read_data_lzh(a, buff, size, offset); 1411231200Smm else 1412231200Smm /* No compression. */ 1413231200Smm r = lha_read_data_none(a, buff, size, offset); 1414231200Smm return (r); 1415231200Smm} 1416231200Smm 1417231200Smm/* 1418231200Smm * Read a file content in no compression. 1419231200Smm * 1420231200Smm * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets 1421231200Smm * lha->end_of_entry if it consumes all of the data. 1422231200Smm */ 1423231200Smmstatic int 1424231200Smmlha_read_data_none(struct archive_read *a, const void **buff, 1425231200Smm size_t *size, int64_t *offset) 1426231200Smm{ 1427231200Smm struct lha *lha = (struct lha *)(a->format->data); 1428231200Smm ssize_t bytes_avail; 1429231200Smm 1430231200Smm if (lha->entry_bytes_remaining == 0) { 1431231200Smm *buff = NULL; 1432231200Smm *size = 0; 1433231200Smm *offset = lha->entry_offset; 1434231200Smm lha->end_of_entry = 1; 1435231200Smm return (ARCHIVE_OK); 1436231200Smm } 1437231200Smm /* 1438231200Smm * Note: '1' here is a performance optimization. 1439231200Smm * Recall that the decompression layer returns a count of 1440231200Smm * available bytes; asking for more than that forces the 1441231200Smm * decompressor to combine reads by copying data. 1442231200Smm */ 1443231200Smm *buff = __archive_read_ahead(a, 1, &bytes_avail); 1444231200Smm if (bytes_avail <= 0) { 1445231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1446231200Smm "Truncated LHa file data"); 1447231200Smm return (ARCHIVE_FATAL); 1448231200Smm } 1449231200Smm if (bytes_avail > lha->entry_bytes_remaining) 1450238856Smm bytes_avail = (ssize_t)lha->entry_bytes_remaining; 1451231200Smm lha->entry_crc_calculated = 1452231200Smm lha_crc16(lha->entry_crc_calculated, *buff, bytes_avail); 1453231200Smm *size = bytes_avail; 1454231200Smm *offset = lha->entry_offset; 1455231200Smm lha->entry_offset += bytes_avail; 1456231200Smm lha->entry_bytes_remaining -= bytes_avail; 1457231200Smm if (lha->entry_bytes_remaining == 0) 1458231200Smm lha->end_of_entry = 1; 1459231200Smm lha->entry_unconsumed = bytes_avail; 1460231200Smm return (ARCHIVE_OK); 1461231200Smm} 1462231200Smm 1463231200Smm/* 1464231200Smm * Read a file content in LZHUFF encoding. 1465231200Smm * 1466231200Smm * Returns ARCHIVE_OK if successful, returns ARCHIVE_WARN if compression is 1467231200Smm * unsupported, ARCHIVE_FATAL otherwise, sets lha->end_of_entry if it consumes 1468231200Smm * all of the data. 1469231200Smm */ 1470231200Smmstatic int 1471231200Smmlha_read_data_lzh(struct archive_read *a, const void **buff, 1472231200Smm size_t *size, int64_t *offset) 1473231200Smm{ 1474231200Smm struct lha *lha = (struct lha *)(a->format->data); 1475231200Smm ssize_t bytes_avail; 1476231200Smm int r; 1477231200Smm 1478231200Smm /* If the buffer hasn't been allocated, allocate it now. */ 1479231200Smm if (lha->uncompressed_buffer == NULL) { 1480231200Smm lha->uncompressed_buffer_size = 64 * 1024; 1481231200Smm lha->uncompressed_buffer 1482231200Smm = (unsigned char *)malloc(lha->uncompressed_buffer_size); 1483231200Smm if (lha->uncompressed_buffer == NULL) { 1484231200Smm archive_set_error(&a->archive, ENOMEM, 1485231200Smm "No memory for lzh decompression"); 1486231200Smm return (ARCHIVE_FATAL); 1487231200Smm } 1488231200Smm } 1489231200Smm 1490231200Smm /* If we haven't yet read any data, initialize the decompressor. */ 1491231200Smm if (!lha->decompress_init) { 1492231200Smm r = lzh_decode_init(&(lha->strm), lha->method); 1493231200Smm switch (r) { 1494231200Smm case ARCHIVE_OK: 1495231200Smm break; 1496231200Smm case ARCHIVE_FAILED: 1497231200Smm /* Unsupported compression. */ 1498231200Smm *buff = NULL; 1499231200Smm *size = 0; 1500231200Smm *offset = 0; 1501231200Smm archive_set_error(&a->archive, 1502231200Smm ARCHIVE_ERRNO_FILE_FORMAT, 1503231200Smm "Unsupported lzh compression method -%c%c%c-", 1504231200Smm lha->method[0], lha->method[1], lha->method[2]); 1505231200Smm /* We know compressed size; just skip it. */ 1506231200Smm archive_read_format_lha_read_data_skip(a); 1507231200Smm return (ARCHIVE_WARN); 1508231200Smm default: 1509231200Smm archive_set_error(&a->archive, ENOMEM, 1510231200Smm "Couldn't allocate memory " 1511231200Smm "for lzh decompression"); 1512231200Smm return (ARCHIVE_FATAL); 1513231200Smm } 1514231200Smm /* We've initialized decompression for this stream. */ 1515231200Smm lha->decompress_init = 1; 1516231200Smm lha->strm.avail_out = 0; 1517231200Smm lha->strm.total_out = 0; 1518231200Smm } 1519231200Smm 1520231200Smm /* 1521231200Smm * Note: '1' here is a performance optimization. 1522231200Smm * Recall that the decompression layer returns a count of 1523231200Smm * available bytes; asking for more than that forces the 1524231200Smm * decompressor to combine reads by copying data. 1525231200Smm */ 1526231200Smm lha->strm.next_in = __archive_read_ahead(a, 1, &bytes_avail); 1527231200Smm if (bytes_avail <= 0) { 1528231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, 1529231200Smm "Truncated LHa file body"); 1530231200Smm return (ARCHIVE_FATAL); 1531231200Smm } 1532231200Smm if (bytes_avail > lha->entry_bytes_remaining) 1533238856Smm bytes_avail = (ssize_t)lha->entry_bytes_remaining; 1534231200Smm 1535231200Smm lha->strm.avail_in = bytes_avail; 1536231200Smm lha->strm.total_in = 0; 1537231200Smm if (lha->strm.avail_out == 0) { 1538231200Smm lha->strm.next_out = lha->uncompressed_buffer; 1539231200Smm lha->strm.avail_out = lha->uncompressed_buffer_size; 1540231200Smm } 1541231200Smm 1542231200Smm r = lzh_decode(&(lha->strm), bytes_avail == lha->entry_bytes_remaining); 1543231200Smm switch (r) { 1544231200Smm case ARCHIVE_OK: 1545231200Smm break; 1546231200Smm case ARCHIVE_EOF: 1547231200Smm lha->end_of_entry = 1; 1548231200Smm break; 1549231200Smm default: 1550231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1551231200Smm "Bad lzh data"); 1552231200Smm return (ARCHIVE_FAILED); 1553231200Smm } 1554231200Smm lha->entry_unconsumed = lha->strm.total_in; 1555231200Smm lha->entry_bytes_remaining -= lha->strm.total_in; 1556231200Smm 1557231200Smm if (lha->strm.avail_out == 0 || lha->end_of_entry) { 1558231200Smm *offset = lha->entry_offset; 1559231200Smm *size = lha->strm.next_out - lha->uncompressed_buffer; 1560231200Smm *buff = lha->uncompressed_buffer; 1561231200Smm lha->entry_crc_calculated = 1562231200Smm lha_crc16(lha->entry_crc_calculated, *buff, *size); 1563231200Smm lha->entry_offset += *size; 1564231200Smm } else { 1565231200Smm *offset = lha->entry_offset; 1566231200Smm *size = 0; 1567231200Smm *buff = NULL; 1568231200Smm } 1569231200Smm return (ARCHIVE_OK); 1570231200Smm} 1571231200Smm 1572231200Smm/* 1573231200Smm * Skip a file content. 1574231200Smm */ 1575231200Smmstatic int 1576231200Smmarchive_read_format_lha_read_data_skip(struct archive_read *a) 1577231200Smm{ 1578231200Smm struct lha *lha; 1579238856Smm int64_t bytes_skipped; 1580231200Smm 1581231200Smm lha = (struct lha *)(a->format->data); 1582231200Smm 1583231200Smm if (lha->entry_unconsumed) { 1584231200Smm /* Consume as much as the decompressor actually used. */ 1585231200Smm __archive_read_consume(a, lha->entry_unconsumed); 1586231200Smm lha->entry_unconsumed = 0; 1587231200Smm } 1588231200Smm 1589231200Smm /* if we've already read to end of data, we're done. */ 1590231200Smm if (lha->end_of_entry_cleanup) 1591231200Smm return (ARCHIVE_OK); 1592231200Smm 1593231200Smm /* 1594231200Smm * If the length is at the beginning, we can skip the 1595231200Smm * compressed data much more quickly. 1596231200Smm */ 1597231200Smm bytes_skipped = __archive_read_consume(a, lha->entry_bytes_remaining); 1598231200Smm if (bytes_skipped < 0) 1599231200Smm return (ARCHIVE_FATAL); 1600231200Smm 1601231200Smm /* This entry is finished and done. */ 1602231200Smm lha->end_of_entry_cleanup = lha->end_of_entry = 1; 1603231200Smm return (ARCHIVE_OK); 1604231200Smm} 1605231200Smm 1606231200Smmstatic int 1607231200Smmarchive_read_format_lha_cleanup(struct archive_read *a) 1608231200Smm{ 1609231200Smm struct lha *lha = (struct lha *)(a->format->data); 1610231200Smm 1611231200Smm lzh_decode_free(&(lha->strm)); 1612231200Smm free(lha->uncompressed_buffer); 1613231200Smm archive_string_free(&(lha->dirname)); 1614231200Smm archive_string_free(&(lha->filename)); 1615231200Smm archive_string_free(&(lha->uname)); 1616231200Smm archive_string_free(&(lha->gname)); 1617231200Smm archive_wstring_free(&(lha->ws)); 1618231200Smm free(lha); 1619231200Smm (a->format->data) = NULL; 1620231200Smm return (ARCHIVE_OK); 1621231200Smm} 1622231200Smm 1623231200Smm/* 1624231200Smm * 'LHa for UNIX' utility has archived a symbolic-link name after 1625231200Smm * a pathname with '|' character. 1626231200Smm * This function extracts the symbolic-link name from the pathname. 1627231200Smm * 1628231200Smm * example. 1629231200Smm * 1. a symbolic-name is 'aaa/bb/cc' 1630231200Smm * 2. a filename is 'xxx/bbb' 1631231200Smm * then a archived pathname is 'xxx/bbb|aaa/bb/cc' 1632231200Smm */ 1633231200Smmstatic int 1634231200Smmlha_parse_linkname(struct archive_string *linkname, 1635231200Smm struct archive_string *pathname) 1636231200Smm{ 1637231200Smm char * linkptr; 1638248616Smm size_t symlen; 1639231200Smm 1640231200Smm linkptr = strchr(pathname->s, '|'); 1641231200Smm if (linkptr != NULL) { 1642231200Smm symlen = strlen(linkptr + 1); 1643231200Smm archive_strncpy(linkname, linkptr+1, symlen); 1644231200Smm 1645231200Smm *linkptr = 0; 1646231200Smm pathname->length = strlen(pathname->s); 1647231200Smm 1648231200Smm return (1); 1649231200Smm } 1650231200Smm return (0); 1651231200Smm} 1652231200Smm 1653231200Smm/* Convert an MSDOS-style date/time into Unix-style time. */ 1654231200Smmstatic time_t 1655231200Smmlha_dos_time(const unsigned char *p) 1656231200Smm{ 1657231200Smm int msTime, msDate; 1658231200Smm struct tm ts; 1659231200Smm 1660231200Smm msTime = archive_le16dec(p); 1661231200Smm msDate = archive_le16dec(p+2); 1662231200Smm 1663231200Smm memset(&ts, 0, sizeof(ts)); 1664231200Smm ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */ 1665231200Smm ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */ 1666231200Smm ts.tm_mday = msDate & 0x1f; /* Day of month. */ 1667231200Smm ts.tm_hour = (msTime >> 11) & 0x1f; 1668231200Smm ts.tm_min = (msTime >> 5) & 0x3f; 1669231200Smm ts.tm_sec = (msTime << 1) & 0x3e; 1670231200Smm ts.tm_isdst = -1; 1671231200Smm return (mktime(&ts)); 1672231200Smm} 1673231200Smm 1674231200Smm/* Convert an MS-Windows-style date/time into Unix-style time. */ 1675231200Smmstatic time_t 1676231200Smmlha_win_time(uint64_t wintime, long *ns) 1677231200Smm{ 1678231200Smm#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) 1679231200Smm 1680231200Smm if (wintime >= EPOC_TIME) { 1681231200Smm wintime -= EPOC_TIME; /* 1970-01-01 00:00:00 (UTC) */ 1682231200Smm if (ns != NULL) 1683231200Smm *ns = (long)(wintime % 10000000) * 100; 1684231200Smm return (wintime / 10000000); 1685231200Smm } else { 1686231200Smm if (ns != NULL) 1687231200Smm *ns = 0; 1688231200Smm return (0); 1689231200Smm } 1690231200Smm} 1691231200Smm 1692231200Smmstatic unsigned char 1693248616Smmlha_calcsum(unsigned char sum, const void *pp, int offset, size_t size) 1694231200Smm{ 1695231200Smm unsigned char const *p = (unsigned char const *)pp; 1696231200Smm 1697231200Smm p += offset; 1698248616Smm for (;size > 0; --size) 1699231200Smm sum += *p++; 1700231200Smm return (sum); 1701231200Smm} 1702231200Smm 1703231200Smm#define CRC16(crc, v) do { \ 1704231200Smm (crc) = crc16tbl[((crc) ^ v) & 0xFF] ^ ((crc) >> 8); \ 1705231200Smm} while (0) 1706231200Smm 1707231200Smmstatic uint16_t 1708231200Smmlha_crc16(uint16_t crc, const void *pp, size_t len) 1709231200Smm{ 1710231200Smm const unsigned char *buff = (const unsigned char *)pp; 1711231200Smm 1712231200Smm while (len >= 8) { 1713231200Smm CRC16(crc, *buff++); CRC16(crc, *buff++); 1714231200Smm CRC16(crc, *buff++); CRC16(crc, *buff++); 1715231200Smm CRC16(crc, *buff++); CRC16(crc, *buff++); 1716231200Smm CRC16(crc, *buff++); CRC16(crc, *buff++); 1717231200Smm len -= 8; 1718231200Smm } 1719231200Smm switch (len) { 1720231200Smm case 7: 1721231200Smm CRC16(crc, *buff++); 1722231200Smm /* FALL THROUGH */ 1723231200Smm case 6: 1724231200Smm CRC16(crc, *buff++); 1725231200Smm /* FALL THROUGH */ 1726231200Smm case 5: 1727231200Smm CRC16(crc, *buff++); 1728231200Smm /* FALL THROUGH */ 1729231200Smm case 4: 1730231200Smm CRC16(crc, *buff++); 1731231200Smm /* FALL THROUGH */ 1732231200Smm case 3: 1733231200Smm CRC16(crc, *buff++); 1734231200Smm /* FALL THROUGH */ 1735231200Smm case 2: 1736231200Smm CRC16(crc, *buff++); 1737231200Smm /* FALL THROUGH */ 1738231200Smm case 1: 1739231200Smm CRC16(crc, *buff); 1740231200Smm /* FALL THROUGH */ 1741231200Smm case 0: 1742231200Smm break; 1743231200Smm } 1744231200Smm return (crc); 1745231200Smm} 1746231200Smm 1747231200Smm 1748231200Smm/* 1749231200Smm * Initialize LZHUF decoder. 1750231200Smm * 1751231200Smm * Returns ARCHIVE_OK if initialization was successful. 1752231200Smm * Returns ARCHIVE_FAILED if method is unsupported. 1753231200Smm * Returns ARCHIVE_FATAL if initialization failed; memory allocation 1754231200Smm * error occurred. 1755231200Smm */ 1756231200Smmstatic int 1757231200Smmlzh_decode_init(struct lzh_stream *strm, const char *method) 1758231200Smm{ 1759231200Smm struct lzh_dec *ds; 1760231200Smm int w_bits, w_size; 1761231200Smm 1762231200Smm if (strm->ds == NULL) { 1763231200Smm strm->ds = calloc(1, sizeof(*strm->ds)); 1764231200Smm if (strm->ds == NULL) 1765231200Smm return (ARCHIVE_FATAL); 1766231200Smm } 1767231200Smm ds = strm->ds; 1768231200Smm ds->error = ARCHIVE_FAILED; 1769231200Smm if (method == NULL || method[0] != 'l' || method[1] != 'h') 1770231200Smm return (ARCHIVE_FAILED); 1771231200Smm switch (method[2]) { 1772231200Smm case '5': 1773231200Smm w_bits = 13;/* 8KiB for window */ 1774231200Smm break; 1775231200Smm case '6': 1776231200Smm w_bits = 15;/* 32KiB for window */ 1777231200Smm break; 1778231200Smm case '7': 1779231200Smm w_bits = 16;/* 64KiB for window */ 1780231200Smm break; 1781231200Smm default: 1782231200Smm return (ARCHIVE_FAILED);/* Not supported. */ 1783231200Smm } 1784231200Smm ds->error = ARCHIVE_FATAL; 1785231200Smm w_size = ds->w_size; 1786231200Smm ds->w_size = 1U << w_bits; 1787231200Smm ds->w_mask = ds->w_size -1; 1788231200Smm if (ds->w_buff == NULL || w_size != ds->w_size) { 1789231200Smm free(ds->w_buff); 1790231200Smm ds->w_buff = malloc(ds->w_size); 1791231200Smm if (ds->w_buff == NULL) 1792231200Smm return (ARCHIVE_FATAL); 1793231200Smm } 1794231200Smm memset(ds->w_buff, 0x20, ds->w_size); 1795231200Smm ds->w_pos = 0; 1796231200Smm ds->w_remaining = 0; 1797231200Smm ds->state = 0; 1798231200Smm ds->pos_pt_len_size = w_bits + 1; 1799231200Smm ds->pos_pt_len_bits = (w_bits == 15 || w_bits == 16)? 5: 4; 1800231200Smm ds->literal_pt_len_size = PT_BITLEN_SIZE; 1801231200Smm ds->literal_pt_len_bits = 5; 1802231200Smm ds->br.cache_buffer = 0; 1803231200Smm ds->br.cache_avail = 0; 1804231200Smm 1805231200Smm if (lzh_huffman_init(&(ds->lt), LT_BITLEN_SIZE, 16) 1806231200Smm != ARCHIVE_OK) 1807231200Smm return (ARCHIVE_FATAL); 1808231200Smm ds->lt.len_bits = 9; 1809231200Smm if (lzh_huffman_init(&(ds->pt), PT_BITLEN_SIZE, 16) 1810231200Smm != ARCHIVE_OK) 1811231200Smm return (ARCHIVE_FATAL); 1812231200Smm ds->error = 0; 1813231200Smm 1814231200Smm return (ARCHIVE_OK); 1815231200Smm} 1816231200Smm 1817231200Smm/* 1818231200Smm * Release LZHUF decoder. 1819231200Smm */ 1820231200Smmstatic void 1821231200Smmlzh_decode_free(struct lzh_stream *strm) 1822231200Smm{ 1823231200Smm 1824231200Smm if (strm->ds == NULL) 1825231200Smm return; 1826231200Smm free(strm->ds->w_buff); 1827231200Smm lzh_huffman_free(&(strm->ds->lt)); 1828231200Smm lzh_huffman_free(&(strm->ds->pt)); 1829231200Smm free(strm->ds); 1830231200Smm strm->ds = NULL; 1831231200Smm} 1832231200Smm 1833231200Smm/* 1834231200Smm * Bit stream reader. 1835231200Smm */ 1836231200Smm/* Check that the cache buffer has enough bits. */ 1837231200Smm#define lzh_br_has(br, n) ((br)->cache_avail >= n) 1838231200Smm/* Get compressed data by bit. */ 1839231200Smm#define lzh_br_bits(br, n) \ 1840231200Smm (((uint16_t)((br)->cache_buffer >> \ 1841231200Smm ((br)->cache_avail - (n)))) & cache_masks[n]) 1842231200Smm#define lzh_br_bits_forced(br, n) \ 1843231200Smm (((uint16_t)((br)->cache_buffer << \ 1844231200Smm ((n) - (br)->cache_avail))) & cache_masks[n]) 1845231200Smm/* Read ahead to make sure the cache buffer has enough compressed data we 1846231200Smm * will use. 1847231200Smm * True : completed, there is enough data in the cache buffer. 1848231200Smm * False : we met that strm->next_in is empty, we have to get following 1849231200Smm * bytes. */ 1850231200Smm#define lzh_br_read_ahead_0(strm, br, n) \ 1851231200Smm (lzh_br_has(br, (n)) || lzh_br_fillup(strm, br)) 1852231200Smm/* True : the cache buffer has some bits as much as we need. 1853231200Smm * False : there are no enough bits in the cache buffer to be used, 1854231200Smm * we have to get following bytes if we could. */ 1855231200Smm#define lzh_br_read_ahead(strm, br, n) \ 1856231200Smm (lzh_br_read_ahead_0((strm), (br), (n)) || lzh_br_has((br), (n))) 1857231200Smm 1858231200Smm/* Notify how many bits we consumed. */ 1859231200Smm#define lzh_br_consume(br, n) ((br)->cache_avail -= (n)) 1860231200Smm#define lzh_br_unconsume(br, n) ((br)->cache_avail += (n)) 1861231200Smm 1862231200Smmstatic const uint16_t cache_masks[] = { 1863231200Smm 0x0000, 0x0001, 0x0003, 0x0007, 1864231200Smm 0x000F, 0x001F, 0x003F, 0x007F, 1865231200Smm 0x00FF, 0x01FF, 0x03FF, 0x07FF, 1866231200Smm 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 1867231200Smm 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF 1868231200Smm}; 1869231200Smm 1870231200Smm/* 1871231200Smm * Shift away used bits in the cache data and fill it up with following bits. 1872231200Smm * Call this when cache buffer does not have enough bits you need. 1873231200Smm * 1874231200Smm * Returns 1 if the cache buffer is full. 1875231200Smm * Returns 0 if the cache buffer is not full; input buffer is empty. 1876231200Smm */ 1877231200Smmstatic int 1878231200Smmlzh_br_fillup(struct lzh_stream *strm, struct lzh_br *br) 1879231200Smm{ 1880231200Smm int n = CACHE_BITS - br->cache_avail; 1881231200Smm 1882231200Smm for (;;) { 1883231200Smm switch (n >> 3) { 1884231200Smm case 8: 1885231200Smm if (strm->avail_in >= 8) { 1886231200Smm br->cache_buffer = 1887231200Smm ((uint64_t)strm->next_in[0]) << 56 | 1888231200Smm ((uint64_t)strm->next_in[1]) << 48 | 1889231200Smm ((uint64_t)strm->next_in[2]) << 40 | 1890231200Smm ((uint64_t)strm->next_in[3]) << 32 | 1891231200Smm ((uint32_t)strm->next_in[4]) << 24 | 1892231200Smm ((uint32_t)strm->next_in[5]) << 16 | 1893231200Smm ((uint32_t)strm->next_in[6]) << 8 | 1894231200Smm (uint32_t)strm->next_in[7]; 1895231200Smm strm->next_in += 8; 1896231200Smm strm->avail_in -= 8; 1897231200Smm br->cache_avail += 8 * 8; 1898231200Smm return (1); 1899231200Smm } 1900231200Smm break; 1901231200Smm case 7: 1902231200Smm if (strm->avail_in >= 7) { 1903231200Smm br->cache_buffer = 1904231200Smm (br->cache_buffer << 56) | 1905231200Smm ((uint64_t)strm->next_in[0]) << 48 | 1906231200Smm ((uint64_t)strm->next_in[1]) << 40 | 1907231200Smm ((uint64_t)strm->next_in[2]) << 32 | 1908231200Smm ((uint32_t)strm->next_in[3]) << 24 | 1909231200Smm ((uint32_t)strm->next_in[4]) << 16 | 1910231200Smm ((uint32_t)strm->next_in[5]) << 8 | 1911231200Smm (uint32_t)strm->next_in[6]; 1912231200Smm strm->next_in += 7; 1913231200Smm strm->avail_in -= 7; 1914231200Smm br->cache_avail += 7 * 8; 1915231200Smm return (1); 1916231200Smm } 1917231200Smm break; 1918231200Smm case 6: 1919231200Smm if (strm->avail_in >= 6) { 1920231200Smm br->cache_buffer = 1921231200Smm (br->cache_buffer << 48) | 1922231200Smm ((uint64_t)strm->next_in[0]) << 40 | 1923231200Smm ((uint64_t)strm->next_in[1]) << 32 | 1924231200Smm ((uint32_t)strm->next_in[2]) << 24 | 1925231200Smm ((uint32_t)strm->next_in[3]) << 16 | 1926231200Smm ((uint32_t)strm->next_in[4]) << 8 | 1927231200Smm (uint32_t)strm->next_in[5]; 1928231200Smm strm->next_in += 6; 1929231200Smm strm->avail_in -= 6; 1930231200Smm br->cache_avail += 6 * 8; 1931231200Smm return (1); 1932231200Smm } 1933231200Smm break; 1934231200Smm case 0: 1935231200Smm /* We have enough compressed data in 1936231200Smm * the cache buffer.*/ 1937231200Smm return (1); 1938231200Smm default: 1939231200Smm break; 1940231200Smm } 1941231200Smm if (strm->avail_in == 0) { 1942231200Smm /* There is not enough compressed data to fill up the 1943231200Smm * cache buffer. */ 1944231200Smm return (0); 1945231200Smm } 1946231200Smm br->cache_buffer = 1947231200Smm (br->cache_buffer << 8) | *strm->next_in++; 1948231200Smm strm->avail_in--; 1949231200Smm br->cache_avail += 8; 1950231200Smm n -= 8; 1951231200Smm } 1952231200Smm} 1953231200Smm 1954231200Smm/* 1955231200Smm * Decode LZHUF. 1956231200Smm * 1957231200Smm * 1. Returns ARCHIVE_OK if output buffer or input buffer are empty. 1958231200Smm * Please set available buffer and call this function again. 1959231200Smm * 2. Returns ARCHIVE_EOF if decompression has been completed. 1960231200Smm * 3. Returns ARCHIVE_FAILED if an error occurred; compressed data 1961231200Smm * is broken or you do not set 'last' flag properly. 1962231200Smm * 4. 'last' flag is very important, you must set 1 to the flag if there 1963231200Smm * is no input data. The lha compressed data format does not provide how 1964231200Smm * to know the compressed data is really finished. 1965231200Smm * Note: lha command utility check if the total size of output bytes is 1966231200Smm * reached the uncompressed size recorded in its header. it does not mind 1967231200Smm * that the decoding process is properly finished. 1968231200Smm * GNU ZIP can decompress another compressed file made by SCO LZH compress. 1969231200Smm * it handles EOF as null to fill read buffer with zero until the decoding 1970231200Smm * process meet 2 bytes of zeros at reading a size of a next chunk, so the 1971231200Smm * zeros are treated as the mark of the end of the data although the zeros 1972231200Smm * is dummy, not the file data. 1973231200Smm */ 1974231200Smmstatic int lzh_read_blocks(struct lzh_stream *, int); 1975231200Smmstatic int lzh_decode_blocks(struct lzh_stream *, int); 1976231200Smm#define ST_RD_BLOCK 0 1977231200Smm#define ST_RD_PT_1 1 1978231200Smm#define ST_RD_PT_2 2 1979231200Smm#define ST_RD_PT_3 3 1980231200Smm#define ST_RD_PT_4 4 1981231200Smm#define ST_RD_LITERAL_1 5 1982231200Smm#define ST_RD_LITERAL_2 6 1983231200Smm#define ST_RD_LITERAL_3 7 1984231200Smm#define ST_RD_POS_DATA_1 8 1985231200Smm#define ST_GET_LITERAL 9 1986231200Smm#define ST_GET_POS_1 10 1987231200Smm#define ST_GET_POS_2 11 1988231200Smm#define ST_COPY_DATA 12 1989231200Smm 1990231200Smmstatic int 1991231200Smmlzh_decode(struct lzh_stream *strm, int last) 1992231200Smm{ 1993231200Smm struct lzh_dec *ds = strm->ds; 1994231200Smm int64_t avail_in; 1995231200Smm int r; 1996231200Smm 1997231200Smm if (ds->error) 1998231200Smm return (ds->error); 1999231200Smm 2000231200Smm avail_in = strm->avail_in; 2001231200Smm do { 2002231200Smm if (ds->state < ST_GET_LITERAL) 2003231200Smm r = lzh_read_blocks(strm, last); 2004231200Smm else 2005231200Smm r = lzh_decode_blocks(strm, last); 2006231200Smm } while (r == 100); 2007231200Smm strm->total_in += avail_in - strm->avail_in; 2008231200Smm return (r); 2009231200Smm} 2010231200Smm 2011231200Smmstatic int 2012231200Smmlzh_copy_from_window(struct lzh_stream *strm, struct lzh_dec *ds) 2013231200Smm{ 2014231200Smm size_t copy_bytes; 2015231200Smm 2016231200Smm if (ds->w_remaining == 0 && ds->w_pos > 0) { 2017231200Smm if (ds->w_pos - ds->copy_pos <= strm->avail_out) 2018231200Smm copy_bytes = ds->w_pos - ds->copy_pos; 2019231200Smm else 2020238856Smm copy_bytes = (size_t)strm->avail_out; 2021231200Smm memcpy(strm->next_out, 2022231200Smm ds->w_buff + ds->copy_pos, copy_bytes); 2023248616Smm ds->copy_pos += (int)copy_bytes; 2024231200Smm } else { 2025231200Smm if (ds->w_remaining <= strm->avail_out) 2026231200Smm copy_bytes = ds->w_remaining; 2027231200Smm else 2028238856Smm copy_bytes = (size_t)strm->avail_out; 2029231200Smm memcpy(strm->next_out, 2030231200Smm ds->w_buff + ds->w_size - ds->w_remaining, copy_bytes); 2031248616Smm ds->w_remaining -= (int)copy_bytes; 2032231200Smm } 2033231200Smm strm->next_out += copy_bytes; 2034231200Smm strm->avail_out -= copy_bytes; 2035231200Smm strm->total_out += copy_bytes; 2036231200Smm if (strm->avail_out == 0) 2037231200Smm return (0); 2038231200Smm else 2039231200Smm return (1); 2040231200Smm} 2041231200Smm 2042231200Smmstatic int 2043231200Smmlzh_read_blocks(struct lzh_stream *strm, int last) 2044231200Smm{ 2045231200Smm struct lzh_dec *ds = strm->ds; 2046231200Smm struct lzh_br *br = &(ds->br); 2047231200Smm int c = 0, i; 2048231200Smm unsigned rbits; 2049231200Smm 2050231200Smm for (;;) { 2051231200Smm switch (ds->state) { 2052231200Smm case ST_RD_BLOCK: 2053231200Smm /* 2054231200Smm * Read a block number indicates how many blocks 2055231200Smm * we will handle. The block is composed of a 2056231200Smm * literal and a match, sometimes a literal only 2057231200Smm * in particular, there are no reference data at 2058231200Smm * the beginning of the decompression. 2059231200Smm */ 2060231200Smm if (!lzh_br_read_ahead_0(strm, br, 16)) { 2061231200Smm if (!last) 2062231200Smm /* We need following data. */ 2063231200Smm return (ARCHIVE_OK); 2064231200Smm if (lzh_br_has(br, 8)) { 2065231200Smm /* 2066231200Smm * It seems there are extra bits. 2067231200Smm * 1. Compressed data is broken. 2068231200Smm * 2. `last' flag does not properly 2069231200Smm * set. 2070231200Smm */ 2071231200Smm goto failed; 2072231200Smm } 2073231200Smm if (ds->w_pos > 0) { 2074231200Smm if (!lzh_copy_from_window(strm, ds)) 2075231200Smm return (ARCHIVE_OK); 2076231200Smm } 2077231200Smm /* End of compressed data; we have completely 2078231200Smm * handled all compressed data. */ 2079231200Smm return (ARCHIVE_EOF); 2080231200Smm } 2081231200Smm ds->blocks_avail = lzh_br_bits(br, 16); 2082231200Smm if (ds->blocks_avail == 0) 2083231200Smm goto failed; 2084231200Smm lzh_br_consume(br, 16); 2085231200Smm /* 2086231200Smm * Read a literal table compressed in huffman 2087231200Smm * coding. 2088231200Smm */ 2089231200Smm ds->pt.len_size = ds->literal_pt_len_size; 2090231200Smm ds->pt.len_bits = ds->literal_pt_len_bits; 2091231200Smm ds->reading_position = 0; 2092231200Smm /* FALL THROUGH */ 2093231200Smm case ST_RD_PT_1: 2094231200Smm /* Note: ST_RD_PT_1, ST_RD_PT_2 and ST_RD_PT_4 are 2095231200Smm * used in reading both a literal table and a 2096231200Smm * position table. */ 2097231200Smm if (!lzh_br_read_ahead(strm, br, ds->pt.len_bits)) { 2098231200Smm if (last) 2099231200Smm goto failed;/* Truncated data. */ 2100231200Smm ds->state = ST_RD_PT_1; 2101231200Smm return (ARCHIVE_OK); 2102231200Smm } 2103231200Smm ds->pt.len_avail = lzh_br_bits(br, ds->pt.len_bits); 2104231200Smm lzh_br_consume(br, ds->pt.len_bits); 2105231200Smm /* FALL THROUGH */ 2106231200Smm case ST_RD_PT_2: 2107231200Smm if (ds->pt.len_avail == 0) { 2108231200Smm /* There is no bitlen. */ 2109231200Smm if (!lzh_br_read_ahead(strm, br, 2110231200Smm ds->pt.len_bits)) { 2111231200Smm if (last) 2112231200Smm goto failed;/* Truncated data.*/ 2113231200Smm ds->state = ST_RD_PT_2; 2114231200Smm return (ARCHIVE_OK); 2115231200Smm } 2116231200Smm if (!lzh_make_fake_table(&(ds->pt), 2117231200Smm lzh_br_bits(br, ds->pt.len_bits))) 2118231200Smm goto failed;/* Invalid data. */ 2119231200Smm lzh_br_consume(br, ds->pt.len_bits); 2120231200Smm if (ds->reading_position) 2121231200Smm ds->state = ST_GET_LITERAL; 2122231200Smm else 2123231200Smm ds->state = ST_RD_LITERAL_1; 2124231200Smm break; 2125231200Smm } else if (ds->pt.len_avail > ds->pt.len_size) 2126231200Smm goto failed;/* Invalid data. */ 2127231200Smm ds->loop = 0; 2128231200Smm memset(ds->pt.freq, 0, sizeof(ds->pt.freq)); 2129231200Smm if (ds->pt.len_avail < 3 || 2130231200Smm ds->pt.len_size == ds->pos_pt_len_size) { 2131231200Smm ds->state = ST_RD_PT_4; 2132231200Smm break; 2133231200Smm } 2134231200Smm /* FALL THROUGH */ 2135231200Smm case ST_RD_PT_3: 2136231200Smm ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 3); 2137231200Smm if (ds->loop < 3) { 2138231200Smm if (ds->loop < 0 || last) 2139231200Smm goto failed;/* Invalid data. */ 2140231200Smm /* Not completed, get following data. */ 2141231200Smm ds->state = ST_RD_PT_3; 2142231200Smm return (ARCHIVE_OK); 2143231200Smm } 2144231200Smm /* There are some null in bitlen of the literal. */ 2145231200Smm if (!lzh_br_read_ahead(strm, br, 2)) { 2146231200Smm if (last) 2147231200Smm goto failed;/* Truncated data. */ 2148231200Smm ds->state = ST_RD_PT_3; 2149231200Smm return (ARCHIVE_OK); 2150231200Smm } 2151231200Smm c = lzh_br_bits(br, 2); 2152231200Smm lzh_br_consume(br, 2); 2153231200Smm if (c > ds->pt.len_avail - 3) 2154231200Smm goto failed;/* Invalid data. */ 2155231200Smm for (i = 3; c-- > 0 ;) 2156231200Smm ds->pt.bitlen[i++] = 0; 2157231200Smm ds->loop = i; 2158231200Smm /* FALL THROUGH */ 2159231200Smm case ST_RD_PT_4: 2160231200Smm ds->loop = lzh_read_pt_bitlen(strm, ds->loop, 2161231200Smm ds->pt.len_avail); 2162231200Smm if (ds->loop < ds->pt.len_avail) { 2163231200Smm if (ds->loop < 0 || last) 2164231200Smm goto failed;/* Invalid data. */ 2165231200Smm /* Not completed, get following data. */ 2166231200Smm ds->state = ST_RD_PT_4; 2167231200Smm return (ARCHIVE_OK); 2168231200Smm } 2169231200Smm if (!lzh_make_huffman_table(&(ds->pt))) 2170231200Smm goto failed;/* Invalid data */ 2171231200Smm if (ds->reading_position) { 2172231200Smm ds->state = ST_GET_LITERAL; 2173231200Smm break; 2174231200Smm } 2175231200Smm /* FALL THROUGH */ 2176231200Smm case ST_RD_LITERAL_1: 2177231200Smm if (!lzh_br_read_ahead(strm, br, ds->lt.len_bits)) { 2178231200Smm if (last) 2179231200Smm goto failed;/* Truncated data. */ 2180231200Smm ds->state = ST_RD_LITERAL_1; 2181231200Smm return (ARCHIVE_OK); 2182231200Smm } 2183231200Smm ds->lt.len_avail = lzh_br_bits(br, ds->lt.len_bits); 2184231200Smm lzh_br_consume(br, ds->lt.len_bits); 2185231200Smm /* FALL THROUGH */ 2186231200Smm case ST_RD_LITERAL_2: 2187231200Smm if (ds->lt.len_avail == 0) { 2188231200Smm /* There is no bitlen. */ 2189231200Smm if (!lzh_br_read_ahead(strm, br, 2190231200Smm ds->lt.len_bits)) { 2191231200Smm if (last) 2192231200Smm goto failed;/* Truncated data.*/ 2193231200Smm ds->state = ST_RD_LITERAL_2; 2194231200Smm return (ARCHIVE_OK); 2195231200Smm } 2196231200Smm if (!lzh_make_fake_table(&(ds->lt), 2197231200Smm lzh_br_bits(br, ds->lt.len_bits))) 2198231200Smm goto failed;/* Invalid data */ 2199231200Smm lzh_br_consume(br, ds->lt.len_bits); 2200231200Smm ds->state = ST_RD_POS_DATA_1; 2201231200Smm break; 2202231200Smm } else if (ds->lt.len_avail > ds->lt.len_size) 2203231200Smm goto failed;/* Invalid data */ 2204231200Smm ds->loop = 0; 2205231200Smm memset(ds->lt.freq, 0, sizeof(ds->lt.freq)); 2206231200Smm /* FALL THROUGH */ 2207231200Smm case ST_RD_LITERAL_3: 2208231200Smm i = ds->loop; 2209231200Smm while (i < ds->lt.len_avail) { 2210231200Smm if (!lzh_br_read_ahead(strm, br, 2211231200Smm ds->pt.max_bits)) { 2212231200Smm if (last) 2213231200Smm goto failed;/* Truncated data.*/ 2214231200Smm ds->loop = i; 2215231200Smm ds->state = ST_RD_LITERAL_3; 2216231200Smm return (ARCHIVE_OK); 2217231200Smm } 2218231200Smm rbits = lzh_br_bits(br, ds->pt.max_bits); 2219231200Smm c = lzh_decode_huffman(&(ds->pt), rbits); 2220231200Smm if (c > 2) { 2221231200Smm /* Note: 'c' will never be more than 2222231200Smm * eighteen since it's limited by 2223231200Smm * PT_BITLEN_SIZE, which is being set 2224231200Smm * to ds->pt.len_size through 2225231200Smm * ds->literal_pt_len_size. */ 2226231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2227231200Smm c -= 2; 2228231200Smm ds->lt.freq[c]++; 2229231200Smm ds->lt.bitlen[i++] = c; 2230231200Smm } else if (c == 0) { 2231231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2232231200Smm ds->lt.bitlen[i++] = 0; 2233231200Smm } else { 2234231200Smm /* c == 1 or c == 2 */ 2235231200Smm int n = (c == 1)?4:9; 2236231200Smm if (!lzh_br_read_ahead(strm, br, 2237231200Smm ds->pt.bitlen[c] + n)) { 2238231200Smm if (last) /* Truncated data. */ 2239231200Smm goto failed; 2240231200Smm ds->loop = i; 2241231200Smm ds->state = ST_RD_LITERAL_3; 2242231200Smm return (ARCHIVE_OK); 2243231200Smm } 2244231200Smm lzh_br_consume(br, ds->pt.bitlen[c]); 2245231200Smm c = lzh_br_bits(br, n); 2246231200Smm lzh_br_consume(br, n); 2247231200Smm c += (n == 4)?3:20; 2248231200Smm if (i + c > ds->lt.len_avail) 2249231200Smm goto failed;/* Invalid data */ 2250231200Smm memset(&(ds->lt.bitlen[i]), 0, c); 2251231200Smm i += c; 2252231200Smm } 2253231200Smm } 2254231200Smm if (i > ds->lt.len_avail || 2255231200Smm !lzh_make_huffman_table(&(ds->lt))) 2256231200Smm goto failed;/* Invalid data */ 2257231200Smm /* FALL THROUGH */ 2258231200Smm case ST_RD_POS_DATA_1: 2259231200Smm /* 2260231200Smm * Read a position table compressed in huffman 2261231200Smm * coding. 2262231200Smm */ 2263231200Smm ds->pt.len_size = ds->pos_pt_len_size; 2264231200Smm ds->pt.len_bits = ds->pos_pt_len_bits; 2265231200Smm ds->reading_position = 1; 2266231200Smm ds->state = ST_RD_PT_1; 2267231200Smm break; 2268231200Smm case ST_GET_LITERAL: 2269231200Smm return (100); 2270231200Smm } 2271231200Smm } 2272231200Smmfailed: 2273231200Smm return (ds->error = ARCHIVE_FAILED); 2274231200Smm} 2275231200Smm 2276231200Smmstatic int 2277231200Smmlzh_decode_blocks(struct lzh_stream *strm, int last) 2278231200Smm{ 2279231200Smm struct lzh_dec *ds = strm->ds; 2280231200Smm struct lzh_br bre = ds->br; 2281231200Smm struct huffman *lt = &(ds->lt); 2282231200Smm struct huffman *pt = &(ds->pt); 2283231200Smm unsigned char *w_buff = ds->w_buff; 2284231200Smm unsigned char *lt_bitlen = lt->bitlen; 2285231200Smm unsigned char *pt_bitlen = pt->bitlen; 2286231200Smm int blocks_avail = ds->blocks_avail, c = 0; 2287231200Smm int copy_len = ds->copy_len, copy_pos = ds->copy_pos; 2288231200Smm int w_pos = ds->w_pos, w_mask = ds->w_mask, w_size = ds->w_size; 2289231200Smm int lt_max_bits = lt->max_bits, pt_max_bits = pt->max_bits; 2290231200Smm int state = ds->state; 2291231200Smm 2292231200Smm if (ds->w_remaining > 0) { 2293231200Smm if (!lzh_copy_from_window(strm, ds)) 2294231200Smm goto next_data; 2295231200Smm } 2296231200Smm for (;;) { 2297231200Smm switch (state) { 2298231200Smm case ST_GET_LITERAL: 2299231200Smm for (;;) { 2300231200Smm if (blocks_avail == 0) { 2301231200Smm /* We have decoded all blocks. 2302231200Smm * Let's handle next blocks. */ 2303231200Smm ds->state = ST_RD_BLOCK; 2304231200Smm ds->br = bre; 2305231200Smm ds->blocks_avail = 0; 2306231200Smm ds->w_pos = w_pos; 2307231200Smm ds->copy_pos = 0; 2308231200Smm return (100); 2309231200Smm } 2310231200Smm 2311231200Smm /* lzh_br_read_ahead() always try to fill the 2312231200Smm * cache buffer up. In specific situation we 2313231200Smm * are close to the end of the data, the cache 2314231200Smm * buffer will not be full and thus we have to 2315231200Smm * determine if the cache buffer has some bits 2316231200Smm * as much as we need after lzh_br_read_ahead() 2317231200Smm * failed. */ 2318231200Smm if (!lzh_br_read_ahead(strm, &bre, 2319231200Smm lt_max_bits)) { 2320231200Smm if (!last) 2321231200Smm goto next_data; 2322231200Smm /* Remaining bits are less than 2323231200Smm * maximum bits(lt.max_bits) but maybe 2324231200Smm * it still remains as much as we need, 2325231200Smm * so we should try to use it with 2326231200Smm * dummy bits. */ 2327231200Smm c = lzh_decode_huffman(lt, 2328231200Smm lzh_br_bits_forced(&bre, 2329231200Smm lt_max_bits)); 2330231200Smm lzh_br_consume(&bre, lt_bitlen[c]); 2331231200Smm if (!lzh_br_has(&bre, 0)) 2332231200Smm goto failed;/* Over read. */ 2333231200Smm } else { 2334231200Smm c = lzh_decode_huffman(lt, 2335231200Smm lzh_br_bits(&bre, lt_max_bits)); 2336231200Smm lzh_br_consume(&bre, lt_bitlen[c]); 2337231200Smm } 2338231200Smm blocks_avail--; 2339231200Smm if (c > UCHAR_MAX) 2340231200Smm /* Current block is a match data. */ 2341231200Smm break; 2342231200Smm /* 2343231200Smm * 'c' is exactly a literal code. 2344231200Smm */ 2345231200Smm /* Save a decoded code to reference it 2346231200Smm * afterward. */ 2347231200Smm w_buff[w_pos] = c; 2348231200Smm if (++w_pos >= w_size) { 2349231200Smm w_pos = 0; 2350231200Smm ds->w_remaining = w_size; 2351231200Smm if (!lzh_copy_from_window(strm, ds)) 2352231200Smm goto next_data; 2353231200Smm } 2354231200Smm } 2355231200Smm /* 'c' is the length of a match pattern we have 2356231200Smm * already extracted, which has be stored in 2357231200Smm * window(ds->w_buff). */ 2358231200Smm copy_len = c - (UCHAR_MAX + 1) + MINMATCH; 2359231200Smm /* FALL THROUGH */ 2360231200Smm case ST_GET_POS_1: 2361231200Smm /* 2362231200Smm * Get a reference position. 2363231200Smm */ 2364231200Smm if (!lzh_br_read_ahead(strm, &bre, pt_max_bits)) { 2365231200Smm if (!last) { 2366231200Smm state = ST_GET_POS_1; 2367231200Smm ds->copy_len = copy_len; 2368231200Smm goto next_data; 2369231200Smm } 2370231200Smm copy_pos = lzh_decode_huffman(pt, 2371231200Smm lzh_br_bits_forced(&bre, pt_max_bits)); 2372231200Smm lzh_br_consume(&bre, pt_bitlen[copy_pos]); 2373231200Smm if (!lzh_br_has(&bre, 0)) 2374231200Smm goto failed;/* Over read. */ 2375231200Smm } else { 2376231200Smm copy_pos = lzh_decode_huffman(pt, 2377231200Smm lzh_br_bits(&bre, pt_max_bits)); 2378231200Smm lzh_br_consume(&bre, pt_bitlen[copy_pos]); 2379231200Smm } 2380231200Smm /* FALL THROUGH */ 2381231200Smm case ST_GET_POS_2: 2382231200Smm if (copy_pos > 1) { 2383231200Smm /* We need an additional adjustment number to 2384231200Smm * the position. */ 2385231200Smm int p = copy_pos - 1; 2386231200Smm if (!lzh_br_read_ahead(strm, &bre, p)) { 2387231200Smm if (last) 2388231200Smm goto failed;/* Truncated data.*/ 2389231200Smm state = ST_GET_POS_2; 2390231200Smm ds->copy_len = copy_len; 2391231200Smm ds->copy_pos = copy_pos; 2392231200Smm goto next_data; 2393231200Smm } 2394231200Smm copy_pos = (1 << p) + lzh_br_bits(&bre, p); 2395231200Smm lzh_br_consume(&bre, p); 2396231200Smm } 2397231200Smm /* The position is actually a distance from the last 2398231200Smm * code we had extracted and thus we have to convert 2399231200Smm * it to a position of the window. */ 2400231200Smm copy_pos = (w_pos - copy_pos - 1) & w_mask; 2401231200Smm /* FALL THROUGH */ 2402231200Smm case ST_COPY_DATA: 2403231200Smm /* 2404231200Smm * Copy `copy_len' bytes as extracted data from 2405231200Smm * the window into the output buffer. 2406231200Smm */ 2407231200Smm for (;;) { 2408231200Smm int l; 2409231200Smm 2410231200Smm l = copy_len; 2411231200Smm if (copy_pos > w_pos) { 2412231200Smm if (l > w_size - copy_pos) 2413231200Smm l = w_size - copy_pos; 2414231200Smm } else { 2415231200Smm if (l > w_size - w_pos) 2416231200Smm l = w_size - w_pos; 2417231200Smm } 2418231200Smm if ((copy_pos + l < w_pos) 2419231200Smm || (w_pos + l < copy_pos)) { 2420231200Smm /* No overlap. */ 2421231200Smm memcpy(w_buff + w_pos, 2422231200Smm w_buff + copy_pos, l); 2423231200Smm } else { 2424231200Smm const unsigned char *s; 2425231200Smm unsigned char *d; 2426231200Smm int li; 2427231200Smm 2428231200Smm d = w_buff + w_pos; 2429231200Smm s = w_buff + copy_pos; 2430231200Smm for (li = 0; li < l; li++) 2431231200Smm d[li] = s[li]; 2432231200Smm } 2433231200Smm w_pos = (w_pos + l) & w_mask; 2434231200Smm if (w_pos == 0) { 2435231200Smm ds->w_remaining = w_size; 2436231200Smm if (!lzh_copy_from_window(strm, ds)) { 2437231200Smm if (copy_len <= l) 2438231200Smm state = ST_GET_LITERAL; 2439231200Smm else { 2440231200Smm state = ST_COPY_DATA; 2441231200Smm ds->copy_len = 2442231200Smm copy_len - l; 2443231200Smm ds->copy_pos = 2444231200Smm (copy_pos + l) 2445231200Smm & w_mask; 2446231200Smm } 2447231200Smm goto next_data; 2448231200Smm } 2449231200Smm } 2450231200Smm if (copy_len <= l) 2451231200Smm /* A copy of current pattern ended. */ 2452231200Smm break; 2453231200Smm copy_len -= l; 2454231200Smm copy_pos = (copy_pos + l) & w_mask; 2455231200Smm } 2456231200Smm state = ST_GET_LITERAL; 2457231200Smm break; 2458231200Smm } 2459231200Smm } 2460231200Smmfailed: 2461231200Smm return (ds->error = ARCHIVE_FAILED); 2462231200Smmnext_data: 2463231200Smm ds->br = bre; 2464231200Smm ds->blocks_avail = blocks_avail; 2465231200Smm ds->state = state; 2466231200Smm ds->w_pos = w_pos; 2467231200Smm return (ARCHIVE_OK); 2468231200Smm} 2469231200Smm 2470231200Smmstatic int 2471231200Smmlzh_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits) 2472231200Smm{ 2473231200Smm int bits; 2474231200Smm 2475231200Smm if (hf->bitlen == NULL) { 2476231200Smm hf->bitlen = malloc(len_size * sizeof(hf->bitlen[0])); 2477231200Smm if (hf->bitlen == NULL) 2478231200Smm return (ARCHIVE_FATAL); 2479231200Smm } 2480231200Smm if (hf->tbl == NULL) { 2481231200Smm if (tbl_bits < HTBL_BITS) 2482231200Smm bits = tbl_bits; 2483231200Smm else 2484231200Smm bits = HTBL_BITS; 2485248616Smm hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0])); 2486231200Smm if (hf->tbl == NULL) 2487231200Smm return (ARCHIVE_FATAL); 2488231200Smm } 2489231200Smm if (hf->tree == NULL && tbl_bits > HTBL_BITS) { 2490231200Smm hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4); 2491231200Smm hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0])); 2492231200Smm if (hf->tree == NULL) 2493231200Smm return (ARCHIVE_FATAL); 2494231200Smm } 2495248616Smm hf->len_size = (int)len_size; 2496231200Smm hf->tbl_bits = tbl_bits; 2497231200Smm return (ARCHIVE_OK); 2498231200Smm} 2499231200Smm 2500231200Smmstatic void 2501231200Smmlzh_huffman_free(struct huffman *hf) 2502231200Smm{ 2503231200Smm free(hf->bitlen); 2504231200Smm free(hf->tbl); 2505231200Smm free(hf->tree); 2506231200Smm} 2507231200Smm 2508231200Smmstatic int 2509231200Smmlzh_read_pt_bitlen(struct lzh_stream *strm, int start, int end) 2510231200Smm{ 2511231200Smm struct lzh_dec *ds = strm->ds; 2512231200Smm struct lzh_br * br = &(ds->br); 2513231200Smm int c, i; 2514231200Smm 2515231200Smm for (i = start; i < end;) { 2516231200Smm /* 2517231200Smm * bit pattern the number we need 2518231200Smm * 000 -> 0 2519231200Smm * 001 -> 1 2520231200Smm * 010 -> 2 2521231200Smm * ... 2522231200Smm * 110 -> 6 2523231200Smm * 1110 -> 7 2524231200Smm * 11110 -> 8 2525231200Smm * ... 2526231200Smm * 1111111111110 -> 16 2527231200Smm */ 2528231200Smm if (!lzh_br_read_ahead(strm, br, 3)) 2529231200Smm return (i); 2530231200Smm if ((c = lzh_br_bits(br, 3)) == 7) { 2531231200Smm int d; 2532231200Smm if (!lzh_br_read_ahead(strm, br, 13)) 2533231200Smm return (i); 2534231200Smm d = lzh_br_bits(br, 13); 2535231200Smm while (d & 0x200) { 2536231200Smm c++; 2537231200Smm d <<= 1; 2538231200Smm } 2539231200Smm if (c > 16) 2540231200Smm return (-1);/* Invalid data. */ 2541231200Smm lzh_br_consume(br, c - 3); 2542231200Smm } else 2543231200Smm lzh_br_consume(br, 3); 2544231200Smm ds->pt.bitlen[i++] = c; 2545231200Smm ds->pt.freq[c]++; 2546231200Smm } 2547231200Smm return (i); 2548231200Smm} 2549231200Smm 2550231200Smmstatic int 2551231200Smmlzh_make_fake_table(struct huffman *hf, uint16_t c) 2552231200Smm{ 2553231200Smm if (c >= hf->len_size) 2554231200Smm return (0); 2555231200Smm hf->tbl[0] = c; 2556231200Smm hf->max_bits = 0; 2557231200Smm hf->shift_bits = 0; 2558231200Smm hf->bitlen[hf->tbl[0]] = 0; 2559231200Smm return (1); 2560231200Smm} 2561231200Smm 2562231200Smm/* 2563231200Smm * Make a huffman coding table. 2564231200Smm */ 2565231200Smmstatic int 2566231200Smmlzh_make_huffman_table(struct huffman *hf) 2567231200Smm{ 2568231200Smm uint16_t *tbl; 2569231200Smm const unsigned char *bitlen; 2570231200Smm int bitptn[17], weight[17]; 2571231200Smm int i, maxbits = 0, ptn, tbl_size, w; 2572231200Smm int diffbits, len_avail; 2573231200Smm 2574231200Smm /* 2575231200Smm * Initialize bit patterns. 2576231200Smm */ 2577231200Smm ptn = 0; 2578231200Smm for (i = 1, w = 1 << 15; i <= 16; i++, w >>= 1) { 2579231200Smm bitptn[i] = ptn; 2580231200Smm weight[i] = w; 2581231200Smm if (hf->freq[i]) { 2582231200Smm ptn += hf->freq[i] * w; 2583231200Smm maxbits = i; 2584231200Smm } 2585231200Smm } 2586231200Smm if (ptn != 0x10000 || maxbits > hf->tbl_bits) 2587231200Smm return (0);/* Invalid */ 2588231200Smm 2589231200Smm hf->max_bits = maxbits; 2590231200Smm 2591231200Smm /* 2592231200Smm * Cut out extra bits which we won't house in the table. 2593231200Smm * This preparation reduces the same calculation in the for-loop 2594231200Smm * making the table. 2595231200Smm */ 2596231200Smm if (maxbits < 16) { 2597231200Smm int ebits = 16 - maxbits; 2598231200Smm for (i = 1; i <= maxbits; i++) { 2599231200Smm bitptn[i] >>= ebits; 2600231200Smm weight[i] >>= ebits; 2601231200Smm } 2602231200Smm } 2603231200Smm if (maxbits > HTBL_BITS) { 2604231200Smm int htbl_max; 2605231200Smm uint16_t *p; 2606231200Smm 2607231200Smm diffbits = maxbits - HTBL_BITS; 2608231200Smm for (i = 1; i <= HTBL_BITS; i++) { 2609231200Smm bitptn[i] >>= diffbits; 2610231200Smm weight[i] >>= diffbits; 2611231200Smm } 2612231200Smm htbl_max = bitptn[HTBL_BITS] + 2613231200Smm weight[HTBL_BITS] * hf->freq[HTBL_BITS]; 2614231200Smm p = &(hf->tbl[htbl_max]); 2615231200Smm while (p < &hf->tbl[1U<<HTBL_BITS]) 2616231200Smm *p++ = 0; 2617231200Smm } else 2618231200Smm diffbits = 0; 2619231200Smm hf->shift_bits = diffbits; 2620231200Smm 2621231200Smm /* 2622231200Smm * Make the table. 2623231200Smm */ 2624231200Smm tbl_size = 1 << HTBL_BITS; 2625231200Smm tbl = hf->tbl; 2626231200Smm bitlen = hf->bitlen; 2627231200Smm len_avail = hf->len_avail; 2628231200Smm hf->tree_used = 0; 2629231200Smm for (i = 0; i < len_avail; i++) { 2630231200Smm uint16_t *p; 2631231200Smm int len, cnt; 2632231200Smm uint16_t bit; 2633231200Smm int extlen; 2634231200Smm struct htree_t *ht; 2635231200Smm 2636231200Smm if (bitlen[i] == 0) 2637231200Smm continue; 2638231200Smm /* Get a bit pattern */ 2639231200Smm len = bitlen[i]; 2640231200Smm ptn = bitptn[len]; 2641231200Smm cnt = weight[len]; 2642231200Smm if (len <= HTBL_BITS) { 2643231200Smm /* Calculate next bit pattern */ 2644231200Smm if ((bitptn[len] = ptn + cnt) > tbl_size) 2645231200Smm return (0);/* Invalid */ 2646231200Smm /* Update the table */ 2647231200Smm p = &(tbl[ptn]); 2648231200Smm while (--cnt >= 0) 2649231200Smm p[cnt] = (uint16_t)i; 2650231200Smm continue; 2651231200Smm } 2652231200Smm 2653231200Smm /* 2654231200Smm * A bit length is too big to be housed to a direct table, 2655231200Smm * so we use a tree model for its extra bits. 2656231200Smm */ 2657231200Smm bitptn[len] = ptn + cnt; 2658231200Smm bit = 1U << (diffbits -1); 2659231200Smm extlen = len - HTBL_BITS; 2660231200Smm 2661231200Smm p = &(tbl[ptn >> diffbits]); 2662231200Smm if (*p == 0) { 2663231200Smm *p = len_avail + hf->tree_used; 2664231200Smm ht = &(hf->tree[hf->tree_used++]); 2665231200Smm if (hf->tree_used > hf->tree_avail) 2666231200Smm return (0);/* Invalid */ 2667231200Smm ht->left = 0; 2668231200Smm ht->right = 0; 2669231200Smm } else { 2670231200Smm if (*p < len_avail || 2671231200Smm *p >= (len_avail + hf->tree_used)) 2672231200Smm return (0);/* Invalid */ 2673231200Smm ht = &(hf->tree[*p - len_avail]); 2674231200Smm } 2675231200Smm while (--extlen > 0) { 2676231200Smm if (ptn & bit) { 2677231200Smm if (ht->left < len_avail) { 2678231200Smm ht->left = len_avail + hf->tree_used; 2679231200Smm ht = &(hf->tree[hf->tree_used++]); 2680231200Smm if (hf->tree_used > hf->tree_avail) 2681231200Smm return (0);/* Invalid */ 2682231200Smm ht->left = 0; 2683231200Smm ht->right = 0; 2684231200Smm } else { 2685231200Smm ht = &(hf->tree[ht->left - len_avail]); 2686231200Smm } 2687231200Smm } else { 2688231200Smm if (ht->right < len_avail) { 2689231200Smm ht->right = len_avail + hf->tree_used; 2690231200Smm ht = &(hf->tree[hf->tree_used++]); 2691231200Smm if (hf->tree_used > hf->tree_avail) 2692231200Smm return (0);/* Invalid */ 2693231200Smm ht->left = 0; 2694231200Smm ht->right = 0; 2695231200Smm } else { 2696231200Smm ht = &(hf->tree[ht->right - len_avail]); 2697231200Smm } 2698231200Smm } 2699231200Smm bit >>= 1; 2700231200Smm } 2701231200Smm if (ptn & bit) { 2702231200Smm if (ht->left != 0) 2703231200Smm return (0);/* Invalid */ 2704231200Smm ht->left = (uint16_t)i; 2705231200Smm } else { 2706231200Smm if (ht->right != 0) 2707231200Smm return (0);/* Invalid */ 2708231200Smm ht->right = (uint16_t)i; 2709231200Smm } 2710231200Smm } 2711231200Smm return (1); 2712231200Smm} 2713231200Smm 2714231200Smmstatic int 2715231200Smmlzh_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c) 2716231200Smm{ 2717231200Smm struct htree_t *ht; 2718231200Smm int extlen; 2719231200Smm 2720231200Smm ht = hf->tree; 2721231200Smm extlen = hf->shift_bits; 2722231200Smm while (c >= hf->len_avail) { 2723231200Smm c -= hf->len_avail; 2724231200Smm if (extlen-- <= 0 || c >= hf->tree_used) 2725231200Smm return (0); 2726231200Smm if (rbits & (1U << extlen)) 2727231200Smm c = ht[c].left; 2728231200Smm else 2729231200Smm c = ht[c].right; 2730231200Smm } 2731231200Smm return (c); 2732231200Smm} 2733231200Smm 2734231200Smmstatic inline int 2735231200Smmlzh_decode_huffman(struct huffman *hf, unsigned rbits) 2736231200Smm{ 2737231200Smm int c; 2738231200Smm /* 2739231200Smm * At first search an index table for a bit pattern. 2740231200Smm * If it fails, search a huffman tree for. 2741231200Smm */ 2742231200Smm c = hf->tbl[rbits >> hf->shift_bits]; 2743231200Smm if (c < hf->len_avail) 2744231200Smm return (c); 2745231200Smm /* This bit pattern needs to be found out at a huffman tree. */ 2746231200Smm return (lzh_decode_huffman_tree(hf, rbits, c)); 2747231200Smm} 2748231200Smm 2749