This commit was manufactured by cvs2svn to create tag 'captive-1_1_7'.
[captive.git] / src / install / acquire / cabextract / cabextract.c
index ade7d8c..d83803f 100644 (file)
@@ -1,5 +1,7 @@
 /* cabextract 0.6 - a program to extract Microsoft Cabinet files
  * (C) 2000-2002 Stuart Caie <kyzer@4u.net>
+ * Modifications for Captive project by:
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -48,6 +50,8 @@
  * Intel code.
  */
 
+#include "config.h"    /* CAPTIVE */
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 
@@ -147,6 +151,12 @@ extern time_t mktime(struct tm *tp);
 
 #endif
 
+#include <glib/gmessages.h>
+#include <ctype.h>
+#include "../cabinet.h"
+#include "../cabinet-memory.h"
+#include "cabextract.h"
+
 #ifdef DEBUG
 # define D(x) printf x ;
 #else
@@ -154,11 +164,6 @@ extern time_t mktime(struct tm *tp);
 #endif
 
 
-typedef unsigned char  UBYTE; /* 8 bits exactly    */
-typedef unsigned short UWORD; /* 16 bits (or more) */
-typedef unsigned int   ULONG; /* 32 bits (or more) */
-typedef   signed int    LONG; /* 32 bits (or more) */
-
 /* number of bits in a ULONG */
 #ifndef CHAR_BIT
 # define CHAR_BIT (8)
@@ -172,21 +177,6 @@ typedef   signed int    LONG; /* 32 bits (or more) */
 /* maximum number of cabinets any one folder can be split across */
 #define CAB_SPLITMAX (10)
 
-struct cabinet {
-  struct cabinet *next;                /* for making a list of cabinets  */
-  char  *filename;                     /* input name of cabinet          */
-  FILE  *fh;                           /* open file handle or NULL       */
-  off_t filelen;                       /* length of cabinet file         */
-  off_t blocks_off;                    /* offset to data blocks in file  */
-  struct cabinet *prevcab, *nextcab;   /* multipart cabinet chains       */
-  char *prevname, *nextname;           /* and their filenames            */
-  char *previnfo, *nextinfo;           /* and their visible names        */
-  struct folder *folders;              /* first folder in this cabinet   */
-  struct file *files;                  /* first file in this cabinet     */
-  UBYTE block_resv;                    /* reserved space in datablocks   */
-  UBYTE flags;                         /* header flags                   */
-};
-
 struct folder {
   struct folder *next;
   struct cabinet *cab[CAB_SPLITMAX];   /* cabinet(s) this folder spans   */
@@ -198,17 +188,6 @@ struct folder {
   struct file *contfile;               /* the first split file           */
 };
 
-struct file {
-  struct file *next;                   /* next file in sequence          */
-  struct folder *folder;               /* folder that contains this file */
-  char *filename;                      /* output name of file            */
-  FILE *fh;                            /* open file handle or NULL       */
-  ULONG length;                        /* uncompressed length of file    */
-  ULONG offset;                        /* uncompressed offset in folder  */
-  UWORD index;                         /* magic index number of folder   */
-  UWORD time, date, attribs;           /* MS-DOS time/date/attributes    */
-};
-
 
 /* structure offsets */
 #define cfhead_Signature         (0x00)
@@ -380,10 +359,11 @@ struct LZXstate {
 
 
 /* generic stuff */
-#define CAB(x) (decomp_state.x)
-#define ZIP(x) (decomp_state.methods.zip.x)
-#define QTM(x) (decomp_state.methods.qtm.x)
-#define LZX(x) (decomp_state.methods.lzx.x)
+#define decomp_state_ptr ((struct decomp_state *)acquire_cabinet_memory_data_get(sizeof(struct decomp_state)))
+#define CAB(x) (decomp_state_ptr->x)
+#define ZIP(x) (decomp_state_ptr->methods.zip.x)
+#define QTM(x) (decomp_state_ptr->methods.qtm.x)
+#define LZX(x) (decomp_state_ptr->methods.lzx.x)
 #define DECR_OK           (0)
 #define DECR_DATAFORMAT   (1)
 #define DECR_ILLEGALDATA  (2)
@@ -400,7 +380,7 @@ struct LZXstate {
 #define CAB_BLOCKMAX (32768)
 #define CAB_INPUTMAX (CAB_BLOCKMAX+6144)
 
-struct {
+struct decomp_state {
   struct folder *current; /* current folder we're extracting from  */
   ULONG offset;           /* uncompressed offset within folder     */
   UBYTE *outpos;          /* (high level) start of data to use up  */
@@ -414,7 +394,7 @@ struct {
     struct QTMstate qtm;
     struct LZXstate lzx;
   } methods;
-} decomp_state;
+};
 
 
 /* MSZIP decruncher */
@@ -447,7 +427,7 @@ static const UWORD Zipmask[17] = {
     b|=((ULONG)c)<<k;k+=8;}}
 #define ZIPDUMPBITS(n) {b>>=(n);k-=(n);}
 
-void Ziphuft_free(struct Ziphuft *t)
+static void Ziphuft_free(struct Ziphuft *t)
 {
   register struct Ziphuft *p, *q;
 
@@ -456,12 +436,12 @@ void Ziphuft_free(struct Ziphuft *t)
   while (p != (struct Ziphuft *)NULL)
   {
     q = (--p)->v.t;
-    free(p);
+    acquire_cabinet_memory_free(p);
     p = q;
   } 
 }
 
-LONG Ziphuft_build(ULONG *b, ULONG n, ULONG s, UWORD *d, UWORD *e,
+static LONG Ziphuft_build(ULONG *b, ULONG n, ULONG s, UWORD *d, UWORD *e,
 struct Ziphuft **t, LONG *m)
 {
   ULONG a;                     /* counter for codes of length k */
@@ -560,7 +540,7 @@ struct Ziphuft **t, LONG *m)
         w += l[h++];            /* add bits already decoded */
 
         /* compute minimum size table less than or equal to *m bits */
-        z = (z = g - w) > (ULONG)*m ? *m : z;        /* upper limit */
+        z = (z = g - w) > (ULONG)*m ? (ULONG)*m : z;        /* upper limit */
         if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
         {                       /* too few codes for k-w bit table */
           f -= a + 1;           /* deduct codes from patterns left */
@@ -578,7 +558,7 @@ struct Ziphuft **t, LONG *m)
         l[h] = j;               /* set table size in stack */
 
         /* allocate and link in new table */
-        if (!(q = (struct Ziphuft *) malloc((z + 1)*sizeof(struct Ziphuft))))
+        if (!(q = (struct Ziphuft *) acquire_cabinet_memory_malloc((z + 1)*sizeof(struct Ziphuft))))
         {
           if(h)
             Ziphuft_free(ZIP(u)[0]);
@@ -638,7 +618,7 @@ struct Ziphuft **t, LONG *m)
   return y != 0 && g != 1;
 }
 
-LONG Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
+static LONG Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
 LONG bl, LONG bd)
 {
   register ULONG e;  /* table entry flag/number of extra bits */
@@ -718,7 +698,7 @@ LONG bl, LONG bd)
   return 0;
 }
 
