~ubuntu-branches/ubuntu/wily/clamav/wily-proposed

« back to all changes in this revision

Viewing changes to debian/patches/0005-libclamav-use-libmspack.patch

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman, Sebastian Andrzej Siewior, Andreas Cadhalpun, Scott Kitterman, Javier Fernández-Sanguino
  • Date: 2015-01-28 00:25:13 UTC
  • mfrom: (0.48.14 sid)
  • Revision ID: package-import@ubuntu.com-20150128002513-lil2oi74cooy4lzr
Tags: 0.98.6+dfsg-1
[ Sebastian Andrzej Siewior ]
* update "fix-ssize_t-size_t-off_t-printf-modifier", include of misc.h was
  missing but was pulled in via the systemd patch.
* Don't leak return codes from libmspack to clamav API. (Closes: #774686).

[ Andreas Cadhalpun ]
* Add patch to avoid emitting incremental progress messages when not
  outputting to a terminal. (Closes: #767350)
* Update lintian-overrides for unused-file-paragraph-in-dep5-copyright.
* clamav-base.postinst: always chown /var/log/clamav and /var/lib/clamav
  to clamav:clamav, not only on fresh installations. (Closes: #775400)
* Adapt the clamav-daemon and clamav-freshclam logrotate scripts,
  so that they correctly work under systemd.
* Move the PidFile variable from the clamd/freshclam configuration files
  to the init scripts. This makes the init scripts more robust against
  misconfiguration and avoids error messages with systemd. (Closes: #767353)
* debian/copyright: drop files from Files-Excluded only present in github
  tarballs
* Drop Workaround-a-bug-in-libc-on-Hurd.patch, because hurd got fixed.
  (see #752237)
* debian/rules: Remove useless --with-system-tommath --without-included-ltdl
  configure options.

[ Scott Kitterman ]
* Stop stripping llvm when repacking the tarball as the system llvm on some
  releases is too old to use
* New upstream bugfix release
  - Library shared object revisions.
  - Includes a patch from Sebastian Andrzej Siewior making ClamAV pid files
    compatible with systemd.
  - Fix a heap out of bounds condition with crafted Yoda's crypter files.
    This issue was discovered by Felix Groebert of the Google Security Team.
  - Fix a heap out of bounds condition with crafted mew packer files. This
    issue was discovered by Felix Groebert of the Google Security Team.
  - Fix a heap out of bounds condition with crafted upx packer files. This
    issue was discovered by Kevin Szkudlapski of Quarkslab.
  - Fix a heap out of bounds condition with crafted upack packer files. This
    issue was discovered by Sebastian Andrzej Siewior. CVE-2014-9328.
  - Compensate a crash due to incorrect compiler optimization when handling
    crafted petite packer files. This issue was discovered by Sebastian
    Andrzej Siewior.
* Update lintian override for embedded zlib to match new so version

[ Javier Fernández-Sanguino ]
* Updated Spanish Debconf template translation (Closes: #773563)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From 62a5659db47a36c0ad3826c534fea2b243265fb9 Mon Sep 17 00:00:00 2001
 
2
From: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
 
3
Date: Wed, 30 Jul 2014 08:35:16 +0200
 
4
Subject: libclamav: use libmspack
 
5
 
 
6
This patch provides support for upstream / external libmspack version
 
7
libmspack 0.4 (current). The old in-tree version of libmspack is removed
 
8
while no loner used.
 
9
 
 
10
BTS: #675558
 
11
clamav: https://bugzilla.clamav.net/show_bug.cgi?id=11062
 
12
 
 
13
Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
 
14
---
 
15
 configure.ac          |    3 +
 
16
 libclamav/Makefile.am |   11 +-
 
17
 libclamav/cab.c       |  684 -----------------
 
18
 libclamav/cab.h       |   81 --
 
19
 libclamav/chmunpack.h |  122 ---
 
20
 libclamav/libmspack.c |  525 +++++++++++++
 
21
 libclamav/libmspack.h |    7 +
 
22
 libclamav/mspack.c    | 2026 -------------------------------------------------
 
23
 libclamav/mspack.h    |  294 -------
 
24
 libclamav/scanners.c  |  146 +---
 
25
 10 files changed, 541 insertions(+), 3358 deletions(-)
 
26
 delete mode 100644 libclamav/cab.c
 
27
 delete mode 100644 libclamav/cab.h
 
28
 delete mode 100644 libclamav/chmunpack.h
 
29
 create mode 100644 libclamav/libmspack.c
 
30
 create mode 100644 libclamav/libmspack.h
 
31
 delete mode 100644 libclamav/mspack.c
 
32
 delete mode 100644 libclamav/mspack.h
 
33
 
 
34
diff --git a/configure.ac b/configure.ac
 
35
index 8e199cb..92a98ec 100644
 
36
--- a/configure.ac
 
37
+++ b/configure.ac
 
38
@@ -174,6 +174,9 @@ if test "$enable_llvm" = "yes" && test "$subdirfailed" != "no"; then
 
39
 fi
 
40
 AM_CONDITIONAL([ENABLE_LLVM],
 
41
               [test "$subdirfailed" != "yes" && test "$enable_llvm" != "no"])
 
42
+
 
43
+PKG_CHECK_MODULES([LIBMSPACK], [libmspack])
 
44
+
 
45
 no_recursion="yes";
 
46
 AC_OUTPUT([libclamav/Makefile])
 
47
 
 
48
diff --git a/libclamav/Makefile.am b/libclamav/Makefile.am
 
49
index 1aab51b..538e83d 100644
 
50
--- a/libclamav/Makefile.am
 
51
+++ b/libclamav/Makefile.am
 
52
@@ -147,6 +147,9 @@ if VERSIONSCRIPT
 
53
 libclamav_la_LDFLAGS += -Wl,@VERSIONSCRIPTFLAG@,@top_srcdir@/libclamav/libclamav.map
 
54
 endif
 
55
 
 
56
+libclamav_la_CFLAGS += $(LIBMSPACK_CFLAGS)
 
57
+libclamav_la_LDFLAGS += $(LIBMSPACK_LIBS)
 
58
+
 
59
 include_HEADERS = clamav.h
 
60
 
 
61
 libclamav_la_SOURCES = \
 
62
@@ -204,8 +207,8 @@ libclamav_la_SOURCES = \
 
63
        upx.h \
 
64
        htmlnorm.c \
 
65
        htmlnorm.h \
 
66
-       chmunpack.c \
 
67
-       chmunpack.h \
 
68
+       libmspack.c \
 
69
+       libmspack.h \
 
70
        rebuildpe.c \
 
71
        rebuildpe.h \
 
72
        petite.c \
 
73
@@ -283,10 +286,6 @@ libclamav_la_SOURCES = \
 
74
        regex_list.h \
 
75
        regex_suffix.c \
 
76
        regex_suffix.h \
 
77
-       mspack.c \
 
78
-       mspack.h \
 
79
-       cab.c \
 
80
-       cab.h \
 
81
        entconv.c \
 
82
        entconv.h \
 
83
        entitylist.h \
 
84
diff --git a/libclamav/cab.c b/libclamav/cab.c
 
85
deleted file mode 100644
 
86
index 6d2eade..0000000
 
87
--- a/libclamav/cab.c
 
88
+++ /dev/null
 
89
@@ -1,684 +0,0 @@
 
90
-/*
 
91
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
 
92
- *
 
93
- *  Authors: Tomasz Kojm
 
94
- *
 
95
- *  This program is free software; you can redistribute it and/or modify
 
96
- *  it under the terms of the GNU General Public License version 2 as
 
97
- *  published by the Free Software Foundation.
 
98
- *
 
99
- *  This program is distributed in the hope that it will be useful,
 
100
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
101
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
102
- *  GNU General Public License for more details.
 
103
- *
 
104
- *  You should have received a copy of the GNU General Public License
 
105
- *  along with this program; if not, write to the Free Software
 
106
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
107
- *  MA 02110-1301, USA.
 
108
- */
 
109
-
 
110
-#if HAVE_CONFIG_H
 
111
-#include "clamav-config.h"
 
112
-#endif
 
113
-
 
114
-#include <stdio.h>
 
115
-#include <string.h>
 
116
-#include <ctype.h>
 
117
-#include <sys/types.h>
 
118
-#include <sys/stat.h>
 
119
-#ifdef HAVE_UNISTD_H
 
120
-#include <unistd.h>
 
121
-#endif
 
122
-#include <fcntl.h>
 
123
-
 
124
-#include "clamav.h"
 
125
-#include "cltypes.h"
 
126
-#include "others.h"
 
127
-#include "mspack.h"
 
128
-#include "cab.h"
 
129
-
 
130
-#define EC32(x) cli_readint32(&x) /* Convert little endian to host */
 
131
-#define EC16(x) cli_readint16(&x)
 
132
-
 
133
-/* hard limits */
 
134
-#define CAB_FOLDER_LIMIT    5000
 
135
-#define CAB_FILE_LIMIT     5000
 
136
-
 
137
-/* Cabinet format data structures */
 
138
-
 
139
-struct cab_hdr {
 
140
-    uint32_t   signature;      /* file signature */
 
141
-    uint32_t   res1;           /* reserved */
 
142
-    uint32_t   cbCabinet;      /* size of cabinet file */
 
143
-    uint32_t   res2;           /* reserved */
 
144
-    uint32_t   coffFiles;      /* offset of the first file entry */
 
145
-    uint32_t   res3;           /* reserved */
 
146
-    uint8_t    versionMinor;   /* file format version, minor */
 
147
-    uint8_t    versionMajor;   /* file format version, major */
 
148
-    uint16_t   cFolders;       /* number of folder entries */
 
149
-    uint16_t   cFiles;         /* number of file entries */
 
150
-    uint16_t   flags;          /* option flags */
 
151
-    uint16_t   setID;          /* multiple cabs related */
 
152
-    uint16_t   iCabinet;       /* multiple cabs related */
 
153
-};
 
154
-
 
155
-struct cab_hdr_opt {
 
156
-    uint16_t   cbCFHeader;     /* size of reserved header area */
 
157
-    uint8_t    cbCFFolder;     /* size of reserved folder area */
 
158
-    uint8_t    cbCFData;       /* size of reserved block area */
 
159
-};
 
160
-
 
161
-struct cab_folder_hdr
 
162
-{
 
163
-    uint32_t   coffCabStart;   /* offset of the first data block */
 
164
-    uint16_t   cCFData;        /* number of data blocks */
 
165
-    uint16_t   typeCompress;   /* compression type */
 
166
-};
 
167
-
 
168
-struct cab_file_hdr
 
169
-{
 
170
-    uint32_t   cbFile;             /* uncompressed size */
 
171
-    uint32_t   uoffFolderStart;    /* uncompressed offset of file in folder */
 
172
-    uint16_t   iFolder;            /* folder index */
 
173
-    uint16_t   date;               /* date stamp */
 
174
-    uint16_t   time;               /* time stamp */
 
175
-    uint16_t   attribs;            /* attribute flags */
 
176
-};
 
177
-
 
178
-struct cab_block_hdr
 
179
-{
 
180
-    uint32_t   csum;       /* data block checksum */
 
181
-    uint16_t   cbData;     /* number of compressed bytes */
 
182
-    uint16_t   cbUncomp;   /* number of uncompressed bytes */
 
183
-};
 
184
-
 
185
-static char *cab_readstr(fmap_t *map, off_t *offset, int *ret)
 
186
-{
 
187
-       int i;
 
188
-       const char *str;
 
189
-       char *retstr;
 
190
-
 
191
-    if(!(str = fmap_need_offstr(map, *offset, 256))) {
 
192
-       *ret = CL_EFORMAT;
 
193
-       return NULL;
 
194
-    }
 
195
-
 
196
-    i = strlen(str) + 1;
 
197
-    if(i>=255) {
 
198
-       fmap_unneed_ptr(map, str, i);
 
199
-       *ret = CL_EFORMAT;
 
200
-       return NULL;
 
201
-    }
 
202
-
 
203
-    *offset += i;
 
204
-    if((retstr = cli_malloc(i)))
 
205
-       memcpy(retstr, str, i);
 
206
-    fmap_unneed_ptr(map, str, i);
 
207
-
 
208
-    if(!retstr) {
 
209
-       *ret = CL_EMEM;
 
210
-       return NULL;
 
211
-    }
 
212
-
 
213
-    *ret = CL_SUCCESS;
 
214
-    return retstr;
 
215
-}
 
216
-
 
217
-static int cab_chkname(char *name, int san)
 
218
-{
 
219
-       size_t i, len = strlen(name);
 
220
-
 
221
-
 
222
-    for(i = 0; i < len; i++) {
 
223
-       if(!san && (strchr("%/*?|\\\"+=<>;:\t ", name[i]) || !isascii(name[i]))) {
 
224
-           cli_dbgmsg("cab_chkname: File name contains disallowed characters\n");
 
225
-           return 1;
 
226
-       } else if(san && !isalnum(name[i])) {
 
227
-           name[i] = '*';
 
228
-       }
 
229
-    }
 
230
-
 
231
-    return 0;
 
232
-}
 
233
-
 
234
-void cab_free(struct cab_archive *cab)
 
235
-{
 
236
-       struct cab_folder *folder;
 
237
-       struct cab_file *file;
 
238
-
 
239
-
 
240
-    if(cab->state) {
 
241
-       if(cab->state->stream) {
 
242
-           switch(cab->state->cmethod & 0x000f) {
 
243
-               case 0x0001:
 
244
-                   mszip_free(cab->state->stream);
 
245
-                   break;
 
246
-               case 0x0002:
 
247
-                   qtm_free(cab->state->stream);
 
248
-                   break;
 
249
-               case 0x0003:
 
250
-                   lzx_free(cab->state->stream);
 
251
-           }
 
252
-       }
 
253
-       free(cab->state);
 
254
-    }
 
255
-
 
256
-    while(cab->folders) {
 
257
-       folder = cab->folders;
 
258
-       cab->folders = cab->folders->next;
 
259
-       free(folder);
 
260
-    }
 
261
-
 
262
-    while(cab->files) {
 
263
-       file = cab->files;
 
264
-       cab->files = cab->files->next;
 
265
-       free(file->name);
 
266
-       free(file);
 
267
-    }
 
268
-}
 
269
-
 
270
-int cab_open(fmap_t *map, off_t offset, struct cab_archive *cab)
 
271
-{
 
272
-       unsigned int i, folders = 0;
 
273
-       struct cab_file *file, *lfile = NULL;
 
274
-       struct cab_folder *folder, *lfolder = NULL;
 
275
-       const struct cab_hdr *hdr;
 
276
-       const struct cab_hdr_opt *hdr_opt;
 
277
-       uint16_t fidx;
 
278
-       uint32_t coffFiles;
 
279
-       char *pt;
 
280
-       int ret;
 
281
-       off_t resfold = 0, rsize, cur_offset = offset;
 
282
-
 
283
-    if(!(hdr=fmap_need_off_once(map, cur_offset, sizeof(*hdr)))) {
 
284
-       cli_dbgmsg("cab_open: Can't read cabinet header\n");
 
285
-       return CL_EFORMAT; /* most likely a corrupted file */
 
286
-    }
 
287
-    cur_offset += sizeof(*hdr);
 
288
-
 
289
-    if(EC32(hdr->signature) != 0x4643534d) {
 
290
-       cli_dbgmsg("cab_open: Incorrect CAB signature\n");
 
291
-       return CL_EFORMAT;
 
292
-    } else {
 
293
-       cli_dbgmsg("CAB: -------------- Cabinet file ----------------\n");
 
294
-    }
 
295
-
 
296
-    rsize = map->len;
 
297
-
 
298
-    memset(cab, 0, sizeof(struct cab_archive));
 
299
-
 
300
-    cab->length = EC32(hdr->cbCabinet);
 
301
-    cli_dbgmsg("CAB: Cabinet length: %u\n", cab->length);
 
302
-    if((off_t) cab->length > rsize) {
 
303
-       cli_dbgmsg("CAB: Truncating file size from %lu to %lu\n", (unsigned long int) cab->length, (unsigned long int) rsize);
 
304
-       cab->length = (uint32_t) rsize;
 
305
-    }
 
306
-
 
307
-    cab->nfolders = EC16(hdr->cFolders);
 
308
-    if(!cab->nfolders) {
 
309
-       cli_dbgmsg("cab_open: No folders in cabinet (fake cab?)\n");
 
310
-       return CL_EFORMAT;
 
311
-    } else {
 
312
-       cli_dbgmsg("CAB: Folders: %u\n", cab->nfolders);
 
313
-       if(cab->nfolders > CAB_FOLDER_LIMIT) {
 
314
-           cab->nfolders = CAB_FOLDER_LIMIT;
 
315
-           cli_dbgmsg("CAB: *** Number of folders limited to %u ***\n", cab->nfolders);
 
316
-       }
 
317
-    }
 
318
-
 
319
-    cab->nfiles = EC16(hdr->cFiles);
 
320
-    if(!cab->nfiles) {
 
321
-       cli_dbgmsg("cab_open: No files in cabinet (fake cab?)\n");
 
322
-       return CL_EFORMAT;
 
323
-    } else {
 
324
-       cli_dbgmsg("CAB: Files: %u\n", cab->nfiles);
 
325
-       if(cab->nfiles > CAB_FILE_LIMIT) {
 
326
-           cab->nfiles = CAB_FILE_LIMIT;
 
327
-           cli_dbgmsg("CAB: *** Number of files limited to %u ***\n", cab->nfiles);
 
328
-       }
 
329
-    }
 
330
-
 
331
-    cli_dbgmsg("CAB: File format version: %u.%u\n", hdr->versionMajor, hdr->versionMinor);
 
332
-
 
333
-    cab->flags = EC16(hdr->flags);
 
334
-    coffFiles = EC16(hdr->coffFiles);
 
335
-
 
336
-    if(cab->flags & 0x0004) {
 
337
-       if(!(hdr_opt = fmap_need_off_once(map, cur_offset, sizeof(*hdr_opt)))) {
 
338
-           cli_dbgmsg("cab_open: Can't read file header (fake cab?)\n");
 
339
-           return CL_EFORMAT; /* most likely a corrupted file */
 
340
-       }
 
341
-
 
342
-       cab->reshdr = EC16(hdr_opt->cbCFHeader);
 
343
-       resfold = hdr_opt->cbCFFolder;
 
344
-       cab->resdata = hdr_opt->cbCFData;
 
345
-
 
346
-       cur_offset += sizeof(*hdr_opt) + cab->reshdr;
 
347
-       if(cab->reshdr) {
 
348
-           if(cab->reshdr >= rsize) {
 
349
-               cli_dbgmsg("cab_open: Can't lseek to %u (fake cab?)\n", cab->reshdr);
 
350
-               return CL_EFORMAT; /* most likely a corrupted file */
 
351
-           }
 
352
-       }
 
353
-    }
 
354
-
 
355
-    if(cab->flags & 0x0001) { /* preceding cabinet */
 
356
-       /* name */
 
357
-       pt = cab_readstr(map, &cur_offset, &ret);
 
358
-       if(ret)
 
359
-           return ret;
 
360
-       if(cab_chkname(pt, 0))
 
361
-           cli_dbgmsg("CAB: Invalid name of preceding cabinet\n");
 
362
-       else
 
363
-           cli_dbgmsg("CAB: Preceding cabinet name: %s\n", pt);
 
364
-       free(pt);
 
365
-       /* info */
 
366
-       pt = cab_readstr(map, &cur_offset, &ret);
 
367
-       if(ret)
 
368
-           return ret;
 
369
-       if(cab_chkname(pt, 0))
 
370
-           cli_dbgmsg("CAB: Invalid info for preceding cabinet\n");
 
371
-       else
 
372
-           cli_dbgmsg("CAB: Preceding cabinet info: %s\n", pt);
 
373
-       free(pt);
 
374
-    }
 
375
-
 
376
-    if(cab->flags & 0x0002) { /* next cabinet */
 
377
-       /* name */
 
378
-       pt = cab_readstr(map, &cur_offset, &ret);
 
379
-       if(ret)
 
380
-           return ret;
 
381
-       if(cab_chkname(pt, 0))
 
382
-           cli_dbgmsg("CAB: Invalid name of next cabinet\n");
 
383
-       else
 
384
-           cli_dbgmsg("CAB: Next cabinet name: %s\n", pt);
 
385
-       free(pt);
 
386
-       /* info */
 
387
-       pt = cab_readstr(map, &cur_offset, &ret);
 
388
-       if(ret)
 
389
-           return ret;
 
390
-       if(cab_chkname(pt, 0))
 
391
-           cli_dbgmsg("CAB: Invalid info for next cabinet\n");
 
392
-       else
 
393
-           cli_dbgmsg("CAB: Next cabinet info: %s\n", pt);
 
394
-       free(pt);
 
395
-    }
 
396
-
 
397
-    /* folders */
 
398
-    for(i = 0; i < cab->nfolders; i++) {
 
399
-       const struct cab_folder_hdr *folder_hdr;
 
400
-
 
401
-       if(!(folder_hdr = fmap_need_off_once(map, cur_offset, sizeof(*folder_hdr)))) {
 
402
-           cli_dbgmsg("cab_open: Can't read header for folder %u\n", i);
 
403
-           break;
 
404
-       }
 
405
-
 
406
-       cur_offset += sizeof(*folder_hdr) + resfold;
 
407
-
 
408
-       if(EC32(folder_hdr->coffCabStart) + offset > rsize) {
 
409
-           cli_dbgmsg("CAB: Folder out of file\n");
 
410
-           continue;
 
411
-       }
 
412
-
 
413
-       if((EC16(folder_hdr->typeCompress) & 0x000f) > 3) {
 
414
-           cli_dbgmsg("CAB: Unknown compression method\n");
 
415
-           continue;
 
416
-       }
 
417
-
 
418
-       folder = (struct cab_folder *) cli_calloc(1, sizeof(struct cab_folder));
 
419
-       if(!folder) {
 
420
-           cli_errmsg("cab_open: Can't allocate memory for folder\n");
 
421
-           cab_free(cab);
 
422
-           return CL_EMEM;
 
423
-       }
 
424
-
 
425
-       folder->cab = (struct cab_archive *) cab;
 
426
-       folder->offset = (off_t) EC32(folder_hdr->coffCabStart) + offset;
 
427
-       folder->nblocks = EC16(folder_hdr->cCFData);
 
428
-       folder->cmethod = EC16(folder_hdr->typeCompress);
 
429
-
 
430
-       cli_dbgmsg("CAB: Folder record %u\n", i);
 
431
-       cli_dbgmsg("CAB: Folder offset: %u\n", (unsigned int) folder->offset);
 
432
-       cli_dbgmsg("CAB: Folder compression method: %d\n", folder->cmethod);
 
433
-
 
434
-       if(!lfolder)
 
435
-           cab->folders = folder;
 
436
-       else
 
437
-           lfolder->next = folder;
 
438
-
 
439
-       lfolder = folder;
 
440
-       folders++;
 
441
-    }
 
442
-    cli_dbgmsg("CAB: Recorded folders: %u\n", folders);
 
443
-
 
444
-    /* files */
 
445
-    if(cab->nfolders != folders) {
 
446
-       if(coffFiles >= rsize) {
 
447
-           cli_dbgmsg("cab_open: Can't lseek to hdr.coffFiles\n");
 
448
-           cab_free(cab);
 
449
-           return CL_EFORMAT;
 
450
-       }
 
451
-       cur_offset = coffFiles;
 
452
-    }
 
453
-    for(i = 0; i < cab->nfiles; i++) {
 
454
-       const struct cab_file_hdr *file_hdr;
 
455
-
 
456
-       if(!(file_hdr = fmap_need_off_once(map, cur_offset, sizeof(*file_hdr)))) {
 
457
-           cli_dbgmsg("cab_open: Can't read file %u header\n", i);
 
458
-           break;
 
459
-       }
 
460
-       cur_offset += sizeof(*file_hdr);
 
461
-
 
462
-       file = (struct cab_file *) cli_calloc(1, sizeof(struct cab_file));
 
463
-       if(!file) {
 
464
-           cli_errmsg("cab_open: Can't allocate memory for file\n");
 
465
-           cab_free(cab);
 
466
-           return CL_EMEM;
 
467
-       }
 
468
-
 
469
-       file->cab = cab;
 
470
-       cab->map = map;
 
471
-       file->offset = EC32(file_hdr->uoffFolderStart);
 
472
-       file->length = EC32(file_hdr->cbFile);
 
473
-       file->attribs = EC16(file_hdr->attribs);
 
474
-       fidx = EC16(file_hdr->iFolder);
 
475
-       file->error = CL_SUCCESS;
 
476
-
 
477
-       file->name = cab_readstr(map, &cur_offset, &ret);
 
478
-       if(ret) {
 
479
-           free(file);
 
480
-           continue;
 
481
-       }
 
482
-       cab_chkname(file->name, 1);
 
483
-
 
484
-       cli_dbgmsg("CAB: File record %u\n", i);
 
485
-       cli_dbgmsg("CAB: File name: %s\n", file->name);
 
486
-       cli_dbgmsg("CAB: File offset: %u\n", (unsigned int) file->offset);
 
487
-       cli_dbgmsg("CAB: File folder index: %u\n", fidx);
 
488
-       cli_dbgmsg("CAB: File attribs: 0x%x\n", file->attribs);
 
489
-       if(file->attribs & 0x01)
 
490
-           cli_dbgmsg("CAB:   * file is read-only\n");
 
491
-       if(file->attribs & 0x02)
 
492
-           cli_dbgmsg("CAB:   * file is hidden\n");
 
493
-       if(file->attribs & 0x04)
 
494
-           cli_dbgmsg("CAB:   * file is a system file\n");
 
495
-       if(file->attribs & 0x20)
 
496
-           cli_dbgmsg("CAB:   * file modified since last backup\n");
 
497
-       if(file->attribs & 0x40)
 
498
-           cli_dbgmsg("CAB:   * file to be run after extraction\n");
 
499
-       if(file->attribs & 0x80)
 
500
-           cli_dbgmsg("CAB:   * file name contains UTF\n");
 
501
-
 
502
-       /* folder index */
 
503
-       if(fidx < 0xfffd) {
 
504
-           if(fidx > cab->nfolders) {
 
505
-               cli_dbgmsg("cab_open: File %s is not associated with any folder\n", file->name);
 
506
-               free(file->name);
 
507
-               free(file);
 
508
-               continue;
 
509
-           }
 
510
-
 
511
-           file->folder = cab->folders;
 
512
-           while(file->folder && fidx--)
 
513
-               file->folder = file->folder->next;
 
514
-
 
515
-           if(!file->folder) {
 
516
-               cli_dbgmsg("cab_open: Folder not found for file %s\n", file->name);
 
517
-               free(file->name);
 
518
-               free(file);
 
519
-               continue;
 
520
-           }
 
521
-
 
522
-       } else {
 
523
-           cli_dbgmsg("CAB: File is split *skipping*\n");
 
524
-           free(file->name);
 
525
-           free(file);
 
526
-           continue;
 
527
-       }
 
528
-
 
529
-       if(!lfile)
 
530
-           cab->files = file;
 
531
-       else
 
532
-           lfile->next = file;
 
533
-
 
534
-       lfile = file;
 
535
-
 
536
-    }
 
537
-
 
538
-    return CL_SUCCESS;
 
539
-}
 
540
-
 
541
-static int cab_read_block(struct cab_file *file)
 
542
-{
 
543
-       const struct cab_block_hdr *block_hdr;
 
544
-       struct cab_state *state = file->cab->state;
 
545
-
 
546
-    if(!(block_hdr = fmap_need_off_once(file->cab->map, file->cab->cur_offset, sizeof(*block_hdr)))) {
 
547
-       cli_dbgmsg("cab_read_block: Can't read block header\n");
 
548
-       return CL_EFORMAT; /* most likely a corrupted file */
 
549
-    }
 
550
-
 
551
-    file->cab->cur_offset += sizeof(*block_hdr) + file->cab->resdata;
 
552
-    state->blklen = EC16(block_hdr->cbData);
 
553
-    state->outlen = EC16(block_hdr->cbUncomp);
 
554
-
 
555
-    if(fmap_readn(file->cab->map, state->block, file->cab->cur_offset, state->blklen) != state->blklen) {
 
556
-       cli_dbgmsg("cab_read_block: Can't read block data\n");
 
557
-       return CL_EFORMAT; /* most likely a corrupted file */
 
558
-    }
 
559
-
 
560
-    file->cab->cur_offset += state->blklen;
 
561
-    state->pt = state->end = state->block;
 
562
-    state->end += state->blklen;
 
563
-
 
564
-    return CL_SUCCESS;
 
565
-}
 
566
-
 
567
-static int cab_read(struct cab_file *file, unsigned char *buffer, int bytes)
 
568
-{
 
569
-       uint16_t todo, left;
 
570
-
 
571
-
 
572
-    if((file->cab->state->blknum > file->folder->nblocks) && !file->lread) {
 
573
-       file->error = CL_BREAK;
 
574
-       return -1;
 
575
-    }
 
576
-
 
577
-    todo = bytes;
 
578
-    while(todo > 0) {
 
579
-       left = file->cab->state->end - file->cab->state->pt;
 
580
-
 
581
-       if(left) {
 
582
-           if(left > todo)
 
583
-               left = todo;
 
584
-
 
585
-           memcpy(buffer, file->cab->state->pt, left);
 
586
-           file->cab->state->pt += left;
 
587
-           buffer += left;
 
588
-           todo -= left;
 
589
-
 
590
-       } else {
 
591
-           if(file->cab->state->blknum++ >= file->folder->nblocks)
 
592
-               break;
 
593
-
 
594
-           file->error = cab_read_block(file);
 
595
-           if(file->error)
 
596
-               return -1;
 
597
-
 
598
-           if((file->folder->cmethod & 0x000f) == 0x0002) /* Quantum hack */
 
599
-               *file->cab->state->end++ = 0xff;
 
600
-
 
601
-           if(file->cab->state->blknum >= file->folder->nblocks) {
 
602
-               if((file->folder->cmethod & 0x000f) == 0x0003) { /* LZX hack */
 
603
-                   lzx_set_output_length(file->cab->state->stream, (off_t) ((file->cab->state->blknum - 1) * 32768 + file->cab->state->outlen));
 
604
-               }
 
605
-           } else {
 
606
-               if(file->cab->state->outlen != 32768) {
 
607
-                   cli_dbgmsg("cab_read: WARNING: partial data block\n");
 
608
-               }
 
609
-           }
 
610
-       }
 
611
-    }
 
612
-
 
613
-    return file->lread = bytes - todo;
 
614
-}
 
615
-
 
616
-static int cab_unstore(struct cab_file *file)
 
617
-{
 
618
-       int todo, bread, bytes = file->length;
 
619
-       unsigned char buff[4096];
 
620
-
 
621
-
 
622
-    if(bytes < 0) {
 
623
-       cli_dbgmsg("cab_unstore: bytes < 0\n");
 
624
-       return CL_EFORMAT;
 
625
-    }
 
626
-
 
627
-    todo = MIN((unsigned int) bytes, file->max_size);
 
628
-
 
629
-    while(1) {
 
630
-
 
631
-       if((unsigned int) todo <= sizeof(buff))
 
632
-           bread = todo;
 
633
-       else
 
634
-           bread = sizeof(buff);
 
635
-
 
636
-       if((bread = cab_read(file, buff, bread)) == -1) {
 
637
-           cli_dbgmsg("cab_unstore: cab_read failed\n");
 
638
-           return file->error;
 
639
-       } else if(cli_writen(file->ofd, buff, bread) != bread) {
 
640
-           cli_warnmsg("cab_unstore: Can't write %d bytes to descriptor %d\n", bread, file->ofd);
 
641
-           return CL_EWRITE;
 
642
-       }
 
643
-
 
644
-       todo -= bread;
 
645
-
 
646
-       if(!bread || todo <= 0)
 
647
-           break;
 
648
-    }
 
649
-
 
650
-    return CL_SUCCESS;
 
651
-}
 
652
-
 
653
-#define CAB_CHGFOLDER                                                  \
 
654
-    if(!file->cab->actfol || (file->folder != file->cab->actfol)        \
 
655
-       || (file->cab->state && file->cab->state->cmethod != file->folder->cmethod)) { \
 
656
-       if(file->cab->state) {                                          \
 
657
-           if(file->cab->state->stream) {                              \
 
658
-               switch(file->cab->state->cmethod & 0x000f) {            \
 
659
-                   case 0x0001:                                        \
 
660
-                       mszip_free(file->cab->state->stream);           \
 
661
-                       break;                                          \
 
662
-                   case 0x0002:                                        \
 
663
-                       qtm_free(file->cab->state->stream);             \
 
664
-                       break;                                          \
 
665
-                   case 0x0003:                                        \
 
666
-                       lzx_free(file->cab->state->stream);             \
 
667
-               }                                                       \
 
668
-           }                                                           \
 
669
-           free(file->cab->state);                                     \
 
670
-           file->cab->state = NULL;                                    \
 
671
-       }                                                               \
 
672
-       file->cab->cur_offset = file->folder->offset;                   \
 
673
-       file->cab->state = (struct cab_state *) cli_calloc(1, sizeof(struct cab_state));        \
 
674
-       if(!file->cab->state) {                                         \
 
675
-           cli_errmsg("cab_extract: Can't allocate memory for internal state\n");              \
 
676
-           close(file->ofd);                                           \
 
677
-           return CL_EMEM;                                             \
 
678
-       }                                                               \
 
679
-       file->cab->state->cmethod = file->folder->cmethod;              \
 
680
-       switch(file->folder->cmethod & 0x000f) {                        \
 
681
-           case 0x0001:                                                \
 
682
-               file->cab->state->stream = (struct mszip_stream *) mszip_init(file->ofd, 4096, 1, file, &cab_read);     \
 
683
-               break;                                                  \
 
684
-           case 0x0002:                                                \
 
685
-               file->cab->state->stream = (struct qtm_stream *) qtm_init(file->ofd, (int) (file->folder->cmethod >> 8) & 0x1f, 4096, file, &cab_read);                                                                 \
 
686
-               break;                                                  \
 
687
-           case 0x0003:                                                \
 
688
-               file->cab->state->stream = (struct lzx_stream *) lzx_init(file->ofd, (int) (file->folder->cmethod >> 8) & 0x1f, 0, 4096, 0, file, &cab_read);                                                                   \
 
689
-       }                                                               \
 
690
-       if((file->folder->cmethod & 0x000f) && !file->cab->state->stream) { \
 
691
-           close(file->ofd);                                           \
 
692
-           return CL_EUNPACK;                                          \
 
693
-       }                                                               \
 
694
-       file->cab->actfol = file->folder;                               \
 
695
-    } else {                                                           \
 
696
-       if(file->cab->state && file->cab->state->stream) {              \
 
697
-           switch(file->cab->state->cmethod & 0x000f) {                \
 
698
-               case 0x0001:                                            \
 
699
-                   ((struct mszip_stream *) file->cab->state->stream)->ofd = file->ofd;        \
 
700
-                   break;                                              \
 
701
-               case 0x0002:                                            \
 
702
-                   ((struct qtm_stream *) file->cab->state->stream)->ofd = file->ofd;          \
 
703
-                   break;                                              \
 
704
-               case 0x0003:                                            \
 
705
-                   ((struct lzx_stream *) file->cab->state->stream)->ofd = file->ofd;          \
 
706
-                   break;                                              \
 
707
-           }                                                           \
 
708
-       }                                                               \
 
709
-    }
 
710
-
 
711
-
 
712
-int cab_extract(struct cab_file *file, const char *name)
 
713
-{
 
714
-       int ret;
 
715
-
 
716
-
 
717
-    if(!file || !name) {
 
718
-       cli_errmsg("cab_extract: !file || !name\n");
 
719
-       return CL_ENULLARG;
 
720
-    }
 
721
-
 
722
-    if(!file->folder) {
 
723
-       cli_errmsg("cab_extract: file->folder == NULL\n");
 
724
-       return CL_ENULLARG;
 
725
-    }
 
726
-
 
727
-    file->ofd = open(name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, S_IRWXU);
 
728
-    if(file->ofd == -1) {
 
729
-       cli_errmsg("cab_extract: Can't open file %s in write mode\n", name);
 
730
-       return CL_ECREAT;
 
731
-    }
 
732
-
 
733
-    switch(file->folder->cmethod & 0x000f) {
 
734
-       case 0x0000: /* STORE */
 
735
-           cli_dbgmsg("CAB: Compression method: STORED\n");
 
736
-           CAB_CHGFOLDER;
 
737
-           if(file->length > file->cab->length) {
 
738
-               cli_dbgmsg("cab_extract: Stored file larger than archive itself, trimming down\n");
 
739
-               file->length = file->cab->length;
 
740
-           }
 
741
-           ret = cab_unstore(file);
 
742
-           break;
 
743
-
 
744
-       case 0x0001: /* MSZIP */
 
745
-           cli_dbgmsg("CAB: Compression method: MSZIP\n");
 
746
-           CAB_CHGFOLDER;
 
747
-           ret = mszip_decompress(file->cab->state->stream, file->length);
 
748
-           break;
 
749
-
 
750
-       case 0x0002: /* QUANTUM */
 
751
-           cli_dbgmsg("CAB: Compression method: QUANTUM\n");
 
752
-           CAB_CHGFOLDER;
 
753
-           ret = qtm_decompress(file->cab->state->stream, file->length);
 
754
-           break;
 
755
-
 
756
-       case 0x0003: /* LZX */
 
757
-           cli_dbgmsg("CAB: Compression method: LZX\n");
 
758
-           CAB_CHGFOLDER;
 
759
-           ret = lzx_decompress(file->cab->state->stream, file->length);
 
760
-           break;
 
761
-
 
762
-       default:
 
763
-           cli_dbgmsg("CAB: Not supported compression method: 0x%x\n", file->folder->cmethod & 0x000f);
 
764
-           ret = CL_EFORMAT;
 
765
-    }
 
766
-
 
767
-    close(file->ofd);
 
768
-
 
769
-    if(ret == CL_BREAK)
 
770
-       ret = CL_SUCCESS;
 
771
-
 
772
-    return ret;
 
773
-}
 
774
diff --git a/libclamav/cab.h b/libclamav/cab.h
 
775
deleted file mode 100644
 
776
index 795900d..0000000
 
777
--- a/libclamav/cab.h
 
778
+++ /dev/null
 
779
@@ -1,81 +0,0 @@
 
780
-/*
 
781
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
 
782
- *
 
783
- *  Authors: Tomasz Kojm
 
784
- *
 
785
- *  This program is free software; you can redistribute it and/or modify
 
786
- *  it under the terms of the GNU General Public License version 2 as
 
787
- *  published by the Free Software Foundation.
 
788
- *
 
789
- *  This program is distributed in the hope that it will be useful,
 
790
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
791
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
792
- *  GNU General Public License for more details.
 
793
- *
 
794
- *  You should have received a copy of the GNU General Public License
 
795
- *  along with this program; if not, write to the Free Software
 
796
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
797
- *  MA 02110-1301, USA.
 
798
- */
 
799
-
 
800
-#ifndef __CAB_H
 
801
-#define __CAB_H
 
802
-
 
803
-#include <sys/types.h>
 
804
-#include "cltypes.h"
 
805
-#include "fmap.h"
 
806
-
 
807
-#define CAB_BLOCKMAX 65535
 
808
-#define CAB_INPUTMAX (CAB_BLOCKMAX + 6144)
 
809
-
 
810
-struct cab_archive {
 
811
-    struct cab_folder *folders, *actfol;
 
812
-    struct cab_file *files;
 
813
-    struct cab_state *state;
 
814
-    fmap_t *map;
 
815
-    off_t cur_offset;
 
816
-    uint32_t length;
 
817
-    uint16_t nfolders;
 
818
-    uint16_t nfiles;
 
819
-    uint16_t flags;
 
820
-    uint16_t reshdr;
 
821
-    uint8_t resdata;
 
822
-};
 
823
-
 
824
-struct cab_state {
 
825
-    unsigned char *pt, *end;
 
826
-    void *stream;
 
827
-    unsigned char block[CAB_INPUTMAX];
 
828
-    uint16_t blklen;
 
829
-    uint16_t outlen;
 
830
-    uint16_t blknum;
 
831
-    uint16_t cmethod;
 
832
-};
 
833
-
 
834
-struct cab_file {
 
835
-    off_t offset;
 
836
-    char *name;
 
837
-    uint32_t length;
 
838
-    int error;
 
839
-    int lread;
 
840
-    int ofd;
 
841
-    struct cab_folder *folder;
 
842
-    struct cab_file *next;
 
843
-    struct cab_archive *cab;
 
844
-    uint16_t attribs;
 
845
-    uint64_t max_size, written_size;
 
846
-};
 
847
-
 
848
-struct cab_folder {
 
849
-    struct cab_archive *cab;
 
850
-    off_t offset;
 
851
-    struct cab_folder *next;
 
852
-    uint16_t cmethod;
 
853
-    uint16_t nblocks;
 
854
-};
 
855
-
 
856
-int cab_open(fmap_t *map, off_t offset, struct cab_archive *cab);
 
857
-int cab_extract(struct cab_file *file, const char *name);
 
858
-void cab_free(struct cab_archive *cab);
 
859
-
 
860
-#endif
 
861
diff --git a/libclamav/chmunpack.h b/libclamav/chmunpack.h
 
862
deleted file mode 100644
 
863
index 7864386..0000000
 
864
--- a/libclamav/chmunpack.h
 
865
+++ /dev/null
 
866
@@ -1,122 +0,0 @@
 
867
-/*
 
868
- *  Extract component parts of MS CHM files
 
869
- *
 
870
- *  Copyright (C) 2007-2008 Sourcefire, Inc.
 
871
- *
 
872
- *  Authors: Trog
 
873
- *
 
874
- *  This program is free software; you can redistribute it and/or modify
 
875
- *  it under the terms of the GNU General Public License version 2 as
 
876
- *  published by the Free Software Foundation.
 
877
- *
 
878
- *  This program is distributed in the hope that it will be useful,
 
879
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
880
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
881
- *  GNU General Public License for more details.
 
882
- *
 
883
- *  You should have received a copy of the GNU General Public License
 
884
- *  along with this program; if not, write to the Free Software
 
885
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
886
- *  MA 02110-1301, USA.
 
887
- */
 
888
-
 
889
-#ifndef __CHM_UNPACK_H
 
890
-#define __CHM_UNPACK_H
 
891
-
 
892
-#if HAVE_CONFIG_H
 
893
-#include "clamav-config.h"
 
894
-#endif
 
895
-
 
896
-#include "cltypes.h"
 
897
-#include "others.h"
 
898
-#include "fmap.h"
 
899
-
 
900
-#ifndef HAVE_ATTRIB_PACKED
 
901
-#define __attribute__(x)
 
902
-#endif
 
903
-
 
904
-#ifdef HAVE_PRAGMA_PACK
 
905
-#pragma pack(1)
 
906
-#endif
 
907
-
 
908
-#ifdef HAVE_PRAGMA_PACK_HPPA
 
909
-#pragma pack 1
 
910
-#endif
 
911
-
 
912
-#define CHM_ITSF_MIN_LEN (0x60)
 
913
-typedef struct chm_itsf_header_tag
 
914
-{
 
915
-       unsigned char signature[4];
 
916
-       int32_t version __attribute__ ((packed));
 
917
-       int32_t header_len __attribute__ ((packed));
 
918
-       uint32_t unknown __attribute__ ((packed));
 
919
-       uint32_t last_modified __attribute__ ((packed));
 
920
-       uint32_t lang_id __attribute__ ((packed));
 
921
-       unsigned char dir_clsid[16];
 
922
-       unsigned char stream_clsid[16];
 
923
-       uint64_t sec0_offset __attribute__ ((packed));
 
924
-       uint64_t sec0_len __attribute__ ((packed));
 
925
-       uint64_t dir_offset __attribute__ ((packed));
 
926
-       uint64_t dir_len __attribute__ ((packed));
 
927
-       uint64_t data_offset __attribute__ ((packed));
 
928
-} chm_itsf_header_t;
 
929
-
 
930
-#define CHM_ITSP_LEN (0x54)
 
931
-typedef struct chm_itsp_header_tag
 
932
-{
 
933
-       unsigned char signature[4];
 
934
-       int32_t version __attribute__ ((packed));
 
935
-       int32_t header_len __attribute__ ((packed));
 
936
-       int32_t unknown1 __attribute__ ((packed));
 
937
-       uint32_t block_len __attribute__ ((packed));
 
938
-       int32_t blockidx_intvl __attribute__ ((packed));
 
939
-       int32_t index_depth __attribute__ ((packed));
 
940
-       int32_t index_root __attribute__ ((packed));
 
941
-       int32_t index_head __attribute__ ((packed));
 
942
-       int32_t index_tail __attribute__ ((packed));
 
943
-       int32_t unknown2 __attribute__ ((packed));
 
944
-       uint32_t num_blocks __attribute__ ((packed));
 
945
-       uint32_t lang_id __attribute__ ((packed));
 
946
-       unsigned char system_clsid[16];
 
947
-       unsigned char unknown4[16];
 
948
-} chm_itsp_header_t;
 
949
-
 
950
-#ifdef HAVE_PRAGMA_PACK
 
951
-#pragma pack()
 
952
-#endif
 
953
-
 
954
-#ifdef HAVE_PRAGMA_PACK_HPPA
 
955
-#pragma pack
 
956
-#endif
 
957
-
 
958
-typedef struct chm_sys_entry_tag
 
959
-{
 
960
-       uint64_t offset;
 
961
-       uint64_t length;
 
962
-} chm_sys_entry_t;
 
963
-
 
964
-typedef struct chm_metadata_tag {
 
965
-       uint64_t file_length;
 
966
-       uint64_t file_offset;
 
967
-       chm_sys_entry_t sys_control;
 
968
-       chm_sys_entry_t sys_content;
 
969
-       chm_sys_entry_t sys_reset;
 
970
-       off_t m_length;
 
971
-       chm_itsf_header_t itsf_hdr;
 
972
-       chm_itsp_header_t itsp_hdr;
 
973
-       int ufd;
 
974
-       int ofd;
 
975
-       uint32_t num_chunks;
 
976
-       off_t chunk_offset;
 
977
-       const char *chunk_data;
 
978
-       const char *chunk_current;
 
979
-       const char *chunk_end;
 
980
-       fmap_t *map;
 
981
-       uint16_t chunk_entries;
 
982
-} chm_metadata_t;
 
983
-
 
984
-int cli_chm_open(const char *dirname, chm_metadata_t *metadata, cli_ctx *ctx);
 
985
-int cli_chm_prepare_file(chm_metadata_t *metadata);
 
986
-int cli_chm_extract_file(char *dirname, chm_metadata_t *metadata, cli_ctx *ctx);
 
987
-void cli_chm_close(chm_metadata_t *metadata);
 
988
-#endif
 
989
diff --git a/libclamav/libmspack.c b/libclamav/libmspack.c
 
990
new file mode 100644
 
991
index 0000000..788ece0
 
992
--- /dev/null
 
993
+++ b/libclamav/libmspack.c
 
994
@@ -0,0 +1,525 @@
 
995
+/*
 
996
+ * Glue code for libmspack handling.
 
997
+ * Author: 웃 Sebastian Andrzej Siewior
 
998
+ * ✉ sebastian @ breakpoint ̣cc
 
999
+ */
 
1000
+
 
1001
+#include <stdio.h>
 
1002
+#include <stdlib.h>
 
1003
+#include <sys/stat.h>
 
1004
+#include <fcntl.h>
 
1005
+
 
1006
+#include <mspack.h>
 
1007
+
 
1008
+#include "clamav.h"
 
1009
+#include "fmap.h"
 
1010
+#include "scanners.h"
 
1011
+#include "others.h"
 
1012
+
 
1013
+enum mspack_type {
 
1014
+       FILETYPE_DUNNO,
 
1015
+       FILETYPE_FMAP,
 
1016
+       FILETYPE_FILENAME,
 
1017
+};
 
1018
+
 
1019
+struct mspack_name {
 
1020
+       fmap_t *fmap;
 
1021
+       off_t org;
 
1022
+};
 
1023
+
 
1024
+struct mspack_system_ex {
 
1025
+       struct mspack_system ops;
 
1026
+       off_t max_size;
 
1027
+};
 
1028
+
 
1029
+struct mspack_handle {
 
1030
+       enum mspack_type type;
 
1031
+
 
1032
+       fmap_t *fmap;
 
1033
+       off_t org;
 
1034
+       off_t offset;
 
1035
+
 
1036
+       FILE *f;
 
1037
+       off_t max_size;
 
1038
+};
 
1039
+
 
1040
+#define container_of(ptr, type, member) ({                     \
 
1041
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
 
1042
+       (type *)( (char *)__mptr - offsetof(type,member) );})
 
1043
+
 
1044
+#define min_t(type, x, y) ({           \
 
1045
+       type __min1 = (x);              \
 
1046
+       type __min2 = (y);              \
 
1047
+       __min1 < __min2 ? __min1: __min2; })
 
1048
+
 
1049
+static struct mspack_file *mspack_fmap_open(struct mspack_system *self,
 
1050
+               const char *filename, int mode)
 
1051
+{
 
1052
+       struct mspack_name *mspack_name;
 
1053
+       struct mspack_handle *mspack_handle;
 
1054
+       struct mspack_system_ex *self_ex;
 
1055
+       const char *fmode;
 
1056
+
 
1057
+       if (!filename) {
 
1058
+               cli_dbgmsg("%s() failed at %d\n", __func__, __LINE__);
 
1059
+               return NULL;
 
1060
+       }
 
1061
+       mspack_handle = malloc(sizeof(*mspack_handle));
 
1062
+       if (!mspack_handle) {
 
1063
+               cli_dbgmsg("%s() failed at %d\n", __func__, __LINE__);
 
1064
+               return NULL;
 
1065
+       }
 
1066
+       switch (mode) {
 
1067
+       case MSPACK_SYS_OPEN_READ:
 
1068
+               mspack_handle->type = FILETYPE_FMAP;
 
1069
+
 
1070
+               mspack_name = (struct mspack_name *)filename;
 
1071
+               mspack_handle->fmap = mspack_name->fmap;
 
1072
+               mspack_handle->org = mspack_name->org;
 
1073
+               mspack_handle->offset = 0;
 
1074
+
 
1075
+               return (struct mspack_file *)mspack_handle;
 
1076
+
 
1077
+       case MSPACK_SYS_OPEN_WRITE:
 
1078
+               fmode = "wb";
 
1079
+               break;
 
1080
+       case MSPACK_SYS_OPEN_UPDATE:
 
1081
+               fmode = "r+b";
 
1082
+               break;
 
1083
+       case MSPACK_SYS_OPEN_APPEND:
 
1084
+               fmode = "ab";
 
1085
+               break;
 
1086
+       default:
 
1087
+               cli_dbgmsg("%s() wrong mode\n", __func__);
 
1088
+               goto out_err;
 
1089
+       }
 
1090
+
 
1091
+       mspack_handle->type = FILETYPE_FILENAME;
 
1092
+
 
1093
+       mspack_handle->f = fopen(filename, fmode);
 
1094
+       if (!mspack_handle->f) {
 
1095
+               cli_dbgmsg("%s() failed %d\n", __func__, __LINE__);
 
1096
+               goto out_err;
 
1097
+       }
 
1098
+       self_ex = container_of(self, struct mspack_system_ex, ops);
 
1099
+       mspack_handle->max_size = self_ex->max_size;
 
1100
+       return (struct mspack_file *)mspack_handle;
 
1101
+
 
1102
+out_err:
 
1103
+       free(mspack_handle);
 
1104
+       return NULL;
 
1105
+}
 
1106
+
 
1107
+static void mspack_fmap_close(struct mspack_file *file)
 
1108
+{
 
1109
+       struct mspack_handle *mspack_handle = (struct mspack_handle *)file;
 
1110
+
 
1111
+       if (!mspack_handle)
 
1112
+               return;
 
1113
+
 
1114
+       if (mspack_handle->type == FILETYPE_FILENAME)
 
1115
+               fclose(mspack_handle->f);
 
1116
+       free(mspack_handle);
 
1117
+}
 
1118
+
 
1119
+static int mspack_fmap_read(struct mspack_file *file, void *buffer, int bytes)
 
1120
+{
 
1121
+       struct mspack_handle *mspack_handle = (struct mspack_handle *)file;
 
1122
+       off_t offset;
 
1123
+       size_t count;
 
1124
+       int ret;
 
1125
+
 
1126
+       if (bytes < 0) {
 
1127
+               cli_dbgmsg("%s() %d\n", __func__, __LINE__);
 
1128
+               return -1;
 
1129
+       }
 
1130
+       if (!mspack_handle) {
 
1131
+               cli_dbgmsg("%s() %d\n", __func__, __LINE__);
 
1132
+               return -1;
 
1133
+       }
 
1134
+
 
1135
+       if (mspack_handle->type == FILETYPE_FMAP) {
 
1136
+               offset = mspack_handle->offset + mspack_handle->org;
 
1137
+
 
1138
+               ret = fmap_readn(mspack_handle->fmap, buffer, offset, bytes);
 
1139
+               if (ret != bytes) {
 
1140
+                       cli_dbgmsg("%s() %d %d, %d\n", __func__, __LINE__, bytes, ret);
 
1141
+                       return ret;
 
1142
+               }
 
1143
+
 
1144
+               mspack_handle->offset += bytes;
 
1145
+               return bytes;
 
1146
+       }
 
1147
+       count = fread(buffer, bytes, 1, mspack_handle->f);
 
1148
+       if (count < 1) {
 
1149
+               cli_dbgmsg("%s() %d %d, %zd\n", __func__, __LINE__, bytes, count);
 
1150
+               return -1;
 
1151
+       }
 
1152
+       return bytes;
 
1153
+}
 
1154
+
 
1155
+static int mspack_fmap_write(struct mspack_file *file, void *buffer, int bytes)
 
1156
+{
 
1157
+       struct mspack_handle *mspack_handle = (struct mspack_handle *)file;
 
1158
+       size_t count;
 
1159
+       off_t max_size;
 
1160
+
 
1161
+       if (bytes < 0 || !mspack_handle) {
 
1162
+               cli_dbgmsg("%s() err %d\n", __func__, __LINE__);
 
1163
+               return -1;
 
1164
+       }
 
1165
+
 
1166
+       if (mspack_handle->type == FILETYPE_FMAP) {
 
1167
+               cli_dbgmsg("%s() err %d\n", __func__, __LINE__);
 
1168
+               return -1;
 
1169
+       }
 
1170
+
 
1171
+       if (!bytes)
 
1172
+               return 0;
 
1173
+
 
1174
+       max_size = mspack_handle->max_size;
 
1175
+       if (!max_size)
 
1176
+               return bytes;
 
1177
+
 
1178
+       max_size = min_t(off_t, max_size, bytes);
 
1179
+       mspack_handle->max_size -= max_size;
 
1180
+
 
1181
+       count = fwrite(buffer, max_size, 1, mspack_handle->f);
 
1182
+       if (count < 1) {
 
1183
+               cli_dbgmsg("%s() err %m <%zd %d>\n", __func__, count, bytes);
 
1184
+               return -1;
 
1185
+       }
 
1186
+
 
1187
+       return bytes;
 
1188
+}
 
1189
+
 
1190
+static int mspack_fmap_seek(struct mspack_file *file, off_t offset, int mode)
 
1191
+{
 
1192
+       struct mspack_handle *mspack_handle = (struct mspack_handle *)file;
 
1193
+
 
1194
+       if (!mspack_handle) {
 
1195
+               cli_dbgmsg("%s() err %d\n", __func__, __LINE__);
 
1196
+               return -1;
 
1197
+       }
 
1198
+
 
1199
+       if (mspack_handle->type == FILETYPE_FMAP) {
 
1200
+               off_t new_pos;
 
1201
+
 
1202
+               switch (mode) {
 
1203
+               case MSPACK_SYS_SEEK_START:
 
1204
+                       new_pos = offset;
 
1205
+                       break;
 
1206
+               case MSPACK_SYS_SEEK_CUR:
 
1207
+                       new_pos = mspack_handle->offset + offset;
 
1208
+                       break;
 
1209
+               case MSPACK_SYS_SEEK_END:
 
1210
+                       new_pos = mspack_handle->fmap->len + offset;
 
1211
+                       break;
 
1212
+               default:
 
1213
+                       cli_dbgmsg("%s() err %d\n", __func__, __LINE__);
 
1214
+                       return -1;
 
1215
+               }
 
1216
+               if (new_pos < 0 || new_pos > mspack_handle->fmap->len) {
 
1217
+                       cli_dbgmsg("%s() err %d\n", __func__, __LINE__);
 
1218
+                       return -1;
 
1219
+               }
 
1220
+
 
1221
+               mspack_handle->offset = new_pos;
 
1222
+               return 0;
 
1223
+       }
 
1224
+
 
1225
+       switch (mode) {
 
1226
+       case MSPACK_SYS_SEEK_START:
 
1227
+               mode = SEEK_SET;
 
1228
+               break;
 
1229
+       case MSPACK_SYS_SEEK_CUR:
 
1230
+               mode = SEEK_CUR;
 
1231
+               break;
 
1232
+       case MSPACK_SYS_SEEK_END:
 
1233
+               mode = SEEK_END;
 
1234
+               break;
 
1235
+       default:
 
1236
+               cli_dbgmsg("%s() err %d\n", __func__, __LINE__);
 
1237
+               return -1;
 
1238
+       }
 
1239
+
 
1240
+       return fseeko(mspack_handle->f, offset, mode);
 
1241
+}
 
1242
+
 
1243
+static off_t mspack_fmap_tell(struct mspack_file *file)
 
1244
+{
 
1245
+       struct mspack_handle *mspack_handle = (struct mspack_handle *)file;
 
1246
+
 
1247
+       if (!mspack_handle)
 
1248
+               return -1;
 
1249
+
 
1250
+       if (mspack_handle->type == FILETYPE_FMAP)
 
1251
+               return mspack_handle->offset;
 
1252
+
 
1253
+       return ftello(mspack_handle->f);
 
1254
+}
 
1255
+
 
1256
+static void mspack_fmap_message(struct mspack_file *file, const char *fmt, ...)
 
1257
+{
 
1258
+       cli_dbgmsg("%s() %s\n", __func__, fmt);
 
1259
+}
 
1260
+static void *mspack_fmap_alloc(struct mspack_system *self, size_t num)
 
1261
+{
 
1262
+       return malloc(num);
 
1263
+}
 
1264
+
 
1265
+static void mspack_fmap_free(void *mem)
 
1266
+{
 
1267
+       free(mem);
 
1268
+}
 
1269
+
 
1270
+static void mspack_fmap_copy(void *src, void *dst, size_t num)
 
1271
+{
 
1272
+       memcpy(dst, src, num);
 
1273
+}
 
1274
+
 
1275
+static struct mspack_system mspack_sys_fmap_ops = {
 
1276
+       .open = mspack_fmap_open,
 
1277
+       .close = mspack_fmap_close,
 
1278
+       .read = mspack_fmap_read,
 
1279
+       .write = mspack_fmap_write,
 
1280
+       .seek = mspack_fmap_seek,
 
1281
+       .tell = mspack_fmap_tell,
 
1282
+       .message = mspack_fmap_message,
 
1283
+       .alloc = mspack_fmap_alloc,
 
1284
+       .free = mspack_fmap_free,
 
1285
+       .copy = mspack_fmap_copy,
 
1286
+};
 
1287
+
 
1288
+static int cli_scanfile(const char *filename, cli_ctx *ctx)
 
1289
+{
 
1290
+       int fd, ret;
 
1291
+
 
1292
+       /* internal version of cl_scanfile with arec/mrec preserved */
 
1293
+       fd = safe_open(filename, O_RDONLY|O_BINARY);
 
1294
+       if (fd < 0)
 
1295
+               return CL_EOPEN;
 
1296
+
 
1297
+       ret = cli_magic_scandesc(fd, ctx);
 
1298
+
 
1299
+       close(fd);
 
1300
+       return ret;
 
1301
+}
 
1302
+
 
1303
+int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset)
 
