Coverage Report

Created: 2023-12-08 06:48

/src/clamav/libclammspack/mspack/cabd.c
Line
Count
Source (jump to first uncovered line)
1
/* This file is part of libmspack.
2
 * (C) 2003-2023 Stuart Caie.
3
 *
4
 * libmspack is free software; you can redistribute it and/or modify it under
5
 * the terms of the GNU Lesser General Public License (LGPL) version 2.1
6
 *
7
 * For further details, see the file COPYING.LIB distributed with libmspack
8
 */
9
10
/* Cabinet (.CAB) files are a form of file archive. Each cabinet contains
11
 * "folders", which are compressed spans of data. Each cabinet has
12
 * "files", whose metadata is in the cabinet header, but whose actual data
13
 * is stored compressed in one of the "folders". Cabinets can span more
14
 * than one physical file on disk, in which case they are a "cabinet set",
15
 * and usually the last folder of each cabinet extends into the next
16
 * cabinet.
17
 *
18
 * For a complete description of the format, see the MSDN site:
19
 *   http://msdn.microsoft.com/en-us/library/bb267310.aspx
20
 */
21
22
/* CAB decompression implementation */
23
24
#include <system.h>
25
#include <cab.h>
26
#include <mszip.h>
27
#include <lzx.h>
28
#include <qtm.h>
29
30
/* Notes on compliance with cabinet specification:
31
 *
32
 * One of the main changes between cabextract 0.6 and libmspack's cab
33
 * decompressor is the move from block-oriented decompression to
34
 * stream-oriented decompression.
35
 *
36
 * cabextract would read one data block from disk, decompress it with the
37
 * appropriate method, then write the decompressed data. The CAB
38
 * specification is specifically designed to work like this, as it ensures
39
 * compression matches do not span the maximum decompressed block size
40
 * limit of 32kb.
41
 *
42
 * However, the compression algorithms used are stream oriented, with
43
 * specific hacks added to them to enforce the "individual 32kb blocks"
44
 * rule in CABs. In other file formats, they do not have this limitation.
45
 *
46
 * In order to make more generalised decompressors, libmspack's CAB
47
 * decompressor has moved from being block-oriented to more stream
48
 * oriented. This also makes decompression slightly faster.
49
 *
50
 * However, this leads to incompliance with the CAB specification. The
51
 * CAB controller can no longer ensure each block of input given to the
52
 * decompressors is matched with their output. The "decompressed size" of
53
 * each individual block is thrown away.
54
 *
55
 * Each CAB block is supposed to be seen as individually compressed. This
56
 * means each consecutive data block can have completely different
57
 * "uncompressed" sizes, ranging from 1 to 32768 bytes. However, in
58
 * reality, all data blocks in a folder decompress to exactly 32768 bytes,
59
 * excepting the final block. 
60
 *
61
 * Given this situation, the decompression algorithms are designed to
62
 * realign their input bitstreams on 32768 output-byte boundaries, and
63
 * various other special cases have been made. libmspack will not
64
 * correctly decompress LZX or Quantum compressed folders where the blocks
65
 * do not follow this "32768 bytes until last block" pattern. It could be
66
 * implemented if needed, but hopefully this is not necessary -- it has
67
 * not been seen in over 3Gb of CAB archives.
68
 */
69
70
/* prototypes */
71
static struct mscabd_cabinet * cabd_open(
72
  struct mscab_decompressor *base, const char *filename);
73
static void cabd_close(
74
  struct mscab_decompressor *base, struct mscabd_cabinet *origcab);
75
static int cabd_read_headers(
76
  struct mspack_system *sys, struct mspack_file *fh,
77
  struct mscabd_cabinet_p *cab, off_t offset, int salvage, int quiet);
78
static char *cabd_read_string(
79
  struct mspack_system *sys, struct mspack_file *fh, int permit_empty,
80
  int *error);
81
82
static struct mscabd_cabinet *cabd_search(
83
  struct mscab_decompressor *base, const char *filename);
84
static int cabd_find(
85
  struct mscab_decompressor_p *self, unsigned char *buf,
86
  struct mspack_file *fh, const char *filename, off_t flen,
87
  off_t *firstlen, struct mscabd_cabinet_p **firstcab);
88
89
static int cabd_prepend(
90
  struct mscab_decompressor *base, struct mscabd_cabinet *cab,
91
  struct mscabd_cabinet *prevcab);
92
static int cabd_append(
93
  struct mscab_decompressor *base, struct mscabd_cabinet *cab,
94
  struct mscabd_cabinet *nextcab);
95
static int cabd_merge(
96
  struct mscab_decompressor *base, struct mscabd_cabinet *lcab,
97
  struct mscabd_cabinet *rcab);
98
static int cabd_can_merge_folders(
99
  struct mspack_system *sys, struct mscabd_folder_p *lfol,
100
  struct mscabd_folder_p *rfol);
101
102
static int cabd_extract(
103
  struct mscab_decompressor *base, struct mscabd_file *file,
104
  const char *filename);
105
static int cabd_init_decomp(
106
  struct mscab_decompressor_p *self, unsigned int ct);
107
static void cabd_free_decomp(
108
  struct mscab_decompressor_p *self);
109
static int cabd_sys_read(
110
  struct mspack_file *file, void *buffer, int bytes);
111
static int cabd_sys_write(
112
  struct mspack_file *file, void *buffer, int bytes);
113
static int cabd_sys_read_block(
114
  struct mspack_system *sys, struct mscabd_decompress_state *d, int *out,
115
  int ignore_cksum, int ignore_blocksize);
116
static unsigned int cabd_checksum(
117
  unsigned char *data, unsigned int bytes, unsigned int cksum);
118
static struct noned_state *noned_init(
119
  struct mspack_system *sys, struct mspack_file *in, struct mspack_file *out,
120
  int bufsize);
121
122
static int noned_decompress(
123
  struct noned_state *s, off_t bytes);
124
static void noned_free(
125
  struct noned_state *state);
126
127
static int cabd_param(
128
  struct mscab_decompressor *base, int param, int value);
129
130
static int cabd_error(
131
  struct mscab_decompressor *base);
132
133
134
/***************************************
135
 * MSPACK_CREATE_CAB_DECOMPRESSOR
136
 ***************************************
137
 * constructor
138
 */
139
struct mscab_decompressor *
140
  mspack_create_cab_decompressor(struct mspack_system *sys)
141
436k
{
142
436k
  struct mscab_decompressor_p *self = NULL;
143
144
436k
  if (!sys) sys = mspack_default_system;
145
436k
  if (!mspack_valid_system(sys)) return NULL;
146
147
436k
  if ((self = (struct mscab_decompressor_p *) sys->alloc(sys, sizeof(struct mscab_decompressor_p)))) {
148
436k
    self->base.open       = &cabd_open;
149
436k
    self->base.close      = &cabd_close;
150
436k
    self->base.search     = &cabd_search;
151
436k
    self->base.extract    = &cabd_extract;
152
436k
    self->base.prepend    = &cabd_prepend;
153
436k
    self->base.append     = &cabd_append;
154
436k
    self->base.set_param  = &cabd_param;
155
436k
    self->base.last_error = &cabd_error;
156
436k
    self->system          = sys;
157
436k
    self->d               = NULL;
158
436k
    self->error           = MSPACK_ERR_OK;
159
160
436k
    self->searchbuf_size  = 32768;
161
436k
    self->fix_mszip       = 0;
162
436k
    self->buf_size        = 4096;
163
436k
    self->salvage         = 0;
164
436k
  }
165
436k
  return (struct mscab_decompressor *) self;
166
436k
}
167
168
/***************************************
169
 * MSPACK_DESTROY_CAB_DECOMPRESSOR
170
 ***************************************
171
 * destructor
172
 */
173
436k
void mspack_destroy_cab_decompressor(struct mscab_decompressor *base) {
174
436k
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
175
436k
  if (self) {
176
436k
    struct mspack_system *sys = self->system;
177
436k
    if (self->d) {
178
11.8k
      if (self->d->infh) sys->close(self->d->infh);
179
11.8k
      cabd_free_decomp(self);
180
11.8k
      sys->free(self->d);
181
11.8k
    }
182
436k
    sys->free(self);
183
436k
  }
184
436k
}
185
186
187
/***************************************
188
 * CABD_OPEN
189
 ***************************************
190
 * opens a file and tries to read it as a cabinet file
191
 */
192
static struct mscabd_cabinet *cabd_open(struct mscab_decompressor *base,
193
                                        const char *filename)
