Rizin
unix-like reverse engineering framework and cli tools
cabd.c File Reference
#include <system.h>
#include <cab.h>
#include <mszip.h>
#include <lzx.h>
#include <qtm.h>

Go to the source code of this file.

Classes

struct  noned_state
 

Functions

static struct mscabd_cabinetcabd_open (struct mscab_decompressor *base, const char *filename)
 
static void cabd_close (struct mscab_decompressor *base, struct mscabd_cabinet *origcab)
 
static int cabd_read_headers (struct mspack_system *sys, struct mspack_file *fh, struct mscabd_cabinet_p *cab, off_t offset, int salvage, int quiet)
 
static char * cabd_read_string (struct mspack_system *sys, struct mspack_file *fh, int permit_empty, int *error)
 
static struct mscabd_cabinetcabd_search (struct mscab_decompressor *base, const char *filename)
 
static int cabd_find (struct mscab_decompressor_p *self, unsigned char *buf, struct mspack_file *fh, const char *filename, off_t flen, off_t *firstlen, struct mscabd_cabinet_p **firstcab)
 
static int cabd_prepend (struct mscab_decompressor *base, struct mscabd_cabinet *cab, struct mscabd_cabinet *prevcab)
 
static int cabd_append (struct mscab_decompressor *base, struct mscabd_cabinet *cab, struct mscabd_cabinet *nextcab)
 
static int cabd_merge (struct mscab_decompressor *base, struct mscabd_cabinet *lcab, struct mscabd_cabinet *rcab)
 
static int cabd_can_merge_folders (struct mspack_system *sys, struct mscabd_folder_p *lfol, struct mscabd_folder_p *rfol)
 
static int cabd_extract (struct mscab_decompressor *base, struct mscabd_file *file, const char *filename)
 
static int cabd_init_decomp (struct mscab_decompressor_p *self, unsigned int ct)
 
static void cabd_free_decomp (struct mscab_decompressor_p *self)
 
static int cabd_sys_read (struct mspack_file *file, void *buffer, int bytes)
 
static int cabd_sys_write (struct mspack_file *file, void *buffer, int bytes)
 
static int cabd_sys_read_block (struct mspack_system *sys, struct mscabd_decompress_state *d, int *out, int ignore_cksum, int ignore_blocksize)
 
static unsigned int cabd_checksum (unsigned char *data, unsigned int bytes, unsigned int cksum)
 
static struct noned_statenoned_init (struct mspack_system *sys, struct mspack_file *in, struct mspack_file *out, int bufsize)
 
static int noned_decompress (struct noned_state *s, off_t bytes)
 
static void noned_free (struct noned_state *state)
 
static int cabd_param (struct mscab_decompressor *base, int param, int value)
 
static int cabd_error (struct mscab_decompressor *base)
 
struct mscab_decompressormspack_create_cab_decompressor (struct mspack_system *sys)
 
void mspack_destroy_cab_decompressor (struct mscab_decompressor *base)
 

Function Documentation

◆ cabd_append()

static int cabd_append ( struct mscab_decompressor base,
struct mscabd_cabinet cab,
struct mscabd_cabinet nextcab 
)
static

Definition at line 807 of file cabd.c.

810 {
811  return cabd_merge(base, cab, nextcab);
812 }
static int cabd_merge(struct mscab_decompressor *base, struct mscabd_cabinet *lcab, struct mscabd_cabinet *rcab)
Definition: cabd.c:814

References cabd_merge(), and mscabd_cabinet::nextcab.

Referenced by mspack_create_cab_decompressor().

◆ cabd_can_merge_folders()

static int cabd_can_merge_folders ( struct mspack_system sys,
struct mscabd_folder_p lfol,
struct mscabd_folder_p rfol 
)
static

Definition at line 953 of file cabd.c.

956 {
957  struct mscabd_file *lfi, *rfi, *l, *r;
958  int matching = 1;
959 
960  /* check that both folders use the same compression method/settings */
961  if (lfol->base.comp_type != rfol->base.comp_type) {
962  D(("folder merge: compression type mismatch"))
963  return 0;
964  }
965 
966  /* check there are not too many data blocks after merging */
967  if ((lfol->base.num_blocks + rfol->base.num_blocks) > CAB_FOLDERMAX) {
968  D(("folder merge: too many data blocks in merged folders"))
969  return 0;
970  }
971 
972  if (!(lfi = lfol->merge_next) || !(rfi = rfol->merge_prev)) {
973  D(("folder merge: one cabinet has no files to merge"))
974  return 0;
975  }
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  for (l=lfi, r=rfi; l; l=l->next, r=r->next) {
982  if (!r || (l->offset != r->offset) || (l->length != r->length)) {
983  matching = 0;
984  break;
985  }
986  }
987 
988  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  matching = 0;
994  for (l = lfi; l; l = l->next) {
995  for (r = rfi; r; r = r->next) {
996  if (l->offset == r->offset && l->length == r->length) break;
997  }
998  if (r) matching = 1; else sys->message(NULL,
999  "WARNING; merged file %s not listed in both cabinets", l->filename);
1000  }
1001  return matching;
1002 }
#define D
Definition: block.c:38
#define CAB_FOLDERMAX
Definition: cab.h:82
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
unsigned int length
Definition: mspack.h:881
unsigned int offset
Definition: mspack.h:915
struct mscabd_file * next
Definition: mspack.h:868
char * filename
Definition: mspack.h:878
struct mscabd_folder base
Definition: cab.h:134
int comp_type
Definition: mspack.h:822
void(* message)(struct mspack_file *file, const char *format,...)
Definition: mspack.h:407
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4

References mscabd_folder_p::base, CAB_FOLDERMAX, mscabd_folder::comp_type, D, mscabd_file::filename, mscabd_file::length, mscabd_folder_p::merge_next, mscabd_folder_p::merge_prev, mspack_system::message, mscabd_file::next, NULL, mscabd_folder::num_blocks, mscabd_file::offset, and r.

Referenced by cabd_merge().

◆ cabd_checksum()

static unsigned int cabd_checksum ( unsigned char *  data,
unsigned int  bytes,
unsigned int  cksum 
)
static

Definition at line 1397 of file cabd.c.

1399 {
1400  unsigned int len, ul = 0;
1401 
1402  for (len = bytes >> 2; len--; data += 4) {
1403  unsigned int byte0 = data[0];
1404  unsigned int byte1 = ((unsigned int)data[1]) << 8;
1405  unsigned int byte2 = ((unsigned int)data[2]) << 16;
1406  unsigned int byte3 = ((unsigned int)data[3]) << 24;
1407  cksum ^= (byte0 | byte1 | byte2 | byte3);
1408  }
1409 
1410  switch (bytes & 3) {
1411  case 3: ul |= *data++ << 16; /*@fallthrough@*/
1412  case 2: ul |= *data++ << 8; /*@fallthrough@*/
1413  case 1: ul |= *data;
1414  }
1415  cksum ^= ul;
1416 
1417  return cksum;
1418 }
size_t len
Definition: 6502dis.c:15
static ut8 bytes[32]
Definition: asm_arc.c:23
static int
Definition: sfsocketcall.h:114

References bytes, int, and len.

Referenced by cabd_sys_read_block().

◆ cabd_close()

static void cabd_close ( struct mscab_decompressor base,
struct mscabd_cabinet origcab 
)
static

Definition at line 230 of file cabd.c.

232 {
233  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
234  struct mscabd_folder_data *dat, *ndat;
235  struct mscabd_cabinet *cab, *ncab;
236  struct mscabd_folder *fol, *nfol;
237  struct mscabd_file *fi, *nfi;
238  struct mspack_system *sys;
239 
240  if (!base) return;
241  sys = self->system;
242 
243  self->error = MSPACK_ERR_OK;
244 
245  while (origcab) {
246  /* free files */
247  for (fi = origcab->files; fi; fi = nfi) {
248  nfi = fi->next;
249  sys->free(fi->filename);
250  sys->free(fi);
251  }
252 
253  /* free folders */
254  for (fol = origcab->folders; fol; fol = nfol) {
255  nfol = fol->next;
256 
257  /* free folder decompression state if it has been decompressed */
258  if (self->d && (self->d->folder == (struct mscabd_folder_p *) fol)) {
259  if (self->d->infh) sys->close(self->d->infh);
260  cabd_free_decomp(self);
261  sys->free(self->d);
262  self->d = NULL;
263  }
264 
265  /* free folder data segments */
266  for (dat = ((struct mscabd_folder_p *)fol)->data.next; dat; dat = ndat) {
267  ndat = dat->next;
268  sys->free(dat);
269  }
270  sys->free(fol);
271  }
272 
273  /* free predecessor cabinets (and the original cabinet's strings) */
274  for (cab = origcab; cab; cab = ncab) {
275  ncab = cab->prevcab;
276  sys->free(cab->prevname);
277  sys->free(cab->nextname);
278  sys->free(cab->previnfo);
279  sys->free(cab->nextinfo);
280  if (cab != origcab) sys->free(cab);
281  }
282 
283  /* free successor cabinets */
284  for (cab = origcab->nextcab; cab; cab = ncab) {
285  ncab = cab->nextcab;
286  sys->free(cab->prevname);
287  sys->free(cab->nextname);
288  sys->free(cab->previnfo);
289  sys->free(cab->nextinfo);
290  sys->free(cab);
291  }
292 
293  /* free actual cabinet structure */
294  cab = origcab->next;
295  sys->free(origcab);
296 
297  /* repeat full procedure again with the cab->next pointer (if set) */
298  origcab = cab;
299  }
300 }
#define MSPACK_ERR_OK
Definition: mspack.h:485
static void cabd_free_decomp(struct mscab_decompressor_p *self)
Definition: cabd.c:1193
struct mscab_decompressor base
Definition: cab.h:113
char * prevname
Definition: mspack.h:727
struct mscabd_cabinet * next
Definition: mspack.h:705
struct mscabd_cabinet * prevcab
Definition: mspack.h:721
char * previnfo
Definition: mspack.h:735
struct mscabd_folder * folders
Definition: mspack.h:746
char * nextinfo
Definition: mspack.h:740
char * nextname
Definition: mspack.h:730
struct mscabd_file * files
Definition: mspack.h:743
struct mscabd_cabinet * nextcab
Definition: mspack.h:724
struct mscabd_folder_data * next
Definition: cab.h:128
struct mscabd_folder * next
Definition: mspack.h:811
void(* close)(struct mspack_file *file)
Definition: mspack.h:321
void(* free)(void *ptr)
Definition: mspack.h:430