-LONG Zipinflate_stored(void)
+static LONG Zipinflate_stored(void)
 /* "decompress" an inflated type 0 (stored) block. */
 {
   ULONG n;           /* number of bytes in block */
@@ -759,7 +739,7 @@ LONG Zipinflate_stored(void)
   return 0;
 }
 
-LONG Zipinflate_fixed(void)
+static LONG Zipinflate_fixed(void)
 {
   struct Ziphuft *fixed_tl;
   struct Ziphuft *fixed_td;
@@ -802,7 +782,7 @@ LONG Zipinflate_fixed(void)
   return i;
 }
 
-LONG Zipinflate_dynamic(void)
+static LONG Zipinflate_dynamic(void)
  /* decompress an inflated type 2 (dynamic Huffman codes) block. */
 {
   LONG i;              /* temporary variables */
@@ -932,7 +912,7 @@ LONG Zipinflate_dynamic(void)
   return 0;
 }
 
-LONG Zipinflate_block(LONG *e) /* e == last block flag */
+static LONG Zipinflate_block(LONG *e) /* e == last block flag */
 { /* decompress an inflated block */
   ULONG t;             /* block type */
   register ULONG b;     /* bit buffer */
@@ -967,7 +947,7 @@ LONG Zipinflate_block(LONG *e) /* e == last block flag */
   return 2;
 }
 
-int ZIPdecompress(int inlen, int outlen)
+static int ZIPdecompress(int inlen, int outlen)
 {
   LONG e;               /* last block flag */
 
@@ -1000,7 +980,7 @@ static UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
 static ULONG q_position_base[42];
 
 /* Initialise a model which decodes symbols from [s] to [s]+[n]-1 */
-void QTMinitmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
+static void QTMinitmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
   int i;
   m->shiftsleft = 4;
   m->entries    = n;
@@ -1014,19 +994,19 @@ void QTMinitmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
   m->syms[n].cumfreq = 0;
 }
 
