libmspack 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +5 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +4 -0
  6. data/README.md +75 -0
  7. data/Rakefile +22 -0
  8. data/UNLICENSE +24 -0
  9. data/ext/Rakefile +16 -0
  10. data/ext/i386-windows/libmspack.dll +0 -0
  11. data/ext/libmspack/AUTHORS +12 -0
  12. data/ext/libmspack/COPYING.LIB +504 -0
  13. data/ext/libmspack/ChangeLog +491 -0
  14. data/ext/libmspack/Makefile.am +100 -0
  15. data/ext/libmspack/NEWS +0 -0
  16. data/ext/libmspack/README +130 -0
  17. data/ext/libmspack/TODO +8 -0
  18. data/ext/libmspack/cleanup.sh +9 -0
  19. data/ext/libmspack/configure.ac +50 -0
  20. data/ext/libmspack/debian/changelog +6 -0
  21. data/ext/libmspack/debian/control +14 -0
  22. data/ext/libmspack/debian/rules +101 -0
  23. data/ext/libmspack/doc/Doxyfile.in +22 -0
  24. data/ext/libmspack/doc/Makefile.in +14 -0
  25. data/ext/libmspack/doc/szdd_kwaj_format.html +331 -0
  26. data/ext/libmspack/libmspack.pc.in +10 -0
  27. data/ext/libmspack/mspack/cab.h +127 -0
  28. data/ext/libmspack/mspack/cabc.c +24 -0
  29. data/ext/libmspack/mspack/cabd.c +1444 -0
  30. data/ext/libmspack/mspack/chm.h +122 -0
  31. data/ext/libmspack/mspack/chmc.c +24 -0
  32. data/ext/libmspack/mspack/chmd.c +1392 -0
  33. data/ext/libmspack/mspack/crc32.c +95 -0
  34. data/ext/libmspack/mspack/crc32.h +17 -0
  35. data/ext/libmspack/mspack/des.h +15 -0
  36. data/ext/libmspack/mspack/hlp.h +33 -0
  37. data/ext/libmspack/mspack/hlpc.c +24 -0
  38. data/ext/libmspack/mspack/hlpd.c +24 -0
  39. data/ext/libmspack/mspack/kwaj.h +118 -0
  40. data/ext/libmspack/mspack/kwajc.c +24 -0
  41. data/ext/libmspack/mspack/kwajd.c +561 -0
  42. data/ext/libmspack/mspack/lit.h +35 -0
  43. data/ext/libmspack/mspack/litc.c +24 -0
  44. data/ext/libmspack/mspack/litd.c +24 -0
  45. data/ext/libmspack/mspack/lzss.h +66 -0
  46. data/ext/libmspack/mspack/lzssd.c +93 -0
  47. data/ext/libmspack/mspack/lzx.h +221 -0
  48. data/ext/libmspack/mspack/lzxc.c +18 -0
  49. data/ext/libmspack/mspack/lzxd.c +895 -0
  50. data/ext/libmspack/mspack/mspack.def +28 -0
  51. data/ext/libmspack/mspack/mspack.h +2353 -0
  52. data/ext/libmspack/mspack/mszip.h +126 -0
  53. data/ext/libmspack/mspack/mszipc.c +18 -0
  54. data/ext/libmspack/mspack/mszipd.c +514 -0
  55. data/ext/libmspack/mspack/oab.h +60 -0
  56. data/ext/libmspack/mspack/oabc.c +24 -0
  57. data/ext/libmspack/mspack/oabd.c +408 -0
  58. data/ext/libmspack/mspack/qtm.h +128 -0
  59. data/ext/libmspack/mspack/qtmc.c +18 -0
  60. data/ext/libmspack/mspack/qtmd.c +489 -0
  61. data/ext/libmspack/mspack/readbits.h +207 -0
  62. data/ext/libmspack/mspack/readhuff.h +173 -0
  63. data/ext/libmspack/mspack/sha.h +15 -0
  64. data/ext/libmspack/mspack/system.c +239 -0
  65. data/ext/libmspack/mspack/system.h +124 -0
  66. data/ext/libmspack/mspack/szdd.h +39 -0
  67. data/ext/libmspack/mspack/szddc.c +24 -0
  68. data/ext/libmspack/mspack/szddd.c +247 -0
  69. data/ext/libmspack/rebuild.sh +8 -0
  70. data/ext/libmspack/test/cabd_c10 +19 -0
  71. data/ext/libmspack/test/cabd_compare +34 -0
  72. data/ext/libmspack/test/cabd_md5.c +161 -0
  73. data/ext/libmspack/test/cabd_memory.c +179 -0
  74. data/ext/libmspack/test/cabd_test.c +386 -0
  75. data/ext/libmspack/test/cabrip.c +81 -0
  76. data/ext/libmspack/test/chmd_compare +38 -0
  77. data/ext/libmspack/test/chmd_find.c +95 -0
  78. data/ext/libmspack/test/chmd_md5.c +67 -0
  79. data/ext/libmspack/test/chmd_order.c +144 -0
  80. data/ext/libmspack/test/chminfo.c +284 -0
  81. data/ext/libmspack/test/chmx.c +216 -0
  82. data/ext/libmspack/test/error.h +22 -0
  83. data/ext/libmspack/test/expand.c +79 -0
  84. data/ext/libmspack/test/md5.c +457 -0
  85. data/ext/libmspack/test/md5.h +165 -0
  86. data/ext/libmspack/test/md5_fh.h +123 -0
  87. data/ext/libmspack/test/msdecompile_md5 +24 -0
  88. data/ext/libmspack/test/msexpand_md5 +39 -0
  89. data/ext/libmspack/test/multifh.c +435 -0
  90. data/ext/libmspack/test/oabx.c +41 -0
  91. data/ext/libmspack/test/test_files/cabd/1.pl +84 -0
  92. data/ext/libmspack/test/test_files/cabd/2.pl +75 -0
  93. data/ext/libmspack/test/test_files/cabd/bad_folderindex.cab +0 -0
  94. data/ext/libmspack/test/test_files/cabd/bad_nofiles.cab +0 -0
  95. data/ext/libmspack/test/test_files/cabd/bad_nofolders.cab +0 -0
  96. data/ext/libmspack/test/test_files/cabd/bad_signature.cab +0 -0
  97. data/ext/libmspack/test/test_files/cabd/multi_basic_pt1.cab +0 -0
  98. data/ext/libmspack/test/test_files/cabd/multi_basic_pt2.cab +0 -0
  99. data/ext/libmspack/test/test_files/cabd/multi_basic_pt3.cab +0 -0
  100. data/ext/libmspack/test/test_files/cabd/multi_basic_pt4.cab +0 -0
  101. data/ext/libmspack/test/test_files/cabd/multi_basic_pt5.cab +0 -0
  102. data/ext/libmspack/test/test_files/cabd/normal_255c_filename.cab +0 -0
  103. data/ext/libmspack/test/test_files/cabd/normal_2files_1folder.cab +0 -0
  104. data/ext/libmspack/test/test_files/cabd/partial_nodata.cab +0 -0
  105. data/ext/libmspack/test/test_files/cabd/partial_nofiles.cab +0 -0
  106. data/ext/libmspack/test/test_files/cabd/partial_nofolder.cab +0 -0
  107. data/ext/libmspack/test/test_files/cabd/partial_shortextheader.cab +0 -0
  108. data/ext/libmspack/test/test_files/cabd/partial_shortfile1.cab +0 -0
  109. data/ext/libmspack/test/test_files/cabd/partial_shortfile2.cab +0 -0
  110. data/ext/libmspack/test/test_files/cabd/partial_shortfolder.cab +0 -0
  111. data/ext/libmspack/test/test_files/cabd/partial_shortheader.cab +0 -0
  112. data/ext/libmspack/test/test_files/cabd/partial_str_nofname.cab +0 -0
  113. data/ext/libmspack/test/test_files/cabd/partial_str_noninfo.cab +0 -0
  114. data/ext/libmspack/test/test_files/cabd/partial_str_nonname.cab +0 -0
  115. data/ext/libmspack/test/test_files/cabd/partial_str_nopinfo.cab +0 -0
  116. data/ext/libmspack/test/test_files/cabd/partial_str_nopname.cab +0 -0
  117. data/ext/libmspack/test/test_files/cabd/partial_str_shortfname.cab +0 -0
  118. data/ext/libmspack/test/test_files/cabd/partial_str_shortninfo.cab +0 -0
  119. data/ext/libmspack/test/test_files/cabd/partial_str_shortnname.cab +0 -0
  120. data/ext/libmspack/test/test_files/cabd/partial_str_shortpinfo.cab +0 -0
  121. data/ext/libmspack/test/test_files/cabd/partial_str_shortpname.cab +0 -0
  122. data/ext/libmspack/test/test_files/cabd/reserve_---.cab +0 -0
  123. data/ext/libmspack/test/test_files/cabd/reserve_--D.cab +0 -0
  124. data/ext/libmspack/test/test_files/cabd/reserve_-F-.cab +0 -0
  125. data/ext/libmspack/test/test_files/cabd/reserve_-FD.cab +0 -0
  126. data/ext/libmspack/test/test_files/cabd/reserve_H--.cab +0 -0
  127. data/ext/libmspack/test/test_files/cabd/reserve_H-D.cab +0 -0
  128. data/ext/libmspack/test/test_files/cabd/reserve_HF-.cab +0 -0
  129. data/ext/libmspack/test/test_files/cabd/reserve_HFD.cab +0 -0
  130. data/ext/libmspack/test/test_files/cabd/search_basic.cab +0 -0
  131. data/ext/libmspack/test/test_files/cabd/search_tricky1.cab +0 -0
  132. data/ext/libmspack/winbuild.sh +26 -0
  133. data/ext/x86_64-windows/libmspack.dll +0 -0
  134. data/lib/libmspack/constants.rb +9 -0
  135. data/lib/libmspack/exceptions.rb +12 -0
  136. data/lib/libmspack/mscab.rb +722 -0
  137. data/lib/libmspack/mschm.rb +301 -0
  138. data/lib/libmspack/mshlp.rb +15 -0
  139. data/lib/libmspack/mskwaj.rb +124 -0
  140. data/lib/libmspack/mslit.rb +18 -0
  141. data/lib/libmspack/msoab.rb +36 -0
  142. data/lib/libmspack/mspack.rb +208 -0
  143. data/lib/libmspack/msszdd.rb +81 -0
  144. data/lib/libmspack/system.rb +84 -0
  145. data/lib/libmspack/version.rb +4 -0
  146. data/lib/libmspack.rb +121 -0
  147. data/libmspack.gemspec +33 -0
  148. data/spec/libmspack_spec.rb +26 -0
  149. data/spec/spec_helper.rb +5 -0
  150. metadata +309 -0