References mscab_decompressor_p::base, cabd_free_decomp(), mspack_system::close, mscabd_file::filename, mscabd_cabinet::files, mscabd_cabinet::folders, mspack_system::free, MSPACK_ERR_OK, mscabd_folder_data::next, mscabd_cabinet::next, mscabd_folder::next, mscabd_file::next, mscabd_cabinet::nextcab, mscabd_cabinet::nextinfo, mscabd_cabinet::nextname, NULL, mscabd_cabinet::prevcab, mscabd_cabinet::previnfo, and mscabd_cabinet::prevname.

Referenced by cabd_find(), cabd_open(), and mspack_create_cab_decompressor().

◆ cabd_error()

static int cabd_error ( struct mscab_decompressor base)
static

Definition at line 1511 of file cabd.c.

1511  {
1512  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1513  return (self) ? self->error : MSPACK_ERR_ARGS;
1514 }
#define MSPACK_ERR_ARGS
Definition: mspack.h:487

References mscab_decompressor_p::base, and MSPACK_ERR_ARGS.

Referenced by mspack_create_cab_decompressor().

◆ cabd_extract()

static int cabd_extract ( struct mscab_decompressor base,
struct mscabd_file file,
const char *  filename 
)
static

Definition at line 1010 of file cabd.c.

1012 {
1013  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1014  struct mscabd_folder_p *fol;
1015  struct mspack_system *sys;
1016  struct mspack_file *fh;
1017  off_t filelen;
1018 
1019  if (!self) return MSPACK_ERR_ARGS;
1020  if (!file) return self->error = MSPACK_ERR_ARGS;
1021 
1022  sys = self->system;
1023  fol = (struct mscabd_folder_p *) file->folder;
1024 
1025  /* if offset is beyond 2GB, nothing can be extracted */
1026  if (file->offset > CAB_LENGTHMAX) {
1027  return self->error = MSPACK_ERR_DATAFORMAT;
1028  }
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  filelen = file->length;
1034  if (filelen > CAB_LENGTHMAX || (file->offset + filelen) > CAB_LENGTHMAX) {
1035  if (self->salvage) {
1036  filelen = CAB_LENGTHMAX - file->offset;
1037  }
1038  else {
1039  return self->error = MSPACK_ERR_DATAFORMAT;
1040  }
1041  }
1042 
1043  /* extraction impossible if no folder, or folder needs predecessor */
1044  if (!fol || fol->merge_prev) {
1045  sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
1046  "cabinet set is incomplete", file->filename);
1047  return self->error = MSPACK_ERR_DECRUNCH;
1048  }
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  if (!self->salvage) {
1055  if ((file->offset + filelen) > maxlen) {
1056  sys->message(NULL, "ERROR; file \"%s\" cannot be extracted, "
1057  "cabinet set is incomplete", file->filename);
1058  return self->error = MSPACK_ERR_DECRUNCH;
1059  }
1060  }
1061 
1062  /* allocate generic decompression state */
1063  if (!self->d) {
1064  self->d = (struct mscabd_decompress_state *) sys->alloc(sys, sizeof(struct mscabd_decompress_state));
1065  if (!self->d) return self->error = MSPACK_ERR_NOMEMORY;
1066  self->d->folder = NULL;
1067  self->d->data = NULL;
1068  self->d->sys = *sys;
1069  self->d->sys.read = &cabd_sys_read;
1070  self->d->sys.write = &cabd_sys_write;
1071  self->d->state = NULL;
1072  self->d->infh = NULL;
1073  self->d->incab = NULL;
1074  }
1075 
1076  /* do we need to change folder or reset the current folder? */
1077  if ((self->d->folder != fol) || (self->d->offset > file->offset) ||
1078  !self->d->state)
1079  {
1080  /* free any existing decompressor */
1081  cabd_free_decomp(self);
1082 
1083  /* do we need to open a new cab file? */
1084  if (!self->d->infh || (fol->data.cab != self->d->incab)) {
1085  /* close previous file handle if from a different cab */
1086  if (self->d->infh) sys->close(self->d->infh);
1087  self->d->incab = fol->data.cab;
1088  self->d->infh = sys->open(sys, fol->data.cab->base.filename,
1090  if (!self->d->infh) return self->error = MSPACK_ERR_OPEN;
1091  }
1092  /* seek to start of data blocks */
1093  if (sys->seek(self->d->infh, fol->data.offset, MSPACK_SYS_SEEK_START)) {
1094  return self->error = MSPACK_ERR_SEEK;
1095  }
1096 
1097  /* set up decompressor */
1098  if (cabd_init_decomp(self, (unsigned int) fol->base.comp_type)) {
1099  return self->error;
1100  }
1101 
1102  /* initialise new folder state */
1103  self->d->folder = fol;
1104  self->d->data = &fol->data;
1105  self->d->offset = 0;
1106  self->d->block = 0;
1107  self->d->outlen = 0;
1108  self->d->i_ptr = self->d->i_end = &self->d->input[0];
1109 
1110  /* read_error lasts for the lifetime of a decompressor */
1111  self->read_error = MSPACK_ERR_OK;
1112  }
1113 
1114  /* open file for output */
1115  if (!(fh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) {
1116  return self->error = MSPACK_ERR_OPEN;
1117  }
1118 
1119  self->error = MSPACK_ERR_OK;
1120 
1121  /* if file has more than 0 bytes */
1122  if (filelen) {
1123  off_t bytes;
1124  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  self->d->outfh = NULL;
1131  if ((bytes = file->offset - self->d->offset)) {
1132  error = self->d->decompress(self->d->state, bytes);
1133  self->error = (error == MSPACK_ERR_READ) ? self->read_error : error;
1134  }
1135 
1136  /* if getting to the correct offset was error free, unpack file */
1137  if (!self->error) {
1138  self->d->outfh = fh;
1139  error = self->d->decompress(self->d->state, filelen);
1140  self->error = (error == MSPACK_ERR_READ) ? self->read_error : error;
1141  }
1142  }
1143 
1144  /* close output file */
1145  sys->close(fh);
1146  self->d->outfh = NULL;
1147 
1148  return self->error;
1149 }
#define CAB_LENGTHMAX
Definition: cab.h:83
#define CAB_BLOCKMAX
Definition: cab.h:66
#define MSPACK_ERR_SEEK
Definition: mspack.h:495
#define MSPACK_ERR_OPEN
Definition: mspack.h:489
#define MSPACK_SYS_OPEN_WRITE
Definition: mspack.h:460
#define MSPACK_SYS_SEEK_START
Definition: mspack.h:467
#define MSPACK_SYS_OPEN_READ
Definition: mspack.h:458
#define MSPACK_ERR_DATAFORMAT
Definition: mspack.h:501
#define MSPACK_ERR_DECRUNCH
Definition: mspack.h:507
#define MSPACK_ERR_READ
Definition: mspack.h:491
#define MSPACK_ERR_NOMEMORY
Definition: mspack.h:497
FILE * fh
Definition: cabinfo.c:52
FILELEN filelen
Definition: cabinfo.c:54
const char * filename
Definition: ioapi.h:137
static int cabd_init_decomp(struct mscab_decompressor_p *self, unsigned int ct)
Definition: cabd.c:1161
static int cabd_sys_read(struct mspack_file *file, void *buffer, int bytes)
Definition: cabd.c:1218
static int cabd_sys_write(struct mspack_file *file, void *buffer, int bytes)
Definition: cabd.c:1282
int off_t
Definition: sftypes.h:41
Definition: gzappend.c:170
struct mscabd_cabinet base
Definition: cab.h:121
const char * filename
Definition: mspack.h:712
struct mspack_system sys
Definition: cab.h:101
off_t offset
Definition: cab.h:130
struct mscabd_cabinet_p * cab
Definition: cab.h:129
struct mscabd_folder_data data
Definition: cab.h:135
struct mscabd_file * merge_prev
Definition: cab.h:136
unsigned int num_blocks
Definition: mspack.h:829
struct mspack_file *(* open)(struct mspack_system *self, const char *filename, int mode)
Definition: mspack.h:310
int(* seek)(struct mspack_file *file, off_t offset, int mode)
Definition: mspack.h:380
int(* read)(struct mspack_file *file, void *buffer, int bytes)
Definition: mspack.h:336
void *(* alloc)(struct mspack_system *self, size_t bytes)
Definition: mspack.h:421
ut64 maxlen
Definition: core.c:76
void error(const char *msg)
Definition: untgz.c:593

References mspack_system::alloc, mscab_decompressor_p::base, mscabd_cabinet_p::base, mscabd_folder_p::base, bytes, mscabd_folder_data::cab, CAB_BLOCKMAX, CAB_LENGTHMAX, cabd_free_decomp(), cabd_init_decomp(), cabd_sys_read(), cabd_sys_write(), mspack_system::close, mscabd_folder::comp_type, mscabd_folder_p::data, error(), fh, filelen, mscabd_cabinet::filename, if(), maxlen, mscabd_folder_p::merge_prev, mspack_system::message, MSPACK_ERR_ARGS, MSPACK_ERR_DATAFORMAT, MSPACK_ERR_DECRUNCH, MSPACK_ERR_NOMEMORY, MSPACK_ERR_OK, MSPACK_ERR_OPEN, MSPACK_ERR_READ, MSPACK_ERR_SEEK, MSPACK_SYS_OPEN_READ, MSPACK_SYS_OPEN_WRITE, MSPACK_SYS_SEEK_START, NULL, mscabd_folder::num_blocks, mscabd_folder_data::offset, mspack_system::open, mspack_system::read, mspack_system::seek, and mscabd_decompress_state::sys.

Referenced by mspack_create_cab_decompressor().

◆ cabd_find()

static int cabd_find ( struct mscab_decompressor_p self,
unsigned char *  buf,
struct mspack_file fh,
const char *  filename,
off_t  flen,
off_t firstlen,
struct mscabd_cabinet_p **  firstcab 
)
static

Definition at line 645 of file cabd.c.

648 {
649  struct mscabd_cabinet_p *cab, *link = NULL;
650  off_t caboff, offset, length;
651  struct mspack_system *sys = self->system;
652  unsigned char *p, *pend, state = 0;
653  unsigned int cablen_u32 = 0, foffset_u32 = 0;
654  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  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  length = flen - offset;
669  if (length > self->searchbuf_size) {
670  length = self->searchbuf_size;
671  }
672 
673  /* fill the search buffer with data from disk */
674  if (sys->read(fh, &buf[0], (int) length) != (int) length) {
675  return MSPACK_ERR_READ;
676  }
677 
678  /* FAQ avoidance strategy */
679  if ((offset == 0) && (EndGetI32(&buf[0]) == 0x28635349)) {
680  sys->message(fh, "WARNING; found InstallShield header. Use unshield "
681  "(https://github.com/twogood/unshield) to unpack this file");
682  }
683 
684  /* read through the entire buffer. */
685  for (p = &buf[0], pend = &buf[length]; p < pend; ) {
686  switch (state) {
687  /* starting state */
688  case 0:
689  /* we spend most of our time in this while loop, looking for
690  * a leading 'M' of the 'MSCF' signature */
691  while (p < pend && *p != 0x4D) p++;
692  /* if we found tht 'M', advance state */
693  if (p++ < pend) state = 1;
694  break;
695 
696  /* verify that the next 3 bytes are 'S', 'C' and 'F' */
697  case 1: state = (*p++ == 0x53) ? 2 : 0; break;
698  case 2: state = (*p++ == 0x43) ? 3 : 0; break;
699  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  case 8: cablen_u32 = *p++; state++; break;
705  case 9: cablen_u32 |= *p++ << 8; state++; break;
706  case 10: cablen_u32 |= *p++ << 16; state++; break;
707  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  case 16: foffset_u32 = *p++; state++; break;
713  case 17: foffset_u32 |= *p++ << 8; state++; break;
714  case 18: foffset_u32 |= *p++ << 16; state++; break;
715  case 19: foffset_u32 |= *p++ << 24;
716  /* now we have recieved 20 bytes of potential cab header. work out
717  * the offset in the file of this potential cabinet */
718  caboff = offset + (p - &buf[0]) - 20;
719 
720  /* should reading cabinet fail, restart search just after 'MSCF' */
721  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  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  if ((foffset_u32 < cablen_u32) &&
733  ((caboff + (off_t) foffset_u32) < (flen + 32)) &&
734  (((caboff + (off_t) cablen_u32) < (flen + 32)) || self->salvage))
735  {
736  /* likely cabinet found -- try reading it */
737  if (!(cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
738  return MSPACK_ERR_NOMEMORY;
739  }
740  cab->base.filename = filename;
741  if (cabd_read_headers(sys, fh, cab, caboff, self->salvage, 1)) {
742  /* destroy the failed cabinet */
743  cabd_close((struct mscab_decompressor *) self,
744  (struct mscabd_cabinet *) cab);
745  false_cabs++;
746  }
747  else {
748  /* cabinet read correctly! */
749 
750  /* link the cab into the list */
751  if (!link) *firstcab = cab;
752  else link->base.next = (struct mscabd_cabinet *) cab;
753  link = cab;
754 
755  /* cause the search to restart after this cab's data. */
756  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  }
766  }
767 
768  /* restart search */
769  if (offset >= flen) return MSPACK_ERR_OK;
770  if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) {
771  return MSPACK_ERR_SEEK;
772  }
773  length = 0;
774  p = pend;
775  state = 0;
776  break;
777 
778  /* for bytes 4-7 and 12-15, just advance state/pointer */
779  default:
780  p++, state++;
781  } /* switch(state) */
782  } /* for (... p < pend ...) */
783  } /* for (... offset < length ...) */
784 
785  if (false_cabs) {
786  D(("%d false cabinets found", false_cabs))
787  }
788 
789  return MSPACK_ERR_OK;
790 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
static static fork const void static count static fd link
Definition: sflib.h:33
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
void * p
Definition: libc.cpp:67
static void cabd_close(struct mscab_decompressor *base, struct mscabd_cabinet *origcab)
Definition: cabd.c:230
static int cabd_read_headers(struct mspack_system *sys, struct mspack_file *fh, struct mscabd_cabinet_p *cab, off_t offset, int salvage, int quiet)
Definition: cabd.c:309
#define EndGetI32(a)
Definition: macros.h:37
int searchbuf_size
Definition: cab.h:116
Definition: dis.h:43

References mspack_system::alloc, mscabd_cabinet_p::base, cabd_close(), cabd_read_headers(), D, EndGetI32, fh, mscabd_cabinet::filename, length, link, mspack_system::message, MSPACK_ERR_NOMEMORY, MSPACK_ERR_OK, MSPACK_ERR_READ, MSPACK_ERR_SEEK, MSPACK_SYS_SEEK_START, NULL, p, mspack_system::read, and mspack_system::seek.

Referenced by cabd_search().

◆ cabd_free_decomp()

static void cabd_free_decomp ( struct mscab_decompressor_p self)
static

Definition at line 1193 of file cabd.c.

1193  {
1194  if (!self || !self->d || !self->d->state) return;
1195 
1196  switch (self->d->comp_type & cffoldCOMPTYPE_MASK) {
1197  case cffoldCOMPTYPE_NONE: noned_free((struct noned_state *) self->d->state); break;
1198  case cffoldCOMPTYPE_MSZIP: mszipd_free((struct mszipd_stream *) self->d->state); break;
1199  case cffoldCOMPTYPE_QUANTUM: qtmd_free((struct qtmd_stream *) self->d->state); break;
1200  case cffoldCOMPTYPE_LZX: lzxd_free((struct lzxd_stream *) self->d->state); break;
1201  }
1202  self->d->decompress = NULL;
1203  self->d->state = NULL;
1204 }
#define cffoldCOMPTYPE_MSZIP
Definition: cab.h:50
#define cffoldCOMPTYPE_LZX
Definition: cab.h:52
#define cffoldCOMPTYPE_MASK
Definition: cab.h:48
#define cffoldCOMPTYPE_QUANTUM
Definition: cab.h:51
#define cffoldCOMPTYPE_NONE
Definition: cab.h:49
void lzxd_free(struct lzxd_stream *lzx)
Definition: lzxd.c:800
void mszipd_free(struct mszipd_stream *zip)
Definition: mszipd.c:508
void qtmd_free(struct qtmd_stream *qtm)
Definition: qtmd.c:482
static void noned_free(struct noned_state *state)
Definition: cabd.c:1466
struct mscabd_decompress_state * d
Definition: cab.h:114

References cffoldCOMPTYPE_LZX, cffoldCOMPTYPE_MASK, cffoldCOMPTYPE_MSZIP, cffoldCOMPTYPE_NONE, cffoldCOMPTYPE_QUANTUM, lzxd_free(), mszipd_free(), noned_free(), NULL, and qtmd_free().

Referenced by cabd_close(), cabd_extract(), and mspack_destroy_cab_decompressor().

◆ cabd_init_decomp()

static int cabd_init_decomp ( struct mscab_decompressor_p self,
unsigned int  ct 
)
static

Definition at line 1161 of file cabd.c.

1162 {
1163  struct mspack_file *fh = (struct mspack_file *) self;
1164 
1165  self->d->comp_type = ct;
1166 
1167  switch (ct & cffoldCOMPTYPE_MASK) {
1168  case cffoldCOMPTYPE_NONE:
1169  self->d->decompress = (int (*)(void *, off_t)) &noned_decompress;
1170  self->d->state = noned_init(&self->d->sys, fh, fh, self->buf_size);
1171  break;
1172  case cffoldCOMPTYPE_MSZIP:
1173  self->d->decompress = (int (*)(void *, off_t)) &mszipd_decompress;
1174  self->d->state = mszipd_init(&self->d->sys, fh, fh, self->buf_size,
1175  self->fix_mszip);
1176  break;
1178  self->d->decompress = (int (*)(void *, off_t)) &qtmd_decompress;
1179  self->d->state = qtmd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f,
1180  self->buf_size);
1181  break;
1182  case cffoldCOMPTYPE_LZX:
1183  self->d->decompress = (int (*)(void *, off_t)) &lzxd_decompress;
1184  self->d->state = lzxd_init(&self->d->sys, fh, fh, (int) (ct >> 8) & 0x1f, 0,
1185  self->buf_size, (off_t)0,0);
1186  break;
1187  default:
1188  return self->error = MSPACK_ERR_DATAFORMAT;
1189  }
1190  return self->error = (self->d->state) ? MSPACK_ERR_OK : MSPACK_ERR_NOMEMORY;
1191 }
struct lzxd_stream * lzxd_init(struct mspack_system *system, struct mspack_file *input, struct mspack_file *output, int window_bits, int reset_interval, int input_buffer_size, off_t output_length, char is_delta)
Definition: lzxd.c:279
int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes)
Definition: lzxd.c:393
struct mszipd_stream * mszipd_init(struct mspack_system *system, struct mspack_file *input, struct mspack_file *output, int input_buffer_size, int repair_mode)
Definition: mszipd.c:342
int mszipd_decompress(struct mszipd_stream *zip, off_t out_bytes)
Definition: mszipd.c:384
int qtmd_decompress(struct qtmd_stream *qtm, off_t out_bytes)
Definition: qtmd.c:256
struct qtmd_stream * qtmd_init(struct mspack_system *system, struct mspack_file *input, struct mspack_file *output, int window_bits, int input_buffer_size)
Definition: qtmd.c:186
static struct noned_state * noned_init(struct mspack_system *sys, struct mspack_file *in, struct mspack_file *out, int bufsize)
Definition: cabd.c:1433
static int noned_decompress(struct noned_state *s, off_t bytes)
Definition: cabd.c:1455

References cffoldCOMPTYPE_LZX, cffoldCOMPTYPE_MASK, cffoldCOMPTYPE_MSZIP, cffoldCOMPTYPE_NONE, cffoldCOMPTYPE_QUANTUM, fh, int, lzxd_decompress(), lzxd_init(), MSPACK_ERR_DATAFORMAT, MSPACK_ERR_NOMEMORY, MSPACK_ERR_OK, mszipd_decompress(), mszipd_init(), noned_decompress(), noned_init(), qtmd_decompress(), and qtmd_init().

Referenced by cabd_extract().

◆ cabd_merge()

static int cabd_merge ( struct mscab_decompressor base,
struct mscabd_cabinet lcab,
struct mscabd_cabinet rcab 
)
static

Definition at line 814 of file cabd.c.

817 {
818  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
819  struct mscabd_folder_data *data, *ndata;
820  struct mscabd_folder_p *lfol, *rfol;
821  struct mscabd_file *fi, *rfi, *lfi;
822  struct mscabd_cabinet *cab;
823  struct mspack_system *sys;
824 
825  if (!self) return MSPACK_ERR_ARGS;
826  sys = self->system;
827 
828  /* basic args check */
829  if (!lcab || !rcab || (lcab == rcab)) {
830  D(("lcab NULL, rcab NULL or lcab = rcab"))
831  return self->error = MSPACK_ERR_ARGS;
832  }
833 
834  /* check there's not already a cabinet attached */
835  if (lcab->nextcab || rcab->prevcab) {
836  D(("cabs already joined"))
837  return self->error = MSPACK_ERR_ARGS;
838  }
839 
840  /* do not create circular cabinet chains */
841  for (cab = lcab->prevcab; cab; cab = cab->prevcab) {
842  if (cab == rcab) {D(("circular!")) return self->error = MSPACK_ERR_ARGS;}
843  }
844  for (cab = rcab->nextcab; cab; cab = cab->nextcab) {
845  if (cab == lcab) {D(("circular!")) return self->error = MSPACK_ERR_ARGS;}
846  }
847 
848  /* warn about odd set IDs or indices */
849  if (lcab->set_id != rcab->set_id) {
850  sys->message(NULL, "WARNING; merged cabinets with differing Set IDs.");
851  }
852 
853  if (lcab->set_index > rcab->set_index) {
854  sys->message(NULL, "WARNING; merged cabinets with odd order.");
855  }
856 
857  /* merging the last folder in lcab with the first folder in rcab */
858  lfol = (struct mscabd_folder_p *) lcab->folders;
859  rfol = (struct mscabd_folder_p *) rcab->folders;
860  while (lfol->base.next) lfol = (struct mscabd_folder_p *) lfol->base.next;
861 
862  /* do we need to merge folders? */
863  if (!lfol->merge_next && !rfol->merge_prev) {
864  /* no, at least one of the folders is not for merging */
865 
866  /* attach cabs */
867  lcab->nextcab = rcab;
868  rcab->prevcab = lcab;
869 
870  /* attach folders */
871  lfol->base.next = (struct mscabd_folder *) rfol;
872 
873  /* attach files */
874  fi = lcab->files;
875  while (fi->next) fi = fi->next;
876  fi->next = rcab->files;
877  }
878  else {
879  /* folder merge required - do the files match? */
880  if (! cabd_can_merge_folders(sys, lfol, rfol)) {
881  return self->error = MSPACK_ERR_DATAFORMAT;
882  }
883 
884  /* allocate a new folder data structure */
885  if (!(data = (struct mscabd_folder_data *) sys->alloc(sys, sizeof(struct mscabd_folder_data)))) {
886  return self->error = MSPACK_ERR_NOMEMORY;
887  }
888 
889  /* attach cabs */
890  lcab->nextcab = rcab;
891  rcab->prevcab = lcab;
892 
893  /* append rfol's data to lfol */
894  ndata = &lfol->data;
895  while (ndata->next) ndata = ndata->next;
896  ndata->next = data;
897  *data = rfol->data;
898  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  lfol->base.num_blocks += rfol->base.num_blocks - 1;
905  if ((rfol->merge_next == NULL) ||
906  (rfol->merge_next->folder != (struct mscabd_folder *) rfol))
907  {
908  lfol->merge_next = rfol->merge_next;
909  }
910 
911  /* attach the rfol's folder (except the merge folder) */
912  while (lfol->base.next) lfol = (struct mscabd_folder_p *) lfol->base.next;
913  lfol->base.next = rfol->base.next;
914 
915  /* free disused merge folder */
916  sys->free(rfol);
917 
918  /* attach rfol's files */
919  fi = lcab->files;
920  while (fi->next) fi = fi->next;
921  fi->next = rcab->files;
922 
923  /* delete all files from rfol's merge folder */
924  lfi = NULL;
925  for (fi = lcab->files; fi ; fi = rfi) {
926  rfi = fi->next;
927  /* if file's folder matches the merge folder, unlink and free it */
928  if (fi->folder == (struct mscabd_folder *) rfol) {
929  if (lfi) lfi->next = rfi; else lcab->files = rfi;
930  sys->free(fi->filename);
931  sys->free(fi);
932  }
933  else lfi = fi;
934  }
935  }
936 
937  /* all done! fix files and folders pointers in all cabs so they all
938  * point to the same list */
939  for (cab = lcab->prevcab; cab; cab = cab->prevcab) {
940  cab->files = lcab->files;
941  cab->folders = lcab->folders;
942  }
943 
944  for (cab = lcab->nextcab; cab; cab = cab->nextcab) {
945  cab->files = lcab->files;
946  cab->folders = lcab->folders;
947  }
948 
949  return self->error = MSPACK_ERR_OK;
950 }
static int cabd_can_merge_folders(struct mspack_system *sys, struct mscabd_folder_p *lfol, struct mscabd_folder_p *rfol)
Definition: cabd.c:953
unsigned short set_index
Definition: mspack.h:759
struct mscabd_folder * folder
Definition: mspack.h:912
struct mscabd_file * merge_next
Definition: cab.h:137

References mspack_system::alloc, mscab_decompressor_p::base, mscabd_folder_p::base, cabd_can_merge_folders(), D, mscabd_folder_p::data, mscabd_file::filename, mscabd_cabinet::files, mscabd_file::folder, mscabd_cabinet::folders, mspack_system::free, if(), mscabd_folder_p::merge_next, mscabd_folder_p::merge_prev, mspack_system::message, MSPACK_ERR_ARGS, MSPACK_ERR_DATAFORMAT, MSPACK_ERR_NOMEMORY, MSPACK_ERR_OK, mscabd_folder_data::next, mscabd_folder::next, mscabd_file::next, mscabd_cabinet::nextcab, NULL, mscabd_folder::num_blocks, mscabd_cabinet::prevcab, mscabd_cabinet::set_id, and mscabd_cabinet::set_index.

Referenced by cabd_append(), and cabd_prepend().

◆ cabd_open()

static struct mscabd_cabinet * cabd_open ( struct mscab_decompressor base,
const char *  filename 
)
static

Definition at line 192 of file cabd.c.

194 {
195  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
196  struct mscabd_cabinet_p *cab = NULL;
197  struct mspack_system *sys;
198  struct mspack_file *fh;
199  int error;
200 
201  if (!base) return NULL;
202  sys = self->system;
203 
204  if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
205  if ((cab = (struct mscabd_cabinet_p *) sys->alloc(sys, sizeof(struct mscabd_cabinet_p)))) {
206  cab->base.filename = filename;
207  error = cabd_read_headers(sys, fh, cab, (off_t) 0, self->salvage, 0);
208  if (error) {
209  cabd_close(base, (struct mscabd_cabinet *) cab);
210  cab = NULL;
211  }
212  self->error = error;
213  }
214  else {
215  self->error = MSPACK_ERR_NOMEMORY;
216  }
217  sys->close(fh);
218  }
219  else {
220  self->error = MSPACK_ERR_OPEN;
221  }
222  return (struct mscabd_cabinet *) cab;
223 }

References mspack_system::alloc, mscab_decompressor_p::base, mscabd_cabinet_p::base, cabd_close(), cabd_read_headers(), mspack_system::close, error(), fh, mscabd_cabinet::filename, MSPACK_ERR_NOMEMORY, MSPACK_ERR_OPEN, MSPACK_SYS_OPEN_READ, NULL, and mspack_system::open.

Referenced by mspack_create_cab_decompressor().

◆ cabd_param()

static int cabd_param ( struct mscab_decompressor base,
int  param,
int  value 
)
static

Definition at line 1481 of file cabd.c.

1481  {
1482  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
1483  if (!self) return MSPACK_ERR_ARGS;
1484 
1485  switch (param) {
1487  if (value < 4) return MSPACK_ERR_ARGS;
1488  self->searchbuf_size = value;
1489  break;
1490  case MSCABD_PARAM_FIXMSZIP:
1491  self->fix_mszip = value;
1492  break;
1494  if (value < 4) return MSPACK_ERR_ARGS;
1495  self->buf_size = value;
1496  break;
1497  case MSCABD_PARAM_SALVAGE:
1498  self->salvage = value;
1499  break;
1500  default:
1501  return MSPACK_ERR_ARGS;
1502  }
1503  return MSPACK_ERR_OK;
1504 }
#define MSCABD_PARAM_DECOMPBUF
Definition: mspack.h:936
#define MSCABD_PARAM_SEARCHBUF
Definition: mspack.h:932
#define MSCABD_PARAM_FIXMSZIP
Definition: mspack.h:934
#define MSCABD_PARAM_SALVAGE
Definition: mspack.h:943
static int value
Definition: cmd_api.c:93

References mscab_decompressor_p::base, MSCABD_PARAM_DECOMPBUF, MSCABD_PARAM_FIXMSZIP, MSCABD_PARAM_SALVAGE, MSCABD_PARAM_SEARCHBUF, MSPACK_ERR_ARGS, MSPACK_ERR_OK, and value.

Referenced by mspack_create_cab_decompressor().

◆ cabd_prepend()

static int cabd_prepend ( struct mscab_decompressor base,
struct mscabd_cabinet cab,
struct mscabd_cabinet prevcab 
)
static

Definition at line 800 of file cabd.c.

803 {
804  return cabd_merge(base, prevcab, cab);
805 }

References cabd_merge(), and mscabd_cabinet::prevcab.

Referenced by mspack_create_cab_decompressor().

◆ cabd_read_headers()

static int cabd_read_headers ( struct mspack_system sys,
struct mspack_file fh,
struct mscabd_cabinet_p cab,
off_t  offset,
int  salvage,
int  quiet 
)
static

Definition at line 309 of file cabd.c.

