1 /*  $Id: LZX.c,v 1.12 2005/06/23 14:54:41 stoecker Exp $
2     LZX file archiver client
3 
4     XAD library system for archive handling
5     Copyright (C) 1998 and later by Dirk Stöcker <soft@dstoecker.de>
6 
7     This library is free software; you can redistribute it and/or
8     modify it under the terms of the GNU Lesser General Public
9     License as published by the Free Software Foundation; either
10     version 2.1 of the License, or (at your option) any later version.
11 
12     This library is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15     Lesser General Public License for more details.
16 
17     You should have received a copy of the GNU Lesser General Public
18     License along with this library; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21 
22 /*
23     Modified for xmp by Claudio Matsuoka, 2014-01-04
24 */
25 
26 #include "common.h"
27 #include "depacker.h"
28 #include "crc32.h"
29 
30 #if 0
31 #ifndef XADMASTERVERSION
32 #define XADMASTERVERSION      10
33 #endif
34 
35 XADCLIENTVERSTR("LZX 1.10 (21.2.2004)")
36 #define LZX_VERSION             1
37 #define LZX_REVISION            10
38 /* ---------------------------------------------------------------------- */
39 #define LZXINFO_DAMAGE_PROTECT 1
40 #define LZXINFO_FLAG_LOCKED 2
41 struct LZXInfo_Header {
42     uint8 ID[3];	/* "LZX" */
43     uint8 Flags;	/* LZXINFO_FLAG_#? */
44     uint8 Unknown[6];
45 };
46 #endif
47 
48 #define LZXHDR_FLAG_MERGED      (1<<0)
49 
50 #define LZXHDR_PROT_READ        (1<<0)
51 #define LZXHDR_PROT_WRITE       (1<<1)
52 #define LZXHDR_PROT_DELETE      (1<<2)
53 #define LZXHDR_PROT_EXECUTE     (1<<3)
54 #define LZXHDR_PROT_ARCHIVE     (1<<4)
55 #define LZXHDR_PROT_HOLD        (1<<5)
56 #define LZXHDR_PROT_SCRIPT      (1<<6)
57 #define LZXHDR_PROT_PURE        (1<<7)
58 
59 #define LZXHDR_TYPE_MSDOS       0
60 #define LZXHDR_TYPE_WINDOWS     1
61 #define LZXHDR_TYPE_OS2         2
62 #define LZXHDR_TYPE_AMIGA       10
63 #define LZXHDR_TYPE_UNIX        20
64 
65 #define LZXHDR_PACK_STORE       0
66 #define LZXHDR_PACK_NORMAL      2
67 #define LZXHDR_PACK_EOF         32
68 
69 struct LZXArc_Header {
70     uint8 Attributes;	/*  0 - LZXHDR_PROT_#? */
71     uint8 pad1;		/*  1 */
72     uint8 FileSize[4];	/*  2 (little endian) */
73     uint8 CrSize[4];	/*  6 (little endian) */
74     uint8 MachineType;	/* 10 - LZXHDR_TYPE_#? */
75     uint8 PackMode;	/* 11 - LZXHDR_PACK_#? */
76     uint8 Flags;	/* 12 - LZXHDR_FLAG_#? */
77     uint8 pad2;		/* 13 */
78     uint8 CommentSize;	/* 14 - length (0-79) */
79     uint8 ExtractVersion;	/* 15 - version needed to extract */
80     uint8 pad3;		/* 16 */
81     uint8 pad4;		/* 17 */
82     uint8 Date[4];	/* 18 - Packed_Date */
83     uint8 DataCRC[4];	/* 22 (little endian) */
84     uint8 HeaderCRC[4];	/* 26 (little endian) */
85     uint8 FilenameSize;	/* 30 - filename length */
86 };				/* SIZE = 31 */
87 
88 /* Header CRC includes filename and comment. */
89 
90 #define LZXHEADERSIZE   31
91 
92 /* Packed date [4 BYTES, bit 0 is MSB, 31 is LSB]
93   bit  0 -  4   Day
94        5 -  8   Month   (January is 0)
95        9 - 14   Year    (start 1970)
96       15 - 19   Hour
97       20 - 25   Minute
98       26 - 31   Second
99 */
100 
101 struct LZXEntryData {
102     uint32 CRC;		/* CRC of uncrunched data */
103     uint32 PackMode;	/* CrunchMode */
104     uint32 ArchivePos;	/* Position is src file */
105     uint32 DataStart;	/* Position in merged buffer */
106 };
107 
108 #define LZXPE(a)	((struct LZXEntryData *) ((a)->xfi_PrivateInfo))
109 #define LZXDD(a)	((struct LZXDecrData *) ((a)->xai_PrivateClient))
110 struct LZXDecrData {
111     int mode;
112 
113     uint8 archive_header[31];
114     uint8 header_filename[256];
115     uint8 header_comment[256];
116     uint32 crc;
117     uint8 pack_mode;
118     uint32 sum;
119     FILE *outfile;
120 
121     struct filename_node *filename_list;
122 
123     uint8 *src;
124     uint8 *dest;
125     uint8 *src_end;
126     uint8 *dest_end;
127 
128     uint32 method;
129     int decrunch_length;
130     uint32 pack_size;
131     uint32 unpack_size;
132     uint32 last_offset;
133     uint32 control;
134     int shift;
135 
136     uint8 offset_len[8];
137     uint16 offset_table[128];
138     uint8 huffman20_len[20];
139     uint16 huffman20_table[96];
140     uint8 literal_len[768];
141     uint16 literal_table[5120];
142 
143     /* Was 16384, coverity scan reported overrun */
144     uint8 read_buffer[16385];	/* have a reasonable sized read buffer */
145     uint8 buffer[258 + 65536 + 258];	/* allow overrun for speed */
146 };
147 
148 /* ---------------------------------------------------------------------- */
149 #if 0
150 XADRECOGDATA(LZX)
151 {
152     if (data[0] == 'L' && data[1] == 'Z' && data[2] == 'X')
153 	return 1;
154     else
155 	return 0;
156 }
157 
158 #define XADFIBF_DELETE  (1<<0)
159 #define XADFIBF_EXECUTE (1<<1)
160 #define XADFIBF_WRITE   (1<<2)
161 #define XADFIBF_READ    (1<<3)
162 #define XADFIBF_PURE    (1<<4)
163 
164 XADGETINFO(LZX)
165 {
166     int err;
167     uint32 bufpos = 0;
168     struct xadFileInfo *fi, *fig = 0;	/* fig - first grouped ptr */
169     struct LZXArc_Header head;
170 
171     if (!
172 	(err =
173 	 xadHookAccess(XADM XADAC_INPUTSEEK, sizeof(struct LZXInfo_Header), 0,
174 		       ai))) {
175 	while (!err && ai->xai_InPos < ai->xai_InSize) {
176 	    if (!
177 		(err =
178 		 xadHookAccess(XADM XADAC_READ, LZXHEADERSIZE, &head, ai))) {
179 		uint32 i, j, k, l, crc;
180 		i = head.CommentSize;
181 		j = head.FilenameSize;
182 		k = EndGetI32(head.HeaderCRC);
183 		head.HeaderCRC[0] = head.HeaderCRC[1] = head.HeaderCRC[2] =
184 		    head.HeaderCRC[3] = 0;
185 		/* clear for CRC check */
186 
187 		if (!
188 		    (fi =
189 		     (struct xadFileInfo *)xadAllocObject(XADM XADOBJ_FILEINFO,
190 							  XAD_OBJNAMESIZE,
191 							  j + 1,
192 							  i ? XAD_OBJCOMMENTSIZE
193 							  : TAG_IGNORE, i + 1,
194 							  XAD_OBJPRIVINFOSIZE,
195 							  sizeof(struct
196 								 LZXEntryData),
197 							  TAG_DONE)))
198 		    err = XADERR_NOMEMORY;
199 		else if (!
200 			 (err =
201 			  xadHookAccess(XADM XADAC_READ, j, fi->xfi_FileName,
202 					ai)) && (!i
203 						 || !(err =
204 						      xadHookAccess(XADM
205 								    XADAC_READ,
206 								    i,
207 								    fi->
208 								    xfi_Comment,
209 								    ai)))) {
210 		    l = EndGetI32(head.CrSize);
211 
212 		    if (!l
213 			|| !(err =
214 			     xadHookAccess(XADM XADAC_INPUTSEEK, l, 0, ai))) {
215 			crc =
216 			    xadCalcCRC32(XADM XADCRC32_ID1, (uint32)~0,
217 					 LZXHEADERSIZE, (uint8 *)&head);
218 			crc =
219 			    xadCalcCRC32(XADM XADCRC32_ID1, crc, j,
220 					 (uint8 *)fi->xfi_FileName);
221 			if (i)
222 			    crc =
223 				xadCalcCRC32(XADM XADCRC32_ID1, crc, i,
224 					     (uint8 *)fi->xfi_Comment);
225 
226 			if (~crc != k)
227 			    err = XADERR_CHECKSUM;
228 			else {
229 			    if (!fig) {
230 				fig = fi;
231 				bufpos = 0;
232 			    }
233 			    fi->xfi_Size = EndGetI32(head.FileSize);
234 			    if (!l && !fi->xfi_Size
235 				&& fi->xfi_FileName[--j] == '/') {
236 				fi->xfi_FileName[j] = 0;
237 				fi->xfi_Flags |= XADFIF_DIRECTORY;
238 			    }
239 
240 			    i = head.Attributes;
241 			    j = 0;
242 
243 			    if (!(i & LZXHDR_PROT_READ))
244 				j |= XADFIBF_READ;
245 			    if (!(i & LZXHDR_PROT_WRITE))
246 				j |= XADFIBF_WRITE;
247 			    if (!(i & LZXHDR_PROT_DELETE))
248 				j |= XADFIBF_DELETE;
249 			    if (!(i & LZXHDR_PROT_EXECUTE))
250 				j |= XADFIBF_EXECUTE;
251 			    j |= (i &
252 				  (LZXHDR_PROT_ARCHIVE | LZXHDR_PROT_SCRIPT));
253 			    if (i & LZXHDR_PROT_PURE)
254 				j |= XADFIBF_PURE;
255 			    if (i & LZXHDR_PROT_HOLD)
256 				j |= (1 << 7);	/* not defined in <dos/dos.h> */
257 			    fi->xfi_Protection = j;
258 
259 			    {	/* Make the date */
260 				struct xadDate d;
261 				j = EndGetM32(head.Date);
262 				d.xd_Second = j & 63;
263 				j >>= 6;
264 				d.xd_Minute = j & 63;
265 				j >>= 6;
266 				d.xd_Hour = j & 31;
267 				j >>= 5;
268 				d.xd_Year = 1970 + (j & 63);
269 				if (d.xd_Year >= 2028)	/* Original LZX */
270 				    d.xd_Year += 2000 - 2028;
271 				else if (d.xd_Year < 1978)	/* Dr.Titus */
272 				    d.xd_Year += 2034 - 1970;
273 				/* Dates from 1978 to 1999 are correct */
274 				/* Dates from 2000 to 2027 Mikolaj patch are correct */
275 				/* Dates from 2000 to 2005 LZX/Dr.Titus patch are correct */
276 				/* Dates from 2034 to 2041 Dr.Titus patch are correct */
277 				j >>= 6;
278 				d.xd_Month = 1 + (j & 15);
279 				j >>= 4;
280 				d.xd_Day = j;
281 				d.xd_Micros = 0;
282 				xadConvertDates(XADM XAD_DATEXADDATE, &d,
283 						XAD_GETDATEXADDATE,
284 						&fi->xfi_Date, TAG_DONE);
285 			    }
286 			    LZXPE(fi)->CRC = EndGetI32(head.DataCRC);
287 			    LZXPE(fi)->DataStart = bufpos;
288 			    bufpos += fi->xfi_Size;
289 			    if (head.Flags & LZXHDR_FLAG_MERGED) {
290 				fi->xfi_Flags |= XADFIF_GROUPED;
291 				if (l) {
292 				    fi->xfi_Flags |= XADFIF_ENDOFGROUP;
293 				    fi->xfi_GroupCrSize = l;
294 				}
295 			    } else
296 				fi->xfi_CrunchSize = l;
297 
298 			    if (l) {
299 				LZXPE(fi)->ArchivePos = ai->xai_InPos - l;
300 				LZXPE(fi)->PackMode = head.PackMode;
301 				while (fig) {
302 				    fig->xfi_GroupCrSize = l;
303 				    LZXPE(fig)->ArchivePos = ai->xai_InPos - l;
304 				    LZXPE(fig)->PackMode = head.PackMode;
305 				    fig = fig->xfi_Next;
306 				}
307 			    }
308 
309 			    err = xadAddFileEntryA(XADM fi, ai, 0);
310 			    fi = 0;
311 			}	/* skip crunched data */
312 		    }		/* get filename and comment */
313 		    if (fi)
314 			xadFreeObjectA(XADM fi, 0);
315 		}		/* xadFileInfo Allocation */
316 	    }			/* READ header */
317 	}			/* while loop */
318     }
319     /* INPUTSEEK 3 bytes */
320     if (err && ai->xai_FileInfo) {
321 	ai->xai_Flags |= XADAIF_FILECORRUPT;
322 	ai->xai_LastError = err;
323 	err = 0;
324     }
325 
326     return err;
327 }
328 #endif
329 
330 struct filename_node {
331     struct filename_node *next;
332     uint32 length;
333     uint32 crc;
334     char filename[256];
335 };
336 
337 /* ---------------------------------------------------------------------- */
338 
339 static const uint8 table_one[32] = {
340     0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10,
341     11, 11, 12, 12, 13, 13, 14, 14
342 };
343 
344 static const uint32 table_two[32] = {
345     0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, 256, 384, 512,
346     768, 1024,
347     1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152
348 };
349 
350 static const uint32 table_three[16] = {
351     0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767
352 };
353 
354 static const uint8 table_four[34] = {
355     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
356     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
357 };
358 
359 /* ---------------------------------------------------------------------- */
360 
361 /* Build a fast huffman decode table from the symbol bit lengths.         */
362 /* There is an alternate algorithm which is faster but also more complex. */
363 
make_decode_table(int number_symbols,int table_size,uint8 * length,uint16 * table)364 static int make_decode_table(int number_symbols, int table_size,
365 			     uint8 *length, uint16 *table)
366 {
367     register uint8 bit_num = 0;
368     register int symbol;
369     uint32 leaf;		/* could be a register */
370     uint32 table_mask, bit_mask, pos, fill, next_symbol, reverse;
371 
372     pos = 0;			/* current position in decode table */
373 
374     bit_mask = table_mask = 1 << table_size;
375 
376     bit_mask >>= 1;		/* don't do the first number */
377     bit_num++;
378 
379     while (bit_num <= table_size) {
380 	for (symbol = 0; symbol < number_symbols; symbol++) {
381 	    if (length[symbol] == bit_num) {
382 		reverse = pos;	/* reverse the order of the position's bits */
383 		leaf = 0;
384 		fill = table_size;
385 
386 		do {		/* reverse the position */
387 		    leaf = (leaf << 1) + (reverse & 1);
388 		    reverse >>= 1;
389 		} while (--fill);
390 
391 		if ((pos += bit_mask) > table_mask)
392 		    return -1;	/* we will overrun the table! abort! */
393 
394 		fill = bit_mask;
395 		next_symbol = 1 << bit_num;
396 
397 		do {
398 		    table[leaf] = symbol;
399 		    leaf += next_symbol;
400 		} while (--fill);
401 	    }
402 	}
403 	bit_mask >>= 1;
404 	bit_num++;
405     }
406 
407     if (pos != table_mask) {
408 	for (symbol = pos; symbol < table_mask; symbol++) {	/* clear the rest of the table */
409 	    reverse = symbol;	/* reverse the order of the position's bits */
410 	    leaf = 0;
411 	    fill = table_size;
412 
413 	    do {		/* reverse the position */
414 		leaf = (leaf << 1) + (reverse & 1);
415 		reverse >>= 1;
416 	    } while (--fill);
417 
418 	    table[leaf] = 0;
419 	}
420 
421 	next_symbol = table_mask >> 1;
422 	pos <<= 16;
423 	table_mask <<= 16;
424 	bit_mask = 32768;
425 
426 	while (bit_num <= 16) {
427 	    for (symbol = 0; symbol < number_symbols; symbol++) {
428 		if (length[symbol] == bit_num) {
429 		    reverse = pos >> 16;	/* reverse the order of the position's bits */
430 		    leaf = 0;
431 		    fill = table_size;
432 
433 		    do {	/* reverse the position */
434 			leaf = (leaf << 1) + (reverse & 1);
435 			reverse >>= 1;
436 		    } while (--fill);
437 
438 		    for (fill = 0; fill < bit_num - table_size; fill++) {
439 			if (table[leaf] == 0) {
440 			    table[next_symbol << 1] = 0;
441 			    table[(next_symbol << 1) + 1] = 0;
442 			    table[leaf] = next_symbol++;
443 			}
444 			leaf = table[leaf] << 1;
445 			leaf += (pos >> (15 - fill)) & 1;
446 		    }
447 
448 		    table[leaf] = symbol;
449 		    pos += bit_mask;
450 
451 		    if (pos > table_mask)
452 			return -1;	/* we will overrun the table! abort! */
453 		}
454 	    }
455 	    bit_mask >>= 1;
456 	    bit_num++;
457 	}
458     }
459 
460     if (pos != table_mask)
461 	return -1;		/* the table is incomplete! */
462 
463     return 0;
464 }
465 
466 /* ---------------------------------------------------------------------- */
467 /* Read and build the decrunch tables. There better be enough data in the */
468 /* src buffer or it's stuffed. */
469 
read_literal_table(struct LZXDecrData * decr)470 static int read_literal_table(struct LZXDecrData *decr)
471 {
472     register uint32 control;
473     register int shift;
474     uint32 temp;		/* could be a register */
475     uint32 symbol, pos, count, fix, max_symbol;
476     uint8 *src;
477     int abort = 0;
478     int x;
479 
480     control = decr->control;
481     shift = decr->shift;
482     src = decr->src;
483 
484     if (shift < 0) {		/* fix the control word if necessary */
485 	shift += 16;
486 	control += *src++ << (8 + shift);
487 	control += *src++ << shift;
488     }
489 
490     /* read the decrunch method */
491 
492     decr->method = control & 7;
493     control >>= 3;
494     shift -= 3;
495 
496     if (shift < 0) {
497 	shift += 16;
498 	control += *src++ << (8 + shift);
499 	control += *src++ << shift;
500     }
501 
502     /* Read and build the offset huffman table */
503 
504     if (!abort && decr->method == 3) {
505 	for (temp = 0; temp < 8; temp++) {
506 	    decr->offset_len[temp] = control & 7;
507 	    control >>= 3;
508 	    if ((shift -= 3) < 0) {
509 		shift += 16;
510 		control += *src++ << (8 + shift);
511 		control += *src++ << shift;
512 	    }
513 	}
514 	abort = make_decode_table(8, 7, decr->offset_len, decr->offset_table);
515     }
516 
517     /* read decrunch length */
518 
519     if (!abort) {
520 	decr->decrunch_length = (control & 255) << 16;
521 	control >>= 8;
522 	shift -= 8;
523 
524 	if (shift < 0) {
525 	    shift += 16;
526 	    control += *src++ << (8 + shift);
527 	    control += *src++ << shift;
528 	}
529 
530 	decr->decrunch_length += (control & 255) << 8;
531 	control >>= 8;
532 	shift -= 8;
533 
534 	if (shift < 0) {
535 	    shift += 16;
536 	    control += *src++ << (8 + shift);
537 	    control += *src++ << shift;
538 	}
539 
540 	decr->decrunch_length += (control & 255);
541 	control >>= 8;
542 	shift -= 8;
543 
544 	if (shift < 0) {
545 	    shift += 16;
546 	    control += *src++ << (8 + shift);
547 	    control += *src++ << shift;
548 	}
549     }
550 
551     /* read and build the huffman literal table */
552 
553     if (!abort && decr->method != 1) {
554 	pos = 0;
555 	fix = 1;
556 	max_symbol = 256;
557 
558 	do {
559 	    for (temp = 0; temp < 20; temp++) {
560 		decr->huffman20_len[temp] = control & 15;
561 		control >>= 4;
562 		if ((shift -= 4) < 0) {
563 		    shift += 16;
564 		    control += *src++ << (8 + shift);
565 		    control += *src++ << shift;
566 		}
567 	    }
568 	    abort = make_decode_table(20, 6, decr->huffman20_len,
569 				  decr->huffman20_table);
570 
571 	    if (abort)
572 		break;		/* argh! table is corrupt! */
573 
574 	    do {
575 		if ((symbol = decr->huffman20_table[control & 63]) >= 20) {
576 		    do {	/* symbol is longer than 6 bits */
577 			symbol = decr->huffman20_table[((control >> 6) & 1) +
578 						  (symbol << 1)];
579 			if (!shift--) {
580 			    shift += 16;
581 			    control += *src++ << 24;
582 			    control += *src++ << 16;
583 			}
584 			control >>= 1;
585 		    } while (symbol >= 20);
586 		    temp = 6;
587 		} else {
588 		    temp = decr->huffman20_len[symbol];
589 		}
590 
591 		control >>= temp;
592 		if ((shift -= temp) < 0) {
593 		    shift += 16;
594 		    control += *src++ << (8 + shift);
595 		    control += *src++ << shift;
596 		}
597 
598 		switch (symbol) {
599 		case 17:
600 		case 18:
601 		    if (symbol == 17) {
602 			temp = 4;
603 			count = 3;
604 		    } else {	/* symbol == 18 */
605 			temp = 6 - fix;
606 			count = 19;
607 		    }
608 
609 		    count += (control & table_three[temp]) + fix;
610 		    control >>= temp;
611 
612 		    if ((shift -= temp) < 0) {
613 			shift += 16;
614 			control += *src++ << (8 + shift);
615 			control += *src++ << shift;
616 		    }
617 
618 		    while ((pos < max_symbol) && (count--))
619 			decr->literal_len[pos++] = 0;
620 
621 		    break;
622 		case 19:
623 		    count = (control & 1) + 3 + fix;
624 		    if (!shift--) {
625 			shift += 16;
626 			control += *src++ << 24;
627 			control += *src++ << 16;
628 		    }
629 
630 		    control >>= 1;
631 		    if ((symbol = decr->huffman20_table[control & 63]) >= 20) {
632 			do {	/* symbol is longer than 6 bits */
633 			    symbol =
634 				decr->huffman20_table[((control >> 6) & 1) +
635 						      (symbol << 1)];
636 			    if (!shift--) {
637 				shift += 16;
638 				control += *src++ << 24;
639 				control += *src++ << 16;
640 			    }
641 			    control >>= 1;
642 			} while (symbol >= 20);
643 			temp = 6;
644 		    } else {
645 			temp = decr->huffman20_len[symbol];
646 		    }
647 
648 		    control >>= temp;
649 
650 		    if ((shift -= temp) < 0) {
651 			shift += 16;
652 			control += *src++ << (8 + shift);
653 			control += *src++ << shift;
654 		    }
655 
656                     /* Sanity check */
657                     if (pos >= 768)
658                         return -1;
659 
660                     x = decr->literal_len[pos] + 17 - symbol;
661 
662                     /* Sanity check */
663                     if (x < 0 || x >= 34)
664                         return -1;
665 
666 		    symbol = table_four[x];
667 
668 		    while (pos < max_symbol && count--)
669 			decr->literal_len[pos++] = symbol;
670 
671 		    break;
672 		default:
673 		    symbol = table_four[decr->literal_len[pos] + 17 - symbol];
674 		    decr->literal_len[pos++] = symbol;
675 		    break;
676 		}
677 	    } while (pos < max_symbol);
678 
679 	    fix--;
680 	    max_symbol += 512;
681 	} while (max_symbol == 768);
682 
683 	if (!abort)
684 	    abort = make_decode_table(768, 12, decr->literal_len,
685 				  decr->literal_table);
686     }
687 
688     decr->control = control;
689     decr->shift = shift;
690     decr->src = src;
691 
692     return abort;
693 }
694 
695 /* ---------------------------------------------------------------------- */
696 
697 /* Fill up the decrunch buffer. Needs lots of overrun for both decr->dest */
698 /* and src buffers. Most of the time is spent in this routine so it's  */
699 /* pretty damn optimized. */
700 
decrunch(struct LZXDecrData * decr)701 static void decrunch(struct LZXDecrData *decr)
702 {
703     register uint32 control;
704     register int shift;
705     uint32 temp;		/* could be a register */
706     uint32 symbol, count;
707     uint8 *string, *src, *dest;
708 
709     control = decr->control;
710     shift = decr->shift;
711     src = decr->src;
712     dest = decr->dest;
713 
714     do {
715 	if ((symbol = decr->literal_table[control & 4095]) >= 768) {
716 	    control >>= 12;
717 
718 	    if ((shift -= 12) < 0) {
719 		shift += 16;
720 		control += *src++ << (8 + shift);
721 		control += *src++ << shift;
722 	    }
723 	    do {		/* literal is longer than 12 bits */
724 		symbol = decr->literal_table[(control & 1) + (symbol << 1)];
725 		if (!shift--) {
726 		    shift += 16;
727 		    control += *src++ << 24;
728 		    control += *src++ << 16;
729 		}
730 		control >>= 1;
731 	    } while (symbol >= 768);
732 	} else {
733 	    temp = decr->literal_len[symbol];
734 	    control >>= temp;
735 
736 	    if ((shift -= temp) < 0) {
737 		shift += 16;
738 		control += *src++ << (8 + shift);
739 		control += *src++ << shift;
740 	    }
741 	}
742 
743 	if (symbol < 256) {
744 	    *dest++ = symbol;
745 	} else {
746 	    symbol -= 256;
747 	    count = table_two[temp = symbol & 31];
748 	    temp = table_one[temp];
749 
750 	    if ((temp >= 3) && (decr->method == 3)) {
751 		temp -= 3;
752 		count += ((control & table_three[temp]) << 3);
753 		control >>= temp;
754 		if ((shift -= temp) < 0) {
755 		    shift += 16;
756 		    control += *src++ << (8 + shift);
757 		    control += *src++ << shift;
758 		}
759 		count += (temp = decr->offset_table[control & 127]);
760 		temp = decr->offset_len[temp];
761 	    } else {
762 		count += control & table_three[temp];
763 		if (!count)
764 		    count = decr->last_offset;
765 	    }
766 
767 	    control >>= temp;
768 
769 	    if ((shift -= temp) < 0) {
770 		shift += 16;
771 		control += *src++ << (8 + shift);
772 		control += *src++ << shift;
773 	    }
774 
775 	    decr->last_offset = count;
776 
777 	    count = table_two[temp = (symbol >> 5) & 15] + 3;
778 	    temp = table_one[temp];
779 	    count += (control & table_three[temp]);
780 	    control >>= temp;
781 
782 	    shift -= temp;
783 	    if (shift < 0) {
784 		shift += 16;
785 		control += *src++ << (8 + shift);
786 		control += *src++ << shift;
787 	    }
788 
789 	    string = (decr->buffer + decr->last_offset < dest) ?
790 			dest - decr->last_offset :
791 			dest + 65536 - decr->last_offset;
792 
793 	    do {
794 		*dest++ = *string++;
795 	    } while (--count);
796 	}
797     } while (dest < decr->dest_end && src < decr->src_end);
798 
799     decr->control = control;
800     decr->shift = shift;
801     decr->src = src;
802     decr->dest = dest;
803 }
804 
805 /* ---------------------------------------------------------------------- */
806 
807 /* Trying to understand this function is hazardous. */
808 
extract_normal(FILE * in_file,struct LZXDecrData * decr)809 static int extract_normal(FILE * in_file, struct LZXDecrData *decr)
810 {
811     struct filename_node *node;
812     FILE *out_file = 0;
813     uint8 *pos;
814     uint8 *temp;
815     uint32 count;
816     int abort = 0;
817 
818     decr->control = 0;	/* initial control word */
819     decr->shift = -16;
820     decr->last_offset = 1;
821     decr->unpack_size = 0;
822     decr->decrunch_length = 0;
823 
824     memset(decr->offset_len, 0, 8);
825     memset(decr->literal_len, 0, 768);
826 
827     decr->src = decr->read_buffer + 16384;
828     decr->src_end = decr->src - 1024;
829     pos = decr->dest_end = decr->dest = decr->buffer + 258 + 65536;
830 
831     for (node = decr->filename_list; (!abort) && node; node = node->next) {
832 	/*printf("Extracting \"%s\"...", node->filename);
833 	   fflush(stdout); */
834 
835 	if (libxmp_exclude_match(node->filename)) {
836 	    out_file = NULL;
837 	} else {
838 	    out_file = decr->outfile;
839 	}
840 
841 	decr->sum = 0;		/* reset CRC */
842 	decr->unpack_size = node->length;
843 
844 	while (decr->unpack_size > 0) {
845 
846 	    if (pos == decr->dest) {	/* time to fill the buffer? */
847 /* check if we have enough data and read some if not */
848 		if (decr->src >= decr->src_end) {	/* have we exhausted the current read buffer? */
849 		    temp = decr->read_buffer;
850 		    count = temp - decr->src + 16384;
851 		    if (count) {
852 			do {	/* copy the remaining overrun to the start of the buffer */
853 			    *temp++ = *decr->src++;
854 			} while (--count);
855 		    }
856 		    decr->src = decr->read_buffer;
857 		    count = decr->src - temp + 16384;
858 
859 		    if (decr->pack_size < count)
860 			count = decr->pack_size;	/* make sure we don't read too much */
861 
862 		    if (fread(temp, 1, count, in_file) != count) {
863 			/* printf("\n");
864 			if (ferror(in_file))
865 			    perror("FRead(Data)");
866 			else
867 			    fprintf(stderr, "EOF: Data\n"); */
868 			abort = 1;
869 			break;	/* fatal error */
870 		    }
871 		    decr->pack_size -= count;
872 
873 		    temp += count;
874 		    if (decr->src >= temp)
875 			break;	/* argh! no more data! */
876 		}
877 
878 		/* if(src >= decr->src_end) */
879 		/* check if we need to read the tables */
880 		if (decr->decrunch_length <= 0) {
881 		    if (read_literal_table(decr))
882 			break;	/* argh! can't make huffman tables! */
883 		}
884 
885                 /* unpack some data */
886 		if (decr->dest >= decr->buffer + 258 + 65536) {
887 		    count = decr->dest - decr->buffer - 65536;
888 		    if (count) {
889 			temp = (decr->dest =
890 				decr->buffer) + 65536;
891 			do {	/* copy the overrun to the start of the buffer */
892 			    *decr->dest++ = *temp++;
893 			} while (--count);
894 		    }
895 		    pos = decr->dest;
896 		}
897 		decr->dest_end = decr->dest + decr->decrunch_length;
898 		if (decr->dest_end > decr->buffer + 258 + 65536)
899 		    decr->dest_end = decr->buffer + 258 + 65536;
900 		temp = decr->dest;
901 
902 		decrunch(decr);
903 
904 		decr->decrunch_length -= (decr->dest - temp);
905 	    }
906 
907             /* calculate amount of data we can use before we need to
908              * fill the buffer again
909              */
910 	    count = decr->dest - pos;
911 	    if (count > decr->unpack_size)
912 		count = decr->unpack_size;	/* take only what we need */
913 
914 	    decr->sum = libxmp_crc32_A1(pos, count, decr->sum);
915 
916 	    if (out_file) {	/* Write the data to the file */
917 		abort = 1;
918 		if (fwrite(pos, 1, count, out_file) != count) {
919 #if 0
920 		    perror("FWrite");	/* argh! write error */
921 		    fclose(out_file);
922 		    out_file = 0;
923 #endif
924 		}
925 	    }
926 	    decr->unpack_size -= count;
927 	    pos += count;
928 	}
929 
930 #if 0
931 	if (out_file) {
932 	    fclose(out_file);
933 	    if (!abort)
934 		printf(" crc %s\n", (node->crc == sum) ? "good" : "bad");
935 	}
936 #endif
937     }				/* for */
938 
939     return (abort);
940 }
941 
942 /* ---------------------------------------------------------------------- */
943 
extract_archive(FILE * in_file,struct LZXDecrData * decr)944 static int extract_archive(FILE * in_file, struct LZXDecrData *decr)
945 {
946     uint32 temp;
947     struct filename_node **filename_next;
948     struct filename_node *node;
949     struct filename_node *temp_node;
950     int actual;
951     int abort;
952     int result = 1;		/* assume an error */
953 
954     decr->filename_list = 0;	/* clear the list */
955     filename_next = &decr->filename_list;
956 
957     do {
958 	abort = 1;		/* assume an error */
959 	actual = fread(decr->archive_header, 1, 31, in_file);
960 	if (ferror(in_file)) {
961 	    /* perror("FRead(Archive_Header)"); */
962 	    continue;
963 	}
964 
965 	if (actual == 0) {	/* 0 is normal and means EOF */
966 	    result = 0;		/* normal termination */
967 	    continue;
968 	}
969 
970 	if (actual != 31) {
971 	    /* fprintf(stderr, "EOF: Archive_Header\n"); */
972 	    continue;
973 	}
974 
975 	decr->sum = 0;		/* reset CRC */
976 	decr->crc = readmem32l(decr->archive_header + 26);
977 
978 	/* Must set the field to 0 before calculating the crc */
979 	memset(decr->archive_header + 26, 0, 4);
980 	decr->sum = libxmp_crc32_A1(decr->archive_header, 31, decr->sum);
981 	temp = decr->archive_header[30];	/* filename length */
982 	actual = fread(decr->header_filename, 1, temp, in_file);
983 
984 	if (ferror(in_file)) {
985 	    /* perror("FRead(Header_Filename)"); */
986 	    continue;
987 	}
988 
989 	if (actual != temp) {
990 	    /* fprintf(stderr, "EOF: Header_Filename\n"); */
991 	    continue;
992 	}
993 
994 	decr->header_filename[temp] = 0;
995 	decr->sum = libxmp_crc32_A1(decr->header_filename, temp, decr->sum);
996 	temp = decr->archive_header[14];	/* comment length */
997 	actual = fread(decr->header_comment, 1, temp, in_file);
998 
999 	if (ferror(in_file)) {
1000 	    /* perror("FRead(Header_Comment)"); */
1001 	    continue;
1002 	}
1003 
1004 	if (actual != temp) {
1005 	    /* fprintf(stderr, "EOF: Header_Comment\n"); */
1006 	    continue;
1007 	}
1008 
1009 	decr->header_comment[temp] = 0;
1010 	decr->sum = libxmp_crc32_A1(decr->header_comment, temp, decr->sum);
1011 
1012 	if (decr->sum != decr->crc) {
1013 	    /* fprintf(stderr, "CRC: Archive_Header\n"); */
1014 	    continue;
1015 	}
1016 
1017 	decr->unpack_size = readmem32l(decr->archive_header + 2);
1018 	decr->pack_size = readmem32l(decr->archive_header + 6);
1019 	decr->pack_mode = decr->archive_header[11];
1020 	decr->crc = readmem32l(decr->archive_header + 22);
1021 
1022 	/* allocate a filename node */
1023 	node = malloc(sizeof(struct filename_node));
1024 	if (node == NULL) {
1025 	    /* fprintf(stderr, "MAlloc(Filename_node)\n"); */
1026 	    continue;
1027 	}
1028 
1029 	*filename_next = node;	/* add this node to the list */
1030 	filename_next = &(node->next);
1031 	node->next = 0;
1032 	node->length = decr->unpack_size;
1033 	node->crc = decr->crc;
1034 	for (temp = 0; ; temp++) {
1035 	    if (!(node->filename[temp] = decr->header_filename[temp]))
1036 		break;
1037 	}
1038 
1039 #if 0
1040 	if (decr->pack_size == 0) {
1041 	    abort = 0;		/* continue */
1042 	    continue;
1043 	}
1044 #endif
1045 
1046 	switch (decr->pack_mode) {
1047 #if 0
1048 	case 0:			/* store */
1049 	    /*abort =*/ extract_store(in_file, decr);
1050 	    abort = 1;		/* for xmp */
1051 	    break;
1052 #endif
1053 	case 2:			/* normal */
1054 	    /*abort =*/ extract_normal(in_file, decr);
1055 	    abort = 1;		/* for xmp */
1056 	    break;
1057 	default:		/* unknown */
1058 	    break;
1059 	}
1060 
1061 #if 0
1062 	if (abort)
1063 	    break;		/* a read error occured */
1064 
1065 	/* CID 129002 (#1 of 1): Logically dead code (DEADCODE)
1066 	 * dead_error_begin: Execution cannot reach this statement:
1067 	 */
1068 	temp_node = decr->filename_list;	/* free the list now */
1069 	while ((node = temp_node)) {
1070 	    temp_node = node->next;
1071 	    free(node);
1072 	}
1073 	decr->filename_list = 0;	/* clear the list */
1074 	filename_next = &decr->filename_list;
1075 
1076 	if (fseek(in_file, decr->pack_size, SEEK_CUR)) {
1077 	    /* perror("FSeek(Data)"); */
1078 	    break;
1079 	}
1080 #endif
1081 
1082     } while (!abort);
1083 
1084     /* free the filename list in case an error occured */
1085     temp_node = decr->filename_list;
1086     while ((node = temp_node) != NULL) {
1087 	temp_node = node->next;
1088 	free(node);
1089     }
1090 
1091     return result;
1092 }
1093 
test_lzx(unsigned char * b)1094 static int test_lzx(unsigned char *b)
1095 {
1096 	return memcmp(b, "LZX", 3) == 0;
1097 }
1098 
decrunch_lzx(FILE * f,FILE * fo)1099 static int decrunch_lzx(FILE *f, FILE *fo)
1100 {
1101 	struct LZXDecrData *decr;
1102 
1103 	if (fo == NULL)
1104 		goto err;
1105 
1106 	decr = calloc(1, sizeof(struct LZXDecrData));
1107 	if (decr == NULL)
1108 		goto err;
1109 
1110 	if (fseek(f, 10, SEEK_CUR) < 0)		/* skip header */
1111 		goto err2;
1112 
1113 	libxmp_crc32_init_A();
1114 	decr->outfile = fo;
1115 	extract_archive(f, decr);
1116 
1117 	free(decr);
1118 
1119 	return 0;
1120 
1121     err2:
1122 	free(decr);
1123     err:
1124 	return -1;
1125 }
1126 
1127 struct depacker libxmp_depacker_lzx = {
1128 	test_lzx,
1129 	decrunch_lzx
1130 };
1131