home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / zip19 / zipup.c < prev   
C/C++ Source or Header  |  1992-08-26  |  12KB  |  428 lines

  1. /*
  2.  
  3.  Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
  4.  Kai Uwe Rommel and Igor Mandrichenko.
  5.  Permission is granted to any individual or institution to use, copy, or
  6.  redistribute this software so long as all of the original files are included
  7.  unmodified, that it is not sold for profit, and that this copyright notice
  8.  is retained.
  9.  
  10. */
  11.  
  12. /*
  13.  *  zipup.c by Mark Adler. Includes modifications by Jean-loup Gailly.
  14.  */
  15.  
  16. #define NOCPYRT         /* this is not a main module */
  17. #include <ctype.h>
  18. #include "zip.h"
  19. #include "revision.h"
  20. #ifdef OS2
  21. #  include "os2zip.h"
  22. #endif
  23.  
  24. /* Use the raw functions for MSDOS and Unix to save on buffer space.
  25.    They're not used for VMS since it doesn't work (raw is weird on VMS).
  26.    (This sort of stuff belongs in fileio.c, but oh well.) */
  27. #ifdef VMS
  28. #  define fhow "r"
  29. #  define fbad NULL
  30.    typedef void *ftype;
  31. #  define zopen(n,p)   (vms_native?vms_open(n)    :(ftype)fopen((n),(p)))
  32. #  define zread(f,b,n) (vms_native?vms_read(f,b,n):fread((b),1,(n),(FILE*)(f)))
  33. #  define zclose(f)    (vms_native?vms_close(f)   :fclose((FILE*)(f)))
  34. #  define zerr(f)      (vms_native?vms_error(f)   :ferror((FILE*)(f)))
  35. #  define zstdin stdin
  36.    ftype vms_open OF((char *));
  37.    int vms_read OF((ftype, char *, int));
  38.    int vms_close OF((ftype));
  39.    int vms_error OF((ftype));
  40. #else /* !VMS */
  41. #  if defined(MSDOS) && !defined(ATARI_ST)
  42. #    include <io.h>
  43. #    include <fcntl.h>
  44. #    define fhow (O_RDONLY|O_BINARY)
  45. #  else /* !MSDOS */
  46.      int open OF((char *, int));
  47.      int read OF((int, char *, int));
  48.      int close OF((int));
  49.      int lseek OF((int, long, int));
  50. #    define fhow 0
  51. #  endif /* ?MSDOS */
  52.    typedef int ftype;
  53. #  define fbad (-1)
  54. #  define zopen(n,p) open(n,p)
  55. #  define zread(f,b,n) read(f,b,n)
  56. #  define zclose(f) close(f)
  57. #  define zerr(f) (k==(extent)(-1L))
  58. #  define zstdin 0
  59. #endif /* ?VMS */
  60.  
  61.  
  62. /* Local data */
  63.  
  64. #ifndef UTIL
  65. local ulg crc;       /* crc on uncompressed file data */
  66. local ftype ifile;   /* file to compress */
  67. #endif
  68. ulg isize;           /* input file size. global only for debugging */    
  69.  
  70. /* Local functions */
  71. #if defined(PROTO) && !defined(UTIL)
  72.    local int suffixes(char *, char *);
  73. #endif
  74.  
  75.  
  76. /* Note: a zip "entry" includes a local header (which includes the file
  77.    name), an encryption header if encrypting, the compressed data
  78.    and possibly an extended local header. */
  79.  
  80. int zipcopy(z, x, y)
  81. struct zlist far *z;    /* zip entry to copy */
  82. FILE *x, *y;            /* source and destination files */
  83. /* Copy the zip entry described by *z from file *x to file *y.  Return an
  84.    error code in the ZE_ class.  Also update tempzn by the number of bytes
  85.    copied. */
  86. {
  87.   ulg n;                /* holds local header offset */
  88.  
  89.   if (fseek(x, z->off, SEEK_SET))
  90.     return ferror(x) ? ZE_READ : ZE_EOF;
  91.   z->off = tempzn;
  92.   n = 4 + LOCHEAD + (long)z->nam + (long)z->ext + z->siz;
  93.   /* copy the extended local header if there is one */
  94.   if (z->lflg & 8) n += 16;
  95.   tempzn += n;
  96.   return fcopy(x, y, n);
  97. }
  98.  
  99.  
  100. #ifndef UTIL
  101.  
  102. int percent(n, m)
  103. long n, m;               /* n is the original size, m is the new size */
  104. /* Return the percentage compression from n to m using only integer
  105.    operations */
  106. {
  107.   if (n > 0xffffffL)            /* If n >= 16M */
  108.   {                             /*  then divide n and m by 256 */
  109.     n += 0x80;  n >>= 8;
  110.     m += 0x80;  m >>= 8;
  111.   }
  112.   return n ? (int)(1 + (200 * (n - m)/n)) / 2 : 0;
  113. }
  114.  
  115. local int suffixes(a, s)
  116. char *a;                /* name to check suffix of */
  117. char *s;                /* list of suffixes separated by : or ; */
  118. /* Return true if a ends in any of the suffixes in the list s. */
  119. {
  120.   int m;                /* true if suffix matches so far */
  121.   char *p;              /* pointer into special */
  122.   char *q;              /* pointer into name a */
  123.  
  124.   m = 1;
  125. #ifdef VMS
  126.   if( (q = strrchr(a,';')) != NULL )    /* Cut out VMS file version */
  127.     --q;
  128.   else
  129.     q = a + strlen(a) - 1;
  130. #else
  131.   q = a + strlen(a) - 1;
  132. #endif
  133.   for (p = s + strlen(s) - 1; p >= s; p--)
  134.     if (*p == ':' || *p == ';')
  135.       if (m)
  136.         return 1;
  137.       else
  138.       {
  139.         m = 1;
  140. #ifdef VMS
  141.         if( (q = strrchr(a,';')) != NULL )      /* Cut out VMS file version */
  142.           --q;
  143.         else
  144.           q = a + strlen(a) - 1;
  145. #else
  146.         q = a + strlen(a) - 1;
  147. #endif
  148.       }
  149.     else
  150.     {
  151.       m = m && q >= a && case_map(*p) == case_map(*q);
  152.       q--;
  153.     }
  154.   return m;
  155. }
  156.  
  157. int zipup(z, y)
  158. struct zlist far *z;    /* zip entry to compress */
  159. FILE *y;                /* output file */
  160. /* Compress the file z->name into the zip entry described by *z and write
  161.    it to the file *y. Encrypt if requested.  Return an error code in the
  162.    ZE_ class.  Also, update tempzn by the number of bytes written. */
  163. {
  164.   ulg a = 0L;           /* attributes returned by filetime() */
  165.   char *b;              /* malloc'ed file buffer */
  166.   extent k = 0;         /* result of zread */
  167.   int l = 0;            /* true if this file is a symbolic link */
  168.   int m;                /* method for this entry */
  169.   ulg o, p;             /* offsets in zip file */
  170.   long q = -2L;         /* size returned by filetime */
  171.   int r;                /* temporary variable */
  172.   ulg s = 0L;           /* size of compressed data */
  173.   int isdir;            /* set for a directory name */
  174.  
  175.   isdir = z->name[strlen(z->name)-1] == '/';
  176.  
  177.   if ((z->tim = filetime(z->name, &a, &q)) == 0 || q < -1L)
  178.     return ZE_OPEN;
  179.   /* q is set to -1 if the input file is a device */
  180.  
  181.   z->nam = strlen(z->zname);
  182.  
  183.   /* Select method based on the suffix and the global method */
  184.   m = special != NULL && suffixes(z->name, special) ? STORE : method;
  185.  
  186.   /* Open file to zip up unless it is stdin */
  187.   if (strcmp(z->name, "-") == 0)
  188.   {
  189.     ifile = (ftype)zstdin;
  190. #ifdef MSDOS
  191.     setmode(zstdin, O_BINARY);
  192. #endif
  193.   }
  194.   else
  195.   {
  196. #ifdef VMS
  197.    if (vms_native)
  198.      get_vms_attributes(z);
  199. #endif
  200. #ifdef OS2
  201.     GetEAs(z->name, &z->extra, &z->ext, &z->cextra, &z->cext);
  202.     /* store data in local header, and size only in central headers */
  203. #endif
  204.     l = issymlnk(a);
  205.     if (l)
  206.       ifile = fbad;
  207.     else if (isdir) { /* directory */
  208.       ifile = fbad;
  209.       m = STORE;
  210.     }
  211.     else if ((ifile = zopen(z->name, fhow)) == fbad)
  212.       return ZE_OPEN;
  213.   }
  214.  
  215.   if (l || q == 0)
  216.     m = STORE;
  217.   if (m == BEST)
  218.     m = DEFLATE;
  219.  
  220.   /* Do not create STORED files with extended local headers if the
  221.    * input size is not known, because such files could not be extracted.
  222.    * So if the zip file is not seekable and the input file is not
  223.    * on disk, obey the -0 option by forcing deflation with stored block.
  224.    * Note however that using "zip -0" as filter is not very useful...
  225.    * ??? to be done.
  226.    */
  227.  
  228.   /* Fill in header information and write local header to zip file.
  229.    * This header will later be re-written since compressed length and
  230.    * crc are not yet known.
  231.    */
  232.  
  233.   /* (Assume ext, cext, com, and zname already filled in.) */
  234. #ifdef OS2
  235.   z->vem = z->dosflag ? 20 :            /* Made under MSDOS by PKZIP 2.0 */
  236.   /* We for a FAT file system, we must cheat and pretend that the
  237.    * file was not made on OS2 but under DOS. unzip is confused otherwise.
  238.    */
  239. #else
  240.   z->vem = dosify ? 20 :                /* Made under MSDOS by PKZIP 2.0 */
  241. #endif
  242. #ifdef VMS
  243.                     0x200 + REVISION;   /* Made under VMS by this Zip */
  244. #else /* !VMS */
  245. # ifdef OS2
  246.                     0x600 + REVISION;   /* Made under OS/2 by this Zip */
  247. # else /* !OS2 */
  248. #  ifdef MSDOS
  249.                     0     + REVISION;   /* Made under MSDOS by this Zip */
  250. #  else
  251.                     0x300 + REVISION;   /* Made under Unix by this Zip */
  252. #  endif /* MSDOS */
  253. # endif /* ?OS2 */
  254. #endif /* ?VMS */
  255.  
  256.   z->ver = 20;                          /* Need PKUNZIP 2.0 */
  257.   z->crc = 0;  /* to be updated later */
  258.   /* Assume first that we will need an extended local header: */
  259.   z->flg = 8;  /* to be updated later */
  260. #ifdef CRYPT
  261.   if (key != NULL) {
  262.     z->flg |= 1;
  263.     /* Since we do not yet know the crc here, we pretend that the crc
  264.      * is the modification time:
  265.      */
  266.     z->crc = z->tim << 16;
  267.   }
  268. #endif
  269.   z->lflg = z->flg;
  270.   z->how = m;                             /* may be changed later  */
  271.   z->siz = m == STORE && q >= 0 ? q : 0;  /* will be changed later  */
  272.   z->len = q >= 0 ? q : 0;                /* may be changed later  */
  273.   z->dsk = 0;
  274.   z->att = BINARY;                        /* may be changed later */
  275.   z->atx = z->dosflag ? a & 0xff : a;      /* Attributes from filetime() */
  276.   z->off = tempzn;
  277.   if ((r = putlocal(z, y)) != ZE_OK)
  278.     return r;
  279.   tempzn += 4 + LOCHEAD + z->nam + z->ext;
  280.  
  281. #ifdef CRYPT
  282.   if (key != NULL) {
  283.     crypthead(key, z->crc, y);
  284.     z->siz += 12;  /* to be updated later */
  285.     tempzn += 12;
  286.   }
  287. #endif
  288.   o = ftell(y); /* for debugging only */
  289.  
  290.   /* Write stored or deflated file to zip file */
  291.   isize = 0L;
  292.   crc = updcrc((char *)NULL, 0);
  293.  
  294.   if (m == DEFLATE) {
  295.      bi_init(y);
  296.      z->att = (ush)UNKNOWN;
  297.      ct_init(&z->att, &m);
  298.      lm_init(level, &z->flg);
  299.      s = deflate();
  300.   }
  301.   else
  302.   {
  303.     if ((b = malloc(CBSZ)) == NULL)
  304.        return ZE_MEM;
  305.  
  306.     if (!isdir) /* no read for directories */
  307.     while ((k = l ? rdsymlnk(z->name, b, CBSZ) : zread(ifile, b, CBSZ)) > 0)
  308.     {
  309.       isize += k;
  310.       crc = updcrc(b, k);
  311.       if (zfwrite(b, 1, k, y) != k)
  312.       {
  313.         free((voidp *)b);
  314.         return ZE_TEMP;
  315.       }
  316. #ifdef MINIX
  317.       if (l)
  318.         q = k;
  319. #endif /* MINIX */
  320.       if (l)
  321.         break;
  322.     }
  323.     free((voidp *)b);
  324.     s = isize;
  325.   }
  326.   if (ifile != fbad && zerr(ifile))
  327.     return ZE_READ;
  328.   if (ifile != fbad)
  329.     zclose(ifile);
  330.  
  331.   tempzn += s;
  332.   p = tempzn; /* save for future fseek() */
  333.  
  334. #ifndef VMS
  335.   /* Check input size (but not in VMS--variable record lengths mess it up) */
  336.   if (q >= 0 && isize != (ulg)q && !translate_eol)
  337.   {
  338.     fprintf(mesg, " i=%ld, q=%ld ", isize, q);
  339.     error("incorrect input size");
  340.   }
  341. #endif /* !VMS */
  342.  
  343.   /* Try to rewrite the local header with correct information */
  344.   z->crc = crc;
  345.   z->siz = s;
  346. #ifdef CRYPT
  347.   if (key != NULL)
  348.     z->siz += 12;
  349. #endif
  350.   z->len = isize;
  351.   if (fseek(y, z->off, SEEK_SET)) {
  352.     if (z->how != (ush) m)
  353.        error("can't rewrite method");
  354.     if (m == STORE && q < 0)
  355.        error("zip -0 not allowed for input/output from/to pipe or device");
  356.     if ((r = putextended(z, y)) != ZE_OK)
  357.       return r;
  358.     tempzn += 16L;
  359.     z->flg = z->lflg; /* if flg modified by inflate */
  360.   } else {
  361.      /* seek ok, ftell() should work, check compressed size */
  362. #ifndef VMS
  363.     if (p - o != s) {
  364.       fprintf(mesg, " s=%ld, actual=%ld ", s, p-o);
  365.       error("incorrect compressed size");
  366.     }
  367. #endif
  368.     z->how = m;
  369.     if ((z->flg & 1) == 0)
  370.       z->flg &= ~8; /* clear the extended local header flag */
  371.     z->lflg = z->flg;
  372.     /* rewrite the local header: */
  373.     if ((r = putlocal(z, y)) != ZE_OK)
  374.       return r;
  375.     if (fseek(y, p, SEEK_SET))
  376.       return ZE_READ;
  377.     if ((z->flg & 1) != 0) {
  378.       /* encrypted file, extended header still required */
  379.       if ((r = putextended(z, y)) != ZE_OK)
  380.         return r;
  381.       tempzn += 16L;
  382.     }
  383.   }
  384.  
  385.   /* Display statistics */
  386.   if (noisy)
  387.   {
  388.     if (verbose)
  389.       fprintf(mesg, " (in=%lu) (out=%lu)", isize, s);
  390.     if (m == DEFLATE)
  391.       fprintf(mesg, " (deflated %d%%)\n", percent(isize, s));
  392.     else
  393.       fprintf(mesg, " (stored 0%%)\n");
  394.     fflush(mesg);
  395.   }
  396.   return ZE_OK;
  397. }
  398.  
  399.  
  400. int file_read(buf, size)
  401.   char *buf;
  402.   unsigned size;
  403. /* Read a new buffer from the current input file, and update the crc and
  404.  * input file size.
  405.  * IN assertion: size >= 2 (for end-of-line translation)
  406.  */
  407. {
  408.   unsigned len;
  409.   char far *b;
  410.   if (translate_eol) {
  411.     size >>= 1;
  412.     b = buf+size;
  413.     size = len = zread(ifile, b, size);
  414.     if (len == (unsigned)EOF || len == 0) return len;
  415.     do {
  416.        if ((*buf++ = *b++) == '\n') *(buf-1) = '\r', *buf++ = '\n', len++;
  417.     } while (--size != 0);
  418.     buf -= len;
  419.   } else {
  420.     len = zread(ifile, buf, size);
  421.     if (len == (unsigned)EOF || len == 0) return len;
  422.   }
  423.   crc = updcrc(buf, len);
  424.   isize += (ulg)len;
  425.   return len;
  426. }
  427. #endif /* !UTIL */
  428.