1304
+{
 
1305
+       struct mscab_decompressor *cab_d;
 
1306
+       struct mscabd_cabinet *cab_h;
 
1307
+       struct mscabd_file *cab_f;
 
1308
+       int ret;
 
1309
+       int files;
 
1310
+       int virus_num = 0;
 
1311
+       struct mspack_name mspack_fmap = {
 
1312
+               .fmap   = *ctx->fmap,
 
1313
+               .org    = sfx_offset,
 
1314
+       };
 
1315
+       struct mspack_system_ex ops_ex = {
 
1316
+               .ops    = mspack_sys_fmap_ops,
 
1317
+       };
 
1318
+
 
1319
+       MSPACK_SYS_SELFTEST(ret);
 
1320
+       if (ret) {
 
1321
+               cli_dbgmsg("%s() failed at %d\n", __func__, __LINE__);
 
1322
+               return CL_EUNPACK;
 
1323
+       }
 
1324
+
 
1325
+       cab_d = mspack_create_cab_decompressor(&ops_ex.ops);
 
1326
+       if (!cab_d) {
 
1327
+               cli_dbgmsg("%s() failed at %d\n", __func__, __LINE__);
 
1328
+               return CL_EUNPACK;
 
1329
+       }
 
1330
+
 
1331
+       cab_h = cab_d->open(cab_d, (char *)&mspack_fmap);
 
1332
+       if (!cab_h) {
 
1333
+               ret = CL_EFORMAT;
 
1334
+               cli_dbgmsg("%s() failed at %d\n", __func__, __LINE__);
 
1335
+               goto out_dest;
 
1336
+       }
 
1337
+       files = 0;
 
1338
+       for (cab_f = cab_h->files; cab_f; cab_f = cab_f->next) {
 
1339
+               off_t max_size;
 
1340
+               char *tmp_fname;
 
1341
+
 
1342
+               ret = cli_matchmeta(ctx, cab_f->filename, 0, cab_f->length, 0,
 
1343
+                               files, 0, NULL);
 
1344
+               if (ret) {
 
1345
+                       if (ret == CL_VIRUS) {
 
1346
+                               virus_num++;
 
1347
+                               if (!SCAN_ALL)
 
1348
+                                       break;
 
1349
+                       }
 
1350
+                       goto out_close;
 
1351
+               }
 
1352
+
 
1353
+               if (ctx->engine->maxscansize) {
 
1354
+                       if (ctx->scansize >= ctx->engine->maxscansize) {
 
1355
+                               ret = CL_CLEAN;
 
1356
+                               break;
 
1357
+                       }
 
1358
+               }
 
1359
+
 
1360
+               if (ctx->engine->maxscansize &&
 
1361
+                               ctx->scansize + ctx->engine->maxfilesize >=
 
1362
+                               ctx->engine->maxscansize)
 
1363
+                       max_size = ctx->engine->maxscansize -
 
1364
+                               ctx->scansize;
 
1365
+               else
 
1366
+                       max_size = ctx->engine->maxfilesize ?
 
1367
+                               ctx->engine->maxfilesize :
 
1368
+                               0xffffffff;
 
1369
+
 
1370
+               tmp_fname = cli_gentemp(ctx->engine->tmpdir);
 
1371
+               if (!tmp_fname) {
 
1372
+                       ret = CL_EMEM;
 
1373
+                       break;
 
1374
+               }
 
1375
+
 
1376
+               ops_ex.max_size = max_size;
 
1377
+               /* scan */
 
1378
+               ret = cab_d->extract(cab_d, cab_f, tmp_fname);
 
1379
+               if (ret)
 
1380
+                       /* Failed to extract. Try to scan what is there */
 
1381
+                       cli_dbgmsg("%s() failed to extract %d\n", __func__, ret);
 
1382
+
 
1383
+               ret = cli_scanfile(tmp_fname, ctx);
 
1384
+               if (ret == CL_VIRUS)
 
1385
+                       virus_num++;
 
1386
+
 
1387
+               if (!ctx->engine->keeptmp) {
 
1388
+                       if (!access(tmp_fname, R_OK) && cli_unlink(tmp_fname)) {
 
1389
+                               free(tmp_fname);
 
1390
+                               ret = CL_EUNLINK;
 
1391
+                               break;
 
1392
+                       }
 
1393
+               }
 
1394
+               free(tmp_fname);
 
1395
+               files++;
 
1396
+               if (ret == CL_VIRUS && SCAN_ALL)
 
1397
+                       continue;
 
1398
+               if (ret)
 
1399
+                       break;
 
1400
+       }
 
1401
+
 
1402
+out_close:
 
1403
+       cab_d->close(cab_d, cab_h);
 
1404
+out_dest:
 
1405
+       mspack_destroy_cab_decompressor(cab_d);
 
1406
+       if (virus_num)
 
1407
+               return CL_VIRUS;
 
1408
+       return ret;
 
1409
+}
 
