libmspack 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }