12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922 |
- /*
- zipup.c - Zip 3
- Copyright (c) 1990-2008 Info-ZIP. All rights reserved.
- See the accompanying file LICENSE, version 2007-Mar-4 or later
- (the contents of which are also included in zip.h) for terms of use.
- If, for some reason, all these files are missing, the Info-ZIP license
- also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
- */
- /*
- * zipup.c by Mark Adler and Jean-loup Gailly.
- */
- #define __ZIPUP_C
- /* Found that for at least unix port zip.h has to be first or ctype.h will
- define off_t and when using 64-bit file environment off_t in other files
- is 8 bytes while off_t here is 4 bytes, and this makes the zlist struct
- different sizes and needless to say leads to segmentation faults. Putting
- zip.h first seems to fix this. 8/14/04 EG */
- #include "zip.h"
- #include <ctype.h>
- #include <errno.h>
- #ifndef UTIL /* This module contains no code for Zip Utilities */
- #include "revision.h"
- #include "crc32.h"
- #include "crypt.h"
- #ifdef USE_ZLIB
- # include "zlib.h"
- #endif
- #ifdef BZIP2_SUPPORT
- # ifdef BZIP2_USEBZIP2DIR
- # include "bzip2/bzlib.h"
- # else
- # include "bzlib.h"
- # endif
- #endif
- #ifdef OS2
- # include "os2/os2zip.h"
- #endif
- #if defined(MMAP)
- # include <sys/mman.h>
- # ifndef PAGESIZE /* used to be SYSV, what about pagesize on SVR3 ? */
- # define PAGESIZE getpagesize()
- # endif
- # if defined(NO_VALLOC) && !defined(valloc)
- # define valloc malloc
- # endif
- #endif
- /* Use the raw functions for MSDOS and Unix to save on buffer space.
- They're not used for VMS since it doesn't work (raw is weird on VMS).
- */
- #ifdef AMIGA
- # include "amiga/zipup.h"
- #endif /* AMIGA */
- #ifdef AOSVS
- # include "aosvs/zipup.h"
- #endif /* AOSVS */
- #ifdef ATARI
- # include "atari/zipup.h"
- #endif
- #ifdef __BEOS__
- # include "beos/zipup.h"
- #endif
- #ifdef __ATHEOS__
- # include "atheos/zipup.h"
- #endif /* __ATHEOS__ */
- #ifdef __human68k__
- # include "human68k/zipup.h"
- #endif /* __human68k__ */
- #ifdef MACOS
- # include "macos/zipup.h"
- #endif
- #ifdef DOS
- # include "msdos/zipup.h"
- #endif /* DOS */
- #ifdef NLM
- # include "novell/zipup.h"
- # include <nwfattr.h>
- #endif
- #ifdef OS2
- # include "os2/zipup.h"
- #endif /* OS2 */
- #ifdef RISCOS
- # include "acorn/zipup.h"
- #endif
- #ifdef TOPS20
- # include "tops20/zipup.h"
- #endif
- #ifdef UNIX
- # include "unix/zipup.h"
- #endif
- #ifdef CMS_MVS
- # include "zipup.h"
- #endif /* CMS_MVS */
- #ifdef TANDEM
- # include "zipup.h"
- #endif /* TANDEM */
- #ifdef VMS
- # include "vms/zipup.h"
- #endif /* VMS */
- #ifdef QDOS
- # include "qdos/zipup.h"
- #endif /* QDOS */
- #ifdef WIN32
- # include "win32/zipup.h"
- #endif
- #ifdef THEOS
- # include "theos/zipup.h"
- #endif
- /* Local functions */
- #ifndef RISCOS
- local int suffixes OF((char *, char *));
- #else
- local int filetypes OF((char *, char *));
- #endif
- local unsigned file_read OF((char *buf, unsigned size));
- #ifdef USE_ZLIB
- local int zl_deflate_init OF((int pack_level));
- #else /* !USE_ZLIB */
- # ifdef ZP_NEED_MEMCOMPR
- local unsigned mem_read OF((char *buf, unsigned size));
- # endif
- #endif /* ?USE_ZLIB */
- /* zip64 support 08/29/2003 R.Nausedat */
- local zoff_t filecompress OF((struct zlist far *z_entry, int *cmpr_method));
- #ifdef BZIP2_SUPPORT
- local zoff_t bzfilecompress OF((struct zlist far *z_entry, int *cmpr_method));
- #endif
- /* Deflate "internal" global data (currently not in zip.h) */
- #if defined(MMAP) || defined(BIG_MEM)
- # ifdef USE_ZLIB
- local uch *window = NULL; /* Used to read all input file at once */
- local ulg window_size; /* size of said window */
- # else /* !USE_ZLIB */
- extern uch *window; /* Used to read all input file at once */
- #endif /* ?USE_ZLIB */
- #endif /* MMAP || BIG_MEM */
- #ifndef USE_ZLIB
- extern ulg window_size; /* size of said window */
- unsigned (*read_buf) OF((char *buf, unsigned size)) = file_read;
- /* Current input function. Set to mem_read for in-memory compression */
- #endif /* !USE_ZLIB */
- /* Local data */
- local ulg crc; /* crc on uncompressed file data */
- local ftype ifile; /* file to compress */
- #if defined(MMAP) || defined(BIG_MEM)
- local ulg remain;
- /* window bytes not yet processed.
- * special value "(ulg)-1L" reserved to signal normal reads.
- */
- #endif /* MMAP || BIG_MEM */
- #ifdef USE_ZLIB
- local int deflInit = FALSE; /* flag: zlib deflate is initialized */
- local z_stream zstrm; /* zlib's data interface structure */
- local char *f_ibuf = NULL;
- local char *f_obuf = NULL;
- #else /* !USE_ZLIB */
- local char file_outbuf[1024]; /* output buffer for compression to file */
- # ifdef ZP_NEED_MEMCOMPR
- local char *in_buf;
- /* Current input buffer, in_buf is used only for in-memory compression. */
- local unsigned in_offset;
- /* Current offset in input buffer. in_offset is used only for in-memory
- * compression. On 16 bit machines, the buffer is limited to 64K.
- */
- local unsigned in_size; /* size of current input buffer */
- # endif /* ZP_NEED_MEMCOMPR */
- #endif /* ?USE_ZLIB */
- #ifdef BZIP2_SUPPORT
- local int bzipInit; /* flag: bzip2lib is initialized */
- local bz_stream bstrm; /* zlib's data interface structure */
- # if !defined(USE_ZLIB)
- local char *f_ibuf = NULL;
- local char *f_obuf = NULL;
- # endif /* !USE_ZLIB */
- #endif /* BZIP2_SUPPORT */
- #ifdef DEBUG
- zoff_t isize; /* input file size. global only for debugging */
- #else /* !DEBUG */
- local zoff_t isize; /* input file size. global only for debugging */
- #endif /* ?DEBUG */
- /* If file_read detects binary it sets this flag - 12/16/04 EG */
- local int file_binary = 0; /* first buf */
- local int file_binary_final = 0; /* for bzip2 for entire file. assume text until find binary */
- /* moved check to function 3/14/05 EG */
- int is_seekable(y)
- FILE *y;
- {
- zoff_t pos;
- #ifdef BROKEN_FSEEK
- if (!fseekable(y)) {
- return 0;
- }
- #endif
- pos = zftello(y);
- if (zfseeko(y, pos, SEEK_SET)) {
- return 0;
- }
- return 1;
- }
- int percent(n, m)
- uzoff_t n;
- uzoff_t m; /* n is the original size, m is the new size */
- /* Return the percentage compression from n to m using only integer
- operations */
- {
- zoff_t p;
- #if 0
- if (n > 0xffffffL) /* If n >= 16M */
- { /* then divide n and m by 256 */
- n += 0x80; n >>= 8;
- m += 0x80; m >>= 8;
- }
- return n > m ? (int)(1 + (200 * (n - m)/n)) / 2 : 0;
- #endif
- /* 2004-12-01 SMS.
- * Changed to do big-n test only for small zoff_t.
- * Changed big-n arithmetic to accomodate apparently negative values
- * when a small zoff_t value exceeds 2G.
- * Increased the reduction divisor from 256 to 512 to avoid the sign bit
- * in a reduced intermediate, allowing signed arithmetic for the final
- * result (which is no longer artificially limited to non-negative
- * values).
- * Note that right shifts must be on unsigned values to avoid undesired
- * sign extension.
- */
- /* Handle n = 0 case and account for int maybe being 16-bit. 12/28/2004 EG
- */
- #define PC_MAX_SAFE 0x007fffffL /* 9 clear bits at high end. */
- #define PC_MAX_RND 0xffffff00L /* 8 clear bits at low end. */
- if (sizeof(uzoff_t) < 8) /* Don't fiddle with big zoff_t. */
- {
- if ((ulg)n > PC_MAX_SAFE) /* Reduce large values. (n > m) */
- {
- if ((ulg)n < PC_MAX_RND) /* Divide n by 512 with rounding, */
- n = ((ulg)n + 0x100) >> 9; /* if boost won't overflow. */
- else /* Otherwise, use max value. */
- n = PC_MAX_SAFE;
- if ((ulg)m < PC_MAX_RND) /* Divide m by 512 with rounding, */
- m = ((ulg)m + 0x100) >> 9; /* if boost won't overflow. */
- else /* Otherwise, use max value. */
- m = PC_MAX_SAFE;
- }
- }
- if (n != 0)
- p = ((200 * ((zoff_t)n - (zoff_t)m) / (zoff_t)n) + 1) / 2;
- else
- p = 0;
- return (int)p; /* Return (rounded) % reduction. */
- }
- #ifndef RISCOS
- local int suffixes(a, s)
- char *a; /* name to check suffix of */
- char *s; /* list of suffixes separated by : or ; */
- /* Return true if a ends in any of the suffixes in the list s. */
- {
- int m; /* true if suffix matches so far */
- char *p; /* pointer into special */
- char *q; /* pointer into name a */
- #ifdef QDOS
- short dlen = devlen(a);
- a = a + dlen;
- #endif
- m = 1;
- #ifdef VMS
- if( (q = strrchr(a,';')) != NULL ) /* Cut out VMS file version */
- --q;
- else
- q = a + strlen(a) - 1;
- #else /* !VMS */
- q = a + strlen(a) - 1;
- #endif /* ?VMS */
- for (p = s + strlen(s) - 1; p >= s; p--)
- if (*p == ':' || *p == ';')
- {
- if (m)
- return 1;
- else
- {
- m = 1;
- #ifdef VMS
- if( (q = strrchr(a,';')) != NULL ) /* Cut out VMS file version */
- --q;
- else
- q = a + strlen(a) - 1;
- #else /* !VMS */
- q = a + strlen(a) - 1;
- #endif /* ?VMS */
- }
- }
- else
- {
- m = m && q >= a && case_map(*p) == case_map(*q);
- q--;
- }
- return m;
- }
- #else /* RISCOS */
- local int filetypes(a, s)
- char *a; /* extra field of file to check filetype of */
- char *s; /* list of filetypes separated by : or ; */
- /* Return true if a is any of the filetypes in the list s. */
- {
- char *p; /* pointer into special */
- char typestr[4]; /* filetype hex string taken from a */
- if ((((unsigned*)a)[2] & 0xFFF00000) != 0xFFF00000) {
- /* The file is not filestamped, always try to compress it */
- return 0;
- }
- sprintf(typestr,"%.3X",(((unsigned*)a)[2] & 0x000FFF00) >> 8);
- for (p=s;p<=s+strlen(s)-3;p+=3) { /* p+=3 to skip 3 hex type */
- while (*p==':' || *p==';')
- p++;
- if (typestr[0] == toupper(p[0]) &&
- typestr[1] == toupper(p[1]) &&
- typestr[2] == toupper(p[2]))
- return 1;
- }
- return 0;
- }
- #endif /* ?RISCOS */
- /* Note: a zip "entry" includes a local header (which includes the file
- name), an encryption header if encrypting, the compressed data
- and possibly an extended local header. */
- int zipup(z)
- struct zlist far *z; /* zip entry to compress */
- /* Compress the file z->name into the zip entry described by *z and write
- it to the file *y. Encrypt if requested. Return an error code in the
- ZE_ class. Also, update tempzn by the number of bytes written. */
- /* y is now global */
- {
- iztimes f_utim; /* UNIX GMT timestamps, filled by filetime() */
- ulg tim; /* time returned by filetime() */
- ulg a = 0L; /* attributes returned by filetime() */
- char *b; /* malloc'ed file buffer */
- extent k = 0; /* result of zread */
- int l = 0; /* true if this file is a symbolic link */
- int m; /* method for this entry */
- zoff_t o = 0, p; /* offsets in zip file */
- zoff_t q = (zoff_t) -3; /* size returned by filetime */
- uzoff_t uq; /* unsigned q */
- zoff_t s = 0; /* size of compressed data */
- int r; /* temporary variable */
- int isdir; /* set for a directory name */
- int set_type = 0; /* set if file type (ascii/binary) unknown */
- zoff_t last_o; /* used to detect wrap around */
- ush tempext = 0; /* temp copies of extra fields */
- ush tempcext = 0;
- char *tempextra = NULL;
- char *tempcextra = NULL;
- #ifdef WINDLL
- # ifdef ZIP64_SUPPORT
- extern _int64 filesize64;
- extern unsigned long low;
- extern unsigned long high;
- # endif
- #endif
- z->nam = strlen(z->iname);
- isdir = z->iname[z->nam-1] == (char)0x2f; /* ascii[(unsigned)('/')] */
- file_binary = -1; /* not set, set after first read */
- file_binary_final = 0; /* not set, set after first read */
- #if defined(UNICODE_SUPPORT) && defined(WIN32)
- if (!no_win32_wide)
- tim = filetimew(z->namew, &a, &q, &f_utim);
- else
- tim = filetime(z->name, &a, &q, &f_utim);
- #else
- tim = filetime(z->name, &a, &q, &f_utim);
- #endif
- if (tim == 0 || q == (zoff_t) -3)
- return ZE_OPEN;
- /* q is set to -1 if the input file is a device, -2 for a volume label */
- if (q == (zoff_t) -2) {
- isdir = 1;
- q = 0;
- } else if (isdir != ((a & MSDOS_DIR_ATTR) != 0)) {
- /* don't overwrite a directory with a file and vice-versa */
- return ZE_MISS;
- }
- /* reset dot_count for each file */
- if (!display_globaldots)
- dot_count = -1;
- /* display uncompressed size */
- uq = ((uzoff_t) q > (uzoff_t) -3) ? 0 : (uzoff_t) q;
- if (noisy && display_usize) {
- fprintf(mesg, " (");
- DisplayNumString( mesg, uq );
- fprintf(mesg, ")");
- mesg_line_started = 1;
- fflush(mesg);
- }
- if (logall && display_usize) {
- fprintf(logfile, " (");
- DisplayNumString( logfile, uq );
- fprintf(logfile, ")");
- logfile_line_started = 1;
- fflush(logfile);
- }
- /* initial z->len so if error later have something */
- z->len = uq;
- z->att = (ush)UNKNOWN; /* will be changed later */
- z->atx = 0; /* may be changed by set_extra_field() */
- /* Free the old extra fields which are probably obsolete */
- /* Should probably read these and keep any we don't update. 12/30/04 EG */
- if (extra_fields == 2) {
- /* If keeping extra fields, make copy before clearing for set_extra_field()
- A better approach is to modify the port code, but maybe later */
- if (z->ext) {
- if ((tempextra = malloc(z->ext)) == NULL) {
- ZIPERR(ZE_MEM, "extra fields copy");
- }
- memcpy(tempextra, z->extra, z->ext);
- tempext = z->ext;
- }
- if (z->cext) {
- if ((tempcextra = malloc(z->cext)) == NULL) {
- ZIPERR(ZE_MEM, "extra fields copy");
- }
- memcpy(tempcextra, z->cextra, z->cext);
- tempcext = z->cext;
- }
- }
- if (z->ext) {
- free((zvoid *)(z->extra));
- }
- if (z->cext && z->extra != z->cextra) {
- free((zvoid *)(z->cextra));
- }
- z->extra = z->cextra = NULL;
- z->ext = z->cext = 0;
- #if defined(MMAP) || defined(BIG_MEM)
- remain = (ulg)-1L; /* changed only for MMAP or BIG_MEM */
- #endif /* MMAP || BIG_MEM */
- #if (!defined(USE_ZLIB) || defined(MMAP) || defined(BIG_MEM))
- window_size = 0L;
- #endif /* !USE_ZLIB || MMAP || BIG_MEM */
- /* Select method based on the suffix and the global method */
- #ifndef RISCOS
- m = special != NULL && suffixes(z->name, special) ? STORE : method;
- #else /* RISCOS must set m after setting extra field */
- m = method;
- #endif /* ?RISCOS */
- /* For now force deflate if using descriptors. Instead zip and unzip
- could check bytes read against compressed size in each data descriptor
- found and skip over any that don't match. This is how at least one
- other zipper does it. To be added later. Until then it
- probably doesn't hurt to force deflation when streaming. 12/30/04 EG
- */
- /* Now is a good time. For now allow storing for testing. 12/16/05 EG */
- /* By release need to force deflation based on reports some inflate
- streamed data to find the end of the data */
- /* Need to handle bzip2 */
- #ifdef NO_STREAMING_STORE
- if (use_descriptors && m == STORE)
- {
- m = DEFLATE;
- }
- #endif
- /* Open file to zip up unless it is stdin */
- if (strcmp(z->name, "-") == 0)
- {
- ifile = (ftype)zstdin;
- #if defined(MSDOS) || defined(__human68k__)
- if (isatty(zstdin) == 0) /* keep default mode if stdin is a terminal */
- setmode(zstdin, O_BINARY);
- #endif
- z->tim = tim;
- }
- else
- {
- #if !(defined(VMS) && defined(VMS_PK_EXTRA))
- if (extra_fields) {
- /* create extra field and change z->att and z->atx if desired */
- set_extra_field(z, &f_utim);
- # ifdef QLZIP
- if(qlflag)
- a |= (S_IXUSR) << 16; /* Cross compilers don't set this */
- # endif
- # ifdef RISCOS
- m = special != NULL && filetypes(z->extra, special) ? STORE : method;
- # endif /* RISCOS */
- /* For now allow store for testing */
- #ifdef NO_STREAMING_STORE
- /* For now force deflation if using data descriptors. */
- if (use_descriptors && m == STORE)
- {
- m = DEFLATE;
- }
- #endif
- }
- #endif /* !(VMS && VMS_PK_EXTRA) */
- l = issymlnk(a);
- if (l) {
- ifile = fbad;
- m = STORE;
- }
- else if (isdir) { /* directory */
- ifile = fbad;
- m = STORE;
- q = 0;
- }
- #ifdef THEOS
- else if (((a >> 16) & S_IFMT) == S_IFLIB) { /* library */
- ifile = fbad;
- m = STORE;
- q = 0;
- }
- #endif
- else {
- #ifdef CMS_MVS
- if (bflag) {
- if ((ifile = zopen(z->name, fhowb)) == fbad)
- return ZE_OPEN;
- }
- else
- #endif /* CMS_MVS */
- #if defined(UNICODE_SUPPORT) && defined(WIN32)
- if (!no_win32_wide) {
- if ((ifile = zwopen(z->namew, fhow)) == fbad)
- return ZE_OPEN;
- } else {
- if ((ifile = zopen(z->name, fhow)) == fbad)
- return ZE_OPEN;
- }
- #else
- if ((ifile = zopen(z->name, fhow)) == fbad)
- return ZE_OPEN;
- #endif
- }
- z->tim = tim;
- #if defined(VMS) && defined(VMS_PK_EXTRA)
- /* vms_get_attributes must be called after vms_open() */
- if (extra_fields) {
- /* create extra field and change z->att and z->atx if desired */
- vms_get_attributes(ifile, z, &f_utim);
- }
- #endif /* VMS && VMS_PK_EXTRA */
- #if defined(MMAP) || defined(BIG_MEM)
- /* Map ordinary files but not devices. This code should go in fileio.c */
- if (!translate_eol && m != STORE && q != -1L && (ulg)q > 0 &&
- (ulg)q + MIN_LOOKAHEAD > (ulg)q) {
- # ifdef MMAP
- /* Map the whole input file in memory */
- if (window != NULL)
- free(window); /* window can't be a mapped file here */
- window_size = (ulg)q + MIN_LOOKAHEAD;
- remain = window_size & (PAGESIZE-1);
- /* If we can't touch the page beyond the end of file, we must
- * allocate an extra page.
- */
- if (remain > MIN_LOOKAHEAD) {
- window = (uch*)mmap(0, window_size, PROT_READ, MAP_PRIVATE, ifile, 0);
- } else {
- window = (uch*)valloc(window_size - remain + PAGESIZE);
- if (window != NULL) {
- window = (uch*)mmap((char*)window, window_size - remain, PROT_READ,
- MAP_PRIVATE | MAP_FIXED, ifile, 0);
- } else {
- window = (uch*)(-1);
- }
- }
- if (window == (uch*)(-1)) {
- Trace((mesg, " mmap failure on %s\n", z->name));
- window = NULL;
- window_size = 0L;
- remain = (ulg)-1L;
- } else {
- remain = (ulg)q;
- }
- # else /* !MMAP, must be BIG_MEM */
- /* Read the whole input file at once */
- window_size = (ulg)q + MIN_LOOKAHEAD;
- window = window ? (uch*) realloc(window, (unsigned)window_size)
- : (uch*) malloc((unsigned)window_size);
- /* Just use normal code if big malloc or realloc fails: */
- if (window != NULL) {
- remain = (ulg)zread(ifile, (char*)window, q+1);
- if (remain != (ulg)q) {
- fprintf(mesg, " q=%lu, remain=%lu ", (ulg)q, remain);
- error("can't read whole file at once");
- }
- } else {
- window_size = 0L;
- }
- # endif /* ?MMAP */
- }
- #endif /* MMAP || BIG_MEM */
- } /* strcmp(z->name, "-") == 0 */
- if (extra_fields == 2) {
- unsigned len;
- char *p;
- /* step through old extra fields and copy over any not already
- in new extra fields */
- p = copy_nondup_extra_fields(tempextra, tempext, z->extra, z->ext, &len);
- free(z->extra);
- z->ext = len;
- z->extra = p;
- p = copy_nondup_extra_fields(tempcextra, tempcext, z->cextra, z->cext, &len);
- free(z->cextra);
- z->cext = len;
- z->cextra = p;
- if (tempext)
- free(tempextra);
- if (tempcext)
- free(tempcextra);
- }
- if (q == 0)
- m = STORE;
- if (m == BEST)
- m = DEFLATE;
- /* Do not create STORED files with extended local headers if the
- * input size is not known, because such files could not be extracted.
- * So if the zip file is not seekable and the input file is not
- * on disk, obey the -0 option by forcing deflation with stored block.
- * Note however that using "zip -0" as filter is not very useful...
- * ??? to be done.
- */
- /* An alternative used by others is to allow storing but on reading do
- * a second check when a signature is found. This is simply to check
- * the compressed size to the bytes read since the start of the file data.
- * If this is the right signature then the compressed size should match
- * the size of the compressed data to that point. If not look for the
- * next signature. We should do this. 12/31/04 EG
- *
- * For reading and testing we should do this, but should not write
- * stored streamed data unless for testing as finding the end of
- * streamed deflated data can be done by inflating. 6/26/06 EG
- */
- /* Fill in header information and write local header to zip file.
- * This header will later be re-written since compressed length and
- * crc are not yet known.
- */
- /* (Assume ext, cext, com, and zname already filled in.) */
- #if defined(OS2) || defined(WIN32)
- # ifdef WIN32_OEM
- /* When creating OEM-coded names on Win32, the entries must always be marked
- as "created on MSDOS" (OS_CODE = 0), because UnZip needs to handle archive
- entry names just like those created by Zip's MSDOS port.
- */
- z->vem = (ush)(dosify ? 20 : 0 + Z_MAJORVER * 10 + Z_MINORVER);
- # else
- z->vem = (ush)(z->dosflag ? (dosify ? 20 : /* Made under MSDOS by PKZIP 2.0 */
- (0 + Z_MAJORVER * 10 + Z_MINORVER))
- : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);
- /* For a plain old (8+3) FAT file system, we cheat and pretend that the file
- * was not made on OS2/WIN32 but under DOS. unzip is confused otherwise.
- */
- # endif
- #else /* !(OS2 || WIN32) */
- z->vem = (ush)(dosify ? 20 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);
- #endif /* ?(OS2 || WIN32) */
- z->ver = (ush)(m == STORE ? 10 : 20); /* Need PKUNZIP 2.0 except for store */
- #ifdef BZIP2_SUPPORT
- if (method == BZIP2)
- z->ver = (ush)(m == STORE ? 10 : 46);
- #endif
- z->crc = 0; /* to be updated later */
- /* Assume first that we will need an extended local header: */
- if (isdir)
- /* If dir then q = 0 and extended header not needed */
- z->flg = 0;
- else
- z->flg = 8; /* to be updated later */
- #if CRYPT
- if (!isdir && key != NULL) {
- z->flg |= 1;
- /* Since we do not yet know the crc here, we pretend that the crc
- * is the modification time:
- */
- z->crc = z->tim << 16;
- /* More than pretend. File is encrypted using crypt header with that. */
- }
- #endif /* CRYPT */
- z->lflg = z->flg;
- z->how = (ush)m; /* may be changed later */
- z->siz = (zoff_t)(m == STORE && q >= 0 ? q : 0); /* will be changed later */
- z->len = (zoff_t)(q != -1L ? q : 0); /* may be changed later */
- if (z->att == (ush)UNKNOWN) {
- z->att = BINARY; /* set sensible value in header */
- set_type = 1;
- }
- /* Attributes from filetime(), flag bits from set_extra_field(): */
- #if defined(DOS) || defined(OS2) || defined(WIN32)
- z->atx = z->dosflag ? a & 0xff : a | (z->atx & 0x0000ff00);
- #else
- z->atx = dosify ? a & 0xff : a | (z->atx & 0x0000ff00);
- #endif /* DOS || OS2 || WIN32 */
- if ((r = putlocal(z, PUTLOCAL_WRITE)) != ZE_OK) {
- if (ifile != fbad)
- zclose(ifile);
- return r;
- }
- /* now get split information set by bfwrite() */
- z->off = current_local_offset;
- /* disk local header was written to */
- z->dsk = current_local_disk;
- tempzn += 4 + LOCHEAD + z->nam + z->ext;
- #if CRYPT
- if (!isdir && key != NULL) {
- crypthead(key, z->crc);
- z->siz += RAND_HEAD_LEN; /* to be updated later */
- tempzn += RAND_HEAD_LEN;
- }
- #endif /* CRYPT */
- if (ferror(y)) {
- if (ifile != fbad)
- zclose(ifile);
- ZIPERR(ZE_WRITE, "unexpected error on zip file");
- }
- last_o = o;
- o = zftello(y); /* for debugging only, ftell can fail on pipes */
- if (ferror(y))
- clearerr(y);
- if (o != -1 && last_o > o) {
- fprintf(mesg, "last %s o %s\n", zip_fzofft(last_o, NULL, NULL),
- zip_fzofft(o, NULL, NULL));
- ZIPERR(ZE_BIG, "seek wrap - zip file too big to write");
- }
- /* Write stored or deflated file to zip file */
- isize = 0L;
- crc = CRCVAL_INITIAL;
- if (isdir) {
- /* nothing to write */
- }
- else if (m != STORE) {
- if (set_type) z->att = (ush)UNKNOWN;
- /* ... is finally set in file compression routine */
- #ifdef BZIP2_SUPPORT
- if (m == BZIP2) {
- s = bzfilecompress(z, &m);
- }
- else
- #endif /* BZIP2_SUPPORT */
- {
- s = filecompress(z, &m);
- }
- #ifndef PGP
- if (z->att == (ush)BINARY && translate_eol && file_binary) {
- if (translate_eol == 1)
- zipwarn("has binary so -l ignored", "");
- else
- zipwarn("has binary so -ll ignored", "");
- }
- else if (z->att == (ush)BINARY && translate_eol) {
- if (translate_eol == 1)
- zipwarn("-l used on binary file - corrupted?", "");
- else
- zipwarn("-ll used on binary file - corrupted?", "");
- }
- #endif
- }
- else
- {
- if ((b = malloc(SBSZ)) == NULL)
- return ZE_MEM;
- if (l) {
- k = rdsymlnk(z->name, b, SBSZ);
- /*
- * compute crc first because zfwrite will alter the buffer b points to !!
- */
- crc = crc32(crc, (uch *) b, k);
- if (zfwrite(b, 1, k) != k)
- {
- free((zvoid *)b);
- return ZE_TEMP;
- }
- isize = k;
- #ifdef MINIX
- q = k;
- #endif /* MINIX */
- }
- else
- {
- while ((k = file_read(b, SBSZ)) > 0 && k != (extent) EOF)
- {
- if (zfwrite(b, 1, k) != k)
- {
- if (ifile != fbad)
- zclose(ifile);
- free((zvoid *)b);
- return ZE_TEMP;
- }
- if (!display_globaldots) {
- if (dot_size > 0) {
- /* initial space */
- if (noisy && dot_count == -1) {
- #ifndef WINDLL
- putc(' ', mesg);
- fflush(mesg);
- #else
- fprintf(stdout,"%c",' ');
- #endif
- dot_count++;
- }
- dot_count++;
- if (dot_size <= (dot_count + 1) * SBSZ) dot_count = 0;
- }
- if ((verbose || noisy) && dot_size && !dot_count) {
- #ifndef WINDLL
- putc('.', mesg);
- fflush(mesg);
- #else
- fprintf(stdout,"%c",'.');
- #endif
- mesg_line_started = 1;
- }
- }
- }
- }
- free((zvoid *)b);
- s = isize;
- }
- if (ifile != fbad && zerr(ifile)) {
- perror("\nzip warning");
- if (logfile)
- fprintf(logfile, "\nzip warning: %s\n", strerror(errno));
- zipwarn("could not read input file: ", z->oname);
- }
- if (ifile != fbad)
- zclose(ifile);
- #ifdef MMAP
- if (remain != (ulg)-1L) {
- munmap((caddr_t) window, window_size);
- window = NULL;
- }
- #endif /*MMAP */
- tempzn += s;
- p = tempzn; /* save for future fseek() */
- #if (!defined(MSDOS) || defined(OS2))
- #if !defined(VMS) && !defined(CMS_MVS) && !defined(__mpexl)
- /* Check input size (but not in VMS -- variable record lengths mess it up)
- * and not on MSDOS -- diet in TSR mode reports an incorrect file size)
- */
- #ifndef TANDEM /* Tandem EOF does not match byte count unless Unstructured */
- if (!translate_eol && q != -1L && isize != q)
- {
- Trace((mesg, " i=%lu, q=%lu ", isize, q));
- zipwarn(" file size changed while zipping ", z->name);
- }
- #endif /* !TANDEM */
- #endif /* !VMS && !CMS_MVS && !__mpexl */
- #endif /* (!MSDOS || OS2) */
- if (isdir)
- {
- /* A directory */
- z->siz = 0;
- z->len = 0;
- z->how = STORE;
- z->ver = 10;
- /* never encrypt directory so don't need extended local header */
- z->flg &= ~8;
- z->lflg &= ~8;
- }
- else
- {
- /* Try to rewrite the local header with correct information */
- z->crc = crc;
- z->siz = s;
- #if CRYPT
- if (!isdir && key != NULL)
- z->siz += RAND_HEAD_LEN;
- #endif /* CRYPT */
- z->len = isize;
- /* if can seek back to local header */
- #ifdef BROKEN_FSEEK
- if (use_descriptors || !fseekable(y) || zfseeko(y, z->off, SEEK_SET))
- #else
- if (use_descriptors || zfseeko(y, z->off, SEEK_SET))
- #endif
- {
- if (z->how != (ush) m)
- error("can't rewrite method");
- if (m == STORE && q < 0)
- ZIPERR(ZE_PARMS, "zip -0 not supported for I/O on pipes or devices");
- if ((r = putextended(z)) != ZE_OK)
- return r;
- /* if Zip64 and not seekable then Zip64 data descriptor */
- #ifdef ZIP64_SUPPORT
- tempzn += (zip64_entry ? 24L : 16L);
- #else
- tempzn += 16L;
- #endif
- z->flg = z->lflg; /* if z->flg modified by deflate */
- } else {
- /* ftell() not as useful across splits */
- if (bytes_this_entry != (uzoff_t)(key ? s + 12 : s)) {
- fprintf(mesg, " s=%s, actual=%s ",
- zip_fzofft(s, NULL, NULL), zip_fzofft(bytes_this_entry, NULL, NULL));
- error("incorrect compressed size");
- }
- #if 0
- /* seek ok, ftell() should work, check compressed size */
- # if !defined(VMS) && !defined(CMS_MVS)
- if (p - o != s) {
- fprintf(mesg, " s=%s, actual=%s ",
- zip_fzofft(s, NULL, NULL), zip_fzofft(p-o, NULL, NULL));
- error("incorrect compressed size");
- }
- # endif /* !VMS && !CMS_MVS */
- #endif /* 0 */
- z->how = (ush)m;
- switch (m)
- {
- case STORE:
- z->ver = 10; break;
- /* Need PKUNZIP 2.0 for DEFLATE */
- case DEFLATE:
- z->ver = 20; break;
- #ifdef BZIP2_SUPPORT
- case BZIP2:
- z->ver = 46; break;
- #endif
- }
- /*
- * The encryption header needs the crc, but we don't have it
- * for a new file. The file time is used instead and the encryption
- * header then used to encrypt the data. The AppNote standard only
- * can be applied to a file that the crc is known, so that means
- * either an existing entry in an archive or get the crc before
- * creating the encryption header and then encrypt the data.
- */
- if ((z->flg & 1) == 0) {
- /* not encrypting so don't need extended local header */
- z->flg &= ~8;
- }
- /* deflate may have set compression level bit markers in z->flg,
- and we can't think of any reason central and local flags should
- be different. */
- z->lflg = z->flg;
- /* If not using descriptors, back up and rewrite local header. */
- if (split_method == 1 && current_local_file != y) {
- if (zfseeko(current_local_file, z->off, SEEK_SET))
- return ZE_READ;
- }
- /* if local header in another split, putlocal will close it */
- if ((r = putlocal(z, PUTLOCAL_REWRITE)) != ZE_OK)
- return r;
- if (zfseeko(y, bytes_this_split, SEEK_SET))
- return ZE_READ;
- if ((z->flg & 1) != 0) {
- /* encrypted file, extended header still required */
- if ((r = putextended(z)) != ZE_OK)
- return r;
- #ifdef ZIP64_SUPPORT
- if (zip64_entry)
- tempzn += 24L;
- else
- tempzn += 16L;
- #else
- tempzn += 16L;
- #endif
- }
- }
- } /* isdir */
- /* Free the local extra field which is no longer needed */
- if (z->ext) {
- if (z->extra != z->cextra) {
- free((zvoid *)(z->extra));
- z->extra = NULL;
- }
- z->ext = 0;
- }
- /* Display statistics */
- if (noisy)
- {
- if (verbose) {
- fprintf( mesg, "\t(in=%s) (out=%s)",
- zip_fzofft(isize, NULL, "u"), zip_fzofft(s, NULL, "u"));
- }
- #ifdef BZIP2_SUPPORT
- if (m == BZIP2)
- fprintf(mesg, " (bzipped %d%%)\n", percent(isize, s));
- else
- #endif
- if (m == DEFLATE)
- fprintf(mesg, " (deflated %d%%)\n", percent(isize, s));
- else
- fprintf(mesg, " (stored 0%%)\n");
- mesg_line_started = 0;
- fflush(mesg);
- }
- if (logall)
- {
- #ifdef BZIP2_SUPPORT
- if (m == BZIP2)
- fprintf(logfile, " (bzipped %d%%)\n", percent(isize, s));
- else
- #endif
- if (m == DEFLATE)
- fprintf(logfile, " (deflated %d%%)\n", percent(isize, s));
- else
- fprintf(logfile, " (stored 0%%)\n");
- logfile_line_started = 0;
- fflush(logfile);
- }
- #ifdef WINDLL
- # ifdef ZIP64_SUPPORT
- /* The DLL api has been updated and uses a different
- interface. 7/24/04 EG */
- if (lpZipUserFunctions->ServiceApplication64 != NULL)
- {
- if ((*lpZipUserFunctions->ServiceApplication64)(z->zname, isize))
- ZIPERR(ZE_ABORT, "User terminated operation");
- }
- else
- {
- filesize64 = isize;
- low = (unsigned long)(filesize64 & 0x00000000FFFFFFFF);
- high = (unsigned long)((filesize64 >> 32) & 0x00000000FFFFFFFF);
- if (lpZipUserFunctions->ServiceApplication64_No_Int64 != NULL) {
- if ((*lpZipUserFunctions->ServiceApplication64_No_Int64)(z->zname, low, high))
- ZIPERR(ZE_ABORT, "User terminated operation");
- }
- }
- # else
- if (lpZipUserFunctions->ServiceApplication != NULL)
- {
- if ((*lpZipUserFunctions->ServiceApplication)(z->zname, isize))
- {
- ZIPERR(ZE_ABORT, "User terminated operation");
- }
- }
- # endif
- #endif
- return ZE_OK;
- }
- local unsigned file_read(buf, size)
- char *buf;
- unsigned size;
- /* Read a new buffer from the current input file, perform end-of-line
- * translation, and update the crc and input file size.
- * IN assertion: size >= 2 (for end-of-line translation)
- */
- {
- unsigned len;
- char *b;
- zoff_t isize_prev; /* Previous isize. Used for overflow check. */
- #if defined(MMAP) || defined(BIG_MEM)
- if (remain == 0L) {
- return 0;
- } else if (remain != (ulg)-1L) {
- /* The window data is already in place. We still compute the crc
- * by 32K blocks instead of once on whole file to keep a certain
- * locality of reference.
- */
- Assert(buf == (char*)window + isize, "are you lost?");
- if ((ulg)size > remain) size = (unsigned)remain;
- if (size > WSIZE) size = WSIZE; /* don't touch all pages at once */
- remain -= (ulg)size;
- len = size;
- } else
- #endif /* MMAP || BIG_MEM */
- if (translate_eol == 0) {
- len = zread(ifile, buf, size);
- if (len == (unsigned)EOF || len == 0) return len;
- #ifdef OS390
- b = buf;
- if (aflag == ASCII) {
- while (*b != '\0') {
- *b = (char)ascii[(uch)*b];
- b++;
- }
- }
- #endif
- } else if (translate_eol == 1) {
- /* translate_eol == 1 */
- /* Transform LF to CR LF */
- size >>= 1;
- b = buf+size;
- size = len = zread(ifile, b, size);
- if (len == (unsigned)EOF || len == 0) return len;
- /* check buf for binary - 12/16/04 */
- if (file_binary == -1) {
- /* first read */
- file_binary = is_text_buf(b, size) ? 0 : 1;
- }
- if (file_binary != 1) {
- #ifdef EBCDIC
- if (aflag == ASCII)
- {
- do {
- char c;
- if ((c = *b++) == '\n') {
- *buf++ = CR; *buf++ = LF; len++;
- } else {
- *buf++ = (char)ascii[(uch)c];
- }
- } while (--size != 0);
- }
- else
- #endif /* EBCDIC */
- {
- do {
- if ((*buf++ = *b++) == '\n') *(buf-1) = CR, *buf++ = LF, len++;
- } while (--size != 0);
- }
- buf -= len;
- } else { /* do not translate binary */
- memcpy(buf, b, size);
- }
- } else {
- /* translate_eol == 2 */
- /* Transform CR LF to LF and suppress final ^Z */
- b = buf;
- size = len = zread(ifile, buf, size-1);
- if (len == (unsigned)EOF || len == 0) return len;
- /* check buf for binary - 12/16/04 */
- if (file_binary == -1) {
- /* first read */
- file_binary = is_text_buf(b, size) ? 0 : 1;
- }
- if (file_binary != 1) {
- buf[len] = '\n'; /* I should check if next char is really a \n */
- #ifdef EBCDIC
- if (aflag == ASCII)
- {
- do {
- char c;
- if ((c = *b++) == '\r' && *b == '\n') {
- len--;
- } else {
- *buf++ = (char)(c == '\n' ? LF : ascii[(uch)c]);
- }
- } while (--size != 0);
- }
- else
- #endif /* EBCDIC */
- {
- do {
- if (( *buf++ = *b++) == CR && *b == LF) buf--, len--;
- } while (--size != 0);
- }
- if (len == 0) {
- zread(ifile, buf, 1); len = 1; /* keep single \r if EOF */
- #ifdef EBCDIC
- if (aflag == ASCII) {
- *buf = (char)(*buf == '\n' ? LF : ascii[(uch)(*buf)]);
- }
- #endif
- } else {
- buf -= len;
- if (buf[len-1] == CTRLZ) len--; /* suppress final ^Z */
- }
- }
- }
- crc = crc32(crc, (uch *) buf, len);
- /* 2005-05-23 SMS.
- Increment file size. A small-file program reading a large file may
- cause isize to overflow, so complain (and abort) if it goes
- negative or wraps around. Awful things happen later otherwise.
- */
- isize_prev = isize;
- isize += (ulg)len;
- if (isize < isize_prev) {
- ZIPERR(ZE_BIG, "overflow in byte count");
- }
- return len;
- }
- #ifdef USE_ZLIB
- local int zl_deflate_init(pack_level)
- int pack_level;
- {
- unsigned i;
- int windowBits;
- int err = Z_OK;
- int zp_err = ZE_OK;
- if (zlib_version[0] != ZLIB_VERSION[0]) {
- sprintf(errbuf, "incompatible zlib version (expected %s, found %s)",
- ZLIB_VERSION, zlib_version);
- zp_err = ZE_LOGIC;
- } else if (strcmp(zlib_version, ZLIB_VERSION) != 0) {
- fprintf(mesg,
- "\twarning: different zlib version (expected %s, using %s)\n",
- ZLIB_VERSION, zlib_version);
- }
- /* windowBits = log2(WSIZE) */
- for (i = ((unsigned)WSIZE), windowBits = 0; i != 1; i >>= 1, ++windowBits);
- zstrm.zalloc = (alloc_func)Z_NULL;
- zstrm.zfree = (free_func)Z_NULL;
- Trace((stderr, "initializing deflate()\n"));
- err = deflateInit2(&zstrm, pack_level, Z_DEFLATED, -windowBits, 8, 0);
- if (err == Z_MEM_ERROR) {
- sprintf(errbuf, "cannot initialize zlib deflate");
- zp_err = ZE_MEM;
- } else if (err != Z_OK) {
- sprintf(errbuf, "zlib deflateInit failure (%d)", err);
- zp_err = ZE_LOGIC;
- }
- deflInit = TRUE;
- return zp_err;
- }
- void zl_deflate_free()
- {
- int err;
- if (f_obuf != NULL) {
- free(f_obuf);
- f_obuf = NULL;
- }
- if (f_ibuf != NULL) {
- free(f_ibuf);
- f_ibuf = NULL;
- }
- if (deflInit) {
- err = deflateEnd(&zstrm);
- if (err != Z_OK && err !=Z_DATA_ERROR) {
- ziperr(ZE_LOGIC, "zlib deflateEnd failed");
- }
- deflInit = FALSE;
- }
- }
- #else /* !USE_ZLIB */
- # ifdef ZP_NEED_MEMCOMPR
- /* ===========================================================================
- * In-memory read function. As opposed to file_read(), this function
- * does not perform end-of-line translation, and does not update the
- * crc and input size.
- * Note that the size of the entire input buffer is an unsigned long,
- * but the size used in mem_read() is only an unsigned int. This makes a
- * difference on 16 bit machines. mem_read() may be called several
- * times for an in-memory compression.
- */
- local unsigned mem_read(b, bsize)
- char *b;
- unsigned bsize;
- {
- if (in_offset < in_size) {
- ulg block_size = in_size - in_offset;
- if (block_size > (ulg)bsize) block_size = (ulg)bsize;
- memcpy(b, in_buf + in_offset, (unsigned)block_size);
- in_offset += (unsigned)block_size;
- return (unsigned)block_size;
- } else {
- return 0; /* end of input */
- }
- }
- # endif /* ZP_NEED_MEMCOMPR */
- /* ===========================================================================
- * Flush the current output buffer.
- */
- void flush_outbuf(o_buf, o_idx)
- char *o_buf;
- unsigned *o_idx;
- {
- if (y == NULL) {
- error("output buffer too small for in-memory compression");
- }
- /* Encrypt and write the output buffer: */
- if (*o_idx != 0) {
- zfwrite(o_buf, 1, (extent)*o_idx);
- if (ferror(y)) ziperr(ZE_WRITE, "write error on zip file");
- }
- *o_idx = 0;
- }
- /* ===========================================================================
- * Return true if the zip file can be seeked. This is used to check if
- * the local header can be re-rewritten. This function always returns
- * true for in-memory compression.
- * IN assertion: the local header has already been written (ftell() > 0).
- */
- int seekable()
- {
- return fseekable(y);
- }
- #endif /* ?USE_ZLIB */
- /* ===========================================================================
- * Compression to archive file.
- */
- local zoff_t filecompress(z_entry, cmpr_method)
- struct zlist far *z_entry;
- int *cmpr_method;
- {
- #ifdef USE_ZLIB
- int err = Z_OK;
- unsigned mrk_cnt = 1;
- int maybe_stored = FALSE;
- ulg cmpr_size;
- #if defined(MMAP) || defined(BIG_MEM)
- unsigned ibuf_sz = (unsigned)SBSZ;
- #else
- # define ibuf_sz ((unsigned)SBSZ)
- #endif
- #ifndef OBUF_SZ
- # define OBUF_SZ ZBSZ
- #endif
- unsigned u;
- #if defined(MMAP) || defined(BIG_MEM)
- if (remain == (ulg)-1L && f_ibuf == NULL)
- #else /* !(MMAP || BIG_MEM */
- if (f_ibuf == NULL)
- #endif /* MMAP || BIG_MEM */
- f_ibuf = (char *)malloc(SBSZ);
- if (f_obuf == NULL)
- f_obuf = (char *)malloc(OBUF_SZ);
- #if defined(MMAP) || defined(BIG_MEM)
- if ((remain == (ulg)-1L && f_ibuf == NULL) || f_obuf == NULL)
- #else /* !(MMAP || BIG_MEM */
- if (f_ibuf == NULL || f_obuf == NULL)
- #endif /* MMAP || BIG_MEM */
- ziperr(ZE_MEM, "allocating zlib file-I/O buffers");
- if (!deflInit) {
- err = zl_deflate_init(level);
- if (err != ZE_OK)
- ziperr(err, errbuf);
- }
- if (level <= 2) {
- z_entry->flg |= 4;
- } else if (level >= 8) {
- z_entry->flg |= 2;
- }
- #if defined(MMAP) || defined(BIG_MEM)
- if (remain != (ulg)-1L) {
- zstrm.next_in = (Bytef *)window;
- ibuf_sz = (unsigned)WSIZE;
- } else
- #endif /* MMAP || BIG_MEM */
- {
- zstrm.next_in = (Bytef *)f_ibuf;
- }
- zstrm.avail_in = file_read(zstrm.next_in, ibuf_sz);
- if (zstrm.avail_in < ibuf_sz) {
- unsigned more = file_read(zstrm.next_in + zstrm.avail_in,
- (ibuf_sz - zstrm.avail_in));
- if (more == EOF || more == 0) {
- maybe_stored = TRUE;
- } else {
- zstrm.avail_in += more;
- }
- }
- zstrm.next_out = (Bytef *)f_obuf;
- zstrm.avail_out = OBUF_SZ;
- if (!maybe_stored) while (zstrm.avail_in != 0 && zstrm.avail_in != EOF) {
- err = deflate(&zstrm, Z_NO_FLUSH);
- if (err != Z_OK && err != Z_STREAM_END) {
- sprintf(errbuf, "unexpected zlib deflate error %d", err);
- ziperr(ZE_LOGIC, errbuf);
- }
- if (zstrm.avail_out == 0) {
- if (zfwrite(f_obuf, 1, OBUF_SZ) != OBUF_SZ) {
- ziperr(ZE_TEMP, "error writing to zipfile");
- }
- zstrm.next_out = (Bytef *)f_obuf;
- zstrm.avail_out = OBUF_SZ;
- }
- if (zstrm.avail_in == 0) {
- if (verbose || noisy)
- while((unsigned)(zstrm.total_in / (uLong)WSIZE) > mrk_cnt) {
- mrk_cnt++;
- if (!display_globaldots) {
- if (dot_size > 0) {
- /* initial space */
- if (noisy && dot_count == -1) {
- #ifndef WINDLL
- putc(' ', mesg);
- fflush(mesg);
- #else
- fprintf(stdout,"%c",' ');
- #endif
- dot_count++;
- }
- dot_count++;
- if (dot_size <= (dot_count + 1) * WSIZE) dot_count = 0;
- }
- if (noisy && dot_size && !dot_count) {
- #ifndef WINDLL
- putc('.', mesg);
- fflush(mesg);
- #else
- fprintf(stdout,"%c",'.');
- #endif
- mesg_line_started = 1;
- }
- }
- }
- #if defined(MMAP) || defined(BIG_MEM)
- if (remain == (ulg)-1L)
- zstrm.next_in = (Bytef *)f_ibuf;
- #else
- zstrm.next_in = (Bytef *)f_ibuf;
- #endif
- zstrm.avail_in = file_read(zstrm.next_in, ibuf_sz);
- }
- }
- do {
- err = deflate(&zstrm, Z_FINISH);
- if (maybe_stored) {
- if (err == Z_STREAM_END && zstrm.total_out >= zstrm.total_in &&
- fseekable(zipfile)) {
- /* deflation does not reduce size, switch to STORE method */
- unsigned len_out = (unsigned)zstrm.total_in;
- if (zfwrite(f_ibuf, 1, len_out) != len_out) {
- ziperr(ZE_TEMP, "error writing to zipfile");
- }
- zstrm.total_out = (uLong)len_out;
- *cmpr_method = STORE;
- break;
- } else {
- maybe_stored = FALSE;
- }
- }
- if (zstrm.avail_out < OBUF_SZ) {
- unsigned len_out = OBUF_SZ - zstrm.avail_out;
- if (zfwrite(f_obuf, 1, len_out) != len_out) {
- ziperr(ZE_TEMP, "error writing to zipfile");
- }
- zstrm.next_out = (Bytef *)f_obuf;
- zstrm.avail_out = OBUF_SZ;
- }
- } while (err == Z_OK);
- if (err != Z_STREAM_END) {
- sprintf(errbuf, "unexpected zlib deflate error %d", err);
- ziperr(ZE_LOGIC, errbuf);
- }
- if (z_entry->att == (ush)UNKNOWN)
- z_entry->att = (ush)(zstrm.data_type == Z_ASCII ? ASCII : BINARY);
- cmpr_size = (ulg)zstrm.total_out;
- if ((err = deflateReset(&zstrm)) != Z_OK)
- ziperr(ZE_LOGIC, "zlib deflateReset failed");
- return cmpr_size;
- #else /* !USE_ZLIB */
- /* Set the defaults for file compression. */
- read_buf = file_read;
- /* Initialize deflate's internals and execute file compression. */
- bi_init(file_outbuf, sizeof(file_outbuf), TRUE);
- ct_init(&z_entry->att, cmpr_method);
- lm_init(level, &z_entry->flg);
- return deflate();
- #endif /* ?USE_ZLIB */
- }
- #ifdef ZP_NEED_MEMCOMPR
- /* ===========================================================================
- * In-memory compression. This version can be used only if the entire input
- * fits in one memory buffer. The compression is then done in a single
- * call of memcompress(). (An extension to allow repeated calls would be
- * possible but is not needed here.)
- * The first two bytes of the compressed output are set to a short with the
- * method used (DEFLATE or STORE). The following four bytes contain the CRC.
- * The values are stored in little-endian order on all machines.
- * This function returns the byte size of the compressed output, including
- * the first six bytes (method and crc).
- */
- ulg memcompress(tgt, tgtsize, src, srcsize)
- char *tgt, *src; /* target and source buffers */
- ulg tgtsize, srcsize; /* target and source sizes */
- {
- ulg crc;
- unsigned out_total;
- int method = DEFLATE;
- #ifdef USE_ZLIB
- int err = Z_OK;
- #else
- ush att = (ush)UNKNOWN;
- ush flags = 0;
- #endif
- if (tgtsize <= (ulg)6L) error("target buffer too small");
- out_total = 2 + 4;
- #ifdef USE_ZLIB
- if (!deflInit) {
- err = zl_deflate_init(level);
- if (err != ZE_OK)
- ziperr(err, errbuf);
- }
- zstrm.next_in = (Bytef *)src;
- zstrm.avail_in = (uInt)srcsize;
- zstrm.next_out = (Bytef *)(tgt + out_total);
- zstrm.avail_out = (uInt)tgtsize - (uInt)out_total;
- err = deflate(&zstrm, Z_FINISH);
- if (err != Z_STREAM_END)
- error("output buffer too small for in-memory compression");
- out_total += (unsigned)zstrm.total_out;
- if ((err = deflateReset(&zstrm)) != Z_OK)
- error("zlib deflateReset failed");
- #else /* !USE_ZLIB */
- read_buf = mem_read;
- in_buf = src;
- in_size = (unsigned)srcsize;
- in_offset = 0;
- window_size = 0L;
- bi_init(tgt + (2 + 4), (unsigned)(tgtsize - (2 + 4)), FALSE);
- ct_init(&att, &method);
- lm_init((level != 0 ? level : 1), &flags);
- out_total += (unsigned)deflate();
- window_size = 0L; /* was updated by lm_init() */
- #endif /* ?USE_ZLIB */
- crc = CRCVAL_INITIAL;
- crc = crc32(crc, (uch *)src, (extent)srcsize);
- /* For portability, force little-endian order on all machines: */
- tgt[0] = (char)(method & 0xff);
- tgt[1] = (char)((method >> 8) & 0xff);
- tgt[2] = (char)(crc & 0xff);
- tgt[3] = (char)((crc >> 8) & 0xff);
- tgt[4] = (char)((crc >> 16) & 0xff);
- tgt[5] = (char)((crc >> 24) & 0xff);
- return (ulg)out_total;
- }
- #endif /* ZP_NEED_MEMCOMPR */
- #ifdef BZIP2_SUPPORT
- local int bz_compress_init(pack_level)
- int pack_level;
- {
- int err = BZ_OK;
- int zp_err = ZE_OK;
- const char *bzlibVer;
- bzlibVer = BZ2_bzlibVersion();
- /* $TODO - Check BZIP2 LIB version? */
- bstrm.bzalloc = NULL;
- bstrm.bzfree = NULL;
- bstrm.opaque = NULL;
- Trace((stderr, "initializing bzlib compress()\n"));
- err = BZ2_bzCompressInit(&bstrm, pack_level, 0, 30);
- if (err == BZ_MEM_ERROR) {
- sprintf(errbuf, "cannot initialize bzlib compress");
- zp_err = ZE_MEM;
- } else if (err != BZ_OK) {
- sprintf(errbuf, "bzlib bzCompressInit failure (%d)", err);
- zp_err = ZE_LOGIC;
- }
- bzipInit = TRUE;
- return zp_err;
- }
- void bz_compress_free()
- {
- int err;
- if (f_obuf != NULL) {
- free(f_obuf);
- f_obuf = NULL;
- }
- if (f_ibuf != NULL) {
- free(f_ibuf);
- f_ibuf = NULL;
- }
- if (bzipInit) {
- err = BZ2_bzCompressEnd(&bstrm);
- if (err != BZ_OK && err != BZ_DATA_ERROR) {
- ziperr(ZE_LOGIC, "bzlib bzCompressEnd failed");
- }
- bzipInit = FALSE;
- }
- }
- /* ===========================================================================
- * BZIP2 Compression to archive file.
- */
- local zoff_t bzfilecompress(z_entry, cmpr_method)
- struct zlist far *z_entry;
- int *cmpr_method;
- {
- FILE *zipfile = y;
- int err = BZ_OK;
- unsigned mrk_cnt = 1;
- int maybe_stored = FALSE;
- zoff_t cmpr_size;
- #if defined(MMAP) || defined(BIG_MEM)
- unsigned ibuf_sz = (unsigned)SBSZ;
- #else
- # define ibuf_sz ((unsigned)SBSZ)
- #endif
- #ifndef OBUF_SZ
- # define OBUF_SZ ZBSZ
- #endif
- #if defined(MMAP) || defined(BIG_MEM)
- if (remain == (ulg)-1L && f_ibuf == NULL)
- #else /* !(MMAP || BIG_MEM */
- if (f_ibuf == NULL)
- #endif /* MMAP || BIG_MEM */
- f_ibuf = (char *)malloc(SBSZ);
- if (f_obuf == NULL)
- f_obuf = (char *)malloc(OBUF_SZ);
- #if defined(MMAP) || defined(BIG_MEM)
- if ((remain == (ulg)-1L && f_ibuf == NULL) || f_obuf == NULL)
- #else /* !(MMAP || BIG_MEM */
- if (f_ibuf == NULL || f_obuf == NULL)
- #endif /* MMAP || BIG_MEM */
- ziperr(ZE_MEM, "allocating zlib/bzlib file-I/O buffers");
- if (!bzipInit) {
- err = bz_compress_init(level);
- if (err != ZE_OK)
- ziperr(err, errbuf);
- }
- #if defined(MMAP) || defined(BIG_MEM)
- if (remain != (ulg)-1L) {
- bstrm.next_in = (Bytef *)window;
- ibuf_sz = (unsigned)WSIZE;
- } else
- #endif /* MMAP || BIG_MEM */
- {
- bstrm.next_in = (char *)f_ibuf;
- }
- bstrm.avail_in = file_read(bstrm.next_in, ibuf_sz);
- if (file_binary_final == 0) {
- /* check for binary as library does not */
- if (!is_text_buf(bstrm.next_in, ibuf_sz))
- file_binary_final = 1;
- }
- if (bstrm.avail_in < ibuf_sz) {
- unsigned more = file_read(bstrm.next_in + bstrm.avail_in,
- (ibuf_sz - bstrm.avail_in));
- if (more == (unsigned) EOF || more == 0) {
- maybe_stored = TRUE;
- } else {
- bstrm.avail_in += more;
- }
- }
- bstrm.next_out = (char *)f_obuf;
- bstrm.avail_out = OBUF_SZ;
- if (!maybe_stored) {
- while (bstrm.avail_in != 0 && bstrm.avail_in != (unsigned) EOF) {
- err = BZ2_bzCompress(&bstrm, BZ_RUN);
- if (err != BZ_RUN_OK && err != BZ_STREAM_END) {
- sprintf(errbuf, "unexpected bzlib compress error %d", err);
- ziperr(ZE_LOGIC, errbuf);
- }
- if (bstrm.avail_out == 0) {
- if (zfwrite(f_obuf, 1, OBUF_SZ) != OBUF_SZ) {
- ziperr(ZE_TEMP, "error writing to zipfile");
- }
- bstrm.next_out = (char *)f_obuf;
- bstrm.avail_out = OBUF_SZ;
- }
- /* $TODO what about high 32-bits of total-in??? */
- if (bstrm.avail_in == 0) {
- if (verbose || noisy)
- #ifdef LARGE_FILE_SUPPORT
- while((unsigned)((bstrm.total_in_lo32
- + (((zoff_t)bstrm.total_in_hi32) << 32))
- / (zoff_t)(ulg)WSIZE) > mrk_cnt) {
- #else
- while((unsigned)(bstrm.total_in_lo32 / (ulg)WSIZE) > mrk_cnt) {
- #endif
- mrk_cnt++;
- if (!display_globaldots) {
- if (dot_size > 0) {
- /* initial space */
- if (noisy && dot_count == -1) {
- #ifndef WINDLL
- putc(' ', mesg);
- fflush(mesg);
- #else
- fprintf(stdout,"%c",' ');
- #endif
- dot_count++;
- }
- dot_count++;
- if (dot_size <= (dot_count + 1) * WSIZE) dot_count = 0;
- }
- if (noisy && dot_size && !dot_count) {
- #ifndef WINDLL
- putc('.', mesg);
- fflush(mesg);
- #else
- fprintf(stdout,"%c",'.');
- #endif
- mesg_line_started = 1;
- }
- }
- }
- #if defined(MMAP) || defined(BIG_MEM)
- if (remain == (ulg)-1L)
- bstrm.next_in = (char *)f_ibuf;
- #else
- bstrm.next_in = (char *)f_ibuf;
- #endif
- bstrm.avail_in = file_read(bstrm.next_in, ibuf_sz);
- if (file_binary_final == 0) {
- /* check for binary as library does not */
- if (!is_text_buf(bstrm.next_in, ibuf_sz))
- file_binary_final = 1;
- }
- }
- }
- }
- /* binary or text */
- if (file_binary_final)
- /* found binary in file */
- z_entry->att = (ush)BINARY;
- else
- /* text file */
- z_entry->att = (ush)ASCII;
- do {
- err = BZ2_bzCompress(&bstrm, BZ_FINISH);
- if (maybe_stored) {
- /* This code is only executed when the complete data stream fits
- into the input buffer (see above where maybe_stored gets set).
- So, it is safe to assume that total_in_hi32 (and total_out_hi32)
- are 0, because the input buffer size is well below the 32-bit
- limit.
- */
- if (err == BZ_STREAM_END
- && bstrm.total_out_lo32 >= bstrm.total_in_lo32
- && fseekable(zipfile)) {
- /* BZIP2 compress does not reduce size,
- switch to STORE method */
- unsigned len_out = (unsigned)bstrm.total_in_lo32;
- if (zfwrite(f_ibuf, 1, len_out) != len_out) {
- ziperr(ZE_TEMP, "error writing to zipfile");
- }
- bstrm.total_out_lo32 = (ulg)len_out;
- *cmpr_method = STORE;
- break;
- } else {
- maybe_stored = FALSE;
- }
- }
- if (bstrm.avail_out < OBUF_SZ) {
- unsigned len_out = OBUF_SZ - bstrm.avail_out;
- if (zfwrite(f_obuf, 1, len_out) != len_out) {
- ziperr(ZE_TEMP, "error writing to zipfile");
- }
- bstrm.next_out = (char *)f_obuf;
- bstrm.avail_out = OBUF_SZ;
- }
- } while (err == BZ_FINISH_OK);
- if (err < BZ_OK) {
- sprintf(errbuf, "unexpected bzlib compress error %d", err);
- ziperr(ZE_LOGIC, errbuf);
- }
- if (z_entry->att == (ush)UNKNOWN)
- z_entry->att = (ush)BINARY;
- #ifdef LARGE_FILE_SUPPORT
- cmpr_size = (zoff_t)bstrm.total_out_lo32
- + (((zoff_t)bstrm.total_out_hi32) << 32);
- #else
- cmpr_size = (zoff_t)bstrm.total_out_lo32;
- #endif
- if ((err = BZ2_bzCompressEnd(&bstrm)) != BZ_OK)
- ziperr(ZE_LOGIC, "zlib deflateReset failed");
- bzipInit = FALSE;
- return cmpr_size;
- }
- #endif /* BZIP2_SUPPORT */
- #endif /* !UTIL */
|