1410
+
 
1411
+int cli_scanmschm(cli_ctx *ctx)
 
1412
+{
 
1413
+       struct mschm_decompressor *mschm_d;
 
1414
+       struct mschmd_header *mschm_h;
 
1415
+       struct mschmd_file *mschm_f;
 
1416
+       int ret;
 
1417
+       int files;
 
1418
+       int virus_num = 0;
 
1419
+       struct mspack_name mspack_fmap = {
 
1420
+               .fmap = *ctx->fmap,
 
1421
+       };
 
1422
+       struct mspack_system_ex ops_ex = {
 
1423
+               .ops    = mspack_sys_fmap_ops,
 
1424
+       };
 
1425
+
 
1426
+       MSPACK_SYS_SELFTEST(ret);
 
1427
+       if (ret) {
 
1428
+               cli_dbgmsg("%s() failed at %d\n", __func__, __LINE__);
 
1429
+               return CL_EUNPACK;
 
1430
+       }
 
1431
+
 
1432
+       mschm_d = mspack_create_chm_decompressor(&ops_ex.ops);
 
1433
+       if (!mschm_d) {
 
1434
+               cli_dbgmsg("%s() failed at %d\n", __func__, __LINE__);
 
1435
+               return CL_EUNPACK;
 
1436
+       }
 
1437
+
 
1438
+       mschm_h = mschm_d->open(mschm_d, (char *)&mspack_fmap);
 
1439
+       if (!mschm_h) {
 
1440
+               ret = CL_EFORMAT;
 
1441
+               cli_dbgmsg("%s() failed at %d\n", __func__, __LINE__);
 
1442
+               goto out_dest;
 
1443
+       }
 
1444
+       files = 0;
 
1445
+       for (mschm_f = mschm_h->files; mschm_f; mschm_f = mschm_f->next) {
 
1446
+               off_t max_size;
 
1447
+               char *tmp_fname;
 
1448
+
 
1449
+               ret = cli_matchmeta(ctx, mschm_f->filename, 0, mschm_f->length,
 
1450
+                               0, files, 0, NULL);
 
1451
+               if (ret) {
 
1452
+                       if (ret == CL_VIRUS) {
 
1453
+                               virus_num++;
 
1454
+                               if (!SCAN_ALL)
 
1455
+                                       break;
 
1456
+                       }
 
1457
+                       goto out_close;
 
1458
+               }
 
1459
+
 
1460
+               if (ctx->engine->maxscansize) {
 
1461
+                       if (ctx->scansize >= ctx->engine->maxscansize) {
 
1462
+                               ret = CL_CLEAN;
 
1463
+                               break;
 
1464
+                       }
 
1465
+               }
 
1466
+
 
1467
+               if (ctx->engine->maxscansize &&
 
1468
+                               ctx->scansize + ctx->engine->maxfilesize >=
 
1469
+                               ctx->engine->maxscansize)
 
1470
+                       max_size = ctx->engine->maxscansize -
 
1471
+                               ctx->scansize;
 
1472
+               else
 
1473
+                       max_size = ctx->engine->maxfilesize ?
 
1474
+                               ctx->engine->maxfilesize :
 
1475
+                               0xffffffff;
 
1476
+
 
1477
+               ops_ex.max_size = max_size;
 
1478
+
 
1479
+               tmp_fname = cli_gentemp(ctx->engine->tmpdir);
 
1480
+               if (!tmp_fname) {
 
1481
+                       ret = CL_EMEM;
 
1482
+                       break;
 
1483
+               }
 
1484
+
 
1485
+               /* scan */
 
1486
+               ret = mschm_d->extract(mschm_d, mschm_f, tmp_fname);
 
1487
+               if (ret)
 
1488
+                       /* Failed to extract. Try to scan what is there */
 
1489
+                       cli_dbgmsg("%s() failed to extract %d\n", __func__, ret);
 
1490
+
 
1491
+               ret = cli_scanfile(tmp_fname, ctx);
 
1492
+               if (ret == CL_VIRUS)
 
1493
+                       virus_num++;
 
1494
+
 
1495
+               if (!ctx->engine->keeptmp) {
 
1496
+                       if (!access(tmp_fname, R_OK) && cli_unlink(tmp_fname)) {
 
1497
+                               free(tmp_fname);
 
1498
+                               ret = CL_EUNLINK;
 
1499
+                               break;
 
1500
+                       }
 
1501
+               }
 
1502
+               free(tmp_fname);
 
1503
+               files++;
 
1504
+               if (ret == CL_VIRUS && SCAN_ALL)
 
1505
+                       continue;
 
1506
+               if (ret)
 
1507
+                       break;
 
1508
+       }
 
1509
+
 
1510
+out_close:
 
1511
+       mschm_d->close(mschm_d, mschm_h);
 
1512
+out_dest:
 
1513
+       mspack_destroy_chm_decompressor(mschm_d);
 
1514
+       if (virus_num)
 
1515
+               return CL_VIRUS;
 
1516
+       return ret;
 
1517
+
 
1518
+       return 0;
 
1519
+}
 
1520
diff --git a/libclamav/libmspack.h b/libclamav/libmspack.h
 
1521
new file mode 100644
 
1522
index 0000000..07a9442
 
1523
--- /dev/null
 
1524
+++ b/libclamav/libmspack.h
 
1525
@@ -0,0 +1,7 @@
 
1526
+#ifndef __LIBMSPACK_H__
 
1527
+#define __LIBMSPACK_H__
 
1528
+
 
1529
+int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset);
 
1530
+int cli_scanmschm(cli_ctx *ctx);
 
1531
+
 
1532
+#endif
 
1533
diff --git a/libclamav/mspack.c b/libclamav/mspack.c
 
1534
deleted file mode 100644
 
1535
index cc4c0a5..0000000
 
1536
--- a/libclamav/mspack.c
 
1537
+++ /dev/null
 
1538
@@ -1,2026 +0,0 @@
 
1539
-/*
 
1540
- * This file includes code from libmspack adapted for libclamav by
 
1541
- * tkojm@clamav.net and draynor@sourcefire.com
 
1542
- *
 
1543
- * Copyright (C) 2003-2004 Stuart Caie
 
1544
- *
 
1545
- * This library is free software; you can redistribute it and/or
 
1546
- * modify it under the terms of the GNU Lesser General Public
 
1547
- * License version 2.1 as published by the Free Software Foundation.
 
1548
- *
 
1549
- * This library is distributed in the hope that it will be useful,
 
1550
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
1551
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
1552
- * Lesser General Public License for more details.
 
1553
- * 
 
1554
- * You should have received a copy of the GNU Lesser General Public
 
1555
- * License along with this library; if not, write to the Free Software
 
1556
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 
1557
- * USA
 
1558
- */
 
1559
-
 
1560
-#if HAVE_CONFIG_H
 
1561
-#include "clamav-config.h"
 
1562
-#endif
 
1563
-
 
1564
-#include <stdio.h>
 
1565
-#include <string.h>
 
1566
-
 
1567
-#include "others.h"
 
1568
-#include "clamav.h"
 
1569
-#include "mspack.h"
 
1570
-
 
1571
-#if HAVE_LIMITS_H
 
1572
-# include <limits.h>
 
1573
-#endif
 
1574
-#ifndef CHAR_BIT
 
1575
-# define CHAR_BIT (8)
 
1576
-#endif
 
1577
-
 
1578
-
 
1579
-/***************************************************************************
 
1580
- *                      MS-ZIP decompression implementation 
 
1581
- ***************************************************************************
 
1582
- * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted
 
1583
- * by Microsoft Corporation.
 
1584
- *
 
1585
- * The deflate method was created by Phil Katz. MSZIP is equivalent to the
 
1586
- * deflate method.
 
1587
- *
 
1588
- */
 
1589
-
 
1590
-/* match lengths for literal codes 257.. 285 */
 
1591
-static const unsigned short mszip_lit_lengths[29] = {
 
1592
-  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27,
 
1593
-  31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
 
1594
-};
 
1595
-
 
1596
-/* match offsets for distance codes 0 .. 29 */
 
1597
-static const unsigned short mszip_dist_offsets[30] = {
 
1598
-  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385,
 
1599
-  513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577
 
1600
-};
 
1601
-
 
1602
-/* extra bits required for literal codes 257.. 285 */
 
1603
-static const unsigned char mszip_lit_extrabits[29] = {
 
1604
-  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2,
 
1605
-  2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
 
1606
-};
 
1607
-
 
1608
-/* extra bits required for distance codes 0 .. 29 */
 
1609
-static const unsigned char mszip_dist_extrabits[30] = {
 
1610
-  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6,
 
1611
-  6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13
 
1612
-};
 
1613
-
 
1614
-/* the order of the bit length Huffman code lengths */
 
1615
-static const unsigned char mszip_bitlen_order[19] = {
 
1616
-  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
 
1617
-};
 
1618
-
 
1619
-/* ANDing with mszip_bit_mask[n] masks the lower n bits */
 
1620
-static const unsigned short mszip_bit_mask_tab[17] = {
 
1621
- 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
 
1622
- 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
 
1623
-};
 
1624
-
 
1625
-#define MSZIP_STORE_BITS do {                                                 \
 
1626
-  zip->i_ptr      = i_ptr;                                              \
 
1627
-  zip->i_end      = i_end;                                              \
 
1628
-  zip->bit_buffer = bit_buffer;                                         \
 
1629
-  zip->bits_left  = bits_left;                                          \
 
1630
-} while (0)
 
1631
-
 
1632
-#define MSZIP_RESTORE_BITS do {                                               \
 
1633
-  i_ptr      = zip->i_ptr;                                              \
 
1634
-  i_end      = zip->i_end;                                              \
 
1635
-  bit_buffer = zip->bit_buffer;                                         \
 
1636
-  bits_left  = zip->bits_left;                                          \
 
1637
-} while (0)
 
1638
-
 
1639
-#define MSZIP_ENSURE_BITS(nbits) do {                                         \
 
1640
-  while (bits_left < (nbits)) {                                         \
 
1641
-    if (i_ptr >= i_end) {                                               \
 
1642
-      if (mszip_read_input(zip)) return zip->error;                      \
 
1643
-      i_ptr = zip->i_ptr;                                               \
 
1644
-      i_end = zip->i_end;                                               \
 
1645
-      if(i_ptr == i_end) break;                                                \
 
1646
-    }                                                                   \
 
1647
-    bit_buffer |= *i_ptr++ << bits_left; bits_left  += 8;               \
 
1648
-  }                                                                     \
 
1649
-} while (0)
 
1650
-
 
1651
-#define MSZIP_PEEK_BITS(nbits)   (bit_buffer & ((1<<(nbits))-1))
 
1652
-#define MSZIP_PEEK_BITS_T(nbits) (bit_buffer & mszip_bit_mask_tab[(nbits)])
 
1653
-
 
1654
-#define MSZIP_REMOVE_BITS(nbits) ((bit_buffer >>= (nbits)), (bits_left -= (nbits)))
 
1655
-
 
1656
-#define MSZIP_READ_BITS(val, nbits) do {                                      \
 
