X-Git-Url: http://git.jankratochvil.net/?p=captive.git;a=blobdiff_plain;f=src%2Finstall%2Facquire%2Fcabextract%2Fcabextract.c;h=d83803fb60f6a57230096c2a297584637fde31fd;hp=ade7d8cfbf2f936a81b7782ec710c72e2a0af753;hb=e66925ff9c2fca5df2b0a3e38dfbdc03e0cb9a12;hpb=a089075dd3fe0752465e6b7205f4f54ac6f897ab diff --git a/src/install/acquire/cabextract/cabextract.c b/src/install/acquire/cabextract/cabextract.c index ade7d8c..d83803f 100644 --- a/src/install/acquire/cabextract/cabextract.c +++ b/src/install/acquire/cabextract/cabextract.c @@ -1,5 +1,7 @@ /* cabextract 0.6 - a program to extract Microsoft Cabinet files * (C) 2000-2002 Stuart Caie + * Modifications for Captive project by: + * Copyright (C) 2003 Jan Kratochvil * * 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 @@ -147,6 +151,12 @@ extern time_t mktime(struct tm *tp); #endif +#include +#include +#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)<>=(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 */