194
436k
{
195
436k
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
196
436k
  struct mscabd_cabinet_p *cab = NULL;
197
436k
  struct mspack_system *sys;
198
436k
  struct mspack_file *fh;
199
436k
  int error;
200
201
436k
  if (!base) return NULL;
202
436k
  sys = self->system;
203
204
436k
  if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
205
436k
    if ((cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
206
436k
      cab->base.filename = filename;
207
436k
      error = cabd_read_headers(sys, fh, cab, (off_t) 0, self->salvage, 0);
208
436k
      if (error) {
209
293k
        cabd_close(base, (struct mscabd_cabinet *) cab);
210
293k
        cab = NULL;
211
293k
      }
212
436k
      self->error = error;
213
436k
    }
214
0
    else {
215
0
      self->error = MSPACK_ERR_NOMEMORY;
216
0
    }
217
436k
    sys->close(fh);
218
436k
  }
219
0
  else {
220
0
    self->error = MSPACK_ERR_OPEN;
221
0
  }
222
436k
  return (struct mscabd_cabinet *) cab;
223
436k
}
224
225
/***************************************
226
 * CABD_CLOSE
227
 ***************************************
228
 * frees all memory associated with a given mscabd_cabinet.
229
 */
230
static void cabd_close(struct mscab_decompressor *base,
231
                       struct mscabd_cabinet *origcab)
232
436k
{
233
436k
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
234
436k
  struct mscabd_folder_data *dat, *ndat;
235
436k
  struct mscabd_cabinet *cab, *ncab;
236
436k
  struct mscabd_folder *fol, *nfol;
237
436k
  struct mscabd_file *fi, *nfi;
238
436k
  struct mspack_system *sys;
239
240
436k
  if (!base) return;
241
436k
  sys = self->system;
242
243
436k
  self->error = MSPACK_ERR_OK;
244
245
873k
  while (origcab) {
246
    /* free files */
247
871k
    for (fi = origcab->files; fi; fi = nfi) {
248
434k
      nfi = fi->next;
249
434k
      sys->free(fi->filename);
250
434k
      sys->free(fi);
251
434k
    }
252
253
    /* free folders */
254
32.6M
    for (fol = origcab->folders; fol; fol = nfol) {
255
32.1M
      nfol = fol->next;
256
257
      /* free folder decompression state if it has been decompressed */
258
32.1M
      if (self->d && (self->d->folder == (struct mscabd_folder_p *) fol)) {
259
120k
        if (self->d->infh) sys->close(self->d->infh);
260
120k
        cabd_free_decomp(self);
261
120k
        sys->free(self->d);
262
120k
        self->d = NULL;
263
120k
      }
264
265
      /* free folder data segments */
266
32.1M
      for (dat = ((struct mscabd_folder_p *)fol)->data.next; dat; dat = ndat) {
267
0
        ndat = dat->next;
268
0
        sys->free(dat);
269
0
      }
270
32.1M
      sys->free(fol);
271
32.1M
    }
272
273
    /* free predecessor cabinets (and the original cabinet's strings) */
274
873k
    for (cab = origcab; cab; cab = ncab) {
275
436k
      ncab = cab->prevcab;
276
436k
      sys->free(cab->prevname);
277
436k
      sys->free(cab->nextname);
278
436k
      sys->free(cab->previnfo);
279
436k
      sys->free(cab->nextinfo);
280
436k
      if (cab != origcab) sys->free(cab);
281
436k
    }
282
283
    /* free successor cabinets */
284
436k
    for (cab = origcab->nextcab; cab; cab = ncab) {
285
0
      ncab = cab->nextcab;
286
0
      sys->free(cab->prevname);
287
0
      sys->free(cab->nextname);
288
0
      sys->free(cab->previnfo);
289
0
      sys->free(cab->nextinfo);
290
0
      sys->free(cab);
291
0
    }
292
293
    /* free actual cabinet structure */
294
436k
    cab = origcab->next;
295
436k
    sys->free(origcab);
296
297
    /* repeat full procedure again with the cab->next pointer (if set) */
298
436k
    origcab = cab;
299
436k
  }
300
436k
}
301
302
/***************************************
303
 * CABD_READ_HEADERS
304
 ***************************************
305
 * reads the cabinet file header, folder list and file list.
306
 * fills out a pre-existing mscabd_cabinet structure, allocates memory
307
 * for folders and files as necessary
308
 */
309
static int cabd_read_headers(struct mspack_system *sys,
310
                             struct mspack_file *fh,
311
                             struct mscabd_cabinet_p *cab,
312
                             off_t offset, int salvage, int quiet)
313
436k
{
314
436k
  int num_folders, num_files, folder_resv, i, x, err, fidx;
315
436k
  struct mscabd_folder_p *fol, *linkfol = NULL;
316
436k
  struct mscabd_file *file, *linkfile = NULL;
317
436k
  unsigned char buf[64];
318
319
  /* initialise pointers */
320
436k
  cab->base.next     = NULL;
321
436k
  cab->base.files    = NULL;
322
436k
  cab->base.folders  = NULL;
323
436k
  cab->base.prevcab  = cab->base.nextcab  = NULL;
324
436k
  cab->base.prevname = cab->base.nextname = NULL;
325
436k
  cab->base.previnfo = cab->base.nextinfo = NULL;
326
327
436k
  cab->base.base_offset = offset;
328
329
  /* seek to CFHEADER */
330
436k
  if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) {
331
0
    return MSPACK_ERR_SEEK;
332
0
  }
333
334
  /* read in the CFHEADER */
335
436k
  if (sys->read(fh, &buf[0], cfhead_SIZEOF) != cfhead_SIZEOF) {
336
12.5k
    return MSPACK_ERR_READ;
337
12.5k
  }
338
339
  /* check for "MSCF" signature */
340
424k
  if (EndGetI32(&buf[cfhead_Signature]) != 0x4643534D) {
341
0
    return MSPACK_ERR_SIGNATURE;
342
0
  }
343
344
  /* some basic header fields */
345
424k
  cab->base.length    = EndGetI32(&buf[cfhead_CabinetSize]);
346
424k
  cab->base.set_id    = EndGetI16(&buf[cfhead_SetID]);
347
424k
  cab->base.set_index = EndGetI16(&buf[cfhead_CabinetIndex]);
348
349
  /* get the number of folders */
350
424k
  num_folders = EndGetI16(&buf[cfhead_NumFolders]);
351
424k
  if (num_folders == 0) {
352
36.8k
    if (!quiet) sys->message(fh, "no folders in cabinet.");
353
36.8k
    return MSPACK_ERR_DATAFORMAT;
354
36.8k
  }
355
356
  /* get the number of files */
357
387k
  num_files = EndGetI16(&buf[cfhead_NumFiles]);
358
387k
  if (num_files == 0) {
359
12.3k
    if (!quiet) sys->message(fh, "no files in cabinet.");
360
12.3k
    return MSPACK_ERR_DATAFORMAT;
361
12.3k
  }
362
363
  /* check cabinet version */
364
375k
  if ((buf[cfhead_MajorVersion] != 1) && (buf[cfhead_MinorVersion] != 3)) {
365
309k
    if (!quiet) sys->message(fh, "WARNING; cabinet version is not 1.3");
366
309k
  }
367
368
  /* read the reserved-sizes part of header, if present */
369
375k
  cab->base.flags = EndGetI16(&buf[cfhead_Flags]);
370
371
375k
  if (cab->base.flags & cfheadRESERVE_PRESENT) {
372
82.0k
    if (sys->read(fh, &buf[0], cfheadext_SIZEOF) != cfheadext_SIZEOF) {
373
708
      return MSPACK_ERR_READ;
374
708
    }
375
81.3k
    cab->base.header_resv = EndGetI16(&buf[cfheadext_HeaderReserved]);
376
81.3k
    folder_resv           = buf[cfheadext_FolderReserved];
377
81.3k
    cab->block_resv       = buf[cfheadext_DataReserved];
378
379
81.3k
    if (cab->base.header_resv > 60000) {
380
7.15k
      if (!quiet) sys->message(fh, "WARNING; reserved header > 60000.");
381
7.15k
    }
382
383
    /* skip the reserved header */
384
81.3k
    if (cab->base.header_resv) {
385
68.2k
      if (sys->seek(fh, (off_t) cab->base.header_resv, MSPACK_SYS_SEEK_CUR)) {
386
32.7k
        return MSPACK_ERR_SEEK;
387
32.7k
      }
388
68.2k
    }
389
81.3k
  }