1657
-  MSZIP_ENSURE_BITS(nbits); (val) = MSZIP_PEEK_BITS(nbits); MSZIP_REMOVE_BITS(nbits);     \
 
1658
-} while (0)
 
1659
-
 
1660
-#define MSZIP_READ_BITS_T(val, nbits) do {                                    \
 
1661
-  MSZIP_ENSURE_BITS(nbits); (val) = MSZIP_PEEK_BITS_T(nbits); MSZIP_REMOVE_BITS(nbits);   \
 
1662
-} while (0)
 
1663
-
 
1664
-static int mszip_read_input(struct mszip_stream *zip) {
 
1665
-  int nread = zip->read_cb(zip->file, zip->inbuf, (int)zip->inbuf_size);
 
1666
-  if (nread < 0) {
 
1667
-    if (zip->file->error == CL_BREAK) {
 
1668
-      if ((unsigned int)nread == zip->last) {
 
1669
-        cli_dbgmsg("mszip_read_input: Two consecutive CL_BREAKs reached.\n");
 
1670
-        return CL_BREAK;
 
1671
-      }
 
1672
-      // Need short circuit to ensure scanning small files
 
1673
-      cli_dbgmsg("mszip_read_input: First CL_BREAK reached.\n");
 
1674
-      zip->i_ptr = zip->i_end;
 
1675
-      zip->last = nread;
 
1676
-      return CL_SUCCESS;
 
1677
-    }
 
1678
-    else
 
1679
-      return zip->error = CL_EFORMAT;
 
1680
-  }
 
1681
-
 
1682
-  zip->last = nread;
 
1683
-  zip->i_ptr = &zip->inbuf[0];
 
1684
-  zip->i_end = &zip->inbuf[nread];
 
1685
-
 
1686
-  return CL_SUCCESS;
 
1687
-}
 
1688
-
 
1689
-/* inflate() error codes */
 
1690
-#define INF_ERR_BLOCKTYPE   (-1)  /* unknown block type                      */
 
1691
-#define INF_ERR_COMPLEMENT  (-2)  /* block size complement mismatch          */
 
1692
-#define INF_ERR_FLUSH       (-3)  /* error from flush_window() callback      */
 
1693
-#define INF_ERR_BITBUF      (-4)  /* too many bits in bit buffer             */
 
1694
-#define INF_ERR_SYMLENS     (-5)  /* too many symbols in blocktype 2 header  */
 
1695
-#define INF_ERR_BITLENTBL   (-6)  /* failed to build bitlens huffman table   */
 
1696
-#define INF_ERR_LITERALTBL  (-7)  /* failed to build literals huffman table  */
 
1697
-#define INF_ERR_DISTANCETBL (-8)  /* failed to build distance huffman table  */
 
1698
-#define INF_ERR_BITOVERRUN  (-9)  /* bitlen RLE code goes over table size    */
 
1699
-#define INF_ERR_BADBITLEN   (-10) /* invalid bit-length code                 */
 
1700
-#define INF_ERR_LITCODE     (-11) /* out-of-range literal code               */
 
1701
-#define INF_ERR_DISTCODE    (-12) /* out-of-range distance code              */
 
1702
-#define INF_ERR_DISTANCE    (-13) /* somehow, distance is beyond 32k         */
 
1703
-#define INF_ERR_HUFFSYM     (-14) /* out of bits decoding huffman symbol     */
 
1704
-
 
1705
-/* mszip_make_decode_table(nsyms, nbits, length[], table[])
 
1706
- *
 
1707
- * This function was coded by David Tritscher. It builds a fast huffman
 
1708
- * decoding table out of just a canonical huffman code lengths table.
 
1709
- *
 
1710
- * NOTE: this is NOT identical to the mszip_make_decode_table() in lzxd.c. This
 
1711
- * one reverses the quick-lookup bit pattern. Bits are read MSB to LSB in LZX,
 
1712
- * but LSB to MSB in MSZIP.
 
1713
- *
 
1714
- * nsyms  = total number of symbols in this huffman tree.
 
1715
- * nbits  = any symbols with a code length of nbits or less can be decoded
 
1716
- *          in one lookup of the table.
 
1717
- * length = A table to get code lengths from [0 to nsyms-1]
 
1718
- * table  = The table to fill up with decoded symbols and pointers.
 
1719
- *
 
1720
- * Returns 0 for OK or 1 for error
 
1721
- */
 
1722
-static int mszip_make_decode_table(unsigned int nsyms, unsigned int nbits,
 
1723
-                            unsigned char *length, unsigned short *table)
 
1724
-{
 
1725
-  register unsigned int leaf, reverse, fill;
 
1726
-  register unsigned short sym, next_sym;
 
1727
-  register unsigned char bit_num;
 
1728
-  unsigned int pos         = 0; /* the current position in the decode table */
 
1729
-  unsigned int table_mask  = 1 << nbits;
 
1730
-  unsigned int mszip_bit_mask    = table_mask >> 1; /* don't do 0 length codes */
 
1731
-
 
1732
-  /* fill entries for codes short enough for a direct mapping */
 
1733
-  for (bit_num = 1; bit_num <= nbits; bit_num++) {
 
1734
-    for (sym = 0; sym < nsyms; sym++) {
 
1735
-      if (length[sym] != bit_num) continue;
 
1736
-
 
1737
-      /* reverse the significant bits */
 
1738
-      fill = length[sym]; reverse = pos >> (nbits - fill); leaf = 0;
 
1739
-      do {leaf <<= 1; leaf |= reverse & 1; reverse >>= 1;} while (--fill);
 
1740
-
 
1741
-      if((pos += mszip_bit_mask) > table_mask) return 1; /* table overrun */
 
1742
-
 
1743
-      /* fill all possible lookups of this symbol with the symbol itself */
 
1744
-      fill = mszip_bit_mask; next_sym = 1 << bit_num;
 
1745
-      do { table[leaf] = sym; leaf += next_sym; } while (--fill);
 
1746
-    }
 
1747
-    mszip_bit_mask >>= 1;
 
1748
-  }
 
1749
-
 
1750
-  /* exit with success if table is now complete */
 
1751
-  if (pos == table_mask) return 0;
 
1752
-
 
1753
-  /* mark all remaining table entries as unused */
 
1754
-  for (sym = pos; sym < table_mask; sym++) {
 
1755
-    reverse = sym; leaf = 0; fill = nbits;
 
1756
-    do { leaf <<= 1; leaf |= reverse & 1; reverse >>= 1; } while (--fill);
 
1757
-    table[leaf] = 0xFFFF;
 
1758
-  }
 
1759
-
 
1760
-  /* where should the longer codes be allocated from? */
 
1761
-  next_sym = ((table_mask >> 1) < nsyms) ? nsyms : (table_mask >> 1);
 
1762
-
 
1763
-  /* give ourselves room for codes to grow by up to 16 more bits.
 
1764
-   * codes now start at bit nbits+16 and end at (nbits+16-codelength) */
 
1765
-  pos <<= 16;
 
1766
-  table_mask <<= 16;
 
1767
-  mszip_bit_mask = 1 << 15;
 
1768
-
 
1769
-  for (bit_num = nbits+1; bit_num <= MSZIP_MAX_HUFFBITS; bit_num++) {
 
1770
-    for (sym = 0; sym < nsyms; sym++) {
 
1771
-      if (length[sym] != bit_num) continue;
 
1772
-
 
1773
-      /* leaf = the first nbits of the code, reversed */
 
1774
-      reverse = pos >> 16; leaf = 0; fill = nbits;
 
1775
-      do {leaf <<= 1; leaf |= reverse & 1; reverse >>= 1;} while (--fill);
 
1776
-
 
1777
-      for (fill = 0; fill < (bit_num - nbits); fill++) {
 
1778
-       /* if this path hasn't been taken yet, 'allocate' two entries */
 
1779
-       if (table[leaf] == 0xFFFF) {
 
1780
-         table[(next_sym << 1)     ] = 0xFFFF;
 
1781
-         table[(next_sym << 1) + 1 ] = 0xFFFF;
 
1782
-         table[leaf] = next_sym++;
 
1783
-       }
 
1784
-       /* follow the path and select either left or right for next bit */
 
1785
-       leaf = (table[leaf] << 1) | ((pos >> (15 - fill)) & 1);
 
1786
-      }
 
1787
-      table[leaf] = sym;
 
1788
-
 
1789
-      if ((pos += mszip_bit_mask) > table_mask) return 1; /* table overflow */
 
1790
-    }
 
1791
-    mszip_bit_mask >>= 1;
 
1792
-  }
 
1793
-
 
1794
-  /* full table? */
 
1795
-  return (pos != table_mask) ? 1 : 0;
 
1796
-}
 
1797
-
 
1798
-/* MSZIP_READ_HUFFSYM(tablename, var) decodes one huffman symbol from the
 
1799
- * bitstream using the stated table and puts it in var.
 
1800
- */
 
1801
-#define MSZIP_READ_HUFFSYM(tbl, var) do {                                     \
 
1802
-  /* huffman symbols can be up to 16 bits long */                       \
 
1803
-  MSZIP_ENSURE_BITS(MSZIP_MAX_HUFFBITS);                                      \
 
1804
-  /* immediate table lookup of [tablebits] bits of the code */          \
 
1805
-  sym = zip->tbl##_table[MSZIP_PEEK_BITS(MSZIP_##tbl##_TABLEBITS)];            \
 
1806
-  /* is the symbol is longer than [tablebits] bits? (i=node index) */   \
 
1807
-  if (sym >= MSZIP_##tbl##_MAXSYMBOLS) {                                \
 
1808
-    /* decode remaining bits by tree traversal */                       \
 
1809
-    i = MSZIP_##tbl##_TABLEBITS - 1;                                   \
 
1810
-    do {                                                                \
 
1811
-      /* check next bit. error if we run out of bits before decode */  \
 
1812
-      if (i++ > MSZIP_MAX_HUFFBITS) {                                  \
 
1813
-        cli_dbgmsg("zip_inflate: out of bits in huffman decode\n");    \
 
1814
-        return INF_ERR_HUFFSYM;                                         \
 
1815
-      }                                                                 \
 
1816
-      sym = (sym << 1) | ((bit_buffer >> i) & 1);                      \
 
1817
-      if(sym >= MSZIP_##tbl##_TABLESIZE) {                             \
 
1818
-       cli_dbgmsg("zip_inflate: index out of table\n");                \
 
1819
-        return INF_ERR_HUFFSYM;                                         \
 
1820
-      }                                                                        \
 
1821
-      /* double node index and add 0 (left branch) or 1 (right) */     \
 
1822
-      sym = zip->tbl##_table[sym];                                     \
 
1823
-      /* while we are still in node indicies, not decoded symbols */    \
 
1824
-    } while (sym >= MSZIP_##tbl##_MAXSYMBOLS);                          \
 
1825
-  }                                                                     \
 
1826
-  /* result */                                                          \
 
1827
-  (var) = sym;                                                          \
 
1828
-  /* look up the code length of that symbol and discard those bits */   \
 
1829
-  i = zip->tbl##_len[sym];                                              \
 
1830
-  MSZIP_REMOVE_BITS(i);                                                       \
 
1831
-} while (0)
 
1832
-
 
1833
-static int mszip_read_lens(struct mszip_stream *zip) {
 
1834
-  /* for the bit buffer and huffman decoding */
 
1835
-  register unsigned int bit_buffer;
 
1836
-  register int bits_left;
 
1837
-  unsigned char *i_ptr, *i_end;
 
1838
-
 
1839
-  /* bitlen Huffman codes -- immediate lookup, 7 bit max code length */
 
1840
-  unsigned short bl_table[(1 << 7)];
 
1841
-  unsigned char bl_len[19];
 
1842
-
 
1843
-  unsigned char lens[MSZIP_LITERAL_MAXSYMBOLS + MSZIP_DISTANCE_MAXSYMBOLS];
 
1844
-  unsigned int lit_codes, dist_codes, code, last_code=0, bitlen_codes, i, run;
 
1845
-
 
1846
-  MSZIP_RESTORE_BITS;
 
1847
-
 
1848
-  /* read the number of codes */
 
1849
-  MSZIP_READ_BITS(lit_codes,    5); lit_codes    += 257;
 
1850
-  MSZIP_READ_BITS(dist_codes,   5); dist_codes   += 1;
 
1851
-  MSZIP_READ_BITS(bitlen_codes, 4); bitlen_codes += 4;
 
1852
-  if (lit_codes  > MSZIP_LITERAL_MAXSYMBOLS)  return INF_ERR_SYMLENS;
 
1853
-  if (dist_codes > MSZIP_DISTANCE_MAXSYMBOLS) return INF_ERR_SYMLENS;
 
1854
-
 
1855
-  /* read in the bit lengths in their unusual order */
 
1856
-  for (i = 0; i < bitlen_codes; i++) MSZIP_READ_BITS(bl_len[mszip_bitlen_order[i]], 3);
 
1857
-  while (i < 19) bl_len[mszip_bitlen_order[i++]] = 0;
 
1858
-
 
1859
-  /* create decoding table with an immediate lookup */
 
1860
-  if (mszip_make_decode_table(19, 7, &bl_len[0], &bl_table[0])) {
 
1861
-    return INF_ERR_BITLENTBL;
 
1862
-  }
 
1863
-
 
1864
-  /* read literal / distance code lengths */
 
1865
-  for (i = 0; i < (lit_codes + dist_codes); i++) {
 
1866
-    /* single-level huffman lookup */
 
1867
-    MSZIP_ENSURE_BITS(7);
 
1868
-    code = bl_table[MSZIP_PEEK_BITS(7)];
 
1869
-    MSZIP_REMOVE_BITS(bl_len[code]);
 
1870
-
 
1871
-    if (code < 16) lens[i] = last_code = code;
 
1872
-    else {
 
1873
-      switch (code) {
 
1874
-      case 16: MSZIP_READ_BITS(run, 2); run += 3;  code = last_code; break;
 
1875
-      case 17: MSZIP_READ_BITS(run, 3); run += 3;  code = 0;         break;
 
1876
-      case 18: MSZIP_READ_BITS(run, 7); run += 11; code = 0;         break;
 
1877
-      default: cli_dbgmsg("zip_read_lens: bad code!: %u\n", code); return INF_ERR_BADBITLEN;
 
1878
-      }
 
1879
-      if ((i + run) > (lit_codes + dist_codes)) return INF_ERR_BITOVERRUN;
 
1880
-      while (run--) lens[i++] = code;
 
1881
-      i--;
 
1882
-    }
 
1883
-  }
 
1884
-
 
1885
-  /* copy LITERAL code lengths and clear any remaining */
 
1886
-  i = lit_codes;
 
1887
-  memcpy(&zip->LITERAL_len[0], &lens[0], i);
 
1888
-  while (i < MSZIP_LITERAL_MAXSYMBOLS) zip->LITERAL_len[i++] = 0;
 
1889
-
 
1890
-  i = dist_codes;
 
1891
-  memcpy(&zip->DISTANCE_len[0], &lens[lit_codes], i);
 
1892
-  while (i < MSZIP_DISTANCE_MAXSYMBOLS) zip->DISTANCE_len[i++] = 0;
 
1893
-
 
1894
-  MSZIP_STORE_BITS;
 
1895
-  return 0;
 
1896
-}
 
1897
-
 
1898
-static int mspack_write(int fd, const void *buff, unsigned int count, struct cab_file *file)
 
1899
-{
 
1900
-       int ret;
 
1901
-
 
1902
-    if(file->max_size) {
 
1903
-       if(file->written_size >= file->max_size)
 
1904
-           return CL_BREAK;
 
1905
-
 
1906
-       if(file->written_size + count > file->max_size)
 
1907
-           count = file->max_size - file->written_size;
 
1908
-    }
 
1909
-    if((ret = cli_writen(fd, buff, count)) > 0)
 
1910
-       file->written_size += ret;
 
1911
-
 
1912
-    return (ret == -1) ? CL_EWRITE : CL_SUCCESS;
 
1913
-}
 
1914
-
 
1915
-/* a clean implementation of RFC 1951 / inflate */
 
1916
-static int mszip_inflate(struct mszip_stream *zip) {
 
1917
-  unsigned int last_block, block_type, distance, length, this_run, i;
 
1918
-
 
1919
-  /* for the bit buffer and huffman decoding */
 
1920
-  register unsigned int bit_buffer;
 
1921
-  register int bits_left;
 
1922
-  register unsigned short sym;
 
1923
-  unsigned char *i_ptr, *i_end;
 
1924
-
 
1925
-  MSZIP_RESTORE_BITS;
 
1926
-
 
1927
-  do {
 
1928
-    /* read in last block bit */
 
1929
-    MSZIP_READ_BITS(last_block, 1);
 
1930
-
 
1931
-    /* read in block type */
 
1932
-    MSZIP_READ_BITS(block_type, 2);
 
1933
-
 
1934
-    if (block_type == 0) {
 
1935
-      /* uncompressed block */
 
1936
-      unsigned char lens_buf[4];
 
1937
-
 
1938
-      /* go to byte boundary */
 
1939
-      i = bits_left & 7; MSZIP_REMOVE_BITS(i);
 
1940
-
 
1941
-      /* read 4 bytes of data, emptying the bit-buffer if necessary */
 
1942
-      for (i = 0; (bits_left >= 8); i++) {
 
1943
-       if (i == 4) return INF_ERR_BITBUF;
 
1944
-       lens_buf[i] = MSZIP_PEEK_BITS(8);
 
1945
-       MSZIP_REMOVE_BITS(8);
 
1946
-      }
 
1947
-      if (bits_left != 0) return INF_ERR_BITBUF;
 
1948
-      while (i < 4) {
 
1949
-       if (i_ptr >= i_end) {
 
1950
-         if (mszip_read_input(zip)) return zip->error;
 
1951
-         i_ptr = zip->i_ptr;
 
1952
-         i_end = zip->i_end;
 
1953
-         if(i_ptr == i_end) break;
 
1954
-       }
 
1955
-       lens_buf[i++] = *i_ptr++;
 
1956
-      }
 
1957
-      if (i < 4) return INF_ERR_BITBUF;
 
1958
-
 
1959
-      /* get the length and its complement */
 
1960
-      length = lens_buf[0] | (lens_buf[1] << 8);
 
1961
-      i      = lens_buf[2] | (lens_buf[3] << 8);
 
1962
-      if (length != (~i & 0xFFFF)) return INF_ERR_COMPLEMENT;
 
1963
-
 
1964
-      /* read and copy the uncompressed data into the window */
 
1965
-      while (length > 0) {
 
1966
-       if (i_ptr >= i_end) {
 
1967
-         if (mszip_read_input(zip)) return zip->error;
 
1968
-         i_ptr = zip->i_ptr;
 
1969
-         i_end = zip->i_end;
 
1970
-         if(i_ptr == i_end) break;
 
1971
-       }
 
1972
-
 
1973
-       this_run = length;
 
1974
-       if (this_run > (unsigned int)(i_end - i_ptr)) this_run = i_end - i_ptr;
 
1975
-       if (this_run > (MSZIP_FRAME_SIZE - zip->window_posn))
 
1976
-         this_run = MSZIP_FRAME_SIZE - zip->window_posn;
 
1977
-
 
1978
-       memcpy(&zip->window[zip->window_posn], i_ptr, this_run);
 
1979
-       zip->window_posn += this_run;
 
1980
-       i_ptr    += this_run;
 
1981
-       length   -= this_run;
 
1982
-
 
1983
-       if (zip->window_posn == MSZIP_FRAME_SIZE) {
 
1984
-         if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) return INF_ERR_FLUSH;
 
1985
-         zip->window_posn = 0;
 
1986
-       }
 
1987
-      }
 
1988
-    }
 
1989
-    else if ((block_type == 1) || (block_type == 2)) {
 
1990
-      /* Huffman-compressed LZ77 block */
 
1991
-      unsigned int window_posn, match_posn, code;
 
1992
-
 
1993
-      if (block_type == 1) {
 
1994
-       /* block with fixed Huffman codes */
 
1995
-       i = 0;
 
1996
-       while (i < 144) zip->LITERAL_len[i++] = 8;
 
1997
-       while (i < 256) zip->LITERAL_len[i++] = 9;
 
1998
-       while (i < 280) zip->LITERAL_len[i++] = 7;
 
1999
-       while (i < 288) zip->LITERAL_len[i++] = 8;
 
2000
-       for (i = 0; i < 32; i++) zip->DISTANCE_len[i] = 5;
 
2001
-      }
 
2002
-      else {
 
2003
-       /* block with dynamic Huffman codes */
 
2004
-       MSZIP_STORE_BITS;
 
2005
-       if ((i = mszip_read_lens(zip))) return i;
 
2006
-       MSZIP_RESTORE_BITS;
 
2007
-      }
 
2008
-
 
2009
-      /* now huffman lengths are read for either kind of block, 
 
2010
-       * create huffman decoding tables */
 
2011
-      if (mszip_make_decode_table(MSZIP_LITERAL_MAXSYMBOLS, MSZIP_LITERAL_TABLEBITS,
 
2012
-                           &zip->LITERAL_len[0], &zip->LITERAL_table[0]))
 
2013
-      {
 
2014
-       return INF_ERR_LITERALTBL;
 
2015
-      }
 
2016
-
 
2017
-      if (mszip_make_decode_table(MSZIP_DISTANCE_MAXSYMBOLS,MSZIP_DISTANCE_TABLEBITS,
 
2018
-                           &zip->DISTANCE_len[0], &zip->DISTANCE_table[0]))
 
2019
-      {
 
2020
-       return INF_ERR_DISTANCETBL;
 
2021
-      }
 
2022
-
 
2023
-      /* decode forever until end of block code */
 
2024
-      window_posn = zip->window_posn;
 
2025
-      while (1) {
 
2026
-       MSZIP_READ_HUFFSYM(LITERAL, code);
 
2027
-       if (code < 256) {
 
2028
-         zip->window[window_posn++] = (unsigned char) code;
 
2029
-         if (window_posn == MSZIP_FRAME_SIZE) {
 
2030
-           if (zip->flush_window(zip, MSZIP_FRAME_SIZE)) return INF_ERR_FLUSH;
 
2031
-           window_posn = 0;
 
2032
-         }
 
2033
-       }
 
2034
-       else if (code == 256) {
 
2035
-         /* END OF BLOCK CODE: loop break point */
 
2036
-         break;
 
2037
-       }
 
2038
-       else {
 
2039
-         code -= 257;
 
2040
-         if (code >= 29) return INF_ERR_LITCODE;
 
2041
-         MSZIP_READ_BITS_T(length, mszip_lit_extrabits[code]);
 
2042
-         length += mszip_lit_lengths[code];
 
2043
-
 
2044
-         MSZIP_READ_HUFFSYM(DISTANCE, code);
 
2045
-         if (code >= 30) return INF_ERR_DISTCODE;
 
2046
-         MSZIP_READ_BITS_T(distance, mszip_dist_extrabits[code]);
 
2047
-         distance += mszip_dist_offsets[code];
 
2048
-
 
2049
-         /* match position is window position minus distance. If distance
 
2050
-          * is more than window position numerically, it must 'wrap
 
2051
-          * around' the frame size. */ 
 
2052
-         match_posn = ((distance > window_posn) ? MSZIP_FRAME_SIZE : 0)
 
2053
-           + window_posn - distance;
 
2054
-
 
2055
-         /* copy match */
 
2056
-         if (length < 12) {
 
2057
-           /* short match, use slower loop but no loop setup code */
 
2058
-           while (length--) {
 
2059
-             zip->window[window_posn++] = zip->window[match_posn++];
 
2060
-             match_posn &= MSZIP_FRAME_SIZE - 1;
 
2061
-
 
2062
-             if (window_posn == MSZIP_FRAME_SIZE) {
 
2063
-               if (zip->flush_window(zip, MSZIP_FRAME_SIZE))
 
2064
-                 return INF_ERR_FLUSH;
 
2065
-               window_posn = 0;
 
2066
-             }
 
2067
-           }
 
2068
-         }
 
2069
-         else {
 
2070
-           /* longer match, use faster loop but with setup expense */
 
2071
-           unsigned char *runsrc, *rundest;
 
2072
-           do {
 
2073
-             this_run = length;
 
2074
-             if ((match_posn + this_run) > MSZIP_FRAME_SIZE)
 
2075
-               this_run = MSZIP_FRAME_SIZE - match_posn;
 
2076
-             if ((window_posn + this_run) > MSZIP_FRAME_SIZE)
 
2077
-               this_run = MSZIP_FRAME_SIZE - window_posn;
 
2078
-
 
2079
-             rundest = &zip->window[window_posn]; window_posn += this_run;
 
2080
-             runsrc  = &zip->window[match_posn];  match_posn  += this_run;
 
2081
-             length -= this_run;
 
2082
-             while (this_run--) *rundest++ = *runsrc++;
 
2083
-
 
2084
-             /* flush if necessary */
 
2085
-             if (window_posn == MSZIP_FRAME_SIZE) {
 
2086
-               if (zip->flush_window(zip, MSZIP_FRAME_SIZE))
 
2087
-                 return INF_ERR_FLUSH;
 
2088
-               window_posn = 0;
 
2089
-             }
 
2090
-             if (match_posn == MSZIP_FRAME_SIZE) match_posn = 0;
 
2091
-           } while (length > 0);
 
2092
-         }
 
2093
-
 
2094
-       } /* else (code >= 257) */
 
2095
-
 
2096
-      } /* while (forever) -- break point at 'code == 256' */
 
2097
-      zip->window_posn = window_posn;
 
2098
-    }
 
2099
-    else {
 
2100
-      /* block_type == 3 -- bad block type */
 
2101
-      return INF_ERR_BLOCKTYPE;
 
2102
-    }
 
2103
-  } while (!last_block);
 