-int QTMinit(int window, int level) {
+static int QTMinit(int window, int level) {
   int wndsize = 1 << window, msz = window * 2, i;
   ULONG j;
 
   /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
   /* if a previously allocated window is big enough, keep it    */
   if (window < 10 || window > 21) return DECR_DATAFORMAT;
-  if (QTM(actual_size) < wndsize) {
-    if (QTM(window)) free(QTM(window));
+  if (QTM(actual_size) < (ULONG)wndsize) {
+    if (QTM(window)) acquire_cabinet_memory_free(QTM(window));
     QTM(window) = NULL;
   }
   if (!QTM(window)) {
-    if (!(QTM(window) = malloc(wndsize))) return DECR_NOMEMORY;
+    if (!(QTM(window) = acquire_cabinet_memory_malloc(wndsize))) return DECR_NOMEMORY;
     QTM(actual_size) = wndsize;
   }
   QTM(window_size) = wndsize;
@@ -1063,7 +1043,7 @@ int QTMinit(int window, int level) {
 }
 
 
-void QTMupdatemodel(struct QTMmodel *model, int sym) {
+static void QTMupdatemodel(struct QTMmodel *model, int sym) {
   struct QTMmodelsym temp;
   int i, j;
 
@@ -1145,7 +1125,7 @@ void QTMupdatemodel(struct QTMmodel *model, int sym) {
 #define Q_INIT_BITSTREAM do { bitsleft = 0; bitbuf = 0; } while (0)
 
 #define Q_FILL_BUFFER do {                                              \
-  if (bitsleft <= (ULONG_BITS - 16)) {                                  \
+  if (bitsleft <= (int)(ULONG_BITS - 16)) {                             \
     bitbuf |= ((inpos[0]<<8)|inpos[1]) << (ULONG_BITS-16 - bitsleft);   \
     bitsleft += 16; inpos += 2;                                         \
   }                                                                     \
@@ -1201,7 +1181,7 @@ void QTMupdatemodel(struct QTMmodel *model, int sym) {
 } while (0)
 
 
-int QTMdecompress(int inlen, int outlen) {
+static int QTMdecompress(int inlen, int outlen) {
   UBYTE *inpos  = CAB(inbuf);
   UBYTE *window = QTM(window);
   UBYTE *runsrc, *rundest;
@@ -1218,9 +1198,10 @@ int QTMdecompress(int inlen, int outlen) {
   UWORD symf;
   int i;
 
-  int extra, togo = outlen, match_length, copy_length;
+  int extra, togo = outlen, match_length = 0; /* Prevent: ... might be used uninitialized in this function */
+  int copy_length;
   UBYTE selector, sym;
-  ULONG match_offset;
+  ULONG match_offset = 0;      /* Prevent: ... might be used uninitialized in this function */
 
   UWORD H = 0xFFFF, L = 0, C;
 
@@ -1381,7 +1362,7 @@ int QTMdecompress(int inlen, int outlen) {
 static ULONG lzx_position_base[51];
 static UBYTE extra_bits[51];
 
-int LZXinit(int window) {
+static int LZXinit(int window) {
   ULONG wndsize = 1 << window;
   int i, j, posn_slots;
 
@@ -1389,11 +1370,11 @@ int LZXinit(int window) {
   /* if a previously allocated window is big enough, keep it     */
   if (window < 15 || window > 21) return DECR_DATAFORMAT;
   if (LZX(actual_size) < wndsize) {
-    if (LZX(window)) free(LZX(window));
+    if (LZX(window)) acquire_cabinet_memory_free(LZX(window));
     LZX(window) = NULL;
   }
   if (!LZX(window)) {
-    if (!(LZX(window) = malloc(wndsize))) return DECR_NOMEMORY;
+    if (!(LZX(window) = acquire_cabinet_memory_malloc(wndsize))) return DECR_NOMEMORY;
     LZX(actual_size) = wndsize;
   }
   LZX(window_size) = wndsize;
@@ -1537,7 +1518,7 @@ int LZXinit(int window) {
  * Returns 0 for OK or 1 for error
  */
 
-int make_decode_table(ULONG nsyms, ULONG nbits, UBYTE *length, UWORD *table) {
+static int make_decode_table(ULONG nsyms, ULONG nbits, UBYTE *length, UWORD *table) {
   register UWORD sym;
   register ULONG leaf;
   register UBYTE bit_num = 1;
@@ -1613,7 +1594,7 @@ struct lzx_bits {
   UBYTE *ip;
 };
 
-int lzx_read_lens(UBYTE *lens, ULONG first, ULONG last, struct lzx_bits *lb) {
+static int lzx_read_lens(UBYTE *lens, ULONG first, ULONG last, struct lzx_bits *lb) {
   ULONG i,j, x,y;
   int z;
 
@@ -1656,7 +1637,7 @@ int lzx_read_lens(UBYTE *lens, ULONG first, ULONG last, struct lzx_bits *lb) {
   return 0;
 }
 
-int LZXdecompress(int inlen, int outlen) {
+static int LZXdecompress(int inlen, int outlen) {
   UBYTE *inpos  = CAB(inbuf);
   UBYTE *endinp = inpos + inlen;
   UBYTE *window = LZX(window);
@@ -1976,6 +1957,7 @@ int LZXdecompress(int inlen, int outlen) {
 
 
 
+#if 0 /* CAPTIVE */
 
 /* all the file IO is abstracted into these routines:
  * cabinet_(open|close|read|seek|skip|getoffset)
@@ -2008,8 +1990,8 @@ int file_open(struct file *fi, int lower, char *dir) {
   char c, *s, *d, *name;
   int ok = 0;
 
-  if (!(name = malloc(strlen(fi->filename) + (dir ? strlen(dir) : 0) + 2))) {
-    fprintf(stderr, "out of memory!\n");
+  if (!(name = acquire_cabinet_memory_malloc(strlen(fi->filename) + (dir ? strlen(dir) : 0) + 2))) {
+    g_warning(_("out of memory!"));
     return 0;
   }
   
@@ -2044,7 +2026,7 @@ int file_open(struct file *fi, int lower, char *dir) {
   }
 
   /* as full filename is no longer needed, free it */
-  free(name);
+  acquire_cabinet_memory_free(name);
 
   if (!ok) {
     perror(fi->filename);
@@ -2052,6 +2034,7 @@ int file_open(struct file *fi, int lower, char *dir) {
   return ok;
 }
 
+
 /* closes a completed file, updates protections and timestamp */
 void file_close(struct file *fi) {
   struct utimbuf utb;
@@ -2092,7 +2075,6 @@ int file_write(struct file *fi, UBYTE *buf, size_t length) {
   return 1;
 }
 
-
 void cabinet_close(struct cabinet *cab) {
   if (cab->fh) {
     fclose(cab->fh);
@@ -2100,36 +2082,37 @@ void cabinet_close(struct cabinet *cab) {
   cab->fh = NULL;
 }
 
-void cabinet_seek(struct cabinet *cab, off_t offset) {
-  if (fseek(cab->fh, offset, SEEK_SET) < 0) {
-    perror(cab->filename);
-  }
+#endif /* CAPTIVE */
+
+static void cabinet_seek(struct cabinet *cab, off_t offset) {
+  acquire_cabinet_seek(cab->acquire_cabinet,offset);
 }
 
-void cabinet_skip(struct cabinet *cab, off_t distance) {
-  if (fseek(cab->fh, distance, SEEK_CUR) < 0) {
-    perror(cab->filename);
-  }
+static void cabinet_skip(struct cabinet *cab, off_t distance) {
+  acquire_cabinet_seek_skip(cab->acquire_cabinet,distance);
 }
 
-off_t cabinet_getoffset(struct cabinet *cab) {
-  return ftell(cab->fh);
+static off_t cabinet_getoffset(struct cabinet *cab) {
+  return acquire_cabinet_tell(cab->acquire_cabinet);
 }
 
 /* read data from a cabinet, returns success */
-int cabinet_read(struct cabinet *cab, UBYTE *buf, size_t length) {
-  size_t avail = (size_t) (cab->filelen - cabinet_getoffset(cab));
-  if (length > avail) {
-    fprintf(stderr, "%s: WARNING; cabinet is truncated\n", cab->filename);
-    length = avail;
-  }
-  if (fread((void *)buf, 1, length, cab->fh) != length) {
-    perror(cab->filename);
+static int cabinet_read(struct cabinet *cab, UBYTE *buf, size_t length) {
+  GnomeVFSResult errvfsresult;
+  GnomeVFSFileSize bytes_read;
+
+  errvfsresult=acquire_cabinet_read(cab->acquire_cabinet,buf,length,&bytes_read);
+  if (errvfsresult!=GNOME_VFS_OK) {
+    g_warning(_("%s: cabinet read error: %s"), cab->filename, gnome_vfs_result_to_string(errvfsresult));
     return 0;
   }
+  if (bytes_read!=length)
+    g_warning(_("%s: WARNING; cabinet is truncated"), cab->filename);
   return 1;
 }
 
+#if 0 /* CAPTIVE */
+
 /* try to open a cabinet file, returns success */
 int cabinet_open(struct cabinet *cab) {
   char *name = cab->filename;
@@ -2162,14 +2145,16 @@ int cabinet_open(struct cabinet *cab) {
   return 1;
 }
 
+#endif /* CAPTIVE */
+
 /* allocate and read an aribitrarily long string from the cabinet */
-char *cabinet_read_string(struct cabinet *cab) {
+static char *cabinet_read_string(struct cabinet *cab) {
   off_t len=256, base = cabinet_getoffset(cab), maxlen = cab->filelen - base;
   int ok = 0, i;
   UBYTE *buf = NULL;
   do {
     if (len > maxlen) len = maxlen;
-    if (!(buf = realloc(buf, (size_t) len))) break;
+    if (!(buf = acquire_cabinet_memory_realloc(buf, (size_t) len))) break;
     if (!cabinet_read(cab, buf, (size_t) len)) break;
 
     /* search for a null terminator in what we've just read */
@@ -2179,7 +2164,7 @@ char *cabinet_read_string(struct cabinet *cab) {
 
     if (!ok) {
       if (len == maxlen) {
-        fprintf(stderr, "%s: WARNING; cabinet is truncated\n", cab->filename);
+        g_warning(_("%s: WARNING; cabinet is truncated"), cab->filename);
         break;
       }
       len += 256;
@@ -2188,7 +2173,7 @@ char *cabinet_read_string(struct cabinet *cab) {
   } while (!ok);
 
   if (!ok) {
-    if (buf) free(buf); else fprintf(stderr, "out of memory!\n");
+    if (buf) acquire_cabinet_memory_free(buf); else g_warning(_("out of memory!"));
     return NULL;
   }
 
@@ -2198,7 +2183,7 @@ char *cabinet_read_string(struct cabinet *cab) {
 }
 
 /* reads the header and all folder and file entries in this cabinet */
-int cabinet_read_entries(struct cabinet *cab) {
+static int cabinet_read_entries(struct cabinet *cab) {
   int num_folders, num_files, header_resv, folder_resv = 0, i;
   struct folder *fol, *linkfol = NULL;
   struct file *file, *linkfile = NULL;
@@ -2213,21 +2198,21 @@ int cabinet_read_entries(struct cabinet *cab) {
   
   /* check basic MSCF signature */
   if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
-    fprintf(stderr, "%s: not a Microsoft cabinet file\n", cab->filename);
+    g_warning(_("%s: not a Microsoft cabinet file"), cab->filename);
     return 0;
   }
 
   /* get the number of folders */
   num_folders = EndGetI16(buf+cfhead_NumFolders);
   if (num_folders == 0) {
-    fprintf(stderr, "%s: no folders in cabinet\n", cab->filename);
+    g_warning(_("%s: no folders in cabinet"), cab->filename);
     return 0;
   }
 
   /* get the number of files */
   num_files = EndGetI16(buf+cfhead_NumFiles);
   if (num_files == 0) {
-    fprintf(stderr, "%s: no files in cabinet\n", cab->filename);
+    g_warning(_("%s: no files in cabinet"), cab->filename);
     return 0;
   }
 
@@ -2235,7 +2220,7 @@ int cabinet_read_entries(struct cabinet *cab) {
   if ((buf[cfhead_MajorVersion] > 1) ||
       (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
   {
-    fprintf(stderr, "%s: WARNING; cabinet format version > 1.3\n",
+    g_warning(_("%s: WARNING; cabinet format version > 1.3"),
            cab->filename);
   }
 
@@ -2248,24 +2233,26 @@ int cabinet_read_entries(struct cabinet *cab) {
     cab->block_resv = buf[cfheadext_DataReserved];
 
     if (header_resv > 60000) {
-      fprintf(stderr, "%s: WARNING; header reserved space > 60000\n",
+      g_warning(_("%s: WARNING; header reserved space > 60000"),
              cab->filename);
     }
 
     /* skip the reserved header */
-    if (header_resv) fseek(cab->fh, (off_t) header_resv, SEEK_CUR);
+    if (header_resv) cabinet_skip(cab, (off_t) header_resv);
   }
 
   if (cab->flags & cfheadPREV_CABINET) {
     cab->prevname = cabinet_read_string(cab);
     if (!cab->prevname) return 0;
     cab->previnfo = cabinet_read_string(cab);
+    if (!cab->previnfo) return 0;
   }
 
   if (cab->flags & cfheadNEXT_CABINET) {
     cab->nextname = cabinet_read_string(cab);
     if (!cab->nextname) return 0;
     cab->nextinfo = cabinet_read_string(cab);
+    if (!cab->nextinfo) return 0;
   }
 
   /* read folders */
@@ -2273,8 +2260,8 @@ int cabinet_read_entries(struct cabinet *cab) {
     if (!cabinet_read(cab, buf, cffold_SIZEOF)) return 0;
     if (folder_resv) cabinet_skip(cab, folder_resv);
 
-    fol = (struct folder *) calloc(1, sizeof(struct folder));
-    if (!fol) { fprintf(stderr, "out of memory!\n"); return 0; }
+    fol = (struct folder *) acquire_cabinet_memory_malloc0(sizeof(struct folder));
+    if (!fol) { g_warning(_("out of memory!")); return 0; }
 
     fol->cab[0]     = cab;
     fol->offset[0]  = base_offset + (off_t) EndGetI32(buf+cffold_DataOffset);
@@ -2288,8 +2275,8 @@ int cabinet_read_entries(struct cabinet *cab) {
   /* read files */
   for (i = 0; i < num_files; i++) {
     if (!cabinet_read(cab, buf, cffile_SIZEOF)) return 0;
-    file = (struct file *) calloc(1, sizeof(struct file));
-    if (!file) { fprintf(stderr, "out of memory!\n"); return 0; }
+    file = (struct file *) acquire_cabinet_memory_malloc0(sizeof(struct file));
+    if (!file) { g_warning(_("out of memory!")); return 0; }
       
     file->length   = EndGetI32(buf+cffile_UncompressedSize);
     file->offset   = EndGetI32(buf+cffile_FolderOffset);
@@ -2359,7 +2346,7 @@ struct file *process_files(struct cabinet *basecab) {
               /* increase the number of splits */
               if ((i = ++(predfol->num_splits)) > CAB_SPLITMAX) {
                 mergeok = 0;
-                fprintf(stderr, "%s: internal error, increase CAB_SPLITMAX\n",
+                g_warning(_("%s: internal error, increase CAB_SPLITMAX"),
                   basecab->filename);
               }
               else {
@@ -2398,20 +2385,21 @@ struct file *process_files(struct cabinet *basecab) {
  * file [name]. Returns a cabinet structure if successful, or NULL
  * otherwise.
  */
-struct cabinet *load_cab_offset(char *name, off_t offset) {
-  struct cabinet *cab = (struct cabinet *) calloc(1, sizeof(struct cabinet));
+static struct cabinet *load_cab_offset(struct acquire_cabinet *acquire_cabinet, off_t offset) {
+  struct cabinet *cab = (struct cabinet *) acquire_cabinet_memory_malloc0(sizeof(struct cabinet));
   int ok;
   if (!cab) return NULL;
 
-  cab->filename = name;
-  if ((ok = cabinet_open(cab))) {
-    cabinet_seek(cab, offset);
-    ok = cabinet_read_entries(cab);
-    cabinet_close(cab);
-  }
+  cab->acquire_cabinet = acquire_cabinet;
+  cab->filename = cab->acquire_cabinet->filename;
+  /* if ((ok = cabinet_open(cab))) * CAPTIVE */
+  cab->filelen = acquire_cabinet->size;
+  cabinet_seek(cab, offset);
+  ok = cabinet_read_entries(cab);
+  /* cabinet_close(cab); * CAPTIVE */
 
   if (ok) return cab;
-  free(cab);
+  acquire_cabinet_memory_free(cab);
   return NULL;
 }
 
@@ -2421,19 +2409,23 @@ struct cabinet *load_cab_offset(char *name, off_t offset) {
  * member.
  */
 #define SEARCH_SIZE (32*1024)
-UBYTE search_buf[SEARCH_SIZE];
+static UBYTE search_buf[SEARCH_SIZE];
 
-struct cabinet *find_cabs_in_file(char *name) {
+struct cabinet *find_cabs_in_file(struct acquire_cabinet *acquire_cabinet) {
   struct cabinet *cab, *cab2, *firstcab = NULL, *linkcab = NULL;
   UBYTE *pstart = &search_buf[0], *pend, *p;
-  ULONG offset, caboff, cablen, foffset, filelen;
+  ULONG offset, caboff, cablen = 0;    /* Prevent: ... might be used uninitialized in this function */
+  ULONG foffset = 0;   /* Prevent: ... might be used uninitialized in this function */
+  ULONG filelen;
   size_t length;
   int state = 0, found = 0, ok = 0;
 
   /* open the file and search for cabinet headers */
-  if ((cab = (struct cabinet *) calloc(1, sizeof(struct cabinet)))) {
-    cab->filename = name;
-    if (cabinet_open(cab)) {
+  if ((cab = (struct cabinet *) acquire_cabinet_memory_malloc0(sizeof(struct cabinet)))) {
+    cab->acquire_cabinet = acquire_cabinet;
+    cab->filename = acquire_cabinet->filename;
+    cab->filelen = acquire_cabinet->size;
+    if (1 /* cabinet_open(cab) * CAPTIVE */) {
       filelen = (ULONG) cab->filelen;
       for (offset = 0; offset < filelen; offset += length) {
        /* search length is either the full length of the search buffer,
@@ -2492,7 +2484,7 @@ struct cabinet *find_cabs_in_file(char *name) {
            {
              /* found a potential result - try loading it */
              found++;
-             cab2 = load_cab_offset(name, (off_t) caboff);
+             cab2 = load_cab_offset(acquire_cabinet, (off_t) caboff);
              if (cab2) {
                /* success */
                ok++;
@@ -2516,23 +2508,25 @@ struct cabinet *find_cabs_in_file(char *name) {
          }
        }
       }
-      cabinet_close(cab);
+      /* cabinet_close(cab); * CAPTIVE */
     }
-    free(cab);
+    acquire_cabinet_memory_free(cab);
   }
 
   /* if there were cabinets that were found but are not ok, point this out */
   if (found > ok) {
-    fprintf(stderr, "%s: WARNING; found %d bad cabinets\n", name, found-ok);
+    g_warning(_("%s: WARNING; found %d bad cabinets"), acquire_cabinet->filename, found-ok);
   }
 
   /* if no cabinets were found, let the user know */
   if (!firstcab) {
-    fprintf(stderr, "%s: not a Microsoft cabinet file.\n", name);
+    g_warning(_("%s: not a Microsoft cabinet file."), acquire_cabinet->filename);
   }
   return firstcab;
 }
 
+#if 0 /* CAPTIVE */
+
 /* UTF translates two-byte unicode characters into 1, 2 or 3 bytes.
  * %000000000xxxxxxx -> %0xxxxxxx
  * %00000xxxxxyyyyyy -> %110xxxxx %10yyyyyy
@@ -2548,7 +2542,7 @@ struct cabinet *find_cabs_in_file(char *name) {
  */
 
 /* translate UTF -> ASCII */
-int convertUTF(UBYTE *in) {
+static int convertUTF(UBYTE *in) {
   UBYTE c, *out = in, *end = in + strlen((char *) in) + 1;
   ULONG x;
 
@@ -2582,7 +2576,7 @@ void print_fileinfo(struct file *fi) {
   char *fname = NULL;
 
   if (fi->attribs & cffile_A_NAME_IS_UTF) {
-    fname = malloc(strlen(fi->filename) + 1);
+    fname = acquire_cabinet_memory_malloc(strlen(fi->filename) + 1);
     if (fname) {
       strcpy(fname, fi->filename);
       convertUTF((UBYTE *) fname);
@@ -2596,16 +2590,18 @@ void print_fileinfo(struct file *fi) {
     fname ? fname : fi->filename
   );
 
-  if (fname) free(fname);
+  if (fname) acquire_cabinet_memory_free(fname);
 }
 
-int NONEdecompress(int inlen, int outlen) {
+#endif /* CAPTIVE */
+
+static int NONEdecompress(int inlen, int outlen) {
   if (inlen != outlen) return DECR_ILLEGALDATA;
   memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
   return DECR_OK;
 }
 
-ULONG checksum(UBYTE *data, UWORD bytes, ULONG csum) {
+static ULONG checksum(UBYTE *data, UWORD bytes, ULONG csum) {
   int len;
   ULONG ul = 0;
 
@@ -2623,7 +2619,9 @@ ULONG checksum(UBYTE *data, UWORD bytes, ULONG csum) {
   return csum;
 }
 
-int decompress(struct file *fi, int savemode, int fix) {
+int file_write(struct file *fi, UBYTE *buf, size_t length);
+
+static int decompress(struct file *fi, int savemode, int fix) {
   ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
   struct cabinet *cab = CAB(current)->cab[CAB(split)];
   UBYTE buf[cfdata_SIZEOF], *data;
@@ -2649,7 +2647,19 @@ int decompress(struct file *fi, int savemode, int fix) {
     inlen = outlen = 0;
     while (outlen == 0) {
       /* read the block header, skip the reserved part */
-      if (!cabinet_read(cab, buf, cfdata_SIZEOF)) return DECR_INPUT;
+      if ((NONEdecompress==CAB(decompress) && !savemode && bytes>32768)) {
+       cabinet_skip(cab, cfdata_SIZEOF);
+       memset(buf + cfdata_CheckSum, 0, 4);    /* no CheckSum */
+       /* FIXME: Is it safe to assume 'NONEdecompress' block size 32768?
+        * Probably not but we need to prevent scattering block headers through the file.
+        */
+       buf[cfdata_CompressedSize   + 0]=(32768>>0)&0xFF;
+       buf[cfdata_CompressedSize   + 1]=(32768>>8)&0xFF;
+       buf[cfdata_UncompressedSize + 0]=(32768>>0)&0xFF;
+       buf[cfdata_UncompressedSize + 1]=(32768>>8)&0xFF;
+      } else {
+       if (!cabinet_read(cab, buf, cfdata_SIZEOF)) return DECR_INPUT;
+      }
       cabinet_skip(cab, cab->block_resv);
 
       /* we shouldn't get blocks over CAB_INPUTMAX in size */
@@ -2657,45 +2667,57 @@ int decompress(struct file *fi, int savemode, int fix) {
       len = EndGetI16(buf+cfdata_CompressedSize);
       inlen += len;
       if (inlen > CAB_INPUTMAX) return DECR_INPUT;
-      if (!cabinet_read(cab, data, len)) return DECR_INPUT;
+      if ((NONEdecompress==CAB(decompress) && !savemode && bytes>32768)) {
+       cabinet_skip(cab, len);
+      } else {
+       if (!cabinet_read(cab, data, len)) return DECR_INPUT;
+      }
 
       /* clear two bytes after read-in data */
       data[len+1] = data[len+2] = 0;
 
       /* perform checksum test on the block (if one is stored) */
       cksum = EndGetI32(buf+cfdata_CheckSum);
-      if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0))) {
-       /* checksum is wrong */
-       if (fix && ((fi->folder->comp_type & cffoldCOMPTYPE_MASK)
-                   == cffoldCOMPTYPE_MSZIP))
-        {
-         fprintf(stderr, "%s: WARNING; checksum failed\n", fi->filename); 
-       }
-       else {
-         return DECR_CHECKSUM;
+      if (!(NONEdecompress==CAB(decompress) && !savemode && bytes>32768)) {
+       if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0))) {
+         /* checksum is wrong */
+         if (fix && ((fi->folder->comp_type & cffoldCOMPTYPE_MASK)
+                     == cffoldCOMPTYPE_MSZIP))
+         {
+           g_warning(_("%s: WARNING; checksum failed"), fi->filename); 
+         }
+         else {
+           return DECR_CHECKSUM;
+         }
        }
       }
 
       /* outlen=0 means this block was part of a split block */
       outlen = EndGetI16(buf+cfdata_UncompressedSize);
       if (outlen == 0) {
+#if 0 /* CAPTIVE */
         cabinet_close(cab);
         cab = CAB(current)->cab[++CAB(split)];
         if (!cabinet_open(cab)) return DECR_INPUT;
         cabinet_seek(cab, CAB(current)->offset[CAB(split)]);
+#else
+        return DECR_INPUT;
+#endif
       }
     }
 
-    /* decompress block */
-    if ((err = CAB(decompress)(inlen, outlen))) {
-      if (fix && ((fi->folder->comp_type & cffoldCOMPTYPE_MASK)
-                 == cffoldCOMPTYPE_MSZIP))
-      {
-       fprintf(stderr, "%s: WARNING; failed decrunching block\n",
-               fi->filename); 
-      }
-      else {
-       return err;
+    if (!(NONEdecompress==CAB(decompress) && !savemode && bytes>32768)) {
+      /* decompress block */
+      if ((err = CAB(decompress)(inlen, outlen))) {
+       if (fix && ((fi->folder->comp_type & cffoldCOMPTYPE_MASK)
+                   == cffoldCOMPTYPE_MSZIP))
+       {
+         g_warning(_("%s: WARNING; failed decrunching block"),
+                 fi->filename); 
+       }
+       else {
+         return err;
+       }
       }
     }
     CAB(outlen) = outlen;
@@ -2706,7 +2728,7 @@ int decompress(struct file *fi, int savemode, int fix) {
 }
 
 
-void extract_file(struct file *fi, int lower, int fix, char *dir) {
+int extract_file(struct file *fi, int lower, int fix, char *dir) {
   struct folder *fol = fi->folder, *oldfol = CAB(current);
   LONG err = DECR_OK;
 
@@ -2721,13 +2743,13 @@ void extract_file(struct file *fi, int lower, int fix, char *dir) {
       switch (ct2) {
       case cffoldCOMPTYPE_LZX:
         if (LZX(window)) {
-         free(LZX(window));
+         acquire_cabinet_memory_free(LZX(window));
          LZX(window) = NULL;
        }
        break;
       case cffoldCOMPTYPE_QUANTUM:
        if (QTM(window)) {
-         free(QTM(window));
+         acquire_cabinet_memory_free(QTM(window));
          QTM(window) = NULL;
        }
        break;
@@ -2759,8 +2781,13 @@ void extract_file(struct file *fi, int lower, int fix, char *dir) {
     if (err) goto exit_handler;
 
     /* initialisation OK, set current folder and reset offset */
+#if 0 /* CAPTIVE */
     if (oldfol) cabinet_close(oldfol->cab[CAB(split)]);
-    if (!cabinet_open(fol->cab[0])) goto exit_handler;
+    if (!cabinet_open(fol->cab[0])) {
+      err = DECR_ILLEGALDATA;
+      goto exit_handler;
+      }
+#endif /* CAPTIVE */
     cabinet_seek(fol->cab[0], fol->offset[0]);
     CAB(current) = fol;
     CAB(offset) = 0;
@@ -2773,29 +2800,33 @@ void extract_file(struct file *fi, int lower, int fix, char *dir) {
     if ((err = decompress(fi, 0, fix))) goto exit_handler;
     CAB(offset) = fi->offset;
   }
-  if (!file_open(fi, lower, dir)) return;
+#if 0 /* CAPTIVE */
+  if (!file_open(fi, lower, dir)) return 0;
+#endif /* CAPTIVE */
   err = decompress(fi, 1, fix);
   if (err) CAB(current) = NULL; else CAB(offset) += fi->length;
+#if 0 /* CAPTIVE */
   file_close(fi);
+#endif /* CAPTIVE */
 
 exit_handler:
   if (err) {
-    char *errmsg, *cabname;
+    const char *errmsg, *cabname;
     switch (err) {
     case DECR_NOMEMORY:
-      errmsg = "out of memory!\n"; break;
+      errmsg = _("out of memory!"); break;
     case DECR_ILLEGALDATA:
-      errmsg = "%s: illegal or corrupt data\n"; break;
+      errmsg = _("%s: illegal or corrupt data"); break;
     case DECR_DATAFORMAT:
-      errmsg = "%s: unsupported data format\n"; break;
+      errmsg = _("%s: unsupported data format"); break;
     case DECR_CHECKSUM:
-      errmsg = "%s: checksum error\n"; break;
+      errmsg = _("%s: checksum error"); break;
     case DECR_INPUT:
-      errmsg = "%s: input error\n"; break;
+      errmsg = _("%s: input error"); break;
     case DECR_OUTPUT:
-      errmsg = "%s: output error\n"; break;
+      errmsg = _("%s: output error"); break;
     default:
-      errmsg = "%s: unknown error (BUG)\n";
+      errmsg = _("%s: unknown error (BUG)");
     }
 
     if (CAB(current)) {
@@ -2805,10 +2836,14 @@ exit_handler:
       cabname = fi->folder->cab[0]->filename;
     }
 
-    fprintf(stderr, errmsg, cabname);
+    g_warning(errmsg, cabname);
+    return 0;
   }
+  return 1;
 }
 
+#if 0 /* CAPTIVE */
+
 /* tries to find *cabname, from the directory path of origcab, correcting the
  * case of *cabname if necessary, If found, writes back to *cabname.
  */
@@ -2825,7 +2860,7 @@ void find_cabinet_file(char **cabname, char *origcab) {
   /* find if there's a directory path in the origcab */
   tail = origcab ? strrchr(origcab, '/') : NULL;
 
-  if ((cab = (char *) malloc((tail ? tail-origcab : 1) + strlen(name) + 2))) {
+  if ((cab = (char *) acquire_cabinet_memory_malloc((tail ? tail-origcab : 1) + strlen(name) + 2))) {
     /* add the directory path from the original cabinet name */
     if (tail) {
       memcpy(cab, origcab, tail-origcab);
@@ -2880,15 +2915,16 @@ void find_cabinet_file(char **cabname, char *origcab) {
      * otherwise, pretend nothing happened
      */
     if (found) {
-      free((void *) *cabname);
+      acquire_cabinet_memory_free((void *) *cabname);
       *cabname = cab;
     }
     else {
-      free((void *) cab);
+      acquire_cabinet_memory_free((void *) cab);
     }
   }
 }
 
+
 /* process_cabinet() is called by main() for every file listed on the
  * command line. It will find every cabinet file in that file, and will
  * search for every chained cabinet attached to those cabinets, then it
@@ -2921,7 +2957,7 @@ int process_cabinet(char *cabname, char *dir,
                         cab1->prevname, cab1->previnfo);
       find_cabinet_file(&(cab1->prevname), cabname);
       if (!(cab1->prevcab = load_cab_offset(cab1->prevname, 0))) {
-        fprintf(stderr, "%s: can't read previous cabinet %s\n",
+        g_warning(_("%s: can't read previous cabinet %s"),
                cabname, cab1->prevname);
         break;
       }
@@ -2934,7 +2970,7 @@ int process_cabinet(char *cabname, char *dir,
                         cab2->nextname, cab2->nextinfo);
       find_cabinet_file(&(cab2->nextname), cabname);
       if (!(cab2->nextcab = load_cab_offset(cab2->nextname, 0))) {
-        fprintf(stderr, "%s: can't read next cabinet %s\n",
+        g_warning(_("%s: can't read next cabinet %s"),
                cabname, cab2->nextname);
         break;
       }
@@ -3031,3 +3067,5 @@ int main(int argc, char *argv[]) {
 
   return err;
 }
+
+#endif /* CAPTIVE */