390
293k
  else {
391
293k
    cab->base.header_resv = 0;
392
293k
    folder_resv           = 0; 
393
293k
    cab->block_resv       = 0;
394
293k
  }
395
396
  /* read name and info of preceding cabinet in set, if present */
397
341k
  if (cab->base.flags & cfheadPREV_CABINET) {
398
61.7k
    cab->base.prevname = cabd_read_string(sys, fh, 0, &err);
399
61.7k
    if (err) return err;
400
46.3k
    cab->base.previnfo = cabd_read_string(sys, fh, 1, &err);
401
46.3k
    if (err) return err;
402
46.3k
  }
403
404
  /* read name and info of next cabinet in set, if present */
405
324k
  if (cab->base.flags & cfheadNEXT_CABINET) {
406
56.3k
    cab->base.nextname = cabd_read_string(sys, fh, 0, &err);
407
56.3k
    if (err) return err;
408
34.0k
    cab->base.nextinfo = cabd_read_string(sys, fh, 1, &err);
409
34.0k
    if (err) return err;
410
34.0k
  }
411
412
  /* read folders */
413
32.4M
  for (i = 0; i < num_folders; i++) {
414
32.2M
    if (sys->read(fh, &buf[0], cffold_SIZEOF) != cffold_SIZEOF) {
415
75.0k
      return MSPACK_ERR_READ;
416
75.0k
    }
417
32.1M
    if (folder_resv) {
418
1.74M
      if (sys->seek(fh, (off_t) folder_resv, MSPACK_SYS_SEEK_CUR)) {
419
4.91k
        return MSPACK_ERR_SEEK;
420
4.91k
      }
421
1.74M
    }
422
423
32.1M
    if (!(fol = (struct mscabd_folder_p *) sys->alloc(sys, sizeof(struct mscabd_folder_p)))) {
424
0
      return MSPACK_ERR_NOMEMORY;
425
0
    }
426
32.1M
    fol->base.next       = NULL;
427
32.1M
    fol->base.comp_type  = EndGetI16(&buf[cffold_CompType]);
428
32.1M
    fol->base.num_blocks = EndGetI16(&buf[cffold_NumBlocks]);
429
32.1M
    fol->data.next       = NULL;
430
32.1M
    fol->data.cab        = (struct mscabd_cabinet_p *) cab;
431
32.1M
    fol->data.offset     = offset + (off_t)
432
32.1M
      ( (unsigned int) EndGetI32(&buf[cffold_DataOffset]) );
433
32.1M
    fol->merge_prev      = NULL;
434
32.1M
    fol->merge_next      = NULL;
435
436
    /* link folder into list of folders */
437
32.1M
    if (!linkfol) cab->base.folders = (struct mscabd_folder *) fol;
438
31.8M
    else linkfol->base.next = (struct mscabd_folder *) fol;
439
32.1M
    linkfol = fol;
440
32.1M
  }
441
442
  /* read files */
443
2.12M
  for (i = 0; i < num_files; i++) {
444
1.95M
    if (sys->read(fh, &buf[0], cffile_SIZEOF) != cffile_SIZEOF) {
445
53.5k
      return MSPACK_ERR_READ;
446
53.5k
    }
447
448
1.90M
    if (!(file = (struct mscabd_file *) sys->alloc(sys, sizeof(struct mscabd_file)))) {
449
0
      return MSPACK_ERR_NOMEMORY;
450
0
    }
451
452
1.90M
    file->next     = NULL;
453
1.90M
    file->length   = EndGetI32(&buf[cffile_UncompressedSize]);
454
1.90M
    file->attribs  = EndGetI16(&buf[cffile_Attribs]);
455
1.90M
    file->offset   = EndGetI32(&buf[cffile_FolderOffset]);
456
457
    /* set folder pointer */
458
1.90M
    fidx = EndGetI16(&buf[cffile_FolderIndex]);
459
1.90M
    if (fidx < cffileCONTINUED_FROM_PREV) {
460
      /* normal folder index; count up to the correct folder */
461
1.82M
      if (fidx < num_folders) {
462
666k
        struct mscabd_folder *ifol = cab->base.folders;
463
249M
        while (fidx--) if (ifol) ifol = ifol->next;
464
666k
        file->folder = ifol;
465
666k
      }
466
1.15M
      else {
467
1.15M
        D(("invalid folder index"))
468
1.15M
        file->folder = NULL;
469
1.15M
      }
470
1.82M
    }
471
81.0k
    else {
472
      /* either CONTINUED_TO_NEXT, CONTINUED_FROM_PREV or
473
       * CONTINUED_PREV_AND_NEXT */
474
81.0k
      if ((fidx == cffileCONTINUED_TO_NEXT) ||
475
81.0k
          (fidx == cffileCONTINUED_PREV_AND_NEXT))
476
80.2k
      {
477
        /* get last folder */
478
80.2k
        struct mscabd_folder *ifol = cab->base.folders;
479
13.5M
        while (ifol->next) ifol = ifol->next;
480
80.2k
        file->folder = ifol;
481
482
        /* set "merge next" pointer */
483
80.2k
        fol = (struct mscabd_folder_p *) ifol;
484
80.2k
        if (!fol->merge_next) fol->merge_next = file;
485
80.2k
      }
486
487
81.0k
      if ((fidx == cffileCONTINUED_FROM_PREV) ||
488
81.0k
          (fidx == cffileCONTINUED_PREV_AND_NEXT))
489
70.7k
      {
490
        /* get first folder */
491
70.7k
        file->folder = cab->base.folders;
492
493
        /* set "merge prev" pointer */
494
70.7k
        fol = (struct mscabd_folder_p *) file->folder;
495
70.7k
        if (!fol->merge_prev) fol->merge_prev = file;
496
70.7k
      }
497
81.0k
    }
498
499
    /* get time */
500
1.90M
    x = EndGetI16(&buf[cffile_Time]);
501
1.90M
    file->time_h = x >> 11;
502
1.90M
    file->time_m = (x >> 5) & 0x3F;
503
1.90M
    file->time_s = (x << 1) & 0x3E;
504
505
    /* get date */
506
1.90M
    x = EndGetI16(&buf[cffile_Date]);
507
1.90M
    file->date_d = x & 0x1F;
508
1.90M
    file->date_m = (x >> 5) & 0xF;
509
1.90M
    file->date_y = (x >> 9) + 1980;
510
511
    /* get filename */
512
1.90M
    file->filename = cabd_read_string(sys, fh, 0, &err);
513
514
    /* if folder index or filename are bad, either skip it or fail */
515
1.90M
    if (err || !file->folder) {
516
1.47M
      sys->free(file->filename);
517
1.47M
      sys->free(file);
518
1.47M
      if (salvage) continue;
519
0
      return err ? err : MSPACK_ERR_DATAFORMAT;
520
1.47M
    }
521
522
    /* link file entry into file list */
523
434k
    if (!linkfile) cab->base.files = file;
524
253k
    else linkfile->next = file;
525
434k
    linkfile = file;
526
434k
  }
527
528
167k
  if (cab->base.files == NULL) {
529
    /* We never actually added any files to the file list.  Something went wrong.
530
     * The file header may have been invalid */
531
24.0k
    D(("No files found, even though header claimed to have %d files", num_files))
532
24.0k
    return MSPACK_ERR_DATAFORMAT;
533
24.0k
  }
534
535
143k
  return MSPACK_ERR_OK;
536
167k
}
537
538
static char *cabd_read_string(struct mspack_system *sys,
539
                              struct mspack_file *fh, int permit_empty,
540
                              int *error)
541
2.10M
{
542
2.10M
  off_t base = sys->tell(fh);
543
2.10M
  char buf[256], *str;
544
2.10M
  int len, i, ok;
545
546
  /* read up to 256 bytes */
547
2.10M
  if ((len = sys->read(fh, &buf[0], 256)) <= 0) {
548
1.25k
    *error = MSPACK_ERR_READ;
549
1.25k
    return NULL;
550
1.25k
  }
551
552
  /* search for a null terminator in the buffer */
553
42.8M
  for (i = 0, ok = 0; i < len; i++) if (!buf[i]) { ok = 1; break; }
554
  /* optionally reject empty strings */
555
2.10M
  if (i == 0 && !permit_empty) ok = 0;
556
557
2.10M
  if (!ok) {
558
675k
    *error = MSPACK_ERR_DATAFORMAT;
559
675k
    return NULL;
560
675k
  }
561
562
1.42M
  len = i + 1;
563
564
  /* set the data stream to just after the string and return */
565
1.42M
  if (sys->seek(fh, base + (off_t)len, MSPACK_SYS_SEEK_START)) {
566
0
    *error = MSPACK_ERR_SEEK;
567
0
    return NULL;
568
0
  }
569
570
1.42M
  if (!(str = (char *) sys->alloc(sys, len))) {
571
0
    *error = MSPACK_ERR_NOMEMORY;
572
0
    return NULL;
573
0
  }
574
575
1.42M
  sys->copy(&buf[0], str, len);
576
1.42M
  *error = MSPACK_ERR_OK;
577
1.42M
  return str;
578
1.42M
}
579
    