2104
-
 
2105
-  /* flush the remaining data */
 
2106
-  if (zip->window_posn) {
 
2107
-    if (zip->flush_window(zip, zip->window_posn)) return INF_ERR_FLUSH;
 
2108
-  }
 
2109
-  MSZIP_STORE_BITS;
 
2110
-
 
2111
-  /* return success */
 
2112
-  return 0;
 
2113
-}
 
2114
-
 
2115
-/* inflate() calls this whenever the window should be flushed. As
 
2116
- * MSZIP only expands to the size of the window, the implementation used
 
2117
- * simply keeps track of the amount of data flushed, and if more than 32k
 
2118
- * is flushed, an error is raised.
 
2119
- */  
 
2120
-static int mszip_flush_window(struct mszip_stream *zip,
 
2121
-                              unsigned int data_flushed)
 
2122
-{
 
2123
-  zip->bytes_output += data_flushed;
 
2124
-  if (zip->bytes_output > MSZIP_FRAME_SIZE) {
 
2125
-    cli_dbgmsg("mszip_flush_window: overflow: %u bytes flushed, total is now %u\n", data_flushed, zip->bytes_output);
 
2126
-    return 1;
 
2127
-  }
 
2128
-  return 0;
 
2129
-}
 
2130
-
 
2131
-struct mszip_stream *mszip_init(int ofd,
 
2132
-                                 int input_buffer_size,
 
2133
-                                 int repair_mode,
 
2134
-                                 struct cab_file *file,
 
2135
-                                 int (*read_cb)(struct cab_file *, unsigned char *, int))
 
2136
-{
 
2137
-  struct mszip_stream *zip;
 
2138
-
 
2139
-  input_buffer_size = (input_buffer_size + 1) & -2;
 
2140
-  if (!input_buffer_size) return NULL;
 
2141
-
 
2142
-  /* allocate decompression state */
 
2143
-  if (!(zip = cli_calloc(1, sizeof(struct mszip_stream)))) {
 
2144
-      cli_errmsg("mszip_stream: Unable to allocate zip buffer\n");
 
2145
-    return NULL;
 
2146
-  }
 
2147
-
 
2148
-  /* allocate input buffer */
 
2149
-  zip->inbuf  = cli_malloc((size_t) input_buffer_size);
 
2150
-  if (!zip->inbuf) {
 
2151
-      cli_errmsg("mszip_stream: Unable to allocate input buffer\n");
 
2152
-    free(zip);
 
2153
-    return NULL;
 
2154
-  }
 
2155
-
 
2156
-  /* initialise decompression state */
 
2157
-  zip->ofd            = ofd;
 
2158
-  zip->wflag          = 1;
 
2159
-  zip->inbuf_size      = input_buffer_size;
 
2160
-  zip->error           = CL_SUCCESS;
 
2161
-  zip->repair_mode     = repair_mode;
 
2162
-  zip->flush_window    = &mszip_flush_window;
 
2163
-  zip->input_end       = 0;
 
2164
-
 
2165
-  zip->i_ptr = zip->i_end = &zip->inbuf[0];
 
2166
-  zip->o_ptr = zip->o_end = NULL;
 
2167
-  zip->bit_buffer = 0; zip->bits_left = 0;
 
2168
-
 
2169
-  zip->file = file;
 
2170
-  zip->read_cb = read_cb;
 
2171
-
 
2172
-  return zip;
 
2173
-}
 
2174
-
 
2175
-int mszip_decompress(struct mszip_stream *zip, uint32_t out_bytes) {
 
2176
-  /* for the bit buffer */
 
2177
-  register unsigned int bit_buffer;
 
2178
-  register int bits_left;
 
2179
-  unsigned char *i_ptr, *i_end;
 
2180
-
 
2181
-  int i, ret, state, error;
 
2182
-
 
2183
-  /* easy answers */
 
2184
-  if (!zip) return CL_ENULLARG;
 
2185
-  if (zip->error) return zip->error;
 
2186
-
 
2187
-  /* flush out any stored-up bytes before we begin */
 
2188
-  i = zip->o_end - zip->o_ptr;
 
2189
-  if (((off_t) i > out_bytes) && ((int) out_bytes >= 0)) i = (int) out_bytes;
 
2190
-  if (i) {
 
2191
-    if (zip->wflag && (ret = mspack_write(zip->ofd, zip->o_ptr, i, zip->file)) != CL_SUCCESS) {
 
2192
-      return zip->error = ret;
 
2193
-    }
 
2194
-    zip->o_ptr  += i;
 
2195
-    out_bytes   -= i;
 
2196
-  }
 
2197
-  if (out_bytes == 0) return CL_SUCCESS;
 
2198
-
 
2199
-  while (out_bytes > 0) {
 
2200
-    /* unpack another block */
 
2201
-    MSZIP_RESTORE_BITS;
 
2202
-
 
2203
-    /* skip to next read 'CK' header */
 
2204
-    i = bits_left & 7; MSZIP_REMOVE_BITS(i); /* align to bytestream */
 
2205
-    state = 0;
 
2206
-    do {
 
2207
-      MSZIP_READ_BITS(i, 8);
 
2208
-      if (i == 'C') state = 1;
 
2209
-      else if ((state == 1) && (i == 'K')) state = 2;
 
2210
-      else state = 0;
 
2211
-    } while (state != 2);
 
2212
-
 
2213
-    /* inflate a block, repair and realign if necessary */
 
2214
-    zip->window_posn = 0;
 
2215
-    zip->bytes_output = 0;
 
2216
-    MSZIP_STORE_BITS;
 
2217
-    if ((error = mszip_inflate(zip))) {
 
2218
-      cli_dbgmsg("mszip_decompress: inflate error %d\n", error);
 
2219
-      if (zip->repair_mode) {
 
2220
-       cli_dbgmsg("mszip_decompress: MSZIP error, %u bytes of data lost\n",
 
2221
-                         MSZIP_FRAME_SIZE - zip->bytes_output);
 
2222
-       for (i = zip->bytes_output; i < MSZIP_FRAME_SIZE; i++) {
 
2223
-         zip->window[i] = '\0';
 
2224
-       }
 
2225
-       zip->bytes_output = MSZIP_FRAME_SIZE;
 
2226
-      }
 
2227
-      else {
 
2228
-       return zip->error = (error > 0) ? error : CL_EFORMAT;
 
2229
-      }
 
2230
-    }
 
2231
-    zip->o_ptr = &zip->window[0];
 
2232
-    zip->o_end = &zip->o_ptr[zip->bytes_output];
 
2233
-
 
2234
-    /* write a frame */
 
2235
-    i = (out_bytes < (off_t)zip->bytes_output) ?
 
2236
-      (int)out_bytes : zip->bytes_output;
 
2237
-    if (zip->wflag && (ret = mspack_write(zip->ofd, zip->o_ptr, i, zip->file)) != CL_SUCCESS) {
 
2238
-      return zip->error = ret;
 
2239
-    }
 
2240
-
 
2241
-    /* mspack errors (i.e. read errors) are fatal and can't be recovered */
 
2242
-    if ((error > 0) && zip->repair_mode) return error;
 
2243
-
 
2244
-    zip->o_ptr  += i;
 
2245
-    out_bytes   -= i;
 
2246
-  }
 
2247
-
 
2248
-  if (out_bytes)
 
2249
-    cli_dbgmsg("mszip_decompress: bytes left to output\n");
 
2250
-
 
2251
-  return CL_SUCCESS;
 
2252
-}
 
2253
-
 
2254
-void mszip_free(struct mszip_stream *zip) {
 
2255
-  if (zip) {
 
2256
-    free(zip->inbuf);
 
2257
-    free(zip);
 
2258
-  }
 
2259
-}
 
2260
-
 
2261
-/***************************************************************************
 
2262
- *                      LZX decompression implementation 
 
2263
- ***************************************************************************
 
2264
- * The LZX method was created by Jonathan Forbes and Tomi Poutanen, adapted
 
2265
- * by Microsoft Corporation.
 
2266
- *
 
2267
- */
 
2268
-
 
2269
-/* LZX decompressor input macros
 
2270
- *
 
2271
- * LZX_STORE_BITS        stores bitstream state in lzx_stream structure
 
2272
- * LZX_RESTORE_BITS      restores bitstream state from lzx_stream structure
 
2273
- * LZX_READ_BITS(var,n)  takes N bits from the buffer and puts them in var
 
2274
- * LZX_ENSURE_BITS(n)    ensures there are at least N bits in the bit buffer.
 
2275
- * LZX_PEEK_BITS(n)      extracts without removing N bits from the bit buffer
 
2276
- * LZX_REMOVE_BITS(n)    removes N bits from the bit buffer
 
2277
- *
 
2278
- */
 
2279
-
 
2280
-#define LZX_BITBUF_WIDTH (sizeof(bit_buffer) * CHAR_BIT)
 
2281
-
 
2282
-#define LZX_STORE_BITS do {                                                 \
 
2283
-  lzx->i_ptr      = i_ptr;                                              \
 
2284
-  lzx->i_end      = i_end;                                              \
 
2285
-  lzx->bit_buffer = bit_buffer;                                         \
 
2286
-  lzx->bits_left  = bits_left;                                          \
 
2287
-} while (0)
 
2288
-
 
2289
-#define LZX_RESTORE_BITS do {                                               \
 
2290
-  i_ptr      = lzx->i_ptr;                                              \
 
2291
-  i_end      = lzx->i_end;                                              \
 
2292
-  bit_buffer = lzx->bit_buffer;                                         \
 
2293
-  bits_left  = lzx->bits_left;                                          \
 
2294
-} while (0)
 
2295
-
 
2296
-#define LZX_ENSURE_BITS(nbits)                                              \
 
2297
-  while (bits_left < (nbits)) {                                         \
 
2298
-    if (i_ptr + 1 >= i_end) {                                               \
 
2299
-      if (lzx_read_input(lzx)) return lzx->error;                      \
 
2300
-      i_ptr = lzx->i_ptr;                                               \
 
2301
-      i_end = lzx->i_end;                                               \
 
2302
-    }                                                                   \
 
2303
-    bit_buffer |= ((i_ptr[1] << 8) | i_ptr[0])                          \
 
2304
-                  << (LZX_BITBUF_WIDTH - 16 - bits_left);                   \
 
2305
-    bits_left  += 16;                                                   \
 
2306
-    i_ptr      += 2;                                                    \
 
2307
-  }
 
2308
-
 
2309
-#define LZX_PEEK_BITS(nbits) (bit_buffer >> (LZX_BITBUF_WIDTH - (nbits)))
 
2310
-
 
2311
-#define LZX_REMOVE_BITS(nbits) ((bit_buffer <<= (nbits)), (bits_left -= (nbits)))
 
2312
-
 
2313
-#define LZX_READ_BITS(val, nbits) do {                                      \
 
2314
-  LZX_ENSURE_BITS(nbits);                                                   \
 
2315
-  (val) = LZX_PEEK_BITS(nbits);                                             \
 
2316
-  LZX_REMOVE_BITS(nbits);                                                   \
 
2317
-} while (0)
 
2318
-
 
2319
-static int lzx_read_input(struct lzx_stream *lzx) {
 
2320
-  int bread = lzx->read_cb(lzx->file, &lzx->inbuf[0], (int)lzx->inbuf_size);
 
2321
-  if (bread < 0) {
 
2322
-    if (lzx->file->error == CL_BREAK)
 
2323
-      return lzx->error = CL_BREAK;
 
2324
-    else
 
2325
-      return lzx->error = CL_EFORMAT;
 
2326
-  }
 
2327
-
 
2328
-  /* huff decode's ENSURE_BYTES(16) might overrun the input stream, even
 
2329
-   * if those bits aren't used, so fake 2 more bytes */
 
2330
-  if (bread == 0) {
 
2331
-    if (lzx->input_end) {
 
2332
-      cli_dbgmsg("lzx_read_input: out of input bytes\n");
 
2333
-      return lzx->error = CL_EREAD;
 
2334
-    }
 
2335
-    else {
 
2336
-      bread = 2;
 
2337
-      lzx->inbuf[0] = lzx->inbuf[1] = 0;
 
2338
-      lzx->input_end = 1;
 
2339
-    }
 
2340
-  }
 
2341
-
 
2342
-  lzx->i_ptr = &lzx->inbuf[0];
 
2343
-  lzx->i_end = &lzx->inbuf[bread];
 
2344
-
 
2345
-  return CL_SUCCESS;
 
2346
-}
 
2347
-
 
2348
-/* Huffman decoding macros */
 
2349
-
 
2350
-/* LZX_READ_HUFFSYM(tablename, var) decodes one huffman symbol from the
 
2351
- * bitstream using the stated table and puts it in var.
 
2352
- */
 
2353
-#define LZX_READ_HUFFSYM(tbl, var) do {                                     \
 
2354
-  /* huffman symbols can be up to 16 bits long */                       \
 
2355
-  LZX_ENSURE_BITS(16);                                                      \
 
2356
-  /* immediate table lookup of [tablebits] bits of the code */          \
 
2357
-  sym = lzx->tbl##_table[LZX_PEEK_BITS(LZX_##tbl##_TABLEBITS)];             \
 
2358
-  /* is the symbol is longer than [tablebits] bits? (i=node index) */   \
 