313 {
314  int num_folders, num_files, folder_resv, i, x, err, fidx;
315  struct mscabd_folder_p *fol, *linkfol = NULL;
316  struct mscabd_file *file, *linkfile = NULL;
317  unsigned char buf[64];
318 
319  /* initialise pointers */
320  cab->base.next = NULL;
321  cab->base.files = NULL;
322  cab->base.folders = NULL;
323  cab->base.prevcab = cab->base.nextcab = NULL;
324  cab->base.prevname = cab->base.nextname = NULL;
325  cab->base.previnfo = cab->base.nextinfo = NULL;
326 
327  cab->base.base_offset = offset;
328 
329  /* seek to CFHEADER */
330  if (sys->seek(fh, offset, MSPACK_SYS_SEEK_START)) {
331  return MSPACK_ERR_SEEK;
332  }
333 
334  /* read in the CFHEADER */
335  if (sys->read(fh, &buf[0], cfhead_SIZEOF) != cfhead_SIZEOF) {
336  return MSPACK_ERR_READ;
337  }
338 
339  /* check for "MSCF" signature */
340  if (EndGetI32(&buf[cfhead_Signature]) != 0x4643534D) {
341  return MSPACK_ERR_SIGNATURE;
342  }
343 
344  /* some basic header fields */
348 
349  /* get the number of folders */
350  num_folders = EndGetI16(&buf[cfhead_NumFolders]);
351  if (num_folders == 0) {
352  if (!quiet) sys->message(fh, "no folders in cabinet.");
353  return MSPACK_ERR_DATAFORMAT;
354  }
355 
356  /* get the number of files */
357  num_files = EndGetI16(&buf[cfhead_NumFiles]);
358  if (num_files == 0) {
359  if (!quiet) sys->message(fh, "no files in cabinet.");
360  return MSPACK_ERR_DATAFORMAT;
361  }
362 
363  /* check cabinet version */
364  if ((buf[cfhead_MajorVersion] != 1) && (buf[cfhead_MinorVersion] != 3)) {
365  if (!quiet) sys->message(fh, "WARNING; cabinet version is not 1.3");
366  }
367 
368  /* read the reserved-sizes part of header, if present */
369  cab->base.flags = EndGetI16(&buf[cfhead_Flags]);
370 
371  if (cab->base.flags & cfheadRESERVE_PRESENT) {
372  if (sys->read(fh, &buf[0], cfheadext_SIZEOF) != cfheadext_SIZEOF) {
373  return MSPACK_ERR_READ;
374  }
376  folder_resv = buf[cfheadext_FolderReserved];
378 
379  if (cab->base.header_resv > 60000) {
380  if (!quiet) sys->message(fh, "WARNING; reserved header > 60000.");
381  }
382 
383  /* skip the reserved header */
384  if (cab->base.header_resv) {
385  if (sys->seek(fh, (off_t) cab->base.header_resv, MSPACK_SYS_SEEK_CUR)) {
386  return MSPACK_ERR_SEEK;
387  }
388  }
389  }
390  else {
391  cab->base.header_resv = 0;
392  folder_resv = 0;
393  cab->block_resv = 0;
394  }
395 
396  /* read name and info of preceeding cabinet in set, if present */
397  if (cab->base.flags & cfheadPREV_CABINET) {
398  cab->base.prevname = cabd_read_string(sys, fh, 0, &err);
399  if (err) return err;
400  cab->base.previnfo = cabd_read_string(sys, fh, 1, &err);
401  if (err) return err;
402  }
403 
404  /* read name and info of next cabinet in set, if present */
405  if (cab->base.flags & cfheadNEXT_CABINET) {
406  cab->base.nextname = cabd_read_string(sys, fh, 0, &err);
407  if (err) return err;
408  cab->base.nextinfo = cabd_read_string(sys, fh, 1, &err);
409  if (err) return err;
410  }
411 
412  /* read folders */
413  for (i = 0; i < num_folders; i++) {
414  if (sys->read(fh, &buf[0], cffold_SIZEOF) != cffold_SIZEOF) {
415  return MSPACK_ERR_READ;
416  }
417  if (folder_resv) {
418  if (sys->seek(fh, (off_t) folder_resv, MSPACK_SYS_SEEK_CUR)) {
419  return MSPACK_ERR_SEEK;
420  }
421  }
422 
423  if (!(fol = (struct mscabd_folder_p *) sys->alloc(sys, sizeof(struct mscabd_folder_p)))) {
424  return MSPACK_ERR_NOMEMORY;
425  }
426  fol->base.next = NULL;
429  fol->data.next = NULL;
430  fol->data.cab = (struct mscabd_cabinet_p *) cab;
431  fol->data.offset = offset + (off_t)
432  ( (unsigned int) EndGetI32(&buf[cffold_DataOffset]) );
433  fol->merge_prev = NULL;
434  fol->merge_next = NULL;
435 
436  /* link folder into list of folders */
437  if (!linkfol) cab->base.folders = (struct mscabd_folder *) fol;
438  else linkfol->base.next = (struct mscabd_folder *) fol;
439  linkfol = fol;
440  }
441 
442  /* read files */
443  for (i = 0; i < num_files; i++) {
444  if (sys->read(fh, &buf[0], cffile_SIZEOF) != cffile_SIZEOF) {
445  return MSPACK_ERR_READ;
446  }
447 
448  if (!(file = (struct mscabd_file *) sys->alloc(sys, sizeof(struct mscabd_file)))) {
449  return MSPACK_ERR_NOMEMORY;
450  }
451 
452  file->next = NULL;
454  file->attribs = EndGetI16(&buf[cffile_Attribs]);
455  file->offset = EndGetI32(&buf[cffile_FolderOffset]);
456 
457  /* set folder pointer */
458  fidx = EndGetI16(&buf[cffile_FolderIndex]);
459  if (fidx < cffileCONTINUED_FROM_PREV) {
460  /* normal folder index; count up to the correct folder */
461  if (fidx < num_folders) {
462  struct mscabd_folder *ifol = cab->base.folders;
463  while (fidx--) if (ifol) ifol = ifol->next;
464  file->folder = ifol;
465  }
466  else {
467  D(("invalid folder index"))
468  file->folder = NULL;
469  }
470  }
471  else {
472  /* either CONTINUED_TO_NEXT, CONTINUED_FROM_PREV or
473  * CONTINUED_PREV_AND_NEXT */
474  if ((fidx == cffileCONTINUED_TO_NEXT) ||
476  {
477  /* get last folder */
478  struct mscabd_folder *ifol = cab->base.folders;
479  while (ifol->next) ifol = ifol->next;
480  file->folder = ifol;
481 
482  /* set "merge next" pointer */
483  fol = (struct mscabd_folder_p *) ifol;
484  if (!fol->merge_next) fol->merge_next = file;
485  }
486 
487  if ((fidx == cffileCONTINUED_FROM_PREV) ||
489  {
490  /* get first folder */
491  file->folder = cab->base.folders;
492 
493  /* set "merge prev" pointer */
494  fol = (struct mscabd_folder_p *) file->folder;
495  if (!fol->merge_prev) fol->merge_prev = file;
496  }
497  }
498 
499  /* get time */
500  x = EndGetI16(&buf[cffile_Time]);
501  file->time_h = x >> 11;
502  file->time_m = (x >> 5) & 0x3F;
503  file->time_s = (x << 1) & 0x3E;
504 
505  /* get date */
506  x = EndGetI16(&buf[cffile_Date]);
507  file->date_d = x & 0x1F;
508  file->date_m = (x >> 5) & 0xF;
509  file->date_y = (x >> 9) + 1980;
510 
511  /* get filename */
512  file->filename = cabd_read_string(sys, fh, 0, &err);
513 
514  /* if folder index or filename are bad, either skip it or fail */
515  if (err || !file->folder) {
516  sys->free(file->filename);
517  sys->free(file);
518  if (salvage) continue;
519  return err ? err : MSPACK_ERR_DATAFORMAT;
520  }
521 
522  /* link file entry into file list */
523  if (!linkfile) cab->base.files = file;
524  else linkfile->next = file;
525  linkfile = file;
526  }
527 
528  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  D(("No files found, even though header claimed to have %d files", num_files))
532  return MSPACK_ERR_DATAFORMAT;
533  }
534 
535  return MSPACK_ERR_OK;
536 }
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
#define cffile_Attribs
Definition: cab.h:40
#define cffold_NumBlocks
Definition: cab.h:32
#define cffile_Time
Definition: cab.h:39
#define cffold_SIZEOF
Definition: cab.h:34
#define cffile_SIZEOF
Definition: cab.h:41
#define cffileCONTINUED_FROM_PREV
Definition: cab.h:56
#define cfheadext_HeaderReserved
Definition: cab.h:27
#define cfheadRESERVE_PRESENT
Definition: cab.h:55
#define cfhead_Signature
Definition: cab.h:16
#define cffile_FolderOffset
Definition: cab.h:36
#define cffile_FolderIndex
Definition: cab.h:37
#define cfheadext_DataReserved
Definition: cab.h:29
#define cfhead_MajorVersion
Definition: cab.h:20
#define cffileCONTINUED_PREV_AND_NEXT
Definition: cab.h:58
#define cffile_Date
Definition: cab.h:38
#define cfheadNEXT_CABINET
Definition: cab.h:54
#define cffileCONTINUED_TO_NEXT
Definition: cab.h:57
#define cffile_UncompressedSize
Definition: cab.h:35
#define cfhead_CabinetIndex
Definition: cab.h:25
#define cfhead_SetID
Definition: cab.h:24
#define cfhead_NumFiles
Definition: cab.h:22
#define cfhead_SIZEOF
Definition: cab.h:26
#define cfhead_MinorVersion
Definition: cab.h:19
#define cfhead_NumFolders
Definition: cab.h:21
#define cfhead_CabinetSize
Definition: cab.h:17
#define cfheadext_FolderReserved
Definition: cab.h:28
#define cfheadext_SIZEOF
Definition: cab.h:30
#define cffold_DataOffset
Definition: cab.h:31
#define cffold_CompType
Definition: cab.h:33
#define cfhead_Flags
Definition: cab.h:23
#define cfheadPREV_CABINET
Definition: cab.h:53
#define MSPACK_ERR_SIGNATURE
Definition: mspack.h:499
#define MSPACK_SYS_SEEK_CUR
Definition: mspack.h:469
static char * cabd_read_string(struct mspack_system *sys, struct mspack_file *fh, int permit_empty, int *error)
Definition: cabd.c:538
#define EndGetI16(a)
Definition: macros.h:38
int x
Definition: mipsasm.c:20
z_const unsigned char * next
Definition: gzappend.c:175
int block_resv
Definition: cab.h:123
unsigned short set_id
Definition: mspack.h:752
unsigned short header_resv
Definition: mspack.h:771
unsigned int length
Definition: mspack.h:718
off_t base_offset
Definition: mspack.h:715
else
static int file
Definition: z80asm.c:58

References mspack_system::alloc, mscabd_cabinet_p::base, mscabd_folder_p::base, mscabd_cabinet::base_offset, mscabd_cabinet_p::block_resv, mscabd_folder_data::cab, cabd_read_string(), cffile_Attribs, cffile_Date, cffile_FolderIndex, cffile_FolderOffset, cffile_SIZEOF, cffile_Time, cffile_UncompressedSize, cffileCONTINUED_FROM_PREV, cffileCONTINUED_PREV_AND_NEXT, cffileCONTINUED_TO_NEXT, cffold_CompType, cffold_DataOffset, cffold_NumBlocks, cffold_SIZEOF, cfhead_CabinetIndex, cfhead_CabinetSize, cfhead_Flags, cfhead_MajorVersion, cfhead_MinorVersion, cfhead_NumFiles, cfhead_NumFolders, cfhead_SetID, cfhead_Signature, cfhead_SIZEOF, cfheadext_DataReserved, cfheadext_FolderReserved, cfheadext_HeaderReserved, cfheadext_SIZEOF, cfheadNEXT_CABINET, cfheadPREV_CABINET, cfheadRESERVE_PRESENT, mscabd_folder::comp_type, D, mscabd_folder_p::data, EndGetI16, EndGetI32, err, fh, file, mscabd_cabinet::files, mscabd_cabinet::flags, mscabd_cabinet::folders, mspack_system::free, mscabd_cabinet::header_resv, i, if(), mscabd_cabinet::length, mscabd_folder_p::merge_next, mscabd_folder_p::merge_prev, mspack_system::message, MSPACK_ERR_DATAFORMAT, MSPACK_ERR_NOMEMORY, MSPACK_ERR_OK, MSPACK_ERR_READ, MSPACK_ERR_SEEK, MSPACK_ERR_SIGNATURE, MSPACK_SYS_SEEK_CUR, MSPACK_SYS_SEEK_START, mscabd_folder_data::next, mscabd_cabinet::next, mscabd_folder::next, mscabd_file::next, file::next, mscabd_cabinet::nextcab, mscabd_cabinet::nextinfo, mscabd_cabinet::nextname, NULL, mscabd_folder::num_blocks, mscabd_folder_data::offset, mscabd_cabinet::prevcab, mscabd_cabinet::previnfo, mscabd_cabinet::prevname, mspack_system::read, mspack_system::seek, mscabd_cabinet::set_id, mscabd_cabinet::set_index, and x.

Referenced by cabd_find(), and cabd_open().

◆ cabd_read_string()

static char * cabd_read_string ( struct mspack_system sys,
struct mspack_file fh,
int  permit_empty,
int error 
)
static

Definition at line 538 of file cabd.c.

541 {
542  off_t base = sys->tell(fh);
543  char buf[256], *str;
544  int len, i, ok;
545 
546  /* read up to 256 bytes */
547  if ((len = sys->read(fh, &buf[0], 256)) <= 0) {
549  return NULL;
550  }
551 
552  /* search for a null terminator in the buffer */
553  for (i = 0, ok = 0; i < len; i++) if (!buf[i]) { ok = 1; break; }
554  /* optionally reject empty strings */
555  if (i == 0 && !permit_empty) ok = 0;
556 
557  if (!ok) {
559  return NULL;
560  }
561 
562  len = i + 1;
563 
564  /* set the data stream to just after the string and return */
565  if (sys->seek(fh, base + (off_t)len, MSPACK_SYS_SEEK_START)) {
567  return NULL;
568  }
569 
570  if (!(str = (char *) sys->alloc(sys, len))) {
572  return NULL;
573  }
574 
575  sys->copy(&buf[0], str, len);
576  *error = MSPACK_ERR_OK;
577  return str;
578 }
@ ok
Definition: lz4.c:1706
void(* copy)(void *src, void *dest, size_t bytes)
Definition: mspack.h:444
off_t(* tell)(struct mspack_file *file)
Definition: mspack.h:391

References mspack_system::alloc, mscabd_folder_p::base, mspack_system::copy, error(), fh, i, len, MSPACK_ERR_DATAFORMAT, MSPACK_ERR_NOMEMORY, MSPACK_ERR_OK, MSPACK_ERR_READ, MSPACK_ERR_SEEK, MSPACK_SYS_SEEK_START, NULL, ok, mspack_system::read, mspack_system::seek, cmd_descs_generate::str, and mspack_system::tell.

Referenced by cabd_read_headers().

◆ cabd_search()

static struct mscabd_cabinet * cabd_search ( struct mscab_decompressor base,
const char *  filename 
)
static

Definition at line 591 of file cabd.c.

593 {
594  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
595  struct mscabd_cabinet_p *cab = NULL;
596  struct mspack_system *sys;
597  unsigned char *search_buf;
598  struct mspack_file *fh;
599  off_t filelen, firstlen = 0;
600 
601  if (!base) return NULL;
602  sys = self->system;
603 
604  /* allocate a search buffer */
605  search_buf = (unsigned char *) sys->alloc(sys, (size_t) self->searchbuf_size);
606  if (!search_buf) {
607  self->error = MSPACK_ERR_NOMEMORY;
608  return NULL;
609  }
610 
611  /* open file and get its full file length */
612  if ((fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ))) {
613  if (!(self->error = mspack_sys_filelen(sys, fh, &filelen))) {
614  self->error = cabd_find(self, search_buf, fh, filename,
615  filelen, &firstlen, &cab);
616  }
617 
618  /* truncated / extraneous data warning: */
619  if (firstlen && (firstlen != filelen) &&
620  (!cab || (cab->base.base_offset == 0)))
621  {
622  if (firstlen < filelen) {
623  sys->message(fh, "WARNING; possible %" LD
624  " extra bytes at end of file.",
625  filelen - firstlen);
626  }
627  else {
628  sys->message(fh, "WARNING; file possibly truncated by %" LD " bytes.",
629  firstlen - filelen);
630  }
631  }
632 
633  sys->close(fh);
634  }
635  else {
636  self->error = MSPACK_ERR_OPEN;
637  }
638 
639  /* free the search buffer */
640  sys->free(search_buf);
641 
642  return (struct mscabd_cabinet *) cab;
643 }
int mspack_sys_filelen(struct mspack_system *system, struct mspack_file *file, off_t *length)
Definition: system.c:66
unsigned char search_buf[SEARCH_SIZE]
Definition: cabinfo.c:89
static int cabd_find(struct mscab_decompressor_p *self, unsigned char *buf, struct mspack_file *fh, const char *filename, off_t flen, off_t *firstlen, struct mscabd_cabinet_p **firstcab)
Definition: cabd.c:645
#define LD
Definition: macros.h:27