580
/***************************************
581
 * CABD_SEARCH, CABD_FIND
582
 ***************************************
583
 * cabd_search opens a file, finds its extent, allocates a search buffer,
584
 * then reads through the whole file looking for possible cabinet headers.
585
 * if it finds any, it tries to read them as real cabinets. returns a linked
586
 * list of results
587
 *
588
 * cabd_find is the inner loop of cabd_search, to make it easier to
589
 * break out of the loop and be sure that all resources are freed
590
 */
591
static struct mscabd_cabinet *cabd_search(struct mscab_decompressor *base,
592
                                          const char *filename)
593
0
{
594
0
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
595
0
  struct mscabd_cabinet_p *cab = NULL;
596
0
  struct mspack_system *sys;
597
0
  unsigned char *search_buf;
598
0
  struct mspack_file *fh;
599
0
  off_t filelen, firstlen = 0;
600
601
0
  if (!base) return NULL;
602
0
  sys = self->system;
603
604
  /* allocate a search buffer */
605
0
  search_buf = (unsigned char *) sys->alloc(sys, (size_t) self->searchbuf_size);
606
0
  if (!search_buf) {
607
0
    self->error = MSPACK_ERR_NOMEMORY;
608
0
    return NULL;
609
0
  }
610
611
  /* open file and get its full file length */
612
0
  if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
613
0
    if (!(self->error = mspack_sys_filelen(sys, fh, &filelen))) {
614
0
      self->error = cabd_find(self, search_buf, fh, filename,
615
0
                              filelen, &firstlen, &cab);
616
0
    }
617
618
    /* truncated / extraneous data warning: */
619
0
    if (firstlen && (firstlen != filelen) &&
620
0
        (!cab || (cab->base.base_offset == 0)))
621
0
    {
622
0
      if (firstlen < filelen) {
623
0
        sys->message(fh, "WARNING; possible %" LD
624
0
                     " extra bytes at end of file.",
625
0
                     filelen - firstlen);
626
0
      }
627
0
      else {
628
0
        sys->message(fh, "WARNING; file possibly truncated by %" LD " bytes.",
629
0
                     firstlen - filelen);
630
0
      }
631
0
    }
632
    
633
0
    sys->close(fh);
634
0
  }
635
0
  else {
636
0
    self->error = MSPACK_ERR_OPEN;
637
0
  }
638
639
  /* free the search buffer */
640
0
  sys->free(search_buf);
641
642
0
  return (struct mscabd_cabinet *) cab;
643
0
}
644
645
static int cabd_find(struct mscab_decompressor_p *self, unsigned char *buf,
646
                     struct mspack_file *fh, const char *filename, off_t flen,
647
                     off_t *firstlen, struct mscabd_cabinet_p **firstcab)
648
0
{
649
0
  struct mscabd_cabinet_p *cab, *link = NULL;
650
0
  off_t caboff, offset, length;
651
0
  struct mspack_system *sys = self->system;
652
0
  unsigned char *p, *pend, state = 0;
653
0
  unsigned int cablen_u32 = 0, foffset_u32 = 0;
654
0
  int false_cabs = 0;
655
656
#if SIZEOF_OFF_T < 8
657
  /* detect 32-bit off_t overflow */
658
  if (flen < 0) {
659
    sys->message(fh, "library not compiled to support large files.");
660
    return MSPACK_ERR_OK;
661
  }
662
#endif
663
664
  /* search through the full file length */
665
0
  for (offset = 0; offset < flen; offset += length) {
666
    /* search length is either the full length of the search buffer, or the
667
     * amount of data remaining to the end of the file, whichever is less. */
668
0
    length = flen - offset;
669
0
    if (length > self->searchbuf_size) {
670
0
      length = self->searchbuf_size;
671
0
    }
672
673
    /* fill the search buffer with data from disk */
674
0
    if (sys->read(fh, &buf[0], (int) length) != (int) length) {
675
0
      return MSPACK_ERR_READ;
676
0
    }
677
678
    /* FAQ avoidance strategy */
679
0
    if ((offset == 0) && (EndGetI32(&buf[0]) == 0x28635349)) {
680
0
      sys->message(fh, "WARNING; found InstallShield header. Use unshield "
681
0
                   "(https://github.com/twogood/unshield) to unpack this file"); 
682
0
    }
683
684
    /* read through the entire buffer. */
685
0
    for (p = &buf[0], pend = &buf[length]; p < pend; ) {
686
0
      switch (state) {
687
        /* starting state */
688
0
      case 0:
689
        /* we spend most of our time in this while loop, looking for
690
         * a leading 'M' of the 'MSCF' signature */
691
0
        while (p < pend && *p != 0x4D) p++;
692
        /* if we found tht 'M', advance state */
693
0
        if (p++ < pend) state = 1;
694
0
        break;
695
696
      /* verify that the next 3 bytes are 'S', 'C' and 'F' */
697
0
      case 1: state = (*p++ == 0x53) ? 2 : 0; break;
698
0
      case 2: state = (*p++ == 0x43) ? 3 : 0; break;
699
0
      case 3: state = (*p++ == 0x46) ? 4 : 0; break;
700
701
      /* we don't care about bytes 4-7 (see default: for action) */
702
703
      /* bytes 8-11 are the overall length of the cabinet */
704
0
      case 8:  cablen_u32  = *p++;       state++; break;
705
0
      case 9:  cablen_u32 |= *p++ << 8;  state++; break;
706
0
      case 10: cablen_u32 |= *p++ << 16; state++; break;
707
0
      case 11: cablen_u32 |= *p++ << 24; state++; break;
708
709
      /* we don't care about bytes 12-15 (see default: for action) */
710
711
      /* bytes 16-19 are the offset within the cabinet of the filedata */
712
0
      case 16: foffset_u32  = *p++;       state++; break;
713
0
      case 17: foffset_u32 |= *p++ << 8;  state++; break;
714
0
      case 18: foffset_u32 |= *p++ << 16; state++; break;
715
0
      case 19: foffset_u32 |= *p++ << 24;
716
        /* now we have received 20 bytes of potential cab header. work out
717
         * the offset in the file of this potential cabinet */
718
0
        caboff = offset + (p - &buf[0]) - 20;
719
720
        /* should reading cabinet fail, restart search just after 'MSCF' */
721
0
        offset = caboff + 4;
722
723
        /* capture the "length of cabinet" field if there is a cabinet at
724
         * offset 0 in the file, regardless of whether the cabinet can be
725
         * read correctly or not */
726
0
        if (caboff == 0) *firstlen = (off_t) cablen_u32;
727
728
        /* check that the files offset is less than the alleged length of
729
         * the cabinet, and that the offset + the alleged length are
730
         * 'roughly' within the end of overall file length. In salvage
731
         * mode, don't check the alleged length, allow it to be garbage */
732
0
        if ((foffset_u32 < cablen_u32) &&
733
0
            ((caboff + (off_t) foffset_u32) < (flen + 32)) &&
734
0
            (((caboff + (off_t) cablen_u32)  < (flen + 32)) || self->salvage))
735
0
        {
736
          /* likely cabinet found -- try reading it */
737
0
          if (!(cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
738
0
            return MSPACK_ERR_NOMEMORY;
739
0
          }
740
0
          cab->base.filename = filename;
741
0
          if (cabd_read_headers(sys, fh, cab, caboff, self->salvage, 1)) {
742
            /* destroy the failed cabinet */
743
0
            cabd_close((struct mscab_decompressor *) self,
744
0
                       (struct mscabd_cabinet *) cab);
745
0
            false_cabs++;
746
0
          }
747
0
          else {
748
            /* cabinet read correctly! */
749
750
            /* link the cab into the list */
751
0
            if (!link) *firstcab = cab;
752
0
            else link->base.next = (struct mscabd_cabinet *) cab;
753
0
            link = cab;
754
755
            /* cause the search to restart after this cab's data. */
756
0
            offset = caboff + (off_t) cablen_u32;
757
758
#if SIZEOF_OFF_T < 8
759
            /* detect 32-bit off_t overflow */
760
            if (offset < caboff) {
761
              sys->message(fh, "library not compiled to support large files.");
762
              return MSPACK_ERR_OK;
763
            }
764
#endif        
765
0
          }
766
0
        }
767
768
        /* restart search */
769
0
        if (offset >= flen) return MSPACK_ERR_OK;
770
0
        if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) {
771
0
          return MSPACK_ERR_SEEK;
772
0
        }
773
0
        length = 0;
774
0
        p = pend;
775
0
        state = 0;
776
0
        break;
777
778
      /* for bytes 4-7 and 12-15, just advance state/pointer */
779
0
      default:
780
0
        p++, state++;
781
0
      } /* switch(state) */
782
0
    } /* for (... p < pend ...) */
783
0
  } /* for (... offset < length ...) */
784
785
0
  if (false_cabs) {
786
0
    D(("%d false cabinets found", false_cabs))
787
0
  }
788
789
0
  return MSPACK_ERR_OK;
790
0
}
791
                                             