2359
-  if (sym >= LZX_##tbl##_MAXSYMBOLS) {                                  \
 
2360
-    /* decode remaining bits by tree traversal */                       \
 
2361
-    i = 1 << (LZX_BITBUF_WIDTH - LZX_##tbl##_TABLEBITS);                    \
 
2362
-    do {                                                                \
 
2363
-      /* one less bit. error if we run out of bits before decode */     \
 
2364
-      i >>= 1;                                                          \
 
2365
-      if (i == 0) {                                                     \
 
2366
-        cli_dbgmsg("lzx: out of bits in huffman decode\n");             \
 
2367
-        return lzx->error = CL_EFORMAT;                                        \
 
2368
-      }                                                                 \
 
2369
-      /* double node index and add 0 (left branch) or 1 (right) */      \
 
2370
-      sym <<= 1; sym |= (bit_buffer & i) ? 1 : 0;                       \
 
2371
-      /* hop to next node index / decoded symbol */                     \
 
2372
-      if(sym >= (1 << LZX_##tbl##_TABLEBITS) + (LZX_##tbl##_MAXSYMBOLS * 2)) { \
 
2373
-       cli_dbgmsg("lzx: index out of table\n");                        \
 
2374
-       return lzx->error = CL_EFORMAT;                                 \
 
2375
-      }                                                                        \
 
2376
-      sym = lzx->tbl##_table[sym];                                    \
 
2377
-      /* while we are still in node indicies, not decoded symbols */    \
 
2378
-    } while (sym >= LZX_##tbl##_MAXSYMBOLS);                            \
 
2379
-  }                                                                     \
 
2380
-  /* result */                                                          \
 
2381
-  (var) = sym;                                                          \
 
2382
-  /* look up the code length of that symbol and discard those bits */   \
 
2383
-  i = lzx->tbl##_len[sym];                                              \
 
2384
-  LZX_REMOVE_BITS(i);                                                       \
 
2385
-} while (0)
 
2386
-
 
2387
-/* LZX_BUILD_TABLE(tbl) builds a huffman lookup table from code lengths */
 
2388
-#define LZX_BUILD_TABLE(tbl)                                                \
 
2389
-  if (lzx_make_decode_table(LZX_##tbl##_MAXSYMBOLS, LZX_##tbl##_TABLEBITS,  \
 
2390
-                       &lzx->tbl##_len[0], &lzx->tbl##_table[0]))      \
 
2391
-  {                                                                     \
 
2392
-    cli_dbgmsg("lzx: failed to build %s table\n", #tbl);                \
 
2393
-    return lzx->error = CL_EFORMAT;                                    \
 
2394
-  }
 
2395
-
 
2396
-/* lzx_make_decode_table(nsyms, nbits, length[], table[])
 
2397
- *
 
2398
- * This function was coded by David Tritscher. It builds a fast huffman
 
2399
- * decoding table from a canonical huffman code lengths table.
 
2400
- *
 
2401
- * nsyms  = total number of symbols in this huffman tree.
 
2402
- * nbits  = any symbols with a code length of nbits or less can be decoded
 
2403
- *          in one lookup of the table.
 
2404
- * length = A table to get code lengths from [0 to syms-1]
 
2405
- * table  = The table to fill up with decoded symbols and pointers.
 
2406
- *
 
2407
- * Returns 0 for OK or 1 for error
 
2408
- */
 
2409
-
 
2410
-static int lzx_make_decode_table(unsigned int nsyms, unsigned int nbits,
 
2411
-                            unsigned char *length, unsigned short *table)
 
2412
-{
 
2413
-  register unsigned short sym;
 
2414
-  register unsigned int leaf, fill;
 
2415
-  register unsigned char bit_num;
 
2416
-  unsigned int pos         = 0; /* the current position in the decode table */
 
2417
-  unsigned int table_mask  = 1 << nbits;
 
2418
-  unsigned int bit_mask    = table_mask >> 1; /* don't do 0 length codes */
 
2419
-  unsigned int next_symbol = bit_mask; /* base of allocation for long codes */
 
2420
-
 
2421
-  /* fill entries for codes short enough for a direct mapping */
 
2422
-  for (bit_num = 1; bit_num <= nbits; bit_num++) {
 
2423
-    for (sym = 0; sym < nsyms; sym++) {
 
2424
-      if (length[sym] != bit_num) continue;
 
2425
-      leaf = pos;
 
2426
-      if((pos += bit_mask) > table_mask) return 1; /* table overrun */
 
2427
-      /* fill all possible lookups of this symbol with the symbol itself */
 
2428
-      for (fill = bit_mask; fill-- > 0;) table[leaf++] = sym;
 
2429
-    }
 
2430
-    bit_mask >>= 1;
 
2431
-  }
 
2432
-
 
2433
-  /* full table already? */
 
2434
-  if (pos == table_mask) return 0;
 
2435
-
 
2436
-  /* clear the remainder of the table */
 
2437
-  for (sym = pos; sym < table_mask; sym++) table[sym] = 0xFFFF;
 
2438
-
 
2439
-  /* allow codes to be up to nbits+16 long, instead of nbits */
 
2440
-  pos <<= 16;
 
2441
-  table_mask <<= 16;
 
2442
-  bit_mask = 1 << 15;
 
2443
-
 
2444
-  for (bit_num = nbits+1; bit_num <= 16; bit_num++) {
 
2445
-    for (sym = 0; sym < nsyms; sym++) {
 
2446
-      if (length[sym] != bit_num) continue;
 
2447
-
 
2448
-      leaf = pos >> 16;
 
2449
-      for (fill = 0; fill < bit_num - nbits; fill++) {
 
2450
-       /* if this path hasn't been taken yet, 'allocate' two entries */
 
2451
-       if (table[leaf] == 0xFFFF) {
 
2452
-         table[(next_symbol << 1)] = 0xFFFF;
 
2453
-         table[(next_symbol << 1) + 1] = 0xFFFF;
 
2454
-         table[leaf] = next_symbol++;
 
2455
-       }
 
2456
-       /* follow the path and select either left or right for next bit */
 
2457
-       leaf = table[leaf] << 1;
 
2458
-       if ((pos >> (15-fill)) & 1) leaf++;
 
2459
-      }
 
2460
-      table[leaf] = sym;
 
2461
-
 
2462
-      if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
 
2463
-    }
 
2464
-    bit_mask >>= 1;
 
2465
-  }
 
2466
-
 
2467
-  /* full table? */
 
2468
-  if (pos == table_mask) return 0;
 
2469
-
 
2470
-  /* either erroneous table, or all elements are 0 - let's find out. */
 
2471
-  for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1;
 
2472
-  return 0;
 
2473
-}
 
2474
-
 
2475
-/* LZX_READ_LENGTHS(tablename, first, last) reads in code lengths for symbols
 
2476
- * first to last in the given table. The code lengths are stored in their
 
2477
- * own special LZX way.
 
2478
- */
 
2479
-#define LZX_READ_LENGTHS(tbl, first, last) do {                            \
 
2480
-  LZX_STORE_BITS;                                                          \
 
2481
-  if (lzx_read_lens(lzx, &lzx->tbl##_len[0], (first),                 \
 
2482
-    (unsigned int)(last))) return lzx->error;                          \
 
2483
-  LZX_RESTORE_BITS;                                                        \
 
2484
-} while (0)
 
2485
-
 
2486
-static int lzx_read_lens(struct lzx_stream *lzx, unsigned char *lens,
 
2487
-                         unsigned int first, unsigned int last)
 
2488
-{
 
2489
-  /* bit buffer and huffman symbol decode variables */
 
2490
-  register unsigned int bit_buffer;
 
2491
-  register int bits_left, i;
 
2492
-  register unsigned short sym;
 
2493
-  unsigned char *i_ptr, *i_end;
 
2494
-
 
2495
-  unsigned int x, y;
 
2496
-  int z;
 
2497
-
 
2498
-  LZX_RESTORE_BITS;
 
2499
-  
 
2500
-  /* read lengths for pretree (20 symbols, lengths stored in fixed 4 bits) */
 
2501
-  for (x = 0; x < 20; x++) {
 
2502
-    LZX_READ_BITS(y, 4);
 
2503
-    lzx->PRETREE_len[x] = y;
 
2504
-  }
 
2505
-  LZX_BUILD_TABLE(PRETREE);
 
2506
-
 
2507
-  for (x = first; x < last; ) {
 
2508
-    LZX_READ_HUFFSYM(PRETREE, z);
 
2509
-    if (z == 17) {
 
2510
-      /* code = 17, run of ([read 4 bits]+4) zeros */
 
2511
-      LZX_READ_BITS(y, 4); y += 4;
 
2512
-      while (y--) lens[x++] = 0;
 
2513
-    }
 
2514
-    else if (z == 18) {
 
2515
-      /* code = 18, run of ([read 5 bits]+20) zeros */
 
2516
-      LZX_READ_BITS(y, 5); y += 20;
 
2517
-      while (y--) lens[x++] = 0;
 
2518
-    }
 
2519
-    else if (z == 19) {
 
2520
-      /* code = 19, run of ([read 1 bit]+4) [read huffman symbol] */
 
2521
-      LZX_READ_BITS(y, 1); y += 4;
 
2522
-      LZX_READ_HUFFSYM(PRETREE, z);
 
2523
-      z = lens[x] - z; if (z < 0) z += 17;
 
2524
-      while (y--) lens[x++] = z;
 
2525
-    }
 
2526
-    else {
 
2527
-      /* code = 0 to 16, delta current length entry */
 
2528
-      z = lens[x] - z; if (z < 0) z += 17;
 
2529
-      lens[x++] = z;
 
2530
-    }
 
2531
-  }
 
2532
-
 
2533
-  LZX_STORE_BITS;
 
2534
-
 
2535
-  return CL_SUCCESS;
 
2536
-}
 
2537
-
 
2538
-static void lzx_reset_state(struct lzx_stream *lzx) {
 
2539
-  int i;
 
2540
-
 
2541
-  lzx->R0              = 1;
 
2542
-  lzx->R1              = 1;
 
2543
-  lzx->R2              = 1;
 
2544
-  lzx->header_read     = 0;
 
2545
-  lzx->block_remaining = 0;
 
2546
-  lzx->block_type      = LZX_BLOCKTYPE_INVALID;
 
2547
-
 
2548
-  /* initialise tables to 0 (because deltas will be applied to them) */
 
2549
-  for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) lzx->MAINTREE_len[i] = 0;
 
2550
-  for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)   lzx->LENGTH_len[i]   = 0;
 
2551
-}
 
2552
-
 
2553
-/*-------- main LZX code --------*/
 
2554
-
 
2555
-struct lzx_stream *lzx_init(int ofd,
 
2556
-                             int window_bits,
 
2557
-                             int reset_interval,
 
2558
-                             int input_buffer_size,
 
2559
-                             off_t output_length,
 
2560
-                             struct cab_file *file,
 
2561
-                             int (*read_cb)(struct cab_file *, unsigned char *, int))
 
2562
-{
 
2563
-  unsigned int window_size = 1 << window_bits;
 
2564
-  struct lzx_stream *lzx;
 
2565
-  int i, j;
 
2566
-
 
2567
-  /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
 
2568
-  if (window_bits < 15 || window_bits > 21) return NULL;
 
2569
-
 
2570
-  input_buffer_size = (input_buffer_size + 1) & -2;
 
2571
-  if (!input_buffer_size) return NULL;
 
2572
-
 
2573
-  /* allocate decompression state */
 
2574
-  if (!(lzx = cli_calloc(1, sizeof(struct lzx_stream)))) {
 
2575
-    return NULL;
 
2576
-  }
 
2577
-
 
2578
-  for (i = 0, j = 0; i < 51; i += 2) {
 
2579
-    lzx->extra_bits[i]   = j; /* 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7... */
 
2580
-    if(i < 50)
 
2581
-       lzx->extra_bits[i+1] = j;
 
2582
-    if ((i != 0) && (j < 17)) j++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */
 
2583
-  }
 
2584
-
 
2585
-  for (i = 0, j = 0; i < 51; i++) {
 
2586
-    lzx->position_base[i] = j; /* 0,1,2,3,4,6,8,12,16,24,32,... */
 
2587
-    j += 1 << lzx->extra_bits[i]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */
 
2588
-  }
 
2589
-
 
2590
-  /* allocate decompression window and input buffer */
 
2591
-  lzx->window = cli_calloc(1, (size_t) window_size);
 
2592
-  if(!lzx->window) {
 
2593
-    free(lzx);
 
2594
-    return NULL;
 
2595
-  }
 
2596
-
 
2597
-  lzx->inbuf  = cli_calloc(1, (size_t) input_buffer_size);
 
2598
-  if (!lzx->inbuf) {
 
2599
-    free(lzx->window);
 
2600
-    free(lzx);
 
2601
-    return NULL;
 
2602
-  }
 
2603
-
 
2604
-  /* initialise decompression state */
 
2605
-  lzx->ofd            = ofd;
 
2606
-  lzx->wflag          = 1;
 
2607
-  lzx->offset          = 0;
 
2608
-  lzx->length          = output_length;
 
2609
-  lzx->file           = file;
 
2610
-  lzx->read_cb        = read_cb;
 
2611
-
 
2612
-  lzx->inbuf_size      = input_buffer_size;
 
2613
-  lzx->window_size     = 1 << window_bits;
 
2614
-  lzx->window_posn     = 0;
 
2615
-  lzx->frame_posn      = 0;
 
2616
-  lzx->frame           = 0;
 
2617
-  lzx->reset_interval  = reset_interval;
 
2618
-  lzx->intel_filesize  = 0;
 
2619
-  lzx->intel_curpos    = 0;
 
2620
-
 
2621
-  /* window bits:    15  16  17  18  19  20  21
 
2622
-   * position slots: 30  32  34  36  38  42  50  */
 
2623
-  lzx->posn_slots      = ((window_bits == 21) ? 50 :
 
2624
-                         ((window_bits == 20) ? 42 : (window_bits << 1)));
 
2625
-  lzx->intel_started   = 0;
 
2626
-  lzx->input_end       = 0;
 
2627
-
 
2628
-  lzx->error = CL_SUCCESS;
 
2629
-
 
2630
-  lzx->i_ptr = lzx->i_end = &lzx->inbuf[0];
 
2631
-  lzx->o_ptr = lzx->o_end = &lzx->e8_buf[0];
 
2632
-  lzx->bit_buffer = lzx->bits_left = 0;
 
2633
-
 
2634
-  lzx_reset_state(lzx);
 
2635
-  return lzx;
 
2636
-}
 
2637
-
 
2638
-void lzx_set_output_length(struct lzx_stream *lzx, off_t out_bytes) {
 
2639
-  if (lzx) lzx->length = out_bytes;
 
2640
-}
 
2641
-
 
2642
-int lzx_decompress(struct lzx_stream *lzx, uint32_t out_bytes) {
 
2643
-  /* bitstream reading and huffman variables */
 
2644
-  register unsigned int bit_buffer;
 
2645
-  register int bits_left, i=0;
 
2646
-  register unsigned short sym;
 
2647
-  unsigned char *i_ptr, *i_end;
 
2648
-
 
2649
-  int match_length, length_footer, extra, verbatim_bits, bytes_todo;
 
2650
-  int this_run, main_element, aligned_bits, j, ret, warned=0;
 
2651
-  unsigned char *window, *runsrc, *rundest, buf[12];
 
2652
-  unsigned int frame_size=0, end_frame, match_offset, window_posn;
 
2653
-  unsigned int R0, R1, R2;
 
2654
-
 
2655
-  /* easy answers */
 
2656
-  if (!lzx) return CL_ENULLARG;
 
2657
-  if (lzx->error) return lzx->error;
 
2658
-
 
2659
-  /* flush out any stored-up bytes before we begin */
 
2660
-  i = lzx->o_end - lzx->o_ptr;
 
2661
-  if (((off_t) i > out_bytes) && ((int) out_bytes >= 0)) i = (int) out_bytes;
 
2662
-  if (i) {
 
2663
-    if (lzx->wflag && (ret = mspack_write(lzx->ofd, lzx->o_ptr, i, lzx->file)) != CL_SUCCESS) {
 
2664
-      return lzx->error = ret;
 
2665
-    }
 
2666
-    lzx->o_ptr  += i;
 
2667
-    lzx->offset += i;
 
2668
-    out_bytes   -= i;
 
2669
-  }
 
2670
-  if (out_bytes == 0) return CL_SUCCESS;
 
2671
-
 
2672
-  /* restore local state */
 
2673
-  LZX_RESTORE_BITS;
 
2674
-  window = lzx->window;
 
2675
-  window_posn = lzx->window_posn;
 
2676
-  R0 = lzx->R0;
 
2677
-  R1 = lzx->R1;
 
2678
-  R2 = lzx->R2;
 
2679
-
 
2680
-  end_frame = (unsigned int)((lzx->offset + out_bytes) / LZX_FRAME_SIZE) + 1;
 
2681
-  cli_dbgmsg("lzx_decompress: end frame = %u\n", end_frame);
 
2682
-
 
2683
-  while (lzx->frame < end_frame) {
 
2684
-    cli_dbgmsg("lzx_decompress: current frame = %u\n", lzx->frame);
 
2685
-    /* have we reached the reset interval? (if there is one?) */
 
2686
-    if (lzx->reset_interval && ((lzx->frame % lzx->reset_interval) == 0)) {
 
2687
-      if (lzx->block_remaining) {
 
2688
-        /* this is a file format error, but we need to extract what we can and scan that */
 
2689
-        cli_dbgmsg("lzx_decompress: %d bytes remaining at reset interval\n", lzx->block_remaining);
 
2690
-        if (!warned) {
 
2691
-          cli_dbgmsg("Detected an invalid reset interval during decompression.\n");
 
2692
-          warned++;
 
2693
-        }
 
2694
-        if (!lzx->header_read) {
 
2695
-          /* cannot continue if no header at all */
 
2696
-          return lzx->error = CL_EFORMAT;
 
2697
-        }
 
2698
-      } else {
 
2699
-        /* re-read the intel header and reset the huffman lengths */
 
2700
-        lzx_reset_state(lzx);
 
2701
-      }
 
2702
-    }
 
2703
-
 
2704
-    /* read header if necessary */
 
2705
-    if (!lzx->header_read) {
 
2706
-      /* read 1 bit. if bit=0, intel filesize = 0.
 
2707
-       * if bit=1, read intel filesize (32 bits) */
 
2708
-      j = 0; LZX_READ_BITS(i, 1); if (i) { LZX_READ_BITS(i, 16); LZX_READ_BITS(j, 16); }
 
2709
-      lzx->intel_filesize = (i << 16) | j;
 
2710
-      lzx->header_read = 1;
 
2711
-    } 
 
2712
-
 
2713
-    /* calculate size of frame: all frames are 32k except the final frame
 
2714
-     * which is 32kb or less. this can only be calculated when lzx->length
 
2715
-     * has been filled in. */
 
2716
-    frame_size = LZX_FRAME_SIZE;
 
2717
-    if (lzx->length && (lzx->length - lzx->offset) < (off_t)frame_size) {
 
2718
-      frame_size = lzx->length - lzx->offset;
 
2719
-    }
 
2720
-
 
2721
-    /* decode until one more frame is available */
 
2722
-    bytes_todo = lzx->frame_posn + frame_size - window_posn;
 
2723
-    while (bytes_todo > 0) {
 
2724
-      /* initialise new block, if one is needed */
 
2725
-      if (lzx->block_remaining == 0) {
 
2726
-       /* realign if previous block was an odd-sized UNCOMPRESSED block */
 
2727
-       if ((lzx->block_type == LZX_BLOCKTYPE_UNCOMPRESSED) &&
 
2728
-           (lzx->block_length & 1))
 
2729
-       {
 
2730
-         if (i_ptr == i_end) {
 
2731
-           if (lzx_read_input(lzx)) return lzx->error;
 
2732
-           i_ptr = lzx->i_ptr;
 
2733
-           i_end = lzx->i_end;
 
2734
-         }
 
2735
-         i_ptr++;
 
2736
-       }
 
2737
-
 
2738
-       /* read block type (3 bits) and block length (24 bits) */
 
2739
-       LZX_READ_BITS(lzx->block_type, 3);
 
2740
-       LZX_READ_BITS(i, 16); LZX_READ_BITS(j, 8);
 
2741
-       lzx->block_remaining = lzx->block_length = (i << 8) | j;
 
2742
-
 
2743
-       /* read individual block headers */
 
2744
-       switch (lzx->block_type) {
 
2745
-       case LZX_BLOCKTYPE_ALIGNED:
 
2746
-         /* read lengths of and build aligned huffman decoding tree */
 
2747
-         for (i = 0; i < 8; i++) { LZX_READ_BITS(j, 3); lzx->ALIGNED_len[i] = j; }
 
2748
-         LZX_BUILD_TABLE(ALIGNED);
 
2749
-         /* no break -- rest of aligned header is same as verbatim */
 
2750
-       case LZX_BLOCKTYPE_VERBATIM:
 
2751
-         /* read lengths of and build main huffman decoding tree */
 
2752
-         LZX_READ_LENGTHS(MAINTREE, 0, 256);
 
2753
-         LZX_READ_LENGTHS(MAINTREE, 256, LZX_NUM_CHARS + (lzx->posn_slots << 3));
 
2754
-         LZX_BUILD_TABLE(MAINTREE);
 
2755
-         /* if the literal 0xE8 is anywhere in the block... */
 
2756
-         if (lzx->MAINTREE_len[0xE8] != 0) lzx->intel_started = 1;
 
2757
-         /* read lengths of and build lengths huffman decoding tree */
 
2758
-         LZX_READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS);
 
2759
-         LZX_BUILD_TABLE(LENGTH);
 
2760
-         break;
 
2761
-
 
2762
-       case LZX_BLOCKTYPE_UNCOMPRESSED:
 
2763
-         /* because we can't assume otherwise */
 
2764
-         lzx->intel_started = 1;
 
2765
-
 
2766
-         /* read 1-16 (not 0-15) bits to align to bytes */
 
2767
-         LZX_ENSURE_BITS(16);
 
2768
-         if (bits_left > 16) i_ptr -= 2;
 
2769
-         bits_left = 0; bit_buffer = 0;
 
2770
-
 
2771
-         /* read 12 bytes of stored R0 / R1 / R2 values */
 
2772
-         for (rundest = &buf[0], i = 0; i < 12; i++) {
 
2773
-           if (i_ptr == i_end) {
 
2774
-             if (lzx_read_input(lzx)) return lzx->error;
 
2775
-             i_ptr = lzx->i_ptr;
 
2776
-             i_end = lzx->i_end;
 
2777
-           }
 
2778
-           *rundest++ = *i_ptr++;
 
2779
-         }
 
2780
-         R0 = buf[0] | (buf[1] << 8) | (buf[2]  << 16) | (buf[3]  << 24);
 
2781
-         R1 = buf[4] | (buf[5] << 8) | (buf[6]  << 16) | (buf[7]  << 24);
 
2782
-         R2 = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
 
2783
-         break;
 
2784
-
 
2785
-       default:
 
2786
-         cli_dbgmsg("lzx_decompress: bad block type (0x%x)\n", lzx->block_type);
 
2787
-         return lzx->error = CL_EFORMAT;
 
2788
-       }
 
2789
-      }
 
2790
-
 
2791
-      /* decode more of the block:
 
2792
-       * run = min(what's available, what's needed) */
 
2793
-      this_run = lzx->block_remaining;
 
2794
-      if (this_run > bytes_todo) this_run = bytes_todo;
 
2795
-
 
2796
-      /* assume we decode exactly this_run bytes, for now */
 
2797
-      bytes_todo           -= this_run;
 
2798
-      lzx->block_remaining -= this_run;
 
2799
-
 
2800
-      /* decode at least this_run bytes */
 
2801
-      switch (lzx->block_type) {
 
2802
-      case LZX_BLOCKTYPE_VERBATIM:
 
2803
-       while (this_run > 0) {
 
2804
-         LZX_READ_HUFFSYM(MAINTREE, main_element);
 
2805
-         if (main_element < LZX_NUM_CHARS) {
 
2806
-           /* literal: 0 to LZX_NUM_CHARS-1 */
 
2807
-           window[window_posn++] = main_element;
 
2808
-           this_run--;
 
2809
-         }
 
2810
-         else {
 
2811
-           /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
 
2812
-           main_element -= LZX_NUM_CHARS;
 
2813
-
 
2814
-           /* get match length */
 
2815
-           match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
 
2816
-           if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
 
2817
-             LZX_READ_HUFFSYM(LENGTH, length_footer);
 
2818
-             match_length += length_footer;
 
2819
-           }
 
2820
-           match_length += LZX_MIN_MATCH;
 
2821
-         
 
2822
-           /* get match offset */
 
2823
-           switch ((match_offset = (main_element >> 3))) {
 
2824
-           case 0: match_offset = R0;                                  break;
 
2825
-           case 1: match_offset = R1; R1=R0;        R0 = match_offset; break;
 
2826
-           case 2: match_offset = R2; R2=R0;        R0 = match_offset; break;
 
2827
-           case 3: match_offset = 1;  R2=R1; R1=R0; R0 = match_offset; break;
 
2828
-           default:
 
2829
-             extra = lzx->extra_bits[match_offset];
 
2830
-             LZX_READ_BITS(verbatim_bits, extra);
 
2831
-             match_offset = lzx->position_base[match_offset] - 2 + verbatim_bits;
 
2832
-             R2 = R1; R1 = R0; R0 = match_offset;
 
2833
-           }
 
2834
-
 
2835
-           if ((window_posn + match_length) > lzx->window_size) {
 
2836
-             cli_dbgmsg("lzx_decompress: match ran over window wrap\n");
 
2837
-             return lzx->error = CL_EFORMAT;
 
2838
-           }
 
2839
-           
 
2840
-           /* copy match */
 
2841
-           rundest = &window[window_posn];
 
2842
-           i = match_length;
 
2843
-           /* does match offset wrap the window? */
 
2844
-           if (match_offset > window_posn) {
 
2845
-             /* j = length from match offset to end of window */
 
2846
-             j = match_offset - window_posn;
 
2847
-             if (j > (int) lzx->window_size) {
 
2848
-               cli_dbgmsg("lzx_decompress: match offset beyond window boundaries\n");
 
2849
-               return lzx->error = CL_EFORMAT;
 
2850
-             }
 
2851
-             runsrc = &window[lzx->window_size - j];
 
2852
-             if (j < i) {
 
2853
-               /* if match goes over the window edge, do two copy runs */
 
2854
-               i -= j; while (j-- > 0) *rundest++ = *runsrc++;
 
2855
-               runsrc = window;
 
2856
-             }
 
2857
-             while (i-- > 0) *rundest++ = *runsrc++;
 
2858
-           }
 
2859
-           else {
 
2860
-             runsrc = rundest - match_offset;
 
2861
-             if(i > (int) (lzx->window_size - window_posn))
 
2862
-               i = lzx->window_size - window_posn;
 
2863
-             while (i-- > 0) *rundest++ = *runsrc++;
 
2864
-           }
 
2865
-
 
2866
-           this_run    -= match_length;
 
2867
-           window_posn += match_length;
 
2868
-         }
 
2869
-       } /* while (this_run > 0) */
 
2870
-       break;
 
2871
-
 
2872
-      case LZX_BLOCKTYPE_ALIGNED:
 
2873
-       while (this_run > 0) {
 
2874
-         LZX_READ_HUFFSYM(MAINTREE, main_element);
 
2875
-         if (main_element < LZX_NUM_CHARS) {
 
2876
-           /* literal: 0 to LZX_NUM_CHARS-1 */
 
2877
-           window[window_posn++] = main_element;
 
2878
-           this_run--;
 
2879
-         }
 
2880
-         else {
 
2881
-           /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
 
2882
-           main_element -= LZX_NUM_CHARS;
 
2883
-
 
2884
-           /* get match length */
 
2885
-           match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
 
2886
-           if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
 
2887
-             LZX_READ_HUFFSYM(LENGTH, length_footer);
 
2888
-             match_length += length_footer;
 
2889
-           }
 
2890
-           match_length += LZX_MIN_MATCH;
 
2891
-
 
2892
-           /* get match offset */
 
2893
-           switch ((match_offset = (main_element >> 3))) {
 
2894
-           case 0: match_offset = R0;                             break;
 
2895
-           case 1: match_offset = R1; R1 = R0; R0 = match_offset; break;
 
2896
-           case 2: match_offset = R2; R2 = R0; R0 = match_offset; break;
 
2897
-           default:
 
2898
-             extra = lzx->extra_bits[match_offset];
 
2899
-             match_offset = lzx->position_base[match_offset] - 2;
 
2900
-             if (extra > 3) {
 
2901
-               /* verbatim and aligned bits */
 
2902
-               extra -= 3;
 
2903
-               LZX_READ_BITS(verbatim_bits, extra);
 
2904
-               match_offset += (verbatim_bits << 3);
 
2905
-               LZX_READ_HUFFSYM(ALIGNED, aligned_bits);
 
2906
-               match_offset += aligned_bits;
 
2907
-             }
 
2908
-             else if (extra == 3) {
 
2909
-               /* aligned bits only */
 
2910
-               LZX_READ_HUFFSYM(ALIGNED, aligned_bits);
 
2911
-               match_offset += aligned_bits;
 
2912
-             }
 
2913
-             else if (extra > 0) { /* extra==1, extra==2 */
 
2914
-               /* verbatim bits only */
 
2915
-               LZX_READ_BITS(verbatim_bits, extra);
 
2916
-               match_offset += verbatim_bits;
 
2917
-             }
 
2918
-             else /* extra == 0 */ {
 
2919
-               /* ??? not defined in LZX specification! */
 
2920
-               match_offset = 1;
 
2921
-             }
 
2922
-             /* update repeated offset LRU queue */
 
2923
-             R2 = R1; R1 = R0; R0 = match_offset;
 
2924
-           }
 
2925
-
 
2926
-           if ((window_posn + match_length) > lzx->window_size) {
 
2927
-             cli_dbgmsg("lzx_decompress: match ran over window wrap\n");
 
2928
-             return lzx->error = CL_EFORMAT;
 
2929
-           }
 
2930
-
 
2931
-           /* copy match */
 
2932
-           rundest = &window[window_posn];
 
2933
-           i = match_length;
 
2934
-           /* does match offset wrap the window? */
 
2935
-           if (match_offset > window_posn) {
 
2936
-             /* j = length from match offset to end of window */
 
2937
-             j = match_offset - window_posn;
 
2938
-             if (j > (int) lzx->window_size) {
 
2939
-               cli_dbgmsg("lzx_decompress: match offset beyond window boundaries\n");
 
2940
-               return lzx->error = CL_EFORMAT;
 
2941
-             }
 
2942
-             runsrc = &window[lzx->window_size - j];
 
2943
-             if (j < i) {
 
2944
-               /* if match goes over the window edge, do two copy runs */
 
2945
-               i -= j; while (j-- > 0) *rundest++ = *runsrc++;
 
2946
-               runsrc = window;
 
2947
-             }
 
2948
-             while (i-- > 0) *rundest++ = *runsrc++;
 
2949
-           }
 
2950
-           else {
 
2951
-             runsrc = rundest - match_offset;
 
2952
-             while (i-- > 0) *rundest++ = *runsrc++;
 
2953
-           }
 
2954
-
 
2955
-           this_run    -= match_length;
 
2956
-           window_posn += match_length;
 
2957
-         }
 
2958
-       } /* while (this_run > 0) */
 
2959
-       break;
 
2960
-
 
2961
-      case LZX_BLOCKTYPE_UNCOMPRESSED:
 
2962
-       /* as this_run is limited not to wrap a frame, this also means it
 
2963
-        * won't wrap the window (as the window is a multiple of 32k) */
 
2964
-       rundest = &window[window_posn];
 
2965
-       window_posn += this_run;
 
2966
-       while (this_run > 0) {
 
2967
-         if ((i = i_end - i_ptr)) {
 
2968
-           if (i > this_run) i = this_run;
 
2969
-           memcpy(rundest, i_ptr, (size_t) i);
 
2970
-           rundest  += i;
 
2971
-           i_ptr    += i;
 
2972
-           this_run -= i;
 
2973
-         }
 
2974
-         else {
 
2975
-           if (lzx_read_input(lzx)) return lzx->error;
 
2976
-           i_ptr = lzx->i_ptr;
 
2977
-           i_end = lzx->i_end;
 
2978
-         }
 
2979
-       }
 
2980
-       break;
 
2981
-
 
2982
-      default:
 
2983
-       return lzx->error = CL_EFORMAT; /* might as well */
 
2984
-      }
 
2985
-
 
2986
-      /* did the final match overrun our desired this_run length? */
 
2987
-      if (this_run < 0) {
 
2988
-       if ((unsigned int)(-this_run) > lzx->block_remaining) {
 
2989
-         cli_dbgmsg("lzx_decompress: overrun went past end of block by %d (%d remaining)\n", -this_run, lzx->block_remaining);
 
2990
-         return lzx->error = CL_EFORMAT;
 
2991
-       }
 
2992
-       lzx->block_remaining -= -this_run;
 
2993
-      }
 
2994
-    } /* while (bytes_todo > 0) */
 
2995
-
 
2996
-    /* streams don't extend over frame boundaries */
 
2997
-    if ((window_posn - lzx->frame_posn) != frame_size) {
 
2998
-      cli_dbgmsg("lzx_decompress: decode beyond output frame limits! %d != %d\n", window_posn - lzx->frame_posn, frame_size);
 
2999
-      return lzx->error = CL_EFORMAT;
 
3000
-    }
 
3001
-
 
3002
-    /* re-align input bitstream */
 
3003
-    if (bits_left > 0) LZX_ENSURE_BITS(16);
 
3004
-    if (bits_left & 15) LZX_REMOVE_BITS(bits_left & 15);
 
3005
-
 
3006
-    /* check that we've used all of the previous frame first */
 
3007
-    if (lzx->o_ptr != lzx->o_end) {
 
3008
-      cli_dbgmsg("lzx_decompress: %ld avail bytes, new %d frame\n", lzx->o_end-lzx->o_ptr, frame_size);
 
3009
-      return lzx->error = CL_EFORMAT;
 
3010
-    }
 
3011
-
 
3012
-    /* does this intel block _really_ need decoding? */
 
3013
-    if (lzx->intel_started && lzx->intel_filesize &&
 
3014
-       (lzx->frame <= 32768) && (frame_size > 10))
 
3015
-    {
 
3016
-      unsigned char *data    = &lzx->e8_buf[0];
 
3017
-      unsigned char *dataend = &lzx->e8_buf[frame_size - 10];
 
3018
-      signed int curpos      = lzx->intel_curpos;
 
3019
-      signed int filesize    = lzx->intel_filesize;
 
3020
-      signed int abs_off, rel_off;
 
3021
-
 
3022
-      /* copy e8 block to the e8 buffer and tweak if needed */
 
3023
-      lzx->o_ptr = data;
 
3024
-      memcpy(data, &lzx->window[lzx->frame_posn], frame_size);
 
3025
-
 
3026
-      while (data < dataend) {
 
3027
-       if (*data++ != 0xE8) { curpos++; continue; }
 
3028
-       abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
 
3029
-       if ((abs_off >= -curpos) && (abs_off < filesize)) {
 
3030
-         rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
 
3031
-         data[0] = (unsigned char) rel_off;
 
3032
-         data[1] = (unsigned char) (rel_off >> 8);
 
3033
-         data[2] = (unsigned char) (rel_off >> 16);
 
3034
-         data[3] = (unsigned char) (rel_off >> 24);
 
3035
-       }
 
3036
-       data += 4;
 
3037
-       curpos += 5;
 
3038
-      }
 
3039
-      lzx->intel_curpos += frame_size;
 
3040
-    }
 
3041
-    else {
 
3042
-      lzx->o_ptr = &lzx->window[lzx->frame_posn];
 
3043
-      if (lzx->intel_filesize) lzx->intel_curpos += frame_size;
 
3044
-    }
 
3045
-    lzx->o_end = &lzx->o_ptr[frame_size];
 
3046
-
 
3047
-    /* write a frame */
 
3048
-    i = (out_bytes < (off_t)frame_size) ? (unsigned int)out_bytes : frame_size;
 
3049
-    if (lzx->wflag && (ret = mspack_write(lzx->ofd, lzx->o_ptr, i, lzx->file)) != CL_SUCCESS) {
 
3050
-      return lzx->error = ret;
 
3051
-    }
 
3052
-    lzx->o_ptr  += i;
 
3053
-    lzx->offset += i;
 
3054
-    out_bytes   -= i;
 
3055
-
 
3056
-    /* advance frame start position */
 
3057
-    lzx->frame_posn += frame_size;
 
3058
-    lzx->frame++;
 
3059
-
 
3060
-    /* wrap window / frame position pointers */
 
3061
-    if (window_posn == lzx->window_size)     window_posn = 0;
 
3062
-    if (lzx->frame_posn == lzx->window_size) lzx->frame_posn = 0;
 
3063
-
 
3064
-  } /* while (lzx->frame < end_frame) */
 
3065
-
 
3066
-  if (out_bytes)
 