References mspack_system::alloc, mscab_decompressor_p::base, mscabd_cabinet_p::base, mscabd_cabinet::base_offset, cabd_find(), mspack_system::close, fh, filelen, mspack_system::free, LD, mspack_system::message, MSPACK_ERR_NOMEMORY, MSPACK_ERR_OPEN, mspack_sys_filelen(), MSPACK_SYS_OPEN_READ, NULL, mspack_system::open, and search_buf.

Referenced by mspack_create_cab_decompressor().

◆ cabd_sys_read()

static int cabd_sys_read ( struct mspack_file file,
void *  buffer,
int  bytes 
)
static

Definition at line 1218 of file cabd.c.

1218  {
1219  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) file;
1220  unsigned char *buf = (unsigned char *) buffer;
1221  struct mspack_system *sys = self->system;
1222  int avail, todo, outlen, ignore_cksum, ignore_blocksize;
1223 
1224  ignore_cksum = self->salvage ||
1225  (self->fix_mszip &&
1226  ((self->d->comp_type & cffoldCOMPTYPE_MASK) == cffoldCOMPTYPE_MSZIP));
1227  ignore_blocksize = self->salvage;
1228 
1229  todo = bytes;
1230  while (todo > 0) {
1231  avail = self->d->i_end - self->d->i_ptr;
1232 
1233  /* if out of input data, read a new block */
1234  if (avail) {
1235  /* copy as many input bytes available as possible */
1236  if (avail > todo) avail = todo;
1237  sys->copy(self->d->i_ptr, buf, (size_t) avail);
1238  self->d->i_ptr += avail;
1239  buf += avail;
1240  todo -= avail;
1241  }
1242  else {
1243  /* out of data, read a new block */
1244 
1245  /* check if we're out of input blocks, advance block counter */
1246  if (self->d->block++ >= self->d->folder->base.num_blocks) {
1247  if (!self->salvage) {
1248  self->read_error = MSPACK_ERR_DATAFORMAT;
1249  }
1250  else {
1251  D(("Ran out of CAB input blocks prematurely"))
1252  }
1253  break;
1254  }
1255 
1256  /* read a block */
1257  self->read_error = cabd_sys_read_block(sys, self->d, &outlen,
1258  ignore_cksum, ignore_blocksize);
1259  if (self->read_error) return -1;
1260  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  if ((self->d->comp_type & cffoldCOMPTYPE_MASK)==cffoldCOMPTYPE_QUANTUM) {
1266  *self->d->i_end++ = 0xFF;
1267  }
1268 
1269  /* is this the last block? */
1270  if (self->d->block >= self->d->folder->base.num_blocks) {
1271  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  lzxd_set_output_length((struct lzxd_stream *) self->d->state, self->d->outlen);
1275  }
1276  }
1277  } /* if (avail) */
1278  } /* while (todo > 0) */
1279  return bytes - todo;
1280 }
void lzxd_set_output_length(struct lzxd_stream *lzx, off_t output_length)
Definition: lzxd.c:389
static int cabd_sys_read_block(struct mspack_system *sys, struct mscabd_decompress_state *d, int *out, int ignore_cksum, int ignore_blocksize)
Definition: cabd.c:1297
Definition: buffer.h:15

References bytes, cabd_sys_read_block(), cffoldCOMPTYPE_LZX, cffoldCOMPTYPE_MASK, cffoldCOMPTYPE_MSZIP, cffoldCOMPTYPE_QUANTUM, mspack_system::copy, D, lzxd_set_output_length(), and MSPACK_ERR_DATAFORMAT.

Referenced by cabd_extract().

◆ cabd_sys_read_block()

static int cabd_sys_read_block ( struct mspack_system sys,
struct mscabd_decompress_state d,
int out,
int  ignore_cksum,
int  ignore_blocksize 
)
static

Definition at line 1297 of file cabd.c.