792
/***************************************
793
 * CABD_MERGE, CABD_PREPEND, CABD_APPEND
794
 ***************************************
795
 * joins cabinets together, also merges split folders between these two
796
 * cabinets only. This includes freeing the duplicate folder and file(s)
797
 * and allocating a further mscabd_folder_data structure to append to the
798
 * merged folder's data parts list.
799
 */
800
static int cabd_prepend(struct mscab_decompressor *base,
801
                        struct mscabd_cabinet *cab,
802
                        struct mscabd_cabinet *prevcab)
803
0
{
804
0
  return cabd_merge(base, prevcab, cab);
805
0
}
806
807
static int cabd_append(struct mscab_decompressor *base,
808
                        struct mscabd_cabinet *cab,
809
                        struct mscabd_cabinet *nextcab)
810
0
{
811
0
  return cabd_merge(base, cab, nextcab);
812
0
}
813
814
static int cabd_merge(struct mscab_decompressor *base,
815
                      struct mscabd_cabinet *lcab,
816
                      struct mscabd_cabinet *rcab)
817
0
{
818
0
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
819
0
  struct mscabd_folder_data *data, *ndata;
820
0
  struct mscabd_folder_p *lfol, *rfol;
821
0
  struct mscabd_file *fi, *rfi, *lfi;
822
0
  struct mscabd_cabinet *cab;
823
0
  struct mspack_system *sys;
824
825
0
  if (!self) return MSPACK_ERR_ARGS;
826
0
  sys = self->system;
827
828
  /* basic args check */
829
0
  if (!lcab || !rcab || (lcab == rcab)) {
830
0
    D(("lcab NULL, rcab NULL or lcab = rcab"))
831
0
    return self->error = MSPACK_ERR_ARGS;
832
0
  }
833
834
  /* check there's not already a cabinet attached */
835
0
  if (lcab->nextcab || rcab->prevcab) {
836
0
    D(("cabs already joined"))
837
0
    return self->error = MSPACK_ERR_ARGS;
838
0
  }
839
840
  /* do not create circular cabinet chains */
841
0
  for (cab = lcab->prevcab; cab; cab = cab->prevcab) {
842
0
    if (cab == rcab) {D(("circular!")) return self->error = MSPACK_ERR_ARGS;}
843
0
  }
844
0
  for (cab = rcab->nextcab; cab; cab = cab->nextcab) {
845
0
    if (cab == lcab) {D(("circular!")) return self->error = MSPACK_ERR_ARGS;}
846
0
  }
847
848
  /* warn about odd set IDs or indices */
849
0
  if (lcab->set_id != rcab->set_id) {
850
0
    sys->message(NULL, "WARNING; merged cabinets with differing Set IDs.");
851
0
  }
852
853
0
  if (lcab->set_index > rcab->set_index) {
854
0
    sys->message(NULL, "WARNING; merged cabinets with odd order.");
855
0
  }
856
857
  /* merging the last folder in lcab with the first folder in rcab */
858
0
  lfol = (struct mscabd_folder_p *) lcab->folders;
859
0
  rfol = (struct mscabd_folder_p *) rcab->folders;
860
0
  while (lfol->base.next) lfol = (struct mscabd_folder_p *) lfol->base.next;
861
862
  /* do we need to merge folders? */
863
0
  if (!lfol->merge_next && !rfol->merge_prev) {
864
    /* no, at least one of the folders is not for merging */
865
866
    /* attach cabs */
867
0
    lcab->nextcab = rcab;
868
0
    rcab->prevcab = lcab;
869
870
    /* attach folders */
871
0
    lfol->base.next = (struct mscabd_folder *) rfol;
872
873
    /* attach files */
874
0
    fi = lcab->files;
875
0
    while (fi->next) fi = fi->next;
876
0
    fi->next = rcab->files;
877
0
  }
878
0
  else {
879
    /* folder merge required - do the files match? */
880
0
    if (! cabd_can_merge_folders(sys, lfol, rfol)) {
881
0
      return self->error = MSPACK_ERR_DATAFORMAT;
882
0
    }
883
884
    /* allocate a new folder data structure */
885
0
    if (!(data = (struct mscabd_folder_data *) sys->alloc(sys, sizeof(struct mscabd_folder_data)))) {
886
0
      return self->error = MSPACK_ERR_NOMEMORY;
887
0
    }
888
889
    /* attach cabs */
890
0
    lcab->nextcab = rcab;
891
0
    rcab->prevcab = lcab;
892
893
    /* append rfol's data to lfol */
894
0
    ndata = &lfol->data;
895
0
    while (ndata->next) ndata = ndata->next;
896
0
    ndata->next = data;
897
0
    *data = rfol->data;
898
0
    rfol->data.next = NULL;
899
900
    /* lfol becomes rfol.
901
     * NOTE: special case, don't merge if rfol is merge prev and next,
902
     * rfol->merge_next is going to be deleted, so keep lfol's version
903
     * instead */
904
0
    lfol->base.num_blocks += rfol->base.num_blocks - 1;
905
0
    if ((rfol->merge_next == NULL) ||
906
0
        (rfol->merge_next->folder != (struct mscabd_folder *) rfol))
907
0
    {
908
0
      lfol->merge_next = rfol->merge_next;
909
0
    }
910
911
    /* attach the rfol's folder (except the merge folder) */
912
0
    while (lfol->base.next) lfol = (struct mscabd_folder_p *) lfol->base.next;
913
0
    lfol->base.next = rfol->base.next;
914
915
    /* free disused merge folder */
916
0
    sys->free(rfol);
917
918
    /* attach rfol's files */
919
0
    fi = lcab->files;
920
0
    while (fi->next) fi = fi->next;
921
0
    fi->next = rcab->files;
922
923
    /* delete all files from rfol's merge folder */
924
0
    lfi = NULL;
925
0
    for (fi = lcab->files; fi ; fi = rfi) {
926
0
      rfi = fi->next;
927
      /* if file's folder matches the merge folder, unlink and free it */
928
0
      if (fi->folder == (struct mscabd_folder *) rfol) {
929
0
        if (lfi) lfi->next = rfi; else lcab->files = rfi;
930
0
        sys->free(fi->filename);
931
0
        sys->free(fi);
932
0
      }
933
0
      else lfi = fi;
934
0
    }
935
0
  }
936
937
  /* all done! fix files and folders pointers in all cabs so they all
938
   * point to the same list  */
939
0
  for (cab = lcab->prevcab; cab; cab = cab->prevcab) {
940
0
    cab->files   = lcab->files;
941
0
    cab->folders = lcab->folders;
942
0
  }
943
944
0
  for (cab = lcab->nextcab; cab; cab = cab->nextcab) {
945
0
    cab->files   = lcab->files;
946
0
    cab->folders = lcab->folders;
947
0
  }
948
949
0
  return self->error = MSPACK_ERR_OK;
950
0
}
951
952
/* decides if two folders are OK to merge */
953
static int cabd_can_merge_folders(struct mspack_system *sys,
954
                                  struct mscabd_folder_p *lfol,
955
                                  struct mscabd_folder_p *rfol)