3067
-    cli_dbgmsg("lzx_decompress: bytes left to output\n");
 
3068
-
 
3069
-  /* store local state */
 
3070
-  LZX_STORE_BITS;
 
3071
-  lzx->window_posn = window_posn;
 
3072
-  lzx->R0 = R0;
 
3073
-  lzx->R1 = R1;
 
3074
-  lzx->R2 = R2;
 
3075
-
 
3076
-  return CL_SUCCESS;
 
3077
-}
 
3078
-
 
3079
-void lzx_free(struct lzx_stream *lzx) {
 
3080
-  if (lzx) {
 
3081
-    free(lzx->inbuf);
 
3082
-    free(lzx->window);
 
3083
-    free(lzx);
 
3084
-  }
 
3085
-}
 
3086
-
 
3087
-/***************************************************************************
 
3088
- *                      Quantum decompression implementation 
 
3089
- ***************************************************************************
 
3090
- * The Quantum method was created by David Stafford, adapted by Microsoft
 
3091
- * Corporation.
 
3092
- *
 
3093
- * This decompressor is based on an implementation by Matthew Russotto, used
 
3094
- * with permission.
 
3095
- *
 
3096
- * This decompressor was researched and implemented by Matthew Russotto. It
 
3097
- * has since been tidied up by Stuart Caie. More information can be found at
 
3098
- * http://www.speakeasy.org/~russotto/quantumcomp.html
 
3099
- */
 
3100
-
 
3101
-/* Quantum decompressor bitstream reading macros
 
3102
- *
 
3103
- * QTM_STORE_BITS        stores bitstream state in qtm_stream structure
 
3104
- * QTM_RESTORE_BITS      restores bitstream state from qtm_stream structure
 
3105
- * QTM_READ_BITS(var,n)  takes N bits from the buffer and puts them in var
 
3106
- * QTM_FILL_BUFFER       if there is room for another 16 bits, reads another
 
3107
- *                   16 bits from the input stream.
 
3108
- * QTM_PEEK_BITS(n)      extracts without removing N bits from the bit buffer
 
3109
- * QTM_REMOVE_BITS(n)    removes N bits from the bit buffer
 
3110
- *
 
3111
- * These bit access routines work by using the area beyond the MSB and the
 
3112
- * LSB as a free source of zeroes. This avoids having to mask any bits.
 
3113
- * So we have to know the bit width of the bitbuffer variable.
 
3114
- */
 
3115
-
 
3116
-#define QTM_BITBUF_WIDTH (sizeof(unsigned int) * CHAR_BIT)
 
3117
-
 
3118
-#define QTM_STORE_BITS do {                                                 \
 
3119
-  qtm->i_ptr      = i_ptr;                                              \
 
3120
-  qtm->i_end      = i_end;                                              \
 
3121
-  qtm->bit_buffer = bit_buffer;                                         \
 
3122
-  qtm->bits_left  = bits_left;                                          \
 
3123
-} while (0)
 
3124
-
 
3125
-#define QTM_RESTORE_BITS do {                                               \
 
3126
-  i_ptr      = qtm->i_ptr;                                              \
 
3127
-  i_end      = qtm->i_end;                                              \
 
3128
-  bit_buffer = qtm->bit_buffer;                                         \
 
3129
-  bits_left  = qtm->bits_left;                                          \
 
3130
-} while (0)
 
3131
-
 
3132
-/* adds 16 bits to bit buffer, if there's space for the new bits */
 
3133
-#define QTM_FILL_BUFFER do {                                                \
 
3134
-  if (bits_left <= (QTM_BITBUF_WIDTH - 16)) {                               \
 
3135
-    if (i_ptr >= i_end) {                                               \
 
3136
-      if (qtm_read_input(qtm)) return qtm->error;                      \
 
3137
-      i_ptr = qtm->i_ptr;                                               \
 
3138
-      i_end = qtm->i_end;                                               \
 
3139
-    }                                                                   \
 
3140
-    bit_buffer |= ((i_ptr[0] << 8) | i_ptr[1])                          \
 
3141
-                  << (QTM_BITBUF_WIDTH - 16 - bits_left);                   \
 
3142
-    bits_left  += 16;                                                   \
 
3143
-    i_ptr      += 2;                                                    \
 
3144
-  }                                                                     \
 
3145
-} while (0)
 
3146
-
 
3147
-#define QTM_PEEK_BITS(n)   (bit_buffer >> (QTM_BITBUF_WIDTH - (n)))
 
3148
-#define QTM_REMOVE_BITS(n) ((bit_buffer <<= (n)), (bits_left -= (n)))
 
3149
-
 
3150
-#define QTM_READ_BITS(val, bits) do {                                       \
 
3151
-  (val) = 0;                                                            \
 
3152
-  for (bits_needed = (bits); bits_needed > 0; bits_needed -= bit_run) { \
 
3153
-    QTM_FILL_BUFFER;                                                        \
 
3154
-    bit_run = (bits_left < bits_needed) ? bits_left : bits_needed;      \
 
3155
-    (val) = ((val) << bit_run) | QTM_PEEK_BITS(bit_run);                    \
 
3156
-    QTM_REMOVE_BITS(bit_run);                                               \
 
3157
-  }                                                                     \
 
3158
-} while (0)
 
3159
-
 
3160
-static int qtm_read_input(struct qtm_stream *qtm) {
 
3161
-  int nread = qtm->read_cb(qtm->file, &qtm->inbuf[0], (int)qtm->inbuf_size);
 
3162
-  if (nread < 0) {
 
3163
-    if (qtm->file->error == CL_BREAK)
 
3164
-      return qtm->error = CL_BREAK;
 
3165
-    else
 
3166
-      return qtm->error = CL_EFORMAT;
 
3167
-  }
 
3168
-
 
3169
-  if (nread == 0) {
 
3170
-    if (qtm->input_end) {
 
3171
-      cli_dbgmsg("qtm_read_input: out of input bytes\n");
 
3172
-      return qtm->error = CL_EREAD;
 
3173
-    }
 
3174
-    else {
 
3175
-      nread = 2;
 
3176
-      qtm->inbuf[0] = qtm->inbuf[1] = 0;
 
3177
-      qtm->input_end = 1;
 
3178
-    }
 
3179
-  }
 
3180
-
 
3181
-  qtm->i_ptr = &qtm->inbuf[0];
 
3182
-  qtm->i_end = &qtm->inbuf[nread];
 
3183
-  return CL_SUCCESS;
 
3184
-}
 
3185
-
 
3186
-/* Arithmetic decoder:
 
3187
- * 
 
3188
- * QTM_GET_SYMBOL(model, var) fetches the next symbol from the stated model
 
3189
- * and puts it in var.
 
3190
- *
 
3191
- * If necessary, qtm_update_model() is called.
 
3192
- */
 
3193
-#define QTM_GET_SYMBOL(model, var) do {                                     \
 
3194
-  range = ((H - L) & 0xFFFF) + 1;                                       \
 
3195
-  symf = ((((C - L + 1) * model.syms[0].cumfreq)-1) / range) & 0xFFFF;  \
 
3196
-                                                                        \
 
3197
-  for (i = 1; i < model.entries; i++) {                                 \
 
3198
-    if (model.syms[i].cumfreq <= symf) break;                           \
 
3199
-  }                                                                     \
 
3200
-  (var) = model.syms[i-1].sym;                                          \
 
3201
-                                                                        \
 
3202
-  range = (H - L) + 1;                                                  \
 
3203
-  symf = model.syms[0].cumfreq;                                         \
 
3204
-  H = L + ((model.syms[i-1].cumfreq * range) / symf) - 1;               \
 
3205
-  L = L + ((model.syms[i].cumfreq   * range) / symf);                   \
 
3206
-                                                                        \
 
3207
-  do { model.syms[--i].cumfreq += 8; } while (i > 0);                   \
 
3208
-  if (model.syms[0].cumfreq > 3800) qtm_update_model(&model);          \
 
3209
-                                                                        \
 
3210
-  while (1) {                                                           \
 
3211
-    if ((L & 0x8000) != (H & 0x8000)) {                                 \
 
3212
-      if ((L & 0x4000) && !(H & 0x4000)) {                              \
 
3213
-        /* underflow case */                                            \
 
3214
-        C ^= 0x4000; L &= 0x3FFF; H |= 0x4000;                          \
 
3215
-      }                                                                 \
 
3216
-      else break;                                                       \
 
3217
-    }                                                                   \
 
3218
-    L <<= 1; H = (H << 1) | 1;                                          \
 
3219
-    QTM_FILL_BUFFER;                                                        \
 
3220
-    C  = (C << 1) | QTM_PEEK_BITS(1);                                       \
 
3221
-    QTM_REMOVE_BITS(1);                                                     \
 
3222
-  }                                                                     \
 
3223
-} while (0)
 
3224
-
 
3225
-static void qtm_update_model(struct qtm_model *model) {
 
3226
-  struct qtm_modelsym tmp;
 
3227
-  int i, j;
 
3228
-
 
3229
-  if (--model->shiftsleft) {
 
3230
-    for (i = model->entries - 1; i >= 0; i--) {
 
3231
-      /* -1, not -2; the 0 entry saves this */
 
3232
-      model->syms[i].cumfreq >>= 1;
 
3233
-      if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) {
 
3234
-       model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1;
 
3235
-      }
 
3236
-    }
 
3237
-  }
 
3238
-  else {
 
3239
-    model->shiftsleft = 50;
 
3240
-    for (i = 0; i < model->entries; i++) {
 
3241
-      /* no -1, want to include the 0 entry */
 
3242
-      /* this converts cumfreqs into frequencies, then shifts right */
 
3243
-      model->syms[i].cumfreq -= model->syms[i+1].cumfreq;
 
3244
-      model->syms[i].cumfreq++; /* avoid losing things entirely */
 
3245
-      model->syms[i].cumfreq >>= 1;
 
3246
-    }
 
3247
-
 
3248
-    /* now sort by frequencies, decreasing order -- this must be an
 
3249
-     * inplace selection sort, or a sort with the same (in)stability
 
3250
-     * characteristics */
 
3251
-    for (i = 0; i < model->entries - 1; i++) {
 
3252
-      for (j = i + 1; j < model->entries; j++) {
 
3253
-       if (model->syms[i].cumfreq < model->syms[j].cumfreq) {
 
3254
-         tmp = model->syms[i];
 
3255
-         model->syms[i] = model->syms[j];
 
3256
-         model->syms[j] = tmp;
 
3257
-       }
 
3258
-      }
 
3259
-    }
 
3260
-
 
3261
-    /* then convert frequencies back to cumfreq */
 
3262
-    for (i = model->entries - 1; i >= 0; i--) {
 
3263
-      model->syms[i].cumfreq += model->syms[i+1].cumfreq;
 
3264
-    }
 
3265
-  }
 
3266
-}
 
3267
-
 
3268
-/* Initialises a model to decode symbols from [start] to [start]+[len]-1 */
 
3269
-static void qtm_init_model(struct qtm_model *model,
 
3270
-                           struct qtm_modelsym *syms, int start, int len)
 
3271
-{
 
3272
-  int i;
 
3273
-
 
3274
-  model->shiftsleft = 4;
 
3275
-  model->entries    = len;
 
3276
-  model->syms       = syms;
 
3277
-
 
3278
-  for (i = 0; i <= len; i++) {
 
3279
-    syms[i].sym     = start + i; /* actual symbol */
 
3280
-    syms[i].cumfreq = len - i;   /* current frequency of that symbol */
 
3281
-  }
 
3282
-}
 
3283
-
 
3284
-
 
3285
-/*-------- main Quantum code --------*/
 
3286
-
 
3287
-struct qtm_stream *qtm_init(int ofd,
 
3288
-                             int window_bits, int input_buffer_size,
 
3289
-                             struct cab_file *file,
 
3290
-                             int (*read_cb)(struct cab_file *, unsigned char *, int))
 
3291
-{
 
3292
-  unsigned int window_size = 1 << window_bits;
 
3293
-  struct qtm_stream *qtm;
 
3294
-  unsigned offset;
 
3295
-  int i;
 
3296
-
 
3297
-  /* Quantum supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
 
3298
-
 
3299
-  /* tk: temporary fix: only process 32KB+ window sizes */
 
3300
-  if (window_bits < 15 || window_bits > 21) return NULL;
 
3301
-
 
3302
-  input_buffer_size = (input_buffer_size + 1) & -2;
 
3303
-  if (input_buffer_size < 2) return NULL;
 
3304
-
 
3305
-  /* allocate decompression state */
 
3306
-  if (!(qtm = cli_calloc(1, sizeof(struct qtm_stream)))) {
 
3307
-    return NULL;
 
3308
-  }
 
3309
-
 
3310
-  for (i = 0, offset = 0; i < 42; i++) {
 
3311
-    qtm->position_base[i] = offset;
 
3312
-    qtm->extra_bits[i] = ((i < 2) ? 0 : (i - 2)) >> 1;
 
3313
-    offset += 1 << qtm->extra_bits[i];
 
3314
-  }
 
3315
-
 
3316
-  for (i = 0, offset = 0; i < 26; i++) {
 
3317
-    qtm->length_base[i] = offset;
 
3318
-    qtm->length_extra[i] = (i < 2 ? 0 : i - 2) >> 2;
 
3319
-    offset += 1 << qtm->length_extra[i];
 
3320
-  }
 
3321
-  qtm->length_base[26] = 254; qtm->length_extra[26] = 0;
 
3322
-
 
3323
-  /* allocate decompression window and input buffer */
 
3324
-  qtm->window = cli_malloc((size_t) window_size);
 
3325
-  if (!qtm->window) {
 
3326
-      cli_errmsg("qtm_init: Unable to allocate decompression window\n");
 
3327
-    free(qtm);
 
3328
-    return NULL;
 
3329
-  }
 
3330
-
 
3331
-  qtm->inbuf  = cli_malloc((size_t) input_buffer_size);
 
3332
-  if (!qtm->inbuf) {
 
3333
-      cli_errmsg("qtm_init: Unable to allocate input buffer\n");
 
3334
-    free(qtm->window);
 
3335
-    free(qtm);
 
3336
-    return NULL;
 
3337
-  }
 
3338
-
 
3339
-  /* initialise decompression state */
 
3340
-  qtm->ofd        = ofd;
 
3341
-  qtm->wflag      = 1;
 
3342
-  qtm->inbuf_size  = input_buffer_size;
 
3343
-  qtm->window_size = window_size;
 
3344
-  qtm->window_posn = 0;
 
3345
-  qtm->frame_start = 0;
 
3346
-  qtm->header_read = 0;
 
3347
-  qtm->error       = CL_SUCCESS;
 
3348
-
 
3349
-  qtm->i_ptr = qtm->i_end = &qtm->inbuf[0];
 
3350
-  qtm->o_ptr = qtm->o_end = &qtm->window[0];
 
3351
-  qtm->bits_left = 0;
 
3352
-  qtm->bit_buffer = 0;
 
3353
-
 
3354
-  /* initialise arithmetic coding models
 
3355
-   * - model 4    depends on window size, ranges from 20 to 24
 
3356
-   * - model 5    depends on window size, ranges from 20 to 36
 
3357
-   * - model 6pos depends on window size, ranges from 20 to 42
 
3358
-   */
 
3359
-  i = window_bits * 2;
 
3360
-  qtm_init_model(&qtm->model0,    &qtm->m0sym[0],   0, 64);
 
3361
-  qtm_init_model(&qtm->model1,    &qtm->m1sym[0],  64, 64);
 
3362
-  qtm_init_model(&qtm->model2,    &qtm->m2sym[0], 128, 64);
 
3363
-  qtm_init_model(&qtm->model3,    &qtm->m3sym[0], 192, 64);
 
3364
-  qtm_init_model(&qtm->model4,    &qtm->m4sym[0],   0, (i > 24) ? 24 : i);
 
3365
-  qtm_init_model(&qtm->model5,    &qtm->m5sym[0],   0, (i > 36) ? 36 : i);
 
3366
-  qtm_init_model(&qtm->model6,    &qtm->m6sym[0],   0, i);
 
3367
-  qtm_init_model(&qtm->model6len, &qtm->m6lsym[0],  0, 27);
 
3368
-  qtm_init_model(&qtm->model7,    &qtm->m7sym[0],   0, 7);
 
3369
-
 
3370
-  qtm->file = file;
 
3371
-  qtm->read_cb = read_cb;
 
3372
-
 
3373
-  /* all ok */
 
3374
-  return qtm;
 
3375
-}
 
3376
-
 
3377
-int qtm_decompress(struct qtm_stream *qtm, uint32_t out_bytes) {
 
3378
-  unsigned int frame_start, frame_end, window_posn, match_offset, range;
 
3379
-  unsigned char *window, *i_ptr, *i_end, *runsrc, *rundest;
 
3380
-  int i, j, selector, extra, sym, match_length, ret;
 
3381
-  unsigned short H, L, C, symf;
 
3382
-
 
3383
-  register unsigned int bit_buffer;
 
3384
-  register unsigned char bits_left;
 
3385
-  unsigned char bits_needed, bit_run;
 
3386
-
 
3387
-  /* easy answers */
 
3388
-  if (!qtm) return CL_ENULLARG;
 
3389
-  if (qtm->error) return qtm->error;
 
3390
-
 
3391
-  /* flush out any stored-up bytes before we begin */
 
3392
-  i = qtm->o_end - qtm->o_ptr;
 
3393
-  if (((off_t) i > out_bytes) && ((int) out_bytes >= 0)) i = (int) out_bytes;
 
3394
-  if (i) {
 
3395
-    if (qtm->wflag && (ret = mspack_write(qtm->ofd, qtm->o_ptr, i, qtm->file)) != CL_SUCCESS) {
 
3396
-      return qtm->error = ret;
 
3397
-    }
 
3398
-    qtm->o_ptr  += i;
 
3399
-    out_bytes   -= i;
 
3400
-  }
 
3401
-  if (out_bytes == 0) return CL_SUCCESS;
 
3402
-
 
3403
-  /* restore local state */
 
3404
-  QTM_RESTORE_BITS;
 
3405
-  window = qtm->window;
 
3406
-  window_posn = qtm->window_posn;
 
3407
-  frame_start = qtm->frame_start;
 
3408
-  H = qtm->H;
 
3409
-  L = qtm->L;
 
3410
-  C = qtm->C;
 
3411
-
 
3412
-  /* while we do not have enough decoded bytes in reserve: */
 
3413
-  while ((qtm->o_end - qtm->o_ptr) < out_bytes) {
 
3414
-
 
3415
-    /* read header if necessary. Initialises H, L and C */
 
3416
-    if (!qtm->header_read) {
 
3417
-      H = 0xFFFF; L = 0; QTM_READ_BITS(C, 16);
 
3418
-      qtm->header_read = 1;
 
3419
-    }
 
3420
-
 
3421
-    /* decode more, at most up to to frame boundary */
 
3422
-    frame_end = window_posn + (out_bytes - (qtm->o_end - qtm->o_ptr));
 
3423
-    if ((frame_start + QTM_FRAME_SIZE) < frame_end) {
 
3424
-      frame_end = frame_start + QTM_FRAME_SIZE;
 
3425
-    }
 
3426
-    if (frame_end < window_posn) {
 
3427
-       cli_dbgmsg("qtm_decompress: window position beyond end of frame\n");
 
3428
-       return qtm->error = CL_EFORMAT;
 
3429
-    }
 
3430
-
 
3431
-    while (window_posn < frame_end) {
 
3432
-      QTM_GET_SYMBOL(qtm->model7, selector);
 
3433
-      if (selector < 4) {
 
3434
-       struct qtm_model *mdl = (selector == 0) ? &qtm->model0 :
 
3435
-                               ((selector == 1) ? &qtm->model1 :
 
3436
-                               ((selector == 2) ? &qtm->model2 :
 
3437
-                                                   &qtm->model3));
 
3438
-       QTM_GET_SYMBOL((*mdl), sym);
 
3439
-       window[window_posn++] = sym;
 
3440
-      }
 
3441
-      else {
 
3442
-       switch (selector) {
 
3443
-       case 4: /* selector 4 = fixed length match (3 bytes) */
 
3444
-         QTM_GET_SYMBOL(qtm->model4, sym);
 
3445
-         QTM_READ_BITS(extra, qtm->extra_bits[sym]);
 
3446
-         match_offset = qtm->position_base[sym] + extra + 1;
 
3447
-         match_length = 3;
 
3448
-         break;
 
3449
-
 
3450
-       case 5: /* selector 5 = fixed length match (4 bytes) */
 
3451
-         QTM_GET_SYMBOL(qtm->model5, sym);
 
3452
-         QTM_READ_BITS(extra, qtm->extra_bits[sym]);
 
3453
-         match_offset = qtm->position_base[sym] + extra + 1;
 
3454
-         match_length = 4;
 
3455
-         break;
 
3456
-
 
3457
-       case 6: /* selector 6 = variable length match */
 
3458
-         QTM_GET_SYMBOL(qtm->model6len, sym);
 
3459
-         QTM_READ_BITS(extra, qtm->length_extra[sym]);
 
3460
-         match_length = qtm->length_base[sym] + extra + 5;
 
3461
-
 
3462
-         QTM_GET_SYMBOL(qtm->model6, sym);
 
3463
-         QTM_READ_BITS(extra, qtm->extra_bits[sym]);
 
3464
-         match_offset = qtm->position_base[sym] + extra + 1;
 
3465
-         break;
 
3466
-
 
3467
-       default:
 
3468
-         /* should be impossible, model7 can only return 0-6 */
 
3469
-         return qtm->error = CL_EFORMAT;
 
3470
-       }
 
3471
-
 
3472
-       if (window_posn + match_length > qtm->window_size) {
 
3473
-         cli_dbgmsg("qtm_decompress: match ran over window wrap\n");
 
3474
-         return qtm->error = CL_EFORMAT;
 
3475
-       }
 
3476
-
 
3477
-       rundest = &window[window_posn];
 
3478
-       i = match_length;
 
3479
-       /* does match offset wrap the window? */
 
3480
-       if (match_offset > window_posn) {
 
3481
-         /* j = length from match offset to end of window */
 
3482
-         j = match_offset - window_posn;
 
3483
-         if (j > (int) qtm->window_size) {
 
3484
-           cli_dbgmsg("qtm_decompress: match offset beyond window boundaries\n");
 
3485
-           return qtm->error = CL_EFORMAT;
 
3486
-         }
 
3487
-         runsrc = &window[qtm->window_size - j];
 
3488
-         if (j < i) {
 
3489
-           /* if match goes over the window edge, do two copy runs */
 
3490
-           i -= j; while (j-- > 0) *rundest++ = *runsrc++;
 
3491
-           runsrc = window;
 
3492
-         }
 
3493
-         while (i-- > 0) *rundest++ = *runsrc++;
 
3494
-       }
 
3495
-       else {
 
3496
-         runsrc = rundest - match_offset;
 
3497
-         if(i > (int) (qtm->window_size - window_posn))
 
3498
-           i = qtm->window_size - window_posn;
 
3499
-         while (i-- > 0) *rundest++ = *runsrc++;
 
3500
-       }
 
3501
-       window_posn += match_length;
 
3502
-      }
 
3503
-    } /* while (window_posn < frame_end) */
 
3504
-
 
3505
-    qtm->o_end = &window[window_posn];
 
3506
-
 
3507
-    /* another frame completed? */
 
3508
-    if ((window_posn - frame_start) >= QTM_FRAME_SIZE) {
 
3509
-      if ((window_posn - frame_start) != QTM_FRAME_SIZE) {
 
3510
-       cli_dbgmsg("qtm_decompress: overshot frame alignment\n");
 
3511
-       return qtm->error = CL_EFORMAT;
 
3512
-      }
 
3513
-
 
3514
-      /* re-align input */
 
3515
-      if (bits_left & 7) QTM_REMOVE_BITS(bits_left & 7);
 
3516
-      do { QTM_READ_BITS(i, 8); } while (i != 0xFF);
 
3517
-      qtm->header_read = 0;
 
3518
-
 
3519
-      /* window wrap? */
 
3520
-      if (window_posn == qtm->window_size) {
 
3521
-       /* flush all currently stored data */
 
3522
-       i = (qtm->o_end - qtm->o_ptr);
 
3523
-       if(i <= 0)
 
3524
-           break;
 
3525
-       if (qtm->wflag && (ret = mspack_write(qtm->ofd, qtm->o_ptr, i, qtm->file)) != CL_SUCCESS) {
 
3526
-         return qtm->error = ret;
 
3527
-       }
 
3528
-       out_bytes -= i;
 
3529
-       qtm->o_ptr = &window[0];
 
3530
-       qtm->o_end = &window[0];
 
3531
-       window_posn = 0;
 
3532
-      }
 
3533
-
 
3534
-      frame_start = window_posn;
 
3535
-    }
 
3536
-
 
3537
-  } /* while (more bytes needed) */
 
3538
-
 
3539
-  if (out_bytes > 0) {
 
3540
-    i = (int) out_bytes;
 
3541
-    if (qtm->wflag && (ret = mspack_write(qtm->ofd, qtm->o_ptr, i, qtm->file)) != CL_SUCCESS) {
 
3542
-      return qtm->error = ret;
 
3543
-    }
 
3544
-    qtm->o_ptr += i;
 
3545
-  }
 
3546
-
 
3547
-  /* store local state */
 
3548
-  QTM_STORE_BITS;
 
3549
-  qtm->window_posn = window_posn;
 
3550
-  qtm->frame_start = frame_start;
 
3551
-  qtm->H = H;
 
3552
-  qtm->L = L;
 
3553
-  qtm->C = C;
 
3554
-
 
3555
-  return CL_SUCCESS;
 
3556
-}
 
