git-svn-id: file:///var/lib/svn/clamav-devel/tags/clamav-0.74@2763 77e5149b-7576-45b1-b177-96237e5ba77b
Sven Strickroth authored on 2007/02/18 22:46:10... | ... |
@@ -17,7 +17,7 @@ dnl Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
17 | 17 |
|
18 | 18 |
AC_INIT(clamscan/clamscan.c) |
19 | 19 |
AC_CREATE_TARGET_H(target.h) |
20 |
-AM_INIT_AUTOMAKE(clamav, "devel-`date +%Y%m%d`") |
|
20 |
+AM_INIT_AUTOMAKE(clamav, "0.74") |
|
21 | 21 |
AM_CONFIG_HEADER(clamav-config.h) |
22 | 22 |
|
23 | 23 |
LC_CURRENT=1 |
24 | 24 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,75 @@ |
0 |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> |
|
1 |
+ |
|
2 |
+<!--Converted with LaTeX2HTML 2K.1beta (1.48) |
|
3 |
+original version by: Nikos Drakos, CBLU, University of Leeds |
|
4 |
+* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan |
|
5 |
+* with significant contributions from: |
|
6 |
+ Jens Lippmann, Marek Rouchal, Martin Wilck and others --> |
|
7 |
+<HTML> |
|
8 |
+<HEAD> |
|
9 |
+<TITLE>Core developers</TITLE> |
|
10 |
+<META NAME="description" CONTENT="Core developers"> |
|
11 |
+<META NAME="keywords" CONTENT="clamdoc"> |
|
12 |
+<META NAME="resource-type" CONTENT="document"> |
|
13 |
+<META NAME="distribution" CONTENT="global"> |
|
14 |
+ |
|
15 |
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
|
16 |
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta"> |
|
17 |
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"> |
|
18 |
+ |
|
19 |
+<LINK REL="STYLESHEET" HREF="clamdoc.css"> |
|
20 |
+ |
|
21 |
+<LINK REL="previous" HREF="node85.html"> |
|
22 |
+<LINK REL="up" HREF="node82.html"> |
|
23 |
+<LINK REL="next" HREF="node87.html"> |
|
24 |
+</HEAD> |
|
25 |
+ |
|
26 |
+<BODY > |
|
27 |
+<!--Navigation Panel--> |
|
28 |
+<A NAME="tex2html1433" |
|
29 |
+ HREF="node87.html"> |
|
30 |
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next" |
|
31 |
+ SRC="/usr/share/latex2html/icons/next.png"></A> |
|
32 |
+<A NAME="tex2html1429" |
|
33 |
+ HREF="node82.html"> |
|
34 |
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up" |
|
35 |
+ SRC="/usr/share/latex2html/icons/up.png"></A> |
|
36 |
+<A NAME="tex2html1425" |
|
37 |
+ HREF="node85.html"> |
|
38 |
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous" |
|
39 |
+ SRC="/usr/share/latex2html/icons/prev.png"></A> |
|
40 |
+<A NAME="tex2html1431" |
|
41 |
+ HREF="node1.html"> |
|
42 |
+<IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents" |
|
43 |
+ SRC="/usr/share/latex2html/icons/contents.png"></A> |
|
44 |
+<BR> |
|
45 |
+<B> Next:</B> <A NAME="tex2html1434" |
|
46 |
+ HREF="node87.html">Bibliography</A> |
|
47 |
+<B> Up:</B> <A NAME="tex2html1430" |
|
48 |
+ HREF="node82.html">Authors</A> |
|
49 |
+<B> Previous:</B> <A NAME="tex2html1426" |
|
50 |
+ HREF="node85.html">Graphics</A> |
|
51 |
+   <B> <A NAME="tex2html1432" |
|
52 |
+ HREF="node1.html">Contents</A></B> |
|
53 |
+<BR> |
|
54 |
+<BR> |
|
55 |
+<!--End of Navigation Panel--> |
|
56 |
+ |
|
57 |
+<H2><A NAME="SECTION00094000000000000000"> |
|
58 |
+Core developers</A> |
|
59 |
+</H2> |
|
60 |
+ Nigel Horne <njh*clamav.net> is a very active ClamAV developer |
|
61 |
+ responsible for the mbox code and clamav-milter. Trog |
|
62 |
+ <trog*clamav.net> developes the OLE2 code and the new thread |
|
63 |
+ manager in clamd. Thomas Lamy is a great memory leak killer and code |
|
64 |
+ stabilizer. Tomasz Kojm <tkojm*clamav.net> navigates the project |
|
65 |
+ and keeps an eye on everything <code>8-)</code> |
|
66 |
+ |
|
67 |
+<P> |
|
68 |
+<BR><HR> |
|
69 |
+<ADDRESS> |
|
70 |
+Tomasz Kojm |
|
71 |
+2004-06-29 |
|
72 |
+</ADDRESS> |
|
73 |
+</BODY> |
|
74 |
+</HTML> |
0 | 75 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,75 @@ |
0 |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> |
|
1 |
+ |
|
2 |
+<!--Converted with LaTeX2HTML 2K.1beta (1.48) |
|
3 |
+original version by: Nikos Drakos, CBLU, University of Leeds |
|
4 |
+* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan |
|
5 |
+* with significant contributions from: |
|
6 |
+ Jens Lippmann, Marek Rouchal, Martin Wilck and others --> |
|
7 |
+<HTML> |
|
8 |
+<HEAD> |
|
9 |
+<TITLE>Bibliography</TITLE> |
|
10 |
+<META NAME="description" CONTENT="Bibliography"> |
|
11 |
+<META NAME="keywords" CONTENT="clamdoc"> |
|
12 |
+<META NAME="resource-type" CONTENT="document"> |
|
13 |
+<META NAME="distribution" CONTENT="global"> |
|
14 |
+ |
|
15 |
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
|
16 |
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta"> |
|
17 |
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"> |
|
18 |
+ |
|
19 |
+<LINK REL="STYLESHEET" HREF="clamdoc.css"> |
|
20 |
+ |
|
21 |
+<LINK REL="next" HREF="node88.html"> |
|
22 |
+<LINK REL="previous" HREF="node82.html"> |
|
23 |
+<LINK REL="up" HREF="clamdoc.html"> |
|
24 |
+<LINK REL="next" HREF="node88.html"> |
|
25 |
+</HEAD> |
|
26 |
+ |
|
27 |
+<BODY > |
|
28 |
+<!--Navigation Panel--> |
|
29 |
+<A NAME="tex2html1445" |
|
30 |
+ HREF="node88.html"> |
|
31 |
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next" |
|
32 |
+ SRC="/usr/share/latex2html/icons/next.png"></A> |
|
33 |
+<A NAME="tex2html1441" |
|
34 |
+ HREF="clamdoc.html"> |
|
35 |
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up" |
|
36 |
+ SRC="/usr/share/latex2html/icons/up.png"></A> |
|
37 |
+<A NAME="tex2html1435" |
|
38 |
+ HREF="node86.html"> |
|
39 |
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous" |
|
40 |
+ SRC="/usr/share/latex2html/icons/prev.png"></A> |
|
41 |
+<A NAME="tex2html1443" |
|
42 |
+ HREF="node1.html"> |
|
43 |
+<IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents" |
|
44 |
+ SRC="/usr/share/latex2html/icons/contents.png"></A> |
|
45 |
+<BR> |
|
46 |
+<B> Next:</B> <A NAME="tex2html1446" |
|
47 |
+ HREF="node88.html">About this document ...</A> |
|
48 |
+<B> Up:</B> <A NAME="tex2html1442" |
|
49 |
+ HREF="clamdoc.html">clamdoc</A> |
|
50 |
+<B> Previous:</B> <A NAME="tex2html1436" |
|
51 |
+ HREF="node86.html">Core developers</A> |
|
52 |
+   <B> <A NAME="tex2html1444" |
|
53 |
+ HREF="node1.html">Contents</A></B> |
|
54 |
+<BR><BR> |
|
55 |
+<!--End of Navigation Panel--> |
|
56 |
+ |
|
57 |
+<H2><A NAME="SECTION000100000000000000000"> |
|
58 |
+Bibliography</A> |
|
59 |
+</H2><DL COMPACT><DD><P></P><DT><A NAME="clr">1</A> |
|
60 |
+<DD> |
|
61 |
+ Cormen, Leiserson, Rivest: <I>Introduction to Algorithms</I>, |
|
62 |
+ Chapter 34, MIT Press. |
|
63 |
+ <P></P><DT><A NAME="acwww">2</A> |
|
64 |
+<DD> |
|
65 |
+ <FONT SIZE="-1"> <TT><A NAME="tex2html163" |
|
66 |
+ HREF="http://www-sr.informatik.uni-tuebingen.de/~buehler/AC/AC.html">http://www-sr.informatik.uni-tuebingen.de/~buehler/AC/AC.html</A></TT></FONT>: |
|
67 |
+<BR> Aho-Corasick algorithm description |
|
68 |
+</DL><BR><HR> |
|
69 |
+<ADDRESS> |
|
70 |
+Tomasz Kojm |
|
71 |
+2004-06-29 |
|
72 |
+</ADDRESS> |
|
73 |
+</BODY> |
|
74 |
+</HTML> |
0 | 75 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,79 @@ |
0 |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> |
|
1 |
+ |
|
2 |
+<!--Converted with LaTeX2HTML 2K.1beta (1.48) |
|
3 |
+original version by: Nikos Drakos, CBLU, University of Leeds |
|
4 |
+* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan |
|
5 |
+* with significant contributions from: |
|
6 |
+ Jens Lippmann, Marek Rouchal, Martin Wilck and others --> |
|
7 |
+<HTML> |
|
8 |
+<HEAD> |
|
9 |
+<TITLE>About this document ...</TITLE> |
|
10 |
+<META NAME="description" CONTENT="About this document ..."> |
|
11 |
+<META NAME="keywords" CONTENT="clamdoc"> |
|
12 |
+<META NAME="resource-type" CONTENT="document"> |
|
13 |
+<META NAME="distribution" CONTENT="global"> |
|
14 |
+ |
|
15 |
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
|
16 |
+<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta"> |
|
17 |
+<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css"> |
|
18 |
+ |
|
19 |
+<LINK REL="STYLESHEET" HREF="clamdoc.css"> |
|
20 |
+ |
|
21 |
+<LINK REL="previous" HREF="node87.html"> |
|
22 |
+<LINK REL="up" HREF="clamdoc.html"> |
|
23 |
+</HEAD> |
|
24 |
+ |
|
25 |
+<BODY > |
|
26 |
+<!--Navigation Panel--> |
|
27 |
+<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next" |
|
28 |
+ SRC="/usr/share/latex2html/icons/next_g.png"> |
|
29 |
+<A NAME="tex2html1451" |
|
30 |
+ HREF="clamdoc.html"> |
|
31 |
+<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up" |
|
32 |
+ SRC="/usr/share/latex2html/icons/up.png"></A> |
|
33 |
+<A NAME="tex2html1447" |
|
34 |
+ HREF="node87.html"> |
|
35 |
+<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous" |
|
36 |
+ SRC="/usr/share/latex2html/icons/prev.png"></A> |
|
37 |
+<A NAME="tex2html1453" |
|
38 |
+ HREF="node1.html"> |
|
39 |
+<IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents" |
|
40 |
+ SRC="/usr/share/latex2html/icons/contents.png"></A> |
|
41 |
+<BR> |
|
42 |
+<B> Up:</B> <A NAME="tex2html1452" |
|
43 |
+ HREF="clamdoc.html">clamdoc</A> |
|
44 |
+<B> Previous:</B> <A NAME="tex2html1448" |
|
45 |
+ HREF="node87.html">Bibliography</A> |
|
46 |
+   <B> <A NAME="tex2html1454" |
|
47 |
+ HREF="node1.html">Contents</A></B> |
|
48 |
+<BR> |
|
49 |
+<BR> |
|
50 |
+<!--End of Navigation Panel--> |
|
51 |
+ |
|
52 |
+<H1><A NAME="SECTION000110000000000000000"> |
|
53 |
+About this document ...</A> |
|
54 |
+</H1> |
|
55 |
+ <P> |
|
56 |
+This document was generated using the |
|
57 |
+<A HREF="http://www-texdev.mpce.mq.edu.au/l2h/docs/manual/"><STRONG>LaTeX</STRONG>2<tt>HTML</tt></A> translator Version 2K.1beta (1.48) |
|
58 |
+<P> |
|
59 |
+Copyright © 1993, 1994, 1995, 1996, |
|
60 |
+<A HREF="http://cbl.leeds.ac.uk/nikos/personal.html">Nikos Drakos</A>, |
|
61 |
+Computer Based Learning Unit, University of Leeds. |
|
62 |
+<BR> |
|
63 |
+Copyright © 1997, 1998, 1999, |
|
64 |
+<A HREF="http://www.maths.mq.edu.au/~ross/">Ross Moore</A>, |
|
65 |
+Mathematics Department, Macquarie University, Sydney. |
|
66 |
+<P> |
|
67 |
+The command line arguments were: <BR> |
|
68 |
+ <STRONG>latex2html</STRONG> <TT><A NAME="tex2html164" |
|
69 |
+ HREF="../clamdoc.tex">clamdoc.tex</A></TT> |
|
70 |
+<P> |
|
71 |
+The translation was initiated by Tomasz Kojm on 2004-06-29 |
|
72 |
+<BR><HR> |
|
73 |
+<ADDRESS> |
|
74 |
+Tomasz Kojm |
|
75 |
+2004-06-29 |
|
76 |
+</ADDRESS> |
|
77 |
+</BODY> |
|
78 |
+</HTML> |
... | ... |
@@ -80,21 +80,6 @@ libclamav_la_SOURCES = \ |
80 | 80 |
vba_extract.h \ |
81 | 81 |
cltypes.h \ |
82 | 82 |
msexpand.c \ |
83 |
- msexpand.h \ |
|
84 |
- pe.c \ |
|
85 |
- pe.h \ |
|
86 |
- mspack/cabd.c \ |
|
87 |
- mspack/cab.h \ |
|
88 |
- mspack/lzxd.c \ |
|
89 |
- mspack/lzx.h \ |
|
90 |
- mspack/mspack.h \ |
|
91 |
- mspack/mszipd.c \ |
|
92 |
- mspack/mszip.h \ |
|
93 |
- mspack/qtmd.c \ |
|
94 |
- mspack/qtm.h \ |
|
95 |
- mspack/system.c \ |
|
96 |
- mspack/system.h \ |
|
97 |
- upx.c \ |
|
98 |
- upx.h |
|
83 |
+ msexpand.h |
|
99 | 84 |
|
100 | 85 |
lib_LTLIBRARIES = libclamav.la |
... | ... |
@@ -76,26 +76,21 @@ am_libclamav_la_OBJECTS = matcher.lo md5.lo others.lo readdb.lo cvd.lo \ |
76 | 76 |
dsig.lo str.lo scanners.lo unrarlib.lo zzip-dir.lo zzip-err.lo \ |
77 | 77 |
zzip-file.lo zzip-info.lo zzip-io.lo zzip-stat.lo zzip-zip.lo \ |
78 | 78 |
strc.lo blob.lo mbox.lo message.lo snprintf.lo strrcpy.lo \ |
79 |
- table.lo text.lo ole2_extract.lo vba_extract.lo msexpand.lo \ |
|
80 |
- pe.lo cabd.lo lzxd.lo mszipd.lo qtmd.lo system.lo upx.lo |
|
79 |
+ table.lo text.lo ole2_extract.lo vba_extract.lo msexpand.lo |
|
81 | 80 |
libclamav_la_OBJECTS = $(am_libclamav_la_OBJECTS) |
82 | 81 |
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) |
83 | 82 |
depcomp = $(SHELL) $(top_srcdir)/depcomp |
84 | 83 |
am__depfiles_maybe = depfiles |
85 |
-@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/blob.Plo ./$(DEPDIR)/cabd.Plo \ |
|
86 |
-@AMDEP_TRUE@ ./$(DEPDIR)/cvd.Plo ./$(DEPDIR)/dsig.Plo \ |
|
87 |
-@AMDEP_TRUE@ ./$(DEPDIR)/lzxd.Plo ./$(DEPDIR)/matcher.Plo \ |
|
84 |
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/blob.Plo ./$(DEPDIR)/cvd.Plo \ |
|
85 |
+@AMDEP_TRUE@ ./$(DEPDIR)/dsig.Plo ./$(DEPDIR)/matcher.Plo \ |
|
88 | 86 |
@AMDEP_TRUE@ ./$(DEPDIR)/mbox.Plo ./$(DEPDIR)/md5.Plo \ |
89 | 87 |
@AMDEP_TRUE@ ./$(DEPDIR)/message.Plo ./$(DEPDIR)/msexpand.Plo \ |
90 |
-@AMDEP_TRUE@ ./$(DEPDIR)/mszipd.Plo \ |
|
91 | 88 |
@AMDEP_TRUE@ ./$(DEPDIR)/ole2_extract.Plo \ |
92 |
-@AMDEP_TRUE@ ./$(DEPDIR)/others.Plo ./$(DEPDIR)/pe.Plo \ |
|
93 |
-@AMDEP_TRUE@ ./$(DEPDIR)/qtmd.Plo ./$(DEPDIR)/readdb.Plo \ |
|
89 |
+@AMDEP_TRUE@ ./$(DEPDIR)/others.Plo ./$(DEPDIR)/readdb.Plo \ |
|
94 | 90 |
@AMDEP_TRUE@ ./$(DEPDIR)/scanners.Plo ./$(DEPDIR)/snprintf.Plo \ |
95 | 91 |
@AMDEP_TRUE@ ./$(DEPDIR)/str.Plo ./$(DEPDIR)/strc.Plo \ |
96 |
-@AMDEP_TRUE@ ./$(DEPDIR)/strrcpy.Plo ./$(DEPDIR)/system.Plo \ |
|
97 |
-@AMDEP_TRUE@ ./$(DEPDIR)/table.Plo ./$(DEPDIR)/text.Plo \ |
|
98 |
-@AMDEP_TRUE@ ./$(DEPDIR)/unrarlib.Plo ./$(DEPDIR)/upx.Plo \ |
|
92 |
+@AMDEP_TRUE@ ./$(DEPDIR)/strrcpy.Plo ./$(DEPDIR)/table.Plo \ |
|
93 |
+@AMDEP_TRUE@ ./$(DEPDIR)/text.Plo ./$(DEPDIR)/unrarlib.Plo \ |
|
99 | 94 |
@AMDEP_TRUE@ ./$(DEPDIR)/vba_extract.Plo \ |
100 | 95 |
@AMDEP_TRUE@ ./$(DEPDIR)/zzip-dir.Plo ./$(DEPDIR)/zzip-err.Plo \ |
101 | 96 |
@AMDEP_TRUE@ ./$(DEPDIR)/zzip-file.Plo \ |
... | ... |
@@ -283,22 +278,7 @@ libclamav_la_SOURCES = \ |
283 | 283 |
vba_extract.h \ |
284 | 284 |
cltypes.h \ |
285 | 285 |
msexpand.c \ |
286 |
- msexpand.h \ |
|
287 |
- pe.c \ |
|
288 |
- pe.h \ |
|
289 |
- mspack/cabd.c \ |
|
290 |
- mspack/cab.h \ |
|
291 |
- mspack/lzxd.c \ |
|
292 |
- mspack/lzx.h \ |
|
293 |
- mspack/mspack.h \ |
|
294 |
- mspack/mszipd.c \ |
|
295 |
- mspack/mszip.h \ |
|
296 |
- mspack/qtmd.c \ |
|
297 |
- mspack/qtm.h \ |
|
298 |
- mspack/system.c \ |
|
299 |
- mspack/system.h \ |
|
300 |
- upx.c \ |
|
301 |
- upx.h |
|
286 |
+ msexpand.h |
|
302 | 287 |
|
303 | 288 |
lib_LTLIBRARIES = libclamav.la |
304 | 289 |
all: all-am |
... | ... |
@@ -371,31 +351,24 @@ distclean-compile: |
371 | 371 |
-rm -f *.tab.c |
372 | 372 |
|
373 | 373 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/blob.Plo@am__quote@ |
374 |
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cabd.Plo@am__quote@ |
|
375 | 374 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cvd.Plo@am__quote@ |
376 | 375 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dsig.Plo@am__quote@ |
377 |
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lzxd.Plo@am__quote@ |
|
378 | 376 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/matcher.Plo@am__quote@ |
379 | 377 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbox.Plo@am__quote@ |
380 | 378 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Plo@am__quote@ |
381 | 379 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Plo@am__quote@ |
382 | 380 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/msexpand.Plo@am__quote@ |
383 |
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mszipd.Plo@am__quote@ |
|
384 | 381 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ole2_extract.Plo@am__quote@ |
385 | 382 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/others.Plo@am__quote@ |
386 |
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe.Plo@am__quote@ |
|
387 |
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qtmd.Plo@am__quote@ |
|
388 | 383 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readdb.Plo@am__quote@ |
389 | 384 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scanners.Plo@am__quote@ |
390 | 385 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/snprintf.Plo@am__quote@ |
391 | 386 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str.Plo@am__quote@ |
392 | 387 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strc.Plo@am__quote@ |
393 | 388 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strrcpy.Plo@am__quote@ |
394 |
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Plo@am__quote@ |
|
395 | 389 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@ |
396 | 390 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/text.Plo@am__quote@ |
397 | 391 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unrarlib.Plo@am__quote@ |
398 |
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/upx.Plo@am__quote@ |
|
399 | 392 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vba_extract.Plo@am__quote@ |
400 | 393 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-dir.Plo@am__quote@ |
401 | 394 |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zzip-err.Plo@am__quote@ |
... | ... |
@@ -621,126 +594,6 @@ strc.lo: zziplib/strc.c |
621 | 621 |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
622 | 622 |
@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o strc.lo `test -f 'zziplib/strc.c' || echo '$(srcdir)/'`zziplib/strc.c |
623 | 623 |
|
624 |
-cabd.o: mspack/cabd.c |
|
625 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cabd.o -MD -MP -MF "$(DEPDIR)/cabd.Tpo" -c -o cabd.o `test -f 'mspack/cabd.c' || echo '$(srcdir)/'`mspack/cabd.c; \ |
|
626 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/cabd.Tpo" "$(DEPDIR)/cabd.Po"; else rm -f "$(DEPDIR)/cabd.Tpo"; exit 1; fi |
|
627 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/cabd.c' object='cabd.o' libtool=no @AMDEPBACKSLASH@ |
|
628 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/cabd.Po' tmpdepfile='$(DEPDIR)/cabd.TPo' @AMDEPBACKSLASH@ |
|
629 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
630 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cabd.o `test -f 'mspack/cabd.c' || echo '$(srcdir)/'`mspack/cabd.c |
|
631 |
- |
|
632 |
-cabd.obj: mspack/cabd.c |
|
633 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cabd.obj -MD -MP -MF "$(DEPDIR)/cabd.Tpo" -c -o cabd.obj `if test -f 'mspack/cabd.c'; then $(CYGPATH_W) 'mspack/cabd.c'; else $(CYGPATH_W) '$(srcdir)/mspack/cabd.c'; fi`; \ |
|
634 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/cabd.Tpo" "$(DEPDIR)/cabd.Po"; else rm -f "$(DEPDIR)/cabd.Tpo"; exit 1; fi |
|
635 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/cabd.c' object='cabd.obj' libtool=no @AMDEPBACKSLASH@ |
|
636 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/cabd.Po' tmpdepfile='$(DEPDIR)/cabd.TPo' @AMDEPBACKSLASH@ |
|
637 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
638 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cabd.obj `if test -f 'mspack/cabd.c'; then $(CYGPATH_W) 'mspack/cabd.c'; else $(CYGPATH_W) '$(srcdir)/mspack/cabd.c'; fi` |
|
639 |
- |
|
640 |
-cabd.lo: mspack/cabd.c |
|
641 |
-@am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cabd.lo -MD -MP -MF "$(DEPDIR)/cabd.Tpo" -c -o cabd.lo `test -f 'mspack/cabd.c' || echo '$(srcdir)/'`mspack/cabd.c; \ |
|
642 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/cabd.Tpo" "$(DEPDIR)/cabd.Plo"; else rm -f "$(DEPDIR)/cabd.Tpo"; exit 1; fi |
|
643 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/cabd.c' object='cabd.lo' libtool=yes @AMDEPBACKSLASH@ |
|
644 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/cabd.Plo' tmpdepfile='$(DEPDIR)/cabd.TPlo' @AMDEPBACKSLASH@ |
|
645 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
646 |
-@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cabd.lo `test -f 'mspack/cabd.c' || echo '$(srcdir)/'`mspack/cabd.c |
|
647 |
- |
|
648 |
-lzxd.o: mspack/lzxd.c |
|
649 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lzxd.o -MD -MP -MF "$(DEPDIR)/lzxd.Tpo" -c -o lzxd.o `test -f 'mspack/lzxd.c' || echo '$(srcdir)/'`mspack/lzxd.c; \ |
|
650 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/lzxd.Tpo" "$(DEPDIR)/lzxd.Po"; else rm -f "$(DEPDIR)/lzxd.Tpo"; exit 1; fi |
|
651 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/lzxd.c' object='lzxd.o' libtool=no @AMDEPBACKSLASH@ |
|
652 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/lzxd.Po' tmpdepfile='$(DEPDIR)/lzxd.TPo' @AMDEPBACKSLASH@ |
|
653 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
654 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lzxd.o `test -f 'mspack/lzxd.c' || echo '$(srcdir)/'`mspack/lzxd.c |
|
655 |
- |
|
656 |
-lzxd.obj: mspack/lzxd.c |
|
657 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lzxd.obj -MD -MP -MF "$(DEPDIR)/lzxd.Tpo" -c -o lzxd.obj `if test -f 'mspack/lzxd.c'; then $(CYGPATH_W) 'mspack/lzxd.c'; else $(CYGPATH_W) '$(srcdir)/mspack/lzxd.c'; fi`; \ |
|
658 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/lzxd.Tpo" "$(DEPDIR)/lzxd.Po"; else rm -f "$(DEPDIR)/lzxd.Tpo"; exit 1; fi |
|
659 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/lzxd.c' object='lzxd.obj' libtool=no @AMDEPBACKSLASH@ |
|
660 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/lzxd.Po' tmpdepfile='$(DEPDIR)/lzxd.TPo' @AMDEPBACKSLASH@ |
|
661 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
662 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lzxd.obj `if test -f 'mspack/lzxd.c'; then $(CYGPATH_W) 'mspack/lzxd.c'; else $(CYGPATH_W) '$(srcdir)/mspack/lzxd.c'; fi` |
|
663 |
- |
|
664 |
-lzxd.lo: mspack/lzxd.c |
|
665 |
-@am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lzxd.lo -MD -MP -MF "$(DEPDIR)/lzxd.Tpo" -c -o lzxd.lo `test -f 'mspack/lzxd.c' || echo '$(srcdir)/'`mspack/lzxd.c; \ |
|
666 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/lzxd.Tpo" "$(DEPDIR)/lzxd.Plo"; else rm -f "$(DEPDIR)/lzxd.Tpo"; exit 1; fi |
|
667 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/lzxd.c' object='lzxd.lo' libtool=yes @AMDEPBACKSLASH@ |
|
668 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/lzxd.Plo' tmpdepfile='$(DEPDIR)/lzxd.TPlo' @AMDEPBACKSLASH@ |
|
669 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
670 |
-@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lzxd.lo `test -f 'mspack/lzxd.c' || echo '$(srcdir)/'`mspack/lzxd.c |
|
671 |
- |
|
672 |
-mszipd.o: mspack/mszipd.c |
|
673 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mszipd.o -MD -MP -MF "$(DEPDIR)/mszipd.Tpo" -c -o mszipd.o `test -f 'mspack/mszipd.c' || echo '$(srcdir)/'`mspack/mszipd.c; \ |
|
674 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mszipd.Tpo" "$(DEPDIR)/mszipd.Po"; else rm -f "$(DEPDIR)/mszipd.Tpo"; exit 1; fi |
|
675 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/mszipd.c' object='mszipd.o' libtool=no @AMDEPBACKSLASH@ |
|
676 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/mszipd.Po' tmpdepfile='$(DEPDIR)/mszipd.TPo' @AMDEPBACKSLASH@ |
|
677 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
678 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mszipd.o `test -f 'mspack/mszipd.c' || echo '$(srcdir)/'`mspack/mszipd.c |
|
679 |
- |
|
680 |
-mszipd.obj: mspack/mszipd.c |
|
681 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mszipd.obj -MD -MP -MF "$(DEPDIR)/mszipd.Tpo" -c -o mszipd.obj `if test -f 'mspack/mszipd.c'; then $(CYGPATH_W) 'mspack/mszipd.c'; else $(CYGPATH_W) '$(srcdir)/mspack/mszipd.c'; fi`; \ |
|
682 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mszipd.Tpo" "$(DEPDIR)/mszipd.Po"; else rm -f "$(DEPDIR)/mszipd.Tpo"; exit 1; fi |
|
683 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/mszipd.c' object='mszipd.obj' libtool=no @AMDEPBACKSLASH@ |
|
684 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/mszipd.Po' tmpdepfile='$(DEPDIR)/mszipd.TPo' @AMDEPBACKSLASH@ |
|
685 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
686 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mszipd.obj `if test -f 'mspack/mszipd.c'; then $(CYGPATH_W) 'mspack/mszipd.c'; else $(CYGPATH_W) '$(srcdir)/mspack/mszipd.c'; fi` |
|
687 |
- |
|
688 |
-mszipd.lo: mspack/mszipd.c |
|
689 |
-@am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mszipd.lo -MD -MP -MF "$(DEPDIR)/mszipd.Tpo" -c -o mszipd.lo `test -f 'mspack/mszipd.c' || echo '$(srcdir)/'`mspack/mszipd.c; \ |
|
690 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/mszipd.Tpo" "$(DEPDIR)/mszipd.Plo"; else rm -f "$(DEPDIR)/mszipd.Tpo"; exit 1; fi |
|
691 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/mszipd.c' object='mszipd.lo' libtool=yes @AMDEPBACKSLASH@ |
|
692 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/mszipd.Plo' tmpdepfile='$(DEPDIR)/mszipd.TPlo' @AMDEPBACKSLASH@ |
|
693 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
694 |
-@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mszipd.lo `test -f 'mspack/mszipd.c' || echo '$(srcdir)/'`mspack/mszipd.c |
|
695 |
- |
|
696 |
-qtmd.o: mspack/qtmd.c |
|
697 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT qtmd.o -MD -MP -MF "$(DEPDIR)/qtmd.Tpo" -c -o qtmd.o `test -f 'mspack/qtmd.c' || echo '$(srcdir)/'`mspack/qtmd.c; \ |
|
698 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/qtmd.Tpo" "$(DEPDIR)/qtmd.Po"; else rm -f "$(DEPDIR)/qtmd.Tpo"; exit 1; fi |
|
699 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/qtmd.c' object='qtmd.o' libtool=no @AMDEPBACKSLASH@ |
|
700 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/qtmd.Po' tmpdepfile='$(DEPDIR)/qtmd.TPo' @AMDEPBACKSLASH@ |
|
701 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
702 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o qtmd.o `test -f 'mspack/qtmd.c' || echo '$(srcdir)/'`mspack/qtmd.c |
|
703 |
- |
|
704 |
-qtmd.obj: mspack/qtmd.c |
|
705 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT qtmd.obj -MD -MP -MF "$(DEPDIR)/qtmd.Tpo" -c -o qtmd.obj `if test -f 'mspack/qtmd.c'; then $(CYGPATH_W) 'mspack/qtmd.c'; else $(CYGPATH_W) '$(srcdir)/mspack/qtmd.c'; fi`; \ |
|
706 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/qtmd.Tpo" "$(DEPDIR)/qtmd.Po"; else rm -f "$(DEPDIR)/qtmd.Tpo"; exit 1; fi |
|
707 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/qtmd.c' object='qtmd.obj' libtool=no @AMDEPBACKSLASH@ |
|
708 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/qtmd.Po' tmpdepfile='$(DEPDIR)/qtmd.TPo' @AMDEPBACKSLASH@ |
|
709 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
710 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o qtmd.obj `if test -f 'mspack/qtmd.c'; then $(CYGPATH_W) 'mspack/qtmd.c'; else $(CYGPATH_W) '$(srcdir)/mspack/qtmd.c'; fi` |
|
711 |
- |
|
712 |
-qtmd.lo: mspack/qtmd.c |
|
713 |
-@am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT qtmd.lo -MD -MP -MF "$(DEPDIR)/qtmd.Tpo" -c -o qtmd.lo `test -f 'mspack/qtmd.c' || echo '$(srcdir)/'`mspack/qtmd.c; \ |
|
714 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/qtmd.Tpo" "$(DEPDIR)/qtmd.Plo"; else rm -f "$(DEPDIR)/qtmd.Tpo"; exit 1; fi |
|
715 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/qtmd.c' object='qtmd.lo' libtool=yes @AMDEPBACKSLASH@ |
|
716 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/qtmd.Plo' tmpdepfile='$(DEPDIR)/qtmd.TPlo' @AMDEPBACKSLASH@ |
|
717 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
718 |
-@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o qtmd.lo `test -f 'mspack/qtmd.c' || echo '$(srcdir)/'`mspack/qtmd.c |
|
719 |
- |
|
720 |
-system.o: mspack/system.c |
|
721 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT system.o -MD -MP -MF "$(DEPDIR)/system.Tpo" -c -o system.o `test -f 'mspack/system.c' || echo '$(srcdir)/'`mspack/system.c; \ |
|
722 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/system.Tpo" "$(DEPDIR)/system.Po"; else rm -f "$(DEPDIR)/system.Tpo"; exit 1; fi |
|
723 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/system.c' object='system.o' libtool=no @AMDEPBACKSLASH@ |
|
724 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/system.Po' tmpdepfile='$(DEPDIR)/system.TPo' @AMDEPBACKSLASH@ |
|
725 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
726 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o system.o `test -f 'mspack/system.c' || echo '$(srcdir)/'`mspack/system.c |
|
727 |
- |
|
728 |
-system.obj: mspack/system.c |
|
729 |
-@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT system.obj -MD -MP -MF "$(DEPDIR)/system.Tpo" -c -o system.obj `if test -f 'mspack/system.c'; then $(CYGPATH_W) 'mspack/system.c'; else $(CYGPATH_W) '$(srcdir)/mspack/system.c'; fi`; \ |
|
730 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/system.Tpo" "$(DEPDIR)/system.Po"; else rm -f "$(DEPDIR)/system.Tpo"; exit 1; fi |
|
731 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/system.c' object='system.obj' libtool=no @AMDEPBACKSLASH@ |
|
732 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/system.Po' tmpdepfile='$(DEPDIR)/system.TPo' @AMDEPBACKSLASH@ |
|
733 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
734 |
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o system.obj `if test -f 'mspack/system.c'; then $(CYGPATH_W) 'mspack/system.c'; else $(CYGPATH_W) '$(srcdir)/mspack/system.c'; fi` |
|
735 |
- |
|
736 |
-system.lo: mspack/system.c |
|
737 |
-@am__fastdepCC_TRUE@ if $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT system.lo -MD -MP -MF "$(DEPDIR)/system.Tpo" -c -o system.lo `test -f 'mspack/system.c' || echo '$(srcdir)/'`mspack/system.c; \ |
|
738 |
-@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/system.Tpo" "$(DEPDIR)/system.Plo"; else rm -f "$(DEPDIR)/system.Tpo"; exit 1; fi |
|
739 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mspack/system.c' object='system.lo' libtool=yes @AMDEPBACKSLASH@ |
|
740 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/system.Plo' tmpdepfile='$(DEPDIR)/system.TPlo' @AMDEPBACKSLASH@ |
|
741 |
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
|
742 |
-@am__fastdepCC_FALSE@ $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o system.lo `test -f 'mspack/system.c' || echo '$(srcdir)/'`mspack/system.c |
|
743 |
- |
|
744 | 624 |
mostlyclean-libtool: |
745 | 625 |
-rm -f *.lo |
746 | 626 |
|
747 | 627 |
deleted file mode 100644 |
... | ... |
@@ -1,127 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
5 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
6 |
- * |
|
7 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
8 |
- */ |
|
9 |
- |
|
10 |
-#ifndef MSPACK_CAB_H |
|
11 |
-#define MSPACK_CAB_H 1 |
|
12 |
- |
|
13 |
-#include <mszip.h> |
|
14 |
-#include <qtm.h> |
|
15 |
-#include <lzx.h> |
|
16 |
- |
|
17 |
-/* generic CAB definitions */ |
|
18 |
- |
|
19 |
-/* structure offsets */ |
|
20 |
-#define cfhead_Signature (0x00) |
|
21 |
-#define cfhead_CabinetSize (0x08) |
|
22 |
-#define cfhead_FileOffset (0x10) |
|
23 |
-#define cfhead_MinorVersion (0x18) |
|
24 |
-#define cfhead_MajorVersion (0x19) |
|
25 |
-#define cfhead_NumFolders (0x1A) |
|
26 |
-#define cfhead_NumFiles (0x1C) |
|
27 |
-#define cfhead_Flags (0x1E) |
|
28 |
-#define cfhead_SetID (0x20) |
|
29 |
-#define cfhead_CabinetIndex (0x22) |
|
30 |
-#define cfhead_SIZEOF (0x24) |
|
31 |
-#define cfheadext_HeaderReserved (0x00) |
|
32 |
-#define cfheadext_FolderReserved (0x02) |
|
33 |
-#define cfheadext_DataReserved (0x03) |
|
34 |
-#define cfheadext_SIZEOF (0x04) |
|
35 |
-#define cffold_DataOffset (0x00) |
|
36 |
-#define cffold_NumBlocks (0x04) |
|
37 |
-#define cffold_CompType (0x06) |
|
38 |
-#define cffold_SIZEOF (0x08) |
|
39 |
-#define cffile_UncompressedSize (0x00) |
|
40 |
-#define cffile_FolderOffset (0x04) |
|
41 |
-#define cffile_FolderIndex (0x08) |
|
42 |
-#define cffile_Date (0x0A) |
|
43 |
-#define cffile_Time (0x0C) |
|
44 |
-#define cffile_Attribs (0x0E) |
|
45 |
-#define cffile_SIZEOF (0x10) |
|
46 |
-#define cfdata_CheckSum (0x00) |
|
47 |
-#define cfdata_CompressedSize (0x04) |
|
48 |
-#define cfdata_UncompressedSize (0x06) |
|
49 |
-#define cfdata_SIZEOF (0x08) |
|
50 |
- |
|
51 |
-/* flags */ |
|
52 |
-#define cffoldCOMPTYPE_MASK (0x000f) |
|
53 |
-#define cffoldCOMPTYPE_NONE (0x0000) |
|
54 |
-#define cffoldCOMPTYPE_MSZIP (0x0001) |
|
55 |
-#define cffoldCOMPTYPE_QUANTUM (0x0002) |
|
56 |
-#define cffoldCOMPTYPE_LZX (0x0003) |
|
57 |
-#define cfheadPREV_CABINET (0x0001) |
|
58 |
-#define cfheadNEXT_CABINET (0x0002) |
|
59 |
-#define cfheadRESERVE_PRESENT (0x0004) |
|
60 |
-#define cffileCONTINUED_FROM_PREV (0xFFFD) |
|
61 |
-#define cffileCONTINUED_TO_NEXT (0xFFFE) |
|
62 |
-#define cffileCONTINUED_PREV_AND_NEXT (0xFFFF) |
|
63 |
- |
|
64 |
-/* CAB data blocks are <= 32768 bytes in uncompressed form. Uncompressed |
|
65 |
- * blocks have zero growth. MSZIP guarantees that it won't grow above |
|
66 |
- * uncompressed size by more than 12 bytes. LZX guarantees it won't grow |
|
67 |
- * more than 6144 bytes. Quantum has no documentation, but the largest |
|
68 |
- * block seen in the wild is 337 bytes above uncompressed size. |
|
69 |
- */ |
|
70 |
-#define CAB_BLOCKMAX (32768) |
|
71 |
-#define CAB_INPUTMAX (CAB_BLOCKMAX+6144) |
|
72 |
- |
|
73 |
-/* CAB compression definitions */ |
|
74 |
- |
|
75 |
-struct mscab_compressor_p { |
|
76 |
- struct mscab_compressor base; |
|
77 |
- struct mspack_system *system; |
|
78 |
- /* todo */ |
|
79 |
-}; |
|
80 |
- |
|
81 |
-/* CAB decompression definitions */ |
|
82 |
- |
|
83 |
-struct mscabd_decompress_state { |
|
84 |
- struct mscabd_folder_p *folder; /* current folder we're extracting from */ |
|
85 |
- struct mscabd_folder_data *data; /* current folder split we're in */ |
|
86 |
- unsigned int offset; /* uncompressed offset within folder */ |
|
87 |
- unsigned int block; /* which block are we decompressing? */ |
|
88 |
- struct mspack_system sys; /* special I/O code for decompressor */ |
|
89 |
- int comp_type; /* type of compression used by folder */ |
|
90 |
- int (*decompress)(void *, off_t); /* decompressor code */ |
|
91 |
- void *state; /* decompressor state */ |
|
92 |
- struct mscabd_cabinet_p *incab; /* cabinet where input data comes from */ |
|
93 |
- struct mspack_file *infh; /* input file handle */ |
|
94 |
- struct mspack_file *outfh; /* output file handle */ |
|
95 |
- unsigned char *i_ptr, *i_end; /* input data consumed, end */ |
|
96 |
- unsigned char input[CAB_INPUTMAX]; /* one input block of data */ |
|
97 |
-}; |
|
98 |
- |
|
99 |
-struct mscab_decompressor_p { |
|
100 |
- struct mscab_decompressor base; |
|
101 |
- struct mscabd_decompress_state *d; |
|
102 |
- struct mspack_system *system; |
|
103 |
- int param[3]; /* !!! MATCH THIS TO NUM OF PARAMS IN MSPACK.H !!! */ |
|
104 |
- int error; |
|
105 |
-}; |
|
106 |
- |
|
107 |
-struct mscabd_cabinet_p { |
|
108 |
- struct mscabd_cabinet base; |
|
109 |
- off_t blocks_off; /* offset to data blocks */ |
|
110 |
- int block_resv; /* reserved space in data blocks */ |
|
111 |
-}; |
|
112 |
- |
|
113 |
-/* there is one of these for every cabinet a folder spans */ |
|
114 |
-struct mscabd_folder_data { |
|
115 |
- struct mscabd_folder_data *next; |
|
116 |
- struct mscabd_cabinet_p *cab; /* cabinet file of this folder span */ |
|
117 |
- off_t offset; /* cabinet offset of first datablock */ |
|
118 |
-}; |
|
119 |
- |
|
120 |
-struct mscabd_folder_p { |
|
121 |
- struct mscabd_folder base; |
|
122 |
- struct mscabd_folder_data data; /* where are the data blocks? */ |
|
123 |
- struct mscabd_file *merge_prev; /* do we need to merge backwards? */ |
|
124 |
- struct mscabd_file *merge_next; /* do we need to merge forwards? */ |
|
125 |
-}; |
|
126 |
- |
|
127 |
-#endif |
128 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,1519 +0,0 @@ |
1 |
-/* WARNING: This version also supports dopen for descriptor opening and |
|
2 |
- * is not compatible with the original version. -- T. Kojm |
|
3 |
- * |
|
4 |
- * This file is part of libmspack. |
|
5 |
- * (C) 2003-2004 Stuart Caie. |
|
6 |
- * |
|
7 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
8 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
9 |
- * |
|
10 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
11 |
- */ |
|
12 |
- |
|
13 |
-/* Cabinet (.CAB) files are a form of file archive. Each cabinet contains |
|
14 |
- * "folders", which are compressed spans of data. Each cabinet has |
|
15 |
- * "files", whose metadata is in the cabinet header, but whose actual data |
|
16 |
- * is stored compressed in one of the "folders". Cabinets can span more |
|
17 |
- * than one physical file on disk, in which case they are a "cabinet set", |
|
18 |
- * and usually the last folder of each cabinet extends into the next |
|
19 |
- * cabinet. |
|
20 |
- * |
|
21 |
- * For a complete description of the format, get the official Microsoft |
|
22 |
- * CAB SDK. It can be found at the following URL: |
|
23 |
- * |
|
24 |
- * http://msdn.microsoft.com/library/en-us/dncabsdk/html/cabdl.asp |
|
25 |
- * |
|
26 |
- * It is a self-extracting ZIP file, which can be extracted with the unzip |
|
27 |
- * command. |
|
28 |
- */ |
|
29 |
- |
|
30 |
-/* CAB decompression implementation */ |
|
31 |
- |
|
32 |
-#if HAVE_CONFIG_H |
|
33 |
-#include "clamav-config.h" |
|
34 |
-#endif |
|
35 |
- |
|
36 |
-#include <mspack.h> |
|
37 |
-#include <system.h> |
|
38 |
-#include <cab.h> |
|
39 |
- |
|
40 |
-/* Notes on compliance with cabinet specification: |
|
41 |
- * |
|
42 |
- * One of the main changes between cabextract 0.6 and libmspack's cab |
|
43 |
- * decompressor is the move from block-oriented decompression to |
|
44 |
- * stream-oriented decompression. |
|
45 |
- * |
|
46 |
- * cabextract would read one data block from disk, decompress it with the |
|
47 |
- * appropriate method, then write the decompressed data. The CAB |
|
48 |
- * specification is specifically designed to work like this, as it ensures |
|
49 |
- * compression matches do not span the maximum decompressed block size |
|
50 |
- * limit of 32kb. |
|
51 |
- * |
|
52 |
- * However, the compression algorithms used are stream oriented, with |
|
53 |
- * specific hacks added to them to enforce the "individual 32kb blocks" |
|
54 |
- * rule in CABs. In other file formats, they do not have this limitation. |
|
55 |
- * |
|
56 |
- * In order to make more generalised decompressors, libmspack's CAB |
|
57 |
- * decompressor has moved from being block-oriented to more stream |
|
58 |
- * oriented. This also makes decompression slightly faster. |
|
59 |
- * |
|
60 |
- * However, this leads to incompliance with the CAB specification. The |
|
61 |
- * CAB controller can no longer ensure each block of input given to the |
|
62 |
- * decompressors is matched with their output. The "decompressed size" of |
|
63 |
- * each individual block is thrown away. |
|
64 |
- * |
|
65 |
- * Each CAB block is supposed to be seen as individually compressed. This |
|
66 |
- * means each consecutive data block can have completely different |
|
67 |
- * "uncompressed" sizes, ranging from 1 to 32768 bytes. However, in |
|
68 |
- * reality, all data blocks in a folder decompress to exactly 32768 bytes, |
|
69 |
- * excepting the final block. |
|
70 |
- * |
|
71 |
- * Given this situation, the decompression algorithms are designed to |
|
72 |
- * realign their input bitstreams on 32768 output-byte boundaries, and |
|
73 |
- * various other special cases have been made. libmspack will not |
|
74 |
- * correctly decompress LZX or Quantum compressed folders where the blocks |
|
75 |
- * do not follow this "32768 bytes until last block" pattern. It could be |
|
76 |
- * implemented if needed, but hopefully this is not necessary -- it has |
|
77 |
- * not been seen in over 3Gb of CAB archives. |
|
78 |
- */ |
|
79 |
- |
|
80 |
-/* prototypes */ |
|
81 |
-static struct mscabd_cabinet * cabd_open( |
|
82 |
- struct mscab_decompressor *base, char *filename); |
|
83 |
-static struct mscabd_cabinet * cabd_dopen( |
|
84 |
- struct mscab_decompressor *base, int desc); |
|
85 |
-static void cabd_close( |
|
86 |
- struct mscab_decompressor *base, struct mscabd_cabinet *origcab); |
|
87 |
-static int cabd_read_headers( |
|
88 |
- struct mspack_system *sys, struct mspack_file *fh, |
|
89 |
- struct mscabd_cabinet_p *cab, off_t offset, int quiet); |
|
90 |
-static char *cabd_read_string( |
|
91 |
- struct mspack_system *sys, struct mspack_file *fh, |
|
92 |
- struct mscabd_cabinet_p *cab, int *error); |
|
93 |
- |
|
94 |
-static struct mscabd_cabinet *cabd_search( |
|
95 |
- struct mscab_decompressor *base, char *filename); |
|
96 |
-static struct mscabd_cabinet *cabd_dsearch( |
|
97 |
- struct mscab_decompressor *base, int desc); |
|
98 |
-static int cabd_find( |
|
99 |
- struct mscab_decompressor_p *this, unsigned char *buf, |
|
100 |
- struct mspack_file *fh, char *filename, int desc, off_t flen, |
|
101 |
- unsigned int *firstlen, struct mscabd_cabinet_p **firstcab); |
|
102 |
- |
|
103 |
-static int cabd_prepend( |
|
104 |
- struct mscab_decompressor *base, struct mscabd_cabinet *cab, |
|
105 |
- struct mscabd_cabinet *prevcab); |
|
106 |
-static int cabd_append( |
|
107 |
- struct mscab_decompressor *base, struct mscabd_cabinet *cab, |
|
108 |
- struct mscabd_cabinet *nextcab); |
|
109 |
-static int cabd_merge( |
|
110 |
- struct mscab_decompressor *base, struct mscabd_cabinet *lcab, |
|
111 |
- struct mscabd_cabinet *rcab); |
|
112 |
- |
|
113 |
-static int cabd_extract( |
|
114 |
- struct mscab_decompressor *base, struct mscabd_file *file, char *filename); |
|
115 |
-static int cabd_init_decomp( |
|
116 |
- struct mscab_decompressor_p *this, unsigned int ct); |
|
117 |
-static void cabd_free_decomp( |
|
118 |
- struct mscab_decompressor_p *this); |
|
119 |
-static int cabd_sys_read( |
|
120 |
- struct mspack_file *file, void *buffer, int bytes); |
|
121 |
-static int cabd_sys_write( |
|
122 |
- struct mspack_file *file, void *buffer, int bytes); |
|
123 |
-static int cabd_sys_read_block( |
|
124 |
- struct mspack_system *sys, struct mscabd_decompress_state *d, int *out, |
|
125 |
- int ignore_cksum); |
|
126 |
-static unsigned int cabd_checksum( |
|
127 |
- unsigned char *data, unsigned int bytes, unsigned int cksum); |
|
128 |
-static struct noned_state *noned_init( |
|
129 |
- struct mspack_system *sys, struct mspack_file *in, struct mspack_file *out, |
|
130 |
- int bufsize); |
|
131 |
- |
|
132 |
-static int noned_decompress( |
|
133 |
- struct noned_state *s, off_t bytes); |
|
134 |
-static void noned_free( |
|
135 |
- struct noned_state *state); |
|
136 |
- |
|
137 |
-static int cabd_param( |
|
138 |
- struct mscab_decompressor *base, int param, int value); |
|
139 |
- |
|
140 |
-static int cabd_error( |
|
141 |
- struct mscab_decompressor *base); |
|
142 |
- |
|
143 |
- |
|
144 |
-/*************************************** |
|
145 |
- * MSPACK_CREATE_CAB_DECOMPRESSOR |
|
146 |
- *************************************** |
|
147 |
- * constructor |
|
148 |
- */ |
|
149 |
-struct mscab_decompressor * |
|
150 |
- mspack_create_cab_decompressor(struct mspack_system *sys) |
|
151 |
-{ |
|
152 |
- struct mscab_decompressor_p *this = NULL; |
|
153 |
- |
|
154 |
- if (!sys) sys = mspack_default_system; |
|
155 |
- if (!mspack_valid_system(sys)) return NULL; |
|
156 |
- |
|
157 |
- if ((this = sys->alloc(sys, sizeof(struct mscab_decompressor_p)))) { |
|
158 |
- this->base.open = &cabd_open; |
|
159 |
- this->base.dopen = &cabd_dopen; |
|
160 |
- this->base.close = &cabd_close; |
|
161 |
- this->base.search = &cabd_search; |
|
162 |
- this->base.dsearch = &cabd_dsearch; |
|
163 |
- this->base.extract = &cabd_extract; |
|
164 |
- this->base.prepend = &cabd_prepend; |
|
165 |
- this->base.append = &cabd_append; |
|
166 |
- this->base.set_param = &cabd_param; |
|
167 |
- this->base.last_error = &cabd_error; |
|
168 |
- this->system = sys; |
|
169 |
- this->d = NULL; |
|
170 |
- this->error = MSPACK_ERR_OK; |
|
171 |
- |
|
172 |
- this->param[MSCABD_PARAM_SEARCHBUF] = 32768; |
|
173 |
- this->param[MSCABD_PARAM_FIXMSZIP] = 0; |
|
174 |
- this->param[MSCABD_PARAM_DECOMPBUF] = 4096; |
|
175 |
- } |
|
176 |
- return (struct mscab_decompressor *) this; |
|
177 |
-} |
|
178 |
- |
|
179 |
-/*************************************** |
|
180 |
- * MSPACK_DESTROY_CAB_DECOMPRESSOR |
|
181 |
- *************************************** |
|
182 |
- * destructor |
|
183 |
- */ |
|
184 |
-void mspack_destroy_cab_decompressor(struct mscab_decompressor *base) { |
|
185 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
186 |
- if (this) { |
|
187 |
- struct mspack_system *sys = this->system; |
|
188 |
- cabd_free_decomp(this); |
|
189 |
- if (this->d) { |
|
190 |
- if (this->d->infh) sys->close(this->d->infh); |
|
191 |
- sys->free(this->d); |
|
192 |
- } |
|
193 |
- sys->free(this); |
|
194 |
- } |
|
195 |
-} |
|
196 |
- |
|
197 |
- |
|
198 |
-/*************************************** |
|
199 |
- * CABD_OPEN |
|
200 |
- *************************************** |
|
201 |
- * opens a file and tries to read it as a cabinet file |
|
202 |
- */ |
|
203 |
-static struct mscabd_cabinet *cabd_open(struct mscab_decompressor *base, |
|
204 |
- char *filename) |
|
205 |
-{ |
|
206 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
207 |
- struct mscabd_cabinet_p *cab = NULL; |
|
208 |
- struct mspack_system *sys; |
|
209 |
- struct mspack_file *fh; |
|
210 |
- int error; |
|
211 |
- |
|
212 |
- if (!base) return NULL; |
|
213 |
- sys = this->system; |
|
214 |
- |
|
215 |
- if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) { |
|
216 |
- if ((cab = sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) { |
|
217 |
- cab->base.filename = filename; |
|
218 |
- /* cab->base.desc = 0; */ |
|
219 |
- error = cabd_read_headers(sys, fh, cab, (off_t) 0, 0); |
|
220 |
- if (error) { |
|
221 |
- cabd_close(base, (struct mscabd_cabinet *) cab); |
|
222 |
- cab = NULL; |
|
223 |
- } |
|
224 |
- this->error = error; |
|
225 |
- } |
|
226 |
- else { |
|
227 |
- this->error = MSPACK_ERR_NOMEMORY; |
|
228 |
- } |
|
229 |
- sys->close(fh); |
|
230 |
- } |
|
231 |
- else { |
|
232 |
- this->error = MSPACK_ERR_OPEN; |
|
233 |
- } |
|
234 |
- return (struct mscabd_cabinet *) cab; |
|
235 |
-} |
|
236 |
- |
|
237 |
-static struct mscabd_cabinet *cabd_dopen(struct mscab_decompressor *base, |
|
238 |
- int desc) |
|
239 |
-{ |
|
240 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
241 |
- struct mscabd_cabinet_p *cab = NULL; |
|
242 |
- struct mspack_system *sys; |
|
243 |
- struct mspack_file *fh; |
|
244 |
- int error; |
|
245 |
- |
|
246 |
- if (!base) return NULL; |
|
247 |
- sys = this->system; |
|
248 |
- |
|
249 |
- if ((fh = sys->dopen(sys, desc, MSPACK_SYS_OPEN_READ))) { |
|
250 |
- if ((cab = sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) { |
|
251 |
- cab->base.filename = "descriptor"; |
|
252 |
- cab->base.desc = desc; |
|
253 |
- error = cabd_read_headers(sys, fh, cab, (off_t) 0, 0); |
|
254 |
- if (error) { |
|
255 |
- cabd_close(base, (struct mscabd_cabinet *) cab); |
|
256 |
- cab = NULL; |
|
257 |
- } |
|
258 |
- this->error = error; |
|
259 |
- } |
|
260 |
- else { |
|
261 |
- this->error = MSPACK_ERR_NOMEMORY; |
|
262 |
- } |
|
263 |
- sys->close(fh); |
|
264 |
- } |
|
265 |
- else { |
|
266 |
- this->error = MSPACK_ERR_OPEN; |
|
267 |
- } |
|
268 |
- return (struct mscabd_cabinet *) cab; |
|
269 |
-} |
|
270 |
- |
|
271 |
-/*************************************** |
|
272 |
- * CABD_CLOSE |
|
273 |
- *************************************** |
|
274 |
- * frees all memory associated with a given mscabd_cabinet. |
|
275 |
- */ |
|
276 |
-static void cabd_close(struct mscab_decompressor *base, |
|
277 |
- struct mscabd_cabinet *origcab) |
|
278 |
-{ |
|
279 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
280 |
- struct mscabd_folder_data *dat, *ndat; |
|
281 |
- struct mscabd_cabinet *cab, *ncab; |
|
282 |
- struct mscabd_folder *fol, *nfol; |
|
283 |
- struct mscabd_file *fi, *nfi; |
|
284 |
- struct mspack_system *sys; |
|
285 |
- |
|
286 |
- if (!base) return; |
|
287 |
- sys = this->system; |
|
288 |
- |
|
289 |
- this->error = MSPACK_ERR_OK; |
|
290 |
- |
|
291 |
- while (origcab) { |
|
292 |
- /* free files */ |
|
293 |
- for (fi = origcab->files; fi; fi = nfi) { |
|
294 |
- nfi = fi->next; |
|
295 |
- sys->free(fi->filename); |
|
296 |
- sys->free(fi); |
|
297 |
- } |
|
298 |
- |
|
299 |
- /* free folders */ |
|
300 |
- for (fol = origcab->folders; fol; fol = nfol) { |
|
301 |
- nfol = fol->next; |
|
302 |
- |
|
303 |
- /* free folder decompression state if it has been decompressed */ |
|
304 |
- if (this->d && (this->d->folder == (struct mscabd_folder_p *) fol)) { |
|
305 |
- if (this->d->infh) sys->close(this->d->infh); |
|
306 |
- cabd_free_decomp(this); |
|
307 |
- sys->free(this->d); |
|
308 |
- this->d = NULL; |
|
309 |
- } |
|
310 |
- |
|
311 |
- /* free folder data segments */ |
|
312 |
- for (dat = ((struct mscabd_folder_p *)fol)->data.next; dat; dat = ndat) { |
|
313 |
- ndat = dat->next; |
|
314 |
- sys->free(dat); |
|
315 |
- } |
|
316 |
- sys->free(fol); |
|
317 |
- } |
|
318 |
- |
|
319 |
- /* free predecessor cabinets (and the original cabinet's strings) */ |
|
320 |
- for (cab = origcab; cab; cab = ncab) { |
|
321 |
- ncab = cab->prevcab; |
|
322 |
- sys->free(cab->prevname); |
|
323 |
- sys->free(cab->nextname); |
|
324 |
- sys->free(cab->previnfo); |
|
325 |
- sys->free(cab->nextinfo); |
|
326 |
- if (cab != origcab) sys->free(cab); |
|
327 |
- } |
|
328 |
- |
|
329 |
- /* free successor cabinets */ |
|
330 |
- for (cab = origcab->nextcab; cab; cab = ncab) { |
|
331 |
- ncab = cab->nextcab; |
|
332 |
- sys->free(cab->prevname); |
|
333 |
- sys->free(cab->nextname); |
|
334 |
- sys->free(cab->previnfo); |
|
335 |
- sys->free(cab->nextinfo); |
|
336 |
- sys->free(cab); |
|
337 |
- } |
|
338 |
- |
|
339 |
- /* free actual cabinet structure */ |
|
340 |
- cab = origcab->next; |
|
341 |
- sys->free(origcab); |
|
342 |
- |
|
343 |
- /* repeat full procedure again with the cab->next pointer (if set) */ |
|
344 |
- origcab = cab; |
|
345 |
- } |
|
346 |
-} |
|
347 |
- |
|
348 |
-/*************************************** |
|
349 |
- * CABD_READ_HEADERS |
|
350 |
- *************************************** |
|
351 |
- * reads the cabinet file header, folder list and file list. |
|
352 |
- * fills out a pre-existing mscabd_cabinet structure, allocates memory |
|
353 |
- * for folders and files as necessary |
|
354 |
- */ |
|
355 |
-static int cabd_read_headers(struct mspack_system *sys, |
|
356 |
- struct mspack_file *fh, |
|
357 |
- struct mscabd_cabinet_p *cab, |
|
358 |
- off_t offset, int quiet) |
|
359 |
-{ |
|
360 |
- int num_folders, num_files, folder_resv, i, x; |
|
361 |
- struct mscabd_folder_p *fol, *linkfol = NULL; |
|
362 |
- struct mscabd_file *file, *linkfile = NULL; |
|
363 |
- unsigned char buf[64]; |
|
364 |
- |
|
365 |
- /* initialise pointers */ |
|
366 |
- cab->base.next = NULL; |
|
367 |
- cab->base.files = NULL; |
|
368 |
- cab->base.folders = NULL; |
|
369 |
- cab->base.prevcab = cab->base.nextcab = NULL; |
|
370 |
- cab->base.prevname = cab->base.nextname = NULL; |
|
371 |
- cab->base.previnfo = cab->base.nextinfo = NULL; |
|
372 |
- |
|
373 |
- cab->base.base_offset = offset; |
|
374 |
- |
|
375 |
- /* seek to CFHEADER */ |
|
376 |
- if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) { |
|
377 |
- return MSPACK_ERR_SEEK; |
|
378 |
- } |
|
379 |
- |
|
380 |
- /* read in the CFHEADER */ |
|
381 |
- if (sys->read(fh, &buf[0], cfhead_SIZEOF) != cfhead_SIZEOF) { |
|
382 |
- return MSPACK_ERR_READ; |
|
383 |
- } |
|
384 |
- |
|
385 |
- /* check for "MSCF" signature */ |
|
386 |
- if (EndGetI32(&buf[cfhead_Signature]) != 0x4643534D) { |
|
387 |
- return MSPACK_ERR_SIGNATURE; |
|
388 |
- } |
|
389 |
- |
|
390 |
- /* some basic header fields */ |
|
391 |
- cab->base.length = EndGetI32(&buf[cfhead_CabinetSize]); |
|
392 |
- cab->base.set_id = EndGetI16(&buf[cfhead_SetID]); |
|
393 |
- cab->base.set_index = EndGetI16(&buf[cfhead_CabinetIndex]); |
|
394 |
- |
|
395 |
- /* get the number of folders */ |
|
396 |
- num_folders = EndGetI16(&buf[cfhead_NumFolders]); |
|
397 |
- if (num_folders == 0) { |
|
398 |
- if (!quiet) sys->message(fh, "no folders in cabinet."); |
|
399 |
- return MSPACK_ERR_DATAFORMAT; |
|
400 |
- } |
|
401 |
- |
|
402 |
- /* get the number of files */ |
|
403 |
- num_files = EndGetI16(&buf[cfhead_NumFiles]); |
|
404 |
- if (num_files == 0) { |
|
405 |
- if (!quiet) sys->message(fh, "no files in cabinet."); |
|
406 |
- return MSPACK_ERR_DATAFORMAT; |
|
407 |
- } |
|
408 |
- |
|
409 |
- /* check cabinet version */ |
|
410 |
- if ((buf[cfhead_MajorVersion] != 1) && (buf[cfhead_MinorVersion] != 3)) { |
|
411 |
- if (!quiet) sys->message(fh, "WARNING; cabinet version is not 1.3"); |
|
412 |
- } |
|
413 |
- |
|
414 |
- /* read the reserved-sizes part of header, if present */ |
|
415 |
- cab->base.flags = EndGetI16(&buf[cfhead_Flags]); |
|
416 |
- if (cab->base.flags & cfheadRESERVE_PRESENT) { |
|
417 |
- if (sys->read(fh, &buf[0], cfheadext_SIZEOF) != cfheadext_SIZEOF) { |
|
418 |
- return MSPACK_ERR_READ; |
|
419 |
- } |
|
420 |
- cab->base.header_resv = EndGetI16(&buf[cfheadext_HeaderReserved]); |
|
421 |
- folder_resv = buf[cfheadext_FolderReserved]; |
|
422 |
- cab->block_resv = buf[cfheadext_DataReserved]; |
|
423 |
- |
|
424 |
- if (cab->base.header_resv > 60000) { |
|
425 |
- if (!quiet) sys->message(fh, "WARNING; reserved header > 60000."); |
|
426 |
- } |
|
427 |
- |
|
428 |
- /* skip the reserved header */ |
|
429 |
- if (cab->base.header_resv) { |
|
430 |
- if (sys->seek(fh, (off_t) cab->base.header_resv, MSPACK_SYS_SEEK_CUR)) { |
|
431 |
- return MSPACK_ERR_SEEK; |
|
432 |
- } |
|
433 |
- } |
|
434 |
- } |
|
435 |
- else { |
|
436 |
- cab->base.header_resv = 0; |
|
437 |
- folder_resv = 0; |
|
438 |
- cab->block_resv = 0; |
|
439 |
- } |
|
440 |
- |
|
441 |
- /* read name and info of preceeding cabinet in set, if present */ |
|
442 |
- if (cab->base.flags & cfheadPREV_CABINET) { |
|
443 |
- cab->base.prevname = cabd_read_string(sys, fh, cab, &x); if (x) return x; |
|
444 |
- cab->base.previnfo = cabd_read_string(sys, fh, cab, &x); if (x) return x; |
|
445 |
- } |
|
446 |
- |
|
447 |
- /* read name and info of next cabinet in set, if present */ |
|
448 |
- if (cab->base.flags & cfheadNEXT_CABINET) { |
|
449 |
- cab->base.nextname = cabd_read_string(sys, fh, cab, &x); if (x) return x; |
|
450 |
- cab->base.nextinfo = cabd_read_string(sys, fh, cab, &x); if (x) return x; |
|
451 |
- } |
|
452 |
- |
|
453 |
- /* read folders */ |
|
454 |
- for (i = 0; i < num_folders; i++) { |
|
455 |
- if (sys->read(fh, &buf[0], cffold_SIZEOF) != cffold_SIZEOF) { |
|
456 |
- return MSPACK_ERR_READ; |
|
457 |
- } |
|
458 |
- if (folder_resv) { |
|
459 |
- if (sys->seek(fh, (off_t) folder_resv, MSPACK_SYS_SEEK_CUR)) { |
|
460 |
- return MSPACK_ERR_SEEK; |
|
461 |
- } |
|
462 |
- } |
|
463 |
- |
|
464 |
- if (!(fol = sys->alloc(sys, sizeof(struct mscabd_folder_p)))) { |
|
465 |
- return MSPACK_ERR_NOMEMORY; |
|
466 |
- } |
|
467 |
- fol->base.next = NULL; |
|
468 |
- fol->base.comp_type = EndGetI16(&buf[cffold_CompType]); |
|
469 |
- fol->base.num_blocks = EndGetI16(&buf[cffold_NumBlocks]); |
|
470 |
- fol->data.next = NULL; |
|
471 |
- fol->data.cab = (struct mscabd_cabinet_p *) cab; |
|
472 |
- fol->data.offset = offset + (off_t) |
|
473 |
- ( (unsigned int) EndGetI32(&buf[cffold_DataOffset]) ); |
|
474 |
- fol->merge_prev = NULL; |
|
475 |
- fol->merge_next = NULL; |
|
476 |
- |
|
477 |
- /* link folder into list of folders */ |
|
478 |
- if (!linkfol) cab->base.folders = (struct mscabd_folder *) fol; |
|
479 |
- else linkfol->base.next = (struct mscabd_folder *) fol; |
|
480 |
- linkfol = fol; |
|
481 |
- } |
|
482 |
- |
|
483 |
- /* read files */ |
|
484 |
- for (i = 0; i < num_files; i++) { |
|
485 |
- if (sys->read(fh, &buf[0], cffile_SIZEOF) != cffile_SIZEOF) { |
|
486 |
- return MSPACK_ERR_READ; |
|
487 |
- } |
|
488 |
- |
|
489 |
- if (!(file = sys->alloc(sys, sizeof(struct mscabd_file)))) { |
|
490 |
- return MSPACK_ERR_NOMEMORY; |
|
491 |
- } |
|
492 |
- |
|
493 |
- file->next = NULL; |
|
494 |
- file->length = EndGetI32(&buf[cffile_UncompressedSize]); |
|
495 |
- file->attribs = EndGetI16(&buf[cffile_Attribs]); |
|
496 |
- file->offset = EndGetI32(&buf[cffile_FolderOffset]); |
|
497 |
- |
|
498 |
- /* set folder pointer */ |
|
499 |
- x = EndGetI16(&buf[cffile_FolderIndex]); |
|
500 |
- if (x < cffileCONTINUED_FROM_PREV) { |
|
501 |
- /* normal folder index; count up to the correct folder. the folder |
|
502 |
- * pointer will be NULL if folder index is invalid */ |
|
503 |
- struct mscabd_folder *ifol = cab->base.folders; |
|
504 |
- while (x--) if (ifol) ifol = ifol->next; |
|
505 |
- file->folder = ifol; |
|
506 |
- |
|
507 |
- if (!ifol) { |
|
508 |
- sys->free(file); |
|
509 |
- D(("invalid folder index")) |
|
510 |
- return MSPACK_ERR_DATAFORMAT; |
|
511 |
- } |
|
512 |
- } |
|
513 |
- else { |
|
514 |
- /* either CONTINUED_TO_NEXT, CONTINUED_FROM_PREV or |
|
515 |
- * CONTINUED_PREV_AND_NEXT */ |
|
516 |
- if ((x == cffileCONTINUED_TO_NEXT) || |
|
517 |
- (x == cffileCONTINUED_PREV_AND_NEXT)) |
|
518 |
- { |
|
519 |
- /* get last folder */ |
|
520 |
- struct mscabd_folder *ifol = cab->base.folders; |
|
521 |
- while (ifol->next) ifol = ifol->next; |
|
522 |
- file->folder = ifol; |
|
523 |
- |
|
524 |
- /* set "merge next" pointer */ |
|
525 |
- fol = (struct mscabd_folder_p *) ifol; |
|
526 |
- if (!fol->merge_next) fol->merge_next = file; |
|
527 |
- } |
|
528 |
- |
|
529 |
- if ((x == cffileCONTINUED_FROM_PREV) || |
|
530 |
- (x == cffileCONTINUED_PREV_AND_NEXT)) |
|
531 |
- { |
|
532 |
- /* get first folder */ |
|
533 |
- file->folder = cab->base.folders; |
|
534 |
- |
|
535 |
- /* set "merge prev" pointer */ |
|
536 |
- fol = (struct mscabd_folder_p *) file->folder; |
|
537 |
- if (!fol->merge_prev) fol->merge_prev = file; |
|
538 |
- } |
|
539 |
- } |
|
540 |
- |
|
541 |
- /* get time */ |
|
542 |
- x = EndGetI16(&buf[cffile_Time]); |
|
543 |
- file->time_h = x >> 11; |
|
544 |
- file->time_m = (x >> 5) & 0x3F; |
|
545 |
- file->time_s = (x << 1) & 0x3E; |
|
546 |
- |
|
547 |
- /* get date */ |
|
548 |
- x = EndGetI16(&buf[cffile_Date]); |
|
549 |
- file->date_d = x & 0x1F; |
|
550 |
- file->date_m = (x >> 5) & 0xF; |
|
551 |
- file->date_y = (x >> 9) + 1980; |
|
552 |
- |
|
553 |
- /* get filename */ |
|
554 |
- file->filename = cabd_read_string(sys, fh, cab, &x); |
|
555 |
- if (x) { |
|
556 |
- sys->free(file); |
|
557 |
- return x; |
|
558 |
- } |
|
559 |
- |
|
560 |
- /* link file entry into file list */ |
|
561 |
- if (!linkfile) cab->base.files = file; |
|
562 |
- else linkfile->next = file; |
|
563 |
- linkfile = file; |
|
564 |
- } |
|
565 |
- |
|
566 |
- return MSPACK_ERR_OK; |
|
567 |
-} |
|
568 |
- |
|
569 |
-static char *cabd_read_string(struct mspack_system *sys, |
|
570 |
- struct mspack_file *fh, |
|
571 |
- struct mscabd_cabinet_p *cab, int *error) |
|
572 |
-{ |
|
573 |
- off_t base = sys->tell(fh); |
|
574 |
- char buf[256], *str; |
|
575 |
- unsigned int len, i, ok; |
|
576 |
- |
|
577 |
- /* read up to 256 bytes */ |
|
578 |
- len = sys->read(fh, &buf[0], 256); |
|
579 |
- |
|
580 |
- /* search for a null terminator in the buffer */ |
|
581 |
- for (i = 0, ok = 0; i < len; i++) if (!buf[i]) { ok = 1; break; } |
|
582 |
- if (!ok) { |
|
583 |
- *error = MSPACK_ERR_DATAFORMAT; |
|
584 |
- return NULL; |
|
585 |
- } |
|
586 |
- |
|
587 |
- len = i + 1; |
|
588 |
- |
|
589 |
- /* set the data stream to just after the string and return */ |
|
590 |
- if (sys->seek(fh, base + (off_t)len, MSPACK_SYS_SEEK_START)) { |
|
591 |
- *error = MSPACK_ERR_SEEK; |
|
592 |
- return NULL; |
|
593 |
- } |
|
594 |
- |
|
595 |
- if (!(str = sys->alloc(sys, len))) { |
|
596 |
- *error = MSPACK_ERR_NOMEMORY; |
|
597 |
- return NULL; |
|
598 |
- } |
|
599 |
- |
|
600 |
- sys->copy(&buf[0], str, len); |
|
601 |
- *error = MSPACK_ERR_OK; |
|
602 |
- return str; |
|
603 |
-} |
|
604 |
- |
|
605 |
-/*************************************** |
|
606 |
- * CABD_SEARCH, CABD_FIND |
|
607 |
- *************************************** |
|
608 |
- * cabd_search opens a file, finds its extent, allocates a search buffer, |
|
609 |
- * then reads through the whole file looking for possible cabinet headers. |
|
610 |
- * if it finds any, it tries to read them as real cabinets. returns a linked |
|
611 |
- * list of results |
|
612 |
- * |
|
613 |
- * cabd_find is the inner loop of cabd_search, to make it easier to |
|
614 |
- * break out of the loop and be sure that all resources are freed |
|
615 |
- */ |
|
616 |
-static struct mscabd_cabinet *cabd_search(struct mscab_decompressor *base, |
|
617 |
- char *filename) |
|
618 |
-{ |
|
619 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
620 |
- struct mscabd_cabinet_p *cab = NULL; |
|
621 |
- struct mspack_system *sys; |
|
622 |
- unsigned char *search_buf; |
|
623 |
- struct mspack_file *fh; |
|
624 |
- unsigned int firstlen = 0; |
|
625 |
- off_t filelen; |
|
626 |
- |
|
627 |
- if (!base) return NULL; |
|
628 |
- sys = this->system; |
|
629 |
- |
|
630 |
- /* allocate a search buffer */ |
|
631 |
- search_buf = sys->alloc(sys, (size_t) this->param[MSCABD_PARAM_SEARCHBUF]); |
|
632 |
- if (!search_buf) { |
|
633 |
- this->error = MSPACK_ERR_NOMEMORY; |
|
634 |
- return NULL; |
|
635 |
- } |
|
636 |
- |
|
637 |
- /* open file and get its full file length */ |
|
638 |
- if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) { |
|
639 |
- if (!(this->error = mspack_sys_filelen(sys, fh, &filelen))) { |
|
640 |
- this->error = cabd_find(this, search_buf, fh, filename, 0, |
|
641 |
- filelen, &firstlen, &cab); |
|
642 |
- } |
|
643 |
- |
|
644 |
- /* truncated / extraneous data warning: */ |
|
645 |
- if (firstlen && (firstlen != filelen) && |
|
646 |
- (!cab || (cab->base.base_offset == 0))) |
|
647 |
- { |
|
648 |
- if (firstlen < filelen) { |
|
649 |
- sys->message(fh, "WARNING; possible %u extra bytes at end of file.", |
|
650 |
- (unsigned int) (filelen - firstlen)); |
|
651 |
- } |
|
652 |
- else { |
|
653 |
- sys->message(fh, "WARNING; file possibly truncated by %u bytes.", |
|
654 |
- (unsigned int) (firstlen - filelen)); |
|
655 |
- } |
|
656 |
- } |
|
657 |
- |
|
658 |
- sys->close(fh); |
|
659 |
- } |
|
660 |
- else { |
|
661 |
- this->error = MSPACK_ERR_OPEN; |
|
662 |
- } |
|
663 |
- |
|
664 |
- /* free the search buffer */ |
|
665 |
- sys->free(search_buf); |
|
666 |
- |
|
667 |
- return (struct mscabd_cabinet *) cab; |
|
668 |
-} |
|
669 |
- |
|
670 |
-static struct mscabd_cabinet *cabd_dsearch(struct mscab_decompressor *base, |
|
671 |
- int desc) |
|
672 |
-{ |
|
673 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
674 |
- struct mscabd_cabinet_p *cab = NULL; |
|
675 |
- struct mspack_system *sys; |
|
676 |
- unsigned char *search_buf; |
|
677 |
- struct mspack_file *fh; |
|
678 |
- unsigned int firstlen = 0; |
|
679 |
- off_t filelen; |
|
680 |
- char *filename = "descriptor-"; |
|
681 |
- |
|
682 |
- if (!base) return NULL; |
|
683 |
- sys = this->system; |
|
684 |
- |
|
685 |
- /* allocate a search buffer */ |
|
686 |
- search_buf = sys->alloc(sys, (size_t) this->param[MSCABD_PARAM_SEARCHBUF]); |
|
687 |
- if (!search_buf) { |
|
688 |
- this->error = MSPACK_ERR_NOMEMORY; |
|
689 |
- return NULL; |
|
690 |
- } |
|
691 |
- |
|
692 |
- /* open file and get its full file length */ |
|
693 |
- if ((fh = sys->dopen(sys, desc, MSPACK_SYS_OPEN_READ))) { |
|
694 |
- if (!(this->error = mspack_sys_filelen(sys, fh, &filelen))) { |
|
695 |
- this->error = cabd_find(this, search_buf, fh, filename, desc, |
|
696 |
- filelen, &firstlen, &cab); |
|
697 |
- } |
|
698 |
- |
|
699 |
- /* truncated / extraneous data warning: */ |
|
700 |
- if (firstlen && (firstlen != filelen) && |
|
701 |
- (!cab || (cab->base.base_offset == 0))) |
|
702 |
- { |
|
703 |
- if (firstlen < filelen) { |
|
704 |
- sys->message(fh, "WARNING; possible %u extra bytes at end of file.", |
|
705 |
- (unsigned int) (filelen - firstlen)); |
|
706 |
- } |
|
707 |
- else { |
|
708 |
- sys->message(fh, "WARNING; file possibly truncated by %u bytes.", |
|
709 |
- (unsigned int) (firstlen - filelen)); |
|
710 |
- } |
|
711 |
- } |
|
712 |
- |
|
713 |
- /* sys->close(fh); */ |
|
714 |
- } |
|
715 |
- else { |
|
716 |
- this->error = MSPACK_ERR_OPEN; |
|
717 |
- } |
|
718 |
- |
|
719 |
- /* free the search buffer */ |
|
720 |
- sys->free(search_buf); |
|
721 |
- |
|
722 |
- return (struct mscabd_cabinet *) cab; |
|
723 |
-} |
|
724 |
- |
|
725 |
- |
|
726 |
-static int cabd_find(struct mscab_decompressor_p *this, unsigned char *buf, |
|
727 |
- struct mspack_file *fh, char *filename, int desc, off_t flen, |
|
728 |
- unsigned int *firstlen, |
|
729 |
- struct mscabd_cabinet_p **firstcab) |
|
730 |
-{ |
|
731 |
- struct mscabd_cabinet_p *cab, *link = NULL; |
|
732 |
- off_t caboff, offset, foffset=0, cablen=0; |
|
733 |
- struct mspack_system *sys = this->system; |
|
734 |
- unsigned char *p, *pend, state = 0; |
|
735 |
- int false_cabs = 0, length; |
|
736 |
- |
|
737 |
- /* search through the full file length */ |
|
738 |
- for (offset = 0; offset < flen; offset += length) { |
|
739 |
- /* search length is either the full length of the search buffer, or the |
|
740 |
- * amount of data remaining to the end of the file, whichever is less. */ |
|
741 |
- length = flen - offset; |
|
742 |
- if (length > this->param[MSCABD_PARAM_SEARCHBUF]) { |
|
743 |
- length = this->param[MSCABD_PARAM_SEARCHBUF]; |
|
744 |
- } |
|
745 |
- |
|
746 |
- /* fill the search buffer with data from disk */ |
|
747 |
- if (sys->read(fh, &buf[0], length) != length) { |
|
748 |
- return MSPACK_ERR_READ; |
|
749 |
- } |
|
750 |
- |
|
751 |
- /* FAQ avoidance strategy */ |
|
752 |
- if ((offset == 0) && (EndGetI32(&buf[0]) == 0x28635349)) { |
|
753 |
- sys->message(fh, "WARNING; found InstallShield header. " |
|
754 |
- "This is probably an InstallShield file. " |
|
755 |
- "Use UNSHIELD (http://synce.sf.net) to unpack it."); |
|
756 |
- } |
|
757 |
- |
|
758 |
- /* read through the entire buffer. */ |
|
759 |
- for (p = &buf[0], pend = &buf[length]; p < pend; ) { |
|
760 |
- switch (state) { |
|
761 |
- /* starting state */ |
|
762 |
- case 0: |
|
763 |
- /* we spend most of our time in this while loop, looking for |
|
764 |
- * a leading 'M' of the 'MSCF' signature */ |
|
765 |
- while (p < pend && *p != 0x4D) p++; |
|
766 |
- /* if we found tht 'M', advance state */ |
|
767 |
- if (p++ < pend) state = 1; |
|
768 |
- break; |
|
769 |
- |
|
770 |
- /* verify that the next 3 bytes are 'S', 'C' and 'F' */ |
|
771 |
- case 1: state = (*p++ == 0x53) ? 2 : 0; break; |
|
772 |
- case 2: state = (*p++ == 0x43) ? 3 : 0; break; |
|
773 |
- case 3: state = (*p++ == 0x46) ? 4 : 0; break; |
|
774 |
- |
|
775 |
- /* we don't care about bytes 4-7 (see default: for action) */ |
|
776 |
- |
|
777 |
- /* bytes 8-11 are the overall length of the cabinet */ |
|
778 |
- case 8: cablen = *p++; state++; break; |
|
779 |
- case 9: cablen |= *p++ << 8; state++; break; |
|
780 |
- case 10: cablen |= *p++ << 16; state++; break; |
|
781 |
- case 11: cablen |= *p++ << 24; state++; break; |
|
782 |
- |
|
783 |
- /* we don't care about bytes 12-15 (see default: for action) */ |
|
784 |
- |
|
785 |
- /* bytes 16-19 are the offset within the cabinet of the filedata */ |
|
786 |
- case 16: foffset = *p++; state++; break; |
|
787 |
- case 17: foffset |= *p++ << 8; state++; break; |
|
788 |
- case 18: foffset |= *p++ << 16; state++; break; |
|
789 |
- case 19: foffset |= *p++ << 24; |
|
790 |
- /* now we have recieved 20 bytes of potential cab header. work out |
|
791 |
- * the offset in the file of this potential cabinet */ |
|
792 |
- caboff = offset + (p - &buf[0]) - 20; |
|
793 |
- |
|
794 |
- /* should reading cabinet fail, restart search just after 'MSCF' */ |
|
795 |
- offset = caboff + 4; |
|
796 |
- |
|
797 |
- /* capture the "length of cabinet" field if there is a cabinet at |
|
798 |
- * offset 0 in the file, regardless of whether the cabinet can be |
|
799 |
- * read correctly or not */ |
|
800 |
- if (caboff == 0) *firstlen = cablen; |
|
801 |
- |
|
802 |
- /* check that the files offset is less than the alleged length of |
|
803 |
- * the cabinet, and that the offset + the alleged length are |
|
804 |
- * 'roughly' within the end of overall file length */ |
|
805 |
- if ((foffset < cablen) && |
|
806 |
- ((caboff + foffset) < (flen + 32)) && |
|
807 |
- ((caboff + cablen) < (flen + 32)) ) |
|
808 |
- { |
|
809 |
- /* likely cabinet found -- try reading it */ |
|
810 |
- if (!(cab = sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) { |
|
811 |
- return MSPACK_ERR_NOMEMORY; |
|
812 |
- } |
|
813 |
- cab->base.filename = filename; |
|
814 |
- cab->base.desc = desc; |
|
815 |
- if (cabd_read_headers(sys, fh, cab, caboff, 1)) { |
|
816 |
- /* destroy the failed cabinet */ |
|
817 |
- cabd_close((struct mscab_decompressor *) this, |
|
818 |
- (struct mscabd_cabinet *) cab); |
|
819 |
- false_cabs++; |
|
820 |
- } |
|
821 |
- else { |
|
822 |
- /* cabinet read correctly! */ |
|
823 |
- |
|
824 |
- /* cause the search to restart after this cab's data. */ |
|
825 |
- offset = caboff + cablen; |
|
826 |
- |
|
827 |
- /* link the cab into the list */ |
|
828 |
- if (!link) *firstcab = cab; |
|
829 |
- else link->base.next = (struct mscabd_cabinet *) cab; |
|
830 |
- link = cab; |
|
831 |
- } |
|
832 |
- } |
|
833 |
- |
|
834 |
- /* restart search */ |
|
835 |
- if (offset >= flen) return MSPACK_ERR_OK; |
|
836 |
- if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) |
|
837 |
- return MSPACK_ERR_SEEK; |
|
838 |
- length = 0; |
|
839 |
- p = pend; |
|
840 |
- state = 0; |
|
841 |
- break; |
|
842 |
- |
|
843 |
- /* for bytes 4-7 and 12-15, just advance state/pointer */ |
|
844 |
- default: |
|
845 |
- p++, state++; |
|
846 |
- } /* switch(state) */ |
|
847 |
- } /* for (... p < pend ...) */ |
|
848 |
- } /* for (... offset < length ...) */ |
|
849 |
- |
|
850 |
- if (false_cabs) { |
|
851 |
- D(("%d false cabinets found", false_cabs)) |
|
852 |
- } |
|
853 |
- |
|
854 |
- return MSPACK_ERR_OK; |
|
855 |
-} |
|
856 |
- |
|
857 |
-/*************************************** |
|
858 |
- * CABD_MERGE, CABD_PREPEND, CABD_APPEND |
|
859 |
- *************************************** |
|
860 |
- * joins cabinets together, also merges split folders between these two |
|
861 |
- * cabinets only. this includes freeing the duplicate folder and file(s) |
|
862 |
- * and allocating a further mscabd_folder_data structure to append to the |
|
863 |
- * merged folder's data parts list. |
|
864 |
- */ |
|
865 |
-static int cabd_prepend(struct mscab_decompressor *base, |
|
866 |
- struct mscabd_cabinet *cab, |
|
867 |
- struct mscabd_cabinet *prevcab) |
|
868 |
-{ |
|
869 |
- return cabd_merge(base, prevcab, cab); |
|
870 |
-} |
|
871 |
- |
|
872 |
-static int cabd_append(struct mscab_decompressor *base, |
|
873 |
- struct mscabd_cabinet *cab, |
|
874 |
- struct mscabd_cabinet *nextcab) |
|
875 |
-{ |
|
876 |
- return cabd_merge(base, cab, nextcab); |
|
877 |
-} |
|
878 |
- |
|
879 |
-static int cabd_merge(struct mscab_decompressor *base, |
|
880 |
- struct mscabd_cabinet *lcab, |
|
881 |
- struct mscabd_cabinet *rcab) |
|
882 |
-{ |
|
883 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
884 |
- struct mscabd_folder_data *data, *ndata; |
|
885 |
- struct mscabd_folder_p *lfol, *rfol; |
|
886 |
- struct mscabd_file *fi, *rfi, *lfi; |
|
887 |
- struct mscabd_cabinet *cab; |
|
888 |
- struct mspack_system *sys; |
|
889 |
- |
|
890 |
- if (!this) return MSPACK_ERR_ARGS; |
|
891 |
- sys = this->system; |
|
892 |
- |
|
893 |
- /* basic args check */ |
|
894 |
- if (!lcab || !rcab || (lcab == rcab)) { |
|
895 |
- D(("lcab NULL, rcab NULL or lcab = rcab")) |
|
896 |
- return this->error = MSPACK_ERR_ARGS; |
|
897 |
- } |
|
898 |
- |
|
899 |
- /* check there's not already a cabinet attached */ |
|
900 |
- if (lcab->nextcab || rcab->prevcab) { |
|
901 |
- D(("cabs already joined")) |
|
902 |
- return this->error = MSPACK_ERR_ARGS; |
|
903 |
- } |
|
904 |
- |
|
905 |
- /* do not create circular cabinet chains */ |
|
906 |
- for (cab = lcab->prevcab; cab; cab = cab->prevcab) { |
|
907 |
- if (cab == rcab) {D(("circular!")) return this->error = MSPACK_ERR_ARGS;} |
|
908 |
- } |
|
909 |
- for (cab = rcab->nextcab; cab; cab = cab->nextcab) { |
|
910 |
- if (cab == lcab) {D(("circular!")) return this->error = MSPACK_ERR_ARGS;} |
|
911 |
- } |
|
912 |
- |
|
913 |
- /* warn about odd set IDs or indices */ |
|
914 |
- if (lcab->set_id != rcab->set_id) { |
|
915 |
- sys->message(NULL, "WARNING; merged cabinets with differing Set IDs."); |
|
916 |
- } |
|
917 |
- |
|
918 |
- if (lcab->set_index > rcab->set_index) { |
|
919 |
- sys->message(NULL, "WARNING; merged cabinets with odd order."); |
|
920 |
- } |
|
921 |
- |
|
922 |
- /* merging the last folder in lcab with the first folder in rcab */ |
|
923 |
- lfol = (struct mscabd_folder_p *) lcab->folders; |
|
924 |
- rfol = (struct mscabd_folder_p *) rcab->folders; |
|
925 |
- while (lfol->base.next) lfol = (struct mscabd_folder_p *) lfol->base.next; |
|
926 |
- |
|
927 |
- /* do we need to merge folders? */ |
|
928 |
- if (!lfol->merge_next && !rfol->merge_prev) { |
|
929 |
- /* no, at least one of the folders is not for merging */ |
|
930 |
- |
|
931 |
- /* attach cabs */ |
|
932 |
- lcab->nextcab = rcab; |
|
933 |
- rcab->prevcab = lcab; |
|
934 |
- |
|
935 |
- /* attach folders */ |
|
936 |
- lfol->base.next = (struct mscabd_folder *) rfol; |
|
937 |
- |
|
938 |
- /* attach files */ |
|
939 |
- fi = lcab->files; |
|
940 |
- while (fi->next) fi = fi->next; |
|
941 |
- fi->next = rcab->files; |
|
942 |
- } |
|
943 |
- else { |
|
944 |
- /* folder merge required */ |
|
945 |
- |
|
946 |
- if (!lfol->merge_next) { |
|
947 |
- D(("rcab has merge files, lcab doesn't")) |
|
948 |
- return this->error = MSPACK_ERR_DATAFORMAT; |
|
949 |
- } |
|
950 |
- |
|
951 |
- if (!rfol->merge_prev) { |
|
952 |
- D(("lcab has merge files, rcab doesn't")) |
|
953 |
- return this->error = MSPACK_ERR_DATAFORMAT; |
|
954 |
- } |
|
955 |
- |
|
956 |
- /* check that both folders use the same compression method/settings */ |
|
957 |
- if (lfol->base.comp_type != rfol->base.comp_type) { |
|
958 |
- D(("compression type mismatch")) |
|
959 |
- return this->error = MSPACK_ERR_DATAFORMAT; |
|
960 |
- } |
|
961 |
- |
|
962 |
- /* for all files in lfol (which is the last folder in whichever cab), |
|
963 |
- * compare them to the files from rfol. they should be identical in |
|
964 |
- * number and order. to verify this, check the OFFSETS of each file. */ |
|
965 |
- lfi = lfol->merge_next; |
|
966 |
- rfi = rfol->merge_prev; |
|
967 |
- while (lfi) { |
|
968 |
- if (!rfi || (lfi->offset != rfi->offset)) { |
|
969 |
- D(("folder merge mismatch")) |
|
970 |
- return this->error = MSPACK_ERR_DATAFORMAT; |
|
971 |
- } |
|
972 |
- lfi = lfi->next; |
|
973 |
- rfi = rfi->next; |
|
974 |
- } |
|
975 |
- |
|
976 |
- /* allocate a new folder data structure */ |
|
977 |
- if (!(data = sys->alloc(sys, sizeof(struct mscabd_folder_data)))) { |
|
978 |
- return this->error = MSPACK_ERR_NOMEMORY; |
|
979 |
- } |
|
980 |
- |
|
981 |
- /* attach cabs */ |
|
982 |
- lcab->nextcab = rcab; |
|
983 |
- rcab->prevcab = lcab; |
|
984 |
- |
|
985 |
- /* append rfol's data to lfol */ |
|
986 |
- ndata = &lfol->data; |
|
987 |
- while (ndata->next) ndata = ndata->next; |
|
988 |
- ndata->next = data; |
|
989 |
- *data = rfol->data; |
|
990 |
- rfol->data.next = NULL; |
|
991 |
- |
|
992 |
- /* lfol becomes rfol. |
|
993 |
- * NOTE: special case, don't merge if rfol is merge prev and next, |
|
994 |
- * rfol->merge_next is going to be deleted, so keep lfol's version |
|
995 |
- * instead */ |
|
996 |
- lfol->base.num_blocks += rfol->base.num_blocks - 1; |
|
997 |
- if ((rfol->merge_next == NULL) || |
|
998 |
- (rfol->merge_next->folder != (struct mscabd_folder *) rfol)) |
|
999 |
- { |
|
1000 |
- lfol->merge_next = rfol->merge_next; |
|
1001 |
- } |
|
1002 |
- |
|
1003 |
- /* attach the rfol's folder (except the merge folder) */ |
|
1004 |
- while (lfol->base.next) lfol = (struct mscabd_folder_p *) lfol->base.next; |
|
1005 |
- lfol->base.next = rfol->base.next; |
|
1006 |
- |
|
1007 |
- /* free disused merge folder */ |
|
1008 |
- sys->free(rfol); |
|
1009 |
- |
|
1010 |
- /* attach rfol's files */ |
|
1011 |
- fi = lcab->files; |
|
1012 |
- while (fi->next) fi = fi->next; |
|
1013 |
- fi->next = rcab->files; |
|
1014 |
- |
|
1015 |
- /* delete all files from rfol's merge folder */ |
|
1016 |
- lfi = NULL; |
|
1017 |
- for (fi = lcab->files; fi ; fi = rfi) { |
|
1018 |
- rfi = fi->next; |
|
1019 |
- /* if file's folder matches the merge folder, unlink and free it */ |
|
1020 |
- if (fi->folder == (struct mscabd_folder *) rfol) { |
|
1021 |
- if (lfi) lfi->next = rfi; else lcab->files = rfi; |
|
1022 |
- sys->free(fi->filename); |
|
1023 |
- sys->free(fi); |
|
1024 |
- } |
|
1025 |
- else lfi = fi; |
|
1026 |
- } |
|
1027 |
- } |
|
1028 |
- |
|
1029 |
- /* all done! fix files and folders pointers in all cabs so they all |
|
1030 |
- * point to the same list */ |
|
1031 |
- for (cab = lcab->prevcab; cab; cab = cab->prevcab) { |
|
1032 |
- cab->files = lcab->files; |
|
1033 |
- cab->folders = lcab->folders; |
|
1034 |
- } |
|
1035 |
- |
|
1036 |
- for (cab = lcab->nextcab; cab; cab = cab->nextcab) { |
|
1037 |
- cab->files = lcab->files; |
|
1038 |
- cab->folders = lcab->folders; |
|
1039 |
- } |
|
1040 |
- |
|
1041 |
- return this->error = MSPACK_ERR_OK; |
|
1042 |
-} |
|
1043 |
- |
|
1044 |
-/*************************************** |
|
1045 |
- * CABD_EXTRACT |
|
1046 |
- *************************************** |
|
1047 |
- * extracts a file from a cabinet |
|
1048 |
- */ |
|
1049 |
-static int cabd_extract(struct mscab_decompressor *base, |
|
1050 |
- struct mscabd_file *file, char *filename) |
|
1051 |
-{ |
|
1052 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
1053 |
- struct mscabd_folder_p *fol; |
|
1054 |
- struct mspack_system *sys; |
|
1055 |
- struct mspack_file *fh; |
|
1056 |
- |
|
1057 |
- if (!this) return MSPACK_ERR_ARGS; |
|
1058 |
- if (!file) return this->error = MSPACK_ERR_ARGS; |
|
1059 |
- |
|
1060 |
- sys = this->system; |
|
1061 |
- fol = (struct mscabd_folder_p *) file->folder; |
|
1062 |
- |
|
1063 |
- /* check if file can be extracted */ |
|
1064 |
- if ((!fol) || (fol->merge_prev) || |
|
1065 |
- (((file->offset + file->length) / CAB_BLOCKMAX) > fol->base.num_blocks)) |
|
1066 |
- { |
|
1067 |
- sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, " |
|
1068 |
- "cabinet set is incomplete.", file->filename); |
|
1069 |
- return this->error = MSPACK_ERR_DATAFORMAT; |
|
1070 |
- } |
|
1071 |
- |
|
1072 |
- /* allocate generic decompression state */ |
|
1073 |
- if (!this->d) { |
|
1074 |
- this->d = sys->alloc(sys, sizeof(struct mscabd_decompress_state)); |
|
1075 |
- if (!this->d) return this->error = MSPACK_ERR_NOMEMORY; |
|
1076 |
- this->d->folder = NULL; |
|
1077 |
- this->d->data = NULL; |
|
1078 |
- this->d->sys = *sys; |
|
1079 |
- this->d->sys.read = &cabd_sys_read; |
|
1080 |
- this->d->sys.write = &cabd_sys_write; |
|
1081 |
- this->d->state = NULL; |
|
1082 |
- this->d->infh = NULL; |
|
1083 |
- this->d->incab = NULL; |
|
1084 |
- } |
|
1085 |
- |
|
1086 |
- /* do we need to change folder or reset the current folder? */ |
|
1087 |
- if ((this->d->folder != fol) || (this->d->offset > file->offset)) { |
|
1088 |
- /* do we need to open a new cab file? */ |
|
1089 |
- |
|
1090 |
- if (!this->d->infh || (fol->data.cab != this->d->incab)) { |
|
1091 |
- if (this->d->infh) sys->close(this->d->infh); |
|
1092 |
- this->d->incab = fol->data.cab; |
|
1093 |
- |
|
1094 |
- if(fol->data.cab->base.desc) { |
|
1095 |
- this->d->infh = sys->dopen(sys, fol->data.cab->base.desc, |
|
1096 |
- MSPACK_SYS_OPEN_READ); |
|
1097 |
- } else { |
|
1098 |
- this->d->infh = sys->open(sys, fol->data.cab->base.filename, |
|
1099 |
- MSPACK_SYS_OPEN_READ); |
|
1100 |
- } |
|
1101 |
- if (!this->d->infh) return this->error = MSPACK_ERR_OPEN; |
|
1102 |
- } |
|
1103 |
- |
|
1104 |
- /* seek to start of data blocks */ |
|
1105 |
- if (sys->seek(this->d->infh, fol->data.offset, MSPACK_SYS_SEEK_START)) { |
|
1106 |
- return this->error = MSPACK_ERR_SEEK; |
|
1107 |
- } |
|
1108 |
- |
|
1109 |
- /* set up decompressor */ |
|
1110 |
- if (cabd_init_decomp(this, (unsigned int) fol->base.comp_type)) { |
|
1111 |
- return this->error; |
|
1112 |
- } |
|
1113 |
- |
|
1114 |
- /* initialise new folder state */ |
|
1115 |
- this->d->folder = fol; |
|
1116 |
- this->d->data = &fol->data; |
|
1117 |
- this->d->offset = 0; |
|
1118 |
- this->d->block = 0; |
|
1119 |
- this->d->i_ptr = this->d->i_end = &this->d->input[0]; |
|
1120 |
- } |
|
1121 |
- |
|
1122 |
- /* open file for output */ |
|
1123 |
- if (!(fh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) { |
|
1124 |
- return this->error = MSPACK_ERR_OPEN; |
|
1125 |
- } |
|
1126 |
- |
|
1127 |
- this->error = MSPACK_ERR_OK; |
|
1128 |
- |
|
1129 |
- /* if file has more than 0 bytes */ |
|
1130 |
- if (file->length) { |
|
1131 |
- off_t bytes; |
|
1132 |
- int error; |
|
1133 |
- /* get to correct offset. |
|
1134 |
- * - use NULL fh to say 'no writing' to cabd_sys_write() |
|
1135 |
- * - MSPACK_ERR_READ returncode indicates error in cabd_sys_read(), |
|
1136 |
- * the real error will already be stored in this->error |
|
1137 |
- */ |
|
1138 |
- this->d->outfh = NULL; |
|
1139 |
- if ((bytes = file->offset - this->d->offset)) { |
|
1140 |
- error = this->d->decompress(this->d->state, bytes); |
|
1141 |
- if (error != MSPACK_ERR_READ) this->error = error; |
|
1142 |
- } |
|
1143 |
- |
|
1144 |
- /* if getting to the correct offset was error free, unpack file */ |
|
1145 |
- if (!this->error) { |
|
1146 |
- this->d->outfh = fh; |
|
1147 |
- error = this->d->decompress(this->d->state, (off_t) file->length); |
|
1148 |
- if (error != MSPACK_ERR_READ) this->error = error; |
|
1149 |
- } |
|
1150 |
- } |
|
1151 |
- |
|
1152 |
- /* close output file */ |
|
1153 |
- sys->close(fh); |
|
1154 |
- this->d->outfh = NULL; |
|
1155 |
- |
|
1156 |
- return this->error; |
|
1157 |
-} |
|
1158 |
- |
|
1159 |
-/*************************************** |
|
1160 |
- * CABD_INIT_DECOMP, CABD_FREE_DECOMP |
|
1161 |
- *************************************** |
|
1162 |
- * cabd_init_decomp initialises decompression state, according to which |
|
1163 |
- * decompression method was used. relies on this->d->folder being the same |
|
1164 |
- * as when initialised. |
|
1165 |
- * |
|
1166 |
- * cabd_free_decomp frees decompression state, according to which method |
|
1167 |
- * was used. |
|
1168 |
- */ |
|
1169 |
-static int cabd_init_decomp(struct mscab_decompressor_p *this, unsigned int ct) |
|
1170 |
-{ |
|
1171 |
- struct mspack_file *fh = (struct mspack_file *) this; |
|
1172 |
- |
|
1173 |
- if (!this || !this->d) { |
|
1174 |
- return this->error = MSPACK_ERR_ARGS; |
|
1175 |
- } |
|
1176 |
- |
|
1177 |
- /* free any existing decompressor */ |
|
1178 |
- cabd_free_decomp(this); |
|
1179 |
- |
|
1180 |
- this->d->comp_type = ct; |
|
1181 |
- |
|
1182 |
- switch (ct & cffoldCOMPTYPE_MASK) { |
|
1183 |
- case cffoldCOMPTYPE_NONE: |
|
1184 |
- this->d->decompress = (int (*)(void *, off_t)) &noned_decompress; |
|
1185 |
- this->d->state = noned_init(&this->d->sys, fh, fh, |
|
1186 |
- this->param[MSCABD_PARAM_DECOMPBUF]); |
|
1187 |
- break; |
|
1188 |
- case cffoldCOMPTYPE_MSZIP: |
|
1189 |
- this->d->decompress = (int (*)(void *, off_t)) &mszipd_decompress; |
|
1190 |
- this->d->state = mszipd_init(&this->d->sys, fh, fh, |
|
1191 |
- this->param[MSCABD_PARAM_DECOMPBUF], |
|
1192 |
- this->param[MSCABD_PARAM_FIXMSZIP]); |
|
1193 |
- break; |
|
1194 |
- case cffoldCOMPTYPE_QUANTUM: |
|
1195 |
- this->d->decompress = (int (*)(void *, off_t)) &qtmd_decompress; |
|
1196 |
- this->d->state = qtmd_init(&this->d->sys, fh, fh, (int) (ct >> 8) & 0x1f, |
|
1197 |
- this->param[MSCABD_PARAM_DECOMPBUF]); |
|
1198 |
- break; |
|
1199 |
- case cffoldCOMPTYPE_LZX: |
|
1200 |
- this->d->decompress = (int (*)(void *, off_t)) &lzxd_decompress; |
|
1201 |
- this->d->state = lzxd_init(&this->d->sys, fh, fh, (int) (ct >> 8) & 0x1f, 0, |
|
1202 |
- this->param[MSCABD_PARAM_DECOMPBUF], (off_t) 0); |
|
1203 |
- break; |
|
1204 |
- default: |
|
1205 |
- return this->error = MSPACK_ERR_DATAFORMAT; |
|
1206 |
- } |
|
1207 |
- return this->error = (this->d->state) ? MSPACK_ERR_OK : MSPACK_ERR_NOMEMORY; |
|
1208 |
-} |
|
1209 |
- |
|
1210 |
-static void cabd_free_decomp(struct mscab_decompressor_p *this) { |
|
1211 |
- if (!this || !this->d || !this->d->folder || !this->d->state) return; |
|
1212 |
- |
|
1213 |
- switch (this->d->comp_type & cffoldCOMPTYPE_MASK) { |
|
1214 |
- case cffoldCOMPTYPE_NONE: noned_free(this->d->state); break; |
|
1215 |
- case cffoldCOMPTYPE_MSZIP: mszipd_free(this->d->state); break; |
|
1216 |
- case cffoldCOMPTYPE_QUANTUM: qtmd_free(this->d->state); break; |
|
1217 |
- case cffoldCOMPTYPE_LZX: lzxd_free(this->d->state); break; |
|
1218 |
- } |
|
1219 |
- this->d->decompress = NULL; |
|
1220 |
- this->d->state = NULL; |
|
1221 |
-} |
|
1222 |
- |
|
1223 |
-/*************************************** |
|
1224 |
- * CABD_SYS_READ, CABD_SYS_WRITE |
|
1225 |
- *************************************** |
|
1226 |
- * cabd_sys_read is the internal reader function which the decompressors |
|
1227 |
- * use. will read data blocks (and merge split blocks) from the cabinet |
|
1228 |
- * and serve the read bytes to the decompressors |
|
1229 |
- * |
|
1230 |
- * cabd_sys_write is the internal writer function which the decompressors |
|
1231 |
- * use. it either writes data to disk (this->d->outfh) with the real |
|
1232 |
- * sys->write() function, or does nothing with the data when |
|
1233 |
- * this->d->outfh == NULL. advances this->d->offset |
|
1234 |
- */ |
|
1235 |
-static int cabd_sys_read(struct mspack_file *file, void *buffer, int bytes) { |
|
1236 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) file; |
|
1237 |
- unsigned char *buf = (unsigned char *) buffer; |
|
1238 |
- struct mspack_system *sys = this->system; |
|
1239 |
- int avail, todo, outlen, ignore_cksum; |
|
1240 |
- |
|
1241 |
- ignore_cksum = this->param[MSCABD_PARAM_FIXMSZIP] && |
|
1242 |
- ((this->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_MSZIP); |
|
1243 |
- |
|
1244 |
- todo = bytes; |
|
1245 |
- while (todo > 0) { |
|
1246 |
- avail = this->d->i_end - this->d->i_ptr; |
|
1247 |
- |
|
1248 |
- /* if out of input data, read a new block */ |
|
1249 |
- if (avail) { |
|
1250 |
- /* copy as many input bytes available as possible */ |
|
1251 |
- if (avail > todo) avail = todo; |
|
1252 |
- sys->copy(this->d->i_ptr, buf, (size_t) avail); |
|
1253 |
- this->d->i_ptr += avail; |
|
1254 |
- buf += avail; |
|
1255 |
- todo -= avail; |
|
1256 |
- } |
|
1257 |
- else { |
|
1258 |
- /* out of data, read a new block */ |
|
1259 |
- |
|
1260 |
- /* check if we're out of input blocks, advance block counter */ |
|
1261 |
- if (this->d->block++ >= this->d->folder->base.num_blocks) { |
|
1262 |
- this->error = MSPACK_ERR_DATAFORMAT; |
|
1263 |
- break; |
|
1264 |
- } |
|
1265 |
- |
|
1266 |
- /* read a block */ |
|
1267 |
- this->error = cabd_sys_read_block(sys, this->d, &outlen, ignore_cksum); |
|
1268 |
- if (this->error) return -1; |
|
1269 |
- |
|
1270 |
- /* special Quantum hack -- trailer byte to allow the decompressor |
|
1271 |
- * to realign itself. CAB Quantum blocks, unlike LZX blocks, can have |
|
1272 |
- * anything from 0 to 4 trailing null bytes. */ |
|
1273 |
- if ((this->d->comp_type & cffoldCOMPTYPE_MASK)==cffoldCOMPTYPE_QUANTUM) { |
|
1274 |
- *this->d->i_end++ = 0xFF; |
|
1275 |
- } |
|
1276 |
- |
|
1277 |
- /* is this the last block? */ |
|
1278 |
- if (this->d->block >= this->d->folder->base.num_blocks) { |
|
1279 |
- /* last block */ |
|
1280 |
- if ((this->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_LZX) { |
|
1281 |
- /* special LZX hack -- on the last block, inform LZX of the |
|
1282 |
- * size of the output data stream. */ |
|
1283 |
- lzxd_set_output_length(this->d->state, (off_t) |
|
1284 |
- ((this->d->block-1) * CAB_BLOCKMAX + outlen)); |
|
1285 |
- } |
|
1286 |
- } |
|
1287 |
- else { |
|
1288 |
- /* not the last block */ |
|
1289 |
- if (outlen != CAB_BLOCKMAX) { |
|
1290 |
- this->system->message(this->d->infh, |
|
1291 |
- "WARNING; non-maximal data block"); |
|
1292 |
- } |
|
1293 |
- } |
|
1294 |
- } /* if (avail) */ |
|
1295 |
- } /* while (todo > 0) */ |
|
1296 |
- return bytes - todo; |
|
1297 |
-} |
|
1298 |
- |
|
1299 |
-static int cabd_sys_write(struct mspack_file *file, void *buffer, int bytes) { |
|
1300 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) file; |
|
1301 |
- this->d->offset += bytes; |
|
1302 |
- if (this->d->outfh) { |
|
1303 |
- return this->system->write(this->d->outfh, buffer, bytes); |
|
1304 |
- } |
|
1305 |
- return bytes; |
|
1306 |
-} |
|
1307 |
- |
|
1308 |
-/*************************************** |
|
1309 |
- * CABD_SYS_READ_BLOCK |
|
1310 |
- *************************************** |
|
1311 |
- * reads a whole data block from a cab file. the block may span more than |
|
1312 |
- * one cab file, if it does then the fragments will be reassembled |
|
1313 |
- */ |
|
1314 |
-static int cabd_sys_read_block(struct mspack_system *sys, |
|
1315 |
- struct mscabd_decompress_state *d, |
|
1316 |
- int *out, int ignore_cksum) |
|
1317 |
-{ |
|
1318 |
- unsigned char hdr[cfdata_SIZEOF]; |
|
1319 |
- unsigned int cksum; |
|
1320 |
- int len; |
|
1321 |
- |
|
1322 |
- /* reset the input block pointer and end of block pointer */ |
|
1323 |
- d->i_ptr = d->i_end = &d->input[0]; |
|
1324 |
- |
|
1325 |
- do { |
|
1326 |
- /* read the block header */ |
|
1327 |
- if (sys->read(d->infh, &hdr[0], cfdata_SIZEOF) != cfdata_SIZEOF) { |
|
1328 |
- return MSPACK_ERR_READ; |
|
1329 |
- } |
|
1330 |
- |
|
1331 |
- /* skip any reserved block headers */ |
|
1332 |
- if (d->data->cab->block_resv && |
|
1333 |
- sys->seek(d->infh, (off_t) d->data->cab->block_resv, |
|
1334 |
- MSPACK_SYS_SEEK_CUR)) |
|
1335 |
- { |
|
1336 |
- return MSPACK_ERR_SEEK; |
|
1337 |
- } |
|
1338 |
- |
|
1339 |
- /* blocks must not be over CAB_INPUTMAX in size */ |
|
1340 |
- len = EndGetI16(&hdr[cfdata_CompressedSize]); |
|
1341 |
- if (((d->i_end - d->i_ptr) + len) > CAB_INPUTMAX) { |
|
1342 |
- D(("block size > CAB_INPUTMAX (%d + %d)", d->i_end - d->i_ptr, len)) |
|
1343 |
- return MSPACK_ERR_DATAFORMAT; |
|
1344 |
- } |
|
1345 |
- |
|
1346 |
- /* blocks must not expand to more than CAB_BLOCKMAX */ |
|
1347 |
- if (EndGetI16(&hdr[cfdata_UncompressedSize]) > CAB_BLOCKMAX) { |
|
1348 |
- D(("block size > CAB_BLOCKMAX")) |
|
1349 |
- return MSPACK_ERR_DATAFORMAT; |
|
1350 |
- } |
|
1351 |
- |
|
1352 |
- /* read the block data */ |
|
1353 |
- if (sys->read(d->infh, d->i_end, len) != len) { |
|
1354 |
- return MSPACK_ERR_READ; |
|
1355 |
- } |
|
1356 |
- |
|
1357 |
- /* perform checksum test on the block (if one is stored) */ |
|
1358 |
- if ((cksum = EndGetI32(&hdr[cfdata_CheckSum]))) { |
|
1359 |
- unsigned int sum2 = cabd_checksum(d->i_end, (unsigned int) len, 0); |
|
1360 |
- if (cabd_checksum(&hdr[4], 4, sum2) != cksum) { |
|
1361 |
- if (!ignore_cksum) return MSPACK_ERR_CHECKSUM; |
|
1362 |
- sys->message(d->infh, "WARNING; bad block checksum found"); |
|
1363 |
- } |
|
1364 |
- } |
|
1365 |
- |
|
1366 |
- /* advance end of block pointer to include newly read data */ |
|
1367 |
- d->i_end += len; |
|
1368 |
- |
|
1369 |
- /* uncompressed size == 0 means this block was part of a split block |
|
1370 |
- * and it continues as the first block of the next cabinet in the set. |
|
1371 |
- * otherwise, this is the last part of the block, and no more block |
|
1372 |
- * reading needs to be done. |
|
1373 |
- */ |
|
1374 |
- /* EXIT POINT OF LOOP -- uncompressed size != 0 */ |
|
1375 |
- if ((*out = EndGetI16(&hdr[cfdata_UncompressedSize]))) { |
|
1376 |
- return MSPACK_ERR_OK; |
|
1377 |
- } |
|
1378 |
- |
|
1379 |
- /* otherwise, advance to next cabinet */ |
|
1380 |
- |
|
1381 |
- /* close current file handle */ |
|
1382 |
- sys->close(d->infh); |
|
1383 |
- d->infh = NULL; |
|
1384 |
- |
|
1385 |
- /* advance to next member in the cabinet set */ |
|
1386 |
- if (!(d->data = d->data->next)) { |
|
1387 |
- D(("ran out of splits in cabinet set")) |
|
1388 |
- return MSPACK_ERR_DATAFORMAT; |
|
1389 |
- } |
|
1390 |
- |
|
1391 |
- /* open next cab file */ |
|
1392 |
- d->incab = d->data->cab; |
|
1393 |
- if (!(d->infh = sys->open(sys, d->incab->base.filename, |
|
1394 |
- MSPACK_SYS_OPEN_READ))) |
|
1395 |
- { |
|
1396 |
- return MSPACK_ERR_OPEN; |
|
1397 |
- } |
|
1398 |
- |
|
1399 |
- /* seek to start of data blocks */ |
|
1400 |
- if (sys->seek(d->infh, d->data->offset, MSPACK_SYS_SEEK_START)) { |
|
1401 |
- return MSPACK_ERR_SEEK; |
|
1402 |
- } |
|
1403 |
- } while (1); |
|
1404 |
- |
|
1405 |
- /* not reached */ |
|
1406 |
- return MSPACK_ERR_OK; |
|
1407 |
-} |
|
1408 |
- |
|
1409 |
-static unsigned int cabd_checksum(unsigned char *data, unsigned int bytes, |
|
1410 |
- unsigned int cksum) |
|
1411 |
-{ |
|
1412 |
- unsigned int len, ul = 0; |
|
1413 |
- |
|
1414 |
- for (len = bytes >> 2; len--; data += 4) { |
|
1415 |
- cksum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24)); |
|
1416 |
- } |
|
1417 |
- |
|
1418 |
- switch (bytes & 3) { |
|
1419 |
- case 3: ul |= *data++ << 16; |
|
1420 |
- case 2: ul |= *data++ << 8; |
|
1421 |
- case 1: ul |= *data; |
|
1422 |
- } |
|
1423 |
- cksum ^= ul; |
|
1424 |
- |
|
1425 |
- return cksum; |
|
1426 |
-} |
|
1427 |
- |
|
1428 |
-/*************************************** |
|
1429 |
- * NONED_INIT, NONED_DECOMPRESS, NONED_FREE |
|
1430 |
- *************************************** |
|
1431 |
- * the "not compressed" method decompressor |
|
1432 |
- */ |
|
1433 |
-struct noned_state { |
|
1434 |
- struct mspack_system *sys; |
|
1435 |
- struct mspack_file *i; |
|
1436 |
- struct mspack_file *o; |
|
1437 |
- unsigned char *buf; |
|
1438 |
- int bufsize; |
|
1439 |
-}; |
|
1440 |
- |
|
1441 |
-static struct noned_state *noned_init(struct mspack_system *sys, |
|
1442 |
- struct mspack_file *in, |
|
1443 |
- struct mspack_file *out, |
|
1444 |
- int bufsize) |
|
1445 |
-{ |
|
1446 |
- struct noned_state *state = sys->alloc(sys, sizeof(struct noned_state)); |
|
1447 |
- unsigned char *buf = sys->alloc(sys, (size_t) bufsize); |
|
1448 |
- if (state && buf) { |
|
1449 |
- state->sys = sys; |
|
1450 |
- state->i = in; |
|
1451 |
- state->o = out; |
|
1452 |
- state->buf = buf; |
|
1453 |
- state->bufsize = bufsize; |
|
1454 |
- } |
|
1455 |
- else { |
|
1456 |
- sys->free(buf); |
|
1457 |
- sys->free(state); |
|
1458 |
- state = NULL; |
|
1459 |
- } |
|
1460 |
- return state; |
|
1461 |
-} |
|
1462 |
- |
|
1463 |
-static int noned_decompress(struct noned_state *s, off_t bytes) { |
|
1464 |
- int run; |
|
1465 |
- while (bytes > 0) { |
|
1466 |
- run = (bytes > s->bufsize) ? s->bufsize : (int) bytes; |
|
1467 |
- if (s->sys->read(s->i, &s->buf[0], run) != run) return MSPACK_ERR_READ; |
|
1468 |
- if (s->sys->write(s->o, &s->buf[0], run) != run) return MSPACK_ERR_WRITE; |
|
1469 |
- bytes -= run; |
|
1470 |
- } |
|
1471 |
- return MSPACK_ERR_OK; |
|
1472 |
-} |
|
1473 |
- |
|
1474 |
-static void noned_free(struct noned_state *state) { |
|
1475 |
- struct mspack_system *sys; |
|
1476 |
- if (state) { |
|
1477 |
- sys = state->sys; |
|
1478 |
- sys->free(state->buf); |
|
1479 |
- sys->free(state); |
|
1480 |
- } |
|
1481 |
-} |
|
1482 |
- |
|
1483 |
- |
|
1484 |
-/*************************************** |
|
1485 |
- * CABD_PARAM |
|
1486 |
- *************************************** |
|
1487 |
- * allows a parameter to be set |
|
1488 |
- */ |
|
1489 |
-static int cabd_param(struct mscab_decompressor *base, int param, int value) { |
|
1490 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
1491 |
- if (!this) return MSPACK_ERR_ARGS; |
|
1492 |
- |
|
1493 |
- switch (param) { |
|
1494 |
- case MSCABD_PARAM_SEARCHBUF: |
|
1495 |
- if (value < 4) return MSPACK_ERR_ARGS; |
|
1496 |
- this->param[MSCABD_PARAM_SEARCHBUF] = value; |
|
1497 |
- break; |
|
1498 |
- case MSCABD_PARAM_FIXMSZIP: |
|
1499 |
- this->param[MSCABD_PARAM_FIXMSZIP] = value; |
|
1500 |
- break; |
|
1501 |
- case MSCABD_PARAM_DECOMPBUF: |
|
1502 |
- if (value < 4) return MSPACK_ERR_ARGS; |
|
1503 |
- this->param[MSCABD_PARAM_DECOMPBUF] = value; |
|
1504 |
- break; |
|
1505 |
- default: |
|
1506 |
- return MSPACK_ERR_ARGS; |
|
1507 |
- } |
|
1508 |
- return MSPACK_ERR_OK; |
|
1509 |
-} |
|
1510 |
- |
|
1511 |
-/*************************************** |
|
1512 |
- * CABD_ERROR |
|
1513 |
- *************************************** |
|
1514 |
- * returns the last error that occurred |
|
1515 |
- */ |
|
1516 |
-static int cabd_error(struct mscab_decompressor *base) { |
|
1517 |
- struct mscab_decompressor_p *this = (struct mscab_decompressor_p *) base; |
|
1518 |
- return (this) ? this->error : MSPACK_ERR_ARGS; |
|
1519 |
-} |
1520 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,167 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted |
|
5 |
- * by Microsoft Corporation. |
|
6 |
- * |
|
7 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
8 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
9 |
- * |
|
10 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
11 |
- */ |
|
12 |
- |
|
13 |
-#ifndef MSPACK_LZX_H |
|
14 |
-#define MSPACK_LZX_H 1 |
|
15 |
- |
|
16 |
-/* LZX compression / decompression definitions */ |
|
17 |
- |
|
18 |
-/* some constants defined by the LZX specification */ |
|
19 |
-#define LZX_MIN_MATCH (2) |
|
20 |
-#define LZX_MAX_MATCH (257) |
|
21 |
-#define LZX_NUM_CHARS (256) |
|
22 |
-#define LZX_BLOCKTYPE_INVALID (0) /* also blocktypes 4-7 invalid */ |
|
23 |
-#define LZX_BLOCKTYPE_VERBATIM (1) |
|
24 |
-#define LZX_BLOCKTYPE_ALIGNED (2) |
|
25 |
-#define LZX_BLOCKTYPE_UNCOMPRESSED (3) |
|
26 |
-#define LZX_PRETREE_NUM_ELEMENTS (20) |
|
27 |
-#define LZX_ALIGNED_NUM_ELEMENTS (8) /* aligned offset tree #elements */ |
|
28 |
-#define LZX_NUM_PRIMARY_LENGTHS (7) /* this one missing from spec! */ |
|
29 |
-#define LZX_NUM_SECONDARY_LENGTHS (249) /* length tree #elements */ |
|
30 |
- |
|
31 |
-/* LZX huffman defines: tweak tablebits as desired */ |
|
32 |
-#define LZX_PRETREE_MAXSYMBOLS (LZX_PRETREE_NUM_ELEMENTS) |
|
33 |
-#define LZX_PRETREE_TABLEBITS (6) |
|
34 |
-#define LZX_MAINTREE_MAXSYMBOLS (LZX_NUM_CHARS + 50*8) |
|
35 |
-#define LZX_MAINTREE_TABLEBITS (12) |
|
36 |
-#define LZX_LENGTH_MAXSYMBOLS (LZX_NUM_SECONDARY_LENGTHS+1) |
|
37 |
-#define LZX_LENGTH_TABLEBITS (12) |
|
38 |
-#define LZX_ALIGNED_MAXSYMBOLS (LZX_ALIGNED_NUM_ELEMENTS) |
|
39 |
-#define LZX_ALIGNED_TABLEBITS (7) |
|
40 |
-#define LZX_LENTABLE_SAFETY (64) /* table decoding overruns are allowed */ |
|
41 |
- |
|
42 |
-#define LZX_FRAME_SIZE (32768) /* the size of a frame in LZX */ |
|
43 |
- |
|
44 |
-struct lzxd_stream { |
|
45 |
- struct mspack_system *sys; /* I/O routines */ |
|
46 |
- struct mspack_file *input; /* input file handle */ |
|
47 |
- struct mspack_file *output; /* output file handle */ |
|
48 |
- |
|
49 |
- off_t offset; /* number of bytes actually output */ |
|
50 |
- off_t length; /* overall decompressed length of stream */ |
|
51 |
- |
|
52 |
- unsigned char *window; /* decoding window */ |
|
53 |
- unsigned int window_size; /* window size */ |
|
54 |
- unsigned int window_posn; /* decompression offset within window */ |
|
55 |
- unsigned int frame_posn; /* current frame offset within in window */ |
|
56 |
- unsigned int frame; /* the number of 32kb frames processed */ |
|
57 |
- unsigned int reset_interval; /* which frame do we reset the compressor? */ |
|
58 |
- |
|
59 |
- unsigned int R0, R1, R2; /* for the LRU offset system */ |
|
60 |
- unsigned int block_length; /* uncompressed length of this LZX block */ |
|
61 |
- unsigned int block_remaining; /* uncompressed bytes still left to decode */ |
|
62 |
- |
|
63 |
- signed int intel_filesize; /* magic header value used for transform */ |
|
64 |
- signed int intel_curpos; /* current offset in transform space */ |
|
65 |
- |
|
66 |
- unsigned char intel_started; /* has intel E8 decoding started? */ |
|
67 |
- unsigned char block_type; /* type of the current block */ |
|
68 |
- unsigned char header_read; /* have we started decoding at all yet? */ |
|
69 |
- unsigned char posn_slots; /* how many posn slots in stream? */ |
|
70 |
- unsigned char input_end; /* have we reached the end of input? */ |
|
71 |
- |
|
72 |
- int error; |
|
73 |
- |
|
74 |
- /* I/O buffering */ |
|
75 |
- unsigned char *inbuf, *i_ptr, *i_end, *o_ptr, *o_end; |
|
76 |
- unsigned int bit_buffer, bits_left, inbuf_size; |
|
77 |
- |
|
78 |
- /* huffman code lengths */ |
|
79 |
- unsigned char PRETREE_len [LZX_PRETREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY]; |
|
80 |
- unsigned char MAINTREE_len [LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY]; |
|
81 |
- unsigned char LENGTH_len [LZX_LENGTH_MAXSYMBOLS + LZX_LENTABLE_SAFETY]; |
|
82 |
- unsigned char ALIGNED_len [LZX_ALIGNED_MAXSYMBOLS + LZX_LENTABLE_SAFETY]; |
|
83 |
- |
|
84 |
- /* huffman decoding tables */ |
|
85 |
- unsigned short PRETREE_table [(1 << LZX_PRETREE_TABLEBITS) + |
|
86 |
- (LZX_PRETREE_MAXSYMBOLS * 2)]; |
|
87 |
- unsigned short MAINTREE_table[(1 << LZX_MAINTREE_TABLEBITS) + |
|
88 |
- (LZX_MAINTREE_MAXSYMBOLS * 2)]; |
|
89 |
- unsigned short LENGTH_table [(1 << LZX_LENGTH_TABLEBITS) + |
|
90 |
- (LZX_LENGTH_MAXSYMBOLS * 2)]; |
|
91 |
- unsigned short ALIGNED_table [(1 << LZX_ALIGNED_TABLEBITS) + |
|
92 |
- (LZX_ALIGNED_MAXSYMBOLS * 2)]; |
|
93 |
- |
|
94 |
- /* this is used purely for doing the intel E8 transform */ |
|
95 |
- unsigned char e8_buf[LZX_FRAME_SIZE]; |
|
96 |
-}; |
|
97 |
- |
|
98 |
-/* allocates LZX decompression state for decoding the given stream. |
|
99 |
- * |
|
100 |
- * - returns NULL if window_bits is outwith the range 15 to 21 (inclusive). |
|
101 |
- * |
|
102 |
- * - uses system->alloc() to allocate memory |
|
103 |
- * |
|
104 |
- * - returns NULL if not enough memory |
|
105 |
- * |
|
106 |
- * - window_bits is the size of the LZX window, from 32Kb (15) to 2Mb (21). |
|
107 |
- * |
|
108 |
- * - reset_interval is how often the bitstream is reset, measured in |
|
109 |
- * multiples of 32Kb bytes output. For CAB LZX streams, this is always 0 |
|
110 |
- * (does not occur). |
|
111 |
- * |
|
112 |
- * - input_buffer_size is how many bytes to use as an input bitstream buffer |
|
113 |
- * |
|
114 |
- * - output_length is the length in bytes of the entirely decompressed |
|
115 |
- * output stream, if known in advance. It is used to correctly perform |
|
116 |
- * the Intel E8 transformation, which must stop 6 bytes before the very |
|
117 |
- * end of the decompressed stream. It is not otherwise used or adhered |
|
118 |
- * to. If the full decompressed length is known in advance, set it here. |
|
119 |
- * If it is NOT known, use the value 0, and call lzxd_set_output_length() |
|
120 |
- * once it is known. If never set, 4 of the final 6 bytes of the output |
|
121 |
- * stream may be incorrect. |
|
122 |
- */ |
|
123 |
-extern struct lzxd_stream *lzxd_init(struct mspack_system *system, |
|
124 |
- struct mspack_file *input, |
|
125 |
- struct mspack_file *output, |
|
126 |
- int window_bits, |
|
127 |
- int reset_interval, |
|
128 |
- int input_buffer_size, |
|
129 |
- off_t output_length); |
|
130 |
- |
|
131 |
-/* see description of output_length in lzxd_init() */ |
|
132 |
-extern void lzxd_set_output_length(struct lzxd_stream *lzx, |
|
133 |
- off_t output_length); |
|
134 |
- |
|
135 |
-/* decompresses, or decompresses more of, an LZX stream. |
|
136 |
- * |
|
137 |
- * - out_bytes of data will be decompressed and the function will return |
|
138 |
- * with an MSPACK_ERR_OK return code. |
|
139 |
- * |
|
140 |
- * - decompressing will stop as soon as out_bytes is reached. if the true |
|
141 |
- * amount of bytes decoded spills over that amount, they will be kept for |
|
142 |
- * a later invocation of lzxd_decompress(). |
|
143 |
- * |
|
144 |
- * - the output bytes will be passed to the system->write() function given in |
|
145 |
- * lzxd_init(), using the output file handle given in lzxd_init(). More |
|
146 |
- * than one call may be made to system->write(). |
|
147 |
- * |
|
148 |
- * - LZX will read input bytes as necessary using the system->read() function |
|
149 |
- * given in lzxd_init(), using the input file handle given in lzxd_init(). |
|
150 |
- * This will continue until system->read() returns 0 bytes, or an error. |
|
151 |
- * input streams should convey an "end of input stream" by refusing to |
|
152 |
- * supply all the bytes that LZX asks for when they reach the end of the |
|
153 |
- * stream, rather than return an error code. |
|
154 |
- * |
|
155 |
- * - if an error code other than MSPACK_ERR_OK is returned, the stream should |
|
156 |
- * be considered unusable and lzxd_decompress() should not be called again |
|
157 |
- * on this stream. |
|
158 |
- */ |
|
159 |
-extern int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes); |
|
160 |
- |
|
161 |
-/* frees all state associated with an LZX data stream |
|
162 |
- * |
|
163 |
- * - calls system->free() using the system pointer given in lzxd_init() |
|
164 |
- */ |
|
165 |
-void lzxd_free(struct lzxd_stream *lzx); |
|
166 |
- |
|
167 |
-#endif |
168 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,902 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted |
|
5 |
- * by Microsoft Corporation. |
|
6 |
- * |
|
7 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
8 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
9 |
- * |
|
10 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
11 |
- */ |
|
12 |
- |
|
13 |
-/* LZX decompression implementation */ |
|
14 |
- |
|
15 |
-#if HAVE_CONFIG_H |
|
16 |
-#include "clamav-config.h" |
|
17 |
-#endif |
|
18 |
- |
|
19 |
-#include <mspack.h> |
|
20 |
-#include <system.h> |
|
21 |
-#include <lzx.h> |
|
22 |
- |
|
23 |
-/* Microsoft's LZX document and their implementation of the |
|
24 |
- * com.ms.util.cab Java package do not concur. |
|
25 |
- * |
|
26 |
- * In the LZX document, there is a table showing the correlation between |
|
27 |
- * window size and the number of position slots. It states that the 1MB |
|
28 |
- * window = 40 slots and the 2MB window = 42 slots. In the implementation, |
|
29 |
- * 1MB = 42 slots, 2MB = 50 slots. The actual calculation is 'find the |
|
30 |
- * first slot whose position base is equal to or more than the required |
|
31 |
- * window size'. This would explain why other tables in the document refer |
|
32 |
- * to 50 slots rather than 42. |
|
33 |
- * |
|
34 |
- * The constant NUM_PRIMARY_LENGTHS used in the decompression pseudocode |
|
35 |
- * is not defined in the specification. |
|
36 |
- * |
|
37 |
- * The LZX document does not state the uncompressed block has an |
|
38 |
- * uncompressed length field. Where does this length field come from, so |
|
39 |
- * we can know how large the block is? The implementation has it as the 24 |
|
40 |
- * bits following after the 3 blocktype bits, before the alignment |
|
41 |
- * padding. |
|
42 |
- * |
|
43 |
- * The LZX document states that aligned offset blocks have their aligned |
|
44 |
- * offset huffman tree AFTER the main and length trees. The implementation |
|
45 |
- * suggests that the aligned offset tree is BEFORE the main and length |
|
46 |
- * trees. |
|
47 |
- * |
|
48 |
- * The LZX document decoding algorithm states that, in an aligned offset |
|
49 |
- * block, if an extra_bits value is 1, 2 or 3, then that number of bits |
|
50 |
- * should be read and the result added to the match offset. This is |
|
51 |
- * correct for 1 and 2, but not 3, where just a huffman symbol (using the |
|
52 |
- * aligned tree) should be read. |
|
53 |
- * |
|
54 |
- * Regarding the E8 preprocessing, the LZX document states 'No translation |
|
55 |
- * may be performed on the last 6 bytes of the input block'. This is |
|
56 |
- * correct. However, the pseudocode provided checks for the *E8 leader* |
|
57 |
- * up to the last 6 bytes. If the leader appears between -10 and -7 bytes |
|
58 |
- * from the end, this would cause the next four bytes to be modified, at |
|
59 |
- * least one of which would be in the last 6 bytes, which is not allowed |
|
60 |
- * according to the spec. |
|
61 |
- * |
|
62 |
- * The specification states that the huffman trees must always contain at |
|
63 |
- * least one element. However, many CAB files contain blocks where the |
|
64 |
- * length tree is completely empty (because there are no matches), and |
|
65 |
- * this is expected to succeed. |
|
66 |
- */ |
|
67 |
- |
|
68 |
- |
|
69 |
-/* LZX decompressor input macros |
|
70 |
- * |
|
71 |
- * STORE_BITS stores bitstream state in lzxd_stream structure |
|
72 |
- * RESTORE_BITS restores bitstream state from lzxd_stream structure |
|
73 |
- * READ_BITS(var,n) takes N bits from the buffer and puts them in var |
|
74 |
- * ENSURE_BITS(n) ensures there are at least N bits in the bit buffer. |
|
75 |
- * PEEK_BITS(n) extracts without removing N bits from the bit buffer |
|
76 |
- * REMOVE_BITS(n) removes N bits from the bit buffer |
|
77 |
- * |
|
78 |
- * These bit access routines work by using the area beyond the MSB and the |
|
79 |
- * LSB as a free source of zeroes when shifting. This avoids having to |
|
80 |
- * mask any bits. So we have to know the bit width of the bit buffer |
|
81 |
- * variable. |
|
82 |
- * |
|
83 |
- * The bit buffer datatype should be at least 32 bits wide: it must be |
|
84 |
- * possible to ENSURE_BITS(16), so it must be possible to add 16 new bits |
|
85 |
- * to the bit buffer when the bit buffer already has 1 to 15 bits left. |
|
86 |
- */ |
|
87 |
- |
|
88 |
-#if HAVE_LIMITS_H |
|
89 |
-# include <limits.h> |
|
90 |
-#endif |
|
91 |
-#ifndef CHAR_BIT |
|
92 |
-# define CHAR_BIT (8) |
|
93 |
-#endif |
|
94 |
-#define BITBUF_WIDTH (sizeof(bit_buffer) * CHAR_BIT) |
|
95 |
- |
|
96 |
-#define STORE_BITS do { \ |
|
97 |
- lzx->i_ptr = i_ptr; \ |
|
98 |
- lzx->i_end = i_end; \ |
|
99 |
- lzx->bit_buffer = bit_buffer; \ |
|
100 |
- lzx->bits_left = bits_left; \ |
|
101 |
-} while (0) |
|
102 |
- |
|
103 |
-#define RESTORE_BITS do { \ |
|
104 |
- i_ptr = lzx->i_ptr; \ |
|
105 |
- i_end = lzx->i_end; \ |
|
106 |
- bit_buffer = lzx->bit_buffer; \ |
|
107 |
- bits_left = lzx->bits_left; \ |
|
108 |
-} while (0) |
|
109 |
- |
|
110 |
-#define ENSURE_BITS(nbits) \ |
|
111 |
- while (bits_left < (nbits)) { \ |
|
112 |
- if (i_ptr >= i_end) { \ |
|
113 |
- if (lzxd_read_input(lzx)) return lzx->error; \ |
|
114 |
- i_ptr = lzx->i_ptr; \ |
|
115 |
- i_end = lzx->i_end; \ |
|
116 |
- } \ |
|
117 |
- bit_buffer |= ((i_ptr[1] << 8) | i_ptr[0]) \ |
|
118 |
- << (BITBUF_WIDTH - 16 - bits_left); \ |
|
119 |
- bits_left += 16; \ |
|
120 |
- i_ptr += 2; \ |
|
121 |
- } |
|
122 |
- |
|
123 |
-#define PEEK_BITS(nbits) (bit_buffer >> (BITBUF_WIDTH - (nbits))) |
|
124 |
- |
|
125 |
-#define REMOVE_BITS(nbits) ((bit_buffer <<= (nbits)), (bits_left -= (nbits))) |
|
126 |
- |
|
127 |
-#define READ_BITS(val, nbits) do { \ |
|
128 |
- ENSURE_BITS(nbits); \ |
|
129 |
- (val) = PEEK_BITS(nbits); \ |
|
130 |
- REMOVE_BITS(nbits); \ |
|
131 |
-} while (0) |
|
132 |
- |
|
133 |
-static int lzxd_read_input(struct lzxd_stream *lzx) { |
|
134 |
- int read = lzx->sys->read(lzx->input, &lzx->inbuf[0], (int)lzx->inbuf_size); |
|
135 |
- if (read < 0) return lzx->error = MSPACK_ERR_READ; |
|
136 |
- |
|
137 |
- /* huff decode's ENSURE_BYTES(16) might overrun the input stream, even |
|
138 |
- * if those bits aren't used, so fake 2 more bytes */ |
|
139 |
- if (read == 0) { |
|
140 |
- if (lzx->input_end) { |
|
141 |
- D(("out of input bytes")) |
|
142 |
- return lzx->error = MSPACK_ERR_READ; |
|
143 |
- } |
|
144 |
- else { |
|
145 |
- read = 2; |
|
146 |
- lzx->inbuf[0] = lzx->inbuf[1] = 0; |
|
147 |
- lzx->input_end = 1; |
|
148 |
- } |
|
149 |
- } |
|
150 |
- |
|
151 |
- lzx->i_ptr = &lzx->inbuf[0]; |
|
152 |
- lzx->i_end = &lzx->inbuf[read]; |
|
153 |
- |
|
154 |
- return MSPACK_ERR_OK; |
|
155 |
-} |
|
156 |
- |
|
157 |
-/* Huffman decoding macros */ |
|
158 |
- |
|
159 |
-/* READ_HUFFSYM(tablename, var) decodes one huffman symbol from the |
|
160 |
- * bitstream using the stated table and puts it in var. |
|
161 |
- */ |
|
162 |
-#define READ_HUFFSYM(tbl, var) do { \ |
|
163 |
- /* huffman symbols can be up to 16 bits long */ \ |
|
164 |
- ENSURE_BITS(16); \ |
|
165 |
- /* immediate table lookup of [tablebits] bits of the code */ \ |
|
166 |
- sym = lzx->tbl##_table[PEEK_BITS(LZX_##tbl##_TABLEBITS)]; \ |
|
167 |
- /* is the symbol is longer than [tablebits] bits? (i=node index) */ \ |
|
168 |
- if (sym >= LZX_##tbl##_MAXSYMBOLS) { \ |
|
169 |
- /* decode remaining bits by tree traversal */ \ |
|
170 |
- i = 1 << (BITBUF_WIDTH - LZX_##tbl##_TABLEBITS); \ |
|
171 |
- do { \ |
|
172 |
- /* one less bit. error if we run out of bits before decode */ \ |
|
173 |
- i >>= 1; \ |
|
174 |
- if (i == 0) { \ |
|
175 |
- D(("out of bits in huffman decode")) \ |
|
176 |
- return lzx->error = MSPACK_ERR_DECRUNCH; \ |
|
177 |
- } \ |
|
178 |
- /* double node index and add 0 (left branch) or 1 (right) */ \ |
|
179 |
- sym <<= 1; sym |= (bit_buffer & i) ? 1 : 0; \ |
|
180 |
- /* hop to next node index / decoded symbol */ \ |
|
181 |
- sym = lzx->tbl##_table[sym]; \ |
|
182 |
- /* while we are still in node indicies, not decoded symbols */ \ |
|
183 |
- } while (sym >= LZX_##tbl##_MAXSYMBOLS); \ |
|
184 |
- } \ |
|
185 |
- /* result */ \ |
|
186 |
- (var) = sym; \ |
|
187 |
- /* look up the code length of that symbol and discard those bits */ \ |
|
188 |
- i = lzx->tbl##_len[sym]; \ |
|
189 |
- REMOVE_BITS(i); \ |
|
190 |
-} while (0) |
|
191 |
- |
|
192 |
-/* BUILD_TABLE(tbl) builds a huffman lookup table from code lengths */ |
|
193 |
-#define BUILD_TABLE(tbl) \ |
|
194 |
- if (make_decode_table(LZX_##tbl##_MAXSYMBOLS, LZX_##tbl##_TABLEBITS, \ |
|
195 |
- &lzx->tbl##_len[0], &lzx->tbl##_table[0])) \ |
|
196 |
- { \ |
|
197 |
- D(("failed to build %s table", #tbl)) \ |
|
198 |
- return lzx->error = MSPACK_ERR_DECRUNCH; \ |
|
199 |
- } |
|
200 |
- |
|
201 |
-/* make_decode_table(nsyms, nbits, length[], table[]) |
|
202 |
- * |
|
203 |
- * This function was coded by David Tritscher. It builds a fast huffman |
|
204 |
- * decoding table from a canonical huffman code lengths table. |
|
205 |
- * |
|
206 |
- * nsyms = total number of symbols in this huffman tree. |
|
207 |
- * nbits = any symbols with a code length of nbits or less can be decoded |
|
208 |
- * in one lookup of the table. |
|
209 |
- * length = A table to get code lengths from [0 to syms-1] |
|
210 |
- * table = The table to fill up with decoded symbols and pointers. |
|
211 |
- * |
|
212 |
- * Returns 0 for OK or 1 for error |
|
213 |
- */ |
|
214 |
- |
|
215 |
-static int make_decode_table(unsigned int nsyms, unsigned int nbits, |
|
216 |
- unsigned char *length, unsigned short *table) |
|
217 |
-{ |
|
218 |
- register unsigned short sym; |
|
219 |
- register unsigned int leaf, fill; |
|
220 |
- register unsigned char bit_num; |
|
221 |
- unsigned int pos = 0; /* the current position in the decode table */ |
|
222 |
- unsigned int table_mask = 1 << nbits; |
|
223 |
- unsigned int bit_mask = table_mask >> 1; /* don't do 0 length codes */ |
|
224 |
- unsigned int next_symbol = bit_mask; /* base of allocation for long codes */ |
|
225 |
- |
|
226 |
- /* fill entries for codes short enough for a direct mapping */ |
|
227 |
- for (bit_num = 1; bit_num <= nbits; bit_num++) { |
|
228 |
- for (sym = 0; sym < nsyms; sym++) { |
|
229 |
- if (length[sym] != bit_num) continue; |
|
230 |
- leaf = pos; |
|
231 |
- if((pos += bit_mask) > table_mask) return 1; /* table overrun */ |
|
232 |
- /* fill all possible lookups of this symbol with the symbol itself */ |
|
233 |
- for (fill = bit_mask; fill-- > 0;) table[leaf++] = sym; |
|
234 |
- } |
|
235 |
- bit_mask >>= 1; |
|
236 |
- } |
|
237 |
- |
|
238 |
- /* full table already? */ |
|
239 |
- if (pos == table_mask) return 0; |
|
240 |
- |
|
241 |
- /* clear the remainder of the table */ |
|
242 |
- for (sym = pos; sym < table_mask; sym++) table[sym] = 0xFFFF; |
|
243 |
- |
|
244 |
- /* allow codes to be up to nbits+16 long, instead of nbits */ |
|
245 |
- pos <<= 16; |
|
246 |
- table_mask <<= 16; |
|
247 |
- bit_mask = 1 << 15; |
|
248 |
- |
|
249 |
- for (bit_num = nbits+1; bit_num <= 16; bit_num++) { |
|
250 |
- for (sym = 0; sym < nsyms; sym++) { |
|
251 |
- if (length[sym] != bit_num) continue; |
|
252 |
- |
|
253 |
- leaf = pos >> 16; |
|
254 |
- for (fill = 0; fill < bit_num - nbits; fill++) { |
|
255 |
- /* if this path hasn't been taken yet, 'allocate' two entries */ |
|
256 |
- if (table[leaf] == 0xFFFF) { |
|
257 |
- table[(next_symbol << 1)] = 0xFFFF; |
|
258 |
- table[(next_symbol << 1) + 1] = 0xFFFF; |
|
259 |
- table[leaf] = next_symbol++; |
|
260 |
- } |
|
261 |
- /* follow the path and select either left or right for next bit */ |
|
262 |
- leaf = table[leaf] << 1; |
|
263 |
- if ((pos >> (15-fill)) & 1) leaf++; |
|
264 |
- } |
|
265 |
- table[leaf] = sym; |
|
266 |
- |
|
267 |
- if ((pos += bit_mask) > table_mask) return 1; /* table overflow */ |
|
268 |
- } |
|
269 |
- bit_mask >>= 1; |
|
270 |
- } |
|
271 |
- |
|
272 |
- /* full table? */ |
|
273 |
- if (pos == table_mask) return 0; |
|
274 |
- |
|
275 |
- /* either erroneous table, or all elements are 0 - let's find out. */ |
|
276 |
- for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1; |
|
277 |
- return 0; |
|
278 |
-} |
|
279 |
- |
|
280 |
- |
|
281 |
-/* READ_LENGTHS(tablename, first, last) reads in code lengths for symbols |
|
282 |
- * first to last in the given table. The code lengths are stored in their |
|
283 |
- * own special LZX way. |
|
284 |
- */ |
|
285 |
-#define READ_LENGTHS(tbl, first, last) do { \ |
|
286 |
- STORE_BITS; \ |
|
287 |
- if (lzxd_read_lens(lzx, &lzx->tbl##_len[0], (first), \ |
|
288 |
- (unsigned int)(last))) return lzx->error; \ |
|
289 |
- RESTORE_BITS; \ |
|
290 |
-} while (0) |
|
291 |
- |
|
292 |
-static int lzxd_read_lens(struct lzxd_stream *lzx, unsigned char *lens, |
|
293 |
- unsigned int first, unsigned int last) |
|
294 |
-{ |
|
295 |
- /* bit buffer and huffman symbol decode variables */ |
|
296 |
- register unsigned int bit_buffer; |
|
297 |
- register int bits_left, i; |
|
298 |
- register unsigned short sym; |
|
299 |
- unsigned char *i_ptr, *i_end; |
|
300 |
- |
|
301 |
- unsigned int x, y; |
|
302 |
- int z; |
|
303 |
- |
|
304 |
- RESTORE_BITS; |
|
305 |
- |
|
306 |
- /* read lengths for pretree (20 symbols, lengths stored in fixed 4 bits) */ |
|
307 |
- for (x = 0; x < 20; x++) { |
|
308 |
- READ_BITS(y, 4); |
|
309 |
- lzx->PRETREE_len[x] = y; |
|
310 |
- } |
|
311 |
- BUILD_TABLE(PRETREE); |
|
312 |
- |
|
313 |
- for (x = first; x < last; ) { |
|
314 |
- READ_HUFFSYM(PRETREE, z); |
|
315 |
- if (z == 17) { |
|
316 |
- /* code = 17, run of ([read 4 bits]+4) zeros */ |
|
317 |
- READ_BITS(y, 4); y += 4; |
|
318 |
- while (y--) lens[x++] = 0; |
|
319 |
- } |
|
320 |
- else if (z == 18) { |
|
321 |
- /* code = 18, run of ([read 5 bits]+20) zeros */ |
|
322 |
- READ_BITS(y, 5); y += 20; |
|
323 |
- while (y--) lens[x++] = 0; |
|
324 |
- } |
|
325 |
- else if (z == 19) { |
|
326 |
- /* code = 19, run of ([read 1 bit]+4) [read huffman symbol] */ |
|
327 |
- READ_BITS(y, 1); y += 4; |
|
328 |
- READ_HUFFSYM(PRETREE, z); |
|
329 |
- z = lens[x] - z; if (z < 0) z += 17; |
|
330 |
- while (y--) lens[x++] = z; |
|
331 |
- } |
|
332 |
- else { |
|
333 |
- /* code = 0 to 16, delta current length entry */ |
|
334 |
- z = lens[x] - z; if (z < 0) z += 17; |
|
335 |
- lens[x++] = z; |
|
336 |
- } |
|
337 |
- } |
|
338 |
- |
|
339 |
- STORE_BITS; |
|
340 |
- |
|
341 |
- return MSPACK_ERR_OK; |
|
342 |
-} |
|
343 |
- |
|
344 |
-/* LZX static data tables: |
|
345 |
- * |
|
346 |
- * LZX uses 'position slots' to represent match offsets. For every match, |
|
347 |
- * a small 'position slot' number and a small offset from that slot are |
|
348 |
- * encoded instead of one large offset. |
|
349 |
- * |
|
350 |
- * position_base[] is an index to the position slot bases |
|
351 |
- * |
|
352 |
- * extra_bits[] states how many bits of offset-from-base data is needed. |
|
353 |
- */ |
|
354 |
-static unsigned int position_base[51]; |
|
355 |
-static unsigned char extra_bits[51]; |
|
356 |
- |
|
357 |
-static void lzxd_static_init() { |
|
358 |
- int i, j; |
|
359 |
- |
|
360 |
- for (i = 0, j = 0; i < 51; i += 2) { |
|
361 |
- extra_bits[i] = j; /* 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7... */ |
|
362 |
- if(i < 50) |
|
363 |
- extra_bits[i+1] = j; |
|
364 |
- if ((i != 0) && (j < 17)) j++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */ |
|
365 |
- } |
|
366 |
- |
|
367 |
- for (i = 0, j = 0; i < 51; i++) { |
|
368 |
- position_base[i] = j; /* 0,1,2,3,4,6,8,12,16,24,32,... */ |
|
369 |
- j += 1 << extra_bits[i]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */ |
|
370 |
- } |
|
371 |
-} |
|
372 |
- |
|
373 |
-static void lzxd_reset_state(struct lzxd_stream *lzx) { |
|
374 |
- int i; |
|
375 |
- |
|
376 |
- lzx->R0 = 1; |
|
377 |
- lzx->R1 = 1; |
|
378 |
- lzx->R2 = 1; |
|
379 |
- lzx->header_read = 0; |
|
380 |
- lzx->block_remaining = 0; |
|
381 |
- lzx->block_type = LZX_BLOCKTYPE_INVALID; |
|
382 |
- |
|
383 |
- /* initialise tables to 0 (because deltas will be applied to them) */ |
|
384 |
- for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) lzx->MAINTREE_len[i] = 0; |
|
385 |
- for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) lzx->LENGTH_len[i] = 0; |
|
386 |
-} |
|
387 |
- |
|
388 |
-/*-------- main LZX code --------*/ |
|
389 |
- |
|
390 |
-struct lzxd_stream *lzxd_init(struct mspack_system *system, |
|
391 |
- struct mspack_file *input, |
|
392 |
- struct mspack_file *output, |
|
393 |
- int window_bits, |
|
394 |
- int reset_interval, |
|
395 |
- int input_buffer_size, |
|
396 |
- off_t output_length) |
|
397 |
-{ |
|
398 |
- unsigned int window_size = 1 << window_bits; |
|
399 |
- struct lzxd_stream *lzx; |
|
400 |
- |
|
401 |
- if (!system) return NULL; |
|
402 |
- |
|
403 |
- /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */ |
|
404 |
- if (window_bits < 15 || window_bits > 21) return NULL; |
|
405 |
- |
|
406 |
- input_buffer_size = (input_buffer_size + 1) & -2; |
|
407 |
- if (!input_buffer_size) return NULL; |
|
408 |
- |
|
409 |
- /* initialise static data */ |
|
410 |
- lzxd_static_init(); |
|
411 |
- |
|
412 |
- /* allocate decompression state */ |
|
413 |
- if (!(lzx = system->alloc(system, sizeof(struct lzxd_stream)))) { |
|
414 |
- return NULL; |
|
415 |
- } |
|
416 |
- |
|
417 |
- /* allocate decompression window and input buffer */ |
|
418 |
- lzx->window = system->alloc(system, (size_t) window_size); |
|
419 |
- lzx->inbuf = system->alloc(system, (size_t) input_buffer_size); |
|
420 |
- if (!lzx->window || !lzx->inbuf) { |
|
421 |
- system->free(lzx->window); |
|
422 |
- system->free(lzx->inbuf); |
|
423 |
- system->free(lzx); |
|
424 |
- return NULL; |
|
425 |
- } |
|
426 |
- |
|
427 |
- /* initialise decompression state */ |
|
428 |
- lzx->sys = system; |
|
429 |
- lzx->input = input; |
|
430 |
- lzx->output = output; |
|
431 |
- lzx->offset = 0; |
|
432 |
- lzx->length = output_length; |
|
433 |
- |
|
434 |
- lzx->inbuf_size = input_buffer_size; |
|
435 |
- lzx->window_size = 1 << window_bits; |
|
436 |
- lzx->window_posn = 0; |
|
437 |
- lzx->frame_posn = 0; |
|
438 |
- lzx->frame = 0; |
|
439 |
- lzx->reset_interval = reset_interval; |
|
440 |
- lzx->intel_filesize = 0; |
|
441 |
- lzx->intel_curpos = 0; |
|
442 |
- |
|
443 |
- /* window bits: 15 16 17 18 19 20 21 |
|
444 |
- * position slots: 30 32 34 36 38 42 50 */ |
|
445 |
- lzx->posn_slots = ((window_bits == 21) ? 50 : |
|
446 |
- ((window_bits == 20) ? 42 : (window_bits << 1))); |
|
447 |
- lzx->intel_started = 0; |
|
448 |
- lzx->input_end = 0; |
|
449 |
- |
|
450 |
- lzx->error = MSPACK_ERR_OK; |
|
451 |
- |
|
452 |
- lzx->i_ptr = lzx->i_end = &lzx->inbuf[0]; |
|
453 |
- lzx->o_ptr = lzx->o_end = &lzx->e8_buf[0]; |
|
454 |
- lzx->bit_buffer = lzx->bits_left = 0; |
|
455 |
- |
|
456 |
- lzxd_reset_state(lzx); |
|
457 |
- return lzx; |
|
458 |
-} |
|
459 |
- |
|
460 |
-void lzxd_set_output_length(struct lzxd_stream *lzx, off_t out_bytes) { |
|
461 |
- if (lzx) lzx->length = out_bytes; |
|
462 |
-} |
|
463 |
- |
|
464 |
-int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) { |
|
465 |
- /* bitstream reading and huffman variables */ |
|
466 |
- register unsigned int bit_buffer; |
|
467 |
- register int bits_left, i=0; |
|
468 |
- register unsigned short sym; |
|
469 |
- unsigned char *i_ptr, *i_end; |
|
470 |
- |
|
471 |
- int match_length, length_footer, extra, verbatim_bits, bytes_todo; |
|
472 |
- int this_run, main_element, aligned_bits, j; |
|
473 |
- unsigned char *window, *runsrc, *rundest, buf[12]; |
|
474 |
- unsigned int frame_size=0, end_frame, match_offset, window_posn; |
|
475 |
- unsigned int R0, R1, R2; |
|
476 |
- |
|
477 |
- /* easy answers */ |
|
478 |
- if (!lzx || (out_bytes < 0)) return MSPACK_ERR_ARGS; |
|
479 |
- if (lzx->error) return lzx->error; |
|
480 |
- |
|
481 |
- /* flush out any stored-up bytes before we begin */ |
|
482 |
- i = lzx->o_end - lzx->o_ptr; |
|
483 |
- if ((off_t) i > out_bytes) i = (int) out_bytes; |
|
484 |
- if (i) { |
|
485 |
- if (lzx->sys->write(lzx->output, lzx->o_ptr, i) != i) { |
|
486 |
- return lzx->error = MSPACK_ERR_WRITE; |
|
487 |
- } |
|
488 |
- lzx->o_ptr += i; |
|
489 |
- lzx->offset += i; |
|
490 |
- out_bytes -= i; |
|
491 |
- } |
|
492 |
- if (out_bytes == 0) return MSPACK_ERR_OK; |
|
493 |
- |
|
494 |
- /* restore local state */ |
|
495 |
- RESTORE_BITS; |
|
496 |
- window = lzx->window; |
|
497 |
- window_posn = lzx->window_posn; |
|
498 |
- R0 = lzx->R0; |
|
499 |
- R1 = lzx->R1; |
|
500 |
- R2 = lzx->R2; |
|
501 |
- |
|
502 |
- end_frame = (unsigned int)((lzx->offset + out_bytes) / LZX_FRAME_SIZE) + 1; |
|
503 |
- |
|
504 |
- while (lzx->frame < end_frame) { |
|
505 |
- /* have we reached the reset interval? (if there is one?) */ |
|
506 |
- if (lzx->reset_interval && ((lzx->frame % lzx->reset_interval) == 0)) { |
|
507 |
- if (lzx->block_remaining) { |
|
508 |
- D(("%d bytes remaining at reset interval", lzx->block_remaining)) |
|
509 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
510 |
- } |
|
511 |
- |
|
512 |
- /* re-read the intel header and reset the huffman lengths */ |
|
513 |
- lzxd_reset_state(lzx); |
|
514 |
- } |
|
515 |
- |
|
516 |
- /* read header if necessary */ |
|
517 |
- if (!lzx->header_read) { |
|
518 |
- /* read 1 bit. if bit=0, intel filesize = 0. |
|
519 |
- * if bit=1, read intel filesize (32 bits) */ |
|
520 |
- j = 0; READ_BITS(i, 1); if (i) { READ_BITS(i, 16); READ_BITS(j, 16); } |
|
521 |
- lzx->intel_filesize = (i << 16) | j; |
|
522 |
- lzx->header_read = 1; |
|
523 |
- } |
|
524 |
- |
|
525 |
- /* calculate size of frame: all frames are 32k except the final frame |
|
526 |
- * which is 32kb or less. this can only be calculated when lzx->length |
|
527 |
- * has been filled in. */ |
|
528 |
- frame_size = LZX_FRAME_SIZE; |
|
529 |
- if (lzx->length && (lzx->length - lzx->offset) < (off_t)frame_size) { |
|
530 |
- frame_size = lzx->length - lzx->offset; |
|
531 |
- } |
|
532 |
- |
|
533 |
- /* decode until one more frame is available */ |
|
534 |
- bytes_todo = lzx->frame_posn + frame_size - window_posn; |
|
535 |
- while (bytes_todo > 0) { |
|
536 |
- /* initialise new block, if one is needed */ |
|
537 |
- if (lzx->block_remaining == 0) { |
|
538 |
- /* realign if previous block was an odd-sized UNCOMPRESSED block */ |
|
539 |
- if ((lzx->block_type == LZX_BLOCKTYPE_UNCOMPRESSED) && |
|
540 |
- (lzx->block_length & 1)) |
|
541 |
- { |
|
542 |
- if (i_ptr == i_end) { |
|
543 |
- if (lzxd_read_input(lzx)) return lzx->error; |
|
544 |
- i_ptr = lzx->i_ptr; |
|
545 |
- i_end = lzx->i_end; |
|
546 |
- } |
|
547 |
- i_ptr++; |
|
548 |
- } |
|
549 |
- |
|
550 |
- /* read block type (3 bits) and block length (24 bits) */ |
|
551 |
- READ_BITS(lzx->block_type, 3); |
|
552 |
- READ_BITS(i, 16); READ_BITS(j, 8); |
|
553 |
- lzx->block_remaining = lzx->block_length = (i << 8) | j; |
|
554 |
- /*D(("new block t%d len %u", lzx->block_type, lzx->block_length))*/ |
|
555 |
- |
|
556 |
- /* read individual block headers */ |
|
557 |
- switch (lzx->block_type) { |
|
558 |
- case LZX_BLOCKTYPE_ALIGNED: |
|
559 |
- /* read lengths of and build aligned huffman decoding tree */ |
|
560 |
- for (i = 0; i < 8; i++) { READ_BITS(j, 3); lzx->ALIGNED_len[i] = j; } |
|
561 |
- BUILD_TABLE(ALIGNED); |
|
562 |
- /* no break -- rest of aligned header is same as verbatim */ |
|
563 |
- case LZX_BLOCKTYPE_VERBATIM: |
|
564 |
- /* read lengths of and build main huffman decoding tree */ |
|
565 |
- READ_LENGTHS(MAINTREE, 0, 256); |
|
566 |
- READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + (lzx->posn_slots << 3)); |
|
567 |
- BUILD_TABLE(MAINTREE); |
|
568 |
- /* if the literal 0xE8 is anywhere in the block... */ |
|
569 |
- if (lzx->MAINTREE_len[0xE8] != 0) lzx->intel_started = 1; |
|
570 |
- /* read lengths of and build lengths huffman decoding tree */ |
|
571 |
- READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS); |
|
572 |
- BUILD_TABLE(LENGTH); |
|
573 |
- break; |
|
574 |
- |
|
575 |
- case LZX_BLOCKTYPE_UNCOMPRESSED: |
|
576 |
- /* because we can't assume otherwise */ |
|
577 |
- lzx->intel_started = 1; |
|
578 |
- |
|
579 |
- /* read 1-16 (not 0-15) bits to align to bytes */ |
|
580 |
- ENSURE_BITS(16); |
|
581 |
- if (bits_left > 16) i_ptr -= 2; |
|
582 |
- bits_left = 0; bit_buffer = 0; |
|
583 |
- |
|
584 |
- /* read 12 bytes of stored R0 / R1 / R2 values */ |
|
585 |
- for (rundest = &buf[0], i = 0; i < 12; i++) { |
|
586 |
- if (i_ptr == i_end) { |
|
587 |
- if (lzxd_read_input(lzx)) return lzx->error; |
|
588 |
- i_ptr = lzx->i_ptr; |
|
589 |
- i_end = lzx->i_end; |
|
590 |
- } |
|
591 |
- *rundest++ = *i_ptr++; |
|
592 |
- } |
|
593 |
- R0 = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); |
|
594 |
- R1 = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24); |
|
595 |
- R2 = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24); |
|
596 |
- break; |
|
597 |
- |
|
598 |
- default: |
|
599 |
- D(("bad block type")) |
|
600 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
601 |
- } |
|
602 |
- } |
|
603 |
- |
|
604 |
- /* decode more of the block: |
|
605 |
- * run = min(what's available, what's needed) */ |
|
606 |
- this_run = lzx->block_remaining; |
|
607 |
- if (this_run > bytes_todo) this_run = bytes_todo; |
|
608 |
- |
|
609 |
- /* assume we decode exactly this_run bytes, for now */ |
|
610 |
- bytes_todo -= this_run; |
|
611 |
- lzx->block_remaining -= this_run; |
|
612 |
- |
|
613 |
- /* decode at least this_run bytes */ |
|
614 |
- switch (lzx->block_type) { |
|
615 |
- case LZX_BLOCKTYPE_VERBATIM: |
|
616 |
- while (this_run > 0) { |
|
617 |
- READ_HUFFSYM(MAINTREE, main_element); |
|
618 |
- if (main_element < LZX_NUM_CHARS) { |
|
619 |
- /* literal: 0 to LZX_NUM_CHARS-1 */ |
|
620 |
- window[window_posn++] = main_element; |
|
621 |
- this_run--; |
|
622 |
- } |
|
623 |
- else { |
|
624 |
- /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ |
|
625 |
- main_element -= LZX_NUM_CHARS; |
|
626 |
- |
|
627 |
- /* get match length */ |
|
628 |
- match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; |
|
629 |
- if (match_length == LZX_NUM_PRIMARY_LENGTHS) { |
|
630 |
- READ_HUFFSYM(LENGTH, length_footer); |
|
631 |
- match_length += length_footer; |
|
632 |
- } |
|
633 |
- match_length += LZX_MIN_MATCH; |
|
634 |
- |
|
635 |
- /* get match offset */ |
|
636 |
- switch ((match_offset = (main_element >> 3))) { |
|
637 |
- case 0: match_offset = R0; break; |
|
638 |
- case 1: match_offset = R1; R1=R0; R0 = match_offset; break; |
|
639 |
- case 2: match_offset = R2; R2=R0; R0 = match_offset; break; |
|
640 |
- case 3: match_offset = 1; R2=R1; R1=R0; R0 = match_offset; break; |
|
641 |
- default: |
|
642 |
- extra = extra_bits[match_offset]; |
|
643 |
- READ_BITS(verbatim_bits, extra); |
|
644 |
- match_offset = position_base[match_offset] - 2 + verbatim_bits; |
|
645 |
- R2 = R1; R1 = R0; R0 = match_offset; |
|
646 |
- } |
|
647 |
- |
|
648 |
- if ((window_posn + match_length) > lzx->window_size) { |
|
649 |
- D(("match ran over window wrap")) |
|
650 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
651 |
- } |
|
652 |
- |
|
653 |
- /* copy match */ |
|
654 |
- rundest = &window[window_posn]; |
|
655 |
- i = match_length; |
|
656 |
- /* does match offset wrap the window? */ |
|
657 |
- if (match_offset > window_posn) { |
|
658 |
- /* j = length from match offset to end of window */ |
|
659 |
- j = match_offset - window_posn; |
|
660 |
- if (j > (int) lzx->window_size) { |
|
661 |
- D(("match offset beyond window boundaries")) |
|
662 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
663 |
- } |
|
664 |
- runsrc = &window[lzx->window_size - j]; |
|
665 |
- if (j < i) { |
|
666 |
- /* if match goes over the window edge, do two copy runs */ |
|
667 |
- i -= j; while (j-- > 0) *rundest++ = *runsrc++; |
|
668 |
- runsrc = window; |
|
669 |
- } |
|
670 |
- while (i-- > 0) *rundest++ = *runsrc++; |
|
671 |
- } |
|
672 |
- else { |
|
673 |
- runsrc = rundest - match_offset; |
|
674 |
- while (i-- > 0) *rundest++ = *runsrc++; |
|
675 |
- } |
|
676 |
- |
|
677 |
- this_run -= match_length; |
|
678 |
- window_posn += match_length; |
|
679 |
- } |
|
680 |
- } /* while (this_run > 0) */ |
|
681 |
- break; |
|
682 |
- |
|
683 |
- case LZX_BLOCKTYPE_ALIGNED: |
|
684 |
- while (this_run > 0) { |
|
685 |
- READ_HUFFSYM(MAINTREE, main_element); |
|
686 |
- if (main_element < LZX_NUM_CHARS) { |
|
687 |
- /* literal: 0 to LZX_NUM_CHARS-1 */ |
|
688 |
- window[window_posn++] = main_element; |
|
689 |
- this_run--; |
|
690 |
- } |
|
691 |
- else { |
|
692 |
- /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */ |
|
693 |
- main_element -= LZX_NUM_CHARS; |
|
694 |
- |
|
695 |
- /* get match length */ |
|
696 |
- match_length = main_element & LZX_NUM_PRIMARY_LENGTHS; |
|
697 |
- if (match_length == LZX_NUM_PRIMARY_LENGTHS) { |
|
698 |
- READ_HUFFSYM(LENGTH, length_footer); |
|
699 |
- match_length += length_footer; |
|
700 |
- } |
|
701 |
- match_length += LZX_MIN_MATCH; |
|
702 |
- |
|
703 |
- /* get match offset */ |
|
704 |
- switch ((match_offset = (main_element >> 3))) { |
|
705 |
- case 0: match_offset = R0; break; |
|
706 |
- case 1: match_offset = R1; R1 = R0; R0 = match_offset; break; |
|
707 |
- case 2: match_offset = R2; R2 = R0; R0 = match_offset; break; |
|
708 |
- default: |
|
709 |
- extra = extra_bits[match_offset]; |
|
710 |
- match_offset = position_base[match_offset] - 2; |
|
711 |
- if (extra > 3) { |
|
712 |
- /* verbatim and aligned bits */ |
|
713 |
- extra -= 3; |
|
714 |
- READ_BITS(verbatim_bits, extra); |
|
715 |
- match_offset += (verbatim_bits << 3); |
|
716 |
- READ_HUFFSYM(ALIGNED, aligned_bits); |
|
717 |
- match_offset += aligned_bits; |
|
718 |
- } |
|
719 |
- else if (extra == 3) { |
|
720 |
- /* aligned bits only */ |
|
721 |
- READ_HUFFSYM(ALIGNED, aligned_bits); |
|
722 |
- match_offset += aligned_bits; |
|
723 |
- } |
|
724 |
- else if (extra > 0) { /* extra==1, extra==2 */ |
|
725 |
- /* verbatim bits only */ |
|
726 |
- READ_BITS(verbatim_bits, extra); |
|
727 |
- match_offset += verbatim_bits; |
|
728 |
- } |
|
729 |
- else /* extra == 0 */ { |
|
730 |
- /* ??? not defined in LZX specification! */ |
|
731 |
- match_offset = 1; |
|
732 |
- } |
|
733 |
- /* update repeated offset LRU queue */ |
|
734 |
- R2 = R1; R1 = R0; R0 = match_offset; |
|
735 |
- } |
|
736 |
- |
|
737 |
- if ((window_posn + match_length) > lzx->window_size) { |
|
738 |
- D(("match ran over window wrap")) |
|
739 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
740 |
- } |
|
741 |
- |
|
742 |
- /* copy match */ |
|
743 |
- rundest = &window[window_posn]; |
|
744 |
- i = match_length; |
|
745 |
- /* does match offset wrap the window? */ |
|
746 |
- if (match_offset > window_posn) { |
|
747 |
- /* j = length from match offset to end of window */ |
|
748 |
- j = match_offset - window_posn; |
|
749 |
- if (j > (int) lzx->window_size) { |
|
750 |
- D(("match offset beyond window boundaries")) |
|
751 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
752 |
- } |
|
753 |
- runsrc = &window[lzx->window_size - j]; |
|
754 |
- if (j < i) { |
|
755 |
- /* if match goes over the window edge, do two copy runs */ |
|
756 |
- i -= j; while (j-- > 0) *rundest++ = *runsrc++; |
|
757 |
- runsrc = window; |
|
758 |
- } |
|
759 |
- while (i-- > 0) *rundest++ = *runsrc++; |
|
760 |
- } |
|
761 |
- else { |
|
762 |
- runsrc = rundest - match_offset; |
|
763 |
- while (i-- > 0) *rundest++ = *runsrc++; |
|
764 |
- } |
|
765 |
- |
|
766 |
- this_run -= match_length; |
|
767 |
- window_posn += match_length; |
|
768 |
- } |
|
769 |
- } /* while (this_run > 0) */ |
|
770 |
- break; |
|
771 |
- |
|
772 |
- case LZX_BLOCKTYPE_UNCOMPRESSED: |
|
773 |
- /* as this_run is limited not to wrap a frame, this also means it |
|
774 |
- * won't wrap the window (as the window is a multiple of 32k) */ |
|
775 |
- rundest = &window[window_posn]; |
|
776 |
- window_posn += this_run; |
|
777 |
- while (this_run > 0) { |
|
778 |
- if ((i = i_end - i_ptr)) { |
|
779 |
- if (i > this_run) i = this_run; |
|
780 |
- lzx->sys->copy(i_ptr, rundest, (size_t) i); |
|
781 |
- rundest += i; |
|
782 |
- i_ptr += i; |
|
783 |
- this_run -= i; |
|
784 |
- } |
|
785 |
- else { |
|
786 |
- if (lzxd_read_input(lzx)) return lzx->error; |
|
787 |
- i_ptr = lzx->i_ptr; |
|
788 |
- i_end = lzx->i_end; |
|
789 |
- } |
|
790 |
- } |
|
791 |
- break; |
|
792 |
- |
|
793 |
- default: |
|
794 |
- return lzx->error = MSPACK_ERR_DECRUNCH; /* might as well */ |
|
795 |
- } |
|
796 |
- |
|
797 |
- /* did the final match overrun our desired this_run length? */ |
|
798 |
- if (this_run < 0) { |
|
799 |
- if ((unsigned int)(-this_run) > lzx->block_remaining) { |
|
800 |
- D(("overrun went past end of block by %d (%d remaining)", |
|
801 |
- -this_run, lzx->block_remaining )) |
|
802 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
803 |
- } |
|
804 |
- lzx->block_remaining -= -this_run; |
|
805 |
- } |
|
806 |
- } /* while (bytes_todo > 0) */ |
|
807 |
- |
|
808 |
- /* streams don't extend over frame boundaries */ |
|
809 |
- if ((window_posn - lzx->frame_posn) != frame_size) { |
|
810 |
- D(("decode beyond output frame limits! %d != %d", |
|
811 |
- window_posn - lzx->frame_posn, frame_size)) |
|
812 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
813 |
- } |
|
814 |
- |
|
815 |
- /* re-align input bitstream */ |
|
816 |
- if (bits_left > 0) ENSURE_BITS(16); |
|
817 |
- if (bits_left & 15) REMOVE_BITS(bits_left & 15); |
|
818 |
- |
|
819 |
- /* check that we've used all of the previous frame first */ |
|
820 |
- if (lzx->o_ptr != lzx->o_end) { |
|
821 |
- D(("%d avail bytes, new %d frame", lzx->o_end-lzx->o_ptr, frame_size)) |
|
822 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
823 |
- } |
|
824 |
- |
|
825 |
- /* does this intel block _really_ need decoding? */ |
|
826 |
- if (lzx->intel_started && lzx->intel_filesize && |
|
827 |
- (lzx->frame <= 32768) && (frame_size > 10)) |
|
828 |
- { |
|
829 |
- unsigned char *data = &lzx->e8_buf[0]; |
|
830 |
- unsigned char *dataend = &lzx->e8_buf[frame_size - 10]; |
|
831 |
- signed int curpos = lzx->intel_curpos; |
|
832 |
- signed int filesize = lzx->intel_filesize; |
|
833 |
- signed int abs_off, rel_off; |
|
834 |
- |
|
835 |
- /* copy e8 block to the e8 buffer and tweak if needed */ |
|
836 |
- lzx->o_ptr = data; |
|
837 |
- lzx->sys->copy(&lzx->window[lzx->frame_posn], data, frame_size); |
|
838 |
- |
|
839 |
- while (data < dataend) { |
|
840 |
- if (*data++ != 0xE8) { curpos++; continue; } |
|
841 |
- abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24); |
|
842 |
- if ((abs_off >= -curpos) && (abs_off < filesize)) { |
|
843 |
- rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize; |
|
844 |
- data[0] = (unsigned char) rel_off; |
|
845 |
- data[1] = (unsigned char) (rel_off >> 8); |
|
846 |
- data[2] = (unsigned char) (rel_off >> 16); |
|
847 |
- data[3] = (unsigned char) (rel_off >> 24); |
|
848 |
- } |
|
849 |
- data += 4; |
|
850 |
- curpos += 5; |
|
851 |
- } |
|
852 |
- lzx->intel_curpos += frame_size; |
|
853 |
- } |
|
854 |
- else { |
|
855 |
- lzx->o_ptr = &lzx->window[lzx->frame_posn]; |
|
856 |
- if (lzx->intel_filesize) lzx->intel_curpos += frame_size; |
|
857 |
- } |
|
858 |
- lzx->o_end = &lzx->o_ptr[frame_size]; |
|
859 |
- |
|
860 |
- /* write a frame */ |
|
861 |
- i = (out_bytes < (off_t)frame_size) ? (unsigned int)out_bytes : frame_size; |
|
862 |
- if (lzx->sys->write(lzx->output, lzx->o_ptr, i) != i) { |
|
863 |
- return lzx->error = MSPACK_ERR_WRITE; |
|
864 |
- } |
|
865 |
- lzx->o_ptr += i; |
|
866 |
- lzx->offset += i; |
|
867 |
- out_bytes -= i; |
|
868 |
- |
|
869 |
- /* advance frame start position */ |
|
870 |
- lzx->frame_posn += frame_size; |
|
871 |
- lzx->frame++; |
|
872 |
- |
|
873 |
- /* wrap window / frame position pointers */ |
|
874 |
- if (window_posn == lzx->window_size) window_posn = 0; |
|
875 |
- if (lzx->frame_posn == lzx->window_size) lzx->frame_posn = 0; |
|
876 |
- |
|
877 |
- } /* while (lzx->frame < end_frame) */ |
|
878 |
- |
|
879 |
- if (out_bytes) { |
|
880 |
- D(("bytes left to output")) |
|
881 |
- return lzx->error = MSPACK_ERR_DECRUNCH; |
|
882 |
- } |
|
883 |
- |
|
884 |
- /* store local state */ |
|
885 |
- STORE_BITS; |
|
886 |
- lzx->window_posn = window_posn; |
|
887 |
- lzx->R0 = R0; |
|
888 |
- lzx->R1 = R1; |
|
889 |
- lzx->R2 = R2; |
|
890 |
- |
|
891 |
- return MSPACK_ERR_OK; |
|
892 |
-} |
|
893 |
- |
|
894 |
-void lzxd_free(struct lzxd_stream *lzx) { |
|
895 |
- struct mspack_system *sys; |
|
896 |
- if (lzx) { |
|
897 |
- sys = lzx->sys; |
|
898 |
- sys->free(lzx->inbuf); |
|
899 |
- sys->free(lzx->window); |
|
900 |
- sys->free(lzx); |
|
901 |
- } |
|
902 |
-} |
903 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,1494 +0,0 @@ |
1 |
-/* WARNING: This version also supports dopen for descriptor opening and |
|
2 |
- * is not compatible with the original version. -- T. Kojm |
|
3 |
- * |
|
4 |
- * libmspack -- a library for working with Microsoft compression formats. |
|
5 |
- * (C) 2003-2004 Stuart Caie <kyzer@4u.net> |
|
6 |
- * |
|
7 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
8 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
9 |
- * |
|
10 |
- * This program is distributed in the hope that it will be useful, |
|
11 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 |
- * GNU Lesser General Public License for more details. |
|
14 |
- * |
|
15 |
- * You should have received a copy of the GNU Lesser General Public License |
|
16 |
- * along with this program; if not, write to the Free Software |
|
17 |
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
18 |
- */ |
|
19 |
- |
|
20 |
-/** \mainpage |
|
21 |
- * |
|
22 |
- * \section intro Introduction |
|
23 |
- * |
|
24 |
- * libmspack is a library which provides compressors and decompressors, |
|
25 |
- * archivers and dearchivers for Microsoft compression formats. |
|
26 |
- * |
|
27 |
- * \section formats Formats supported |
|
28 |
- * |
|
29 |
- * The following file formats are supported: |
|
30 |
- * - SZDD files, which use LZSS compression |
|
31 |
- * - KWAJ files, which use LZSS, LZSS+Huffman or deflate compression |
|
32 |
- * - .HLP (MS Help) files, which use LZSS compression |
|
33 |
- * - .CAB (MS Cabinet) files, which use deflate, LZX or Quantum compression |
|
34 |
- * - .CHM (HTML Help) files, which use LZX compression |
|
35 |
- * - .LIT (MS EBook) files, which use LZX compression and DES encryption |
|
36 |
- * |
|
37 |
- * To determine the capabilities of the library, and the binary |
|
38 |
- * compatibility version of any particular compressor or decompressor, use |
|
39 |
- * the mspack_version() function. The UNIX library interface version is |
|
40 |
- * defined as the highest-versioned library component. |
|
41 |
- * |
|
42 |
- * \section starting Getting started |
|
43 |
- * |
|
44 |
- * The macro MSPACK_SYS_SELFTEST() should be used to ensure the library can |
|
45 |
- * be used. In particular, it checks if the caller is using 32-bit file I/O |
|
46 |
- * when the library is compiled for 64-bit file I/O and vice versa. |
|
47 |
- * |
|
48 |
- * If compiled normally, the library includes basic file I/O and memory |
|
49 |
- * management functionality using the standard C library. This can be |
|
50 |
- * customised and replaced entirely by creating a mspack_system structure. |
|
51 |
- * |
|
52 |
- * A compressor or decompressor for the required format must be |
|
53 |
- * instantiated before it can be used. Each construction function takes |
|
54 |
- * one parameter, which is either a pointer to a custom mspack_system |
|
55 |
- * structure, or NULL to use the default. The instantiation returned, if |
|
56 |
- * not NULL, contains function pointers (methods) to work with the given |
|
57 |
- * file format. |
|
58 |
- * |
|
59 |
- * For compression: |
|
60 |
- * - mspack_create_cab_compressor() creates a mscab_compressor |
|
61 |
- * - mspack_create_chm_compressor() creates a mschm_compressor |
|
62 |
- * - mspack_create_lit_compressor() creates a mslit_compressor |
|
63 |
- * - mspack_create_hlp_compressor() creates a mshlp_compressor |
|
64 |
- * - mspack_create_szdd_compressor() creates a msszdd_compressor |
|
65 |
- * - mspack_create_kwaj_compressor() creates a mskwaj_compressor |
|
66 |
- * |
|
67 |
- * For decompression: |
|
68 |
- * - mspack_create_cab_decompressor() creates a mscab_decompressor |
|
69 |
- * - mspack_create_chm_decompressor() creates a mschm_decompressor |
|
70 |
- * - mspack_create_lit_decompressor() creates a mslit_decompressor |
|
71 |
- * - mspack_create_hlp_decompressor() creates a mshlp_decompressor |
|
72 |
- * - mspack_create_szdd_decompressor() creates a msszdd_decompressor |
|
73 |
- * - mspack_create_kwaj_decompressor() creates a mskwaj_decompressor |
|
74 |
- * |
|
75 |
- * Once finished working with a format, each kind of |
|
76 |
- * compressor/decompressor has its own specific destructor: |
|
77 |
- * - mspack_destroy_cab_compressor() |
|
78 |
- * - mspack_destroy_cab_decompressor() |
|
79 |
- * - mspack_destroy_chm_compressor() |
|
80 |
- * - mspack_destroy_chm_decompressor() |
|
81 |
- * - mspack_destroy_lit_compressor() |
|
82 |
- * - mspack_destroy_lit_decompressor() |
|
83 |
- * - mspack_destroy_hlp_compressor() |
|
84 |
- * - mspack_destroy_hlp_decompressor() |
|
85 |
- * - mspack_destroy_szdd_compressor() |
|
86 |
- * - mspack_destroy_szdd_decompressor() |
|
87 |
- * - mspack_destroy_kwaj_compressor() |
|
88 |
- * - mspack_destroy_kwaj_decompressor() |
|
89 |
- * |
|
90 |
- * Destroying a compressor or decompressor does not destroy any objects, |
|
91 |
- * structures or handles that have been created using that compressor or |
|
92 |
- * decompressor. Ensure that everything created or opened is destroyed or |
|
93 |
- * closed before compressor/decompressor is itself destroyed. |
|
94 |
- * |
|
95 |
- * \section errors Error codes |
|
96 |
- * |
|
97 |
- * All compressors and decompressors use the same set of error codes. Most |
|
98 |
- * methods return an error code directly. For methods which do not |
|
99 |
- * return error codes directly, the error code can be obtained with the |
|
100 |
- * last_error() method. |
|
101 |
- * |
|
102 |
- * - #MSPACK_ERR_OK is used to indicate success. This error code is defined |
|
103 |
- * as zero, all other code are non-zero. |
|
104 |
- * - #MSPACK_ERR_ARGS indicates that a method was called with inappropriate |
|
105 |
- * arguments. |
|
106 |
- * - #MSPACK_ERR_OPEN indicates that mspack_system::open() failed. |
|
107 |
- * - #MSPACK_ERR_READ indicates that mspack_system::read() failed. |
|
108 |
- * - #MSPACK_ERR_WRITE indicates that mspack_system::write() failed. |
|
109 |
- * - #MSPACK_ERR_SEEK indicates that mspack_system::seek() failed. |
|
110 |
- * - #MSPACK_ERR_NOMEMORY indicates that mspack_system::alloc() failed. |
|
111 |
- * - #MSPACK_ERR_SIGNATURE indicates that the file being read does not |
|
112 |
- * have the correct "signature". It is probably not a valid file for |
|
113 |
- * whatever format is being read. |
|
114 |
- * - #MSPACK_ERR_DATAFORMAT indicates that the file being used or read |
|
115 |
- * is corrupt. |
|
116 |
- * - #MSPACK_ERR_CHECKSUM indicates that a data checksum has failed. |
|
117 |
- * - #MSPACK_ERR_CRUNCH indicates an error occured during compression. |
|
118 |
- * - #MSPACK_ERR_DECRUNCH indicates an error occured during decompression. |
|
119 |
- */ |
|
120 |
- |
|
121 |
-#ifndef LIB_MSPACK_H |
|
122 |
-#define LIB_MSPACK_H 1 |
|
123 |
- |
|
124 |
-#ifdef __cplusplus |
|
125 |
-extern "C" { |
|
126 |
-#endif |
|
127 |
- |
|
128 |
-#include <sys/types.h> |
|
129 |
-#include <unistd.h> |
|
130 |
- |
|
131 |
-/** |
|
132 |
- * System self-test function, to ensure both library and calling program |
|
133 |
- * can use one another. |
|
134 |
- * |
|
135 |
- * A result of MSPACK_ERR_OK means the library and caller are |
|
136 |
- * compatible. Any other result indicates that the library and caller are |
|
137 |
- * not compatible and should not be used. In particular, a value of |
|
138 |
- * MSPACK_ERR_SEEK means the library and caller use different off_t |
|
139 |
- * datatypes. |
|
140 |
- * |
|
141 |
- * It should be used like so: |
|
142 |
- * |
|
143 |
- * @code |
|
144 |
- * int selftest_result; |
|
145 |
- * MSPACK_SYS_SELFTEST(selftest_result); |
|
146 |
- * if (selftest_result != MSPACK_ERR_OK) { |
|
147 |
- * fprintf(stderr, "incompatible with this build of libmspack\n"); |
|
148 |
- * exit(0); |
|
149 |
- * } |
|
150 |
- * @endcode |
|
151 |
- * |
|
152 |
- * @param result an int variable to store the result of the self-test |
|
153 |
- */ |
|
154 |
-#define MSPACK_SYS_SELFTEST(result) do { \ |
|
155 |
- (result) = mspack_sys_selftest_internal(sizeof(off_t)); \ |
|
156 |
-} while (0) |
|
157 |
- |
|
158 |
-/** Part of the MSPACK_SYS_SELFTEST() macro, must not be used directly. */ |
|
159 |
-extern int mspack_sys_selftest_internal(int); |
|
160 |
- |
|
161 |
-/** |
|
162 |
- * Enquire about the binary compatibility version of a specific interface in |
|
163 |
- * the library. Currently, the following interfaces are defined: |
|
164 |
- * |
|
165 |
- * - #MSPACK_VER_LIBRARY: the overall library |
|
166 |
- * - #MSPACK_VER_SYSTEM: the mspack_system interface |
|
167 |
- * - #MSPACK_VER_MSCABD: the mscab_decompressor interface |
|
168 |
- * - #MSPACK_VER_MSCABC: the mscab_compressor interface |
|
169 |
- * - #MSPACK_VER_MSCHMD: the mschm_decompressor interface |
|
170 |
- * - #MSPACK_VER_MSCHMC: the mschm_compressor interface |
|
171 |
- * - #MSPACK_VER_MSLITD: the mslit_decompressor interface |
|
172 |
- * - #MSPACK_VER_MSLITC: the mslit_compressor interface |
|
173 |
- * - #MSPACK_VER_MSHLPD: the mshlp_decompressor interface |
|
174 |
- * - #MSPACK_VER_MSHLPC: the mshlp_compressor interface |
|
175 |
- * - #MSPACK_VER_MSSZDDD: the msszdd_decompressor interface |
|
176 |
- * - #MSPACK_VER_MSSZDDC: the msszdd_compressor interface |
|
177 |
- * - #MSPACK_VER_MSKWAJD: the mskwaj_decompressor interface |
|
178 |
- * - #MSPACK_VER_MSKWAJC: the mskwaj_compressor interface |
|
179 |
- * |
|
180 |
- * The result of the function should be interpreted as follows: |
|
181 |
- * - -1: this interface is completely unknown to the library |
|
182 |
- * - 0: this interface is known, but non-functioning |
|
183 |
- * - 1: this interface has all basic functionality |
|
184 |
- * - 2, 3, ...: this interface has additional functionality, clearly marked |
|
185 |
- * in the documentation as "version 2", "version 3" and so on. |
|
186 |
- * |
|
187 |
- * @param interface the interface to request current version of |
|
188 |
- * @return the version of the requested interface |
|
189 |
- */ |
|
190 |
-extern int mspack_version(int interface); |
|
191 |
- |
|
192 |
-/** Pass to mspack_version() to get the overall library version */ |
|
193 |
-#define MSPACK_VER_LIBRARY (0) |
|
194 |
-/** Pass to mspack_version() to get the mspack_system version */ |
|
195 |
-#define MSPACK_VER_SYSTEM (1) |
|
196 |
-/** Pass to mspack_version() to get the mscab_decompressor version */ |
|
197 |
-#define MSPACK_VER_MSCABD (2) |
|
198 |
-/** Pass to mspack_version() to get the mscab_compressor version */ |
|
199 |
-#define MSPACK_VER_MSCABC (3) |
|
200 |
-/** Pass to mspack_version() to get the mschm_decompressor version */ |
|
201 |
-#define MSPACK_VER_MSCHMD (4) |
|
202 |
-/** Pass to mspack_version() to get the mschm_compressor version */ |
|
203 |
-#define MSPACK_VER_MSCHMC (5) |
|
204 |
-/** Pass to mspack_version() to get the mslit_decompressor version */ |
|
205 |
-#define MSPACK_VER_MSLITD (6) |
|
206 |
-/** Pass to mspack_version() to get the mslit_compressor version */ |
|
207 |
-#define MSPACK_VER_MSLITC (7) |
|
208 |
-/** Pass to mspack_version() to get the mshlp_decompressor version */ |
|
209 |
-#define MSPACK_VER_MSHLPD (8) |
|
210 |
-/** Pass to mspack_version() to get the mshlp_compressor version */ |
|
211 |
-#define MSPACK_VER_MSHLPC (9) |
|
212 |
-/** Pass to mspack_version() to get the msszdd_decompressor version */ |
|
213 |
-#define MSPACK_VER_MSSZDDD (10) |
|
214 |
-/** Pass to mspack_version() to get the msszdd_compressor version */ |
|
215 |
-#define MSPACK_VER_MSSZDDC (11) |
|
216 |
-/** Pass to mspack_version() to get the mskwaj_decompressor version */ |
|
217 |
-#define MSPACK_VER_MSKWAJD (12) |
|
218 |
-/** Pass to mspack_version() to get the mskwaj_compressor version */ |
|
219 |
-#define MSPACK_VER_MSKWAJC (13) |
|
220 |
- |
|
221 |
-/* --- file I/O abstraction ------------------------------------------------ */ |
|
222 |
- |
|
223 |
-/** |
|
224 |
- * A structure which abstracts file I/O and memory management. |
|
225 |
- * |
|
226 |
- * The library always uses the mspack_system structure for interaction |
|
227 |
- * with the file system and to allocate, free and copy all memory. It also |
|
228 |
- * uses it to send literal messages to the library user. |
|
229 |
- * |
|
230 |
- * When the library is compiled normally, passing NULL to a compressor or |
|
231 |
- * decompressor constructor will result in a default mspack_system being |
|
232 |
- * used, where all methods are implemented with the standard C library. |
|
233 |
- * However, all constructors support being given a custom created |
|
234 |
- * mspack_system structure, with the library user's own methods. This |
|
235 |
- * allows for more abstract interaction, such as reading and writing files |
|
236 |
- * directly to memory, or from a network socket or pipe. |
|
237 |
- * |
|
238 |
- * Implementors of an mspack_system structure should read all |
|
239 |
- * documentation entries for every structure member, and write methods |
|
240 |
- * which conform to those standards. |
|
241 |
- */ |
|
242 |
-struct mspack_system { |
|
243 |
- /** |
|
244 |
- * Opens a file for reading, writing, appending or updating. |
|
245 |
- * |
|
246 |
- * @param this a self-referential pointer to the mspack_system |
|
247 |
- * structure whose open() method is being called. If |
|
248 |
- * this pointer is required by close(), read(), write(), |
|
249 |
- * seek() or tell(), it should be stored in the result |
|
250 |
- * structure at this time. |
|
251 |
- * @param filename the file to be opened. It is passed directly from the |
|
252 |
- * library caller without being modified, so it is up to |
|
253 |
- * the caller what this parameter actually represents. |
|
254 |
- * @param mode one of #MSPACK_SYS_OPEN_READ (open an existing file |
|
255 |
- * for reading), #MSPACK_SYS_OPEN_WRITE (open a new file |
|
256 |
- * for writing), #MSPACK_SYS_OPEN_UPDATE (open an existing |
|
257 |
- * file for reading/writing from the start of the file) or |
|
258 |
- * #MSPACK_SYS_OPEN_APPEND (open an existing file for |
|
259 |
- * reading/writing from the end of the file) |
|
260 |
- * @return a pointer to a mspack_file structure. This structure officially |
|
261 |
- * contains no members, its true contents are up to the |
|
262 |
- * mspack_system implementor. It should contain whatever is needed |
|
263 |
- * for other mspack_system methods to operate. |
|
264 |
- * @see close(), read(), write(), seek(), tell(), message() |
|
265 |
- */ |
|
266 |
- struct mspack_file * (*open)(struct mspack_system *this, |
|
267 |
- char *filename, |
|
268 |
- int mode); |
|
269 |
- |
|
270 |
- struct mspack_file * (*dopen)(struct mspack_system *this, |
|
271 |
- int desc, |
|
272 |
- int mode); |
|
273 |
- |
|
274 |
- /** |
|
275 |
- * Closes a previously opened file. If any memory was allocated for this |
|
276 |
- * particular file handle, it should be freed at this time. |
|
277 |
- * |
|
278 |
- * @param file the file to close |
|
279 |
- * @see open() |
|
280 |
- */ |
|
281 |
- void (*close)(struct mspack_file *file); |
|
282 |
- |
|
283 |
- /** |
|
284 |
- * Reads a given number of bytes from an open file. |
|
285 |
- * |
|
286 |
- * @param file the file to read from |
|
287 |
- * @param buffer the location where the read bytes should be stored |
|
288 |
- * @param bytes the number of bytes to read from the file. |
|
289 |
- * @return the number of bytes successfully read (this can be less than |
|
290 |
- * the number requested), zero to mark the end of file, or less |
|
291 |
- * than zero to indicate an error. |
|
292 |
- * @see open(), write() |
|
293 |
- */ |
|
294 |
- int (*read)(struct mspack_file *file, |
|
295 |
- void *buffer, |
|
296 |
- int bytes); |
|
297 |
- |
|
298 |
- /** |
|
299 |
- * Writes a given number of bytes to an open file. |
|
300 |
- * |
|
301 |
- * @param file the file to write to |
|
302 |
- * @param buffer the location where the written bytes should be read from |
|
303 |
- * @param bytes the number of bytes to write to the file. |
|
304 |
- * @return the number of bytes successfully written, this can be less |
|
305 |
- * than the number requested. Zero or less can indicate an error |
|
306 |
- * where no bytes at all could be written. All cases where less |
|
307 |
- * bytes were written than requested are considered by the library |
|
308 |
- * to be an error. |
|
309 |
- * @see open(), read() |
|
310 |
- */ |
|
311 |
- int (*write)(struct mspack_file *file, |
|
312 |
- void *buffer, |
|
313 |
- int bytes); |
|
314 |
- |
|
315 |
- /** |
|
316 |
- * Seeks to a specific file offset within an open file. |
|
317 |
- * |
|
318 |
- * Sometimes the library needs to know the length of a file. It does |
|
319 |
- * this by seeking to the end of the file with seek(file, 0, |
|
320 |
- * MSPACK_SYS_SEEK_END), then calling tell(). Implementations may want |
|
321 |
- * to make a special case for this. |
|
322 |
- * |
|
323 |
- * Due to the potentially varying 32/64 bit datatype off_t on some |
|
324 |
- * architectures, the #MSPACK_SYS_SELFTEST macro MUST be used before |
|
325 |
- * using the library. If not, the error caused by the library passing an |
|
326 |
- * inappropriate stackframe to seek() is subtle and hard to trace. |
|
327 |
- * |
|
328 |
- * @param file the file to be seeked |
|
329 |
- * @param offset an offset to seek, measured in bytes |
|
330 |
- * @param mode one of #MSPACK_SYS_SEEK_START (the offset should be |
|
331 |
- * measured from the start of the file), #MSPACK_SYS_SEEK_CUR |
|
332 |
- * (the offset should be measured from the current file offset) |
|
333 |
- * or #MSPACK_SYS_SEEK_END (the offset should be measured from |
|
334 |
- * the end of the file) |
|
335 |
- * @return zero for success, non-zero for an error |
|
336 |
- * @see open(), tell() |
|
337 |
- */ |
|
338 |
- int (*seek)(struct mspack_file *file, |
|
339 |
- off_t offset, |
|
340 |
- int mode); |
|
341 |
- |
|
342 |
- /** |
|
343 |
- * Returns the current file position (in bytes) of the given file. |
|
344 |
- * |
|
345 |
- * @param file the file whose file position is wanted |
|
346 |
- * @return the current file position of the file |
|
347 |
- * @see open(), seek() |
|
348 |
- */ |
|
349 |
- off_t (*tell)(struct mspack_file *file); |
|
350 |
- |
|
351 |
- /** |
|
352 |
- * Used to send messages from the library to the user. |
|
353 |
- * |
|
354 |
- * Occasionally, the library generates warnings or other messages in |
|
355 |
- * plain english to inform the human user. These are informational only |
|
356 |
- * and can be ignored if not wanted. |
|
357 |
- * |
|
358 |
- * @param file may be a file handle returned from open() if this message |
|
359 |
- * pertains to a specific open file, or NULL if not related to |
|
360 |
- * a specific file. |
|
361 |
- * @param format a printf() style format string. It does NOT include a |
|
362 |
- * trailing newline. |
|
363 |
- * @see open() |
|
364 |
- */ |
|
365 |
- void (*message)(struct mspack_file *file, |
|
366 |
- char *format, |
|
367 |
- ...); |
|
368 |
- |
|
369 |
- /** |
|
370 |
- * Allocates memory. |
|
371 |
- * |
|
372 |
- * @param this a self-referential pointer to the mspack_system |
|
373 |
- * structure whose alloc() method is being called. |
|
374 |
- * @param bytes the number of bytes to allocate |
|
375 |
- * @result a pointer to the requested number of bytes, or NULL if |
|
376 |
- * not enough memory is available |
|
377 |
- * @see free() |
|
378 |
- */ |
|
379 |
- void * (*alloc)(struct mspack_system *this, |
|
380 |
- size_t bytes); |
|
381 |
- |
|
382 |
- /** |
|
383 |
- * Frees memory. |
|
384 |
- * |
|
385 |
- * @param ptr the memory to be freed. |
|
386 |
- * @see alloc() |
|
387 |
- */ |
|
388 |
- void (*free)(void *ptr); |
|
389 |
- |
|
390 |
- /** |
|
391 |
- * Copies from one region of memory to another. |
|
392 |
- * |
|
393 |
- * The regions of memory are guaranteed not to overlap, are usually less |
|
394 |
- * than 256 bytes, and may not be aligned. Please note that the source |
|
395 |
- * parameter comes before the destination parameter, unlike the standard |
|
396 |
- * C function memcpy(). |
|
397 |
- * |
|
398 |
- * @param src the region of memory to copy from |
|
399 |
- * @param dest the region of memory to copy to |
|
400 |
- * @param bytes the size of the memory region, in bytes |
|
401 |
- */ |
|
402 |
- void (*copy)(void *src, |
|
403 |
- void *dest, |
|
404 |
- size_t bytes); |
|
405 |
- |
|
406 |
- /** |
|
407 |
- * A null pointer to mark the end of mspack_system. It must equal NULL. |
|
408 |
- * |
|
409 |
- * Should the mspack_system structure extend in the future, this NULL |
|
410 |
- * will be seen, rather than have an invalid method pointer called. |
|
411 |
- */ |
|
412 |
- void *null_ptr; |
|
413 |
-}; |
|
414 |
- |
|
415 |
-/** mspack_system::open() mode: open existing file for reading. */ |
|
416 |
-#define MSPACK_SYS_OPEN_READ (0) |
|
417 |
-/** mspack_system::open() mode: open new file for writing */ |
|
418 |
-#define MSPACK_SYS_OPEN_WRITE (1) |
|
419 |
-/** mspack_system::open() mode: open existing file for writing */ |
|
420 |
-#define MSPACK_SYS_OPEN_UPDATE (2) |
|
421 |
-/** mspack_system::open() mode: open existing file for writing */ |
|
422 |
-#define MSPACK_SYS_OPEN_APPEND (3) |
|
423 |
- |
|
424 |
-/** mspack_system::seek() mode: seek relative to start of file */ |
|
425 |
-#define MSPACK_SYS_SEEK_START (0) |
|
426 |
-/** mspack_system::seek() mode: seek relative to current offset */ |
|
427 |
-#define MSPACK_SYS_SEEK_CUR (1) |
|
428 |
-/** mspack_system::seek() mode: seek relative to end of file */ |
|
429 |
-#define MSPACK_SYS_SEEK_END (2) |
|
430 |
- |
|
431 |
-/** |
|
432 |
- * A structure which represents an open file handle. The contents of this |
|
433 |
- * structure are determined by the implementation of the |
|
434 |
- * mspack_system::open() method. |
|
435 |
- */ |
|
436 |
-struct mspack_file { |
|
437 |
- int dummy; |
|
438 |
-}; |
|
439 |
- |
|
440 |
-/* --- error codes --------------------------------------------------------- */ |
|
441 |
- |
|
442 |
-/** Error code: no error */ |
|
443 |
-#define MSPACK_ERR_OK (0) |
|
444 |
-/** Error code: bad arguments to method */ |
|
445 |
-#define MSPACK_ERR_ARGS (1) |
|
446 |
-/** Error code: error opening file */ |
|
447 |
-#define MSPACK_ERR_OPEN (2) |
|
448 |
-/** Error code: error reading file */ |
|
449 |
-#define MSPACK_ERR_READ (3) |
|
450 |
-/** Error code: error writing file */ |
|
451 |
-#define MSPACK_ERR_WRITE (4) |
|
452 |
-/** Error code: seek error */ |
|
453 |
-#define MSPACK_ERR_SEEK (5) |
|
454 |
-/** Error code: out of memory */ |
|
455 |
-#define MSPACK_ERR_NOMEMORY (6) |
|
456 |
-/** Error code: bad "magic id" in file */ |
|
457 |
-#define MSPACK_ERR_SIGNATURE (7) |
|
458 |
-/** Error code: bad or corrupt file format */ |
|
459 |
-#define MSPACK_ERR_DATAFORMAT (8) |
|
460 |
-/** Error code: bad checksum or CRC */ |
|
461 |
-#define MSPACK_ERR_CHECKSUM (9) |
|
462 |
-/** Error code: error during compression */ |
|
463 |
-#define MSPACK_ERR_CRUNCH (10) |
|
464 |
-/** Error code: error during decompression */ |
|
465 |
-#define MSPACK_ERR_DECRUNCH (11) |
|
466 |
- |
|
467 |
-/* --- functions available in library -------------------------------------- */ |
|
468 |
- |
|
469 |
-/** Creates a new CAB compressor. |
|
470 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
471 |
- * @return a #mscab_compressor or NULL |
|
472 |
- */ |
|
473 |
-extern struct mscab_compressor * |
|
474 |
- mspack_create_cab_compressor(struct mspack_system *sys); |
|
475 |
- |
|
476 |
-/** Creates a new CAB decompressor. |
|
477 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
478 |
- * @return a #mscab_decompressor or NULL |
|
479 |
- */ |
|
480 |
-extern struct mscab_decompressor * |
|
481 |
- mspack_create_cab_decompressor(struct mspack_system *sys); |
|
482 |
- |
|
483 |
-/** Destroys an existing CAB compressor. |
|
484 |
- * @param this the #mscab_compressor to destroy |
|
485 |
- */ |
|
486 |
-extern void mspack_destroy_cab_compressor(struct mscab_compressor *this); |
|
487 |
- |
|
488 |
-/** Destroys an existing CAB decompressor. |
|
489 |
- * @param this the #mscab_decompressor to destroy |
|
490 |
- */ |
|
491 |
-extern void mspack_destroy_cab_decompressor(struct mscab_decompressor *this); |
|
492 |
- |
|
493 |
- |
|
494 |
-/** Creates a new CHM compressor. |
|
495 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
496 |
- * @return a #mschm_compressor or NULL |
|
497 |
- */ |
|
498 |
-extern struct mschm_compressor * |
|
499 |
- mspack_create_chm_compressor(struct mspack_system *sys); |
|
500 |
- |
|
501 |
-/** Creates a new CHM decompressor. |
|
502 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
503 |
- * @return a #mschm_decompressor or NULL |
|
504 |
- */ |
|
505 |
-extern struct mschm_decompressor * |
|
506 |
- mspack_create_chm_decompressor(struct mspack_system *sys); |
|
507 |
- |
|
508 |
-/** Destroys an existing CHM compressor. |
|
509 |
- * @param this the #mschm_compressor to destroy |
|
510 |
- */ |
|
511 |
-extern void mspack_destroy_chm_compressor(struct mschm_compressor *this); |
|
512 |
- |
|
513 |
-/** Destroys an existing CHM decompressor. |
|
514 |
- * @param this the #mschm_decompressor to destroy |
|
515 |
- */ |
|
516 |
-extern void mspack_destroy_chm_decompressor(struct mschm_decompressor *this); |
|
517 |
- |
|
518 |
- |
|
519 |
-/** Creates a new LIT compressor. |
|
520 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
521 |
- * @return a #mslit_compressor or NULL |
|
522 |
- */ |
|
523 |
-extern struct mslit_compressor * |
|
524 |
- mspack_create_lit_compressor(struct mspack_system *sys); |
|
525 |
- |
|
526 |
-/** Creates a new LIT decompressor. |
|
527 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
528 |
- * @return a #mslit_decompressor or NULL |
|
529 |
- */ |
|
530 |
-extern struct mslit_decompressor * |
|
531 |
- mspack_create_lit_decompressor(struct mspack_system *sys); |
|
532 |
- |
|
533 |
-/** Destroys an existing LIT compressor. |
|
534 |
- * @param this the #mslit_compressor to destroy |
|
535 |
- */ |
|
536 |
-extern void mspack_destroy_lit_compressor(struct mslit_compressor *this); |
|
537 |
- |
|
538 |
-/** Destroys an existing LIT decompressor. |
|
539 |
- * @param this the #mslit_decompressor to destroy |
|
540 |
- */ |
|
541 |
-extern void mspack_destroy_lit_decompressor(struct mslit_decompressor *this); |
|
542 |
- |
|
543 |
- |
|
544 |
-/** Creates a new HLP compressor. |
|
545 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
546 |
- * @return a #mshlp_compressor or NULL |
|
547 |
- */ |
|
548 |
-extern struct mshlp_compressor * |
|
549 |
- mspack_create_hlp_compressor(struct mspack_system *sys); |
|
550 |
- |
|
551 |
-/** Creates a new HLP decompressor. |
|
552 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
553 |
- * @return a #mshlp_decompressor or NULL |
|
554 |
- */ |
|
555 |
-extern struct mshlp_decompressor * |
|
556 |
- mspack_create_hlp_decompressor(struct mspack_system *sys); |
|
557 |
- |
|
558 |
-/** Destroys an existing hlp compressor. |
|
559 |
- * @param this the #mshlp_compressor to destroy |
|
560 |
- */ |
|
561 |
-extern void mspack_destroy_hlp_compressor(struct mshlp_compressor *this); |
|
562 |
- |
|
563 |
-/** Destroys an existing hlp decompressor. |
|
564 |
- * @param this the #mshlp_decompressor to destroy |
|
565 |
- */ |
|
566 |
-extern void mspack_destroy_hlp_decompressor(struct mshlp_decompressor *this); |
|
567 |
- |
|
568 |
- |
|
569 |
-/** Creates a new SZDD compressor. |
|
570 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
571 |
- * @return a #msszdd_compressor or NULL |
|
572 |
- */ |
|
573 |
-extern struct msszdd_compressor * |
|
574 |
- mspack_create_szdd_compressor(struct mspack_system *sys); |
|
575 |
- |
|
576 |
-/** Creates a new SZDD decompressor. |
|
577 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
578 |
- * @return a #msszdd_decompressor or NULL |
|
579 |
- */ |
|
580 |
-extern struct msszdd_decompressor * |
|
581 |
- mspack_create_szdd_decompressor(struct mspack_system *sys); |
|
582 |
- |
|
583 |
-/** Destroys an existing SZDD compressor. |
|
584 |
- * @param this the #msszdd_compressor to destroy |
|
585 |
- */ |
|
586 |
-extern void mspack_destroy_szdd_compressor(struct msszdd_compressor *this); |
|
587 |
- |
|
588 |
-/** Destroys an existing SZDD decompressor. |
|
589 |
- * @param this the #msszdd_decompressor to destroy |
|
590 |
- */ |
|
591 |
-extern void mspack_destroy_szdd_decompressor(struct msszdd_decompressor *this); |
|
592 |
- |
|
593 |
- |
|
594 |
-/** Creates a new KWAJ compressor. |
|
595 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
596 |
- * @return a #mskwaj_compressor or NULL |
|
597 |
- */ |
|
598 |
-extern struct mskwaj_compressor * |
|
599 |
- mspack_create_kwaj_compressor(struct mspack_system *sys); |
|
600 |
- |
|
601 |
-/** Creates a new KWAJ decompressor. |
|
602 |
- * @param sys a custom mspack_system structure, or NULL to use the default |
|
603 |
- * @return a #mskwaj_decompressor or NULL |
|
604 |
- */ |
|
605 |
-extern struct mskwaj_decompressor * |
|
606 |
- mspack_create_kwaj_decompressor(struct mspack_system *sys); |
|
607 |
- |
|
608 |
-/** Destroys an existing KWAJ compressor. |
|
609 |
- * @param this the #mskwaj_compressor to destroy |
|
610 |
- */ |
|
611 |
-extern void mspack_destroy_kwaj_compressor(struct mskwaj_compressor *this); |
|
612 |
- |
|
613 |
-/** Destroys an existing KWAJ decompressor. |
|
614 |
- * @param this the #mskwaj_decompressor to destroy |
|
615 |
- */ |
|
616 |
-extern void mspack_destroy_kwaj_decompressor(struct mskwaj_decompressor *this); |
|
617 |
- |
|
618 |
- |
|
619 |
-/* --- support for .CAB (MS Cabinet) file format --------------------------- */ |
|
620 |
- |
|
621 |
-/** |
|
622 |
- * A structure which represents a single cabinet file. |
|
623 |
- * |
|
624 |
- * All fields are READ ONLY. |
|
625 |
- * |
|
626 |
- * If this cabinet is part of a merged cabinet set, the #files and #folders |
|
627 |
- * fields are common to all cabinets in the set, and will be identical. |
|
628 |
- * |
|
629 |
- * @see mscab_decompressor::open(), mscab_decompressor::close(), |
|
630 |
- * mscab_decompressor::search() |
|
631 |
- */ |
|
632 |
-struct mscabd_cabinet { |
|
633 |
- /** |
|
634 |
- * The next cabinet in a chained list, if this cabinet was opened with |
|
635 |
- * mscab_decompressor::search(). May be NULL to mark the end of the |
|
636 |
- * list. |
|
637 |
- */ |
|
638 |
- struct mscabd_cabinet *next; |
|
639 |
- |
|
640 |
- /** |
|
641 |
- * The filename of the cabinet. More correctly, the filename of the |
|
642 |
- * physical file that the cabinet resides in. This is given by the |
|
643 |
- * library user and may be in any format. |
|
644 |
- */ |
|
645 |
- char *filename; |
|
646 |
- |
|
647 |
- int desc; |
|
648 |
- |
|
649 |
- |
|
650 |
- /** The file offset of cabinet within the physical file it resides in. */ |
|
651 |
- off_t base_offset; |
|
652 |
- |
|
653 |
- /** The length of the cabinet file in bytes. */ |
|
654 |
- unsigned int length; |
|
655 |
- |
|
656 |
- /** The previous cabinet in a cabinet set, or NULL. */ |
|
657 |
- struct mscabd_cabinet *prevcab; |
|
658 |
- |
|
659 |
- /** The next cabinet in a cabinet set, or NULL. */ |
|
660 |
- struct mscabd_cabinet *nextcab; |
|
661 |
- |
|
662 |
- /** The filename of the previous cabinet in a cabinet set, or NULL. */ |
|
663 |
- char *prevname; |
|
664 |
- |
|
665 |
- /** The filename of the next cabinet in a cabinet set, or NULL. */ |
|
666 |
- char *nextname; |
|
667 |
- |
|
668 |
- /** The name of the disk containing the previous cabinet in a cabinet |
|
669 |
- * set, or NULL. |
|
670 |
- */ |
|
671 |
- char *previnfo; |
|
672 |
- |
|
673 |
- /** The name of the disk containing the next cabinet in a cabinet set, |
|
674 |
- * or NULL. |
|
675 |
- */ |
|
676 |
- char *nextinfo; |
|
677 |
- |
|
678 |
- /** A list of all files in the cabinet or cabinet set. */ |
|
679 |
- struct mscabd_file *files; |
|
680 |
- |
|
681 |
- /** A list of all folders in the cabinet or cabinet set. */ |
|
682 |
- struct mscabd_folder *folders; |
|
683 |
- |
|
684 |
- /** |
|
685 |
- * The set ID of the cabinet. All cabinets in the same set should have |
|
686 |
- * the same set ID. |
|
687 |
- */ |
|
688 |
- unsigned short set_id; |
|
689 |
- |
|
690 |
- /** |
|
691 |
- * The index number of the cabinet within the set. Numbering should |
|
692 |
- * start from 0 for the first cabinet in the set, and increment by 1 for |
|
693 |
- * each following cabinet. |
|
694 |
- */ |
|
695 |
- unsigned short set_index; |
|
696 |
- |
|
697 |
- /** |
|
698 |
- * The number of bytes reserved in the header area of the cabinet. |
|
699 |
- * |
|
700 |
- * If this is non-zero and flags has MSCAB_HDR_RESV set, this data can |
|
701 |
- * be read by the calling application. It is of the given length, |
|
702 |
- * located at offset (base_offset + MSCAB_HDR_RESV_OFFSET) in the |
|
703 |
- * cabinet file. |
|
704 |
- * |
|
705 |
- * @see flags |
|
706 |
- */ |
|
707 |
- unsigned short header_resv; |
|
708 |
- |
|
709 |
- /** |
|
710 |
- * Header flags. |
|
711 |
- * |
|
712 |
- * - MSCAB_HDR_PREVCAB indicates the cabinet is part of a cabinet set, and |
|
713 |
- * has a predecessor cabinet. |
|
714 |
- * - MSCAB_HDR_NEXTCAB indicates the cabinet is part of a cabinet set, and |
|
715 |
- * has a successor cabinet. |
|
716 |
- * - MSCAB_HDR_RESV indicates the cabinet has reserved header space. |
|
717 |
- * |
|
718 |
- * @see prevname, previnfo, nextname, nextinfo, header_resv |
|
719 |
- */ |
|
720 |
- int flags; |
|
721 |
-}; |
|
722 |
- |
|
723 |
-/** Offset from start of cabinet to the reserved header data (if present). */ |
|
724 |
-#define MSCAB_HDR_RESV_OFFSET (0x28) |
|
725 |
- |
|
726 |
-/** Cabinet header flag: cabinet has a predecessor */ |
|
727 |
-#define MSCAB_HDR_PREVCAB (0x01) |
|
728 |
-/** Cabinet header flag: cabinet has a successor */ |
|
729 |
-#define MSCAB_HDR_NEXTCAB (0x02) |
|
730 |
-/** Cabinet header flag: cabinet has reserved header space */ |
|
731 |
-#define MSCAB_HDR_RESV (0x04) |
|
732 |
- |
|
733 |
-/** |
|
734 |
- * A structure which represents a single folder in a cabinet or cabinet set. |
|
735 |
- * |
|
736 |
- * All fields are READ ONLY. |
|
737 |
- * |
|
738 |
- * A folder is a single compressed stream of data. When uncompressed, it |
|
739 |
- * holds the data of one or more files. A folder may be split across more |
|
740 |
- * than one cabinet. |
|
741 |
- */ |
|
742 |
-struct mscabd_folder { |
|
743 |
- /** |
|
744 |
- * A pointer to the next folder in this cabinet or cabinet set, or NULL |
|
745 |
- * if this is the final folder. |
|
746 |
- */ |
|
747 |
- struct mscabd_folder *next; |
|
748 |
- |
|
749 |
- /** |
|
750 |
- * The compression format used by this folder. |
|
751 |
- * |
|
752 |
- * The macro MSCABD_COMP_METHOD() should be used on this field to get |
|
753 |
- * the algorithm used. The macro MSCABD_COMP_LEVEL() should be used to get |
|
754 |
- * the "compression level". |
|
755 |
- * |
|
756 |
- * @see MSCABD_COMP_METHOD(), MSCABD_COMP_LEVEL() |
|
757 |
- */ |
|
758 |
- int comp_type; |
|
759 |
- |
|
760 |
- /** |
|
761 |
- * The total number of data blocks used by this folder. This includes |
|
762 |
- * data blocks present in other files, if this folder spans more than |
|
763 |
- * one cabinet. |
|
764 |
- */ |
|
765 |
- unsigned int num_blocks; |
|
766 |
-}; |
|
767 |
- |
|
768 |
-/** |
|
769 |
- * Returns the compression method used by a folder. |
|
770 |
- * |
|
771 |
- * @param comp_type a mscabd_folder::comp_type value |
|
772 |
- * @return one of #MSCAB_COMP_NONE, #MSCAB_COMP_MSZIP, #MSCAB_COMP_QUANTUM |
|
773 |
- * or #MSCAB_COMP_LZX |
|
774 |
- */ |
|
775 |
-#define MSCABD_COMP_METHOD(comp_type) ((comp_type) & 0x0F) |
|
776 |
-/** |
|
777 |
- * Returns the compression level used by a folder. |
|
778 |
- * |
|
779 |
- * @param comp_type a mscabd_folder::comp_type value |
|
780 |
- * @return the compression level. This is only defined by LZX and Quantum |
|
781 |
- * compression |
|
782 |
- */ |
|
783 |
-#define MSCABD_COMP_LEVEL(comp_type) (((comp_type) >> 8) & 0x1F) |
|
784 |
- |
|
785 |
-/** Compression mode: no compression. */ |
|
786 |
-#define MSCAB_COMP_NONE (0) |
|
787 |
-/** Compression mode: MSZIP (deflate) compression. */ |
|
788 |
-#define MSCAB_COMP_MSZIP (1) |
|
789 |
-/** Compression mode: Quantum compression */ |
|
790 |
-#define MSCAB_COMP_QUANTUM (2) |
|
791 |
-/** Compression mode: LZX compression */ |
|
792 |
-#define MSCAB_COMP_LZX (3) |
|
793 |
- |
|
794 |
-/** |
|
795 |
- * A structure which represents a single file in a cabinet or cabinet set. |
|
796 |
- * |
|
797 |
- * All fields are READ ONLY. |
|
798 |
- */ |
|
799 |
-struct mscabd_file { |
|
800 |
- /** |
|
801 |
- * The next file in the cabinet or cabinet set, or NULL if this is the |
|
802 |
- * final file. |
|
803 |
- */ |
|
804 |
- struct mscabd_file *next; |
|
805 |
- |
|
806 |
- /** |
|
807 |
- * The filename of the file. |
|
808 |
- * |
|
809 |
- * A null terminated string of up to 255 bytes in length, it may be in |
|
810 |
- * either ISO-8859-1 or UTF8 format, depending on the file attributes. |
|
811 |
- * |
|
812 |
- * @see attribs |
|
813 |
- */ |
|
814 |
- char *filename; |
|
815 |
- |
|
816 |
- /** The uncompressed length of the file, in bytes. */ |
|
817 |
- unsigned int length; |
|
818 |
- |
|
819 |
- /** |
|
820 |
- * File attributes. |
|
821 |
- * |
|
822 |
- * The following attributes are defined: |
|
823 |
- * - #MSCAB_ATTRIB_RDONLY indicates the file is write protected. |
|
824 |
- * - #MSCAB_ATTRIB_HIDDEN indicates the file is hidden. |
|
825 |
- * - #MSCAB_ATTRIB_SYSTEM indicates the file is a operating system file. |
|
826 |
- * - #MSCAB_ATTRIB_ARCH indicates the file is "archived". |
|
827 |
- * - #MSCAB_ATTRIB_EXEC indicates the file is an executable program. |
|
828 |
- * - #MSCAB_ATTRIB_UTF_NAME indicates the filename is in UTF8 format rather |
|
829 |
- * than ISO-8859-1. |
|
830 |
- */ |
|
831 |
- int attribs; |
|
832 |
- |
|
833 |
- /** File's last modified time, hour field. */ |
|
834 |
- char time_h; |
|
835 |
- /** File's last modified time, minute field. */ |
|
836 |
- char time_m; |
|
837 |
- /** File's last modified time, second field. */ |
|
838 |
- char time_s; |
|
839 |
- |
|
840 |
- /** File's last modified date, day field. */ |
|
841 |
- char date_d; |
|
842 |
- /** File's last modified date, month field. */ |
|
843 |
- char date_m; |
|
844 |
- /** File's last modified date, year field. */ |
|
845 |
- int date_y; |
|
846 |
- |
|
847 |
- /** A pointer to the folder that contains this file. */ |
|
848 |
- struct mscabd_folder *folder; |
|
849 |
- |
|
850 |
- /** The uncompressed offset of this file in its folder. */ |
|
851 |
- unsigned int offset; |
|
852 |
-}; |
|
853 |
- |
|
854 |
-/** mscabd_file::attribs attribute: file is read-only. */ |
|
855 |
-#define MSCAB_ATTRIB_RDONLY (0x01) |
|
856 |
-/** mscabd_file::attribs attribute: file is hidden. */ |
|
857 |
-#define MSCAB_ATTRIB_HIDDEN (0x02) |
|
858 |
-/** mscabd_file::attribs attribute: file is an operating system file. */ |
|
859 |
-#define MSCAB_ATTRIB_SYSTEM (0x04) |
|
860 |
-/** mscabd_file::attribs attribute: file is "archived". */ |
|
861 |
-#define MSCAB_ATTRIB_ARCH (0x20) |
|
862 |
-/** mscabd_file::attribs attribute: file is an executable program. */ |
|
863 |
-#define MSCAB_ATTRIB_EXEC (0x40) |
|
864 |
-/** mscabd_file::attribs attribute: filename is UTF8, not ISO-8859-1. */ |
|
865 |
-#define MSCAB_ATTRIB_UTF_NAME (0x80) |
|
866 |
- |
|
867 |
-/** mscab_decompressor::set_param() parameter: search buffer size. */ |
|
868 |
-#define MSCABD_PARAM_SEARCHBUF (0) |
|
869 |
-/** mscab_decompressor::set_param() parameter: repair MS-ZIP streams? */ |
|
870 |
-#define MSCABD_PARAM_FIXMSZIP (1) |
|
871 |
-/** mscab_decompressor::set_param() parameter: size of decompression buffer */ |
|
872 |
-#define MSCABD_PARAM_DECOMPBUF (2) |
|
873 |
- |
|
874 |
-/** TODO */ |
|
875 |
-struct mscab_compressor { |
|
876 |
- int dummy; |
|
877 |
-}; |
|
878 |
- |
|
879 |
-/** |
|
880 |
- * A decompressor for .CAB (Microsoft Cabinet) files |
|
881 |
- * |
|
882 |
- * All fields are READ ONLY. |
|
883 |
- * |
|
884 |
- * @see mspack_create_cab_decompressor(), mspack_destroy_cab_decompressor() |
|
885 |
- */ |
|
886 |
-struct mscab_decompressor { |
|
887 |
- /** |
|
888 |
- * Opens a cabinet file and reads its contents. |
|
889 |
- * |
|
890 |
- * If the file opened is a valid cabinet file, all headers will be read |
|
891 |
- * and a mscabd_cabinet structure will be returned, with a full list of |
|
892 |
- * folders and files. |
|
893 |
- * |
|
894 |
- * In the case of an error occuring, NULL is returned and the error code |
|
895 |
- * is available from last_error(). |
|
896 |
- * |
|
897 |
- * The filename pointer should be considered "in use" until close() is |
|
898 |
- * called on the cabinet. |
|
899 |
- * |
|
900 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
901 |
- * instance being called |
|
902 |
- * @param filename the filename of the cabinet file. This is passed |
|
903 |
- * directly to mspack_system::open(). |
|
904 |
- * @return a pointer to a mscabd_cabinet structure, or NULL on failure |
|
905 |
- * @see close(), search(), last_error() |
|
906 |
- */ |
|
907 |
- struct mscabd_cabinet * (*open) (struct mscab_decompressor *this, |
|
908 |
- char *filename); |
|
909 |
- |
|
910 |
- struct mscabd_cabinet * (*dopen) (struct mscab_decompressor *this, |
|
911 |
- int desc); |
|
912 |
- /** |
|
913 |
- * Closes a previously opened cabinet or cabinet set. |
|
914 |
- * |
|
915 |
- * This closes a cabinet, all cabinets associated with it via the |
|
916 |
- * mscabd_cabinet::next, mscabd_cabinet::prevcab and |
|
917 |
- * mscabd_cabinet::nextcab pointers, and all folders and files. All |
|
918 |
- * memory used by these entities is freed. |
|
919 |
- * |
|
920 |
- * The cabinet pointer is now invalid and cannot be used again. All |
|
921 |
- * mscabd_folder and mscabd_file pointers from that cabinet or cabinet |
|
922 |
- * set are also now invalid, and cannot be used again. |
|
923 |
- * |
|
924 |
- * If the cabinet pointer given was created using search(), it MUST be |
|
925 |
- * the cabinet pointer returned by search() and not one of the later |
|
926 |
- * cabinet pointers further along the mscabd_cabinet::next chain. |
|
927 |
- |
|
928 |
- * If extra cabinets have been added using append() or prepend(), these |
|
929 |
- * will all be freed, even if the cabinet pointer given is not the first |
|
930 |
- * cabinet in the set. Do NOT close() more than one cabinet in the set. |
|
931 |
- * |
|
932 |
- * The mscabd_cabinet::filename is not freed by the library, as it is |
|
933 |
- * not allocated by the library. The caller should free this itself if |
|
934 |
- * necessary, before it is lost forever. |
|
935 |
- * |
|
936 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
937 |
- * instance being called |
|
938 |
- * @param cab the cabinet to close |
|
939 |
- * @see open(), search(), append(), prepend() |
|
940 |
- */ |
|
941 |
- void (*close)(struct mscab_decompressor *this, |
|
942 |
- struct mscabd_cabinet *cab); |
|
943 |
- |
|
944 |
- /** |
|
945 |
- * Searches a regular file for embedded cabinets. |
|
946 |
- * |
|
947 |
- * This opens a normal file with the given filename and will search the |
|
948 |
- * entire file for embedded cabinet files |
|
949 |
- * |
|
950 |
- * If any cabinets are found, the equivalent of open() is called on each |
|
951 |
- * potential cabinet file at the offset it was found. All successfully |
|
952 |
- * open()ed cabinets are kept in a list. |
|
953 |
- * |
|
954 |
- * The first cabinet found will be returned directly as the result of |
|
955 |
- * this method. Any further cabinets found will be chained in a list |
|
956 |
- * using the mscabd_cabinet::next field. |
|
957 |
- * |
|
958 |
- * In the case of an error occuring anywhere other than the simulated |
|
959 |
- * open(), NULL is returned and the error code is available from |
|
960 |
- * last_error(). |
|
961 |
- * |
|
962 |
- * If no error occurs, but no cabinets can be found in the file, NULL is |
|
963 |
- * returned and last_error() returns MSPACK_ERR_OK. |
|
964 |
- * |
|
965 |
- * The filename pointer should be considered in use until close() is |
|
966 |
- * called on the cabinet. |
|
967 |
- * |
|
968 |
- * close() should only be called on the result of search(), not on any |
|
969 |
- * subsequent cabinets in the mscabd_cabinet::next chain. |
|
970 |
- * |
|
971 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
972 |
- * instance being called |
|
973 |
- * @param filename the filename of the file to search for cabinets. This |
|
974 |
- * is passed directly to mspack_system::open(). |
|
975 |
- * @return a pointer to a mscabd_cabinet structure, or NULL |
|
976 |
- * @see close(), open(), last_error() |
|
977 |
- */ |
|
978 |
- struct mscabd_cabinet * (*search) (struct mscab_decompressor *this, |
|
979 |
- char *filename); |
|
980 |
- |
|
981 |
- struct mscabd_cabinet * (*dsearch) (struct mscab_decompressor *this, |
|
982 |
- int desc); |
|
983 |
- |
|
984 |
- /** |
|
985 |
- * Appends one mscabd_cabinet to another, forming or extending a cabinet |
|
986 |
- * set. |
|
987 |
- * |
|
988 |
- * This will attempt to append one cabinet to another such that |
|
989 |
- * <tt>(cab->nextcab == nextcab) && (nextcab->prevcab == cab)</tt> and |
|
990 |
- * any folders split between the two cabinets are merged. |
|
991 |
- * |
|
992 |
- * The cabinets MUST be part of a cabinet set -- a cabinet set is a |
|
993 |
- * cabinet that spans more than one physical cabinet file on disk -- and |
|
994 |
- * must be appropriately matched. |
|
995 |
- * |
|
996 |
- * It can be determined if a cabinet has further parts to load by |
|
997 |
- * examining the mscabd_cabinet::flags field: |
|
998 |
- * |
|
999 |
- * - if <tt>(flags & MSCAB_HDR_PREVCAB)</tt> is non-zero, there is a |
|
1000 |
- * predecessor cabinet to open() and prepend(). Its MS-DOS |
|
1001 |
- * case-insensitive filename is mscabd_cabinet::prevname |
|
1002 |
- * - if <tt>(flags & MSCAB_HDR_NEXTCAB)</tt> is non-zero, there is a |
|
1003 |
- * successor cabinet to open() and append(). Its MS-DOS case-insensitive |
|
1004 |
- * filename is mscabd_cabinet::nextname |
|
1005 |
- * |
|
1006 |
- * If the cabinets do not match, an error code will be returned. Neither |
|
1007 |
- * cabinet has been altered, and both should be closed seperately. |
|
1008 |
- * |
|
1009 |
- * Files and folders in a cabinet set are a single entity. All cabinets |
|
1010 |
- * in a set use the same file list, which is updated as cabinets in the |
|
1011 |
- * set are added. All pointers to mscabd_folder and mscabd_file |
|
1012 |
- * structures in either cabinet must be discarded and re-obtained after |
|
1013 |
- * merging. |
|
1014 |
- * |
|
1015 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
1016 |
- * instance being called |
|
1017 |
- * @param cab the cabinet which will be appended to, |
|
1018 |
- * predecessor of nextcab |
|
1019 |
- * @param nextcab the cabinet which will be appended, |
|
1020 |
- * successor of cab |
|
1021 |
- * @return an error code, or MSPACK_ERR_OK if successful |
|
1022 |
- * @see prepend(), open(), close() |
|
1023 |
- */ |
|
1024 |
- int (*append) (struct mscab_decompressor *this, |
|
1025 |
- struct mscabd_cabinet *cab, |
|
1026 |
- struct mscabd_cabinet *nextcab); |
|
1027 |
- |
|
1028 |
- /** |
|
1029 |
- * Prepends one mscabd_cabinet to another, forming or extending a |
|
1030 |
- * cabinet set. |
|
1031 |
- * |
|
1032 |
- * This will attempt to prepend one cabinet to another, such that |
|
1033 |
- * <tt>(cab->prevcab == prevcab) && (prevcab->nextcab == cab)</tt>. In |
|
1034 |
- * all other respects, it is identical to append(). See append() for the |
|
1035 |
- * full documentation. |
|
1036 |
- * |
|
1037 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
1038 |
- * instance being called |
|
1039 |
- * @param cab the cabinet which will be prepended to, |
|
1040 |
- * successor of prevcab |
|
1041 |
- * @param prevcab the cabinet which will be prepended, |
|
1042 |
- * predecessor of cab |
|
1043 |
- * @return an error code, or MSPACK_ERR_OK if successful |
|
1044 |
- * @see append(), open(), close() |
|
1045 |
- */ |
|
1046 |
- int (*prepend) (struct mscab_decompressor *this, |
|
1047 |
- struct mscabd_cabinet *cab, |
|
1048 |
- struct mscabd_cabinet *prevcab); |
|
1049 |
- |
|
1050 |
- /** |
|
1051 |
- * Extracts a file from a cabinet or cabinet set. |
|
1052 |
- * |
|
1053 |
- * This extracts a compressed file in a cabinet and writes it to the given |
|
1054 |
- * filename. |
|
1055 |
- * |
|
1056 |
- * The MS-DOS filename of the file, mscabd_file::filename, is NOT USED |
|
1057 |
- * by extract(). The caller must examine this MS-DOS filename, copy and |
|
1058 |
- * change it as necessary, create directories as necessary, and provide |
|
1059 |
- * the correct filename as a parameter, which will be passed unchanged |
|
1060 |
- * to the decompressor's mspack_system::open() |
|
1061 |
- * |
|
1062 |
- * If the file belongs to a split folder in a multi-part cabinet set, |
|
1063 |
- * and not enough parts of the cabinet set have been loaded and appended |
|
1064 |
- * or prepended, an error will be returned immediately. |
|
1065 |
- * |
|
1066 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
1067 |
- * instance being called |
|
1068 |
- * @param file the file to be decompressed |
|
1069 |
- * @param filename the filename of the file being written to |
|
1070 |
- * @return an error code, or MSPACK_ERR_OK if successful |
|
1071 |
- */ |
|
1072 |
- int (*extract)(struct mscab_decompressor *this, |
|
1073 |
- struct mscabd_file *file, |
|
1074 |
- char *filename); |
|
1075 |
- |
|
1076 |
- /** |
|
1077 |
- * Sets a CAB decompression engine parameter. |
|
1078 |
- * |
|
1079 |
- * The following parameters are defined: |
|
1080 |
- * - #MSCABD_PARAM_SEARCHBUF: How many bytes should be allocated as a |
|
1081 |
- * buffer when using search()? The minimum value is 4. The default |
|
1082 |
- * value is 32768. |
|
1083 |
- * - #MSCABD_PARAM_FIXMSZIP: If non-zero, extract() will ignore bad |
|
1084 |
- * checksums and recover from decompression errors in MS-ZIP |
|
1085 |
- * compressed folders. The default value is 0 (don't recover). |
|
1086 |
- * - #MSCABD_PARAM_DECOMPBUF: How many bytes should be used as an input |
|
1087 |
- * bit buffer by decompressors? The minimum value is 4. The default |
|
1088 |
- * value is 4096. |
|
1089 |
- * |
|
1090 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
1091 |
- * instance being called |
|
1092 |
- * @param param the parameter to set |
|
1093 |
- * @param value the value to set the parameter to |
|
1094 |
- * @return MSPACK_ERR_OK if all is OK, or MSPACK_ERR_ARGS if there |
|
1095 |
- * is a problem with either parameter or value. |
|
1096 |
- * @see search(), extract() |
|
1097 |
- */ |
|
1098 |
- int (*set_param)(struct mscab_decompressor *this, |
|
1099 |
- int param, |
|
1100 |
- int value); |
|
1101 |
- |
|
1102 |
- /** |
|
1103 |
- * Returns the error code set by the most recently called method. |
|
1104 |
- * |
|
1105 |
- * This is useful for open() and search(), which do not return an error |
|
1106 |
- * code directly. |
|
1107 |
- * |
|
1108 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
1109 |
- * instance being called |
|
1110 |
- * @return the most recent error code |
|
1111 |
- * @see open(), search() |
|
1112 |
- */ |
|
1113 |
- int (*last_error)(struct mscab_decompressor *); |
|
1114 |
-}; |
|
1115 |
- |
|
1116 |
-/* --- support for .CHM (HTMLHelp) file format ----------------------------- */ |
|
1117 |
- |
|
1118 |
-/** |
|
1119 |
- * A structure which represents a section of a CHM helpfile. |
|
1120 |
- * |
|
1121 |
- * All fields are READ ONLY. |
|
1122 |
- * |
|
1123 |
- * Not used directly, but used as a generic base type for |
|
1124 |
- * mschmd_sec_uncompressed and mschmd_sec_mscompressed. |
|
1125 |
- */ |
|
1126 |
-struct mschmd_section { |
|
1127 |
- /** A pointer to the CHM helpfile that contains this section. */ |
|
1128 |
- struct mschmd_header *chm; |
|
1129 |
- |
|
1130 |
- /** |
|
1131 |
- * The section ID. Either 0 for the uncompressed section |
|
1132 |
- * mschmd_sec_uncompressed, or 1 for the LZX compressed section |
|
1133 |
- * mschmd_sec_mscompressed. No other section IDs are known. |
|
1134 |
- */ |
|
1135 |
- unsigned int id; |
|
1136 |
-}; |
|
1137 |
- |
|
1138 |
-/** |
|
1139 |
- * A structure which represents the uncompressed section of a CHM helpfile. |
|
1140 |
- * |
|
1141 |
- * All fields are READ ONLY. |
|
1142 |
- */ |
|
1143 |
-struct mschmd_sec_uncompressed { |
|
1144 |
- /** Generic section data. */ |
|
1145 |
- struct mschmd_section base; |
|
1146 |
- |
|
1147 |
- /** The file offset of where this section begins in the CHM helpfile. */ |
|
1148 |
- off_t offset; |
|
1149 |
-}; |
|
1150 |
- |
|
1151 |
-/** |
|
1152 |
- * A structure which represents the compressed section of a CHM helpfile. |
|
1153 |
- * |
|
1154 |
- * All fields are READ ONLY. |
|
1155 |
- */ |
|
1156 |
-struct mschmd_sec_mscompressed { |
|
1157 |
- /** Generic section data. */ |
|
1158 |
- struct mschmd_section base; |
|
1159 |
- |
|
1160 |
- /** A pointer to the meta-file which represents all LZX compressed data. */ |
|
1161 |
- struct mschmd_file *content; |
|
1162 |
- |
|
1163 |
- /** A pointer to the file which contains the LZX control data. */ |
|
1164 |
- struct mschmd_file *control; |
|
1165 |
- |
|
1166 |
- /** A pointer to the file which contains the LZX reset table. */ |
|
1167 |
- struct mschmd_file *rtable; |
|
1168 |
-}; |
|
1169 |
- |
|
1170 |
-/** |
|
1171 |
- * A structure which represents a CHM helpfile. |
|
1172 |
- * |
|
1173 |
- * All fields are READ ONLY. |
|
1174 |
- */ |
|
1175 |
-struct mschmd_header { |
|
1176 |
- /** The version of the CHM file format used in this file. */ |
|
1177 |
- unsigned int version; |
|
1178 |
- |
|
1179 |
- /** |
|
1180 |
- * The "timestamp" of the CHM helpfile. |
|
1181 |
- * |
|
1182 |
- * It is the lower 32 bits of a 64-bit value representing the number of |
|
1183 |
- * centiseconds since 1601-01-01 00:00:00 UTC, plus 42. It is not useful |
|
1184 |
- * as a timestamp, but it is useful as a semi-unique ID. |
|
1185 |
- */ |
|
1186 |
- unsigned int timestamp; |
|
1187 |
- |
|
1188 |
- |
|
1189 |
- /** |
|
1190 |
- * The default Language and Country ID (LCID) of the user who ran the |
|
1191 |
- * HTMLHelp Compiler. This is not the language of the CHM file itself. |
|
1192 |
- */ |
|
1193 |
- unsigned int language; |
|
1194 |
- |
|
1195 |
- /** |
|
1196 |
- * The filename of the CHM helpfile. This is given by the library user |
|
1197 |
- * and may be in any format. |
|
1198 |
- */ |
|
1199 |
- char *filename; |
|
1200 |
- |
|
1201 |
- /** The length of the CHM helpfile, in bytes. */ |
|
1202 |
- off_t length; |
|
1203 |
- |
|
1204 |
- /** A list of all non-system files in the CHM helpfile. */ |
|
1205 |
- struct mschmd_file *files; |
|
1206 |
- |
|
1207 |
- /** |
|
1208 |
- * A list of all system files in the CHM helpfile. |
|
1209 |
- * |
|
1210 |
- * System files are files which begin with "::". They are meta-files |
|
1211 |
- * generated by the CHM creation process. |
|
1212 |
- */ |
|
1213 |
- struct mschmd_file *sysfiles; |
|
1214 |
- |
|
1215 |
- /** The section 0 (uncompressed) data in this CHM helpfile. */ |
|
1216 |
- struct mschmd_sec_uncompressed sec0; |
|
1217 |
- |
|
1218 |
- /** The section 1 (MSCompressed) data in this CHM helpfile. */ |
|
1219 |
- struct mschmd_sec_mscompressed sec1; |
|
1220 |
- |
|
1221 |
- /** The file offset of the first PMGL/PMGI directory chunk. */ |
|
1222 |
- off_t dir_offset; |
|
1223 |
- |
|
1224 |
- /** The number of PMGL/PMGI directory chunks in this CHM helpfile. */ |
|
1225 |
- unsigned int num_chunks; |
|
1226 |
- |
|
1227 |
- /** The size of each PMGL/PMGI chunk, in bytes. */ |
|
1228 |
- unsigned int chunk_size; |
|
1229 |
- |
|
1230 |
- /** The "density" of the quick-reference section in PMGL/PMGI chunks. */ |
|
1231 |
- unsigned int density; |
|
1232 |
- |
|
1233 |
- /** The depth of the index tree. |
|
1234 |
- * |
|
1235 |
- * - if 1, there are no PMGI chunks, only PMGL chunks. |
|
1236 |
- * - if 2, there is 1 PMGI chunk. All chunk indices point to PMGL chunks. |
|
1237 |
- * - if 3, the root PMGI chunk points to secondary PMGI chunks, which in |
|
1238 |
- * turn point to PMGL chunks. |
|
1239 |
- * - and so on... |
|
1240 |
- */ |
|
1241 |
- unsigned int depth; |
|
1242 |
- |
|
1243 |
- /** |
|
1244 |
- * The number of the root PGMI chunk. |
|
1245 |
- * |
|
1246 |
- * If there is no index in the CHM helpfile, this will be 0xFFFFFFFF. |
|
1247 |
- */ |
|
1248 |
- unsigned int index_root; |
|
1249 |
-}; |
|
1250 |
- |
|
1251 |
-/** |
|
1252 |
- * A structure which represents a file stored in a CHM helpfile. |
|
1253 |
- * |
|
1254 |
- * All fields are READ ONLY. |
|
1255 |
- */ |
|
1256 |
-struct mschmd_file { |
|
1257 |
- /** |
|
1258 |
- * A pointer to the next file in the list, or NULL if this is the final |
|
1259 |
- * file. |
|
1260 |
- */ |
|
1261 |
- struct mschmd_file *next; |
|
1262 |
- |
|
1263 |
- /** |
|
1264 |
- * A pointer to the section that this file is located in. Indirectly, |
|
1265 |
- * it also points to the CHM helpfile the file is located in. |
|
1266 |
- */ |
|
1267 |
- struct mschmd_section *section; |
|
1268 |
- |
|
1269 |
- /** The offset within the section data that this file is located at. */ |
|
1270 |
- off_t offset; |
|
1271 |
- |
|
1272 |
- /** The length of this file, in bytes */ |
|
1273 |
- off_t length; |
|
1274 |
- |
|
1275 |
- /** The filename of this file -- a null terminated string in UTF8. */ |
|
1276 |
- char *filename; |
|
1277 |
-}; |
|
1278 |
- |
|
1279 |
-/** TODO */ |
|
1280 |
-struct mschm_compressor { |
|
1281 |
- int dummy; |
|
1282 |
-}; |
|
1283 |
- |
|
1284 |
-/** |
|
1285 |
- * A decompressor for .CHM (Microsoft HTMLHelp) files |
|
1286 |
- * |
|
1287 |
- * All fields are READ ONLY. |
|
1288 |
- * |
|
1289 |
- * @see mspack_create_chm_decompressor(), mspack_destroy_chm_decompressor() |
|
1290 |
- */ |
|
1291 |
-struct mschm_decompressor { |
|
1292 |
- /** |
|
1293 |
- * Opens a CHM helpfile and reads its contents. |
|
1294 |
- * |
|
1295 |
- * If the file opened is a valid CHM helpfile, all headers will be read |
|
1296 |
- * and a mschmd_header structure will be returned, with a full list of |
|
1297 |
- * files. |
|
1298 |
- * |
|
1299 |
- * In the case of an error occuring, NULL is returned and the error code |
|
1300 |
- * is available from last_error(). |
|
1301 |
- * |
|
1302 |
- * The filename pointer should be considered "in use" until close() is |
|
1303 |
- * called on the CHM helpfile. |
|
1304 |
- * |
|
1305 |
- * @param this a self-referential pointer to the mschm_decompressor |
|
1306 |
- * instance being called |
|
1307 |
- * @param filename the filename of the CHM helpfile. This is passed |
|
1308 |
- * directly to mspack_system::open(). |
|
1309 |
- * @return a pointer to a mschmd_header structure, or NULL on failure |
|
1310 |
- * @see close() |
|
1311 |
- */ |
|
1312 |
- struct mschmd_header *(*open)(struct mschm_decompressor *this, |
|
1313 |
- char *filename); |
|
1314 |
- |
|
1315 |
- /** |
|
1316 |
- * Closes a previously opened CHM helpfile. |
|
1317 |
- * |
|
1318 |
- * This closes a CHM helpfile, frees the mschmd_header and all |
|
1319 |
- * mschmd_file structures associated with it (if any). This works on |
|
1320 |
- * both helpfiles opened with open() and helpfiles opened with |
|
1321 |
- * fast_open(). |
|
1322 |
- * |
|
1323 |
- * The CHM header pointer is now invalid and cannot be used again. All |
|
1324 |
- * mschmd_file pointers referencing that CHM are also now invalid, and |
|
1325 |
- * cannot be used again. |
|
1326 |
- * |
|
1327 |
- * @param this a self-referential pointer to the mschm_decompressor |
|
1328 |
- * instance being called |
|
1329 |
- * @param chm the CHM helpfile to close |
|
1330 |
- * @see open(), fast_open() |
|
1331 |
- */ |
|
1332 |
- void (*close)(struct mschm_decompressor *this, |
|
1333 |
- struct mschmd_header *chm); |
|
1334 |
- |
|
1335 |
- /** |
|
1336 |
- * Extracts a file from a CHM helpfile. |
|
1337 |
- * |
|
1338 |
- * This extracts a file from a CHM helpfile and writes it to the given |
|
1339 |
- * filename. The filename of the file, mscabd_file::filename, is not |
|
1340 |
- * used by extract(), but can be used by the caller as a guide for |
|
1341 |
- * constructing an appropriate filename. |
|
1342 |
- * |
|
1343 |
- * This method works both with files found in the mschmd_header::files |
|
1344 |
- * and mschmd_header::sysfiles list and mschmd_file structures generated |
|
1345 |
- * on the fly by fast_find(). |
|
1346 |
- * |
|
1347 |
- * @param this a self-referential pointer to the mscab_decompressor |
|
1348 |
- * instance being called |
|
1349 |
- * @param file the file to be decompressed |
|
1350 |
- * @param filename the filename of the file being written to |
|
1351 |
- * @return an error code, or MSPACK_ERR_OK if successful |
|
1352 |
- */ |
|
1353 |
- int (*extract)(struct mschm_decompressor *this, |
|
1354 |
- struct mschmd_file *file, |
|
1355 |
- char *filename); |
|
1356 |
- |
|
1357 |
- /** |
|
1358 |
- * Returns the error code set by the most recently called method. |
|
1359 |
- * |
|
1360 |
- * This is useful for open() and fast_open(), which do not return an |
|
1361 |
- * error code directly. |
|
1362 |
- * |
|
1363 |
- * @param this a self-referential pointer to the mschm_decompressor |
|
1364 |
- * instance being called |
|
1365 |
- * @return the most recent error code |
|
1366 |
- * @see open(), search() |
|
1367 |
- */ |
|
1368 |
- int (*last_error)(struct mschm_decompressor *this); |
|
1369 |
- |
|
1370 |
- /** |
|
1371 |
- * Opens a CHM helpfile quickly. |
|
1372 |
- * |
|
1373 |
- * If the file opened is a valid CHM helpfile, only essential headers |
|
1374 |
- * will be read. A mschmd_header structure will be still be returned, as |
|
1375 |
- * with open(), but the mschmd_header::files field will be NULL. No |
|
1376 |
- * files details will be automatically read. The fast_find() method |
|
1377 |
- * must be used to obtain file details. |
|
1378 |
- * |
|
1379 |
- * In the case of an error occuring, NULL is returned and the error code |
|
1380 |
- * is available from last_error(). |
|
1381 |
- * |
|
1382 |
- * The filename pointer should be considered "in use" until close() is |
|
1383 |
- * called on the CHM helpfile. |
|
1384 |
- * |
|
1385 |
- * @param this a self-referential pointer to the mschm_decompressor |
|
1386 |
- * instance being called |
|
1387 |
- * @param filename the filename of the CHM helpfile. This is passed |
|
1388 |
- * directly to mspack_system::open(). |
|
1389 |
- * @return a pointer to a mschmd_header structure, or NULL on failure |
|
1390 |
- * @see open(), close(), fast_find(), extract() |
|
1391 |
- */ |
|
1392 |
- struct mschmd_header *(*fast_open)(struct mschm_decompressor *this, |
|
1393 |
- char *filename); |
|
1394 |
- |
|
1395 |
- /** |
|
1396 |
- * Finds file details quickly. |
|
1397 |
- * |
|
1398 |
- * Instead of reading all CHM helpfile headers and building a list of |
|
1399 |
- * files, fast_open() and fast_find() are intended for finding file |
|
1400 |
- * details only when they are needed. The CHM file format includes an |
|
1401 |
- * on-disk file index to allow this. |
|
1402 |
- * |
|
1403 |
- * Given a case-sensitive filename, fast_find() will search the on-disk |
|
1404 |
- * index for that file. |
|
1405 |
- * |
|
1406 |
- * If the file was found, the caller-provided mschmd_file structure will |
|
1407 |
- * be filled out like so: |
|
1408 |
- * - section: the correct value for the found file |
|
1409 |
- * - offset: the correct value for the found file |
|
1410 |
- * - length: the correct value for the found file |
|
1411 |
- * - all other structure elements: NULL or 0 |
|
1412 |
- * |
|
1413 |
- * If the file was not found, MSPACK_ERR_OK will still be returned as the |
|
1414 |
- * result, but the caller-provided structure will be filled out like so: |
|
1415 |
- * - section: NULL |
|
1416 |
- * - offset: 0 |
|
1417 |
- * - length: 0 |
|
1418 |
- * - all other structure elements: NULL or 0 |
|
1419 |
- * |
|
1420 |
- * This method is intended to be used in conjunction with CHM helpfiles |
|
1421 |
- * opened with fast_open(), but it also works with helpfiles opened |
|
1422 |
- * using the regular open(). |
|
1423 |
- * |
|
1424 |
- * @param this a self-referential pointer to the mschm_decompressor |
|
1425 |
- * instance being called |
|
1426 |
- * @param chm the CHM helpfile to search for the file |
|
1427 |
- * @param filename the filename of the file to search for |
|
1428 |
- * @param f_ptr a pointer to a caller-provded mschmd_file structure |
|
1429 |
- * @param f_size <tt>sizeof(struct mschmd_file)</tt> |
|
1430 |
- * @return MSPACK_ERR_OK, or an error code |
|
1431 |
- * @see open(), close(), fast_find(), extract() |
|
1432 |
- */ |
|
1433 |
- int (*fast_find)(struct mschm_decompressor *this, |
|
1434 |
- struct mschmd_header *chm, |
|
1435 |
- char *filename, |
|
1436 |
- struct mschmd_file *f_ptr, |
|
1437 |
- int f_size); |
|
1438 |
-}; |
|
1439 |
- |
|
1440 |
-/* --- support for .LIT (EBook) file format -------------------------------- */ |
|
1441 |
- |
|
1442 |
-/** TODO */ |
|
1443 |
-struct mslit_compressor { |
|
1444 |
- int dummy; |
|
1445 |
-}; |
|
1446 |
- |
|
1447 |
-/** TODO */ |
|
1448 |
-struct mslit_decompressor { |
|
1449 |
- int dummy; |
|
1450 |
-}; |
|
1451 |
- |
|
1452 |
- |
|
1453 |
-/* --- support for .HLP (MS Help) file format ------------------------------ */ |
|
1454 |
- |
|
1455 |
-/** TODO */ |
|
1456 |
-struct mshlp_compressor { |
|
1457 |
- int dummy; |
|
1458 |
-}; |
|
1459 |
- |
|
1460 |
-/** TODO */ |
|
1461 |
-struct mshlp_decompressor { |
|
1462 |
- int dummy; |
|
1463 |
-}; |
|
1464 |
- |
|
1465 |
- |
|
1466 |
-/* --- support for SZDD file format ---------------------------------------- */ |
|
1467 |
- |
|
1468 |
-/** TODO */ |
|
1469 |
-struct msszdd_compressor { |
|
1470 |
- int dummy; |
|
1471 |
-}; |
|
1472 |
- |
|
1473 |
-/** TODO */ |
|
1474 |
-struct msszdd_decompressor { |
|
1475 |
- int dummy; |
|
1476 |
-}; |
|
1477 |
- |
|
1478 |
-/* --- support for KWAJ file format ---------------------------------------- */ |
|
1479 |
- |
|
1480 |
-/** TODO */ |
|
1481 |
-struct mskwaj_compressor { |
|
1482 |
- int dummy; |
|
1483 |
-}; |
|
1484 |
- |
|
1485 |
-/** TODO */ |
|
1486 |
-struct mskwaj_decompressor { |
|
1487 |
- int dummy; |
|
1488 |
-}; |
|
1489 |
- |
|
1490 |
-#ifdef __cplusplus |
|
1491 |
-}; |
|
1492 |
-#endif |
|
1493 |
- |
|
1494 |
-#endif |
1495 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,114 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * The deflate method was created by Phil Katz. MSZIP is equivalent to the |
|
5 |
- * deflate method. |
|
6 |
- * |
|
7 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
8 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
9 |
- * |
|
10 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
11 |
- */ |
|
12 |
- |
|
13 |
-#ifndef MSPACK_MSZIP_H |
|
14 |
-#define MSPACK_MSZIP_H 1 |
|
15 |
- |
|
16 |
-/* MSZIP (deflate) compression / (inflate) decompression definitions */ |
|
17 |
- |
|
18 |
-#define MSZIP_FRAME_SIZE (32768) /* size of LZ history window */ |
|
19 |
-#define MSZIP_MAX_HUFFBITS (16) /* maximum huffman code length */ |
|
20 |
-#define MSZIP_LITERAL_MAXSYMBOLS (288) /* literal/length huffman tree */ |
|
21 |
-#define MSZIP_LITERAL_TABLEBITS (9) |
|
22 |
-#define MSZIP_DISTANCE_MAXSYMBOLS (32) /* distance huffman tree */ |
|
23 |
-#define MSZIP_DISTANCE_TABLEBITS (6) |
|
24 |
- |
|
25 |
-/* if there are less direct lookup entries than symbols, the longer |
|
26 |
- * code pointers will be <= maxsymbols. This must not happen, or we |
|
27 |
- * will decode entries badly */ |
|
28 |
-#if (1 << MSZIP_LITERAL_TABLEBITS) < (MSZIP_LITERAL_MAXSYMBOLS * 2) |
|
29 |
-# define MSZIP_LITERAL_TABLESIZE (MSZIP_LITERAL_MAXSYMBOLS * 4) |
|
30 |
-#else |
|
31 |
-# define MSZIP_LITERAL_TABLESIZE ((1 << MSZIP_LITERAL_TABLEBITS) + \ |
|
32 |
- (MSZIP_LITERAL_MAXSYMBOLS * 2)) |
|
33 |
-#endif |
|
34 |
- |
|
35 |
-#if (1 << MSZIP_DISTANCE_TABLEBITS) < (MSZIP_DISTANCE_MAXSYMBOLS * 2) |
|
36 |
-# define MSZIP_DISTANCE_TABLESIZE (MSZIP_DISTANCE_MAXSYMBOLS * 4) |
|
37 |
-#else |
|
38 |
-# define MSZIP_DISTANCE_TABLESIZE ((1 << MSZIP_DISTANCE_TABLEBITS) + \ |
|
39 |
- (MSZIP_DISTANCE_MAXSYMBOLS * 2)) |
|
40 |
-#endif |
|
41 |
- |
|
42 |
-struct mszipd_stream { |
|
43 |
- struct mspack_system *sys; /* I/O routines */ |
|
44 |
- struct mspack_file *input; /* input file handle */ |
|
45 |
- struct mspack_file *output; /* output file handle */ |
|
46 |
- unsigned int window_posn; /* offset within window */ |
|
47 |
- |
|
48 |
- /* inflate() will call this whenever the window should be emptied. */ |
|
49 |
- int (*flush_window)(struct mszipd_stream *, unsigned int); |
|
50 |
- |
|
51 |
- int error, repair_mode, bytes_output; |
|
52 |
- |
|
53 |
- /* I/O buffering */ |
|
54 |
- unsigned char *inbuf, *i_ptr, *i_end, *o_ptr, *o_end; |
|
55 |
- unsigned int bit_buffer, bits_left, inbuf_size; |
|
56 |
- |
|
57 |
- |
|
58 |
- /* huffman code lengths */ |
|
59 |
- unsigned char LITERAL_len[MSZIP_LITERAL_MAXSYMBOLS]; |
|
60 |
- unsigned char DISTANCE_len[MSZIP_DISTANCE_MAXSYMBOLS]; |
|
61 |
- |
|
62 |
- /* huffman decoding tables */ |
|
63 |
- unsigned short LITERAL_table [MSZIP_LITERAL_TABLESIZE]; |
|
64 |
- unsigned short DISTANCE_table[MSZIP_DISTANCE_TABLESIZE]; |
|
65 |
- |
|
66 |
- /* 32kb history window */ |
|
67 |
- unsigned char window[MSZIP_FRAME_SIZE]; |
|
68 |
-}; |
|
69 |
- |
|
70 |
-/* allocates MS-ZIP decompression stream for decoding the given stream. |
|
71 |
- * |
|
72 |
- * - uses system->alloc() to allocate memory |
|
73 |
- * |
|
74 |
- * - returns NULL if not enough memory |
|
75 |
- * |
|
76 |
- * - input_buffer_size is how many bytes to use as an input bitstream buffer |
|
77 |
- * |
|
78 |
- * - if repair_mode is non-zero, errors in decompression will be skipped |
|
79 |
- * and 'holes' left will be filled with zero bytes. This allows at least |
|
80 |
- * a partial recovery of erroneous data. |
|
81 |
- */ |
|
82 |
-extern struct mszipd_stream *mszipd_init(struct mspack_system *system, |
|
83 |
- struct mspack_file *input, |
|
84 |
- struct mspack_file *output, |
|
85 |
- int input_buffer_size, |
|
86 |
- int repair_mode); |
|
87 |
- |
|
88 |
-/* decompresses, or decompresses more of, an MS-ZIP stream. |
|
89 |
- * |
|
90 |
- * - out_bytes of data will be decompressed and the function will return |
|
91 |
- * with an MSPACK_ERR_OK return code. |
|
92 |
- * |
|
93 |
- * - decompressing will stop as soon as out_bytes is reached. if the true |
|
94 |
- * amount of bytes decoded spills over that amount, they will be kept for |
|
95 |
- * a later invocation of mszipd_decompress(). |
|
96 |
- * |
|
97 |
- * - the output bytes will be passed to the system->write() function given in |
|
98 |
- * mszipd_init(), using the output file handle given in mszipd_init(). More |
|
99 |
- * than one call may be made to system->write() |
|
100 |
- * |
|
101 |
- * - MS-ZIP will read input bytes as necessary using the system->read() |
|
102 |
- * function given in mszipd_init(), using the input file handle given in |
|
103 |
- * mszipd_init(). This will continue until system->read() returns 0 bytes, |
|
104 |
- * or an error. |
|
105 |
- */ |
|
106 |
-extern int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes); |
|
107 |
- |
|
108 |
-/* frees all stream associated with an MS-ZIP data stream |
|
109 |
- * |
|
110 |
- * - calls system->free() using the system pointer given in mszipd_init() |
|
111 |
- */ |
|
112 |
-void mszipd_free(struct mszipd_stream *zip); |
|
113 |
- |
|
114 |
-#endif |
115 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,652 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * The deflate method was created by Phil Katz. MSZIP is equivalent to the |
|
5 |
- * deflate method. |
|
6 |
- * |
|
7 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
8 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
9 |
- * |
|
10 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
11 |
- */ |
|
12 |
- |
|
13 |
-/* MS-ZIP decompression implementation. */ |
|
14 |
- |
|
15 |
-#if HAVE_CONFIG_H |
|
16 |
-#include "clamav-config.h" |
|
17 |
-#endif |
|
18 |
- |
|
19 |
-#include <mspack.h> |
|
20 |
-#include <system.h> |
|
21 |
-#include <mszip.h> |
|
22 |
- |
|
23 |
-/* match lengths for literal codes 257.. 285 */ |
|
24 |
-static const unsigned short lit_lengths[29] = { |
|
25 |
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, |
|
26 |
- 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 |
|
27 |
-}; |
|
28 |
- |
|
29 |
-/* match offsets for distance codes 0 .. 29 */ |
|
30 |
-static const unsigned short dist_offsets[30] = { |
|
31 |
- 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, |
|
32 |
- 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 |
|
33 |
-}; |
|
34 |
- |
|
35 |
-/* extra bits required for literal codes 257.. 285 */ |
|
36 |
-static const unsigned char lit_extrabits[29] = { |
|
37 |
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, |
|
38 |
- 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 |
|
39 |
-}; |
|
40 |
- |
|
41 |
-/* extra bits required for distance codes 0 .. 29 */ |
|
42 |
-static const unsigned char dist_extrabits[30] = { |
|
43 |
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, |
|
44 |
- 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 |
|
45 |
-}; |
|
46 |
- |
|
47 |
-/* the order of the bit length Huffman code lengths */ |
|
48 |
-static const unsigned char bitlen_order[19] = { |
|
49 |
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 |
|
50 |
-}; |
|
51 |
- |
|
52 |
-/* ANDing with bit_mask[n] masks the lower n bits */ |
|
53 |
-static const unsigned short bit_mask[17] = { |
|
54 |
- 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, |
|
55 |
- 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff |
|
56 |
-}; |
|
57 |
- |
|
58 |
-#define STORE_BITS do { \ |
|
59 |
- zip->i_ptr = i_ptr; \ |
|
60 |
- zip->i_end = i_end; \ |
|
61 |
- zip->bit_buffer = bit_buffer; \ |
|
62 |
- zip->bits_left = bits_left; \ |
|
63 |
-} while (0) |
|
64 |
- |
|
65 |
-#define RESTORE_BITS do { \ |
|
66 |
- i_ptr = zip->i_ptr; \ |
|
67 |
- i_end = zip->i_end; \ |
|
68 |
- bit_buffer = zip->bit_buffer; \ |
|
69 |
- bits_left = zip->bits_left; \ |
|
70 |
-} while (0) |
|
71 |
- |
|
72 |
-#define ENSURE_BITS(nbits) do { \ |
|
73 |
- while (bits_left < (nbits)) { \ |
|
74 |
- if (i_ptr >= i_end) { \ |
|
75 |
- if (zipd_read_input(zip)) return zip->error; \ |
|
76 |
- i_ptr = zip->i_ptr; \ |
|
77 |
- i_end = zip->i_end; \ |
|
78 |
- } \ |
|
79 |
- bit_buffer |= *i_ptr++ << bits_left; bits_left += 8; \ |
|
80 |
- } \ |
|
81 |
-} while (0) |
|
82 |
- |
|
83 |
-#define PEEK_BITS(nbits) (bit_buffer & ((1<<(nbits))-1)) |
|
84 |
-#define PEEK_BITS_T(nbits) (bit_buffer & bit_mask[(nbits)]) |
|
85 |
- |
|
86 |
-#define REMOVE_BITS(nbits) ((bit_buffer >>= (nbits)), (bits_left -= (nbits))) |
|
87 |
- |
|
88 |
-#define READ_BITS(val, nbits) do { \ |
|
89 |
- ENSURE_BITS(nbits); (val) = PEEK_BITS(nbits); REMOVE_BITS(nbits); \ |
|
90 |
-} while (0) |
|
91 |
- |
|
92 |
-#define READ_BITS_T(val, nbits) do { \ |
|
93 |
- ENSURE_BITS(nbits); (val) = PEEK_BITS_T(nbits); REMOVE_BITS(nbits); \ |
|
94 |
-} while (0) |
|
95 |
- |
|
96 |
-static int zipd_read_input(struct mszipd_stream *zip) { |
|
97 |
- int read = zip->sys->read(zip->input, &zip->inbuf[0], (int)zip->inbuf_size); |
|
98 |
- if (read < 0) return zip->error = MSPACK_ERR_READ; |
|
99 |
- zip->i_ptr = &zip->inbuf[0]; |
|
100 |
- zip->i_end = &zip->inbuf[read]; |
|
101 |
- |
|
102 |
- return MSPACK_ERR_OK; |
|
103 |
-} |
|
104 |
- |
|
105 |
-/* inflate() error codes */ |
|
106 |
-#define INF_ERR_BLOCKTYPE (-1) /* unknown block type */ |
|
107 |
-#define INF_ERR_COMPLEMENT (-2) /* block size complement mismatch */ |
|
108 |
-#define INF_ERR_FLUSH (-3) /* error from flush_window() callback */ |
|
109 |
-#define INF_ERR_BITBUF (-4) /* too many bits in bit buffer */ |
|
110 |
-#define INF_ERR_SYMLENS (-5) /* too many symbols in blocktype 2 header */ |
|
111 |
-#define INF_ERR_BITLENTBL (-6) /* failed to build bitlens huffman table */ |
|
112 |
-#define INF_ERR_LITERALTBL (-7) /* failed to build literals huffman table */ |
|
113 |
-#define INF_ERR_DISTANCETBL (-8) /* failed to build distance huffman table */ |
|
114 |
-#define INF_ERR_BITOVERRUN (-9) /* bitlen RLE code goes over table size */ |
|
115 |
-#define INF_ERR_BADBITLEN (-10) /* invalid bit-length code */ |
|
116 |
-#define INF_ERR_LITCODE (-11) /* out-of-range literal code */ |
|
117 |
-#define INF_ERR_DISTCODE (-12) /* out-of-range distance code */ |
|
118 |
-#define INF_ERR_DISTANCE (-13) /* somehow, distance is beyond 32k */ |
|
119 |
-#define INF_ERR_HUFFSYM (-14) /* out of bits decoding huffman symbol */ |
|
120 |
- |
|
121 |
-/* make_decode_table(nsyms, nbits, length[], table[]) |
|
122 |
- * |
|
123 |
- * This function was coded by David Tritscher. It builds a fast huffman |
|
124 |
- * decoding table out of just a canonical huffman code lengths table. |
|
125 |
- * |
|
126 |
- * NOTE: this is NOT identical to the make_decode_table() in lzxd.c. This |
|
127 |
- * one reverses the quick-lookup bit pattern. Bits are read MSB to LSB in LZX, |
|
128 |
- * but LSB to MSB in MSZIP. |
|
129 |
- * |
|
130 |
- * nsyms = total number of symbols in this huffman tree. |
|
131 |
- * nbits = any symbols with a code length of nbits or less can be decoded |
|
132 |
- * in one lookup of the table. |
|
133 |
- * length = A table to get code lengths from [0 to nsyms-1] |
|
134 |
- * table = The table to fill up with decoded symbols and pointers. |
|
135 |
- * |
|
136 |
- * Returns 0 for OK or 1 for error |
|
137 |
- */ |
|
138 |
-static int make_decode_table(unsigned int nsyms, unsigned int nbits, |
|
139 |
- unsigned char *length, unsigned short *table) |
|
140 |
-{ |
|
141 |
- register unsigned int leaf, reverse, fill; |
|
142 |
- register unsigned short sym, next_sym; |
|
143 |
- register unsigned char bit_num; |
|
144 |
- unsigned int pos = 0; /* the current position in the decode table */ |
|
145 |
- unsigned int table_mask = 1 << nbits; |
|
146 |
- unsigned int bit_mask = table_mask >> 1; /* don't do 0 length codes */ |
|
147 |
- |
|
148 |
- /* fill entries for codes short enough for a direct mapping */ |
|
149 |
- for (bit_num = 1; bit_num <= nbits; bit_num++) { |
|
150 |
- for (sym = 0; sym < nsyms; sym++) { |
|
151 |
- if (length[sym] != bit_num) continue; |
|
152 |
- |
|
153 |
- /* reverse the significant bits */ |
|
154 |
- fill = length[sym]; reverse = pos >> (nbits - fill); leaf = 0; |
|
155 |
- do {leaf <<= 1; leaf |= reverse & 1; reverse >>= 1;} while (--fill); |
|
156 |
- |
|
157 |
- if((pos += bit_mask) > table_mask) return 1; /* table overrun */ |
|
158 |
- |
|
159 |
- /* fill all possible lookups of this symbol with the symbol itself */ |
|
160 |
- fill = bit_mask; next_sym = 1 << bit_num; |
|
161 |
- do { table[leaf] = sym; leaf += next_sym; } while (--fill); |
|
162 |
- } |
|
163 |
- bit_mask >>= 1; |
|
164 |
- } |
|
165 |
- |
|
166 |
- /* exit with success if table is now complete */ |
|
167 |
- if (pos == table_mask) return 0; |
|
168 |
- |
|
169 |
- /* mark all remaining table entries as unused */ |
|
170 |
- for (sym = pos; sym < table_mask; sym++) { |
|
171 |
- reverse = sym; leaf = 0; fill = nbits; |
|
172 |
- do { leaf <<= 1; leaf |= reverse & 1; reverse >>= 1; } while (--fill); |
|
173 |
- table[leaf] = 0xFFFF; |
|
174 |
- } |
|
175 |
- |
|
176 |
- /* where should the longer codes be allocated from? */ |
|
177 |
- next_sym = ((table_mask >> 1) < nsyms) ? nsyms : (table_mask >> 1); |
|
178 |
- |
|
179 |
- /* give ourselves room for codes to grow by up to 16 more bits. |
|
180 |
- * codes now start at bit nbits+16 and end at (nbits+16-codelength) */ |
|
181 |
- pos <<= 16; |
|
182 |
- table_mask <<= 16; |
|
183 |
- bit_mask = 1 << 15; |
|
184 |
- |
|
185 |
- for (bit_num = nbits+1; bit_num <= MSZIP_MAX_HUFFBITS; bit_num++) { |
|
186 |
- for (sym = 0; sym < nsyms; sym++) { |
|
187 |
- if (length[sym] != bit_num) continue; |
|
188 |
- |
|
189 |
- /* leaf = the first nbits of the code, reversed */ |
|
190 |
- reverse = pos >> 16; leaf = 0; fill = nbits; |
|
191 |
- do {leaf <<= 1; leaf |= reverse & 1; reverse >>= 1;} while (--fill); |
|
192 |
- |
|
193 |
- for (fill = 0; fill < (bit_num - nbits); fill++) { |
|
194 |
- /* if this path hasn't been taken yet, 'allocate' two entries */ |
|
195 |
- if (table[leaf] == 0xFFFF) { |
|
196 |
- table[(next_sym << 1) ] = 0xFFFF; |
|
197 |
- table[(next_sym << 1) + 1 ] = 0xFFFF; |
|
198 |
- table[leaf] = next_sym++; |
|
199 |
- } |
|
200 |
- /* follow the path and select either left or right for next bit */ |
|
201 |
- leaf = (table[leaf] << 1) | ((pos >> (15 - fill)) & 1); |
|
202 |
- } |
|
203 |
- table[leaf] = sym; |
|
204 |
- |
|
205 |
- if ((pos += bit_mask) > table_mask) return 1; /* table overflow */ |
|
206 |
- } |
|
207 |
- bit_mask >>= 1; |
|
208 |
- } |
|
209 |
- |
|
210 |
- /* full table? */ |
|
211 |
- return (pos != table_mask) ? 1 : 0; |
|
212 |
-} |
|
213 |
- |
|
214 |
-/* READ_HUFFSYM(tablename, var) decodes one huffman symbol from the |
|
215 |
- * bitstream using the stated table and puts it in var. |
|
216 |
- */ |
|
217 |
-#define READ_HUFFSYM(tbl, var) do { \ |
|
218 |
- /* huffman symbols can be up to 16 bits long */ \ |
|
219 |
- ENSURE_BITS(MSZIP_MAX_HUFFBITS); \ |
|
220 |
- /* immediate table lookup of [tablebits] bits of the code */ \ |
|
221 |
- sym = zip->tbl##_table[PEEK_BITS(MSZIP_##tbl##_TABLEBITS)]; \ |
|
222 |
- /* is the symbol is longer than [tablebits] bits? (i=node index) */ \ |
|
223 |
- if (sym >= MSZIP_##tbl##_MAXSYMBOLS) { \ |
|
224 |
- /* decode remaining bits by tree traversal */ \ |
|
225 |
- i = MSZIP_##tbl##_TABLEBITS - 1; \ |
|
226 |
- do { \ |
|
227 |
- /* check next bit. error if we run out of bits before decode */ \ |
|
228 |
- if (i++ > MSZIP_MAX_HUFFBITS) { \ |
|
229 |
- D(("out of bits in huffman decode")) \ |
|
230 |
- return INF_ERR_HUFFSYM; \ |
|
231 |
- } \ |
|
232 |
- /* double node index and add 0 (left branch) or 1 (right) */ \ |
|
233 |
- sym = zip->tbl##_table[(sym << 1) | ((bit_buffer >> i) & 1)]; \ |
|
234 |
- /* while we are still in node indicies, not decoded symbols */ \ |
|
235 |
- } while (sym >= MSZIP_##tbl##_MAXSYMBOLS); \ |
|
236 |
- } \ |
|
237 |
- /* result */ \ |
|
238 |
- (var) = sym; \ |
|
239 |
- /* look up the code length of that symbol and discard those bits */ \ |
|
240 |
- i = zip->tbl##_len[sym]; \ |
|
241 |
- REMOVE_BITS(i); \ |
|
242 |
-} while (0) |
|
243 |
- |
|
244 |
-static int zip_read_lens(struct mszipd_stream *zip) { |
|
245 |
- /* for the bit buffer and huffman decoding */ |
|
246 |
- register unsigned int bit_buffer; |
|
247 |
- register int bits_left; |
|
248 |
- unsigned char *i_ptr, *i_end; |
|
249 |
- |
|
250 |
- /* bitlen Huffman codes -- immediate lookup, 7 bit max code length */ |
|
251 |
- unsigned short bl_table[(1 << 7)]; |
|
252 |
- unsigned char bl_len[19]; |
|
253 |
- |
|
254 |
- unsigned char lens[MSZIP_LITERAL_MAXSYMBOLS + MSZIP_DISTANCE_MAXSYMBOLS]; |
|
255 |
- unsigned int lit_codes, dist_codes, code, last_code=0, bitlen_codes, i, run; |
|
256 |
- |
|
257 |
- RESTORE_BITS; |
|
258 |
- |
|
259 |
- /* read the number of codes */ |
|
260 |
- READ_BITS(lit_codes, 5); lit_codes += 257; |
|
261 |
- READ_BITS(dist_codes, 5); dist_codes += 1; |
|
262 |
- READ_BITS(bitlen_codes, 4); bitlen_codes += 4; |
|
263 |
- if (lit_codes > MSZIP_LITERAL_MAXSYMBOLS) return INF_ERR_SYMLENS; |
|
264 |
- if (dist_codes > MSZIP_DISTANCE_MAXSYMBOLS) return INF_ERR_SYMLENS; |
|
265 |
- |
|
266 |
- /* read in the bit lengths in their unusual order */ |
|
267 |
- for (i = 0; i < bitlen_codes; i++) READ_BITS(bl_len[bitlen_order[i]], 3); |
|
268 |
- while (i < 19) bl_len[bitlen_order[i++]] = 0; |
|
269 |
- |
|
270 |
- /* create decoding table with an immediate lookup */ |
|
271 |
- if (make_decode_table(19, 7, &bl_len[0], &bl_table[0])) { |
|
272 |
- return INF_ERR_BITLENTBL; |
|
273 |
- } |
|
274 |
- |
|
275 |
- /* read literal / distance code lengths */ |
|
276 |
- for (i = 0; i < (lit_codes + dist_codes); i++) { |
|
277 |
- /* single-level huffman lookup */ |
|
278 |
- ENSURE_BITS(7); |
|
279 |
- code = bl_table[PEEK_BITS(7)]; |
|
280 |
- REMOVE_BITS(bl_len[code]); |
|
281 |
- |
|
282 |
- if (code < 16) lens[i] = last_code = code; |
|
283 |
- else { |
|
284 |
- switch (code) { |
|
285 |
- case 16: READ_BITS(run, 2); run += 3; code = last_code; break; |
|
286 |
- case 17: READ_BITS(run, 3); run += 3; code = 0; break; |
|
287 |
- case 18: READ_BITS(run, 7); run += 11; code = 0; break; |
|
288 |
- default: D(("bad code!: %u", code)) return INF_ERR_BADBITLEN; |
|
289 |
- } |
|
290 |
- if ((i + run) > (lit_codes + dist_codes)) return INF_ERR_BITOVERRUN; |
|
291 |
- while (run--) lens[i++] = code; |
|
292 |
- i--; |
|
293 |
- } |
|
294 |
- } |
|
295 |
- |
|
296 |
- /* copy LITERAL code lengths and clear any remaining */ |
|
297 |
- i = lit_codes; |
|
298 |
- zip->sys->copy(&lens[0], &zip->LITERAL_len[0], i); |
|
299 |
- while (i < MSZIP_LITERAL_MAXSYMBOLS) zip->LITERAL_len[i++] = 0; |
|
300 |
- |
|
301 |
- i = dist_codes; |
|
302 |
- zip->sys->copy(&lens[lit_codes], &zip->DISTANCE_len[0], i); |
|
303 |
- while (i < MSZIP_DISTANCE_MAXSYMBOLS) zip->DISTANCE_len[i++] = 0; |
|
304 |
- |
|
305 |
- STORE_BITS; |
|
306 |
- return 0; |
|
307 |
-} |
|
308 |
- |
|
309 |
-/* a clean implementation of RFC 1951 / inflate */ |
|
310 |
-static int inflate(struct mszipd_stream *zip) { |
|
311 |
- unsigned int last_block, block_type, distance, length, this_run, i; |
|
312 |
- |
|
313 |
- /* for the bit buffer and huffman decoding */ |
|
314 |
- register unsigned int bit_buffer; |
|
315 |
- register int bits_left; |
|
316 |
- register unsigned short sym; |
|
317 |
- unsigned char *i_ptr, *i_end; |
|
318 |
- |
|
319 |
- RESTORE_BITS; |
|
320 |
- |
|
321 |
- do { |
|
322 |
- /* read in last block bit */ |
|
323 |
- READ_BITS(last_block, 1); |
|
324 |
- |
|
325 |
- /* read in block type */ |
|
326 |
- READ_BITS(block_type, 2); |
|
327 |
- D(("block_type=%u last_block=%u", block_type, last_block)) |
|
328 |
- |
|
329 |
- if (block_type == 0) { |
|
330 |
- /* uncompressed block */ |
|
331 |
- unsigned char lens_buf[4]; |
|
332 |
- |
|
333 |
- /* go to byte boundary */ |
|
334 |
- i = bits_left & 7; REMOVE_BITS(i); |
|
335 |
- |
|
336 |
- /* read 4 bytes of data, emptying the bit-buffer if necessary */ |
|
337 |
- for (i = 0; (bits_left >= 8); i++) { |
|
338 |
- if (i == 4) return INF_ERR_BITBUF; |
|
339 |
- lens_buf[i] = PEEK_BITS(8); |
|
340 |
- REMOVE_BITS(8); |
|
341 |
- } |
|
342 |
- if (bits_left != 0) return INF_ERR_BITBUF; |
|
343 |
- while (i < 4) { |
|
344 |
- if (i_ptr >= i_end) { |
|
345 |
- if (zipd_read_input(zip)) return zip->error; |
|
346 |
- i_ptr = zip->i_ptr; |
|
347 |
- i_end = zip->i_end; |
|
348 |
- } |
|
349 |
- lens_buf[i++] = *i_ptr++; |
|
350 |
- } |
|
351 |
- |
|
352 |
- /* get the length and its complement */ |
|
353 |
- length = lens_buf[0] | (lens_buf[1] << 8); |
|
354 |
- i = lens_buf[2] | (lens_buf[3] << 8); |
|
355 |
- if (length != (~i & 0xFFFF)) return INF_ERR_COMPLEMENT; |
|
356 |
- |
|
357 |
- /* read and copy the uncompressed data into the window */ |
|
358 |
- while (length > 0) { |
|
359 |
- if (i_ptr >= i_end) { |
|
360 |
- if (zipd_read_input(zip)) return zip->error; |
|
361 |
- i_ptr = zip->i_ptr; |
|
362 |
- i_end = zip->i_end; |
|
363 |
- } |
|
364 |
- |
|
365 |
- this_run = length; |
|
366 |
- if (this_run > (unsigned int)(i_end - i_ptr)) this_run = i_end - i_ptr; |
|
367 |
- if (this_run > (MSZIP_FRAME_SIZE - zip->window_posn)) |
|
368 |
- this_run = MSZIP_FRAME_SIZE - zip->window_posn; |
|
369 |
- |
|
370 |
- zip->sys->copy(i_ptr, &zip->window[zip->window_posn], this_run); |
|
371 |
- zip->window_posn += this_run; |
|
372 |
- i_ptr += this_run; |
|
373 |
- length -= this_run; |
|
374 |
- |
|
375 |
- if (zip->window_posn == MSZIP_FRAME_SIZE) { |
|
376 |
- if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) return INF_ERR_FLUSH; |
|
377 |
- zip->window_posn = 0; |
|
378 |
- } |
|
379 |
- } |
|
380 |
- } |
|
381 |
- else if ((block_type == 1) || (block_type == 2)) { |
|
382 |
- /* Huffman-compressed LZ77 block */ |
|
383 |
- unsigned int window_posn, match_posn, code; |
|
384 |
- |
|
385 |
- if (block_type == 1) { |
|
386 |
- /* block with fixed Huffman codes */ |
|
387 |
- i = 0; |
|
388 |
- while (i < 144) zip->LITERAL_len[i++] = 8; |
|
389 |
- while (i < 256) zip->LITERAL_len[i++] = 9; |
|
390 |
- while (i < 280) zip->LITERAL_len[i++] = 7; |
|
391 |
- while (i < 288) zip->LITERAL_len[i++] = 8; |
|
392 |
- for (i = 0; i < 32; i++) zip->DISTANCE_len[i] = 5; |
|
393 |
- } |
|
394 |
- else { |
|
395 |
- /* block with dynamic Huffman codes */ |
|
396 |
- STORE_BITS; |
|
397 |
- if ((i = zip_read_lens(zip))) return i; |
|
398 |
- RESTORE_BITS; |
|
399 |
- } |
|
400 |
- |
|
401 |
- /* now huffman lengths are read for either kind of block, |
|
402 |
- * create huffman decoding tables */ |
|
403 |
- if (make_decode_table(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS, |
|
404 |
- &zip->LITERAL_len[0], &zip->LITERAL_table[0])) |
|
405 |
- { |
|
406 |
- return INF_ERR_LITERALTBL; |
|
407 |
- } |
|
408 |
- |
|
409 |
- if (make_decode_table(MSZIP_DISTANCE_MAXSYMBOLS,MSZIP_DISTANCE_TABLEBITS, |
|
410 |
- &zip->DISTANCE_len[0], &zip->DISTANCE_table[0])) |
|
411 |
- { |
|
412 |
- return INF_ERR_DISTANCETBL; |
|
413 |
- } |
|
414 |
- |
|
415 |
- /* decode forever until end of block code */ |
|
416 |
- window_posn = zip->window_posn; |
|
417 |
- while (1) { |
|
418 |
- READ_HUFFSYM(LITERAL, code); |
|
419 |
- if (code < 256) { |
|
420 |
- zip->window[window_posn++] = (unsigned char) code; |
|
421 |
- if (window_posn == MSZIP_FRAME_SIZE) { |
|
422 |
- if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) return INF_ERR_FLUSH; |
|
423 |
- window_posn = 0; |
|
424 |
- } |
|
425 |
- } |
|
426 |
- else if (code == 256) { |
|
427 |
- /* END OF BLOCK CODE: loop break point */ |
|
428 |
- break; |
|
429 |
- } |
|
430 |
- else { |
|
431 |
- code -= 257; |
|
432 |
- if (code > 29) return INF_ERR_LITCODE; |
|
433 |
- READ_BITS_T(length, lit_extrabits[code]); |
|
434 |
- length += lit_lengths[code]; |
|
435 |
- |
|
436 |
- READ_HUFFSYM(DISTANCE, code); |
|
437 |
- if (code > 30) return INF_ERR_DISTCODE; |
|
438 |
- READ_BITS_T(distance, dist_extrabits[code]); |
|
439 |
- distance += dist_offsets[code]; |
|
440 |
- |
|
441 |
- /* match position is window position minus distance. If distance |
|
442 |
- * is more than window position numerically, it must 'wrap |
|
443 |
- * around' the frame size. */ |
|
444 |
- match_posn = ((distance > window_posn) ? MSZIP_FRAME_SIZE : 0) |
|
445 |
- + window_posn - distance; |
|
446 |
- |
|
447 |
- /* copy match */ |
|
448 |
- if (length < 12) { |
|
449 |
- /* short match, use slower loop but no loop setup code */ |
|
450 |
- while (length--) { |
|
451 |
- zip->window[window_posn++] = zip->window[match_posn++]; |
|
452 |
- match_posn &= MSZIP_FRAME_SIZE - 1; |
|
453 |
- |
|
454 |
- if (window_posn == MSZIP_FRAME_SIZE) { |
|
455 |
- if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) |
|
456 |
- return INF_ERR_FLUSH; |
|
457 |
- window_posn = 0; |
|
458 |
- } |
|
459 |
- } |
|
460 |
- } |
|
461 |
- else { |
|
462 |
- /* longer match, use faster loop but with setup expense */ |
|
463 |
- unsigned char *runsrc, *rundest; |
|
464 |
- do { |
|
465 |
- this_run = length; |
|
466 |
- if ((match_posn + this_run) > MSZIP_FRAME_SIZE) |
|
467 |
- this_run = MSZIP_FRAME_SIZE - match_posn; |
|
468 |
- if ((window_posn + this_run) > MSZIP_FRAME_SIZE) |
|
469 |
- this_run = MSZIP_FRAME_SIZE - window_posn; |
|
470 |
- |
|
471 |
- rundest = &zip->window[window_posn]; window_posn += this_run; |
|
472 |
- runsrc = &zip->window[match_posn]; match_posn += this_run; |
|
473 |
- length -= this_run; |
|
474 |
- while (this_run--) *rundest++ = *runsrc++; |
|
475 |
- |
|
476 |
- /* flush if necessary */ |
|
477 |
- if (window_posn == MSZIP_FRAME_SIZE) { |
|
478 |
- if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) |
|
479 |
- return INF_ERR_FLUSH; |
|
480 |
- window_posn = 0; |
|
481 |
- } |
|
482 |
- if (match_posn == MSZIP_FRAME_SIZE) match_posn = 0; |
|
483 |
- } while (length > 0); |
|
484 |
- } |
|
485 |
- |
|
486 |
- } /* else (code >= 257) */ |
|
487 |
- |
|
488 |
- } /* while (forever) -- break point at 'code == 256' */ |
|
489 |
- zip->window_posn = window_posn; |
|
490 |
- } |
|
491 |
- else { |
|
492 |
- /* block_type == 3 -- bad block type */ |
|
493 |
- return INF_ERR_BLOCKTYPE; |
|
494 |
- } |
|
495 |
- } while (!last_block); |
|
496 |
- |
|
497 |
- /* flush the remaining data */ |
|
498 |
- if (zip->window_posn) { |
|
499 |
- if (zip->flush_window(zip, zip->window_posn)) return INF_ERR_FLUSH; |
|
500 |
- } |
|
501 |
- STORE_BITS; |
|
502 |
- |
|
503 |
- /* return success */ |
|
504 |
- return 0; |
|
505 |
-} |
|
506 |
- |
|
507 |
-/* inflate() calls this whenever the window should be flushed. As |
|
508 |
- * MSZIP only expands to the size of the window, the implementation used |
|
509 |
- * simply keeps track of the amount of data flushed, and if more than 32k |
|
510 |
- * is flushed, an error is raised. |
|
511 |
- */ |
|
512 |
-static int mszipd_flush_window(struct mszipd_stream *zip, |
|
513 |
- unsigned int data_flushed) |
|
514 |
-{ |
|
515 |
- zip->bytes_output += data_flushed; |
|
516 |
- if (zip->bytes_output > MSZIP_FRAME_SIZE) { |
|
517 |
- D(("overflow: %u bytes flushed, total is now %u", |
|
518 |
- data_flushed, zip->bytes_output)) |
|
519 |
- return 1; |
|
520 |
- } |
|
521 |
- return 0; |
|
522 |
-} |
|
523 |
- |
|
524 |
-struct mszipd_stream *mszipd_init(struct mspack_system *system, |
|
525 |
- struct mspack_file *input, |
|
526 |
- struct mspack_file *output, |
|
527 |
- int input_buffer_size, |
|
528 |
- int repair_mode) |
|
529 |
-{ |
|
530 |
- struct mszipd_stream *zip; |
|
531 |
- |
|
532 |
- if (!system) return NULL; |
|
533 |
- |
|
534 |
- input_buffer_size = (input_buffer_size + 1) & -2; |
|
535 |
- if (!input_buffer_size) return NULL; |
|
536 |
- |
|
537 |
- /* allocate decompression state */ |
|
538 |
- if (!(zip = system->alloc(system, sizeof(struct mszipd_stream)))) { |
|
539 |
- return NULL; |
|
540 |
- } |
|
541 |
- |
|
542 |
- /* allocate input buffer */ |
|
543 |
- zip->inbuf = system->alloc(system, (size_t) input_buffer_size); |
|
544 |
- if (!zip->inbuf) { |
|
545 |
- system->free(zip); |
|
546 |
- return NULL; |
|
547 |
- } |
|
548 |
- |
|
549 |
- /* initialise decompression state */ |
|
550 |
- zip->sys = system; |
|
551 |
- zip->input = input; |
|
552 |
- zip->output = output; |
|
553 |
- zip->inbuf_size = input_buffer_size; |
|
554 |
- zip->error = MSPACK_ERR_OK; |
|
555 |
- zip->repair_mode = repair_mode; |
|
556 |
- zip->flush_window = &mszipd_flush_window; |
|
557 |
- |
|
558 |
- zip->i_ptr = zip->i_end = &zip->inbuf[0]; |
|
559 |
- zip->o_ptr = zip->o_end = NULL; |
|
560 |
- zip->bit_buffer = 0; zip->bits_left = 0; |
|
561 |
- return zip; |
|
562 |
-} |
|
563 |
- |
|
564 |
-int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes) { |
|
565 |
- /* for the bit buffer */ |
|
566 |
- register unsigned int bit_buffer; |
|
567 |
- register int bits_left; |
|
568 |
- unsigned char *i_ptr, *i_end; |
|
569 |
- |
|
570 |
- int i, state, error; |
|
571 |
- |
|
572 |
- /* easy answers */ |
|
573 |
- if (!zip || (out_bytes < 0)) return MSPACK_ERR_ARGS; |
|
574 |
- if (zip->error) return zip->error; |
|
575 |
- |
|
576 |
- /* flush out any stored-up bytes before we begin */ |
|
577 |
- i = zip->o_end - zip->o_ptr; |
|
578 |
- if ((off_t) i > out_bytes) i = (int) out_bytes; |
|
579 |
- if (i) { |
|
580 |
- if (zip->sys->write(zip->output, zip->o_ptr, i) != i) { |
|
581 |
- return zip->error = MSPACK_ERR_WRITE; |
|
582 |
- } |
|
583 |
- zip->o_ptr += i; |
|
584 |
- out_bytes -= i; |
|
585 |
- } |
|
586 |
- if (out_bytes == 0) return MSPACK_ERR_OK; |
|
587 |
- |
|
588 |
- |
|
589 |
- while (out_bytes > 0) { |
|
590 |
- /* unpack another block */ |
|
591 |
- RESTORE_BITS; |
|
592 |
- |
|
593 |
- /* skip to next read 'CK' header */ |
|
594 |
- i = bits_left & 7; REMOVE_BITS(i); /* align to bytestream */ |
|
595 |
- state = 0; |
|
596 |
- do { |
|
597 |
- READ_BITS(i, 8); |
|
598 |
- if (i == 'C') state = 1; |
|
599 |
- else if ((state == 1) && (i == 'K')) state = 2; |
|
600 |
- else state = 0; |
|
601 |
- } while (state != 2); |
|
602 |
- |
|
603 |
- /* inflate a block, repair and realign if necessary */ |
|
604 |
- zip->window_posn = 0; |
|
605 |
- zip->bytes_output = 0; |
|
606 |
- STORE_BITS; |
|
607 |
- if ((error = inflate(zip))) { |
|
608 |
- D(("inflate error %d", i)) |
|
609 |
- if (zip->repair_mode) { |
|
610 |
- zip->sys->message(NULL, "MSZIP error, %u bytes of data lost.", |
|
611 |
- MSZIP_FRAME_SIZE - zip->bytes_output); |
|
612 |
- for (i = zip->bytes_output; i < MSZIP_FRAME_SIZE; i++) { |
|
613 |
- zip->window[i] = '\0'; |
|
614 |
- } |
|
615 |
- zip->bytes_output = MSZIP_FRAME_SIZE; |
|
616 |
- } |
|
617 |
- else { |
|
618 |
- return zip->error = (error > 0) ? error : MSPACK_ERR_DECRUNCH; |
|
619 |
- } |
|
620 |
- } |
|
621 |
- zip->o_ptr = &zip->window[0]; |
|
622 |
- zip->o_end = &zip->o_ptr[zip->bytes_output]; |
|
623 |
- |
|
624 |
- /* write a frame */ |
|
625 |
- i = (out_bytes < (off_t)zip->bytes_output) ? |
|
626 |
- (int)out_bytes : zip->bytes_output; |
|
627 |
- if (zip->sys->write(zip->output, zip->o_ptr, i) != i) { |
|
628 |
- return zip->error = MSPACK_ERR_WRITE; |
|
629 |
- } |
|
630 |
- |
|
631 |
- /* mspack errors (i.e. read errors) are fatal and can't be recovered */ |
|
632 |
- if ((error > 0) && zip->repair_mode) return error; |
|
633 |
- |
|
634 |
- zip->o_ptr += i; |
|
635 |
- out_bytes -= i; |
|
636 |
- } |
|
637 |
- |
|
638 |
- if (out_bytes) { |
|
639 |
- D(("bytes left to output")) |
|
640 |
- return zip->error = MSPACK_ERR_DECRUNCH; |
|
641 |
- } |
|
642 |
- return MSPACK_ERR_OK; |
|
643 |
-} |
|
644 |
- |
|
645 |
-void mszipd_free(struct mszipd_stream *zip) { |
|
646 |
- struct mspack_system *sys; |
|
647 |
- if (zip) { |
|
648 |
- sys = zip->sys; |
|
649 |
- sys->free(zip->inbuf); |
|
650 |
- sys->free(zip); |
|
651 |
- } |
|
652 |
-} |
653 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,120 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * The Quantum method was created by David Stafford, adapted by Microsoft |
|
5 |
- * Corporation. |
|
6 |
- * |
|
7 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
8 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
9 |
- * |
|
10 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
11 |
- */ |
|
12 |
- |
|
13 |
-#ifndef MSPACK_QTM_H |
|
14 |
-#define MSPACK_QTM_H 1 |
|
15 |
- |
|
16 |
-/* Quantum compression / decompression definitions */ |
|
17 |
- |
|
18 |
-#define QTM_FRAME_SIZE (32768) |
|
19 |
- |
|
20 |
-struct qtmd_modelsym { |
|
21 |
- unsigned short sym, cumfreq; |
|
22 |
-}; |
|
23 |
- |
|
24 |
-struct qtmd_model { |
|
25 |
- int shiftsleft, entries; |
|
26 |
- struct qtmd_modelsym *syms; |
|
27 |
-}; |
|
28 |
- |
|
29 |
-struct qtmd_stream { |
|
30 |
- struct mspack_system *sys; /* I/O routines */ |
|
31 |
- struct mspack_file *input; /* input file handle */ |
|
32 |
- struct mspack_file *output; /* output file handle */ |
|
33 |
- |
|
34 |
- unsigned char *window; /* decoding window */ |
|
35 |
- unsigned int window_size; /* window size */ |
|
36 |
- unsigned int window_posn; /* decompression offset within window */ |
|
37 |
- unsigned int frame_start; /* start of current frame within window */ |
|
38 |
- |
|
39 |
- unsigned short H, L, C; /* high/low/current: arith coding state */ |
|
40 |
- unsigned char header_read; /* have we started decoding a new frame? */ |
|
41 |
- |
|
42 |
- int error; |
|
43 |
- |
|
44 |
- /* I/O buffers */ |
|
45 |
- unsigned char *inbuf, *i_ptr, *i_end, *o_ptr, *o_end; |
|
46 |
- unsigned int bit_buffer, inbuf_size; |
|
47 |
- unsigned char bits_left; |
|
48 |
- |
|
49 |
- /* four literal models, each representing 64 symbols |
|
50 |
- * model0 for literals from 0 to 63 (selector = 0) |
|
51 |
- * model1 for literals from 64 to 127 (selector = 1) |
|
52 |
- * model2 for literals from 128 to 191 (selector = 2) |
|
53 |
- * model3 for literals from 129 to 255 (selector = 3) */ |
|
54 |
- struct qtmd_model model0, model1, model2, model3; |
|
55 |
- |
|
56 |
- /* three match models. |
|
57 |
- * model4 for match with fixed length of 3 bytes |
|
58 |
- * model5 for match with fixed length of 4 bytes |
|
59 |
- * model6 for variable length match, encoded with model6len model */ |
|
60 |
- struct qtmd_model model4, model5, model6, model6len; |
|
61 |
- |
|
62 |
- /* selector model. 0-6 to say literal (0,1,2,3) or match (4,5,6) */ |
|
63 |
- struct qtmd_model model7; |
|
64 |
- |
|
65 |
- /* symbol arrays for all models */ |
|
66 |
- struct qtmd_modelsym m0sym[64 + 1]; |
|
67 |
- struct qtmd_modelsym m1sym[64 + 1]; |
|
68 |
- struct qtmd_modelsym m2sym[64 + 1]; |
|
69 |
- struct qtmd_modelsym m3sym[64 + 1]; |
|
70 |
- struct qtmd_modelsym m4sym[24 + 1]; |
|
71 |
- struct qtmd_modelsym m5sym[36 + 1]; |
|
72 |
- struct qtmd_modelsym m6sym[42 + 1], m6lsym[27 + 1]; |
|
73 |
- struct qtmd_modelsym m7sym[7 + 1]; |
|
74 |
-}; |
|
75 |
- |
|
76 |
-/* allocates Quantum decompression state for decoding the given stream. |
|
77 |
- * |
|
78 |
- * - returns NULL if window_bits is outwith the range 10 to 21 (inclusive). |
|
79 |
- * |
|
80 |
- * - uses system->alloc() to allocate memory |
|
81 |
- * |
|
82 |
- * - returns NULL if not enough memory |
|
83 |
- * |
|
84 |
- * - window_bits is the size of the Quantum window, from 1Kb (10) to 2Mb (21). |
|
85 |
- * |
|
86 |
- * - input_buffer_size is the number of bytes to use to store bitstream data. |
|
87 |
- */ |
|
88 |
-extern struct qtmd_stream *qtmd_init(struct mspack_system *system, |
|
89 |
- struct mspack_file *input, |
|
90 |
- struct mspack_file *output, |
|
91 |
- int window_bits, |
|
92 |
- int input_buffer_size); |
|
93 |
- |
|
94 |
-/* decompresses, or decompresses more of, a Quantum stream. |
|
95 |
- * |
|
96 |
- * - out_bytes of data will be decompressed and the function will return |
|
97 |
- * with an MSPACK_ERR_OK return code. |
|
98 |
- * |
|
99 |
- * - decompressing will stop as soon as out_bytes is reached. if the true |
|
100 |
- * amount of bytes decoded spills over that amount, they will be kept for |
|
101 |
- * a later invocation of qtmd_decompress(). |
|
102 |
- * |
|
103 |
- * - the output bytes will be passed to the system->write() function given in |
|
104 |
- * qtmd_init(), using the output file handle given in qtmd_init(). More |
|
105 |
- * than one call may be made to system->write() |
|
106 |
- * |
|
107 |
- * - Quantum will read input bytes as necessary using the system->read() |
|
108 |
- * function given in qtmd_init(), using the input file handle given in |
|
109 |
- * qtmd_init(). This will continue until system->read() returns 0 bytes, |
|
110 |
- * or an error. |
|
111 |
- */ |
|
112 |
-extern int qtmd_decompress(struct qtmd_stream *qtm, off_t out_bytes); |
|
113 |
- |
|
114 |
-/* frees all state associated with a Quantum data stream |
|
115 |
- * |
|
116 |
- * - calls system->free() using the system pointer given in qtmd_init() |
|
117 |
- */ |
|
118 |
-void qtmd_free(struct qtmd_stream *qtm); |
|
119 |
- |
|
120 |
-#endif |
121 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,488 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * The Quantum method was created by David Stafford, adapted by Microsoft |
|
5 |
- * Corporation. |
|
6 |
- * |
|
7 |
- * This decompressor is based on an implementation by Matthew Russotto, used |
|
8 |
- * with permission. |
|
9 |
- * |
|
10 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
11 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
12 |
- * |
|
13 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
14 |
- */ |
|
15 |
- |
|
16 |
-/* Quantum decompression implementation */ |
|
17 |
- |
|
18 |
-/* This decompressor was researched and implemented by Matthew Russotto. It |
|
19 |
- * has since been tidied up by Stuart Caie. More information can be found at |
|
20 |
- * http://www.speakeasy.org/~russotto/quantumcomp.html |
|
21 |
- */ |
|
22 |
- |
|
23 |
-#if HAVE_CONFIG_H |
|
24 |
-#include "clamav-config.h" |
|
25 |
-#endif |
|
26 |
- |
|
27 |
-#include <mspack.h> |
|
28 |
-#include <system.h> |
|
29 |
-#include <qtm.h> |
|
30 |
- |
|
31 |
-/* Quantum decompressor bitstream reading macros |
|
32 |
- * |
|
33 |
- * STORE_BITS stores bitstream state in qtmd_stream structure |
|
34 |
- * RESTORE_BITS restores bitstream state from qtmd_stream structure |
|
35 |
- * READ_BITS(var,n) takes N bits from the buffer and puts them in var |
|
36 |
- * FILL_BUFFER if there is room for another 16 bits, reads another |
|
37 |
- * 16 bits from the input stream. |
|
38 |
- * PEEK_BITS(n) extracts without removing N bits from the bit buffer |
|
39 |
- * REMOVE_BITS(n) removes N bits from the bit buffer |
|
40 |
- * |
|
41 |
- * These bit access routines work by using the area beyond the MSB and the |
|
42 |
- * LSB as a free source of zeroes. This avoids having to mask any bits. |
|
43 |
- * So we have to know the bit width of the bitbuffer variable. |
|
44 |
- */ |
|
45 |
- |
|
46 |
-#ifdef HAVE_LIMITS_H |
|
47 |
-# include <limits.h> |
|
48 |
-#endif |
|
49 |
-#ifndef CHAR_BIT |
|
50 |
-# define CHAR_BIT (8) |
|
51 |
-#endif |
|
52 |
-#define BITBUF_WIDTH (sizeof(unsigned int) * CHAR_BIT) |
|
53 |
- |
|
54 |
-#define STORE_BITS do { \ |
|
55 |
- qtm->i_ptr = i_ptr; \ |
|
56 |
- qtm->i_end = i_end; \ |
|
57 |
- qtm->bit_buffer = bit_buffer; \ |
|
58 |
- qtm->bits_left = bits_left; \ |
|
59 |
-} while (0) |
|
60 |
- |
|
61 |
-#define RESTORE_BITS do { \ |
|
62 |
- i_ptr = qtm->i_ptr; \ |
|
63 |
- i_end = qtm->i_end; \ |
|
64 |
- bit_buffer = qtm->bit_buffer; \ |
|
65 |
- bits_left = qtm->bits_left; \ |
|
66 |
-} while (0) |
|
67 |
- |
|
68 |
-/* adds 16 bits to bit buffer, if there's space for the new bits */ |
|
69 |
-#define FILL_BUFFER do { \ |
|
70 |
- if (bits_left <= (BITBUF_WIDTH - 16)) { \ |
|
71 |
- if (i_ptr >= i_end) { \ |
|
72 |
- if (qtmd_read_input(qtm)) return qtm->error; \ |
|
73 |
- i_ptr = qtm->i_ptr; \ |
|
74 |
- i_end = qtm->i_end; \ |
|
75 |
- } \ |
|
76 |
- bit_buffer |= ((i_ptr[0] << 8) | i_ptr[1]) \ |
|
77 |
- << (BITBUF_WIDTH - 16 - bits_left); \ |
|
78 |
- bits_left += 16; \ |
|
79 |
- i_ptr += 2; \ |
|
80 |
- } \ |
|
81 |
-} while (0) |
|
82 |
- |
|
83 |
-#define PEEK_BITS(n) (bit_buffer >> (BITBUF_WIDTH - (n))) |
|
84 |
-#define REMOVE_BITS(n) ((bit_buffer <<= (n)), (bits_left -= (n))) |
|
85 |
- |
|
86 |
-#define READ_BITS(val, bits) do { \ |
|
87 |
- (val) = 0; \ |
|
88 |
- for (bits_needed = (bits); bits_needed > 0; bits_needed -= bit_run) { \ |
|
89 |
- FILL_BUFFER; \ |
|
90 |
- bit_run = (bits_left < bits_needed) ? bits_left : bits_needed; \ |
|
91 |
- (val) = ((val) << bit_run) | PEEK_BITS(bit_run); \ |
|
92 |
- REMOVE_BITS(bit_run); \ |
|
93 |
- } \ |
|
94 |
-} while (0) |
|
95 |
- |
|
96 |
-static int qtmd_read_input(struct qtmd_stream *qtm) { |
|
97 |
- int read = qtm->sys->read(qtm->input, &qtm->inbuf[0], (int)qtm->inbuf_size); |
|
98 |
- if (read < 0) return qtm->error = MSPACK_ERR_READ; |
|
99 |
- |
|
100 |
- qtm->i_ptr = &qtm->inbuf[0]; |
|
101 |
- qtm->i_end = &qtm->inbuf[read]; |
|
102 |
- return MSPACK_ERR_OK; |
|
103 |
-} |
|
104 |
- |
|
105 |
-/* Quantum static data tables: |
|
106 |
- * |
|
107 |
- * Quantum uses 'position slots' to represent match offsets. For every |
|
108 |
- * match, a small 'position slot' number and a small offset from that slot |
|
109 |
- * are encoded instead of one large offset. |
|
110 |
- * |
|
111 |
- * position_base[] is an index to the position slot bases |
|
112 |
- * |
|
113 |
- * extra_bits[] states how many bits of offset-from-base data is needed. |
|
114 |
- * |
|
115 |
- * length_base[] and length_extra[] are equivalent in function, but are |
|
116 |
- * used for encoding selector 6 (variable length match) match lengths, |
|
117 |
- * instead of match offsets. |
|
118 |
- */ |
|
119 |
-static unsigned int position_base[42]; |
|
120 |
-static unsigned char extra_bits[42], length_base[27], length_extra[27]; |
|
121 |
- |
|
122 |
-static void qtmd_static_init() { |
|
123 |
- unsigned int i, offset; |
|
124 |
- |
|
125 |
- for (i = 0, offset = 0; i < 42; i++) { |
|
126 |
- position_base[i] = offset; |
|
127 |
- extra_bits[i] = ((i < 2) ? 0 : (i - 2)) >> 1; |
|
128 |
- offset += 1 << extra_bits[i]; |
|
129 |
- } |
|
130 |
- |
|
131 |
- for (i = 0, offset = 0; i < 26; i++) { |
|
132 |
- length_base[i] = offset; |
|
133 |
- length_extra[i] = (i < 2 ? 0 : i - 2) >> 2; |
|
134 |
- offset += 1 << length_extra[i]; |
|
135 |
- } |
|
136 |
- length_base[26] = 254; length_extra[26] = 0; |
|
137 |
-} |
|
138 |
- |
|
139 |
- |
|
140 |
-/* Arithmetic decoder: |
|
141 |
- * |
|
142 |
- * GET_SYMBOL(model, var) fetches the next symbol from the stated model |
|
143 |
- * and puts it in var. |
|
144 |
- * |
|
145 |
- * If necessary, qtmd_update_model() is called. |
|
146 |
- */ |
|
147 |
-#define GET_SYMBOL(model, var) do { \ |
|
148 |
- range = ((H - L) & 0xFFFF) + 1; \ |
|
149 |
- symf = ((((C - L + 1) * model.syms[0].cumfreq)-1) / range) & 0xFFFF; \ |
|
150 |
- \ |
|
151 |
- for (i = 1; i < model.entries; i++) { \ |
|
152 |
- if (model.syms[i].cumfreq <= symf) break; \ |
|
153 |
- } \ |
|
154 |
- (var) = model.syms[i-1].sym; \ |
|
155 |
- \ |
|
156 |
- range = (H - L) + 1; \ |
|
157 |
- symf = model.syms[0].cumfreq; \ |
|
158 |
- H = L + ((model.syms[i-1].cumfreq * range) / symf) - 1; \ |
|
159 |
- L = L + ((model.syms[i].cumfreq * range) / symf); \ |
|
160 |
- \ |
|
161 |
- do { model.syms[--i].cumfreq += 8; } while (i > 0); \ |
|
162 |
- if (model.syms[0].cumfreq > 3800) qtmd_update_model(&model); \ |
|
163 |
- \ |
|
164 |
- while (1) { \ |
|
165 |
- if ((L & 0x8000) != (H & 0x8000)) { \ |
|
166 |
- if ((L & 0x4000) && !(H & 0x4000)) { \ |
|
167 |
- /* underflow case */ \ |
|
168 |
- C ^= 0x4000; L &= 0x3FFF; H |= 0x4000; \ |
|
169 |
- } \ |
|
170 |
- else break; \ |
|
171 |
- } \ |
|
172 |
- L <<= 1; H = (H << 1) | 1; \ |
|
173 |
- FILL_BUFFER; \ |
|
174 |
- C = (C << 1) | PEEK_BITS(1); \ |
|
175 |
- REMOVE_BITS(1); \ |
|
176 |
- } \ |
|
177 |
-} while (0) |
|
178 |
- |
|
179 |
-static void qtmd_update_model(struct qtmd_model *model) { |
|
180 |
- struct qtmd_modelsym tmp; |
|
181 |
- int i, j; |
|
182 |
- |
|
183 |
- if (--model->shiftsleft) { |
|
184 |
- for (i = model->entries - 1; i >= 0; i--) { |
|
185 |
- /* -1, not -2; the 0 entry saves this */ |
|
186 |
- model->syms[i].cumfreq >>= 1; |
|
187 |
- if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) { |
|
188 |
- model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1; |
|
189 |
- } |
|
190 |
- } |
|
191 |
- } |
|
192 |
- else { |
|
193 |
- model->shiftsleft = 50; |
|
194 |
- for (i = 0; i < model->entries; i++) { |
|
195 |
- /* no -1, want to include the 0 entry */ |
|
196 |
- /* this converts cumfreqs into frequencies, then shifts right */ |
|
197 |
- model->syms[i].cumfreq -= model->syms[i+1].cumfreq; |
|
198 |
- model->syms[i].cumfreq++; /* avoid losing things entirely */ |
|
199 |
- model->syms[i].cumfreq >>= 1; |
|
200 |
- } |
|
201 |
- |
|
202 |
- /* now sort by frequencies, decreasing order -- this must be an |
|
203 |
- * inplace selection sort, or a sort with the same (in)stability |
|
204 |
- * characteristics */ |
|
205 |
- for (i = 0; i < model->entries - 1; i++) { |
|
206 |
- for (j = i + 1; j < model->entries; j++) { |
|
207 |
- if (model->syms[i].cumfreq < model->syms[j].cumfreq) { |
|
208 |
- tmp = model->syms[i]; |
|
209 |
- model->syms[i] = model->syms[j]; |
|
210 |
- model->syms[j] = tmp; |
|
211 |
- } |
|
212 |
- } |
|
213 |
- } |
|
214 |
- |
|
215 |
- /* then convert frequencies back to cumfreq */ |
|
216 |
- for (i = model->entries - 1; i >= 0; i--) { |
|
217 |
- model->syms[i].cumfreq += model->syms[i+1].cumfreq; |
|
218 |
- } |
|
219 |
- } |
|
220 |
-} |
|
221 |
- |
|
222 |
-/* Initialises a model to decode symbols from [start] to [start]+[len]-1 */ |
|
223 |
-static void qtmd_init_model(struct qtmd_model *model, |
|
224 |
- struct qtmd_modelsym *syms, int start, int len) |
|
225 |
-{ |
|
226 |
- int i; |
|
227 |
- |
|
228 |
- model->shiftsleft = 4; |
|
229 |
- model->entries = len; |
|
230 |
- model->syms = syms; |
|
231 |
- |
|
232 |
- for (i = 0; i <= len; i++) { |
|
233 |
- syms[i].sym = start + i; /* actual symbol */ |
|
234 |
- syms[i].cumfreq = len - i; /* current frequency of that symbol */ |
|
235 |
- } |
|
236 |
-} |
|
237 |
- |
|
238 |
- |
|
239 |
-/*-------- main Quantum code --------*/ |
|
240 |
- |
|
241 |
-struct qtmd_stream *qtmd_init(struct mspack_system *system, |
|
242 |
- struct mspack_file *input, |
|
243 |
- struct mspack_file *output, |
|
244 |
- int window_bits, int input_buffer_size) |
|
245 |
-{ |
|
246 |
- unsigned int window_size = 1 << window_bits; |
|
247 |
- struct qtmd_stream *qtm; |
|
248 |
- int i; |
|
249 |
- |
|
250 |
- if (!system) return NULL; |
|
251 |
- |
|
252 |
- /* Quantum supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */ |
|
253 |
- if (window_bits < 10 || window_bits > 21) return NULL; |
|
254 |
- |
|
255 |
- input_buffer_size = (input_buffer_size + 1) & -2; |
|
256 |
- if (input_buffer_size < 2) return NULL; |
|
257 |
- |
|
258 |
- /* initialise static data */ |
|
259 |
- qtmd_static_init(); |
|
260 |
- |
|
261 |
- /* allocate decompression state */ |
|
262 |
- if (!(qtm = system->alloc(system, sizeof(struct qtmd_stream)))) { |
|
263 |
- return NULL; |
|
264 |
- } |
|
265 |
- |
|
266 |
- /* allocate decompression window and input buffer */ |
|
267 |
- qtm->window = system->alloc(system, (size_t) window_size); |
|
268 |
- qtm->inbuf = system->alloc(system, (size_t) input_buffer_size); |
|
269 |
- if (!qtm->window || !qtm->inbuf) { |
|
270 |
- system->free(qtm->window); |
|
271 |
- system->free(qtm->inbuf); |
|
272 |
- system->free(qtm); |
|
273 |
- return NULL; |
|
274 |
- } |
|
275 |
- |
|
276 |
- /* initialise decompression state */ |
|
277 |
- qtm->sys = system; |
|
278 |
- qtm->input = input; |
|
279 |
- qtm->output = output; |
|
280 |
- qtm->inbuf_size = input_buffer_size; |
|
281 |
- qtm->window_size = window_size; |
|
282 |
- qtm->window_posn = 0; |
|
283 |
- qtm->frame_start = 0; |
|
284 |
- qtm->header_read = 0; |
|
285 |
- qtm->error = MSPACK_ERR_OK; |
|
286 |
- |
|
287 |
- qtm->i_ptr = qtm->i_end = &qtm->inbuf[0]; |
|
288 |
- qtm->o_ptr = qtm->o_end = &qtm->window[0]; |
|
289 |
- qtm->bits_left = 0; |
|
290 |
- qtm->bit_buffer = 0; |
|
291 |
- |
|
292 |
- /* initialise arithmetic coding models |
|
293 |
- * - model 4 depends on window size, ranges from 20 to 24 |
|
294 |
- * - model 5 depends on window size, ranges from 20 to 36 |
|
295 |
- * - model 6pos depends on window size, ranges from 20 to 42 |
|
296 |
- */ |
|
297 |
- i = window_bits * 2; |
|
298 |
- qtmd_init_model(&qtm->model0, &qtm->m0sym[0], 0, 64); |
|
299 |
- qtmd_init_model(&qtm->model1, &qtm->m1sym[0], 64, 64); |
|
300 |
- qtmd_init_model(&qtm->model2, &qtm->m2sym[0], 128, 64); |
|
301 |
- qtmd_init_model(&qtm->model3, &qtm->m3sym[0], 192, 64); |
|
302 |
- qtmd_init_model(&qtm->model4, &qtm->m4sym[0], 0, (i > 24) ? 24 : i); |
|
303 |
- qtmd_init_model(&qtm->model5, &qtm->m5sym[0], 0, (i > 36) ? 36 : i); |
|
304 |
- qtmd_init_model(&qtm->model6, &qtm->m6sym[0], 0, i); |
|
305 |
- qtmd_init_model(&qtm->model6len, &qtm->m6lsym[0], 0, 27); |
|
306 |
- qtmd_init_model(&qtm->model7, &qtm->m7sym[0], 0, 7); |
|
307 |
- |
|
308 |
- /* all ok */ |
|
309 |
- return qtm; |
|
310 |
-} |
|
311 |
- |
|
312 |
-int qtmd_decompress(struct qtmd_stream *qtm, off_t out_bytes) { |
|
313 |
- unsigned int frame_start, frame_end, window_posn, match_offset, range; |
|
314 |
- unsigned char *window, *i_ptr, *i_end, *runsrc, *rundest; |
|
315 |
- int i, j, selector, extra, sym, match_length; |
|
316 |
- unsigned short H, L, C, symf; |
|
317 |
- |
|
318 |
- register unsigned int bit_buffer; |
|
319 |
- register unsigned char bits_left; |
|
320 |
- unsigned char bits_needed, bit_run; |
|
321 |
- |
|
322 |
- /* easy answers */ |
|
323 |
- if (!qtm || (out_bytes < 0)) return MSPACK_ERR_ARGS; |
|
324 |
- if (qtm->error) return qtm->error; |
|
325 |
- |
|
326 |
- /* flush out any stored-up bytes before we begin */ |
|
327 |
- i = qtm->o_end - qtm->o_ptr; |
|
328 |
- if ((off_t) i > out_bytes) i = (int) out_bytes; |
|
329 |
- if (i) { |
|
330 |
- if (qtm->sys->write(qtm->output, qtm->o_ptr, i) != i) { |
|
331 |
- return qtm->error = MSPACK_ERR_WRITE; |
|
332 |
- } |
|
333 |
- qtm->o_ptr += i; |
|
334 |
- out_bytes -= i; |
|
335 |
- } |
|
336 |
- if (out_bytes == 0) return MSPACK_ERR_OK; |
|
337 |
- |
|
338 |
- /* restore local state */ |
|
339 |
- RESTORE_BITS; |
|
340 |
- window = qtm->window; |
|
341 |
- window_posn = qtm->window_posn; |
|
342 |
- frame_start = qtm->frame_start; |
|
343 |
- H = qtm->H; |
|
344 |
- L = qtm->L; |
|
345 |
- C = qtm->C; |
|
346 |
- |
|
347 |
- /* while we do not have enough decoded bytes in reserve: */ |
|
348 |
- while ((qtm->o_end - qtm->o_ptr) < out_bytes) { |
|
349 |
- |
|
350 |
- /* read header if necessary. Initialises H, L and C */ |
|
351 |
- if (!qtm->header_read) { |
|
352 |
- H = 0xFFFF; L = 0; READ_BITS(C, 16); |
|
353 |
- qtm->header_read = 1; |
|
354 |
- } |
|
355 |
- |
|
356 |
- /* decode more, at most up to to frame boundary */ |
|
357 |
- frame_end = window_posn + (out_bytes - (qtm->o_end - qtm->o_ptr)); |
|
358 |
- if ((frame_start + QTM_FRAME_SIZE) < frame_end) { |
|
359 |
- frame_end = frame_start + QTM_FRAME_SIZE; |
|
360 |
- } |
|
361 |
- |
|
362 |
- while (window_posn < frame_end) { |
|
363 |
- GET_SYMBOL(qtm->model7, selector); |
|
364 |
- if (selector < 4) { |
|
365 |
- struct qtmd_model *mdl = (selector == 0) ? &qtm->model0 : |
|
366 |
- ((selector == 1) ? &qtm->model1 : |
|
367 |
- ((selector == 2) ? &qtm->model2 : |
|
368 |
- &qtm->model3)); |
|
369 |
- GET_SYMBOL((*mdl), sym); |
|
370 |
- window[window_posn++] = sym; |
|
371 |
- } |
|
372 |
- else { |
|
373 |
- switch (selector) { |
|
374 |
- case 4: /* selector 4 = fixed length match (3 bytes) */ |
|
375 |
- GET_SYMBOL(qtm->model4, sym); |
|
376 |
- READ_BITS(extra, extra_bits[sym]); |
|
377 |
- match_offset = position_base[sym] + extra + 1; |
|
378 |
- match_length = 3; |
|
379 |
- break; |
|
380 |
- |
|
381 |
- case 5: /* selector 5 = fixed length match (4 bytes) */ |
|
382 |
- GET_SYMBOL(qtm->model5, sym); |
|
383 |
- READ_BITS(extra, extra_bits[sym]); |
|
384 |
- match_offset = position_base[sym] + extra + 1; |
|
385 |
- match_length = 4; |
|
386 |
- break; |
|
387 |
- |
|
388 |
- case 6: /* selector 6 = variable length match */ |
|
389 |
- GET_SYMBOL(qtm->model6len, sym); |
|
390 |
- READ_BITS(extra, length_extra[sym]); |
|
391 |
- match_length = length_base[sym] + extra + 5; |
|
392 |
- |
|
393 |
- GET_SYMBOL(qtm->model6, sym); |
|
394 |
- READ_BITS(extra, extra_bits[sym]); |
|
395 |
- match_offset = position_base[sym] + extra + 1; |
|
396 |
- break; |
|
397 |
- |
|
398 |
- default: |
|
399 |
- /* should be impossible, model7 can only return 0-6 */ |
|
400 |
- return qtm->error = MSPACK_ERR_DECRUNCH; |
|
401 |
- } |
|
402 |
- |
|
403 |
- rundest = &window[window_posn]; |
|
404 |
- i = match_length; |
|
405 |
- /* does match offset wrap the window? */ |
|
406 |
- if (match_offset > window_posn) { |
|
407 |
- /* j = length from match offset to end of window */ |
|
408 |
- j = match_offset - window_posn; |
|
409 |
- if (j > (int) qtm->window_size) { |
|
410 |
- D(("match offset beyond window boundaries")) |
|
411 |
- return qtm->error = MSPACK_ERR_DECRUNCH; |
|
412 |
- } |
|
413 |
- runsrc = &window[qtm->window_size - j]; |
|
414 |
- if (j < i) { |
|
415 |
- /* if match goes over the window edge, do two copy runs */ |
|
416 |
- i -= j; while (j-- > 0) *rundest++ = *runsrc++; |
|
417 |
- runsrc = window; |
|
418 |
- } |
|
419 |
- while (i-- > 0) *rundest++ = *runsrc++; |
|
420 |
- } |
|
421 |
- else { |
|
422 |
- runsrc = rundest - match_offset; |
|
423 |
- while (i-- > 0) *rundest++ = *runsrc++; |
|
424 |
- } |
|
425 |
- window_posn += match_length; |
|
426 |
- } |
|
427 |
- } /* while (window_posn < frame_end) */ |
|
428 |
- |
|
429 |
- qtm->o_end = &window[window_posn]; |
|
430 |
- |
|
431 |
- /* another frame completed? */ |
|
432 |
- if ((window_posn - frame_start) >= QTM_FRAME_SIZE) { |
|
433 |
- if ((window_posn - frame_start) != QTM_FRAME_SIZE) { |
|
434 |
- D(("overshot frame alignment")) |
|
435 |
- return qtm->error = MSPACK_ERR_DECRUNCH; |
|
436 |
- } |
|
437 |
- |
|
438 |
- /* re-align input */ |
|
439 |
- if (bits_left & 7) REMOVE_BITS(bits_left & 7); |
|
440 |
- do { READ_BITS(i, 8); } while (i != 0xFF); |
|
441 |
- qtm->header_read = 0; |
|
442 |
- |
|
443 |
- /* window wrap? */ |
|
444 |
- if (window_posn == qtm->window_size) { |
|
445 |
- /* flush all currently stored data */ |
|
446 |
- i = (qtm->o_end - qtm->o_ptr); |
|
447 |
- if (qtm->sys->write(qtm->output, qtm->o_ptr, i) != i) { |
|
448 |
- return qtm->error = MSPACK_ERR_WRITE; |
|
449 |
- } |
|
450 |
- out_bytes -= i; |
|
451 |
- qtm->o_ptr = &window[0]; |
|
452 |
- qtm->o_end = &window[0]; |
|
453 |
- window_posn = 0; |
|
454 |
- } |
|
455 |
- |
|
456 |
- frame_start = window_posn; |
|
457 |
- } |
|
458 |
- |
|
459 |
- } /* while (more bytes needed) */ |
|
460 |
- |
|
461 |
- if (out_bytes) { |
|
462 |
- i = (int) out_bytes; |
|
463 |
- if (qtm->sys->write(qtm->output, qtm->o_ptr, i) != i) { |
|
464 |
- return qtm->error = MSPACK_ERR_WRITE; |
|
465 |
- } |
|
466 |
- qtm->o_ptr += i; |
|
467 |
- } |
|
468 |
- |
|
469 |
- /* store local state */ |
|
470 |
- STORE_BITS; |
|
471 |
- qtm->window_posn = window_posn; |
|
472 |
- qtm->frame_start = frame_start; |
|
473 |
- qtm->H = H; |
|
474 |
- qtm->L = L; |
|
475 |
- qtm->C = C; |
|
476 |
- |
|
477 |
- return MSPACK_ERR_OK; |
|
478 |
-} |
|
479 |
- |
|
480 |
-void qtmd_free(struct qtmd_stream *qtm) { |
|
481 |
- struct mspack_system *sys; |
|
482 |
- if (qtm) { |
|
483 |
- sys = qtm->sys; |
|
484 |
- sys->free(qtm->window); |
|
485 |
- sys->free(qtm->inbuf); |
|
486 |
- sys->free(qtm); |
|
487 |
- } |
|
488 |
-} |
489 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,251 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
5 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
6 |
- * |
|
7 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
8 |
- */ |
|
9 |
- |
|
10 |
-#if HAVE_CONFIG_H |
|
11 |
-#include "clamav-config.h" |
|
12 |
-#endif |
|
13 |
- |
|
14 |
-#include <mspack.h> |
|
15 |
-#include "others.h" |
|
16 |
- |
|
17 |
-int mspack_version(int entity) { |
|
18 |
- switch (entity) { |
|
19 |
- case MSPACK_VER_LIBRARY: |
|
20 |
- case MSPACK_VER_SYSTEM: |
|
21 |
- case MSPACK_VER_MSCABD: |
|
22 |
- case MSPACK_VER_MSCHMD: |
|
23 |
- return 1; |
|
24 |
- case MSPACK_VER_MSCABC: |
|
25 |
- case MSPACK_VER_MSCHMC: |
|
26 |
- case MSPACK_VER_MSLITD: |
|
27 |
- case MSPACK_VER_MSLITC: |
|
28 |
- case MSPACK_VER_MSHLPD: |
|
29 |
- case MSPACK_VER_MSHLPC: |
|
30 |
- case MSPACK_VER_MSSZDDD: |
|
31 |
- case MSPACK_VER_MSSZDDC: |
|
32 |
- case MSPACK_VER_MSKWAJD: |
|
33 |
- case MSPACK_VER_MSKWAJC: |
|
34 |
- return 0; |
|
35 |
- } |
|
36 |
- return -1; |
|
37 |
-} |
|
38 |
- |
|
39 |
-int mspack_sys_selftest_internal(int offt_size) { |
|
40 |
- return (sizeof(off_t) == offt_size) ? MSPACK_ERR_OK : MSPACK_ERR_SEEK; |
|
41 |
-} |
|
42 |
- |
|
43 |
-/* validates a system structure */ |
|
44 |
-int mspack_valid_system(struct mspack_system *sys) { |
|
45 |
- return (sys != NULL) && (sys->open != NULL) && (sys->close != NULL) && |
|
46 |
- (sys->read != NULL) && (sys->write != NULL) && (sys->seek != NULL) && |
|
47 |
- (sys->tell != NULL) && (sys->message != NULL) && (sys->alloc != NULL) && |
|
48 |
- (sys->free != NULL) && (sys->copy != NULL) && (sys->null_ptr == NULL); |
|
49 |
-} |
|
50 |
- |
|
51 |
-/* returns the length of a file opened for reading */ |
|
52 |
-int mspack_sys_filelen(struct mspack_system *system, |
|
53 |
- struct mspack_file *file, off_t *length) |
|
54 |
-{ |
|
55 |
- off_t current; |
|
56 |
- |
|
57 |
- if (!system || !file || !length) return MSPACK_ERR_OPEN; |
|
58 |
- |
|
59 |
- /* get current offset */ |
|
60 |
- current = system->tell(file); |
|
61 |
- |
|
62 |
- /* seek to end of file */ |
|
63 |
- if (system->seek(file, (off_t) 0, MSPACK_SYS_SEEK_END)) { |
|
64 |
- return MSPACK_ERR_SEEK; |
|
65 |
- } |
|
66 |
- |
|
67 |
- /* get offset of end of file */ |
|
68 |
- *length = system->tell(file); |
|
69 |
- |
|
70 |
- /* seek back to original offset */ |
|
71 |
- if (system->seek(file, current, MSPACK_SYS_SEEK_START)) { |
|
72 |
- return MSPACK_ERR_SEEK; |
|
73 |
- } |
|
74 |
- |
|
75 |
- return MSPACK_ERR_OK; |
|
76 |
-} |
|
77 |
- |
|
78 |
- |
|
79 |
- |
|
80 |
-/* definition of mspack_default_system -- if the library is compiled with |
|
81 |
- * MSPACK_NO_DEFAULT_SYSTEM, no default system will be provided. Otherwise, |
|
82 |
- * an appropriate default system (e.g. the standard C library, or some native |
|
83 |
- * API calls) |
|
84 |
- */ |
|
85 |
- |
|
86 |
-#ifdef MSPACK_NO_DEFAULT_SYSTEM |
|
87 |
-struct mspack_system *mspack_default_system = NULL; |
|
88 |
-#else |
|
89 |
- |
|
90 |
-/* implementation of mspack_default_system for standard C library */ |
|
91 |
- |
|
92 |
-#include <stdio.h> |
|
93 |
-#include <stdlib.h> |
|
94 |
-#include <string.h> |
|
95 |
-#include <stdarg.h> |
|
96 |
- |
|
97 |
-struct mspack_file_p { |
|
98 |
- FILE *fh; |
|
99 |
- char *name; |
|
100 |
- int desc; |
|
101 |
-}; |
|
102 |
- |
|
103 |
-static struct mspack_file *msp_open(struct mspack_system *this, |
|
104 |
- char *filename, int mode) |
|
105 |
-{ |
|
106 |
- struct mspack_file_p *fh; |
|
107 |
- char *fmode; |
|
108 |
- |
|
109 |
- switch (mode) { |
|
110 |
- case MSPACK_SYS_OPEN_READ: fmode = "rb"; break; |
|
111 |
- case MSPACK_SYS_OPEN_WRITE: fmode = "wb"; break; |
|
112 |
- case MSPACK_SYS_OPEN_UPDATE: fmode = "r+b"; break; |
|
113 |
- case MSPACK_SYS_OPEN_APPEND: fmode = "ab"; break; |
|
114 |
- default: return NULL; |
|
115 |
- } |
|
116 |
- |
|
117 |
- if ((fh = malloc(sizeof(struct mspack_file_p)))) { |
|
118 |
- fh->name = filename; |
|
119 |
- fh->desc = 0; |
|
120 |
- if ((fh->fh = fopen(filename, fmode))) return (struct mspack_file *) fh; |
|
121 |
- free(fh); |
|
122 |
- } |
|
123 |
- return NULL; |
|
124 |
-} |
|
125 |
- |
|
126 |
-static struct mspack_file *msp_dopen(struct mspack_system *this, |
|
127 |
- int desc, int mode) |
|
128 |
-{ |
|
129 |
- struct mspack_file_p *fh; |
|
130 |
- char *fmode; |
|
131 |
- |
|
132 |
- switch (mode) { |
|
133 |
- case MSPACK_SYS_OPEN_READ: fmode = "rb"; break; |
|
134 |
- case MSPACK_SYS_OPEN_WRITE: fmode = "wb"; break; |
|
135 |
- case MSPACK_SYS_OPEN_UPDATE: fmode = "r+b"; break; |
|
136 |
- case MSPACK_SYS_OPEN_APPEND: fmode = "ab"; break; |
|
137 |
- default: return NULL; |
|
138 |
- } |
|
139 |
- |
|
140 |
- if ((fh = malloc(sizeof(struct mspack_file_p)))) { |
|
141 |
- fh->name = "descriptor"; |
|
142 |
- fh->desc = desc; |
|
143 |
- if ((fh->fh = fdopen(desc, fmode))) return (struct mspack_file *) fh; |
|
144 |
- free(fh); |
|
145 |
- } |
|
146 |
- return NULL; |
|
147 |
-} |
|
148 |
- |
|
149 |
-static void msp_close(struct mspack_file *file) { |
|
150 |
- struct mspack_file_p *this = (struct mspack_file_p *) file; |
|
151 |
- if (this) { |
|
152 |
- fclose(this->fh); |
|
153 |
- free(this); |
|
154 |
- } |
|
155 |
-} |
|
156 |
- |
|
157 |
-static int msp_read(struct mspack_file *file, void *buffer, int bytes) { |
|
158 |
- struct mspack_file_p *this = (struct mspack_file_p *) file; |
|
159 |
- if (this) { |
|
160 |
- size_t count = fread(buffer, 1, (size_t) bytes, this->fh); |
|
161 |
- if (!ferror(this->fh)) return (int) count; |
|
162 |
- } |
|
163 |
- return -1; |
|
164 |
-} |
|
165 |
- |
|
166 |
-static int msp_write(struct mspack_file *file, void *buffer, int bytes) { |
|
167 |
- struct mspack_file_p *this = (struct mspack_file_p *) file; |
|
168 |
- if (this) { |
|
169 |
- size_t count = fwrite(buffer, 1, (size_t) bytes, this->fh); |
|
170 |
- if (!ferror(this->fh)) return (int) count; |
|
171 |
- } |
|
172 |
- return -1; |
|
173 |
-} |
|
174 |
- |
|
175 |
-static int msp_seek(struct mspack_file *file, off_t offset, int mode) { |
|
176 |
- struct mspack_file_p *this = (struct mspack_file_p *) file; |
|
177 |
- if (this) { |
|
178 |
- switch (mode) { |
|
179 |
- case MSPACK_SYS_SEEK_START: mode = SEEK_SET; break; |
|
180 |
- case MSPACK_SYS_SEEK_CUR: mode = SEEK_CUR; break; |
|
181 |
- case MSPACK_SYS_SEEK_END: mode = SEEK_END; break; |
|
182 |
- default: return -1; |
|
183 |
- } |
|
184 |
-#ifdef HAVE_FSEEKO |
|
185 |
- return fseeko(this->fh, offset, mode); |
|
186 |
-#else |
|
187 |
- return fseek(this->fh, offset, mode); |
|
188 |
-#endif |
|
189 |
- } |
|
190 |
- return -1; |
|
191 |
-} |
|
192 |
- |
|
193 |
-static off_t msp_tell(struct mspack_file *file) { |
|
194 |
- struct mspack_file_p *this = (struct mspack_file_p *) file; |
|
195 |
-#ifdef HAVE_FSEEKO |
|
196 |
- return (this) ? (off_t) ftello(this->fh) : 0; |
|
197 |
-#else |
|
198 |
- return (this) ? (off_t) ftell(this->fh) : 0; |
|
199 |
-#endif |
|
200 |
-} |
|
201 |
- |
|
202 |
-static void msp_msg(struct mspack_file *file, char *format, ...) { |
|
203 |
- va_list ap; |
|
204 |
- char buff[512]; |
|
205 |
- |
|
206 |
- va_start(ap, format); |
|
207 |
- vsnprintf(buff, 512, format, ap); |
|
208 |
- va_end(ap); |
|
209 |
- cli_dbgmsg("libmspack: %s\n", buff); |
|
210 |
-} |
|
211 |
- |
|
212 |
-static void *msp_alloc(struct mspack_system *this, size_t bytes) { |
|
213 |
-#ifdef DEBUG |
|
214 |
- /* make uninitialised data obvious */ |
|
215 |
- char *buf = malloc(bytes + 8); |
|
216 |
- if (buf) memset(buf, 0xDC, bytes); |
|
217 |
- *((size_t *)buf) = bytes; |
|
218 |
- return &buf[8]; |
|
219 |
-#else |
|
220 |
- return malloc(bytes); |
|
221 |
-#endif |
|
222 |
-} |
|
223 |
- |
|
224 |
-static void msp_free(void *buffer) { |
|
225 |
-#ifdef DEBUG |
|
226 |
- char *buf = buffer; |
|
227 |
- size_t bytes; |
|
228 |
- if (buf) { |
|
229 |
- buf -= 8; |
|
230 |
- bytes = *((size_t *)buf); |
|
231 |
- /* make freed data obvious */ |
|
232 |
- memset(buf, 0xED, bytes); |
|
233 |
- free(buf); |
|
234 |
- } |
|
235 |
-#else |
|
236 |
- free(buffer); |
|
237 |
-#endif |
|
238 |
-} |
|
239 |
- |
|
240 |
-static void msp_copy(void *src, void *dest, size_t bytes) { |
|
241 |
- memcpy(dest, src, bytes); |
|
242 |
-} |
|
243 |
- |
|
244 |
-static struct mspack_system msp_system = { |
|
245 |
- &msp_open, &msp_dopen, &msp_close, &msp_read, &msp_write, &msp_seek, |
|
246 |
- &msp_tell, &msp_msg, &msp_alloc, &msp_free, &msp_copy, NULL |
|
247 |
-}; |
|
248 |
- |
|
249 |
-struct mspack_system *mspack_default_system = &msp_system; |
|
250 |
- |
|
251 |
-#endif |
252 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,58 +0,0 @@ |
1 |
-/* This file is part of libmspack. |
|
2 |
- * (C) 2003-2004 Stuart Caie. |
|
3 |
- * |
|
4 |
- * libmspack is free software; you can redistribute it and/or modify it under |
|
5 |
- * the terms of the GNU Lesser General Public License (LGPL) version 2.1 |
|
6 |
- * |
|
7 |
- * For further details, see the file COPYING.LIB distributed with libmspack |
|
8 |
- */ |
|
9 |
- |
|
10 |
-#ifndef MSPACK_SYSTEM_H |
|
11 |
-#define MSPACK_SYSTEM_H 1 |
|
12 |
- |
|
13 |
-#ifdef DEBUG |
|
14 |
-# include <stdio.h> |
|
15 |
-# define D(x) do { printf("%s:%d (%s) ",__FILE__, __LINE__, __FUNCTION__); \ |
|
16 |
- printf x ; fputc('\n', stdout); fflush(stdout);} while (0); |
|
17 |
-#else |
|
18 |
-# define D(x) |
|
19 |
-#endif |
|
20 |
- |
|
21 |
-/* endian-neutral reading of little-endian data */ |
|
22 |
-#define __egi32(a,n) ( (((a)[n+3]) << 24) | (((a)[n+2]) << 16) | \ |
|
23 |
- (((a)[n+1]) << 8) | ((a)[n+0]) ) |
|
24 |
-#define EndGetI64(a) ((((unsigned long long int) __egi32(a,4)) << 32) | \ |
|
25 |
- ((unsigned int) __egi32(a,0))) |
|
26 |
-#define EndGetI32(a) __egi32(a,0) |
|
27 |
-#define EndGetI16(a) ((((a)[1])<<8)|((a)[0])) |
|
28 |
- |
|
29 |
-/* endian-neutral reading of big-endian data */ |
|
30 |
-#define EndGetM32(a) ((((a)[0])<<24)|(((a)[1])<<16)|(((a)[2])<<8)|((a)[3])) |
|
31 |
-#define EndGetM16(a) ((((a)[0])<<8)|((a)[1])) |
|
32 |
- |
|
33 |
-extern struct mspack_system *mspack_default_system; |
|
34 |
- |
|
35 |
-/* returns the length of a file opened for reading */ |
|
36 |
-extern int mspack_sys_filelen(struct mspack_system *system, |
|
37 |
- struct mspack_file *file, off_t *length); |
|
38 |
- |
|
39 |
-/* validates a system structure */ |
|
40 |
-extern int mspack_valid_system(struct mspack_system *sys); |
|
41 |
- |
|
42 |
-/* inline memcmp() */ |
|
43 |
-static inline int memcmp(const void *s1, const void *s2, size_t n) { |
|
44 |
- unsigned char *c1 = (unsigned char *) s1; |
|
45 |
- unsigned char *c2 = (unsigned char *) s2; |
|
46 |
- if (n == 0) return 0; |
|
47 |
- while (--n && (*c1 == *c2)) c1++, c2++; |
|
48 |
- return *c1 - *c2; |
|
49 |
-} |
|
50 |
- |
|
51 |
-/* inline strlen() */ |
|
52 |
-static inline size_t strlen(const char *s) { |
|
53 |
- const char *e = s; |
|
54 |
- while (*e) e++; |
|
55 |
- return e - s; |
|
56 |
-} |
|
57 |
- |
|
58 |
-#endif |
59 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,491 +0,0 @@ |
1 |
-/* |
|
2 |
- * Copyright (C) 2004 Tomasz Kojm <tkojm@clamav.net> |
|
3 |
- * |
|
4 |
- * Implementation (header structures) based on the PE format description |
|
5 |
- * by B. Luevelsmeyer |
|
6 |
- * |
|
7 |
- * This program is free software; you can redistribute it and/or modify |
|
8 |
- * it under the terms of the GNU General Public License as published by |
|
9 |
- * the Free Software Foundation; either version 2 of the License, or |
|
10 |
- * (at your option) any later version. |
|
11 |
- * |
|
12 |
- * This program 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 |
|
15 |
- * GNU General Public License for more details. |
|
16 |
- * |
|
17 |
- * You should have received a copy of the GNU General Public License |
|
18 |
- * along with this program; if not, write to the Free Software |
|
19 |
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
20 |
- */ |
|
21 |
- |
|
22 |
-#if HAVE_CONFIG_H |
|
23 |
-#include "clamav-config.h" |
|
24 |
-#endif |
|
25 |
- |
|
26 |
-#include <stdio.h> |
|
27 |
-#include <string.h> |
|
28 |
-#include <sys/types.h> |
|
29 |
-#include <sys/stat.h> |
|
30 |
-#include <fcntl.h> |
|
31 |
-#include <sys/stat.h> |
|
32 |
-#include <unistd.h> |
|
33 |
-#include <time.h> |
|
34 |
- |
|
35 |
-#include "cltypes.h" |
|
36 |
-#include "clamav.h" |
|
37 |
-#include "others.h" |
|
38 |
-#include "upx.h" |
|
39 |
- |
|
40 |
-#define IMAGE_DOS_SIGNATURE 0x5a4d /* MZ */ |
|
41 |
-#define IMAGE_NT_SIGNATURE 0x00004550 |
|
42 |
-#define IMAGE_OPTIONAL_SIGNATURE 0x010b |
|
43 |
- |
|
44 |
-#define UPX_NRV2B "\x11\xc9\x75\x20\x41\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x01\xdb\x73\xef\x75\x09" |
|
45 |
-#define UPX_NRV2D "\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x11\xc9\x75\x20" |
|
46 |
-#define UPX_NRV2E "\x83\xf0\xff\x74\x75\xd1\xf8\x89\xc5\xeb\x0b\x01\xdb\x75\x07\x8b\x1e\x83\xee\xfc\x11\xdb\x72\xcc" |
|
47 |
- |
|
48 |
-struct pe_image_file_hdr { |
|
49 |
- uint32_t Magic; |
|
50 |
- uint16_t Machine; |
|
51 |
- uint16_t NumberOfSections; |
|
52 |
- uint32_t TimeDateStamp; /* unreliable */ |
|
53 |
- uint32_t PointerToSymbolTable; /* debug */ |
|
54 |
- uint32_t NumberOfSymbols; /* debug */ |
|
55 |
- uint16_t SizeOfOptionalHeader; /* == 224 */ |
|
56 |
- uint16_t Characteristics; |
|
57 |
-}; |
|
58 |
- |
|
59 |
-struct pe_image_data_dir { |
|
60 |
- uint32_t VirtualAddress; |
|
61 |
- uint32_t Size; |
|
62 |
-}; |
|
63 |
- |
|
64 |
-struct pe_image_optional_hdr { |
|
65 |
- uint16_t Magic; |
|
66 |
- uint8_t MajorLinkerVersion; /* unreliable */ |
|
67 |
- uint8_t MinorLinkerVersion; /* unreliable */ |
|
68 |
- uint32_t SizeOfCode; /* unreliable */ |
|
69 |
- uint32_t SizeOfInitializedData; /* unreliable */ |
|
70 |
- uint32_t SizeOfUninitializedData; /* unreliable */ |
|
71 |
- uint32_t AddressOfEntryPoint; |
|
72 |
- uint32_t BaseOfCode; |
|
73 |
- uint32_t BaseOfData; |
|
74 |
- uint32_t ImageBase; /* multiple of 64 KB */ |
|
75 |
- uint32_t SectionAlignment; /* usually 32 or 4096 */ |
|
76 |
- uint32_t FileAlignment; /* usually 32 or 512 */ |
|
77 |
- uint16_t MajorOperatingSystemVersion; /* not used */ |
|
78 |
- uint16_t MinorOperatingSystemVersion; /* not used */ |
|
79 |
- uint16_t MajorImageVersion; /* unreliable */ |
|
80 |
- uint16_t MinorImageVersion; /* unreliable */ |
|
81 |
- uint16_t MajorSubsystemVersion; |
|
82 |
- uint16_t MinorSubsystemVersion; |
|
83 |
- uint32_t Win32VersionValue; /* ? */ |
|
84 |
- uint32_t SizeOfImage; |
|
85 |
- uint32_t SizeOfHeaders; |
|
86 |
- uint32_t CheckSum; /* NT drivers only */ |
|
87 |
- uint16_t Subsystem; |
|
88 |
- uint16_t DllCharacteristics; |
|
89 |
- uint32_t SizeOfStackReserve; |
|
90 |
- uint32_t SizeOfStackCommit; |
|
91 |
- uint32_t SizeOfHeapReserve; |
|
92 |
- uint32_t SizeOfHeapCommit; |
|
93 |
- uint32_t LoaderFlags; /* ? */ |
|
94 |
- uint32_t NumberOfRvaAndSizes; /* unreliable */ |
|
95 |
- struct pe_image_data_dir DataDirectory[16]; |
|
96 |
-}; |
|
97 |
- |
|
98 |
-struct pe_image_section_hdr { |
|
99 |
- uint8_t Name[8]; /* may not end with NULL */ |
|
100 |
- /* |
|
101 |
- union { |
|
102 |
- uint32_t PhysicalAddress; |
|
103 |
- uint32_t VirtualSize; |
|
104 |
- } AddrSize; |
|
105 |
- */ |
|
106 |
- uint32_t VirtualSize; |
|
107 |
- uint32_t VirtualAddress; |
|
108 |
- uint32_t SizeOfRawData; /* multiple of FileAlignment */ |
|
109 |
- uint32_t PointerToRawData; /* offset to the section's data */ |
|
110 |
- uint32_t PointerToRelocations; /* object files only */ |
|
111 |
- uint32_t PointerToLinenumbers; /* object files only */ |
|
112 |
- uint16_t NumberOfRelocations; /* object files only */ |
|
113 |
- uint16_t NumberOfLinenumbers; /* object files only */ |
|
114 |
- uint32_t Characteristics; |
|
115 |
-}; |
|
116 |
- |
|
117 |
-static uint32_t cli_rawaddr(uint32_t rva, struct pe_image_section_hdr *shp, uint16_t nos) |
|
118 |
-{ |
|
119 |
- int i, found = 0; |
|
120 |
- |
|
121 |
- |
|
122 |
- for(i = 0; i < nos; i++) { |
|
123 |
- if(shp[i].VirtualAddress <= rva && shp[i].VirtualAddress + shp[i].SizeOfRawData > rva) { |
|
124 |
- found = 1; |
|
125 |
- break; |
|
126 |
- } |
|
127 |
- } |
|
128 |
- |
|
129 |
- if(!found) { |
|
130 |
- cli_dbgmsg("Can't calculate raw address from RVA 0x%x\n", rva); |
|
131 |
- return -1; |
|
132 |
- } |
|
133 |
- |
|
134 |
- return rva - shp[i].VirtualAddress + shp[i].PointerToRawData; |
|
135 |
-} |
|
136 |
- |
|
137 |
-static int cli_ddump(int desc, int offset, int size, const char *file) |
|
138 |
-{ |
|
139 |
- int pos, ndesc, bread, sum = 0; |
|
140 |
- char buff[FILEBUFF]; |
|
141 |
- |
|
142 |
- |
|
143 |
- cli_dbgmsg("in ddump()\n"); |
|
144 |
- |
|
145 |
- if((pos = lseek(desc, 0, SEEK_CUR)) == -1) { |
|
146 |
- cli_dbgmsg("Invalid descriptor\n"); |
|
147 |
- return CL_EIO; |
|
148 |
- } |
|
149 |
- |
|
150 |
- if(lseek(desc, offset, SEEK_SET) == -1) { |
|
151 |
- cli_dbgmsg("lseek() failed\n"); |
|
152 |
- lseek(desc, pos, SEEK_SET); |
|
153 |
- return CL_EIO; |
|
154 |
- } |
|
155 |
- |
|
156 |
- if((ndesc = open(file, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
|
157 |
- cli_dbgmsg("Can't create file %s\n", file); |
|
158 |
- lseek(desc, pos, SEEK_SET); |
|
159 |
- return CL_EIO; |
|
160 |
- } |
|
161 |
- |
|
162 |
- while((bread = read(desc, buff, FILEBUFF)) > 0) { |
|
163 |
- if(sum + bread >= size) { |
|
164 |
- if(write(ndesc, buff, size - sum) == -1) { |
|
165 |
- cli_dbgmsg("Can't write to file\n"); |
|
166 |
- lseek(desc, pos, SEEK_SET); |
|
167 |
- close(ndesc); |
|
168 |
- unlink(file); |
|
169 |
- return CL_EIO; |
|
170 |
- } |
|
171 |
- break; |
|
172 |
- } else { |
|
173 |
- if(write(ndesc, buff, bread) == -1) { |
|
174 |
- cli_dbgmsg("Can't write to file\n"); |
|
175 |
- lseek(desc, pos, SEEK_SET); |
|
176 |
- close(ndesc); |
|
177 |
- unlink(file); |
|
178 |
- return CL_EIO; |
|
179 |
- } |
|
180 |
- } |
|
181 |
- sum += bread; |
|
182 |
- } |
|
183 |
- |
|
184 |
- close(ndesc); |
|
185 |
- lseek(desc, pos, SEEK_SET); |
|
186 |
- return 0; |
|
187 |
-} |
|
188 |
- |
|
189 |
-int cli_scanpe(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) |
|
190 |
-{ |
|
191 |
- uint16_t e_magic; /* DOS signature ("MZ") */ |
|
192 |
- uint32_t e_lfanew; /* address of new exe header */ |
|
193 |
- uint32_t ep; /* entry point (raw) */ |
|
194 |
- struct pe_image_file_hdr file_hdr; |
|
195 |
- struct pe_image_optional_hdr optional_hdr; |
|
196 |
- struct pe_image_section_hdr *section_hdr; |
|
197 |
- struct stat sb; |
|
198 |
- char sname[9], buff[24], *tempfile; |
|
199 |
- int i, found; |
|
200 |
- int (*upxfn)(char *, int , char *, int) = NULL; |
|
201 |
- |
|
202 |
- |
|
203 |
- if(read(desc, &e_magic, sizeof(e_magic)) != sizeof(e_magic)) { |
|
204 |
- cli_dbgmsg("Can't read DOS signature\n"); |
|
205 |
- return CL_EIO; |
|
206 |
- } |
|
207 |
- |
|
208 |
- if(e_magic != IMAGE_DOS_SIGNATURE) { |
|
209 |
- cli_dbgmsg("Invalid DOS signature\n"); |
|
210 |
- return -1; |
|
211 |
- } |
|
212 |
- |
|
213 |
- lseek(desc, 58, SEEK_CUR); /* skip to the end of the DOS header */ |
|
214 |
- |
|
215 |
- if(read(desc, &e_lfanew, sizeof(e_lfanew)) != sizeof(e_lfanew)) { |
|
216 |
- cli_dbgmsg("Can't read new header address\n"); |
|
217 |
- return -1; |
|
218 |
- } |
|
219 |
- |
|
220 |
- cli_dbgmsg("e_lfanew == %d\n", e_lfanew); |
|
221 |
- if(!e_lfanew) { |
|
222 |
- cli_dbgmsg("Not a PE file\n"); |
|
223 |
- return -2; |
|
224 |
- } |
|
225 |
- |
|
226 |
- lseek(desc, e_lfanew, SEEK_SET); |
|
227 |
- |
|
228 |
- if(read(desc, &file_hdr, sizeof(struct pe_image_file_hdr)) != sizeof(struct pe_image_file_hdr)) { |
|
229 |
- cli_dbgmsg("Can't read file header\n"); |
|
230 |
- return -1; |
|
231 |
- } |
|
232 |
- |
|
233 |
- if(file_hdr.Magic != IMAGE_NT_SIGNATURE) { |
|
234 |
- cli_dbgmsg("Invalid PE signature (probably NE file)\n"); |
|
235 |
- return -2; |
|
236 |
- } |
|
237 |
- |
|
238 |
- /* cli_dbgmsg("Machine type: "); */ |
|
239 |
- switch(file_hdr.Machine) { |
|
240 |
- case 0x14c: |
|
241 |
- cli_dbgmsg("Machine type: 80386\n"); |
|
242 |
- break; |
|
243 |
- case 0x014d: |
|
244 |
- cli_dbgmsg("Machine type: 80486\n"); |
|
245 |
- break; |
|
246 |
- case 0x014e: |
|
247 |
- cli_dbgmsg("Machine type: 80586\n"); |
|
248 |
- break; |
|
249 |
- case 0x162: |
|
250 |
- cli_dbgmsg("Machine type: R3000\n"); |
|
251 |
- break; |
|
252 |
- case 0x166: |
|
253 |
- cli_dbgmsg("Machine type: R4000\n"); |
|
254 |
- break; |
|
255 |
- case 0x168: |
|
256 |
- cli_dbgmsg("Machine type: R10000\n"); |
|
257 |
- break; |
|
258 |
- case 0x184: |
|
259 |
- cli_dbgmsg("Machine type: DEC Alpha AXP\n"); |
|
260 |
- break; |
|
261 |
- case 0x1f0: |
|
262 |
- cli_dbgmsg("Machine type: PowerPC\n"); |
|
263 |
- break; |
|
264 |
- default: |
|
265 |
- cli_warnmsg("Unknown machine type in PE header\n"); |
|
266 |
- } |
|
267 |
- |
|
268 |
- cli_dbgmsg("NumberOfSections: %d\n", file_hdr.NumberOfSections); |
|
269 |
- cli_dbgmsg("TimeDateStamp: %s", ctime((time_t *) &file_hdr.TimeDateStamp)); |
|
270 |
- |
|
271 |
- cli_dbgmsg("SizeOfOptionalHeader: %d\n", file_hdr.SizeOfOptionalHeader); |
|
272 |
- |
|
273 |
- if(file_hdr.SizeOfOptionalHeader != sizeof(struct pe_image_optional_hdr)) { |
|
274 |
- cli_warnmsg("Broken PE header detected.\n"); |
|
275 |
- return -1; |
|
276 |
- } |
|
277 |
- |
|
278 |
- if(read(desc, &optional_hdr, sizeof(struct pe_image_optional_hdr)) != sizeof(struct pe_image_optional_hdr)) { |
|
279 |
- cli_dbgmsg("Can't optional file header\n"); |
|
280 |
- return -1; |
|
281 |
- } |
|
282 |
- |
|
283 |
- cli_dbgmsg("MajorLinkerVersion: %d\n", optional_hdr.MajorLinkerVersion); |
|
284 |
- cli_dbgmsg("MinorLinkerVersion: %d\n", optional_hdr.MinorLinkerVersion); |
|
285 |
- cli_dbgmsg("SizeOfCode: %d\n", optional_hdr.SizeOfCode); |
|
286 |
- cli_dbgmsg("SizeOfInitializedData: %d\n", optional_hdr.SizeOfInitializedData); |
|
287 |
- cli_dbgmsg("SizeOfUninitializedData: %d\n", optional_hdr.SizeOfUninitializedData); |
|
288 |
- cli_dbgmsg("AddressOfEntryPoint: 0x%x\n", optional_hdr.AddressOfEntryPoint); |
|
289 |
- cli_dbgmsg("SectionAlignment: %d\n", optional_hdr.SectionAlignment); |
|
290 |
- cli_dbgmsg("FileAlignment: %d\n", optional_hdr.FileAlignment); |
|
291 |
- cli_dbgmsg("MajorSubsystemVersion: %d\n", optional_hdr.MajorSubsystemVersion); |
|
292 |
- cli_dbgmsg("MinorSubsystemVersion: %d\n", optional_hdr.MinorSubsystemVersion); |
|
293 |
- cli_dbgmsg("SizeOfImage: %d\n", optional_hdr.SizeOfImage); |
|
294 |
- cli_dbgmsg("SizeOfHeaders: %d\n", optional_hdr.SizeOfHeaders); |
|
295 |
- |
|
296 |
- switch(optional_hdr.Subsystem) { |
|
297 |
- case 1: |
|
298 |
- cli_dbgmsg("Subsystem: Native (a driver ?)\n"); |
|
299 |
- break; |
|
300 |
- case 2: |
|
301 |
- cli_dbgmsg("Subsystem: Win32 GUI\n"); |
|
302 |
- break; |
|
303 |
- case 3: |
|
304 |
- cli_dbgmsg("Subsystem: Win32 console\n"); |
|
305 |
- break; |
|
306 |
- case 5: |
|
307 |
- cli_dbgmsg("Subsystem: OS/2 console\n"); |
|
308 |
- break; |
|
309 |
- case 7: |
|
310 |
- cli_dbgmsg("Subsystem: POSIX console\n"); |
|
311 |
- break; |
|
312 |
- default: |
|
313 |
- cli_warnmsg("Unknown subsystem in PE header\n"); |
|
314 |
- } |
|
315 |
- |
|
316 |
- cli_dbgmsg("NumberOfRvaAndSizes: %d\n", optional_hdr.NumberOfRvaAndSizes); |
|
317 |
- |
|
318 |
- section_hdr = (struct pe_image_section_hdr *) cli_calloc(file_hdr.NumberOfSections, sizeof(struct pe_image_section_hdr)); |
|
319 |
- |
|
320 |
- if(!section_hdr) { |
|
321 |
- cli_dbgmsg("Can't allocate memory for section headers\n"); |
|
322 |
- return CL_EMEM; |
|
323 |
- } |
|
324 |
- |
|
325 |
- for(i = 0; i < file_hdr.NumberOfSections; i++) { |
|
326 |
- |
|
327 |
- if(read(desc, §ion_hdr[i], sizeof(struct pe_image_section_hdr)) != sizeof(struct pe_image_section_hdr)) { |
|
328 |
- cli_dbgmsg("Can't read section header\n"); |
|
329 |
- cli_warnmsg("Possibly broken PE file\n"); |
|
330 |
- free(section_hdr); |
|
331 |
- return CL_CLEAN; |
|
332 |
- } |
|
333 |
- |
|
334 |
- strncpy(sname, section_hdr[i].Name, 8); |
|
335 |
- sname[8] = 0; |
|
336 |
- cli_dbgmsg("------------------------------------\n"); |
|
337 |
- cli_dbgmsg("Section name: %s\n", sname); |
|
338 |
- cli_dbgmsg("VirtualSize: %d\n", section_hdr[i].VirtualSize); |
|
339 |
- cli_dbgmsg("VirtualAddress: 0x%x\n", section_hdr[i].VirtualAddress); |
|
340 |
- cli_dbgmsg("Section size: %d\n", section_hdr[i].SizeOfRawData); |
|
341 |
- cli_dbgmsg("PointerToRawData: 0x%x (%d)\n", section_hdr[i].PointerToRawData, section_hdr[i].PointerToRawData); |
|
342 |
- |
|
343 |
- if(section_hdr[i].Characteristics & 0x20) { |
|
344 |
- cli_dbgmsg("Section contains executable code\n"); |
|
345 |
- |
|
346 |
- if(section_hdr[i].VirtualSize < section_hdr[i].SizeOfRawData) { |
|
347 |
- cli_dbgmsg("Section contains free space\n"); |
|
348 |
- /* |
|
349 |
- cli_dbgmsg("Dumping %d bytes\n", section_hdr.SizeOfRawData - section_hdr.VirtualSize); |
|
350 |
- ddump(desc, section_hdr.PointerToRawData + section_hdr.VirtualSize, section_hdr.SizeOfRawData - section_hdr.VirtualSize, cl_gentemp(NULL)); |
|
351 |
- */ |
|
352 |
- |
|
353 |
- } |
|
354 |
- } |
|
355 |
- |
|
356 |
- if(section_hdr[i].Characteristics & 0x20000000) |
|
357 |
- cli_dbgmsg("Section's memory is executable\n"); |
|
358 |
- |
|
359 |
-/* |
|
360 |
- if(!strcmp(sname, "_winzip_")) { |
|
361 |
- int ptrd = section_hdr.PointerToRawData & ~(optional_hdr.FileAlignment - 1); |
|
362 |
- |
|
363 |
- cli_dbgmsg("WinZip section\n"); |
|
364 |
- ddump(desc, ptrd, section_hdr.SizeOfRawData, cl_gentemp(NULL)); |
|
365 |
- } |
|
366 |
-*/ |
|
367 |
- |
|
368 |
- } |
|
369 |
- |
|
370 |
- if(fstat(desc, &sb) == -1) { |
|
371 |
- cli_dbgmsg("fstat failed\n"); |
|
372 |
- free(section_hdr); |
|
373 |
- return CL_EIO; |
|
374 |
- } |
|
375 |
- |
|
376 |
- ep = cli_rawaddr(optional_hdr.AddressOfEntryPoint, section_hdr, file_hdr.NumberOfSections); |
|
377 |
- |
|
378 |
- if(section_hdr[i].PointerToRawData + section_hdr[i].SizeOfRawData > sb.st_size || ep == -1) { |
|
379 |
- cli_warnmsg("Possibly broken PE file\n"); |
|
380 |
- free(section_hdr); |
|
381 |
- return CL_CLEAN; |
|
382 |
- } |
|
383 |
- |
|
384 |
- cli_dbgmsg("EntryPoint offset: 0x%x (%d)\n", ep, ep); |
|
385 |
- |
|
386 |
- if(lseek(desc, ep + 0x78, SEEK_SET) == -1) { |
|
387 |
- cli_dbgmsg("lseek() failed\n"); |
|
388 |
- free(section_hdr); |
|
389 |
- return CL_EIO; |
|
390 |
- } |
|
391 |
- |
|
392 |
- if(read(desc, buff, 24) != 24) { |
|
393 |
- cli_dbgmsg("Can't read 24 bytes at 0x%x (%d)\n", ep + 0x78, ep + 0x78); |
|
394 |
- } else { |
|
395 |
- if(!memcmp(buff, UPX_NRV2B, 24)) { |
|
396 |
- cli_dbgmsg("UPX: NRV2B decompressor detected\n"); |
|
397 |
- upxfn = upx_inflate2b; |
|
398 |
- } else if(!memcmp(buff, UPX_NRV2D, 24)) { |
|
399 |
- cli_dbgmsg("UPX: NRV2D decompressor detected\n"); |
|
400 |
- upxfn = upx_inflate2d; |
|
401 |
- } else if(!memcmp(buff, UPX_NRV2E, 24)) { |
|
402 |
- cli_dbgmsg("UPX: NRV2E decompressor detected\n"); |
|
403 |
- upxfn = upx_inflate2e; |
|
404 |
- } |
|
405 |
- } |
|
406 |
- |
|
407 |
- if(upxfn) { |
|
408 |
- /* try to find the first section with physical size == 0 */ |
|
409 |
- found = 0; |
|
410 |
- for(i = 0; i < file_hdr.NumberOfSections; i++) { |
|
411 |
- if(!section_hdr[i].SizeOfRawData) { |
|
412 |
- found = 1; |
|
413 |
- break; |
|
414 |
- } |
|
415 |
- } |
|
416 |
- |
|
417 |
- if(found) { |
|
418 |
- uint32_t ssize, dsize; |
|
419 |
- char *src, *dest; |
|
420 |
- |
|
421 |
- /* we assume (i + 1) is UPX1 */ |
|
422 |
- if(strncmp(section_hdr[i].Name, "UPX0", 4) || strncmp(section_hdr[i + 1].Name, "UPX1", 4)) |
|
423 |
- cli_dbgmsg("Possibly hacked UPX section headers\n"); |
|
424 |
- |
|
425 |
- /* FIXME: use file operations in case of big files */ |
|
426 |
- ssize = section_hdr[i + 1].SizeOfRawData; |
|
427 |
- dsize = section_hdr[i].VirtualSize + section_hdr[i + 1].VirtualSize; |
|
428 |
- if((src = (char *) malloc(ssize)) == NULL) { |
|
429 |
- free(section_hdr); |
|
430 |
- return CL_EMEM; |
|
431 |
- } |
|
432 |
- |
|
433 |
- if((dest = (char *) malloc(dsize)) == NULL) { |
|
434 |
- free(section_hdr); |
|
435 |
- free(src); |
|
436 |
- return CL_EMEM; |
|
437 |
- } |
|
438 |
- |
|
439 |
- lseek(desc, section_hdr[i + 1].PointerToRawData, SEEK_SET); |
|
440 |
- if(read(desc, src, ssize) != ssize) { |
|
441 |
- cli_dbgmsg("Can't read raw data of section %d\n", i + 1); |
|
442 |
- free(section_hdr); |
|
443 |
- free(src); |
|
444 |
- free(dest); |
|
445 |
- return CL_EMEM; |
|
446 |
- } |
|
447 |
- |
|
448 |
- if(upxfn(src, ssize, dest, dsize)) { |
|
449 |
- cli_dbgmsg("UPX decompression failed\n"); |
|
450 |
- } else { |
|
451 |
- int ndesc; |
|
452 |
- |
|
453 |
- tempfile = cl_gentemp(NULL); |
|
454 |
- |
|
455 |
- if((ndesc = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU)) < 0) { |
|
456 |
- cli_dbgmsg("Can't create file %s\n", tempfile); |
|
457 |
- free(section_hdr); |
|
458 |
- free(src); |
|
459 |
- free(dest); |
|
460 |
- return CL_EIO; |
|
461 |
- } |
|
462 |
- |
|
463 |
- if(write(ndesc, dest, dsize) != dsize) { |
|
464 |
- cli_dbgmsg("Can't write %d bytes\n", dsize); |
|
465 |
- free(section_hdr); |
|
466 |
- free(src); |
|
467 |
- free(dest); |
|
468 |
- return CL_EIO; |
|
469 |
- } |
|
470 |
- |
|
471 |
- close(ndesc); |
|
472 |
- |
|
473 |
- /* TODO: scan and unlink file */ |
|
474 |
- |
|
475 |
- /* unlink(tempfile); */ |
|
476 |
- free(tempfile); |
|
477 |
- } |
|
478 |
- |
|
479 |
- free(src); |
|
480 |
- free(dest); |
|
481 |
- |
|
482 |
- } else { |
|
483 |
- cli_dbgmsg("UPX sections not found\n"); |
|
484 |
- } |
|
485 |
- } |
|
486 |
- |
|
487 |
- /* to be continued ... */ |
|
488 |
- |
|
489 |
- free(section_hdr); |
|
490 |
- return CL_CLEAN; |
|
491 |
-} |
492 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,26 +0,0 @@ |
1 |
-/* |
|
2 |
- * Copyright (C) 2004 Tomasz Kojm <tkojm@clamav.net> |
|
3 |
- * |
|
4 |
- * This program is free software; you can redistribute it and/or modify |
|
5 |
- * it under the terms of the GNU General Public License as published by |
|
6 |
- * the Free Software Foundation; either version 2 of the License, or |
|
7 |
- * (at your option) any later version. |
|
8 |
- * |
|
9 |
- * This program is distributed in the hope that it will be useful, |
|
10 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
- * GNU General Public License for more details. |
|
13 |
- * |
|
14 |
- * You should have received a copy of the GNU General Public License |
|
15 |
- * along with this program; if not, write to the Free Software |
|
16 |
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
17 |
- */ |
|
18 |
- |
|
19 |
-#ifndef __PE_H |
|
20 |
-#define __PE_H |
|
21 |
- |
|
22 |
-#include "clamav.h" |
|
23 |
- |
|
24 |
-int cli_scanpe(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev); |
|
25 |
- |
|
26 |
-#endif |
... | ... |
@@ -30,8 +30,6 @@ |
30 | 30 |
#include <fcntl.h> |
31 | 31 |
#include <dirent.h> |
32 | 32 |
|
33 |
-#include <mspack.h> |
|
34 |
- |
|
35 | 33 |
#ifdef CL_THREAD_SAFE |
36 | 34 |
# include <pthread.h> |
37 | 35 |
pthread_mutex_t cli_scanrar_mutex = PTHREAD_MUTEX_INITIALIZER; |
... | ... |
@@ -75,10 +73,6 @@ struct cli_magic_s { |
75 | 75 |
#define MAGIC_BUFFER_SIZE 26 |
76 | 76 |
static const struct cli_magic_s cli_magic[] = { |
77 | 77 |
|
78 |
- /* Executables */ |
|
79 |
- |
|
80 |
-/* {0, "MZ", 2, "DOS/W32 executable", CL_DOSEXE},*/ |
|
81 |
- |
|
82 | 78 |
/* Archives */ |
83 | 79 |
|
84 | 80 |
{0, "Rar!", 4, "RAR", CL_RARFILE}, |
... | ... |
@@ -86,7 +80,6 @@ static const struct cli_magic_s cli_magic[] = { |
86 | 86 |
{0, "\037\213", 2, "GZip", CL_GZFILE}, |
87 | 87 |
{0, "BZh", 3, "BZip", CL_BZFILE}, |
88 | 88 |
{0, "SZDD", 4, "compress.exe'd", CL_MSCFILE}, |
89 |
- {0, "MSCF", 4, "MS CAB", CL_MSCABFILE}, |
|
90 | 89 |
|
91 | 90 |
/* Mail */ |
92 | 91 |
|
... | ... |
@@ -716,61 +709,6 @@ static int cli_scanmscomp(int desc, const char **virname, long int *scanned, con |
716 | 716 |
return ret; |
717 | 717 |
} |
718 | 718 |
|
719 |
-static int cli_scanmscab(int desc, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) |
|
720 |
-{ |
|
721 |
- struct mscab_decompressor *cabd = NULL; |
|
722 |
- struct mscabd_cabinet *base, *cab; |
|
723 |
- struct mscabd_file *file; |
|
724 |
- const char *tmpdir; |
|
725 |
- char *tempname; |
|
726 |
- int ret = CL_CLEAN; |
|
727 |
- |
|
728 |
- |
|
729 |
- cli_dbgmsg("in cli_scanmscab()\n"); |
|
730 |
- |
|
731 |
- if((cabd = mspack_create_cab_decompressor(NULL)) == NULL) { |
|
732 |
- cli_dbgmsg("Can't create libmspack CAB decompressor\n"); |
|
733 |
- return CL_EMSCAB; |
|
734 |
- } |
|
735 |
- |
|
736 |
- if((base = cabd->dsearch(cabd, desc)) == NULL) { |
|
737 |
- cli_dbgmsg("I/O error or no valid cabinets found\n"); |
|
738 |
- mspack_destroy_cab_decompressor(cabd); |
|
739 |
- return CL_EMSCAB; |
|
740 |
- } |
|
741 |
- |
|
742 |
- if((tmpdir = getenv("TMPDIR")) == NULL) |
|
743 |
-#ifdef P_tmpdir |
|
744 |
- tmpdir = P_tmpdir; |
|
745 |
-#else |
|
746 |
- tmpdir = "/tmp"; |
|
747 |
-#endif |
|
748 |
- |
|
749 |
- for(cab = base; cab; cab = cab->next) { |
|
750 |
- for(file = cab->files; file; file = file->next) { |
|
751 |
- tempname = cl_gentemp(tmpdir); |
|
752 |
- cli_dbgmsg("Extracting data to %s\n", tempname); |
|
753 |
- if(cabd->extract(cabd, file, tempname)) { |
|
754 |
- cli_dbgmsg("libmscab error code: %d\n", cabd->last_error(cabd)); |
|
755 |
- } else { |
|
756 |
- ret = cli_scanfile(tempname, virname, scanned, root, limits, options, reclev); |
|
757 |
- } |
|
758 |
- if(!cli_leavetemps_flag) |
|
759 |
- unlink(tempname); |
|
760 |
- free(tempname); |
|
761 |
- if(ret == CL_VIRUS) |
|
762 |
- break; |
|
763 |
- } |
|
764 |
- if(ret == CL_VIRUS) |
|
765 |
- break; |
|
766 |
- } |
|
767 |
- |
|
768 |
- cabd->close(cabd, base); |
|
769 |
- mspack_destroy_cab_decompressor(cabd); |
|
770 |
- |
|
771 |
- return ret; |
|
772 |
-} |
|
773 |
- |
|
774 | 719 |
static int cli_scandir(const char *dirname, const char **virname, long int *scanned, const struct cl_node *root, const struct cl_limits *limits, int options, int *reclev) |
775 | 720 |
{ |
776 | 721 |
DIR *dd; |
... | ... |
@@ -867,12 +805,6 @@ static int cli_vba_scandir(const char *dirname, const char **virname, long int * |
867 | 867 |
free(vba_project->dir); |
868 | 868 |
free(vba_project->offset); |
869 | 869 |
free(vba_project); |
870 |
- } else if ((fullname = ppt_vba_read(dirname))) { |
|
871 |
- if(cli_scandir(fullname, virname, scanned, root, limits, options, reclev) == CL_VIRUS) { |
|
872 |
- ret = CL_VIRUS; |
|
873 |
- } |
|
874 |
- cli_rmdirs(fullname); |
|
875 |
- free(fullname); |
|
876 | 870 |
} else if ((vba_project = (vba_project_t *) wm_dir_read(dirname))) { |
877 | 871 |
for (i = 0; i < vba_project->count; i++) { |
878 | 872 |
fullname = (char *) cli_malloc(strlen(vba_project->dir) + strlen(vba_project->name[i]) + 2); |
... | ... |
@@ -1066,11 +998,6 @@ static int cli_magic_scandesc(int desc, const char **virname, long int *scanned, |
1066 | 1066 |
type = cli_filetype(magic, bread); |
1067 | 1067 |
|
1068 | 1068 |
switch(type) { |
1069 |
- case CL_DOSEXE: |
|
1070 |
- /* temporarily the return code is ignored */ |
|
1071 |
- cli_scanpe(desc, virname, scanned, root, limits, options, reclev); |
|
1072 |
- break; |
|
1073 |
- |
|
1074 | 1069 |
case CL_RARFILE: |
1075 | 1070 |
if(!DISABLE_RAR && SCAN_ARCHIVE && !cli_scanrar_inuse) |
1076 | 1071 |
ret = cli_scanrar(desc, virname, scanned, root, limits, options, reclev); |
... | ... |
@@ -1098,11 +1025,6 @@ static int cli_magic_scandesc(int desc, const char **virname, long int *scanned, |
1098 | 1098 |
ret = cli_scanmscomp(desc, virname, scanned, root, limits, options, reclev); |
1099 | 1099 |
break; |
1100 | 1100 |
|
1101 |
- case CL_MSCABFILE: |
|
1102 |
- if(SCAN_ARCHIVE) |
|
1103 |
- ret = cli_scanmscab(desc, virname, scanned, root, limits, options, reclev); |
|
1104 |
- break; |
|
1105 |
- |
|
1106 | 1101 |
case CL_MAILFILE: |
1107 | 1102 |
if(SCAN_MAIL) |
1108 | 1103 |
ret = cli_scanmail(desc, virname, scanned, root, limits, options, reclev); |
... | ... |
@@ -22,7 +22,6 @@ |
22 | 22 |
|
23 | 23 |
typedef enum { |
24 | 24 |
CL_UNKNOWN_TYPE = 0, |
25 |
- CL_DOSEXE, |
|
26 | 25 |
CL_DATAFILE, |
27 | 26 |
CL_MAILFILE, |
28 | 27 |
CL_GZFILE, |
... | ... |
@@ -31,7 +30,6 @@ typedef enum { |
31 | 31 |
CL_RARFILE, |
32 | 32 |
CL_MSCFILE, |
33 | 33 |
CL_OLE2FILE, |
34 |
- CL_MSCABFILE |
|
35 | 34 |
} cli_file_t; |
36 | 35 |
|
37 | 36 |
cli_file_t cli_filetype(const char *buf, size_t buflen); |
38 | 37 |
deleted file mode 100644 |
... | ... |
@@ -1,263 +0,0 @@ |
1 |
-/* |
|
2 |
- * Copyright (C) 2004 aCaB <acab@clamav.net> |
|
3 |
- * |
|
4 |
- * This program is free software; you can redistribute it and/or modify |
|
5 |
- * it under the terms of the GNU General Public License as published by |
|
6 |
- * the Free Software Foundation; either version 2 of the License, or |
|
7 |
- * (at your option) any later version. |
|
8 |
- * |
|
9 |
- * This program is distributed in the hope that it will be useful, |
|
10 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
- * GNU General Public License for more details. |
|
13 |
- * |
|
14 |
- * You should have received a copy of the GNU General Public License |
|
15 |
- * along with this program; if not, write to the Free Software |
|
16 |
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
17 |
- */ |
|
18 |
- |
|
19 |
-/* |
|
20 |
-** upxdec.c |
|
21 |
-** |
|
22 |
-** 05/05/2k4 - 1st attempt |
|
23 |
-** 08/05/2k4 - Now works as a charm :D |
|
24 |
-** 09/05/2k4 - Moved code outta main(), got rid of globals for thread safety, added bound checking, minor cleaning |
|
25 |
-** 04/06/2k4 - Now we handle 2B, 2D and 2E :D |
|
26 |
-*/ |
|
27 |
- |
|
28 |
-/* |
|
29 |
-** This code unpacks a dumped UPX1 section to a file. |
|
30 |
-** It was written reversing the loader found on some Win32 UPX compressed trojans; while porting |
|
31 |
-** it to C i've kinda followed the asm flow so it will probably be a bit hard to read. |
|
32 |
-** This code DOES NOT revert the uncompressed section to its original state as no E8/E9 fixup and |
|
33 |
-** of cause no IAT rebuild are performed. |
|
34 |
-** |
|
35 |
-** The Win32 asm unpacker is really a little programming jewel, pretty damn rare in these days of |
|
36 |
-** bloatness. My gratitude to whoever wrote it. |
|
37 |
-*/ |
|
38 |
- |
|
39 |
- |
|
40 |
-#include <stdio.h> |
|
41 |
-#include <stdlib.h> |
|
42 |
-#include <sys/types.h> |
|
43 |
-#include <sys/stat.h> |
|
44 |
-#include <unistd.h> |
|
45 |
-#include <string.h> |
|
46 |
- |
|
47 |
-/* [doubleebx] */ |
|
48 |
- |
|
49 |
-static int doubleebx(char *src, int *myebx, int *scur, int ssize) |
|
50 |
-{ |
|
51 |
- int oldebx = *myebx; |
|
52 |
- |
|
53 |
- *myebx*=2; |
|
54 |
- if ( !(oldebx & 0x7fffffff)) { |
|
55 |
- if (*scur<0 || ssize-*scur<4) |
|
56 |
- return 0; |
|
57 |
- oldebx = *(int*)(src+*scur); |
|
58 |
- *myebx = oldebx*2+1; |
|
59 |
- *scur+=4; |
|
60 |
- } |
|
61 |
- return (oldebx>>31)&1; |
|
62 |
-} |
|
63 |
- |
|
64 |
-/* [inflate] */ |
|
65 |
- |
|
66 |
-int upx_inflate2b(char *src, int ssize, char *dst, int dsize) |
|
67 |
-{ |
|
68 |
- int backbytes, backsize, unp_offset = -1, i; |
|
69 |
- int myebx = 0; |
|
70 |
- int scur=0, dcur=0; |
|
71 |
- |
|
72 |
- while (1) { |
|
73 |
- while (doubleebx(src, &myebx, &scur, ssize)) { |
|
74 |
- if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize) |
|
75 |
- return -1; |
|
76 |
- dst[dcur++] = src[scur++]; |
|
77 |
- } |
|
78 |
- |
|
79 |
- backbytes = 1; |
|
80 |
- |
|
81 |
- while (1) { |
|
82 |
- backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize); |
|
83 |
- if (doubleebx(src, &myebx, &scur, ssize)) |
|
84 |
- break; |
|
85 |
- } |
|
86 |
- |
|
87 |
- backsize = 0; |
|
88 |
- backbytes-=3; |
|
89 |
- |
|
90 |
- if ( backbytes >= 0 ) { |
|
91 |
- |
|
92 |
- if (scur<0 || scur>=ssize) |
|
93 |
- return -1; |
|
94 |
- backbytes<<=8; |
|
95 |
- backbytes+=(unsigned char)(src[scur++]); |
|
96 |
- backbytes^=0xffffffff; |
|
97 |
- |
|
98 |
- if (!backbytes) |
|
99 |
- break; |
|
100 |
- unp_offset = backbytes; |
|
101 |
- } |
|
102 |
- |
|
103 |
- backsize = doubleebx(src, &myebx, &scur, ssize); |
|
104 |
- backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize); |
|
105 |
- if (!backsize) { |
|
106 |
- backsize++; |
|
107 |
- do { |
|
108 |
- backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize); |
|
109 |
- } while (!doubleebx(src, &myebx, &scur, ssize)); |
|
110 |
- backsize+=2; |
|
111 |
- } |
|
112 |
- |
|
113 |
- if ( (unsigned int)unp_offset < 0xfffff300 ) |
|
114 |
- backsize++; |
|
115 |
- |
|
116 |
- backsize++; |
|
117 |
- for (i = 0; i < backsize; i++) { |
|
118 |
- if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize) |
|
119 |
- return -1; |
|
120 |
- dst[dcur + i] = dst[dcur + unp_offset + i]; |
|
121 |
- } |
|
122 |
- dcur+=backsize; |
|
123 |
- } |
|
124 |
- return 0; |
|
125 |
-} |
|
126 |
- |
|
127 |
-int upx_inflate2d(char *src, int ssize, char *dst, int dsize) |
|
128 |
-{ |
|
129 |
- int backbytes, backsize, unp_offset = -1, i; |
|
130 |
- int myebx = 0; |
|
131 |
- int scur=0, dcur=0; |
|
132 |
- |
|
133 |
- while (1) { |
|
134 |
- while (doubleebx(src, &myebx, &scur, ssize)) { |
|
135 |
- if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize) |
|
136 |
- return -1; |
|
137 |
- dst[dcur++] = src[scur++]; |
|
138 |
- } |
|
139 |
- |
|
140 |
- backbytes = 1; |
|
141 |
- |
|
142 |
- while (1) { |
|
143 |
- backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize); |
|
144 |
- if (doubleebx(src, &myebx, &scur, ssize)) |
|
145 |
- break; |
|
146 |
- backbytes--; |
|
147 |
- backbytes=backbytes*2+doubleebx(src, &myebx, &scur, ssize); |
|
148 |
- } |
|
149 |
- |
|
150 |
- backsize = 0; |
|
151 |
- backbytes-=3; |
|
152 |
- |
|
153 |
- if ( backbytes >= 0 ) { |
|
154 |
- |
|
155 |
- if (scur<0 || scur>=ssize) |
|
156 |
- return -1; |
|
157 |
- backbytes<<=8; |
|
158 |
- backbytes+=(unsigned char)(src[scur++]); |
|
159 |
- backbytes^=0xffffffff; |
|
160 |
- |
|
161 |
- if (!backbytes) |
|
162 |
- break; |
|
163 |
- backsize = backbytes & 1; |
|
164 |
- backbytes>>=1; |
|
165 |
- unp_offset = backbytes; |
|
166 |
- } |
|
167 |
- else |
|
168 |
- backsize = doubleebx(src, &myebx, &scur, ssize); |
|
169 |
- |
|
170 |
- backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize); |
|
171 |
- if (!backsize) { |
|
172 |
- backsize++; |
|
173 |
- do { |
|
174 |
- backsize = backsize*2 + doubleebx(src, &myebx, &scur, ssize); |
|
175 |
- } while (!doubleebx(src, &myebx, &scur, ssize)); |
|
176 |
- backsize+=2; |
|
177 |
- } |
|
178 |
- |
|
179 |
- if ( (unsigned int)unp_offset < 0xfffffb00 ) |
|
180 |
- backsize++; |
|
181 |
- |
|
182 |
- backsize++; |
|
183 |
- for (i = 0; i < backsize; i++) { |
|
184 |
- if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize) |
|
185 |
- return -1; |
|
186 |
- dst[dcur + i] = dst[dcur + unp_offset + i]; |
|
187 |
- } |
|
188 |
- dcur+=backsize; |
|
189 |
- } |
|
190 |
- return 0; |
|
191 |
-} |
|
192 |
- |
|
193 |
-int upx_inflate2e(char *src, int ssize, char *dst, int dsize) |
|
194 |
-{ |
|
195 |
- int backbytes, backsize, unp_offset = -1, i; |
|
196 |
- int myebx = 0; |
|
197 |
- int scur=0, dcur=0; |
|
198 |
- |
|
199 |
- while (1) { |
|
200 |
- while (doubleebx(src, &myebx, &scur, ssize)) { |
|
201 |
- if (scur<0 || scur>=ssize || dcur<0 || dcur>=dsize) |
|
202 |
- return -1; |
|
203 |
- dst[dcur++] = src[scur++]; |
|
204 |
- } |
|
205 |
- |
|
206 |
- backbytes = 1; |
|
207 |
- |
|
208 |
- while (1) { |
|
209 |
- backbytes = backbytes*2+doubleebx(src, &myebx, &scur, ssize); |
|
210 |
- if (doubleebx(src, &myebx, &scur, ssize)) |
|
211 |
- break; |
|
212 |
- backbytes--; |
|
213 |
- backbytes=backbytes*2+doubleebx(src, &myebx, &scur, ssize); |
|
214 |
- } |
|
215 |
- |
|
216 |
- backsize = 0; |
|
217 |
- backbytes-=3; |
|
218 |
- |
|
219 |
- if ( backbytes >= 0 ) { |
|
220 |
- |
|
221 |
- if (scur<0 || scur>=ssize) |
|
222 |
- return -1; |
|
223 |
- backbytes<<=8; |
|
224 |
- backbytes+=(unsigned char)(src[scur++]); |
|
225 |
- backbytes^=0xffffffff; |
|
226 |
- |
|
227 |
- if (!backbytes) |
|
228 |
- break; |
|
229 |
- backsize = backbytes & 1; /* Using backsize to carry on the shifted out bit (UPX uses CF) */ |
|
230 |
- backbytes>>=1; |
|
231 |
- unp_offset = backbytes; |
|
232 |
- } |
|
233 |
- else |
|
234 |
- backsize = doubleebx(src, &myebx, &scur, ssize); /* Using backsize to carry on the doubleebx result (UPX uses CF) */ |
|
235 |
- |
|
236 |
- if (backsize) { /* i.e. IF ( last sar shifted out 1 bit || last doubleebx()==1 ) */ |
|
237 |
- backsize = doubleebx(src, &myebx, &scur, ssize); |
|
238 |
- } |
|
239 |
- else { |
|
240 |
- backsize = 1; |
|
241 |
- if (doubleebx(src, &myebx, &scur, ssize)) |
|
242 |
- backsize = 2 + doubleebx(src, &myebx, &scur, ssize); |
|
243 |
- else { |
|
244 |
- do { |
|
245 |
- backsize = backsize * 2 + doubleebx(src, &myebx, &scur, ssize); |
|
246 |
- } while (!doubleebx(src, &myebx, &scur, ssize)); |
|
247 |
- backsize+=2; |
|
248 |
- } |
|
249 |
- } |
|
250 |
- |
|
251 |
- if ( (unsigned int)unp_offset < 0xfffffb00 ) |
|
252 |
- backsize++; |
|
253 |
- |
|
254 |
- backsize+=2; |
|
255 |
- for (i = 0; i < backsize; i++) { |
|
256 |
- if (dcur+i<0 || dcur+i>=dsize || dcur+unp_offset+i<0 || dcur+unp_offset+i>=dsize) |
|
257 |
- return -1; |
|
258 |
- dst[dcur + i] = dst[dcur + unp_offset + i]; |
|
259 |
- } |
|
260 |
- dcur+=backsize; |
|
261 |
- } |
|
262 |
- return 0; |
|
263 |
-} |
264 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,26 +0,0 @@ |
1 |
-/* |
|
2 |
- * Copyright (C) 2004 aCaB <acab@clamav.net> |
|
3 |
- * |
|
4 |
- * This program is free software; you can redistribute it and/or modify |
|
5 |
- * it under the terms of the GNU General Public License as published by |
|
6 |
- * the Free Software Foundation; either version 2 of the License, or |
|
7 |
- * (at your option) any later version. |
|
8 |
- * |
|
9 |
- * This program is distributed in the hope that it will be useful, |
|
10 |
- * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
- * GNU General Public License for more details. |
|
13 |
- * |
|
14 |
- * You should have received a copy of the GNU General Public License |
|
15 |
- * along with this program; if not, write to the Free Software |
|
16 |
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
17 |
- */ |
|
18 |
- |
|
19 |
-#ifndef __UPX_H |
|
20 |
-#define __UPX_H |
|
21 |
- |
|
22 |
-int upx_inflate2b(char *, int , char *, int); |
|
23 |
-int upx_inflate2d(char *, int , char *, int); |
|
24 |
-int upx_inflate2e(char *, int , char *, int); |
|
25 |
- |
|
26 |
-#endif |