956
0
{
957
0
    struct mscabd_file *lfi, *rfi, *l, *r;
958
0
    int matching = 1;
959
960
    /* check that both folders use the same compression method/settings */
961
0
    if (lfol->base.comp_type != rfol->base.comp_type) {
962
0
        D(("folder merge: compression type mismatch"))
963
0
        return 0;
964
0
    }
965
966
    /* check there are not too many data blocks after merging */
967
0
    if ((lfol->base.num_blocks + rfol->base.num_blocks) > CAB_FOLDERMAX) {
968
0
        D(("folder merge: too many data blocks in merged folders"))
969
0
        return 0;
970
0
    }
971
972
0
    if (!(lfi = lfol->merge_next) || !(rfi = rfol->merge_prev)) {
973
0
        D(("folder merge: one cabinet has no files to merge"))
974
0
        return 0;
975
0
    }
976
977
    /* for all files in lfol (which is the last folder in whichever cab and
978
     * only has files to merge), compare them to the files from rfol. They
979
     * should be identical in number and order. to verify this, check the
980
     * offset and length of each file. */
981
0
    for (l=lfi, r=rfi; l; l=l->next, r=r->next) {
982
0
        if (!r || (l->offset != r->offset) || (l->length != r->length)) {
983
0
            matching = 0;
984
0
            break;
985
0
        }
986
0
    }
987
988
0
    if (matching) return 1;
989
990
    /* if rfol does not begin with an identical copy of the files in lfol, make
991
     * make a judgement call; if at least ONE file from lfol is in rfol, allow
992
     * the merge with a warning about missing files. */
993
0
    matching = 0;
994
0
    for (l = lfi; l; l = l->next) {
995
0
        for (r = rfi; r; r = r->next) {
996
0
            if (l->offset == r->offset && l->length == r->length) break;
997
0
        }
998
0
        if (r) matching = 1; else sys->message(NULL,
999
0
            "WARNING; merged file %s not listed in both cabinets", l->filename);
1000
0
    }
1001
0
    return matching;
1002
0
}
1003
1004
1005
/***************************************
1006
 * CABD_EXTRACT
1007
 ***************************************
1008
 * extracts a file from a cabinet
1009
 */
1010
static int cabd_extract(struct mscab_decompressor *base,
1011
                        struct mscabd_file *file, const char *filename)
1012
241k
{
1013
241k
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1014
241k
  struct mscabd_folder_p *fol;
1015
241k
  struct mspack_system *sys;
1016
241k
  struct mspack_file *fh;
1017
241k
  unsigned int filelen;
1018
1019
241k
  if (!self) return MSPACK_ERR_ARGS;
1020
241k
  if (!file) return self->error = MSPACK_ERR_ARGS;
1021
1022
241k
  sys = self->system;
1023
241k
  fol = (struct mscabd_folder_p *) file->folder;
1024
1025
  /* if offset is beyond 2GB, nothing can be extracted */
1026
241k
  if (file->offset > CAB_LENGTHMAX) {
1027
21.2k
    return self->error = MSPACK_ERR_DATAFORMAT;
1028
21.2k
  }
1029
1030
  /* if file claims to go beyond 2GB either error out,
1031
   * or in salvage mode reduce file length so it fits 2GB limit
1032
   */
1033
220k
  filelen = file->length;
1034
220k
  if (filelen > (CAB_LENGTHMAX - file->offset)) {
1035
49.3k
    if (self->salvage) {
1036
49.3k
      filelen = CAB_LENGTHMAX - file->offset;
1037
49.3k
    }
1038
0
    else {
1039
0
      return self->error = MSPACK_ERR_DATAFORMAT;
1040
0
    }
1041
49.3k
  }
1042
1043
  /* extraction impossible if no folder, or folder needs predecessor */
1044
220k
  if (!fol || fol->merge_prev) {
1045
23.1k
    sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
1046
23.1k
                 "cabinet set is incomplete", file->filename);
1047
23.1k
    return self->error = MSPACK_ERR_DECRUNCH;
1048
23.1k
  }
1049
1050
  /* if file goes beyond what can be decoded, given an error.
1051
   * In salvage mode, don't assume block sizes, just try decoding
1052
   */
1053
197k
  if (!self->salvage) {
1054
0
    unsigned int maxlen = fol->base.num_blocks * CAB_BLOCKMAX;
1055
0
    if (file->offset > maxlen || filelen > (maxlen - file->offset)) {
1056
0
      sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
1057
0
                   "cabinet set is incomplete", file->filename);
1058
0
      return self->error = MSPACK_ERR_DECRUNCH;
1059
0
    }
1060
0
  }
1061
1062
  /* allocate generic decompression state */
1063
197k
  if (!self->d) {
1064
132k
    self->d = (struct mscabd_decompress_state *) sys->alloc(sys, sizeof(struct mscabd_decompress_state));
1065
132k
    if (!self->d) return self->error = MSPACK_ERR_NOMEMORY;
1066
132k
    self->d->folder     = NULL;
1067
132k
    self->d->data       = NULL;
1068
132k
    self->d->sys        = *sys;
1069
132k
    self->d->sys.read   = &cabd_sys_read;
1070
132k
    self->d->sys.write  = &cabd_sys_write;
1071
132k
    self->d->state      = NULL;
1072
132k
    self->d->infh       = NULL;
1073
132k
    self->d->incab      = NULL;
1074
132k
  }
1075
1076
  /* do we need to change folder or reset the current folder? */
1077
197k
  if ((self->d->folder != fol) || (self->d->offset > file->offset) ||
1078
197k
      !self->d->state)
1079
171k
  {
1080
    /* free any existing decompressor */
1081
171k
    cabd_free_decomp(self);
1082
1083
    /* do we need to open a new cab file? */
1084
171k
    if (!self->d->infh || (fol->data.cab != self->d->incab)) {
1085
      /* close previous file handle if from a different cab */
1086
133k
      if (self->d->infh) sys->close(self->d->infh);
1087
133k
      self->d->incab = fol->data.cab;
1088
133k
      self->d->infh = sys->open(sys, fol->data.cab->base.filename,
1089
133k
                                MSPACK_SYS_OPEN_READ);
1090
133k
      if (!self->d->infh) return self->error = MSPACK_ERR_OPEN;
1091
133k
    }
1092
    /* seek to start of data blocks */
1093
171k
    if (sys->seek(self->d->infh, fol->data.offset, MSPACK_SYS_SEEK_START)) {
1094
15.7k
      return self->error = MSPACK_ERR_SEEK;
1095
15.7k
    }
1096
1097
    /* set up decompressor */
1098
155k
    if (cabd_init_decomp(self, (unsigned int) fol->base.comp_type)) {
1099
11.3k
      return self->error;
1100
11.3k
    }
1101
1102
    /* initialise new folder state */
1103
144k
    self->d->folder = fol;
1104
144k
    self->d->data   = &fol->data;
1105
144k
    self->d->offset = 0;
1106
144k
    self->d->block  = 0;
1107
144k
    self->d->outlen = 0;
1108
144k
    self->d->i_ptr = self->d->i_end = &self->d->input[0];
1109
1110
    /* read_error lasts for the lifetime of a decompressor */
1111
144k
    self->read_error = MSPACK_ERR_OK;
1112
144k
  }
1113
1114
  /* open file for output */
1115
170k
  if (!(fh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) {
1116
0
    return self->error = MSPACK_ERR_OPEN;
1117
0
  }
1118
1119
170k
  self->error = MSPACK_ERR_OK;
1120
1121
  /* if file has more than 0 bytes */
1122
170k
  if (filelen) {
1123
160k
    off_t bytes;
1124
160k
    int error;
1125
    /* get to correct offset.
1126
     * - use NULL fh to say 'no writing' to cabd_sys_write()
1127
     * - if cabd_sys_read() has an error, it will set self->read_error
1128
     *   and pass back MSPACK_ERR_READ
1129
     */
1130
160k
    self->d->outfh = NULL;
1131
160k
    if ((bytes = file->offset - self->d->offset)) {
1132
133k
        error = self->d->decompress(self->d->state, bytes);
1133
133k
        self->error = (error == MSPACK_ERR_READ) ? self->read_error : error;
1134
133k
    }
1135
1136
    /* if getting to the correct offset was error free, unpack file */
1137
160k
    if (!self->error) {
1138
108k
      self->d->outfh = fh;
1139
108k
      error = self->d->decompress(self->d->state, filelen);
1140
108k
      self->error = (error == MSPACK_ERR_READ) ? self->read_error : error;
1141
108k
    }
1142
160k
  }
1143
1144
  /* close output file */
1145
170k
  sys->close(fh);
1146
170k
  self->d->outfh = NULL;
1147
1148
170k
  return self->error;
1149
170k
}
1150
1151
/***************************************
1152
 * CABD_INIT_DECOMP, CABD_FREE_DECOMP
1153
 ***************************************
1154
 * cabd_init_decomp initialises decompression state, according to which
1155
 * decompression method was used. relies on self->d->folder being the same
1156
 * as when initialised.
1157
 *
1158
 * cabd_free_decomp frees decompression state, according to which method
1159
 * was used.
1160
 */
