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