1/*
2  zipup.c - Zip 3
3
4  Copyright (c) 1990-2008 Info-ZIP.  All rights reserved.
5
6  See the accompanying file LICENSE, version 2007-Mar-4 or later
7  (the contents of which are also included in zip.h) for terms of use.
8  If, for some reason, all these files are missing, the Info-ZIP license
9  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
10*/
11/*
12 *  zipup.c by Mark Adler and Jean-loup Gailly.
13 */
14#define __ZIPUP_C
15
16/* Found that for at least unix port zip.h has to be first or ctype.h will
17   define off_t and when using 64-bit file environment off_t in other files
18   is 8 bytes while off_t here is 4 bytes, and this makes the zlist struct
19   different sizes and needless to say leads to segmentation faults.  Putting
20   zip.h first seems to fix this.  8/14/04 EG */
21#include "zip.h"
22#include <ctype.h>
23#include <errno.h>
24
25#ifndef UTIL            /* This module contains no code for Zip Utilities */
26
27#include "revision.h"
28#include "crc32.h"
29#include "crypt.h"
30#ifdef USE_ZLIB
31#  include "zlib.h"
32#endif
33#ifdef BZIP2_SUPPORT
34#  ifdef BZIP2_USEBZIP2DIR
35#    include "bzip2/bzlib.h"
36#  else
37#    include "bzlib.h"
38#  endif
39#endif
40
41#ifdef OS2
42#  include "os2/os2zip.h"
43#endif
44
45#if defined(MMAP)
46#  include <sys/mman.h>
47#  ifndef PAGESIZE   /* used to be SYSV, what about pagesize on SVR3 ? */
48#    define PAGESIZE getpagesize()
49#  endif
50#  if defined(NO_VALLOC) && !defined(valloc)
51#    define valloc malloc
52#  endif
53#endif
54
55/* Use the raw functions for MSDOS and Unix to save on buffer space.
56   They're not used for VMS since it doesn't work (raw is weird on VMS).
57 */
58
59#ifdef AMIGA
60#  include "amiga/zipup.h"
61#endif /* AMIGA */
62
63#ifdef AOSVS
64#  include "aosvs/zipup.h"
65#endif /* AOSVS */
66
67#ifdef ATARI
68#  include "atari/zipup.h"
69#endif
70
71#ifdef __BEOS__
72#  include "beos/zipup.h"
73#endif
74
75#ifdef __ATHEOS__
76#  include "atheos/zipup.h"
77#endif /* __ATHEOS__ */
78
79#ifdef __human68k__
80#  include "human68k/zipup.h"
81#endif /* __human68k__ */
82
83#ifdef MACOS
84#  include "macos/zipup.h"
85#endif
86
87#ifdef DOS
88#  include "msdos/zipup.h"
89#endif /* DOS */
90
91#ifdef NLM
92#  include "novell/zipup.h"
93#  include <nwfattr.h>
94#endif
95
96#ifdef OS2
97#  include "os2/zipup.h"
98#endif /* OS2 */
99
100#ifdef RISCOS
101#  include "acorn/zipup.h"
102#endif
103
104#ifdef TOPS20
105#  include "tops20/zipup.h"
106#endif
107
108#ifdef UNIX
109#  include "unix/zipup.h"
110#endif
111
112#ifdef CMS_MVS
113#  include "zipup.h"
114#endif /* CMS_MVS */
115
116#ifdef TANDEM
117#  include "zipup.h"
118#endif /* TANDEM */
119
120#ifdef VMS
121#  include "vms/zipup.h"
122#endif /* VMS */
123
124#ifdef QDOS
125#  include "qdos/zipup.h"
126#endif /* QDOS */
127
128#ifdef WIN32
129#  include "win32/zipup.h"
130#endif
131
132#ifdef THEOS
133#  include "theos/zipup.h"
134#endif
135
136/* Local functions */
137#ifndef RISCOS
138   local int suffixes OF((char *, char *));
139#else
140   local int filetypes OF((char *, char *));
141#endif
142local unsigned file_read OF((char *buf, unsigned size));
143#ifdef USE_ZLIB
144  local int zl_deflate_init OF((int pack_level));
145#else /* !USE_ZLIB */
146# ifdef ZP_NEED_MEMCOMPR
147    local unsigned mem_read OF((char *buf, unsigned size));
148# endif
149#endif /* ?USE_ZLIB */
150
151/* zip64 support 08/29/2003 R.Nausedat */
152local zoff_t filecompress OF((struct zlist far *z_entry, int *cmpr_method));
153
154#ifdef BZIP2_SUPPORT
155local zoff_t bzfilecompress OF((struct zlist far *z_entry, int *cmpr_method));
156#endif
157
158/* Deflate "internal" global data (currently not in zip.h) */
159#if defined(MMAP) || defined(BIG_MEM)
160# ifdef USE_ZLIB
161    local uch *window = NULL;   /* Used to read all input file at once */
162    local ulg window_size;      /* size of said window */
163# else /* !USE_ZLIB */
164    extern uch *window;         /* Used to read all input file at once */
165#endif /* ?USE_ZLIB */
166#endif /* MMAP || BIG_MEM */
167#ifndef USE_ZLIB
168  extern ulg window_size;       /* size of said window */
169
170  unsigned (*read_buf) OF((char *buf, unsigned size)) = file_read;
171  /* Current input function. Set to mem_read for in-memory compression */
172#endif /* !USE_ZLIB */
173
174
175/* Local data */
176local ulg crc;                  /* crc on uncompressed file data */
177local ftype ifile;              /* file to compress */
178#if defined(MMAP) || defined(BIG_MEM)
179  local ulg remain;
180  /* window bytes not yet processed.
181   *  special value "(ulg)-1L" reserved to signal normal reads.
182   */
183#endif /* MMAP || BIG_MEM */
184#ifdef USE_ZLIB
185  local int deflInit = FALSE;   /* flag: zlib deflate is initialized */
186  local z_stream zstrm;         /* zlib's data interface structure */
187  local char *f_ibuf = NULL;
188  local char *f_obuf = NULL;
189#else /* !USE_ZLIB */
190  local char file_outbuf[1024]; /* output buffer for compression to file */
191
192# ifdef ZP_NEED_MEMCOMPR
193    local char *in_buf;
194    /* Current input buffer, in_buf is used only for in-memory compression. */
195    local unsigned in_offset;
196    /* Current offset in input buffer. in_offset is used only for in-memory
197     * compression. On 16 bit machines, the buffer is limited to 64K.
198     */
199    local unsigned in_size;     /* size of current input buffer */
200# endif /* ZP_NEED_MEMCOMPR */
201#endif /* ?USE_ZLIB */
202
203#ifdef BZIP2_SUPPORT
204    local int bzipInit;         /* flag: bzip2lib is initialized */
205    local bz_stream bstrm;      /* zlib's data interface structure */
206# if !defined(USE_ZLIB)
207    local char *f_ibuf = NULL;
208    local char *f_obuf = NULL;
209# endif /* !USE_ZLIB */
210#endif /* BZIP2_SUPPORT */
211
212#ifdef DEBUG
213    zoff_t isize;               /* input file size. global only for debugging */
214#else /* !DEBUG */
215    local zoff_t isize;         /* input file size. global only for debugging */
216#endif /* ?DEBUG */
217  /* If file_read detects binary it sets this flag - 12/16/04 EG */
218  local int file_binary = 0;        /* first buf */
219  local int file_binary_final = 0;  /* for bzip2 for entire file.  assume text until find binary */
220
221
222/* moved check to function 3/14/05 EG */
223int is_seekable(y)
224  FILE *y;
225{
226  zoff_t pos;
227
228#ifdef BROKEN_FSEEK
229  if (!fseekable(y)) {
230    return 0;
231  }
232#endif
233
234  pos = zftello(y);
235  if (zfseeko(y, pos, SEEK_SET)) {
236    return 0;
237  }
238
239  return 1;
240}
241
242
243int percent(n, m)
244  uzoff_t n;
245  uzoff_t m;                    /* n is the original size, m is the new size */
246/* Return the percentage compression from n to m using only integer
247   operations */
248{
249  zoff_t p;
250
251#if 0
252  if (n > 0xffffffL)            /* If n >= 16M */
253  {                             /*  then divide n and m by 256 */
254    n += 0x80;  n >>= 8;
255    m += 0x80;  m >>= 8;
256  }
257  return n > m ? (int)(1 + (200 * (n - m)/n)) / 2 : 0;
258#endif
259
260/* 2004-12-01 SMS.
261 * Changed to do big-n test only for small zoff_t.
262 * Changed big-n arithmetic to accomodate apparently negative values
263 * when a small zoff_t value exceeds 2G.
264 * Increased the reduction divisor from 256 to 512 to avoid the sign bit
265 * in a reduced intermediate, allowing signed arithmetic for the final
266 * result (which is no longer artificially limited to non-negative
267 * values).
268 * Note that right shifts must be on unsigned values to avoid undesired
269 * sign extension.
270 */
271
272/* Handle n = 0 case and account for int maybe being 16-bit.  12/28/2004 EG
273 */
274
275#define PC_MAX_SAFE 0x007fffffL    /* 9 clear bits at high end. */
276#define PC_MAX_RND  0xffffff00L    /* 8 clear bits at low end. */
277
278  if (sizeof(uzoff_t) < 8)          /* Don't fiddle with big zoff_t. */
279  {
280    if ((ulg)n > PC_MAX_SAFE)       /* Reduce large values.  (n > m) */
281    {
282      if ((ulg)n < PC_MAX_RND)      /* Divide n by 512 with rounding, */
283        n = ((ulg)n + 0x100) >> 9;  /* if boost won't overflow. */
284      else                          /* Otherwise, use max value. */
285        n = PC_MAX_SAFE;
286
287      if ((ulg)m < PC_MAX_RND)      /* Divide m by 512 with rounding, */
288        m = ((ulg)m + 0x100) >> 9;  /* if boost won't overflow. */
289      else                          /* Otherwise, use max value. */
290        m = PC_MAX_SAFE;
291    }
292  }
293  if (n != 0)
294    p = ((200 * ((zoff_t)n - (zoff_t)m) / (zoff_t)n) + 1) / 2;
295  else
296    p = 0;
297  return (int)p;  /* Return (rounded) % reduction. */
298}
299
300
301#ifndef RISCOS
302
303local int suffixes(a, s)
304  char *a;                      /* name to check suffix of */
305  char *s;                      /* list of suffixes separated by : or ; */
306/* Return true if a ends in any of the suffixes in the list s. */
307{
308  int m;                        /* true if suffix matches so far */
309  char *p;                      /* pointer into special */
310  char *q;                      /* pointer into name a */
311
312#ifdef QDOS
313  short dlen = devlen(a);
314  a = a + dlen;
315#endif
316
317  m = 1;
318#ifdef VMS
319  if( (q = strrchr(a,';')) != NULL )    /* Cut out VMS file version */
320    --q;
321  else
322    q = a + strlen(a) - 1;
323#else /* !VMS */
324  q = a + strlen(a) - 1;
325#endif /* ?VMS */
326  for (p = s + strlen(s) - 1; p >= s; p--)
327    if (*p == ':' || *p == ';')
328    {
329      if (m)
330        return 1;
331      else
332      {
333        m = 1;
334#ifdef VMS
335        if( (q = strrchr(a,';')) != NULL )      /* Cut out VMS file version */
336          --q;
337        else
338          q = a + strlen(a) - 1;
339#else /* !VMS */
340        q = a + strlen(a) - 1;
341#endif /* ?VMS */
342      }
343    }
344    else
345    {
346      m = m && q >= a && case_map(*p) == case_map(*q);
347      q--;
348    }
349  return m;
350}
351
352#else /* RISCOS */
353
354local int filetypes(a, s)
355char *a;                        /* extra field of file to check filetype of */
356char *s;                        /* list of filetypes separated by : or ; */
357/* Return true if a is any of the filetypes in the list s. */
358{
359 char *p;                       /* pointer into special */
360 char typestr[4];               /* filetype hex string taken from a */
361
362 if ((((unsigned*)a)[2] & 0xFFF00000) != 0xFFF00000) {
363 /* The file is not filestamped, always try to compress it */
364   return 0;
365 }
366
367 sprintf(typestr,"%.3X",(((unsigned*)a)[2] & 0x000FFF00) >> 8);
368
369 for (p=s;p<=s+strlen(s)-3;p+=3) { /* p+=3 to skip 3 hex type */
370   while (*p==':' || *p==';')
371     p++;
372
373   if (typestr[0] == toupper(p[0]) &&
374       typestr[1] == toupper(p[1]) &&
375       typestr[2] == toupper(p[2]))
376     return 1;
377 }
378 return 0;
379}
380#endif /* ?RISCOS */
381
382
383
384/* Note: a zip "entry" includes a local header (which includes the file
385   name), an encryption header if encrypting, the compressed data
386   and possibly an extended local header. */
387
388int zipup(z)
389struct zlist far *z;    /* zip entry to compress */
390/* Compress the file z->name into the zip entry described by *z and write
391   it to the file *y. Encrypt if requested.  Return an error code in the
392   ZE_ class.  Also, update tempzn by the number of bytes written. */
393/* y is now global */
394{
395  iztimes f_utim;       /* UNIX GMT timestamps, filled by filetime() */
396  ulg tim;              /* time returned by filetime() */
397  ulg a = 0L;           /* attributes returned by filetime() */
398  char *b;              /* malloc'ed file buffer */
399  extent k = 0;         /* result of zread */
400  int l = 0;            /* true if this file is a symbolic link */
401  int m;                /* method for this entry */
402
403  zoff_t o = 0, p;      /* offsets in zip file */
404  zoff_t q = (zoff_t) -3; /* size returned by filetime */
405  uzoff_t uq;           /* unsigned q */
406  zoff_t s = 0;         /* size of compressed data */
407
408  int r;                /* temporary variable */
409  int isdir;            /* set for a directory name */
410  int set_type = 0;     /* set if file type (ascii/binary) unknown */
411  zoff_t last_o;        /* used to detect wrap around */
412
413  ush tempext = 0;      /* temp copies of extra fields */
414  ush tempcext = 0;
415  char *tempextra = NULL;
416  char *tempcextra = NULL;
417
418
419#ifdef WINDLL
420# ifdef ZIP64_SUPPORT
421  extern _int64 filesize64;
422  extern unsigned long low;
423  extern unsigned long high;
424#  endif
425#endif
426
427  z->nam = strlen(z->iname);
428  isdir = z->iname[z->nam-1] == (char)0x2f; /* ascii[(unsigned)('/')] */
429
430  file_binary = -1;      /* not set, set after first read */
431  file_binary_final = 0; /* not set, set after first read */
432
433#if defined(UNICODE_SUPPORT) && defined(WIN32)
434  if (!no_win32_wide)
435    tim = filetimew(z->namew, &a, &q, &f_utim);
436  else
437    tim = filetime(z->name, &a, &q, &f_utim);
438#else
439  tim = filetime(z->name, &a, &q, &f_utim);
440#endif
441  if (tim == 0 || q == (zoff_t) -3)
442    return ZE_OPEN;
443
444  /* q is set to -1 if the input file is a device, -2 for a volume label */
445  if (q == (zoff_t) -2) {
446     isdir = 1;
447     q = 0;
448  } else if (isdir != ((a & MSDOS_DIR_ATTR) != 0)) {
449     /* don't overwrite a directory with a file and vice-versa */
450     return ZE_MISS;
451  }
452  /* reset dot_count for each file */
453  if (!display_globaldots)
454    dot_count = -1;
455
456  /* display uncompressed size */
457  uq = ((uzoff_t) q > (uzoff_t) -3) ? 0 : (uzoff_t) q;
458  if (noisy && display_usize) {
459    fprintf(mesg, " (");
460    DisplayNumString( mesg, uq );
461    fprintf(mesg, ")");
462    mesg_line_started = 1;
463    fflush(mesg);
464  }
465  if (logall && display_usize) {
466    fprintf(logfile, " (");
467    DisplayNumString( logfile, uq );
468    fprintf(logfile, ")");
469    logfile_line_started = 1;
470    fflush(logfile);
471  }
472
473  /* initial z->len so if error later have something */
474  z->len = uq;
475
476  z->att = (ush)UNKNOWN; /* will be changed later */
477  z->atx = 0; /* may be changed by set_extra_field() */
478
479  /* Free the old extra fields which are probably obsolete */
480  /* Should probably read these and keep any we don't update.  12/30/04 EG */
481  if (extra_fields == 2) {
482    /* If keeping extra fields, make copy before clearing for set_extra_field()
483       A better approach is to modify the port code, but maybe later */
484    if (z->ext) {
485      if ((tempextra = malloc(z->ext)) == NULL) {
486        ZIPERR(ZE_MEM, "extra fields copy");
487      }
488      memcpy(tempextra, z->extra, z->ext);
489      tempext = z->ext;
490    }
491    if (z->cext) {
492      if ((tempcextra = malloc(z->cext)) == NULL) {
493        ZIPERR(ZE_MEM, "extra fields copy");
494      }
495      memcpy(tempcextra, z->cextra, z->cext);
496      tempcext = z->cext;
497    }
498  }
499  if (z->ext) {
500    free((zvoid *)(z->extra));
501  }
502  if (z->cext && z->extra != z->cextra) {
503    free((zvoid *)(z->cextra));
504  }
505  z->extra = z->cextra = NULL;
506  z->ext = z->cext = 0;
507
508#if defined(MMAP) || defined(BIG_MEM)
509  remain = (ulg)-1L; /* changed only for MMAP or BIG_MEM */
510#endif /* MMAP || BIG_MEM */
511#if (!defined(USE_ZLIB) || defined(MMAP) || defined(BIG_MEM))
512  window_size = 0L;
513#endif /* !USE_ZLIB || MMAP || BIG_MEM */
514
515  /* Select method based on the suffix and the global method */
516#ifndef RISCOS
517  m = special != NULL && suffixes(z->name, special) ? STORE : method;
518#else /* RISCOS  must set m after setting extra field */
519  m = method;
520#endif /* ?RISCOS */
521
522  /* For now force deflate if using descriptors.  Instead zip and unzip
523     could check bytes read against compressed size in each data descriptor
524     found and skip over any that don't match.  This is how at least one
525     other zipper does it.  To be added later.  Until then it
526     probably doesn't hurt to force deflation when streaming.  12/30/04 EG
527  */
528
529  /* Now is a good time.  For now allow storing for testing.  12/16/05 EG */
530  /* By release need to force deflation based on reports some inflate
531     streamed data to find the end of the data */
532  /* Need to handle bzip2 */
533#ifdef NO_STREAMING_STORE
534  if (use_descriptors && m == STORE)
535  {
536      m = DEFLATE;
537  }
538#endif
539
540  /* Open file to zip up unless it is stdin */
541  if (strcmp(z->name, "-") == 0)
542  {
543    ifile = (ftype)zstdin;
544#if defined(MSDOS) || defined(__human68k__)
545    if (isatty(zstdin) == 0)  /* keep default mode if stdin is a terminal */
546      setmode(zstdin, O_BINARY);
547#endif
548    z->tim = tim;
549  }
550  else
551  {
552#if !(defined(VMS) && defined(VMS_PK_EXTRA))
553    if (extra_fields) {
554      /* create extra field and change z->att and z->atx if desired */
555      set_extra_field(z, &f_utim);
556# ifdef QLZIP
557      if(qlflag)
558          a |= (S_IXUSR) << 16;   /* Cross compilers don't set this */
559# endif
560# ifdef RISCOS
561      m = special != NULL && filetypes(z->extra, special) ? STORE : method;
562# endif /* RISCOS */
563
564      /* For now allow store for testing */
565#ifdef NO_STREAMING_STORE
566      /* For now force deflation if using data descriptors. */
567      if (use_descriptors && m == STORE)
568      {
569        m = DEFLATE;
570      }
571#endif
572
573    }
574#endif /* !(VMS && VMS_PK_EXTRA) */
575    l = issymlnk(a);
576    if (l) {
577      ifile = fbad;
578      m = STORE;
579    }
580    else if (isdir) { /* directory */
581      ifile = fbad;
582      m = STORE;
583      q = 0;
584    }
585#ifdef THEOS
586    else if (((a >> 16) & S_IFMT) == S_IFLIB) {   /* library */
587      ifile = fbad;
588      m = STORE;
589      q = 0;
590    }
591#endif
592    else {
593#ifdef CMS_MVS
594      if (bflag) {
595        if ((ifile = zopen(z->name, fhowb)) == fbad)
596           return ZE_OPEN;
597      }
598      else
599#endif /* CMS_MVS */
600#if defined(UNICODE_SUPPORT) && defined(WIN32)
601      if (!no_win32_wide) {
602        if ((ifile = zwopen(z->namew, fhow)) == fbad)
603          return ZE_OPEN;
604      } else {
605        if ((ifile = zopen(z->name, fhow)) == fbad)
606          return ZE_OPEN;
607      }
608#else
609      if ((ifile = zopen(z->name, fhow)) == fbad)
610        return ZE_OPEN;
611#endif
612    }
613
614    z->tim = tim;
615
616#if defined(VMS) && defined(VMS_PK_EXTRA)
617    /* vms_get_attributes must be called after vms_open() */
618    if (extra_fields) {
619      /* create extra field and change z->att and z->atx if desired */
620      vms_get_attributes(ifile, z, &f_utim);
621    }
622#endif /* VMS && VMS_PK_EXTRA */
623
624#if defined(MMAP) || defined(BIG_MEM)
625    /* Map ordinary files but not devices. This code should go in fileio.c */
626    if (!translate_eol && m != STORE && q != -1L && (ulg)q > 0 &&
627        (ulg)q + MIN_LOOKAHEAD > (ulg)q) {
628# ifdef MMAP
629      /* Map the whole input file in memory */
630      if (window != NULL)
631        free(window);  /* window can't be a mapped file here */
632      window_size = (ulg)q + MIN_LOOKAHEAD;
633      remain = window_size & (PAGESIZE-1);
634      /* If we can't touch the page beyond the end of file, we must
635       * allocate an extra page.
636       */
637      if (remain > MIN_LOOKAHEAD) {
638        window = (uch*)mmap(0, window_size, PROT_READ, MAP_PRIVATE, ifile, 0);
639      } else {
640        window = (uch*)valloc(window_size - remain + PAGESIZE);
641        if (window != NULL) {
642          window = (uch*)mmap((char*)window, window_size - remain, PROT_READ,
643                        MAP_PRIVATE | MAP_FIXED, ifile, 0);
644        } else {
645          window = (uch*)(-1);
646        }
647      }
648      if (window == (uch*)(-1)) {
649        Trace((mesg, " mmap failure on %s\n", z->name));
650        window = NULL;
651        window_size = 0L;
652        remain = (ulg)-1L;
653      } else {
654        remain = (ulg)q;
655      }
656# else /* !MMAP, must be BIG_MEM */
657      /* Read the whole input file at once */
658      window_size = (ulg)q + MIN_LOOKAHEAD;
659      window = window ? (uch*) realloc(window, (unsigned)window_size)
660                      : (uch*) malloc((unsigned)window_size);
661      /* Just use normal code if big malloc or realloc fails: */
662      if (window != NULL) {
663        remain = (ulg)zread(ifile, (char*)window, q+1);
664        if (remain != (ulg)q) {
665          fprintf(mesg, " q=%lu, remain=%lu ", (ulg)q, remain);
666          error("can't read whole file at once");
667        }
668      } else {
669        window_size = 0L;
670      }
671# endif /* ?MMAP */
672    }
673#endif /* MMAP || BIG_MEM */
674
675  } /* strcmp(z->name, "-") == 0 */
676
677  if (extra_fields == 2) {
678    unsigned len;
679    char *p;
680
681    /* step through old extra fields and copy over any not already
682       in new extra fields */
683    p = copy_nondup_extra_fields(tempextra, tempext, z->extra, z->ext, &len);
684    free(z->extra);
685    z->ext = len;
686    z->extra = p;
687    p = copy_nondup_extra_fields(tempcextra, tempcext, z->cextra, z->cext, &len);
688    free(z->cextra);
689    z->cext = len;
690    z->cextra = p;
691
692    if (tempext)
693      free(tempextra);
694    if (tempcext)
695      free(tempcextra);
696  }
697
698  if (q == 0)
699    m = STORE;
700  if (m == BEST)
701    m = DEFLATE;
702
703  /* Do not create STORED files with extended local headers if the
704   * input size is not known, because such files could not be extracted.
705   * So if the zip file is not seekable and the input file is not
706   * on disk, obey the -0 option by forcing deflation with stored block.
707   * Note however that using "zip -0" as filter is not very useful...
708   * ??? to be done.
709   */
710
711  /* An alternative used by others is to allow storing but on reading do
712   * a second check when a signature is found.  This is simply to check
713   * the compressed size to the bytes read since the start of the file data.
714   * If this is the right signature then the compressed size should match
715   * the size of the compressed data to that point.  If not look for the
716   * next signature.  We should do this.  12/31/04 EG
717   *
718   * For reading and testing we should do this, but should not write
719   * stored streamed data unless for testing as finding the end of
720   * streamed deflated data can be done by inflating.  6/26/06 EG
721   */
722
723  /* Fill in header information and write local header to zip file.
724   * This header will later be re-written since compressed length and
725   * crc are not yet known.
726   */
727
728  /* (Assume ext, cext, com, and zname already filled in.) */
729#if defined(OS2) || defined(WIN32)
730# ifdef WIN32_OEM
731  /* When creating OEM-coded names on Win32, the entries must always be marked
732     as "created on MSDOS" (OS_CODE = 0), because UnZip needs to handle archive
733     entry names just like those created by Zip's MSDOS port.
734   */
735  z->vem = (ush)(dosify ? 20 : 0 + Z_MAJORVER * 10 + Z_MINORVER);
736# else
737  z->vem = (ush)(z->dosflag ? (dosify ? 20 : /* Made under MSDOS by PKZIP 2.0 */
738                               (0 + Z_MAJORVER * 10 + Z_MINORVER))
739                 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);
740  /* For a plain old (8+3) FAT file system, we cheat and pretend that the file
741   * was not made on OS2/WIN32 but under DOS. unzip is confused otherwise.
742   */
743# endif
744#else /* !(OS2 || WIN32) */
745  z->vem = (ush)(dosify ? 20 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER);
746#endif /* ?(OS2 || WIN32) */
747
748  z->ver = (ush)(m == STORE ? 10 : 20); /* Need PKUNZIP 2.0 except for store */
749#ifdef BZIP2_SUPPORT
750  if (method == BZIP2)
751      z->ver = (ush)(m == STORE ? 10 : 46);
752#endif
753  z->crc = 0;  /* to be updated later */
754  /* Assume first that we will need an extended local header: */
755  if (isdir)
756    /* If dir then q = 0 and extended header not needed */
757    z->flg = 0;
758  else
759    z->flg = 8;  /* to be updated later */
760#if CRYPT
761  if (!isdir && key != NULL) {
762    z->flg |= 1;
763    /* Since we do not yet know the crc here, we pretend that the crc
764     * is the modification time:
765     */
766    z->crc = z->tim << 16;
767    /* More than pretend.  File is encrypted using crypt header with that. */
768  }
769#endif /* CRYPT */
770  z->lflg = z->flg;
771  z->how = (ush)m;                              /* may be changed later  */
772  z->siz = (zoff_t)(m == STORE && q >= 0 ? q : 0); /* will be changed later */
773  z->len = (zoff_t)(q != -1L ? q : 0);          /* may be changed later  */
774  if (z->att == (ush)UNKNOWN) {
775      z->att = BINARY;                    /* set sensible value in header */
776      set_type = 1;
777  }
778  /* Attributes from filetime(), flag bits from set_extra_field(): */
779#if defined(DOS) || defined(OS2) || defined(WIN32)
780  z->atx = z->dosflag ? a & 0xff : a | (z->atx & 0x0000ff00);
781#else
782  z->atx = dosify ? a & 0xff : a | (z->atx & 0x0000ff00);
783#endif /* DOS || OS2 || WIN32 */
784
785  if ((r = putlocal(z, PUTLOCAL_WRITE)) != ZE_OK) {
786    if (ifile != fbad)
787      zclose(ifile);
788    return r;
789  }
790
791  /* now get split information set by bfwrite() */
792  z->off = current_local_offset;
793
794  /* disk local header was written to */
795  z->dsk = current_local_disk;
796
797  tempzn += 4 + LOCHEAD + z->nam + z->ext;
798
799
800#if CRYPT
801  if (!isdir && key != NULL) {
802    crypthead(key, z->crc);
803    z->siz += RAND_HEAD_LEN;  /* to be updated later */
804    tempzn += RAND_HEAD_LEN;
805  }
806#endif /* CRYPT */
807  if (ferror(y)) {
808    if (ifile != fbad)
809      zclose(ifile);
810    ZIPERR(ZE_WRITE, "unexpected error on zip file");
811  }
812
813  last_o = o;
814  o = zftello(y); /* for debugging only, ftell can fail on pipes */
815  if (ferror(y))
816    clearerr(y);
817
818  if (o != -1 && last_o > o) {
819    fprintf(mesg, "last %s o %s\n", zip_fzofft(last_o, NULL, NULL),
820                                    zip_fzofft(o, NULL, NULL));
821    ZIPERR(ZE_BIG, "seek wrap - zip file too big to write");
822  }
823
824  /* Write stored or deflated file to zip file */
825  isize = 0L;
826  crc = CRCVAL_INITIAL;
827
828  if (isdir) {
829    /* nothing to write */
830  }
831  else if (m != STORE) {
832    if (set_type) z->att = (ush)UNKNOWN;
833    /* ... is finally set in file compression routine */
834#ifdef BZIP2_SUPPORT
835    if (m == BZIP2) {
836      s = bzfilecompress(z, &m);
837    }
838    else
839#endif /* BZIP2_SUPPORT */
840    {
841      s = filecompress(z, &m);
842    }
843#ifndef PGP
844    if (z->att == (ush)BINARY && translate_eol && file_binary) {
845      if (translate_eol == 1)
846        zipwarn("has binary so -l ignored", "");
847      else
848        zipwarn("has binary so -ll ignored", "");
849    }
850    else if (z->att == (ush)BINARY && translate_eol) {
851      if (translate_eol == 1)
852        zipwarn("-l used on binary file - corrupted?", "");
853      else
854        zipwarn("-ll used on binary file - corrupted?", "");
855    }
856#endif
857  }
858  else
859  {
860    if ((b = malloc(SBSZ)) == NULL)
861       return ZE_MEM;
862
863    if (l) {
864      k = rdsymlnk(z->name, b, SBSZ);
865/*
866 * compute crc first because zfwrite will alter the buffer b points to !!
867 */
868      crc = crc32(crc, (uch *) b, k);
869      if (zfwrite(b, 1, k) != k)
870      {
871        free((zvoid *)b);
872        return ZE_TEMP;
873      }
874      isize = k;
875
876#ifdef MINIX
877      q = k;
878#endif /* MINIX */
879    }
880    else
881    {
882      while ((k = file_read(b, SBSZ)) > 0 && k != (extent) EOF)
883      {
884        if (zfwrite(b, 1, k) != k)
885        {
886          if (ifile != fbad)
887            zclose(ifile);
888          free((zvoid *)b);
889          return ZE_TEMP;
890        }
891        if (!display_globaldots) {
892          if (dot_size > 0) {
893            /* initial space */
894            if (noisy && dot_count == -1) {
895#ifndef WINDLL
896              putc(' ', mesg);
897              fflush(mesg);
898#else
899              fprintf(stdout,"%c",' ');
900#endif
901              dot_count++;
902            }
903            dot_count++;
904            if (dot_size <= (dot_count + 1) * SBSZ) dot_count = 0;
905          }
906          if ((verbose || noisy) && dot_size && !dot_count) {
907#ifndef WINDLL
908            putc('.', mesg);
909            fflush(mesg);
910#else
911            fprintf(stdout,"%c",'.');
912#endif
913            mesg_line_started = 1;
914          }
915        }
916      }
917    }
918    free((zvoid *)b);
919    s = isize;
920  }
921  if (ifile != fbad && zerr(ifile)) {
922    perror("\nzip warning");
923    if (logfile)
924      fprintf(logfile, "\nzip warning: %s\n", strerror(errno));
925    zipwarn("could not read input file: ", z->oname);
926  }
927  if (ifile != fbad)
928    zclose(ifile);
929#ifdef MMAP
930  if (remain != (ulg)-1L) {
931    munmap((caddr_t) window, window_size);
932    window = NULL;
933  }
934#endif /*MMAP */
935
936  tempzn += s;
937  p = tempzn; /* save for future fseek() */
938
939#if (!defined(MSDOS) || defined(OS2))
940#if !defined(VMS) && !defined(CMS_MVS) && !defined(__mpexl)
941  /* Check input size (but not in VMS -- variable record lengths mess it up)
942   * and not on MSDOS -- diet in TSR mode reports an incorrect file size)
943   */
944#ifndef TANDEM /* Tandem EOF does not match byte count unless Unstructured */
945  if (!translate_eol && q != -1L && isize != q)
946  {
947    Trace((mesg, " i=%lu, q=%lu ", isize, q));
948    zipwarn(" file size changed while zipping ", z->name);
949  }
950#endif /* !TANDEM */
951#endif /* !VMS && !CMS_MVS && !__mpexl */
952#endif /* (!MSDOS || OS2) */
953
954  if (isdir)
955  {
956    /* A directory */
957    z->siz = 0;
958    z->len = 0;
959    z->how = STORE;
960    z->ver = 10;
961    /* never encrypt directory so don't need extended local header */
962    z->flg &= ~8;
963    z->lflg &= ~8;
964  }
965  else
966  {
967    /* Try to rewrite the local header with correct information */
968    z->crc = crc;
969    z->siz = s;
970#if CRYPT
971    if (!isdir && key != NULL)
972      z->siz += RAND_HEAD_LEN;
973#endif /* CRYPT */
974    z->len = isize;
975    /* if can seek back to local header */
976#ifdef BROKEN_FSEEK
977    if (use_descriptors || !fseekable(y) || zfseeko(y, z->off, SEEK_SET))
978#else
979    if (use_descriptors || zfseeko(y, z->off, SEEK_SET))
980#endif
981    {
982      if (z->how != (ush) m)
983         error("can't rewrite method");
984      if (m == STORE && q < 0)
985         ZIPERR(ZE_PARMS, "zip -0 not supported for I/O on pipes or devices");
986      if ((r = putextended(z)) != ZE_OK)
987        return r;
988      /* if Zip64 and not seekable then Zip64 data descriptor */
989#ifdef ZIP64_SUPPORT
990      tempzn += (zip64_entry ? 24L : 16L);
991#else
992      tempzn += 16L;
993#endif
994      z->flg = z->lflg; /* if z->flg modified by deflate */
995    } else {
996      /* ftell() not as useful across splits */
997      if (bytes_this_entry != (uzoff_t)(key ? s + 12 : s)) {
998        fprintf(mesg, " s=%s, actual=%s ",
999                zip_fzofft(s, NULL, NULL), zip_fzofft(bytes_this_entry, NULL, NULL));
1000        error("incorrect compressed size");
1001      }
1002#if 0
1003       /* seek ok, ftell() should work, check compressed size */
1004# if !defined(VMS) && !defined(CMS_MVS)
1005      if (p - o != s) {
1006        fprintf(mesg, " s=%s, actual=%s ",
1007                zip_fzofft(s, NULL, NULL), zip_fzofft(p-o, NULL, NULL));
1008        error("incorrect compressed size");
1009      }
1010# endif /* !VMS && !CMS_MVS */
1011#endif /* 0 */
1012      z->how = (ush)m;
1013      switch (m)
1014      {
1015      case STORE:
1016        z->ver = 10; break;
1017      /* Need PKUNZIP 2.0 for DEFLATE */
1018      case DEFLATE:
1019        z->ver = 20; break;
1020#ifdef BZIP2_SUPPORT
1021      case BZIP2:
1022        z->ver = 46; break;
1023#endif
1024      }
1025      /*
1026       * The encryption header needs the crc, but we don't have it
1027       * for a new file.  The file time is used instead and the encryption
1028       * header then used to encrypt the data.  The AppNote standard only
1029       * can be applied to a file that the crc is known, so that means
1030       * either an existing entry in an archive or get the crc before
1031       * creating the encryption header and then encrypt the data.
1032       */
1033      if ((z->flg & 1) == 0) {
1034        /* not encrypting so don't need extended local header */
1035        z->flg &= ~8;
1036      }
1037      /* deflate may have set compression level bit markers in z->flg,
1038         and we can't think of any reason central and local flags should
1039         be different. */
1040      z->lflg = z->flg;
1041
1042      /* If not using descriptors, back up and rewrite local header. */
1043      if (split_method == 1 && current_local_file != y) {
1044        if (zfseeko(current_local_file, z->off, SEEK_SET))
1045          return ZE_READ;
1046      }
1047
1048      /* if local header in another split, putlocal will close it */
1049      if ((r = putlocal(z, PUTLOCAL_REWRITE)) != ZE_OK)
1050        return r;
1051
1052      if (zfseeko(y, bytes_this_split, SEEK_SET))
1053        return ZE_READ;
1054
1055      if ((z->flg & 1) != 0) {
1056        /* encrypted file, extended header still required */
1057        if ((r = putextended(z)) != ZE_OK)
1058          return r;
1059#ifdef ZIP64_SUPPORT
1060        if (zip64_entry)
1061          tempzn += 24L;
1062        else
1063          tempzn += 16L;
1064#else
1065        tempzn += 16L;
1066#endif
1067      }
1068    }
1069  } /* isdir */
1070  /* Free the local extra field which is no longer needed */
1071  if (z->ext) {
1072    if (z->extra != z->cextra) {
1073      free((zvoid *)(z->extra));
1074      z->extra = NULL;
1075    }
1076    z->ext = 0;
1077  }
1078
1079  /* Display statistics */
1080  if (noisy)
1081  {
1082    if (verbose) {
1083      fprintf( mesg, "\t(in=%s) (out=%s)",
1084               zip_fzofft(isize, NULL, "u"), zip_fzofft(s, NULL, "u"));
1085    }
1086#ifdef BZIP2_SUPPORT
1087    if (m == BZIP2)
1088      fprintf(mesg, " (bzipped %d%%)\n", percent(isize, s));
1089    else
1090#endif
1091    if (m == DEFLATE)
1092      fprintf(mesg, " (deflated %d%%)\n", percent(isize, s));
1093    else
1094      fprintf(mesg, " (stored 0%%)\n");
1095    mesg_line_started = 0;
1096    fflush(mesg);
1097  }
1098  if (logall)
1099  {
1100#ifdef BZIP2_SUPPORT
1101    if (m == BZIP2)
1102      fprintf(logfile, " (bzipped %d%%)\n", percent(isize, s));
1103    else
1104#endif
1105    if (m == DEFLATE)
1106      fprintf(logfile, " (deflated %d%%)\n", percent(isize, s));
1107    else
1108      fprintf(logfile, " (stored 0%%)\n");
1109    logfile_line_started = 0;
1110    fflush(logfile);
1111  }
1112
1113#ifdef WINDLL
1114# ifdef ZIP64_SUPPORT
1115   /* The DLL api has been updated and uses a different
1116      interface.  7/24/04 EG */
1117   if (lpZipUserFunctions->ServiceApplication64 != NULL)
1118    {
1119    if ((*lpZipUserFunctions->ServiceApplication64)(z->zname, isize))
1120                ZIPERR(ZE_ABORT, "User terminated operation");
1121    }
1122  else
1123   {
1124   filesize64 = isize;
1125   low = (unsigned long)(filesize64 & 0x00000000FFFFFFFF);
1126   high = (unsigned long)((filesize64 >> 32) & 0x00000000FFFFFFFF);
1127   if (lpZipUserFunctions->ServiceApplication64_No_Int64 != NULL) {
1128    if ((*lpZipUserFunctions->ServiceApplication64_No_Int64)(z->zname, low, high))
1129                ZIPERR(ZE_ABORT, "User terminated operation");
1130    }
1131   }
1132# else
1133  if (lpZipUserFunctions->ServiceApplication != NULL)
1134  {
1135    if ((*lpZipUserFunctions->ServiceApplication)(z->zname, isize))
1136    {
1137      ZIPERR(ZE_ABORT, "User terminated operation");
1138    }
1139  }
1140# endif
1141#endif
1142
1143  return ZE_OK;
1144}
1145
1146
1147
1148
1149local unsigned file_read(buf, size)
1150  char *buf;
1151  unsigned size;
1152/* Read a new buffer from the current input file, perform end-of-line
1153 * translation, and update the crc and input file size.
1154 * IN assertion: size >= 2 (for end-of-line translation)
1155 */
1156{
1157  unsigned len;
1158  char *b;
1159  zoff_t isize_prev;    /* Previous isize.  Used for overflow check. */
1160
1161#if defined(MMAP) || defined(BIG_MEM)
1162  if (remain == 0L) {
1163    return 0;
1164  } else if (remain != (ulg)-1L) {
1165    /* The window data is already in place. We still compute the crc
1166     * by 32K blocks instead of once on whole file to keep a certain
1167     * locality of reference.
1168     */
1169    Assert(buf == (char*)window + isize, "are you lost?");
1170    if ((ulg)size > remain) size = (unsigned)remain;
1171    if (size > WSIZE) size = WSIZE; /* don't touch all pages at once */
1172    remain -= (ulg)size;
1173    len = size;
1174  } else
1175#endif /* MMAP || BIG_MEM */
1176  if (translate_eol == 0) {
1177    len = zread(ifile, buf, size);
1178    if (len == (unsigned)EOF || len == 0) return len;
1179#ifdef OS390
1180    b = buf;
1181    if (aflag == ASCII) {
1182      while (*b != '\0') {
1183        *b = (char)ascii[(uch)*b];
1184        b++;
1185      }
1186    }
1187#endif
1188  } else if (translate_eol == 1) {
1189    /* translate_eol == 1 */
1190    /* Transform LF to CR LF */
1191    size >>= 1;
1192    b = buf+size;
1193    size = len = zread(ifile, b, size);
1194    if (len == (unsigned)EOF || len == 0) return len;
1195
1196    /* check buf for binary - 12/16/04 */
1197    if (file_binary == -1) {
1198      /* first read */
1199      file_binary = is_text_buf(b, size) ? 0 : 1;
1200    }
1201
1202    if (file_binary != 1) {
1203#ifdef EBCDIC
1204      if (aflag == ASCII)
1205      {
1206         do {
1207            char c;
1208
1209            if ((c = *b++) == '\n') {
1210               *buf++ = CR; *buf++ = LF; len++;
1211            } else {
1212              *buf++ = (char)ascii[(uch)c];
1213            }
1214         } while (--size != 0);
1215      }
1216      else
1217#endif /* EBCDIC */
1218      {
1219         do {
1220            if ((*buf++ = *b++) == '\n') *(buf-1) = CR, *buf++ = LF, len++;
1221         } while (--size != 0);
1222      }
1223      buf -= len;
1224    } else { /* do not translate binary */
1225      memcpy(buf, b, size);
1226    }
1227
1228  } else {
1229    /* translate_eol == 2 */
1230    /* Transform CR LF to LF and suppress final ^Z */
1231    b = buf;
1232    size = len = zread(ifile, buf, size-1);
1233    if (len == (unsigned)EOF || len == 0) return len;
1234
1235    /* check buf for binary - 12/16/04 */
1236    if (file_binary == -1) {
1237      /* first read */
1238      file_binary = is_text_buf(b, size) ? 0 : 1;
1239    }
1240
1241    if (file_binary != 1) {
1242      buf[len] = '\n'; /* I should check if next char is really a \n */
1243#ifdef EBCDIC
1244      if (aflag == ASCII)
1245      {
1246         do {
1247            char c;
1248
1249            if ((c = *b++) == '\r' && *b == '\n') {
1250               len--;
1251            } else {
1252               *buf++ = (char)(c == '\n' ? LF : ascii[(uch)c]);
1253            }
1254         } while (--size != 0);
1255      }
1256      else
1257#endif /* EBCDIC */
1258      {
1259         do {
1260            if (( *buf++ = *b++) == CR && *b == LF) buf--, len--;
1261         } while (--size != 0);
1262      }
1263      if (len == 0) {
1264         zread(ifile, buf, 1); len = 1; /* keep single \r if EOF */
1265#ifdef EBCDIC
1266         if (aflag == ASCII) {
1267            *buf = (char)(*buf == '\n' ? LF : ascii[(uch)(*buf)]);
1268         }
1269#endif
1270      } else {
1271         buf -= len;
1272         if (buf[len-1] == CTRLZ) len--; /* suppress final ^Z */
1273      }
1274    }
1275  }
1276  crc = crc32(crc, (uch *) buf, len);
1277  /* 2005-05-23 SMS.
1278     Increment file size.  A small-file program reading a large file may
1279     cause isize to overflow, so complain (and abort) if it goes
1280     negative or wraps around.  Awful things happen later otherwise.
1281  */
1282  isize_prev = isize;
1283  isize += (ulg)len;
1284  if (isize < isize_prev) {
1285    ZIPERR(ZE_BIG, "overflow in byte count");
1286  }
1287  return len;
1288}
1289
1290
1291#ifdef USE_ZLIB
1292
1293local int zl_deflate_init(pack_level)
1294    int pack_level;
1295{
1296    unsigned i;
1297    int windowBits;
1298    int err = Z_OK;
1299    int zp_err = ZE_OK;
1300
1301    if (zlib_version[0] != ZLIB_VERSION[0]) {
1302        sprintf(errbuf, "incompatible zlib version (expected %s, found %s)",
1303              ZLIB_VERSION, zlib_version);
1304        zp_err = ZE_LOGIC;
1305    } else if (strcmp(zlib_version, ZLIB_VERSION) != 0) {
1306        fprintf(mesg,
1307                "\twarning:  different zlib version (expected %s, using %s)\n",
1308                ZLIB_VERSION, zlib_version);
1309    }
1310
1311    /* windowBits = log2(WSIZE) */
1312    for (i = ((unsigned)WSIZE), windowBits = 0; i != 1; i >>= 1, ++windowBits);
1313
1314    zstrm.zalloc = (alloc_func)Z_NULL;
1315    zstrm.zfree = (free_func)Z_NULL;
1316
1317    Trace((stderr, "initializing deflate()\n"));
1318    err = deflateInit2(&zstrm, pack_level, Z_DEFLATED, -windowBits, 8, 0);
1319
1320    if (err == Z_MEM_ERROR) {
1321        sprintf(errbuf, "cannot initialize zlib deflate");
1322        zp_err = ZE_MEM;
1323    } else if (err != Z_OK) {
1324        sprintf(errbuf, "zlib deflateInit failure (%d)", err);
1325        zp_err = ZE_LOGIC;
1326    }
1327
1328    deflInit = TRUE;
1329    return zp_err;
1330}
1331
1332
1333void zl_deflate_free()
1334{
1335    int err;
1336
1337    if (f_obuf != NULL) {
1338        free(f_obuf);
1339        f_obuf = NULL;
1340    }
1341    if (f_ibuf != NULL) {
1342        free(f_ibuf);
1343        f_ibuf = NULL;
1344    }
1345    if (deflInit) {
1346        err = deflateEnd(&zstrm);
1347        if (err != Z_OK && err !=Z_DATA_ERROR) {
1348            ziperr(ZE_LOGIC, "zlib deflateEnd failed");
1349        }
1350        deflInit = FALSE;
1351    }
1352}
1353
1354#else /* !USE_ZLIB */
1355
1356# ifdef ZP_NEED_MEMCOMPR
1357/* ===========================================================================
1358 * In-memory read function. As opposed to file_read(), this function
1359 * does not perform end-of-line translation, and does not update the
1360 * crc and input size.
1361 *    Note that the size of the entire input buffer is an unsigned long,
1362 * but the size used in mem_read() is only an unsigned int. This makes a
1363 * difference on 16 bit machines. mem_read() may be called several
1364 * times for an in-memory compression.
1365 */
1366local unsigned mem_read(b, bsize)
1367     char *b;
1368     unsigned bsize;
1369{
1370    if (in_offset < in_size) {
1371        ulg block_size = in_size - in_offset;
1372        if (block_size > (ulg)bsize) block_size = (ulg)bsize;
1373        memcpy(b, in_buf + in_offset, (unsigned)block_size);
1374        in_offset += (unsigned)block_size;
1375        return (unsigned)block_size;
1376    } else {
1377        return 0; /* end of input */
1378    }
1379}
1380# endif /* ZP_NEED_MEMCOMPR */
1381
1382
1383/* ===========================================================================
1384 * Flush the current output buffer.
1385 */
1386void flush_outbuf(o_buf, o_idx)
1387    char *o_buf;
1388    unsigned *o_idx;
1389{
1390    if (y == NULL) {
1391        error("output buffer too small for in-memory compression");
1392    }
1393    /* Encrypt and write the output buffer: */
1394    if (*o_idx != 0) {
1395        zfwrite(o_buf, 1, (extent)*o_idx);
1396        if (ferror(y)) ziperr(ZE_WRITE, "write error on zip file");
1397    }
1398    *o_idx = 0;
1399}
1400
1401/* ===========================================================================
1402 * Return true if the zip file can be seeked. This is used to check if
1403 * the local header can be re-rewritten. This function always returns
1404 * true for in-memory compression.
1405 * IN assertion: the local header has already been written (ftell() > 0).
1406 */
1407int seekable()
1408{
1409    return fseekable(y);
1410}
1411#endif /* ?USE_ZLIB */
1412
1413
1414/* ===========================================================================
1415 * Compression to archive file.
1416 */
1417local zoff_t filecompress(z_entry, cmpr_method)
1418    struct zlist far *z_entry;
1419    int *cmpr_method;
1420{
1421#ifdef USE_ZLIB
1422    int err = Z_OK;
1423    unsigned mrk_cnt = 1;
1424    int maybe_stored = FALSE;
1425    ulg cmpr_size;
1426#if defined(MMAP) || defined(BIG_MEM)
1427    unsigned ibuf_sz = (unsigned)SBSZ;
1428#else
1429#   define ibuf_sz ((unsigned)SBSZ)
1430#endif
1431#ifndef OBUF_SZ
1432#  define OBUF_SZ ZBSZ
1433#endif
1434    unsigned u;
1435
1436#if defined(MMAP) || defined(BIG_MEM)
1437    if (remain == (ulg)-1L && f_ibuf == NULL)
1438#else /* !(MMAP || BIG_MEM */
1439    if (f_ibuf == NULL)
1440#endif /* MMAP || BIG_MEM */
1441        f_ibuf = (char *)malloc(SBSZ);
1442    if (f_obuf == NULL)
1443        f_obuf = (char *)malloc(OBUF_SZ);
1444#if defined(MMAP) || defined(BIG_MEM)
1445    if ((remain == (ulg)-1L && f_ibuf == NULL) || f_obuf == NULL)
1446#else /* !(MMAP || BIG_MEM */
1447    if (f_ibuf == NULL || f_obuf == NULL)
1448#endif /* MMAP || BIG_MEM */
1449        ziperr(ZE_MEM, "allocating zlib file-I/O buffers");
1450
1451    if (!deflInit) {
1452        err = zl_deflate_init(level);
1453        if (err != ZE_OK)
1454            ziperr(err, errbuf);
1455    }
1456
1457    if (level <= 2) {
1458        z_entry->flg |= 4;
1459    } else if (level >= 8) {
1460        z_entry->flg |= 2;
1461    }
1462#if defined(MMAP) || defined(BIG_MEM)
1463    if (remain != (ulg)-1L) {
1464        zstrm.next_in = (Bytef *)window;
1465        ibuf_sz = (unsigned)WSIZE;
1466    } else
1467#endif /* MMAP || BIG_MEM */
1468    {
1469        zstrm.next_in = (Bytef *)f_ibuf;
1470    }
1471    zstrm.avail_in = file_read(zstrm.next_in, ibuf_sz);
1472    if (zstrm.avail_in < ibuf_sz) {
1473        unsigned more = file_read(zstrm.next_in + zstrm.avail_in,
1474                                  (ibuf_sz - zstrm.avail_in));
1475        if (more == EOF || more == 0) {
1476            maybe_stored = TRUE;
1477        } else {
1478            zstrm.avail_in += more;
1479        }
1480    }
1481    zstrm.next_out = (Bytef *)f_obuf;
1482    zstrm.avail_out = OBUF_SZ;
1483
1484    if (!maybe_stored) while (zstrm.avail_in != 0 && zstrm.avail_in != EOF) {
1485        err = deflate(&zstrm, Z_NO_FLUSH);
1486        if (err != Z_OK && err != Z_STREAM_END) {
1487            sprintf(errbuf, "unexpected zlib deflate error %d", err);
1488            ziperr(ZE_LOGIC, errbuf);
1489        }
1490        if (zstrm.avail_out == 0) {
1491            if (zfwrite(f_obuf, 1, OBUF_SZ) != OBUF_SZ) {
1492                ziperr(ZE_TEMP, "error writing to zipfile");
1493            }
1494            zstrm.next_out = (Bytef *)f_obuf;
1495            zstrm.avail_out = OBUF_SZ;
1496        }
1497        if (zstrm.avail_in == 0) {
1498            if (verbose || noisy)
1499                while((unsigned)(zstrm.total_in / (uLong)WSIZE) > mrk_cnt) {
1500                    mrk_cnt++;
1501                    if (!display_globaldots) {
1502                      if (dot_size > 0) {
1503                        /* initial space */
1504                        if (noisy && dot_count == -1) {
1505#ifndef WINDLL
1506                          putc(' ', mesg);
1507                          fflush(mesg);
1508#else
1509                          fprintf(stdout,"%c",' ');
1510#endif
1511                          dot_count++;
1512                        }
1513                        dot_count++;
1514                        if (dot_size <= (dot_count + 1) * WSIZE) dot_count = 0;
1515                      }
1516                      if (noisy && dot_size && !dot_count) {
1517#ifndef WINDLL
1518                        putc('.', mesg);
1519                        fflush(mesg);
1520#else
1521                        fprintf(stdout,"%c",'.');
1522#endif
1523                        mesg_line_started = 1;
1524                      }
1525                    }
1526                }
1527#if defined(MMAP) || defined(BIG_MEM)
1528            if (remain == (ulg)-1L)
1529                zstrm.next_in = (Bytef *)f_ibuf;
1530#else
1531            zstrm.next_in = (Bytef *)f_ibuf;
1532#endif
1533            zstrm.avail_in = file_read(zstrm.next_in, ibuf_sz);
1534        }
1535    }
1536
1537    do {
1538        err = deflate(&zstrm, Z_FINISH);
1539        if (maybe_stored) {
1540            if (err == Z_STREAM_END && zstrm.total_out >= zstrm.total_in &&
1541                fseekable(zipfile)) {
1542                /* deflation does not reduce size, switch to STORE method */
1543                unsigned len_out = (unsigned)zstrm.total_in;
1544                if (zfwrite(f_ibuf, 1, len_out) != len_out) {
1545                    ziperr(ZE_TEMP, "error writing to zipfile");
1546                }
1547                zstrm.total_out = (uLong)len_out;
1548                *cmpr_method = STORE;
1549                break;
1550            } else {
1551                maybe_stored = FALSE;
1552            }
1553        }
1554        if (zstrm.avail_out < OBUF_SZ) {
1555            unsigned len_out = OBUF_SZ - zstrm.avail_out;
1556            if (zfwrite(f_obuf, 1, len_out) != len_out) {
1557                ziperr(ZE_TEMP, "error writing to zipfile");
1558            }
1559            zstrm.next_out = (Bytef *)f_obuf;
1560            zstrm.avail_out = OBUF_SZ;
1561        }
1562    } while (err == Z_OK);
1563
1564    if (err != Z_STREAM_END) {
1565        sprintf(errbuf, "unexpected zlib deflate error %d", err);
1566        ziperr(ZE_LOGIC, errbuf);
1567    }
1568
1569    if (z_entry->att == (ush)UNKNOWN)
1570        z_entry->att = (ush)(zstrm.data_type == Z_ASCII ? ASCII : BINARY);
1571    cmpr_size = (ulg)zstrm.total_out;
1572
1573    if ((err = deflateReset(&zstrm)) != Z_OK)
1574        ziperr(ZE_LOGIC, "zlib deflateReset failed");
1575    return cmpr_size;
1576#else /* !USE_ZLIB */
1577
1578    /* Set the defaults for file compression. */
1579    read_buf = file_read;
1580
1581    /* Initialize deflate's internals and execute file compression. */
1582    bi_init(file_outbuf, sizeof(file_outbuf), TRUE);
1583    ct_init(&z_entry->att, cmpr_method);
1584    lm_init(level, &z_entry->flg);
1585    return deflate();
1586#endif /* ?USE_ZLIB */
1587}
1588
1589#ifdef ZP_NEED_MEMCOMPR
1590/* ===========================================================================
1591 * In-memory compression. This version can be used only if the entire input
1592 * fits in one memory buffer. The compression is then done in a single
1593 * call of memcompress(). (An extension to allow repeated calls would be
1594 * possible but is not needed here.)
1595 * The first two bytes of the compressed output are set to a short with the
1596 * method used (DEFLATE or STORE). The following four bytes contain the CRC.
1597 * The values are stored in little-endian order on all machines.
1598 * This function returns the byte size of the compressed output, including
1599 * the first six bytes (method and crc).
1600 */
1601
1602ulg memcompress(tgt, tgtsize, src, srcsize)
1603    char *tgt, *src;       /* target and source buffers */
1604    ulg tgtsize, srcsize;  /* target and source sizes */
1605{
1606    ulg crc;
1607    unsigned out_total;
1608    int method   = DEFLATE;
1609#ifdef USE_ZLIB
1610    int err      = Z_OK;
1611#else
1612    ush att      = (ush)UNKNOWN;
1613    ush flags    = 0;
1614#endif
1615
1616    if (tgtsize <= (ulg)6L) error("target buffer too small");
1617    out_total = 2 + 4;
1618
1619#ifdef USE_ZLIB
1620    if (!deflInit) {
1621        err = zl_deflate_init(level);
1622        if (err != ZE_OK)
1623            ziperr(err, errbuf);
1624    }
1625
1626    zstrm.next_in = (Bytef *)src;
1627    zstrm.avail_in = (uInt)srcsize;
1628    zstrm.next_out = (Bytef *)(tgt + out_total);
1629    zstrm.avail_out = (uInt)tgtsize - (uInt)out_total;
1630
1631    err = deflate(&zstrm, Z_FINISH);
1632    if (err != Z_STREAM_END)
1633        error("output buffer too small for in-memory compression");
1634    out_total += (unsigned)zstrm.total_out;
1635
1636    if ((err = deflateReset(&zstrm)) != Z_OK)
1637        error("zlib deflateReset failed");
1638#else /* !USE_ZLIB */
1639    read_buf  = mem_read;
1640    in_buf    = src;
1641    in_size   = (unsigned)srcsize;
1642    in_offset = 0;
1643    window_size = 0L;
1644
1645    bi_init(tgt + (2 + 4), (unsigned)(tgtsize - (2 + 4)), FALSE);
1646    ct_init(&att, &method);
1647    lm_init((level != 0 ? level : 1), &flags);
1648    out_total += (unsigned)deflate();
1649    window_size = 0L; /* was updated by lm_init() */
1650#endif /* ?USE_ZLIB */
1651
1652    crc = CRCVAL_INITIAL;
1653    crc = crc32(crc, (uch *)src, (extent)srcsize);
1654
1655    /* For portability, force little-endian order on all machines: */
1656    tgt[0] = (char)(method & 0xff);
1657    tgt[1] = (char)((method >> 8) & 0xff);
1658    tgt[2] = (char)(crc & 0xff);
1659    tgt[3] = (char)((crc >> 8) & 0xff);
1660    tgt[4] = (char)((crc >> 16) & 0xff);
1661    tgt[5] = (char)((crc >> 24) & 0xff);
1662
1663    return (ulg)out_total;
1664}
1665#endif /* ZP_NEED_MEMCOMPR */
1666
1667#ifdef BZIP2_SUPPORT
1668
1669local int bz_compress_init(pack_level)
1670int pack_level;
1671{
1672    int err = BZ_OK;
1673    int zp_err = ZE_OK;
1674    const char *bzlibVer;
1675
1676    bzlibVer = BZ2_bzlibVersion();
1677
1678    /* $TODO - Check BZIP2 LIB version? */
1679
1680    bstrm.bzalloc = NULL;
1681    bstrm.bzfree = NULL;
1682    bstrm.opaque = NULL;
1683
1684    Trace((stderr, "initializing bzlib compress()\n"));
1685    err = BZ2_bzCompressInit(&bstrm, pack_level, 0, 30);
1686
1687    if (err == BZ_MEM_ERROR) {
1688        sprintf(errbuf, "cannot initialize bzlib compress");
1689        zp_err = ZE_MEM;
1690    } else if (err != BZ_OK) {
1691        sprintf(errbuf, "bzlib bzCompressInit failure (%d)", err);
1692        zp_err = ZE_LOGIC;
1693    }
1694
1695    bzipInit = TRUE;
1696    return zp_err;
1697}
1698
1699void bz_compress_free()
1700{
1701    int err;
1702
1703    if (f_obuf != NULL) {
1704        free(f_obuf);
1705        f_obuf = NULL;
1706    }
1707    if (f_ibuf != NULL) {
1708        free(f_ibuf);
1709        f_ibuf = NULL;
1710    }
1711    if (bzipInit) {
1712        err = BZ2_bzCompressEnd(&bstrm);
1713        if (err != BZ_OK && err != BZ_DATA_ERROR) {
1714            ziperr(ZE_LOGIC, "bzlib bzCompressEnd failed");
1715        }
1716        bzipInit = FALSE;
1717    }
1718}
1719
1720/* ===========================================================================
1721 * BZIP2 Compression to archive file.
1722 */
1723
1724local zoff_t bzfilecompress(z_entry, cmpr_method)
1725struct zlist far *z_entry;
1726int *cmpr_method;
1727{
1728    FILE *zipfile = y;
1729
1730    int err = BZ_OK;
1731    unsigned mrk_cnt = 1;
1732    int maybe_stored = FALSE;
1733    zoff_t cmpr_size;
1734#if defined(MMAP) || defined(BIG_MEM)
1735    unsigned ibuf_sz = (unsigned)SBSZ;
1736#else
1737#   define ibuf_sz ((unsigned)SBSZ)
1738#endif
1739#ifndef OBUF_SZ
1740#  define OBUF_SZ ZBSZ
1741#endif
1742
1743#if defined(MMAP) || defined(BIG_MEM)
1744    if (remain == (ulg)-1L && f_ibuf == NULL)
1745#else /* !(MMAP || BIG_MEM */
1746    if (f_ibuf == NULL)
1747#endif /* MMAP || BIG_MEM */
1748        f_ibuf = (char *)malloc(SBSZ);
1749    if (f_obuf == NULL)
1750        f_obuf = (char *)malloc(OBUF_SZ);
1751#if defined(MMAP) || defined(BIG_MEM)
1752    if ((remain == (ulg)-1L && f_ibuf == NULL) || f_obuf == NULL)
1753#else /* !(MMAP || BIG_MEM */
1754    if (f_ibuf == NULL || f_obuf == NULL)
1755#endif /* MMAP || BIG_MEM */
1756        ziperr(ZE_MEM, "allocating zlib/bzlib file-I/O buffers");
1757
1758    if (!bzipInit) {
1759        err = bz_compress_init(level);
1760        if (err != ZE_OK)
1761            ziperr(err, errbuf);
1762    }
1763
1764#if defined(MMAP) || defined(BIG_MEM)
1765    if (remain != (ulg)-1L) {
1766        bstrm.next_in = (Bytef *)window;
1767        ibuf_sz = (unsigned)WSIZE;
1768    } else
1769#endif /* MMAP || BIG_MEM */
1770    {
1771        bstrm.next_in = (char *)f_ibuf;
1772    }
1773    bstrm.avail_in = file_read(bstrm.next_in, ibuf_sz);
1774    if (file_binary_final == 0) {
1775      /* check for binary as library does not */
1776      if (!is_text_buf(bstrm.next_in, ibuf_sz))
1777        file_binary_final = 1;
1778    }
1779    if (bstrm.avail_in < ibuf_sz) {
1780        unsigned more = file_read(bstrm.next_in + bstrm.avail_in,
1781                                  (ibuf_sz - bstrm.avail_in));
1782        if (more == (unsigned) EOF || more == 0) {
1783            maybe_stored = TRUE;
1784        } else {
1785            bstrm.avail_in += more;
1786        }
1787    }
1788    bstrm.next_out = (char *)f_obuf;
1789    bstrm.avail_out = OBUF_SZ;
1790
1791    if (!maybe_stored) {
1792      while (bstrm.avail_in != 0 && bstrm.avail_in != (unsigned) EOF) {
1793        err = BZ2_bzCompress(&bstrm, BZ_RUN);
1794        if (err != BZ_RUN_OK && err != BZ_STREAM_END) {
1795            sprintf(errbuf, "unexpected bzlib compress error %d", err);
1796            ziperr(ZE_LOGIC, errbuf);
1797        }
1798        if (bstrm.avail_out == 0) {
1799            if (zfwrite(f_obuf, 1, OBUF_SZ) != OBUF_SZ) {
1800                ziperr(ZE_TEMP, "error writing to zipfile");
1801            }
1802            bstrm.next_out = (char *)f_obuf;
1803            bstrm.avail_out = OBUF_SZ;
1804        }
1805        /* $TODO what about high 32-bits of total-in??? */
1806        if (bstrm.avail_in == 0) {
1807            if (verbose || noisy)
1808#ifdef LARGE_FILE_SUPPORT
1809                while((unsigned)((bstrm.total_in_lo32
1810                                  + (((zoff_t)bstrm.total_in_hi32) << 32))
1811                                 / (zoff_t)(ulg)WSIZE) > mrk_cnt) {
1812#else
1813                while((unsigned)(bstrm.total_in_lo32 / (ulg)WSIZE) > mrk_cnt) {
1814#endif
1815                    mrk_cnt++;
1816                    if (!display_globaldots) {
1817                      if (dot_size > 0) {
1818                        /* initial space */
1819                        if (noisy && dot_count == -1) {
1820#ifndef WINDLL
1821                          putc(' ', mesg);
1822                          fflush(mesg);
1823#else
1824                          fprintf(stdout,"%c",' ');
1825#endif
1826                          dot_count++;
1827                        }
1828                        dot_count++;
1829                        if (dot_size <= (dot_count + 1) * WSIZE) dot_count = 0;
1830                      }
1831                      if (noisy && dot_size && !dot_count) {
1832#ifndef WINDLL
1833                        putc('.', mesg);
1834                        fflush(mesg);
1835#else
1836                        fprintf(stdout,"%c",'.');
1837#endif
1838                        mesg_line_started = 1;
1839                      }
1840                    }
1841                }
1842#if defined(MMAP) || defined(BIG_MEM)
1843            if (remain == (ulg)-1L)
1844                bstrm.next_in = (char *)f_ibuf;
1845#else
1846            bstrm.next_in = (char *)f_ibuf;
1847#endif
1848            bstrm.avail_in = file_read(bstrm.next_in, ibuf_sz);
1849            if (file_binary_final == 0) {
1850              /* check for binary as library does not */
1851              if (!is_text_buf(bstrm.next_in, ibuf_sz))
1852                file_binary_final = 1;
1853            }
1854        }
1855      }
1856    }
1857
1858    /* binary or text */
1859    if (file_binary_final)
1860      /* found binary in file */
1861      z_entry->att = (ush)BINARY;
1862    else
1863      /* text file */
1864      z_entry->att = (ush)ASCII;
1865
1866    do {
1867        err = BZ2_bzCompress(&bstrm, BZ_FINISH);
1868        if (maybe_stored) {
1869            /* This code is only executed when the complete data stream fits
1870               into the input buffer (see above where maybe_stored gets set).
1871               So, it is safe to assume that total_in_hi32 (and total_out_hi32)
1872               are 0, because the input buffer size is well below the 32-bit
1873               limit.
1874             */
1875            if (err == BZ_STREAM_END
1876                && bstrm.total_out_lo32 >= bstrm.total_in_lo32
1877                && fseekable(zipfile)) {
1878                /* BZIP2 compress does not reduce size,
1879                   switch to STORE method */
1880                unsigned len_out = (unsigned)bstrm.total_in_lo32;
1881                if (zfwrite(f_ibuf, 1, len_out) != len_out) {
1882                    ziperr(ZE_TEMP, "error writing to zipfile");
1883                }
1884                bstrm.total_out_lo32 = (ulg)len_out;
1885                *cmpr_method = STORE;
1886                break;
1887            } else {
1888                maybe_stored = FALSE;
1889            }
1890        }
1891        if (bstrm.avail_out < OBUF_SZ) {
1892            unsigned len_out = OBUF_SZ - bstrm.avail_out;
1893            if (zfwrite(f_obuf, 1, len_out) != len_out) {
1894                ziperr(ZE_TEMP, "error writing to zipfile");
1895            }
1896            bstrm.next_out = (char *)f_obuf;
1897            bstrm.avail_out = OBUF_SZ;
1898        }
1899    } while (err == BZ_FINISH_OK);
1900
1901    if (err < BZ_OK) {
1902        sprintf(errbuf, "unexpected bzlib compress error %d", err);
1903        ziperr(ZE_LOGIC, errbuf);
1904    }
1905
1906    if (z_entry->att == (ush)UNKNOWN)
1907        z_entry->att = (ush)BINARY;
1908#ifdef LARGE_FILE_SUPPORT
1909    cmpr_size = (zoff_t)bstrm.total_out_lo32
1910               + (((zoff_t)bstrm.total_out_hi32) << 32);
1911#else
1912    cmpr_size = (zoff_t)bstrm.total_out_lo32;
1913#endif
1914
1915    if ((err = BZ2_bzCompressEnd(&bstrm)) != BZ_OK)
1916        ziperr(ZE_LOGIC, "zlib deflateReset failed");
1917    bzipInit = FALSE;
1918    return cmpr_size;
1919}
1920
1921#endif /* BZIP2_SUPPORT */
1922#endif /* !UTIL */
1923