1161
static int cabd_init_decomp(struct mscab_decompressor_p *self, unsigned int ct)
1162
155k
{
1163
155k
  struct mspack_file *fh = (struct mspack_file *) self;
1164
1165
155k
  self->d->comp_type = ct;
1166
1167
155k
  switch (ct & cffoldCOMPTYPE_MASK) {
1168
8.71k
  case cffoldCOMPTYPE_NONE:
1169
8.71k
    self->d->decompress = (int (*)(void *, off_t)) &noned_decompress;
1170
8.71k
    self->d->state = noned_init(&self->d->sys, fh, fh, self->buf_size);
1171
8.71k
    break;
1172
40.1k
  case cffoldCOMPTYPE_MSZIP:
1173
40.1k
    self->d->decompress = (int (*)(void *, off_t)) &mszipd_decompress;
1174
40.1k
    self->d->state = mszipd_init(&self->d->sys, fh, fh, self->buf_size,
1175
40.1k
                                 self->fix_mszip);
1176
40.1k
    break;
1177
69.9k
  case cffoldCOMPTYPE_QUANTUM:
1178
69.9k
    self->d->decompress = (int (*)(void *, off_t)) &qtmd_decompress;
1179
69.9k
    self->d->state = qtmd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f,
1180
69.9k
                               self->buf_size);
1181
69.9k
    break;
1182
34.2k
  case cffoldCOMPTYPE_LZX:
1183
34.2k
    self->d->decompress = (int (*)(void *, off_t)) &lzxd_decompress;
1184
34.2k
    self->d->state = lzxd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f, 0,
1185
34.2k
                               self->buf_size, (off_t)0,0);
1186
34.2k
    break;
1187
2.51k
  default:
1188
2.51k
    return self->error = MSPACK_ERR_DATAFORMAT;
1189
155k
  }
1190
153k
  return self->error = (self->d->state) ? MSPACK_ERR_OK : MSPACK_ERR_NOMEMORY;
1191
155k
}
1192
1193
303k
static void cabd_free_decomp(struct mscab_decompressor_p *self) {
1194
303k
  if (!self || !self->d || !self->d->state) return;
1195
1196
144k
  switch (self->d->comp_type & cffoldCOMPTYPE_MASK) {
1197
8.71k
  case cffoldCOMPTYPE_NONE:    noned_free((struct noned_state *) self->d->state);   break;
1198
40.1k
  case cffoldCOMPTYPE_MSZIP:   mszipd_free((struct mszipd_stream *) self->d->state);  break;
1199
62.6k
  case cffoldCOMPTYPE_QUANTUM: qtmd_free((struct qtmd_stream *) self->d->state);    break;
1200
32.7k
  case cffoldCOMPTYPE_LZX:     lzxd_free((struct lzxd_stream *) self->d->state);    break;
1201
144k
  }
1202
144k
  self->d->decompress = NULL;
1203
144k
  self->d->state      = NULL;
1204
144k
}
1205
1206
/***************************************
1207
 * CABD_SYS_READ, CABD_SYS_WRITE
1208
 ***************************************
1209
 * cabd_sys_read is the internal reader function which the decompressors
1210
 * use. will read data blocks (and merge split blocks) from the cabinet
1211
 * and serve the read bytes to the decompressors
1212
 *
1213
 * cabd_sys_write is the internal writer function which the decompressors
1214
 * use. it either writes data to disk (self->d->outfh) with the real
1215
 * sys->write() function, or does nothing with the data when
1216
 * self->d->outfh == NULL. advances self->d->offset
1217
 */
1218
330k
static int cabd_sys_read(struct mspack_file *file, void *buffer, int bytes) {
1219
330k
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) file;
1220
330k
  unsigned char *buf = (unsigned char *) buffer;
1221
330k
  struct mspack_system *sys = self->system;
1222
330k
  int avail, todo, outlen, ignore_cksum, ignore_blocksize;
1223
1224
330k
  ignore_cksum = self->salvage ||
1225
330k
    (self->fix_mszip && 
1226
0
     ((self->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_MSZIP));
1227
330k
  ignore_blocksize = self->salvage;
1228
1229
330k
  todo = bytes;
1230
633k
  while (todo > 0) {
1231
593k
    avail = self->d->i_end - self->d->i_ptr;
1232
1233
    /* if out of input data, read a new block */
1234
593k
    if (avail) {
1235
      /* copy as many input bytes available as possible */
1236
168k
      if (avail > todo) avail = todo;
1237
168k
      sys->copy(self->d->i_ptr, buf, (size_t) avail);
1238
168k
      self->d->i_ptr += avail;
1239
168k
      buf  += avail;
1240
168k
      todo -= avail;
1241
168k
    }
1242
424k
    else {
1243
      /* out of data, read a new block */
1244
1245
      /* check if we're out of input blocks, advance block counter */
1246
424k
      if (self->d->block++ >= self->d->folder->base.num_blocks) {
1247
257k
        if (!self->salvage) {
1248
0
          self->read_error = MSPACK_ERR_DATAFORMAT;
1249
0
        }
1250
257k
        else {
1251
257k
          D(("Ran out of CAB input blocks prematurely"))
1252
257k
        }
1253
257k
        break;
1254
257k
      }
1255
1256
      /* read a block */
1257
167k
      self->read_error = cabd_sys_read_block(sys, self->d, &outlen,
1258
167k
        ignore_cksum, ignore_blocksize);
1259
167k
      if (self->read_error) return -1;
1260
134k
      self->d->outlen += outlen;
1261
1262
      /* special Quantum hack -- trailer byte to allow the decompressor
1263
       * to realign itself. CAB Quantum blocks, unlike LZX blocks, can have
1264
       * anything from 0 to 4 trailing null bytes. */
1265
134k
      if ((self->d->comp_type & cffoldCOMPTYPE_MASK)==cffoldCOMPTYPE_QUANTUM) {
1266
57.7k
        *self->d->i_end++ = 0xFF;
1267
57.7k
      }
1268
1269
      /* is this the last block? */
1270
134k
      if (self->d->block >= self->d->folder->base.num_blocks) {
1271
105k
        if ((self->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_LZX) {
1272
          /* special LZX hack -- on the last block, inform LZX of the
1273
           * size of the output data stream. */
1274
28.7k
          lzxd_set_output_length((struct lzxd_stream *) self->d->state, self->d->outlen);
1275
28.7k
        }
1276
105k
      }
1277
134k
    } /* if (avail) */
1278
593k
  } /* while (todo > 0) */
1279
297k
  return bytes - todo;
1280
330k
}
1281
1282
24.2M
static int cabd_sys_write(struct mspack_file *file, void *buffer, int bytes) {
1283
24.2M
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) file;
1284
24.2M
  self->d->offset += bytes;
1285
24.2M
  if (self->d->outfh) {
1286
12.5M
    return self->system->write(self->d->outfh, buffer, bytes);
1287
12.5M
  }
1288
11.6M
  return bytes;
1289
24.2M
}
1290
1291
/***************************************
1292
 * CABD_SYS_READ_BLOCK
1293
 ***************************************
1294
 * reads a whole data block from a cab file. the block may span more than
1295
 * one cab file, if it does then the fragments will be reassembled
1296
 */
1297
static int cabd_sys_read_block(struct mspack_system *sys,
1298
                               struct mscabd_decompress_state *d,
1299
                               int *out, int ignore_cksum,
1300
                               int ignore_blocksize)