1301 {
1302  unsigned char hdr[cfdata_SIZEOF];
1303  unsigned int cksum;
1304  int len, full_len;
1305 
1306  /* reset the input block pointer and end of block pointer */
1307  d->i_ptr = d->i_end = &d->input[0];
1308 
1309  do {
1310  /* read the block header */
1311  if (sys->read(d->infh, &hdr[0], cfdata_SIZEOF) != cfdata_SIZEOF) {
1312  return MSPACK_ERR_READ;
1313  }
1314 
1315  /* skip any reserved block headers */
1316  if (d->data->cab->block_resv &&
1317  sys->seek(d->infh, (off_t) d->data->cab->block_resv,
1319  {
1320  return MSPACK_ERR_SEEK;
1321  }
1322 
1323  /* blocks must not be over CAB_INPUTMAX in size */
1325  full_len = (d->i_end - d->i_ptr) + len; /* include cab-spanning blocks */
1326  if (full_len > CAB_INPUTMAX) {
1327  D(("block size %d > CAB_INPUTMAX", full_len));
1328  /* in salvage mode, blocks can be 65535 bytes but no more than that */
1329  if (!ignore_blocksize || full_len > CAB_INPUTMAX_SALVAGE) {
1330  return MSPACK_ERR_DATAFORMAT;
1331  }
1332  }
1333 
1334  /* blocks must not expand to more than CAB_BLOCKMAX */
1336  D(("block size > CAB_BLOCKMAX"))
1337  if (!ignore_blocksize) return MSPACK_ERR_DATAFORMAT;
1338  }
1339 
1340  /* read the block data */
1341  if (sys->read(d->infh, d->i_end, len) != len) {
1342  return MSPACK_ERR_READ;
1343  }
1344 
1345  /* perform checksum test on the block (if one is stored) */
1346  if ((cksum = EndGetI32(&hdr[cfdata_CheckSum]))) {
1347  unsigned int sum2 = cabd_checksum(d->i_end, (unsigned int) len, 0);
1348  if (cabd_checksum(&hdr[4], 4, sum2) != cksum) {
1349  if (!ignore_cksum) return MSPACK_ERR_CHECKSUM;
1350  sys->message(d->infh, "WARNING; bad block checksum found");
1351  }
1352  }
1353 
1354  /* advance end of block pointer to include newly read data */
1355  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  if ((*out = EndGetI16(&hdr[cfdata_UncompressedSize]))) {
1364  return MSPACK_ERR_OK;
1365  }
1366 
1367  /* otherwise, advance to next cabinet */
1368 
1369  /* close current file handle */
1370  sys->close(d->infh);
1371  d->infh = NULL;
1372 
1373  /* advance to next member in the cabinet set */
1374  if (!(d->data = d->data->next)) {
1375  sys->message(d->infh, "WARNING; ran out of cabinets in set. Are any missing?");
1376  return MSPACK_ERR_DATAFORMAT;
1377  }
1378 
1379  /* open next cab file */
1380  d->incab = d->data->cab;
1381  if (!(d->infh = sys->open(sys, d->incab->base.filename,
1383  {
1384  return MSPACK_ERR_OPEN;
1385  }
1386 
1387  /* seek to start of data blocks */
1388  if (sys->seek(d->infh, d->data->offset, MSPACK_SYS_SEEK_START)) {
1389  return MSPACK_ERR_SEEK;
1390  }
1391  } while (1);
1392 
1393  /* not reached */
1394  return MSPACK_ERR_OK;
1395 }
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define CAB_INPUTMAX_SALVAGE
Definition: cab.h:75
#define cfdata_UncompressedSize
Definition: cab.h:44
#define cfdata_CheckSum
Definition: cab.h:42
#define CAB_INPUTMAX
Definition: cab.h:67
#define cfdata_SIZEOF
Definition: cab.h:45
#define cfdata_CompressedSize
Definition: cab.h:43
#define MSPACK_ERR_CHECKSUM
Definition: mspack.h:503
static unsigned int cabd_checksum(unsigned char *data, unsigned int bytes, unsigned int cksum)
Definition: cabd.c:1397
#define d(i)
Definition: sha256.c:44
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115

References CAB_BLOCKMAX, CAB_INPUTMAX, CAB_INPUTMAX_SALVAGE, cabd_checksum(), cfdata_CheckSum, cfdata_CompressedSize, cfdata_SIZEOF, cfdata_UncompressedSize, mspack_system::close, D, d, EndGetI16, EndGetI32, len, mspack_system::message, MSPACK_ERR_CHECKSUM, MSPACK_ERR_DATAFORMAT, MSPACK_ERR_OK, MSPACK_ERR_OPEN, MSPACK_ERR_READ, MSPACK_ERR_SEEK, MSPACK_SYS_OPEN_READ, MSPACK_SYS_SEEK_CUR, MSPACK_SYS_SEEK_START, NULL, mspack_system::open, out, mspack_system::read, and mspack_system::seek.

Referenced by cabd_sys_read().

◆ cabd_sys_write()

static int cabd_sys_write ( struct mspack_file file,
void *  buffer,
int  bytes 
)
static

Definition at line 1282 of file cabd.c.

1282  {
1283  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) file;
1284  self->d->offset += bytes;
1285  if (self->d->outfh) {
1286  return self->system->write(self->d->outfh, buffer, bytes);
1287  }
1288  return bytes;
1289 }

References bytes.

Referenced by cabd_extract().

◆ mspack_create_cab_decompressor()

struct mscab_decompressor* mspack_create_cab_decompressor ( struct mspack_system sys)

Creates a new CAB decompressor.

Parameters
sysa custom mspack_system structure, or NULL to use the default
Returns
a mscab_decompressor or NULL

Definition at line 140 of file cabd.c.

141 {
142  struct mscab_decompressor_p *self = NULL;
143 
144  if (!sys) sys = mspack_default_system;
145  if (!mspack_valid_system(sys)) return NULL;
146 
147  if ((self = (struct mscab_decompressor_p *) sys->alloc(sys, sizeof(struct mscab_decompressor_p)))) {
148  self->base.open = &cabd_open;
149  self->base.close = &cabd_close;
150  self->base.search = &cabd_search;
151  self->base.extract = &cabd_extract;
152  self->base.prepend = &cabd_prepend;
153  self->base.append = &cabd_append;
154  self->base.set_param = &cabd_param;
155  self->base.last_error = &cabd_error;
156  self->system = sys;
157  self->d = NULL;
158  self->error = MSPACK_ERR_OK;
159 
160  self->searchbuf_size = 32768;
161  self->fix_mszip = 0;
162  self->buf_size = 4096;
163  self->salvage = 0;
164  }
165  return (struct mscab_decompressor *) self;
166 }
struct mspack_system * mspack_default_system
Definition: system.c:238
int mspack_valid_system(struct mspack_system *sys)
Definition: system.c:58
static int cabd_append(struct mscab_decompressor *base, struct mscabd_cabinet *cab, struct mscabd_cabinet *nextcab)
Definition: cabd.c:807
static int cabd_error(struct mscab_decompressor *base)
Definition: cabd.c:1511
static struct mscabd_cabinet * cabd_open(struct mscab_decompressor *base, const char *filename)
Definition: cabd.c:192
static int cabd_param(struct mscab_decompressor *base, int param, int value)
Definition: cabd.c:1481
static struct mscabd_cabinet * cabd_search(struct mscab_decompressor *base, const char *filename)
Definition: cabd.c:591
static int cabd_prepend(struct mscab_decompressor *base, struct mscabd_cabinet *cab, struct mscabd_cabinet *prevcab)
Definition: cabd.c:800
static int cabd_extract(struct mscab_decompressor *base, struct mscabd_file *file, const char *filename)
Definition: cabd.c:1010

References mspack_system::alloc, cabd_append(), cabd_close(), cabd_error(), cabd_extract(), cabd_open(), cabd_param(), cabd_prepend(), cabd_search(), mspack_default_system, MSPACK_ERR_OK, mspack_valid_system(), and NULL.

Referenced by main(), and rz_bin_pdb_extract_in_folder().

◆ mspack_destroy_cab_decompressor()

void mspack_destroy_cab_decompressor ( struct mscab_decompressor self)

Destroys an existing CAB decompressor.

Parameters
selfthe mscab_decompressor to destroy

Definition at line 173 of file cabd.c.

173  {
174  struct mscab_decompressor_p *self = (struct mscab_decompressor_p *) base;
175  if (self) {
176  struct mspack_system *sys = self->system;
177  if (self->d) {
178  if (self->d->infh) sys->close(self->d->infh);
179  cabd_free_decomp(self);
180  sys->free(self->d);
181  }
182  sys->free(self);
183  }
184 }

References mscab_decompressor_p::base, cabd_free_decomp(), mspack_system::close, and mspack_system::free.

Referenced by main(), and rz_bin_pdb_extract_in_folder().

◆ noned_decompress()

static int noned_decompress ( struct noned_state s,
off_t  bytes 
)
static

Definition at line 1455 of file cabd.c.

1455  {
1456  int run;
1457  while (bytes > 0) {
1458  run = (bytes > s->bufsize) ? s->bufsize : (int) bytes;
1459  if (s->sys->read(s->i, &s->buf[0], run) != run) return MSPACK_ERR_READ;
1460  if (s->sys->write(s->o, &s->buf[0], run) != run) return MSPACK_ERR_WRITE;
1461  bytes -= run;
1462  }
1463  return MSPACK_ERR_OK;
1464 }
#define MSPACK_ERR_WRITE
Definition: mspack.h:493
static RzSocket * s
Definition: rtr.c:28
static int run(int i, const char *arg)
Definition: rz-bb.c:19

References bytes, MSPACK_ERR_OK, MSPACK_ERR_READ, MSPACK_ERR_WRITE, run(), and s.

Referenced by cabd_init_decomp().

◆ noned_free()

static void noned_free ( struct noned_state state)
static

Definition at line 1466 of file cabd.c.

1466  {
1467  struct mspack_system *sys;
1468  if (state) {
1469  sys = state->sys;
1470  sys->free(state->buf);
1471  sys->free(state);
1472  }
1473 }

References mspack_system::free.

Referenced by cabd_free_decomp().

◆ noned_init()

static struct noned_state * noned_init ( struct mspack_system sys,
struct mspack_file in,
struct mspack_file out,
int  bufsize 
)
static

Definition at line 1433 of file cabd.c.

1437 {
1438  struct noned_state *state = (struct noned_state *) sys->alloc(sys, sizeof(struct noned_state));
1439  unsigned char *buf = (unsigned char *) sys->alloc(sys, (size_t) bufsize);
1440  if (state && buf) {
1441  state->sys = sys;
1442  state->i = in;
1443  state->o = out;
1444  state->buf = buf;
1445  state->bufsize = bufsize;
1446  }
1447  else {
1448  sys->free(buf);
1449  sys->free(state);
1450  state = NULL;
1451  }
1452  return state;
1453 }
const lzma_allocator const uint8_t * in
Definition: block.h:527
int bufsize
Definition: cabd.c:1430
struct mspack_system * sys
Definition: cabd.c:1426

References mspack_system::alloc, noned_state::bufsize, mspack_system::free, in, NULL, out, and noned_state::sys.

Referenced by cabd_init_decomp().