@@ -0,0 +1,247 @@
1
+ /* This file is part of libmspack.
2
+ * (C) 2003-2010 Stuart Caie.
3
+ *
4
+ * SZDD is a format used in the MS-DOS commands COMPRESS.EXE and
5
+ * EXPAND.EXE. The compression method is attributed to Steven Zeck,
6
+ * however it's pretty much identical to LZSS.
7
+ *
8
+ * libmspack is free software; you can redistribute it and/or modify it under
9
+ * the terms of the GNU Lesser General Public License (LGPL) version 2.1
10
+ *
11
+ * For further details, see the file COPYING.LIB distributed with libmspack
12
+ */
13
+
14
+ /* SZDD decompression implementation */
15
+
16
+ #include <system.h>
17
+ #include <szdd.h>
18
+
19
+ /* prototypes */
20
+ static struct msszddd_header *szddd_open(
21
+ struct msszdd_decompressor *base, const char *filename);
22
+ static void szddd_close(
23
+ struct msszdd_decompressor *base, struct msszddd_header *hdr);
24
+ static int szddd_read_headers(
25
+ struct mspack_system *sys, struct mspack_file *fh,
26
+ struct msszddd_header *hdr);
27
+ static int szddd_extract(
28
+ struct msszdd_decompressor *base, struct msszddd_header *hdr,
29
+ const char *filename);
30
+ static int szddd_decompress(
31
+ struct msszdd_decompressor *base, const char *input, const char *output);
32
+ static int szddd_error(
33
+ struct msszdd_decompressor *base);
34
+
35
+ /***************************************
36
+ * MSPACK_CREATE_SZDD_DECOMPRESSOR
37
+ ***************************************
38
+ * constructor
39
+ */
40
+ struct msszdd_decompressor *
41
+ mspack_create_szdd_decompressor(struct mspack_system *sys)
42
+ {
43
+ struct msszdd_decompressor_p *self = NULL;
44
+
45
+ if (!sys) sys = mspack_default_system;
46
+ if (!mspack_valid_system(sys)) return NULL;
47
+
48
+ if ((self = (struct msszdd_decompressor_p *) sys->alloc(sys, sizeof(struct msszdd_decompressor_p)))) {
49
+ self->base.open = &szddd_open;
50
+ self->base.close = &szddd_close;
51
+ self->base.extract = &szddd_extract;
52
+ self->base.decompress = &szddd_decompress;
53
+ self->base.last_error = &szddd_error;
54
+ self->system = sys;
55
+ self->error = MSPACK_ERR_OK;
56
+ }
57
+ return (struct msszdd_decompressor *) self;
58
+ }
59
+
60
+ /***************************************
61
+ * MSPACK_DESTROY_SZDD_DECOMPRESSOR
62
+ ***************************************
63
+ * destructor
64
+ */
65
+ void mspack_destroy_szdd_decompressor(struct msszdd_decompressor *base)
66
+ {
67
+ struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base;
68
+ if (self) {
69
+ struct mspack_system *sys = self->system;
70
+ sys->free(self);
71
+ }
72
+ }
73
+
74
+ /***************************************
75
+ * SZDDD_OPEN
76
+ ***************************************
77
+ * opens an SZDD file without decompressing, reads header
78
+ */
79
+ static struct msszddd_header *szddd_open(struct msszdd_decompressor *base,
80
+ const char *filename)
81
+ {
82
+ struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base;
83
+ struct msszddd_header *hdr;
84
+ struct mspack_system *sys;
85
+ struct mspack_file *fh;
86
+
87
+ if (!self) return NULL;
88
+ sys = self->system;
89
+
90
+ fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ);
91
+ hdr = (struct msszddd_header *) sys->alloc(sys, sizeof(struct msszddd_header_p));
92
+ if (fh && hdr) {
93
+ ((struct msszddd_header_p *) hdr)->fh = fh;
94
+ self->error = szddd_read_headers(sys, fh, hdr);
95
+ }
96
+ else {
97
+ if (!fh) self->error = MSPACK_ERR_OPEN;
98
+ if (!hdr) self->error = MSPACK_ERR_NOMEMORY;
99
+ }
100
+
101
+ if (self->error) {
102
+ if (fh) sys->close(fh);
103
+ if (hdr) sys->free(hdr);
104
+ hdr = NULL;
105
+ }
106
+
107
+ return hdr;
108
+ }
109
+
110
+ /***************************************
111
+ * SZDDD_CLOSE
112
+ ***************************************
113
+ * closes an SZDD file
114
+ */
115
+ static void szddd_close(struct msszdd_decompressor *base,
116
+ struct msszddd_header *hdr)
117
+ {
118
+ struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base;
119
+ struct msszddd_header_p *hdr_p = (struct msszddd_header_p *) hdr;
120
+
121
+ if (!self || !self->system) return;
122
+
123
+ /* close the file handle associated */
124
+ self->system->close(hdr_p->fh);
125
+
126
+ /* free the memory associated */
127
+ self->system->free(hdr);
128
+
129
+ self->error = MSPACK_ERR_OK;
130
+ }
131
+
132
+ /***************************************
133
+ * SZDDD_READ_HEADERS
134
+ ***************************************
135
+ * reads the headers of an SZDD format file
136
+ */
137
+ static unsigned char szdd_signature_expand[8] = {
138
+ 0x53, 0x5A, 0x44, 0x44, 0x88, 0xF0, 0x27, 0x33
139
+ };
140
+ static unsigned char szdd_signature_qbasic[8] = {
141
+ 0x53, 0x5A, 0x20, 0x88, 0xF0, 0x27, 0x33, 0xD1
142
+ };
143
+
144
+ static int szddd_read_headers(struct mspack_system *sys,
145
+ struct mspack_file *fh,
146
+ struct msszddd_header *hdr)
147
+ {
148
+ unsigned char buf[8];
149
+
150
+ /* read and check signature */
151
+ if (sys->read(fh, buf, 8) != 8) return MSPACK_ERR_READ;
152
+
153
+ if ((mspack_memcmp(buf, szdd_signature_expand, 8) == 0)) {
154
+ /* common SZDD */
155
+ hdr->format = MSSZDD_FMT_NORMAL;
156
+
157
+ /* read the rest of the header */
158
+ if (sys->read(fh, buf, 6) != 6) return MSPACK_ERR_READ;
159
+ if (buf[0] != 0x41) return MSPACK_ERR_DATAFORMAT;
160
+ hdr->missing_char = buf[1];
161
+ hdr->length = EndGetI32(&buf[2]);
162
+ }
163
+ else if ((mspack_memcmp(buf, szdd_signature_qbasic, 8) == 0)) {
164
+ /* special QBasic SZDD */
165
+ hdr->format = MSSZDD_FMT_QBASIC;
166
+ if (sys->read(fh, buf, 4) != 4) return MSPACK_ERR_READ;
167
+ hdr->missing_char = '\0';
168
+ hdr->length = EndGetI32(buf);
169
+ }
170
+ else {
171
+ return MSPACK_ERR_SIGNATURE;
172
+ }
173
+ return MSPACK_ERR_OK;
174
+ }
175
+
176
+ /***************************************
177
+ * SZDDD_EXTRACT
178
+ ***************************************
179
+ * decompresses an SZDD file
180
+ */
181
+ static int szddd_extract(struct msszdd_decompressor *base,
182
+ struct msszddd_header *hdr, const char *filename)
183
+ {
184
+ struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base;
185
+ struct mspack_file *fh, *outfh;
186
+ struct mspack_system *sys;
187
+ off_t data_offset;
188
+
189
+ if (!self) return MSPACK_ERR_ARGS;
190
+ if (!hdr) return self->error = MSPACK_ERR_ARGS;
191
+ sys = self->system;
192
+
193
+ fh = ((struct msszddd_header_p *) hdr)->fh;
194
+
195
+ /* seek to the compressed data */
196
+ data_offset = (hdr->format == MSSZDD_FMT_NORMAL) ? 14 : 12;
197
+ if (sys->seek(fh, data_offset, MSPACK_SYS_SEEK_START)) {
198
+ return self->error = MSPACK_ERR_SEEK;
199
+ }
200
+
201
+ /* open file for output */
202
+ if (!(outfh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) {
203
+ return self->error = MSPACK_ERR_OPEN;
204
+ }
205
+
206
+ /* decompress the data */
207
+ self->error = lzss_decompress(sys, fh, outfh, SZDD_INPUT_SIZE,
208
+ hdr->format == MSSZDD_FMT_NORMAL
209
+ ? LZSS_MODE_EXPAND
210
+ : LZSS_MODE_QBASIC);
211
+
212
+ /* close output file */
213
+ sys->close(outfh);
214
+
215
+ return self->error;
216
+ }
217
+
218
+ /***************************************
219
+ * SZDDD_DECOMPRESS
220
+ ***************************************
221
+ * unpacks directly from input to output
222
+ */
223
+ static int szddd_decompress(struct msszdd_decompressor *base,
224
+ const char *input, const char *output)
225
+ {
226
+ struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base;
227
+ struct msszddd_header *hdr;
228
+ int error;
229
+
230
+ if (!self) return MSPACK_ERR_ARGS;
231
+
232
+ if (!(hdr = szddd_open(base, input))) return self->error;
233
+ error = szddd_extract(base, hdr, output);
234
+ szddd_close(base, hdr);
235
+ return self->error = error;
236
+ }
237
+
238
+ /***************************************
239
+ * SZDDD_ERROR
240
+ ***************************************
241
+ * returns the last error that occurred
242
+ */
243
+ static int szddd_error(struct msszdd_decompressor *base)
244
+ {
245
+ struct msszdd_decompressor_p *self = (struct msszdd_decompressor_p *) base;
246
+ return (self) ? self->error : MSPACK_ERR_ARGS;
247
+ }
@@ -0,0 +1,8 @@
1
+ #!/bin/sh
2
+ ./cleanup.sh
3
+ mkdir m4
4
+ autoreconf -i -W all
5
+ ./configure
6
+ make
7
+ make -C doc
8
+ make distcheck
@@ -0,0 +1,19 @@
1
+ #!/bin/sh
2
+ # Expand all cabs from the C10 collection; none are intentionally valid.
3
+ # See https://www.ee.oulu.fi/research/ouspg/PROTOS_Test-Suite_c10-archive
4
+
5
+ # I downloaded the .iso, unpacked cab_tar.bz2 and moved the cab files into
6
+ # 256 directories (00 to ff) under C10/unpacked. This makes it possible to
7
+ # invoke cabd_md5 just 256 times to test the entire collection.
8
+
9
+ for dir in `find C10/unpacked -maxdepth 1 -type d`
10
+ do
11
+ echo "testing $dir"
12
+ ./cabd_md5 $dir/*.cab >/dev/null 2>.err
13
+ result=$?
14
+ if [ $result -ne 0 ]; then
15
+ echo "FAIL $dir $result" >&2
16
+ cat .err >&2
17
+ fi
18
+ done
19
+ rm .err
@@ -0,0 +1,34 @@
1
+ #!/bin/sh
2
+ # Test if cabd_md5 expands cab files identically to Microsoft's EXPAND.EXE
3
+
4
+ [ -d .cache ] || mkdir .cache
5
+
6
+ for cab in "$@"
7
+ do
8
+ echo "test $cab"
9
+ cached=`echo $cab | sed -e 's/\//-/g' -e 's/^/.cache\//'`
10
+ if [ ! -s $cached ]; then
11
+ ./msexpand_md5 $cab >.orig.out 2>.orig.err
12
+ if [ -s .orig.err ]; then
13
+ echo "FAIL $cab: MS errors" >&2
14
+ cat .orig.err >&2
15
+ else
16
+ mv .orig.out $cached
17
+ fi
18
+ fi
19
+
20
+ ./cabd_md5 $cab >.test.out 2>.test.err
21
+ perl -pi -e 'if($.>1){s{\\}{/}g;s{ /}{ }}' .test.out
22
+ if [ -s .test.err ]; then
23
+ echo "FAIL $cab: errors" >&2
24
+ cat .test.err >&2
25
+ fi
26
+
27
+ if cmp $cached .test.out >/dev/null; then
28
+ echo "OK $cab"
29
+ else
30
+ echo "FAIL $cab: differences" >&2
31
+ diff -u $cached .test.out >&2
32
+ fi
33
+ done
34
+ rm -f .orig.out .orig.err .test.out .test.err
@@ -0,0 +1,161 @@
1
+ #ifdef HAVE_CONFIG_H
2
+ #include <config.h>
3
+ #endif
4
+
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <mspack.h>
9
+ #include <sys/stat.h>
10
+ #include <dirent.h>
11
+
12
+ #include <md5_fh.h>
13
+ #include <error.h>
14
+
15
+ /**
16
+ * Matches a cabinet's filename case-insensitively in the filesystem and
17
+ * returns the case-correct form.
18
+ *
19
+ * @param origcab if this is non-NULL, the pathname part of this filename
20
+ * will be extracted, and the search will be conducted in
21
+ * that directory.
22
+ * @param cabname the internal CAB filename to search for.
23
+ * @return a copy of the full, case-correct filename of the given cabinet
24
+ * filename, or NULL if the specified filename does not exist on disk.
25
+ */
26
+ static char *find_cabinet_file(char *origcab, char *cabname) {
27
+ struct dirent *entry;
28
+ struct stat st_buf;
29
+ int found = 0, len;
30
+ char *tail, *cab;
31
+ DIR *dir;
32
+
33
+ /* ensure we have a cabinet name at all */
34
+ if (!cabname || !cabname[0]) return NULL;
35
+
36
+ /* find if there's a directory path in the origcab */
37
+ tail = origcab ? strrchr(origcab, '/') : NULL;
38
+ len = (tail - origcab) + 1;
39
+
40
+ /* allocate memory for our copy */
41
+ if (!(cab = (char *) malloc((tail ? len : 2) + strlen(cabname) + 1))) return NULL;
42
+
43
+ /* add the directory path from the original cabinet name, or "." */
44
+ if (tail) memcpy(cab, origcab, (size_t) len);
45
+ else cab[0]='.', cab[1]='/', len=2;
46
+ cab[len] = '\0';
47
+
48
+ /* try accessing the cabinet with its current name (case-sensitive) */
49
+ strcpy(&cab[len], cabname);
50
+ if (stat(cab, &st_buf) == 0) {
51
+ found = 1;
52
+ }
53
+ else {
54
+ /* cabinet was not found, look for it in the current dir */
55
+ cab[len] = '\0';
56
+ if ((dir = opendir(cab))) {
57
+ while ((entry = readdir(dir))) {
58
+ if (strcasecmp(cabname, entry->d_name) == 0) {
59
+ strcat(cab, entry->d_name);
60
+ found = (stat(cab, &st_buf) == 0);
61
+ break;
62
+ }
63
+ }
64
+ closedir(dir);
65
+ }
66
+ }
67
+
68
+ if (!found || !S_ISREG(st_buf.st_mode)) {
69
+ /* cabinet not found, or not a regular file */
70
+ free(cab);
71
+ cab = NULL;
72
+ }
73
+
74
+ return cab;
75
+ }
76
+
77
+
78
+ int main(int argc, char *argv[]) {
79
+ struct mscab_decompressor *cabd;
80
+ struct mscabd_cabinet *cab, *c, *c2;
81
+ struct mscabd_file *file;
82
+ char *cabname, *newname;
83
+ int err;
84
+
85
+ setbuf(stdout, NULL);
86
+ setbuf(stderr, NULL);
87
+
88
+ /* if self-test reveals an error */
89
+ MSPACK_SYS_SELFTEST(err);
90
+ if (err) return 1;
91
+
92
+ if (!(cabd = mspack_create_cab_decompressor(&read_files_write_md5))) {
93
+ fprintf(stderr, "can't make decompressor\n");
94
+ return 1;
95
+ }
96
+
97
+ for (argv++; (cabname = *argv); argv++) {
98
+ printf("*** %s\n", cabname);
99
+
100
+ if (!(cab = cabd->open(cabd, cabname))) {
101
+ fprintf(stderr, "cab open error: %s\n", ERROR(cabd));
102
+ continue;
103
+ }
104
+
105
+ /* prepend any spanning cabinets */
106
+ for (c = cab; c && (c->flags & MSCAB_HDR_PREVCAB); c = c->prevcab) {
107
+ if (!(newname = find_cabinet_file(cabname, c->prevname))) {
108
+ fprintf(stderr, "%s: can't find \"%s\" to prepend\n",
109
+ cabname, c->prevname);
110
+ break;
111
+ }
112
+ if (!(c2 = cabd->open(cabd, newname))) {
113
+ fprintf(stderr, "%s: error opening \"%s\" for prepend: %s\n",
114
+ cabname, newname, ERROR(cabd));
115
+ break;
116
+ }
117
+ if (cabd->prepend(cabd, c, c2) != MSPACK_ERR_OK) {
118
+ fprintf(stderr, "%s: error prepending \"%s\": %s\n",
119
+ cabname, newname, ERROR(cabd));
120
+ break;
121
+ }
122
+ }
123
+
124
+ /* append any spanning cabinets */
125
+ for (c = cab; c && (c->flags & MSCAB_HDR_NEXTCAB); c = c->nextcab) {
126
+ if (!(newname = find_cabinet_file(cabname, c->nextname))) {
127
+ fprintf(stderr, "%s: can't find \"%s\" to append\n",
128
+ cabname, c->nextname);
129
+ break;
130
+ }
131
+ if (!(c2 = cabd->open(cabd, newname))) {
132
+ fprintf(stderr, "%s: error opening \"%s\" for append: %s\n",
133
+ cabname, newname, ERROR(cabd));
134
+ break;
135
+ }
136
+ if (cabd->append(cabd, c, c2) != MSPACK_ERR_OK) {
137
+ fprintf(stderr, "%s: error appending \"%s\": %s\n",
138
+ cabname, newname, ERROR(cabd));
139
+ break;
140
+ }
141
+ }
142
+
143
+ /* extract files */
144
+ for (file = cab->files; file; file = file->next ) {
145
+ if (cabd->extract(cabd, file, NULL) == MSPACK_ERR_OK) {
146
+ printf("%s %s\n", md5_string, file->filename);
147
+ }
148
+ else {
149
+ fprintf(stderr, "%s: error extracting \"%s\": %s\n",
150
+ cabname, file->filename, ERROR(cabd));
151
+ }
152
+ }
153
+
154
+ /* free all resources */
155
+ for (c2 = cab->prevcab; c2; c2 = c2->prevcab) free((void*)c2->filename);
156
+ for (c2 = cab->nextcab; c2; c2 = c2->nextcab) free((void*)c2->filename);
157
+ cabd->close(cabd, cab);
158
+ }
159
+ mspack_destroy_cab_decompressor(cabd);
160
+ return 0;
161
+ }
@@ -0,0 +1,179 @@
1
+ /* An implementation of the mspack_system interface using only memory */
2
+
3
+ #ifdef HAVE_CONFIG_H
4
+ #include <config.h>
5
+ #endif
6
+
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+ #include <string.h>
10
+ #include <mspack.h>
11
+
12
+ /* use a pointer to a mem_buf structure as "filenames" */
13
+ struct mem_buf {
14
+ void *data;
15
+ size_t length;
16
+ };
17
+
18
+ struct mem_file {
19
+ char *data;
20
+ size_t length, posn;
21
+ };
22
+
23
+ static void *mem_alloc(struct mspack_system *self, size_t bytes) {
24
+ /* put your memory allocator here */
25
+ return malloc(bytes);
26
+ }
27
+
28
+ static void mem_free(void *buffer) {
29
+ /* put your memory deallocator here */
30
+ free(buffer);
31
+ }
32
+
33
+ static void mem_copy(void *src, void *dest, size_t bytes) {
34
+ /* put your own memory copy routine here */
35
+ memcpy(dest, src, bytes);
36
+ }
37
+
38
+ static void mem_msg(struct mem_file *file, const char *format, ...) {
39
+ /* put your own printf-type routine here, or leave it empty */
40
+ }
41
+
42
+ static struct mem_file *mem_open(struct mspack_system *self,
43
+ struct mem_buf *fn, int mode)
44
+ {
45
+ struct mem_file *fh;
46
+ if (!fn || !fn->data || !fn->length) return NULL;
47
+ if ((fh = (struct mem_file *) mem_alloc(self, sizeof(struct mem_file)))) {
48
+ fh->data = (char *) fn->data;
49
+ fh->length = fn->length;
50
+ fh->posn = (mode == MSPACK_SYS_OPEN_APPEND) ? fn->length : 0;
51
+ }
52
+ return fh;
53
+ }
54
+
55
+ static void mem_close(struct mem_file *fh) {
56
+ if (fh) mem_free(fh);
57
+ }
58
+
59
+ static int mem_read(struct mem_file *fh, void *buffer, int bytes) {
60
+ int todo;
61
+ if (!fh || !buffer || bytes < 0) return -1;
62
+ todo = fh->length - fh->posn;
63
+ if (todo > bytes) todo = bytes;
64
+ if (todo > 0) mem_copy(&fh->data[fh->posn], buffer, (size_t) todo);
65
+ fh->posn += todo; return todo;
66
+ }
67
+
68
+ static int mem_write(struct mem_file *fh, void *buffer, int bytes) {
69
+ int todo;
70
+ if (!fh || !buffer || bytes < 0) return -1;
71
+ todo = fh->length - fh->posn;
72
+ if (todo > bytes) todo = bytes;
73
+ if (todo > 0) mem_copy(buffer, &fh->data[fh->posn], (size_t) todo);
74
+ fh->posn += todo; return todo;
75
+ }
76
+
77
+ static int mem_seek(struct mem_file *fh, off_t offset, int mode) {
78
+ if (!fh) return 1;
79
+ switch (mode) {
80
+ case MSPACK_SYS_SEEK_START: break;
81
+ case MSPACK_SYS_SEEK_CUR: offset += (off_t) fh->posn; break;
82
+ case MSPACK_SYS_SEEK_END: offset += (off_t) fh->length; break;
83
+ default: return 1;
84
+ }
85
+ if ((offset < 0) || (offset > (off_t) fh->length)) return 1;
86
+ fh->posn = (size_t) offset;
87
+ return 0;
88
+ }
89
+
90
+ static off_t mem_tell(struct mem_file *fh) {
91
+ return (fh) ? (off_t) fh->posn : -1;
92
+ }
93
+
94
+ static struct mspack_system mem_system = {
95
+ (struct mspack_file * (*)(struct mspack_system *, const char *, int)) &mem_open,
96
+ (void (*)(struct mspack_file *)) &mem_close,
97
+ (int (*)(struct mspack_file *, void *, int)) &mem_read,
98
+ (int (*)(struct mspack_file *, void *, int)) &mem_write,
99
+ (int (*)(struct mspack_file *, off_t, int)) &mem_seek,
100
+ (off_t (*)(struct mspack_file *)) &mem_tell,
101
+ (void (*)(struct mspack_file *, const char *, ...)) &mem_msg,
102
+ &mem_alloc,
103
+ &mem_free,
104
+ &mem_copy,
105
+ NULL
106
+ };
107
+
108
+ /* example of usage with mscab_decompressor */
109
+
110
+ /* a simple cabinet */
111
+ static unsigned char embedded_cab[] = {
112
+ 0x4D,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,
113
+ 0x00,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x02,0x00,
114
+ 0x00,0x00,0x22,0x06,0x00,0x00,0x5E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4D,
115
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x22,0xBA,0x59,0x20,0x00,
116
+ 0x68,0x65,0x6C,0x6C,0x6F,0x2E,0x63,0x00,0x4A,0x00,0x00,0x00,0x4D,0x00,0x00,
117
+ 0x00,0x00,0x00,0x6C,0x22,0xE7,0x59,0x20,0x00,0x77,0x65,0x6C,0x63,0x6F,0x6D,
118
+ 0x65,0x2E,0x63,0x00,0xBD,0x5A,0xA6,0x30,0x97,0x00,0x97,0x00,0x23,0x69,0x6E,
119
+ 0x63,0x6C,0x75,0x64,0x65,0x20,0x3C,0x73,0x74,0x64,0x69,0x6F,0x2E,0x68,0x3E,
120
+ 0x0D,0x0A,0x0D,0x0A,0x76,0x6F,0x69,0x64,0x20,0x6D,0x61,0x69,0x6E,0x28,0x76,
121
+ 0x6F,0x69,0x64,0x29,0x0D,0x0A,0x7B,0x0D,0x0A,0x20,0x20,0x20,0x20,0x70,0x72,
122
+ 0x69,0x6E,0x74,0x66,0x28,0x22,0x48,0x65,0x6C,0x6C,0x6F,0x2C,0x20,0x77,0x6F,
123
+ 0x72,0x6C,0x64,0x21,0x5C,0x6E,0x22,0x29,0x3B,0x0D,0x0A,0x7D,0x0D,0x0A,0x23,
124
+ 0x69,0x6E,0x63,0x6C,0x75,0x64,0x65,0x20,0x3C,0x73,0x74,0x64,0x69,0x6F,0x2E,
125
+ 0x68,0x3E,0x0D,0x0A,0x0D,0x0A,0x76,0x6F,0x69,0x64,0x20,0x6D,0x61,0x69,0x6E,
126
+ 0x28,0x76,0x6F,0x69,0x64,0x29,0x0D,0x0A,0x7B,0x0D,0x0A,0x20,0x20,0x20,0x20,
127
+ 0x70,0x72,0x69,0x6E,0x74,0x66,0x28,0x22,0x57,0x65,0x6C,0x63,0x6F,0x6D,0x65,
128
+ 0x21,0x5C,0x6E,0x22,0x29,0x3B,0x0D,0x0A,0x7D,0x0D,0x0A,0x0D,0x0A
129
+ };
130
+
131
+ int main() {
132
+ struct mscab_decompressor *cabd;
133
+ struct mscabd_cabinet *cab;
134
+ struct mscabd_file *file;
135
+ struct mem_buf source = { &embedded_cab[0], sizeof(embedded_cab) };
136
+ struct mem_buf output;
137
+ int err;
138
+
139
+ /* if self-test reveals an error */
140
+ MSPACK_SYS_SELFTEST(err);
141
+ if (err) return 1;
142
+
143
+ /* create a cab decompressor using our custom mspack_system interface */
144
+ if ((cabd = mspack_create_cab_decompressor(&mem_system))) {
145
+
146
+ /* open a cab file direct from memory */
147
+ if ((cab = cabd->open(cabd, (char *) &source))) {
148
+
149
+ /* for all files */
150
+ for (file = cab->files; file; file = file->next) {
151
+ /* fill out our "filename" (memory pointer and length) */
152
+ output.data = (char *) malloc(file->length);
153
+ output.length = file->length;
154
+
155
+ /* let cabd extract this file to our memory buffer */
156
+ if (output.data && cabd->extract(cabd, file, (char *) &output)) {
157
+ exit(1);
158
+ }
159
+
160
+ /* dump the memory buffer to stdout (for display purposes) */
161
+ printf("Filename: %s\nContents:\n", file->filename);
162
+ fwrite(output.data, 1, output.length, stdout);
163
+
164
+ /* free our buffer */
165
+ free(output.data);
166
+ }
167
+ cabd->close(cabd, cab);
168
+ }
169
+ else {
170
+ fprintf(stderr, "can't open cabinet (%d)\n", cabd->last_error(cabd));
171
+ }
172
+ mspack_destroy_cab_decompressor(cabd);
173
+ }
174
+ else {
175
+ fprintf(stderr, "can't make decompressor\n");
176
+ }
177
+ return 0;
178
+
179
+ }