3557
-
 
3558
-void qtm_free(struct qtm_stream *qtm) {
 
3559
-  if (qtm) {
 
3560
-    free(qtm->window);
 
3561
-    free(qtm->inbuf);
 
3562
-    free(qtm);
 
3563
-  }
 
3564
-}
 
3565
diff --git a/libclamav/mspack.h b/libclamav/mspack.h
 
3566
deleted file mode 100644
 
3567
index 0ed472c..0000000
 
3568
--- a/libclamav/mspack.h
 
3569
+++ /dev/null
 
3570
@@ -1,294 +0,0 @@
 
3571
-/*
 
3572
- * This file includes code from libmspack adapted for libclamav by
 
3573
- * tkojm@clamav.net
 
3574
- *
 
3575
- * Copyright (C) 2003-2004 Stuart Caie
 
3576
- *
 
3577
- * This library is free software; you can redistribute it and/or
 
3578
- * modify it under the terms of the GNU Lesser General Public
 
3579
- * License version 2.1 as published by the Free Software Foundation.
 
3580
- *
 
3581
- * This library is distributed in the hope that it will be useful,
 
3582
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
3583
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
3584
- * Lesser General Public License for more details.
 
3585
- * 
 
3586
- * You should have received a copy of the GNU Lesser General Public
 
3587
- * License along with this library; if not, write to the Free Software
 
3588
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 
3589
- * USA
 
3590
- */
 
3591
-
 
3592
-#ifndef __MSPACK_H
 
3593
-#define __MSPACK_H
 
3594
-
 
3595
-#include <sys/types.h>
 
3596
-#include "cab.h"
 
3597
-
 
3598
-
 
3599
-/***************************************************************************
 
3600
- *                      MS-ZIP decompression definitions                  *
 
3601
- ***************************************************************************/
 
3602
-
 
3603
-#define MSZIP_FRAME_SIZE          (32768) /* size of LZ history window */
 
3604
-#define MSZIP_MAX_HUFFBITS        (16)    /* maximum huffman code length */
 
3605
-#define MSZIP_LITERAL_MAXSYMBOLS  (288)   /* literal/length huffman tree */
 
3606
-#define MSZIP_LITERAL_TABLEBITS   (9)
 
3607
-#define MSZIP_DISTANCE_MAXSYMBOLS (32)    /* distance huffman tree */
 
3608
-#define MSZIP_DISTANCE_TABLEBITS  (6)
 
3609
-
 
3610
-/* if there are less direct lookup entries than symbols, the longer
 
3611
- * code pointers will be <= maxsymbols. This must not happen, or we
 
3612
- * will decode entries badly */
 
3613
-#if (1 << MSZIP_LITERAL_TABLEBITS) < (MSZIP_LITERAL_MAXSYMBOLS * 2)
 
3614
-# define MSZIP_LITERAL_TABLESIZE (MSZIP_LITERAL_MAXSYMBOLS * 4)
 
3615
-#else
 
3616
-# define MSZIP_LITERAL_TABLESIZE ((1 << MSZIP_LITERAL_TABLEBITS) + \
 
3617
-                                 (MSZIP_LITERAL_MAXSYMBOLS * 2))
 
3618
-#endif
 
3619
-
 
3620
-#if (1 << MSZIP_DISTANCE_TABLEBITS) < (MSZIP_DISTANCE_MAXSYMBOLS * 2)
 
3621
-# define MSZIP_DISTANCE_TABLESIZE (MSZIP_DISTANCE_MAXSYMBOLS * 4)
 
3622
-#else
 
3623
-# define MSZIP_DISTANCE_TABLESIZE ((1 << MSZIP_DISTANCE_TABLEBITS) + \
 
3624
-                                 (MSZIP_DISTANCE_MAXSYMBOLS * 2))
 
3625
-#endif
 
3626
-
 
3627
-struct mszip_stream {
 
3628
-  int ofd;                  /* output file descriptor */
 
3629
-
 
3630
-  /* inflate() will call this whenever the window should be emptied. */
 
3631
-  int (*flush_window)(struct mszip_stream *, unsigned int);
 
3632
-
 
3633
-  int error, repair_mode, bytes_output, input_end;
 
3634
-
 
3635
-  /* I/O buffering */
 
3636
-  unsigned char *inbuf, *i_ptr, *i_end, *o_ptr, *o_end;
 
3637
-  unsigned int bit_buffer, bits_left, inbuf_size;
 
3638
-
 
3639
-  unsigned int window_posn;             /* offset within window  */
 
3640
-
 
3641
-  /* huffman code lengths */
 
3642
-  unsigned char  LITERAL_len[MSZIP_LITERAL_MAXSYMBOLS];
 
3643
-  unsigned char  DISTANCE_len[MSZIP_DISTANCE_MAXSYMBOLS];
 
3644
-
 
3645
-  /* huffman decoding tables */
 
3646
-  unsigned short LITERAL_table [MSZIP_LITERAL_TABLESIZE];
 
3647
-  unsigned short DISTANCE_table[MSZIP_DISTANCE_TABLESIZE];
 
3648
-
 
3649
-  /* 32kb history window */
 
3650
-  unsigned char window[MSZIP_FRAME_SIZE];
 
3651
-
 
3652
-  /* cabinet related stuff */
 
3653
-  struct cab_file *file;
 
3654
-  int (*read_cb)(struct cab_file *, unsigned char *, int);
 
3655
-
 
3656
-  unsigned char wflag;     /* write flag */
 
3657
-  unsigned int last;        /* prior end of content buffer */
 
3658
-
 
3659
-};
 
3660
-
 
3661
-struct mszip_stream *mszip_init(int ofd,
 
3662
-                                 int input_buffer_size,
 
3663
-                                 int repair_mode,
 
3664
-                                 struct cab_file *file,
 
3665
-                                 int (*read_cb)(struct cab_file *, unsigned char *, int));
 
3666
-
 
3667
-extern int mszip_decompress(struct mszip_stream *zip, uint32_t out_bytes);
 
3668
-
 
3669
-void mszip_free(struct mszip_stream *zip);
 
3670
-
 
3671
-
 
3672
-/***************************************************************************
 
3673
- *                      Quantum decompression definitions                 *
 
3674
- ***************************************************************************/
 
3675
-
 
3676
-/* Quantum compression / decompression definitions */
 
3677
-
 
3678
-#define QTM_FRAME_SIZE (32768)
 
3679
-
 
3680
-struct qtm_modelsym {
 
3681
-  unsigned short sym, cumfreq;
 
3682
-};
 
3683
-
 
3684
-struct qtm_model {
 
3685
-  int shiftsleft, entries;
 
3686
-  struct qtm_modelsym *syms;
 
3687
-};
 
3688
-
 
3689
-struct qtm_stream {
 
3690
-  int ofd;                  /* output file descriptor */
 
3691
-
 
3692
-  unsigned char *window;          /* decoding window                         */
 
3693
-  unsigned int window_size;       /* window size                             */
 
3694
-  unsigned int window_posn;       /* decompression offset within window      */
 
3695
-  unsigned int frame_start;       /* start of current frame within window    */
 
3696
-
 
3697
-  unsigned short H, L, C;         /* high/low/current: arith coding state    */
 
3698
-  unsigned char header_read;      /* have we started decoding a new frame?   */
 
3699
-  unsigned char wflag;     /* write flag */
 
3700
-
 
3701
-  int error, input_end;
 
3702
-
 
3703
-  /* data tables */
 
3704
-  unsigned int  position_base[42];
 
3705
-  unsigned char extra_bits[42], length_base[27], length_extra[27];
 
3706
-
 
3707
-  /* four literal models, each representing 64 symbols
 
3708
-   * model0 for literals from   0 to  63 (selector = 0)
 
3709
-   * model1 for literals from  64 to 127 (selector = 1)
 
3710
-   * model2 for literals from 128 to 191 (selector = 2)
 
3711
-   * model3 for literals from 129 to 255 (selector = 3) */
 
3712
-  struct qtm_model model0, model1, model2, model3;
 
3713
-
 
3714
-  /* three match models.
 
3715
-   * model4 for match with fixed length of 3 bytes
 
3716
-   * model5 for match with fixed length of 4 bytes
 
3717
-   * model6 for variable length match, encoded with model6len model */
 
3718
-  struct qtm_model model4, model5, model6, model6len;
 
3719
-
 
3720
-  /* selector model. 0-6 to say literal (0,1,2,3) or match (4,5,6) */
 
3721
-  struct qtm_model model7;
 
3722
-
 
3723
-  /* symbol arrays for all models */
 
3724
-  struct qtm_modelsym m0sym[64 + 1];
 
3725
-  struct qtm_modelsym m1sym[64 + 1];
 
3726
-  struct qtm_modelsym m2sym[64 + 1];
 
3727
-  struct qtm_modelsym m3sym[64 + 1];
 
3728
-  struct qtm_modelsym m4sym[24 + 1];
 
3729
-  struct qtm_modelsym m5sym[36 + 1];
 
3730
-  struct qtm_modelsym m6sym[42 + 1], m6lsym[27 + 1];
 
3731
-  struct qtm_modelsym m7sym[7 + 1];
 
3732
-
 
3733
-  /* I/O buffers - 1*/
 
3734
-  unsigned int  bit_buffer;
 
3735
-
 
3736
-  /* cabinet related stuff */
 
3737
-  struct cab_file *file;
 
3738
-  int (*read_cb)(struct cab_file *, unsigned char *, int);
 
3739
-
 
3740
-  /* I/O buffers - 2*/
 
3741
-  unsigned char *inbuf, *i_ptr, *i_end, *o_ptr, *o_end;
 
3742
-  unsigned int  inbuf_size;
 
3743
-  unsigned char bits_left;
 
3744
-
 
3745
-};
 
3746
-
 
3747
-extern struct qtm_stream *qtm_init(int ofd,
 
3748
-                                    int window_bits,
 
3749
-                                    int input_buffer_size,
 
3750
-                                    struct cab_file *file,
 
3751
-                                    int (*read_cb)(struct cab_file *, unsigned char *, int));
 
3752
-
 
3753
-extern int qtm_decompress(struct qtm_stream *qtm, uint32_t out_bytes);
 
3754
-
 
3755
-void qtm_free(struct qtm_stream *qtm);
 
3756
-
 
3757
-/***************************************************************************
 
3758
- *                      LZX decompression definitions                     *
 
3759
- ***************************************************************************/
 
3760
-
 
3761
-/* some constants defined by the LZX specification */
 
3762
-#define LZX_MIN_MATCH                (2)
 
3763
-#define LZX_MAX_MATCH                (257)
 
3764
-#define LZX_NUM_CHARS                (256)
 
3765
-#define LZX_BLOCKTYPE_INVALID        (0)   /* also blocktypes 4-7 invalid */
 
3766
-#define LZX_BLOCKTYPE_VERBATIM       (1)
 
3767
-#define LZX_BLOCKTYPE_ALIGNED        (2)
 
3768
-#define LZX_BLOCKTYPE_UNCOMPRESSED   (3)
 
3769
-#define LZX_PRETREE_NUM_ELEMENTS     (20)
 
3770
-#define LZX_ALIGNED_NUM_ELEMENTS     (8)   /* aligned offset tree #elements */
 
3771
-#define LZX_NUM_PRIMARY_LENGTHS      (7)   /* this one missing from spec! */
 
3772
-#define LZX_NUM_SECONDARY_LENGTHS    (249) /* length tree #elements */
 
3773
-
 
3774
-/* LZX huffman defines: tweak tablebits as desired */
 
3775
-#define LZX_PRETREE_MAXSYMBOLS  (LZX_PRETREE_NUM_ELEMENTS)
 
3776
-#define LZX_PRETREE_TABLEBITS   (6)
 
3777
-#define LZX_MAINTREE_MAXSYMBOLS (LZX_NUM_CHARS + 50*8)
 
3778
-#define LZX_MAINTREE_TABLEBITS  (12)
 
3779
-#define LZX_LENGTH_MAXSYMBOLS   (LZX_NUM_SECONDARY_LENGTHS+1)
 
3780
-#define LZX_LENGTH_TABLEBITS    (12)
 
3781
-#define LZX_ALIGNED_MAXSYMBOLS  (LZX_ALIGNED_NUM_ELEMENTS)
 
3782
-#define LZX_ALIGNED_TABLEBITS   (7)
 
3783
-#define LZX_LENTABLE_SAFETY (64)  /* table decoding overruns are allowed */
 
3784
-
 
3785
-#define LZX_FRAME_SIZE (32768) /* the size of a frame in LZX */
 
3786
-
 
3787
-struct lzx_stream {
 
3788
-  int ofd;                       /* output file descriptor                  */
 
3789
-
 
3790
-  off_t   offset;                 /* number of bytes actually output         */
 
3791
-  off_t   length;                 /* overall decompressed length of stream   */
 
3792
-
 
3793
-  unsigned char *window;          /* decoding window                         */
 
3794
-  unsigned int   window_size;     /* window size                             */
 
3795
-  unsigned int   window_posn;     /* decompression offset within window      */
 
3796
-  unsigned int   frame_posn;      /* current frame offset within in window   */
 
3797
-  unsigned int   frame;           /* the number of 32kb frames processed     */
 
3798
-  unsigned int   reset_interval;  /* which frame do we reset the compressor? */
 
3799
-
 
3800
-  unsigned int   R0, R1, R2;      /* for the LRU offset system               */
 
3801
-  unsigned int   block_length;    /* uncompressed length of this LZX block   */
 
3802
-  unsigned int   block_remaining; /* uncompressed bytes still left to decode */
 
3803
-
 
3804
-  signed int     intel_filesize;  /* magic header value used for transform   */
 
3805
-  signed int     intel_curpos;    /* current offset in transform space       */
 
3806
-
 
3807
-  unsigned char  intel_started;   /* has intel E8 decoding started?          */
 
3808
-  unsigned char  block_type;      /* type of the current block               */
 
3809
-  unsigned char  header_read;     /* have we started decoding at all yet?    */
 
3810
-  unsigned char  posn_slots;      /* how many posn slots in stream?          */
 
3811
-
 
3812
-  int error;
 
3813
-
 
3814
-  /* I/O buffering */
 
3815
-  unsigned char *inbuf, *i_ptr, *i_end, *o_ptr, *o_end;
 
3816
-  unsigned int  bit_buffer, bits_left, inbuf_size;
 
3817
-
 
3818
-  /* huffman code lengths */
 
3819
-  unsigned char PRETREE_len  [LZX_PRETREE_MAXSYMBOLS  + LZX_LENTABLE_SAFETY];
 
3820
-  unsigned char MAINTREE_len [LZX_MAINTREE_MAXSYMBOLS + LZX_LENTABLE_SAFETY];
 
3821
-  unsigned char LENGTH_len   [LZX_LENGTH_MAXSYMBOLS   + LZX_LENTABLE_SAFETY];
 
3822
-  unsigned char ALIGNED_len  [LZX_ALIGNED_MAXSYMBOLS  + LZX_LENTABLE_SAFETY];
 
3823
-
 
3824
-  /* huffman decoding tables */
 
3825
-  unsigned short PRETREE_table [(1 << LZX_PRETREE_TABLEBITS) +
 
3826
-                               (LZX_PRETREE_MAXSYMBOLS * 2)];
 
3827
-  unsigned short MAINTREE_table[(1 << LZX_MAINTREE_TABLEBITS) +
 
3828
-                               (LZX_MAINTREE_MAXSYMBOLS * 2)];
 
3829
-  unsigned short LENGTH_table  [(1 << LZX_LENGTH_TABLEBITS) +
 
3830
-                               (LZX_LENGTH_MAXSYMBOLS * 2)];
 
3831
-  unsigned short ALIGNED_table [(1 << LZX_ALIGNED_TABLEBITS) +
 
3832
-                               (LZX_ALIGNED_MAXSYMBOLS * 2)];
 
3833
-  unsigned char  input_end;       /* have we reached the end of input?       */
 
3834
-  unsigned char wflag;           /* write flag */
 
3835
-
 
3836
-  /* this is used purely for doing the intel E8 transform */
 
3837
-  unsigned char  e8_buf[LZX_FRAME_SIZE];
 
3838
-
 
3839
-  unsigned int  position_base[51];
 
3840
-
 
3841
-  /* cabinet related stuff */
 
3842
-  struct cab_file *file;
 
3843
-  int (*read_cb)(struct cab_file *, unsigned char *, int);
 
3844
-
 
3845
-  unsigned char extra_bits[51];
 
3846
-
 
3847
-};
 
3848
-
 
3849
-struct lzx_stream *lzx_init(int ofd,
 
3850
-                             int window_bits,
 
3851
-                             int reset_interval,
 
3852
-                             int input_buffer_size,
 
3853
-                             off_t output_length,
 
3854
-                             struct cab_file *file,
 
3855
-                             int (*read_cb)(struct cab_file *, unsigned char *, int));
 
3856
-
 
3857
-extern void lzx_set_output_length(struct lzx_stream *lzx,
 
3858
-                                  off_t output_length);
 
3859
-
 
3860
-extern int lzx_decompress(struct lzx_stream *lzx, uint32_t out_bytes);
 
3861
-
 
3862
-void lzx_free(struct lzx_stream *lzx);
 
3863
-
 
3864
-#endif
 
3865
diff --git a/libclamav/scanners.c b/libclamav/scanners.c
 
3866
index 7f55da7..9de4f88 100644
 
3867
--- a/libclamav/scanners.c
 
3868
+++ b/libclamav/scanners.c
 
3869
@@ -60,7 +60,7 @@
 
3870
 #include "vba_extract.h"
 
3871
 #include "msexpand.h"
 
3872
 #include "mbox.h"
 
3873
-#include "chmunpack.h"
 
3874
+#include "libmspack.h"
 
3875
 #include "pe.h"
 
3876
 #include "elf.h"
 
3877
 #include "filetypes.h"
 
3878
@@ -73,8 +73,6 @@
 
3879
 #include "sis.h"
 
3880
 #include "pdf.h"
 
3881
 #include "str.h"
 
3882
-#include "mspack.h"
 
3883
-#include "cab.h"
 
3884
 #include "rtf.h"
 
3885
 #include "unarj.h"
 
3886
 #include "nsis/nulsft.h"
 
3887
@@ -853,82 +851,6 @@ static int cli_scanszdd(cli_ctx *ctx)
 
3888
     return ret;
 
3889
 }
 
3890
 
 
3891
-static int cli_scanmscab(cli_ctx *ctx, off_t sfx_offset)
 
3892
-{
 
3893
-       char *tempname;
 
3894
-       int ret;
 
3895
-       unsigned int files = 0;
 
3896
-       struct cab_archive cab;
 
3897
-       struct cab_file *file;
 
3898
-       unsigned int corrupted_input;
 
3899
-       unsigned int viruses_found = 0;
 
3900
-
 
3901
-    cli_dbgmsg("in cli_scanmscab()\n");
 
3902
-
 
3903
-    if((ret = cab_open(*ctx->fmap, sfx_offset, &cab)))
 
3904
-       return ret;
 
3905
-
 
3906
-    for(file = cab.files; file; file = file->next) {
 
3907
-       files++;
 
3908
-
 
3909
-       if(cli_matchmeta(ctx, file->name, 0, file->length, 0, files, 0, NULL) == CL_VIRUS) {
 
3910
-           if (!SCAN_ALL) {
 
3911
-               ret = CL_VIRUS;
 
3912
-               break;
 
3913
-           }
 
3914
-           viruses_found++;
 
3915
-       }
 
3916
-
 
3917
-       if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
 
3918
-           ret = CL_CLEAN;
 
3919
-           break;
 
3920
-       }
 
3921
-
 
3922
-       if(!(tempname = cli_gentemp(ctx->engine->tmpdir))) {
 
3923
-           ret = CL_EMEM;
 
3924
-           break;
 
3925
-       }
 
3926
-
 
3927
-       if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
 
3928
-           file->max_size = ctx->engine->maxscansize - ctx->scansize;
 
3929
-       else
 
3930
-           file->max_size = ctx->engine->maxfilesize ? ctx->engine->maxfilesize : 0xffffffff;
 
3931
-
 
3932
-       cli_dbgmsg("CAB: Extracting file %s to %s, size %u, max_size: %u\n", file->name, tempname, file->length, (unsigned int) file->max_size);
 
3933
-       file->written_size = 0;
 
3934
-       if((ret = cab_extract(file, tempname))) {
 
3935
-           cli_dbgmsg("CAB: Failed to extract file: %s\n", cl_strerror(ret));
 
3936
-       } else {
 
3937
-           corrupted_input = ctx->corrupted_input;
 
3938
-           if(file->length != file->written_size) {
 
3939
-               cli_dbgmsg("CAB: Length from header %u but wrote %u bytes\n", (unsigned int) file->length, (unsigned int) file->written_size);
 
3940
-               ctx->corrupted_input = 1;
 
3941
-           }
 
3942
-           ret = cli_scanfile(tempname, ctx);
 
3943
-           ctx->corrupted_input = corrupted_input;
 
3944
-       }
 
3945
-       if(!ctx->engine->keeptmp) {
 
3946
-           if (!access(tempname, R_OK) && cli_unlink(tempname)) {
 
3947
-               free(tempname);
 
3948
-               ret = CL_EUNLINK;
 
3949
-               break;
 
3950
-           }
 
3951
-       }
 
3952
-       free(tempname);
 
3953
-       if(ret == CL_VIRUS) {
 
3954
-           if (SCAN_ALL)
 
3955
-               viruses_found++;
 
3956
-           else
 
3957
-               break;
 
3958
-       }
 
3959
-    }
 
3960
-
 
3961
-    cab_free(&cab);
 
3962
-    if (viruses_found)
 
3963
-       return CL_VIRUS;
 
3964
-    return ret;
 
3965
-}
 
3966
-
 
3967
 static int vba_scandata(const unsigned char *data, unsigned int len, cli_ctx *ctx)
 
3968
 {
 
3969
        struct cli_matcher *groot = ctx->engine->root[0];
 
3970
@@ -1568,72 +1490,6 @@ static int cli_scantar(cli_ctx *ctx, unsigned int posix)
 
3971
     return ret;
 
3972
 }
 
3973
 
 
3974
-static int cli_scanmschm(cli_ctx *ctx)
 
3975
-{
 
3976
-       int ret = CL_CLEAN, rc;
 
3977
-       chm_metadata_t metadata;
 
3978
-       char *dir;
 
3979
-       unsigned int viruses_found = 0;
 
3980
-
 
3981
-    cli_dbgmsg("in cli_scanmschm()\n");
 
3982
-
 
3983
-     /* generate the temporary directory */
 
3984
-    if(!(dir = cli_gentemp(ctx->engine->tmpdir)))
 
3985
-       return CL_EMEM;
 
3986
-
 
3987
-    if(mkdir(dir, 0700)) {
 
3988
-       cli_dbgmsg("CHM: Can't create temporary directory %s\n", dir);
 
3989
-       free(dir);
 
3990
-       return CL_ETMPDIR;
 
3991
-    }
 
3992
-
 
3993
-    ret = cli_chm_open(dir, &metadata, ctx);
 
3994
-    if (ret != CL_SUCCESS) {
 
3995
-       if(!ctx->engine->keeptmp)
 
3996
-           cli_rmdirs(dir);
 
3997
-       free(dir);
 
3998
-       cli_dbgmsg("CHM: Error: %s\n", cl_strerror(ret));
 
3999
-       return ret;
 
4000
-    }
 
4001
-
 
4002
-   do {
 
4003
-       ret = cli_chm_prepare_file(&metadata);
 
4004
-       if (ret != CL_SUCCESS) {
 
4005
-          break;
 
4006
-       }
 
4007
-       ret = cli_chm_extract_file(dir, &metadata, ctx);
 
4008
-       if (ret == CL_SUCCESS) {
 
4009
-           rc = cli_magic_scandesc(metadata.ofd, ctx);
 
4010
-           close(metadata.ofd);
 
4011
-           if (rc == CL_VIRUS) {
 
4012
-               cli_dbgmsg("CHM: infected with %s\n", cli_get_last_virus(ctx));
 
4013
-               if (SCAN_ALL)
 
4014
-                   viruses_found++;
 
4015
-               else {
 
4016
-                   ret = CL_VIRUS;
 
4017
-                   break;
 
4018
-               }
 
4019
-           }
 
4020
-       }
 
4021
-
 
4022
-    } while(ret == CL_SUCCESS);
 
4023
-
 
4024
-    cli_chm_close(&metadata);
 
4025
-   
 
4026
-    if(!ctx->engine->keeptmp)
 
4027
-       cli_rmdirs(dir);
 
4028
-
 
4029
-    free(dir);
 
4030
-
 
4031
-    cli_dbgmsg("CHM: Exit code: %d\n", ret);
 
4032
-    if (ret == CL_BREAK)
 
4033
-       ret = CL_CLEAN;
 
4034
-
 
4035
-    if (SCAN_ALL && viruses_found)
 
4036
-       return CL_VIRUS;
 
4037
-    return ret;
 
4038
-}
 
4039
-
 
4040
 static int cli_scanscrenc(cli_ctx *ctx)
 
4041
 {
 
4042
        char *tempname;