1301
167k
{
1302
167k
  unsigned char hdr[cfdata_SIZEOF];
1303
167k
  unsigned int cksum;
1304
167k
  int len, full_len;
1305
1306
  /* reset the input block pointer and end of block pointer */
1307
167k
  d->i_ptr = d->i_end = &d->input[0];
1308
1309
167k
  do {
1310
    /* read the block header */
1311
167k
    if (sys->read(d->infh, &hdr[0], cfdata_SIZEOF) != cfdata_SIZEOF) {
1312
1.56k
      return MSPACK_ERR_READ;
1313
1.56k
    }
1314
1315
    /* skip any reserved block headers */
1316
165k
    if (d->data->cab->block_resv &&
1317
165k
        sys->seek(d->infh, (off_t) d->data->cab->block_resv,
1318
796
                  MSPACK_SYS_SEEK_CUR))
1319
15
    {
1320
15
      return MSPACK_ERR_SEEK;
1321
15
    }
1322
1323
    /* blocks must not be over CAB_INPUTMAX in size */
1324
165k
    len = EndGetI16(&hdr[cfdata_CompressedSize]);
1325
165k
    full_len = (d->i_end - d->i_ptr) + len; /* include cab-spanning blocks */
1326
165k
    if (full_len > CAB_INPUTMAX) {
1327
6.49k
      D(("block size %d > CAB_INPUTMAX", full_len));
1328
      /* in salvage mode, blocks can be 65535 bytes but no more than that */
1329
6.49k
      if (!ignore_blocksize || full_len > CAB_INPUTMAX_SALVAGE) {
1330
0
          return MSPACK_ERR_DATAFORMAT;
1331
0
      }
1332
6.49k
    }
1333
1334
     /* blocks must not expand to more than CAB_BLOCKMAX */
1335
165k
    if (EndGetI16(&hdr[cfdata_UncompressedSize]) > CAB_BLOCKMAX) {
1336
33.7k
      D(("block size > CAB_BLOCKMAX"))
1337
33.7k
      if (!ignore_blocksize) return MSPACK_ERR_DATAFORMAT;
1338
33.7k
    }
1339
1340
    /* read the block data */
1341
165k
    if (sys->read(d->infh, d->i_end, len) != len) {
1342
25.5k
      return MSPACK_ERR_READ;
1343
25.5k
    }
1344
1345
    /* perform checksum test on the block (if one is stored) */
1346
140k
    if ((cksum = EndGetI32(&hdr[cfdata_CheckSum]))) {
1347
134k
      unsigned int sum2 = cabd_checksum(d->i_end, (unsigned int) len, 0);
1348
134k
      if (cabd_checksum(&hdr[4], 4, sum2) != cksum) {
1349
134k
        if (!ignore_cksum) return MSPACK_ERR_CHECKSUM;
1350
134k
        sys->message(d->infh, "WARNING; bad block checksum found");
1351
134k
      }
1352
134k
    }
1353
1354
    /* advance end of block pointer to include newly read data */
1355
140k
    d->i_end += len;
1356
1357
    /* uncompressed size == 0 means this block was part of a split block
1358
     * and it continues as the first block of the next cabinet in the set.
1359
     * otherwise, this is the last part of the block, and no more block
1360
     * reading needs to be done.
1361
     */
1362
    /* EXIT POINT OF LOOP -- uncompressed size != 0 */
1363
140k
    if ((*out = EndGetI16(&hdr[cfdata_UncompressedSize]))) {
1364
134k
      return MSPACK_ERR_OK;
1365
134k
    }
1366
1367
    /* otherwise, advance to next cabinet */
1368
1369
    /* close current file handle */
1370
5.61k
    sys->close(d->infh);
1371
5.61k
    d->infh = NULL;
1372
1373
    /* advance to next member in the cabinet set */
1374
5.61k
    if (!(d->data = d->data->next)) {
1375
5.61k
      sys->message(d->infh, "WARNING; ran out of cabinets in set. Are any missing?");
1376
5.61k
      return MSPACK_ERR_DATAFORMAT;
1377
5.61k
    }
1378
1379
    /* open next cab file */
1380
0
    d->incab = d->data->cab;
1381
0
    if (!(d->infh = sys->open(sys, d->incab->base.filename,
1382
0
                              MSPACK_SYS_OPEN_READ)))
1383
0
    {
1384
0
      return MSPACK_ERR_OPEN;
1385
0
    }
1386
1387
    /* seek to start of data blocks */
1388
0
    if (sys->seek(d->infh, d->data->offset, MSPACK_SYS_SEEK_START)) {
1389
0
      return MSPACK_ERR_SEEK;
1390
0
    }
1391
0
  } while (1);
1392
1393
  /* not reached */
1394
0
  return MSPACK_ERR_OK;
1395
167k
}
1396
1397
static unsigned int cabd_checksum(unsigned char *data, unsigned int bytes,
1398
                                  unsigned int cksum)
1399
268k
{
1400
268k
  unsigned int len, ul = 0;
1401
1402
54.5M
  for (len = bytes >> 2; len--; data += 4) {
1403
54.2M
    cksum ^= EndGetI32(data);
1404
54.2M
  }
1405
1406
268k
  switch (bytes & 3) {
1407
59.1k
  case 3: ul |= *data++ << 16; /*@fallthrough@*/
1408
79.6k
  case 2: ul |= *data++ <<  8; /*@fallthrough@*/
1409
93.1k
  case 1: ul |= *data;
1410
268k
  }
1411
268k
  cksum ^= ul;
1412
1413
268k
  return cksum;
1414
268k
}
1415
1416
/***************************************
1417
 * NONED_INIT, NONED_DECOMPRESS, NONED_FREE
1418
 ***************************************
1419
 * the "not compressed" method decompressor
1420
 */
1421
struct noned_state {
1422
  struct mspack_system *sys;
1423
  struct mspack_file *i;
1424
  struct mspack_file *o;
1425
  unsigned char *buf;
1426
  int bufsize;
1427
};
1428
1429
static struct noned_state *noned_init(struct mspack_system *sys,
1430
                                      struct mspack_file *in,
1431
                                      struct mspack_file *out,
1432
                                      int bufsize)
1433
8.71k
{
1434
8.71k
  struct noned_state *state = (struct noned_state *) sys->alloc(sys, sizeof(struct noned_state));
1435
8.71k
  unsigned char *buf = (unsigned char *) sys->alloc(sys, (size_t) bufsize);
1436
8.71k
  if (state && buf) {
1437
8.71k
    state->sys     = sys;
1438
8.71k
    state->i       = in;
1439
8.71k
    state->o       = out;
1440
8.71k
    state->buf     = buf;
1441
8.71k
    state->bufsize = bufsize;
1442
8.71k
  }
1443
0
  else {
1444
0
    sys->free(buf);
1445
0
    sys->free(state);
1446
0
    state = NULL;
1447
0
  }
1448
8.71k
  return state;
1449
8.71k
}
1450
1451
10.7k
static int noned_decompress(struct noned_state *s, off_t bytes) {
1452
10.7k
  int run;
1453
18.4k
  while (bytes > 0) {
1454
16.8k
    run = (bytes > s->bufsize) ? s->bufsize : (int) bytes;
1455
16.8k
    if (s->sys->read(s->i, &s->buf[0], run) != run) return MSPACK_ERR_READ;
1456
7.70k
    if (s->sys->write(s->o, &s->buf[0], run) != run) return MSPACK_ERR_WRITE;
1457
7.70k
    bytes -= run;
1458
7.70k
  }
1459
1.57k
  return MSPACK_ERR_OK;
1460
10.7k
}
1461
1462
8.71k
static void noned_free(struct noned_state *state) {
1463
8.71k
  struct mspack_system *sys;
1464
8.71k
  if (state) {
1465
8.71k
    sys = state->sys;
1466
8.71k
    sys->free(state->buf);
1467
8.71k
    sys->free(state);
1468
8.71k
  }
1469
8.71k
}
1470
1471
1472
/***************************************
1473
 * CABD_PARAM
1474
 ***************************************
1475
 * allows a parameter to be set
1476
 */
1477
873k
static int cabd_param(struct mscab_decompressor *base, int param, int value) {
1478
873k
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1479
873k
  if (!self) return MSPACK_ERR_ARGS;
1480
1481
873k
  switch (param) {
1482
0
  case MSCABD_PARAM_SEARCHBUF:
1483
0
    if (value < 4) return MSPACK_ERR_ARGS;
1484
0
    self->searchbuf_size = value;
1485
0
    break;
1486
436k
  case MSCABD_PARAM_FIXMSZIP:
1487
436k
    self->fix_mszip = value;
1488
436k
    break;
1489
0
  case MSCABD_PARAM_DECOMPBUF:
1490
0
    if (value < 4) return MSPACK_ERR_ARGS;
1491
0
    self->buf_size = value;
1492
0
    break;
1493
436k
  case MSCABD_PARAM_SALVAGE:
1494
436k
    self->salvage = value;
1495
436k
    break;
1496
0
  default:
1497
0
    return MSPACK_ERR_ARGS;
1498
873k
  }
1499
873k
  return MSPACK_ERR_OK;
1500
873k
}
1501
1502
/***************************************
1503
 * CABD_ERROR
1504
 ***************************************
1505
 * returns the last error that occurred
1506
 */
1507
0
static int cabd_error(struct mscab_decompressor *base) {
1508
0
  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1509
0
  return (self) ? self->error : MSPACK_ERR_ARGS;
1510
0
}