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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/README.md +75 -0
- data/Rakefile +22 -0
- data/UNLICENSE +24 -0
- data/ext/Rakefile +16 -0
- data/ext/i386-windows/libmspack.dll +0 -0
- data/ext/libmspack/AUTHORS +12 -0
- data/ext/libmspack/COPYING.LIB +504 -0
- data/ext/libmspack/ChangeLog +491 -0
- data/ext/libmspack/Makefile.am +100 -0
- data/ext/libmspack/NEWS +0 -0
- data/ext/libmspack/README +130 -0
- data/ext/libmspack/TODO +8 -0
- data/ext/libmspack/cleanup.sh +9 -0
- data/ext/libmspack/configure.ac +50 -0
- data/ext/libmspack/debian/changelog +6 -0
- data/ext/libmspack/debian/control +14 -0
- data/ext/libmspack/debian/rules +101 -0
- data/ext/libmspack/doc/Doxyfile.in +22 -0
- data/ext/libmspack/doc/Makefile.in +14 -0
- data/ext/libmspack/doc/szdd_kwaj_format.html +331 -0
- data/ext/libmspack/libmspack.pc.in +10 -0
- data/ext/libmspack/mspack/cab.h +127 -0
- data/ext/libmspack/mspack/cabc.c +24 -0
- data/ext/libmspack/mspack/cabd.c +1444 -0
- data/ext/libmspack/mspack/chm.h +122 -0
- data/ext/libmspack/mspack/chmc.c +24 -0
- data/ext/libmspack/mspack/chmd.c +1392 -0
- data/ext/libmspack/mspack/crc32.c +95 -0
- data/ext/libmspack/mspack/crc32.h +17 -0
- data/ext/libmspack/mspack/des.h +15 -0
- data/ext/libmspack/mspack/hlp.h +33 -0
- data/ext/libmspack/mspack/hlpc.c +24 -0
- data/ext/libmspack/mspack/hlpd.c +24 -0
- data/ext/libmspack/mspack/kwaj.h +118 -0
- data/ext/libmspack/mspack/kwajc.c +24 -0
- data/ext/libmspack/mspack/kwajd.c +561 -0
- data/ext/libmspack/mspack/lit.h +35 -0
- data/ext/libmspack/mspack/litc.c +24 -0
- data/ext/libmspack/mspack/litd.c +24 -0
- data/ext/libmspack/mspack/lzss.h +66 -0
- data/ext/libmspack/mspack/lzssd.c +93 -0
- data/ext/libmspack/mspack/lzx.h +221 -0
- data/ext/libmspack/mspack/lzxc.c +18 -0
- data/ext/libmspack/mspack/lzxd.c +895 -0
- data/ext/libmspack/mspack/mspack.def +28 -0
- data/ext/libmspack/mspack/mspack.h +2353 -0
- data/ext/libmspack/mspack/mszip.h +126 -0
- data/ext/libmspack/mspack/mszipc.c +18 -0
- data/ext/libmspack/mspack/mszipd.c +514 -0
- data/ext/libmspack/mspack/oab.h +60 -0
- data/ext/libmspack/mspack/oabc.c +24 -0
- data/ext/libmspack/mspack/oabd.c +408 -0
- data/ext/libmspack/mspack/qtm.h +128 -0
- data/ext/libmspack/mspack/qtmc.c +18 -0
- data/ext/libmspack/mspack/qtmd.c +489 -0
- data/ext/libmspack/mspack/readbits.h +207 -0
- data/ext/libmspack/mspack/readhuff.h +173 -0
- data/ext/libmspack/mspack/sha.h +15 -0
- data/ext/libmspack/mspack/system.c +239 -0
- data/ext/libmspack/mspack/system.h +124 -0
- data/ext/libmspack/mspack/szdd.h +39 -0
- data/ext/libmspack/mspack/szddc.c +24 -0
- data/ext/libmspack/mspack/szddd.c +247 -0
- data/ext/libmspack/rebuild.sh +8 -0
- data/ext/libmspack/test/cabd_c10 +19 -0
- data/ext/libmspack/test/cabd_compare +34 -0
- data/ext/libmspack/test/cabd_md5.c +161 -0
- data/ext/libmspack/test/cabd_memory.c +179 -0
- data/ext/libmspack/test/cabd_test.c +386 -0
- data/ext/libmspack/test/cabrip.c +81 -0
- data/ext/libmspack/test/chmd_compare +38 -0
- data/ext/libmspack/test/chmd_find.c +95 -0
- data/ext/libmspack/test/chmd_md5.c +67 -0
- data/ext/libmspack/test/chmd_order.c +144 -0
- data/ext/libmspack/test/chminfo.c +284 -0
- data/ext/libmspack/test/chmx.c +216 -0
- data/ext/libmspack/test/error.h +22 -0
- data/ext/libmspack/test/expand.c +79 -0
- data/ext/libmspack/test/md5.c +457 -0
- data/ext/libmspack/test/md5.h +165 -0
- data/ext/libmspack/test/md5_fh.h +123 -0
- data/ext/libmspack/test/msdecompile_md5 +24 -0
- data/ext/libmspack/test/msexpand_md5 +39 -0
- data/ext/libmspack/test/multifh.c +435 -0
- data/ext/libmspack/test/oabx.c +41 -0
- data/ext/libmspack/test/test_files/cabd/1.pl +84 -0
- data/ext/libmspack/test/test_files/cabd/2.pl +75 -0
- data/ext/libmspack/test/test_files/cabd/bad_folderindex.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_nofiles.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_nofolders.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/bad_signature.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt1.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt2.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt3.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt4.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/multi_basic_pt5.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/normal_255c_filename.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/normal_2files_1folder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nodata.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nofiles.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_nofolder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortextheader.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfile1.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfile2.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortfolder.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_shortheader.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nofname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_noninfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nonname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nopinfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_nopname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortfname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortninfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortnname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortpinfo.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/partial_str_shortpname.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_---.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_--D.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_-F-.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_-FD.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_H--.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_H-D.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_HF-.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/reserve_HFD.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/search_basic.cab +0 -0
- data/ext/libmspack/test/test_files/cabd/search_tricky1.cab +0 -0
- data/ext/libmspack/winbuild.sh +26 -0
- data/ext/x86_64-windows/libmspack.dll +0 -0
- data/lib/libmspack/constants.rb +9 -0
- data/lib/libmspack/exceptions.rb +12 -0
- data/lib/libmspack/mscab.rb +722 -0
- data/lib/libmspack/mschm.rb +301 -0
- data/lib/libmspack/mshlp.rb +15 -0
- data/lib/libmspack/mskwaj.rb +124 -0
- data/lib/libmspack/mslit.rb +18 -0
- data/lib/libmspack/msoab.rb +36 -0
- data/lib/libmspack/mspack.rb +208 -0
- data/lib/libmspack/msszdd.rb +81 -0
- data/lib/libmspack/system.rb +84 -0
- data/lib/libmspack/version.rb +4 -0
- data/lib/libmspack.rb +121 -0
- data/libmspack.gemspec +33 -0
- data/spec/libmspack_spec.rb +26 -0
- data/spec/spec_helper.rb +5 -0
- 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,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
|
+
}
|