home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip22.zip / zipup.c < prev   
C/C++ Source or Header  |  1997-10-26  |  20KB  |  739 lines

  1. /*
  2.  
  3.  Copyright (C) 1990-1997 Mark Adler, Richard B. Wales, Jean-loup Gailly,
  4.  Kai Uwe Rommel, Onno van der Linden 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.  that it is not sold for profit, and that this copyright notice is retained.
  8.  
  9. */
  10.  
  11. /*
  12.  *  zipup.c by Mark Adler and Jean-loup Gailly.
  13.  */
  14.  
  15. #define NOCPYRT         /* this is not a main module */
  16. #include <ctype.h>
  17. #include "zip.h"
  18.  
  19. #ifndef UTIL            /* This module contains no code for Zip Utilities */
  20.  
  21. #include "revision.h"
  22. #include "crypt.h"
  23.  
  24. #ifdef OS2
  25. #  include "os2/os2zip.h"
  26. #endif
  27.  
  28. #if defined(MMAP)
  29. #  include <sys/mman.h>
  30. #  ifndef PAGESIZE   /* used to be SYSV, what about pagesize on SVR3 ? */
  31. #    define PAGESIZE getpagesize()
  32. #  endif
  33. #  if defined(NO_VALLOC) && !defined(valloc)
  34. #    define valloc malloc
  35. #  endif
  36. #endif
  37.  
  38.  
  39. /* Use the raw functions for MSDOS and Unix to save on buffer space.
  40.    They're not used for VMS since it doesn't work (raw is weird on VMS).
  41.    (This sort of stuff belongs in fileio.c, but oh well.) */
  42.  
  43. #ifdef AMIGA
  44. #  include "amiga/zipup.h"
  45. #endif /* AMIGA */
  46.  
  47. #ifdef AOSVS
  48. #  include "aosvs/zipup.h"
  49. #endif /* AOSVS */
  50.  
  51. #ifdef ATARI
  52. #  include "atari/zipup.h"
  53. #endif
  54.  
  55. #ifdef __BEOS__
  56. #  include "beos/zipup.h"
  57. #endif
  58.  
  59. #ifdef __human68k__
  60. #  include "human68k/zipup.h"
  61. #endif /* __human68k__ */
  62.  
  63. #ifdef DOS
  64. #  include "msdos/zipup.h"
  65. #endif /* DOS */
  66.  
  67. #ifdef OS2
  68. #  include "os2/zipup.h"
  69. #endif /* OS2 */
  70.  
  71. #ifdef RISCOS
  72. #  include "acorn/zipup.h"
  73. #endif
  74.  
  75. #ifdef TOPS20
  76. #  include "tops20/zipup.h"
  77. #endif
  78.  
  79. #ifdef UNIX
  80. #  include "unix/zipup.h"
  81. #endif
  82.  
  83. #ifdef CMS_MVS
  84. #  include "zipup.h"
  85. #endif /* CMS_MVS */
  86.  
  87. #ifdef TANDEM
  88. #  include "zipup.h"
  89. #endif /* TANDEM */
  90.  
  91. #ifdef VMS
  92. #  include "vms/zipup.h"
  93. #endif /* VMS */
  94.  
  95. #ifdef QDOS
  96. #  include "qdos/zipup.h"
  97. #endif /* QDOS */
  98.  
  99. #ifdef WIN32
  100. #  include "win32/zipup.h"
  101. #endif
  102.  
  103.  
  104. /* Deflate "internal" global data (currently not in zip.h) */
  105. #if defined(MMAP) || defined(BIG_MEM)
  106.   extern uch * window;          /* Used to read all input file at once */
  107. #endif
  108. extern ulg window_size;         /* size of said window */
  109.  
  110. /* Local data */
  111.  
  112.   local ulg crc;       /* crc on uncompressed file data */
  113.   local ftype ifile;   /* file to compress */
  114. #if defined(MMAP) || defined(BIG_MEM)
  115.   local long remain;
  116.   /* window bytes not yet processed.
  117.    *  >= 0 only for BIG_MEM or MMAP, -1 for normal reads.
  118.    */
  119. #endif /* MMAP || BIG_MEM */
  120. #ifdef DEBUG
  121.   ulg isize;           /* input file size. global only for debugging */
  122. #else /* !DEBUG */
  123.   local ulg isize;     /* input file size. */
  124. #endif /* ?DEBUG */
  125.  
  126. /* Local functions */
  127. #ifndef RISCOS
  128.    local int suffixes OF((char *, char *));
  129. #else
  130.    local int filetypes OF((char *, char *));
  131. #endif
  132.  
  133.  
  134. int percent(n, m)
  135. ulg n;
  136. ulg m;               /* n is the original size, m is the new size */
  137. /* Return the percentage compression from n to m using only integer
  138.    operations */
  139. {
  140.   if (n > 0xffffffL)            /* If n >= 16M */
  141.   {                             /*  then divide n and m by 256 */
  142.     n += 0x80;  n >>= 8;
  143.     m += 0x80;  m >>= 8;
  144.   }
  145.   return n > m ? (int)(1 + (200 * (n - m)/n)) / 2 : 0;
  146. }
  147.  
  148. #ifndef RISCOS
  149.  
  150. local int suffixes(a, s)
  151. char *a;                /* name to check suffix of */
  152. char *s;                /* list of suffixes separated by : or ; */
  153. /* Return true if a ends in any of the suffixes in the list s. */
  154. {
  155.   int m;                /* true if suffix matches so far */
  156.   char *p;              /* pointer into special */
  157.   char *q;              /* pointer into name a */
  158.  
  159. #ifdef QDOS
  160.   short dlen = devlen(a);
  161.   a = a + dlen;
  162. #endif
  163.  
  164.   m = 1;
  165. #ifdef VMS
  166.   if( (q = strrchr(a,';')) != NULL )    /* Cut out VMS file version */
  167.     --q;
  168.   else
  169.     q = a + strlen(a) - 1;
  170. #else /* !VMS */
  171.   q = a + strlen(a) - 1;
  172. #endif /* ?VMS */
  173.   for (p = s + strlen(s) - 1; p >= s; p--)
  174.     if (*p == ':' || *p == ';')
  175.       if (m)
  176.         return 1;
  177.       else
  178.       {
  179.         m = 1;
  180. #ifdef VMS
  181.         if( (q = strrchr(a,';')) != NULL )      /* Cut out VMS file version */
  182.           --q;
  183.         else
  184.           q = a + strlen(a) - 1;
  185. #else /* !VMS */
  186.         q = a + strlen(a) - 1;
  187. #endif /* ?VMS */
  188.       }
  189.     else
  190.     {
  191.       m = m && q >= a && case_map(*p) == case_map(*q);
  192.       q--;
  193.     }
  194.   return m;
  195. }
  196.  
  197. #else /* RISCOS */
  198.  
  199. local int filetypes(a, s)
  200. char *a;                /* extra field of file to check filetype of */
  201. char *s;                /* list of filetypes separated by : or ; */
  202. /* Return true if a is any of the filetypes in the list s. */
  203. {
  204.  char *p;              /* pointer into special */
  205.  char typestr[4];     /* filetype hex string taken from a */
  206.  
  207.  if ((((unsigned*)a)[2] & 0xFFF00000) != 0xFFF00000) {
  208.  /* The file is not filestamped, always try to compress it */
  209.    return 0;
  210.  }
  211.  
  212.  sprintf(typestr,"%.3X",(((unsigned*)a)[2] & 0x000FFF00) >> 8);
  213.  
  214.  for (p=s;p<=s+strlen(s)-3;p+=3) { /* p+=3 to skip 3 hex type */
  215.    while (*p==':' || *p==';')
  216.      p++;
  217.  
  218.    if (typestr[0]==toupper(p[0]) && typestr[1]==toupper(p[1]) && typestr[2]==toupper(p[2]))
  219.      return 1;
  220.  }
  221.  return 0;
  222. }
  223. #endif /* ?RISCOS */
  224.  
  225. /* Note: a zip "entry" includes a local header (which includes the file
  226.    name), an encryption header if encrypting, the compressed data
  227.    and possibly an extended local header. */
  228.  
  229. int zipup(z, y)
  230. struct zlist far *z;    /* zip entry to compress */
  231. FILE *y;                /* output file */
  232. /* Compress the file z->name into the zip entry described by *z and write
  233.    it to the file *y. Encrypt if requested.  Return an error code in the
  234.    ZE_ class.  Also, update tempzn by the number of bytes written. */
  235. {
  236.   iztimes f_utim;       /* UNIX GMT timestamps, filled by filetime() */
  237.   ulg tim;              /* time returned by filetime() */
  238.   ulg a = 0L;           /* attributes returned by filetime() */
  239.   char *b;              /* malloc'ed file buffer */
  240.   extent k = 0;         /* result of zread */
  241.   int l = 0;            /* true if this file is a symbolic link */
  242.   int m;                /* method for this entry */
  243.   ulg o, p;             /* offsets in zip file */
  244.   long q = -3L;         /* size returned by filetime */
  245.   int r;                /* temporary variable */
  246.   ulg s = 0L;           /* size of compressed data */
  247.   int isdir;            /* set for a directory name */
  248.   int set_type = 0;     /* set if file type (ascii/binary) unknown */
  249.  
  250.   z->nam = strlen(z->iname);
  251.   isdir = z->iname[z->nam-1] == '/';
  252.  
  253.   if ((tim = filetime(z->name, &a, &q, &f_utim)) == 0 || q < -2L)
  254.     return ZE_OPEN;
  255.  
  256.   /* q is set to -1 if the input file is a device, -2 for a volume label */
  257.   if (q == -2L) {
  258.      isdir = 1;
  259.      q = 0;
  260.   } else if (isdir != ((a & MSDOS_DIR_ATTR) != 0)) {
  261.      /* don't overwrite a directory with a file and vice-versa */
  262.      return ZE_MISS;
  263.   }
  264.   z->att = (ush)UNKNOWN; /* will be changed later */
  265.   z->atx = 0; /* may be changed by set_extra_field() */
  266.  
  267.   /* Free the old extra fields which are probably obsolete */
  268.   if (z->ext) {
  269.     free((zvoid *)(z->extra));
  270.   }
  271.   if (z->cext && z->extra != z->cextra) {
  272.     free((zvoid *)(z->cextra));
  273.   }
  274.   z->extra = z->cextra = NULL;
  275.   z->ext = z->cext = 0;
  276.  
  277. #if defined(MMAP) || defined(BIG_MEM)
  278.   remain = -1L; /* changed only for MMAP or BIG_MEM */
  279. #endif /* MMAP || BIG_MEM */
  280.   window_size = 0L;
  281.  
  282.   /* Select method based on the suffix and the global method */
  283. #ifndef RISCOS
  284.   m = special != NULL && suffixes(z->name, special) ? STORE : method;
  285. #else /* RISCOS  must set m after setting extra field */
  286.   m = method;
  287. #endif /* ?RISCOS */
  288.  
  289.   /* Open file to zip up unless it is stdin */
  290.   if (strcmp(z->name, "-") == 0)
  291.   {
  292.     ifile = (ftype)zstdin;
  293. #if defined(MSDOS) || defined(__human68k__)
  294.     setmode(zstdin, O_BINARY);
  295. #endif
  296.     z->tim = tim;
  297.   }
  298.   else
  299.   {
  300. #if !(defined(VMS) && defined(VMS_PK_EXTRA))
  301.     if (extra_fields) {
  302.       /* create extra field and change z->att and z->atx if desired */
  303.       set_extra_field(z, &f_utim);
  304. #ifdef QLZIP
  305.       if(qlflag)
  306.           a |= (S_IXUSR) << 16;   /* Cross compilers don't set this */
  307. #endif
  308. #ifdef RISCOS
  309.       m = special != NULL && filetypes(z->extra, special) ? STORE : method;
  310. #endif /* RISCOS */
  311.     }
  312. #endif /* !(VMS && VMS_PK_EXTRA) */
  313.     l = issymlnk(a);
  314.     if (l)
  315.       ifile = fbad;
  316.     else if (isdir) { /* directory */
  317.       ifile = fbad;
  318.       m = STORE;
  319.       q = 0;
  320.     }
  321.     else {
  322. #ifdef CMS_MVS
  323.       if (bflag) {
  324.         if ((ifile = zopen(z->name, fhowb)) == fbad)
  325.            return ZE_OPEN;
  326.       }
  327.       else
  328. #endif /* CMS_MVS */
  329.       if ((ifile = zopen(z->name, fhow)) == fbad)
  330.          return ZE_OPEN;
  331.     }
  332.  
  333.     z->tim = tim;
  334.  
  335. #if defined(VMS) && defined(VMS_PK_EXTRA)
  336.     /* vms_get_attributes must be called after vms_open() */
  337.     if (extra_fields) {
  338.       /* create extra field and change z->att and z->atx if desired */
  339.       vms_get_attributes(ifile, z, &f_utim);
  340.     }
  341. #endif /* VMS && VMS_PK_EXTRA */
  342.  
  343. #ifdef MMAP
  344.     /* Map ordinary files but not devices. This code should go in fileio.c */
  345.     if (q > 0 && !translate_eol) {
  346.       if (window != NULL)
  347.         free(window);  /* window can't be a mapped file here */
  348.       window_size = q + MIN_LOOKAHEAD;
  349.       remain = window_size & (PAGESIZE-1);
  350.       /* If we can't touch the page beyond the end of file, we must
  351.        * allocate an extra page.
  352.        */
  353.       if (remain > MIN_LOOKAHEAD) {
  354.         window = (uch*)mmap(0, window_size, PROT_READ, MAP_PRIVATE, ifile, 0);
  355.       } else {
  356.         window = (uch*)valloc(window_size - remain + PAGESIZE);
  357.         if (window != NULL) {
  358.           window = (uch*)mmap((char*)window, window_size - remain, PROT_READ,
  359.                         MAP_PRIVATE | MAP_FIXED, ifile, 0);
  360.         } else {
  361.           window = (uch*)(-1);
  362.         }
  363.       }
  364.       if (window == (uch*)(-1)) {
  365.         Trace((mesg, " mmap failure on %s\n", z->name));
  366.         window = NULL;
  367.         window_size = 0L;
  368.         remain = -1L;
  369.       } else {
  370.         remain = q;
  371.       }
  372.     }
  373. #else /* !MMAP */
  374. # ifdef BIG_MEM
  375.     /* Read the whole input file at once */
  376.     if (q > 0 && !translate_eol) {
  377.       window_size = q + MIN_LOOKAHEAD;
  378.       window = window ? (uch*) realloc(window, (unsigned)window_size)
  379.                       : (uch*) malloc((unsigned)window_size);
  380.       /* Just use normal code if big malloc or realloc fails: */
  381.       if (window != NULL) {
  382.         remain = zread(ifile, (char*)window, q+1);
  383.         if (remain != q) {
  384.           fprintf(mesg, " q=%ld, remain=%ld ", q, remain);
  385.           error("can't read whole file at once");
  386.         }
  387.       } else {
  388.         window_size = 0L;
  389.       }
  390.     }
  391. # endif /* BIG_MEM */
  392. #endif /* ?MMAP */
  393.  
  394.   } /* strcmp(z->name, "-") == 0 */
  395.  
  396.   if (l || q == 0)
  397.     m = STORE;
  398.   if (m == BEST)
  399.     m = DEFLATE;
  400.  
  401.   /* Do not create STORED files with extended local headers if the
  402.    * input size is not known, because such files could not be extracted.
  403.    * So if the zip file is not seekable and the input file is not
  404.    * on disk, obey the -0 option by forcing deflation with stored block.
  405.    * Note however that using "zip -0" as filter is not very useful...
  406.    * ??? to be done.
  407.    */
  408.  
  409.   /* Fill in header information and write local header to zip file.
  410.    * This header will later be re-written since compressed length and
  411.    * crc are not yet known.
  412.    */
  413.  
  414.   /* (Assume ext, cext, com, and zname already filled in.) */
  415. #if defined(OS2) || defined(WIN32)
  416.   z->vem = z->dosflag ? (dosify ? 20 :  /* Made under MSDOS by PKZIP 2.0 */
  417.                         (0 + Z_MAJORVER * 10 + Z_MINORVER))
  418.          : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER;
  419.   /* For a FAT file system, we cheat and pretend that the file
  420.    * was not made on OS2 but under DOS. unzip is confused otherwise.
  421.    */
  422. #else /* !(OS2 || WIN32) */
  423.   z->vem = dosify ? 20 : OS_CODE + Z_MAJORVER * 10 + Z_MINORVER;
  424. #endif /* ?(OS2 || WIN32) */
  425.  
  426.   z->ver = m == STORE ? 10 : 20;     /* Need PKUNZIP 2.0 except for store */
  427.   z->crc = 0;  /* to be updated later */
  428.   /* Assume first that we will need an extended local header: */
  429.   z->flg = 8;  /* to be updated later */
  430. #if CRYPT
  431.   if (key != NULL) {
  432.     z->flg |= 1;
  433.     /* Since we do not yet know the crc here, we pretend that the crc
  434.      * is the modification time:
  435.      */
  436.     z->crc = z->tim << 16;
  437.   }
  438. #endif /* CRYPT */
  439.   z->lflg = z->flg;
  440.   z->how = m;                             /* may be changed later  */
  441.   z->siz = m == STORE && q >= 0 ? q : 0;  /* will be changed later  */
  442.   z->len = q >= 0 ? q : 0;                /* may be changed later  */
  443.   z->dsk = 0;
  444.   if (z->att == (ush)UNKNOWN) {
  445.       z->att = BINARY;                    /* set sensible value in header */
  446.       set_type = 1;
  447.   }
  448.   /* Attributes from filetime(), flag bits from set_extra_field(): */
  449. #if defined(DOS) || defined(OS2) || defined(WIN32)
  450.   z->atx = z->dosflag ? a & 0xff : a | (z->atx & 0x0000ff00);
  451. #else
  452.   z->atx = dosify ? a & 0xff : a | (z->atx & 0x0000ff00);
  453. #endif /* DOS || OS2 || WIN32 */
  454.   z->off = tempzn;
  455.   if ((r = putlocal(z, y)) != ZE_OK)
  456.     return r;
  457.   tempzn += 4 + LOCHEAD + z->nam + z->ext;
  458.  
  459. #if CRYPT
  460.   if (key != NULL) {
  461.     crypthead(key, z->crc, y);
  462.     z->siz += RAND_HEAD_LEN;  /* to be updated later */
  463.     tempzn += RAND_HEAD_LEN;
  464.   }
  465. #endif /* CRYPT */
  466.   if (ferror(y))
  467.     ZIPERR(ZE_WRITE, "unexpected error on zip file");
  468.  
  469.   o = ftell(y); /* for debugging only, ftell can fail on pipes */
  470.   if (ferror(y))
  471.     clearerr(y);
  472.  
  473.   /* Write stored or deflated file to zip file */
  474.   isize = 0L;
  475.   crc = CRCVAL_INITIAL;
  476.  
  477.   if (m == DEFLATE) {
  478.      bi_init(y);
  479.      if (set_type) z->att = (ush)UNKNOWN; /* will be changed in deflate() */
  480.      ct_init(&z->att, &m);
  481.      lm_init(level, &z->flg);
  482.      s = deflate();
  483.   }
  484.   else if (!isdir)
  485.   {
  486. #ifdef SBSZ
  487.     if ((b = malloc(SBSZ)) == NULL)
  488. #else
  489.     if ((b = malloc(CBSZ)) == NULL)
  490. #endif
  491.        return ZE_MEM;
  492.  
  493.     if (l) {
  494. #ifdef SBSZ
  495.       k = rdsymlnk(z->name, b, SBSZ);
  496. #else
  497.       k = rdsymlnk(z->name, b, CBSZ);
  498. #endif
  499. /*
  500.  * compute crc first because zfwrite will alter the buffer b points to !!
  501.  */
  502.       crc = crc32(crc, (uch *) b, k);
  503.       if (zfwrite(b, 1, k, y) != k)
  504.       {
  505.         free((zvoid *)b);
  506.         return ZE_TEMP;
  507.       }
  508.       isize = k;
  509.  
  510. #ifdef MINIX
  511.       q = k;
  512. #endif /* MINIX */
  513.     }
  514.     else
  515.     {
  516. #ifdef SBSZ
  517.       while ((k = file_read(b, SBSZ)) > 0 && k != (extent) EOF)
  518. #else
  519.       while ((k = file_read(b, CBSZ)) > 0 && k != (extent) EOF)
  520. #endif
  521.       {
  522.         if (zfwrite(b, 1, k, y) != k)
  523.         {
  524.           free((zvoid *)b);
  525.           return ZE_TEMP;
  526.         }
  527. #ifndef WINDLL
  528.         if (verbose) putc('.', stderr);
  529. #else
  530.         if (verbose) fprintf(stdout,"%c",'.');
  531. #endif
  532.       }
  533.     }
  534.     free((zvoid *)b);
  535.     s = isize;
  536.   }
  537.   if (ifile != fbad && zerr(ifile)) {
  538.     perror("\nzip warning");
  539.     zipwarn("could not read input file: ", z->zname);
  540.   }
  541.   if (ifile != fbad)
  542.     zclose(ifile);
  543. #ifdef MMAP
  544.   if (remain >= 0L) {
  545.     munmap((caddr_t) window, window_size);
  546.     window = NULL;
  547.   }
  548. #endif /*MMAP */
  549.  
  550.   tempzn += s;
  551.   p = tempzn; /* save for future fseek() */
  552.  
  553. #if (!defined(MSDOS) || defined(OS2))
  554. #if !defined(VMS) && !defined(CMS_MVS)
  555.   /* Check input size (but not in VMS -- variable record lengths mess it up)
  556.    * and not on MSDOS -- diet in TSR mode reports an incorrect file size)
  557.    */
  558. #ifndef TANDEM /* Tandem EOF does not match byte count unless Unstructured */
  559.   if (q >= 0 && isize != (ulg)q && !translate_eol)
  560.   {
  561.     Trace((mesg, " i=%ld, q=%ld ", isize, q));
  562.     zipwarn(" file size changed while zipping ", z->name);
  563.   }
  564. #endif /* !TANDEM */
  565. #endif /* !VMS && !CMS_MVS */
  566. #endif /* (!MSDOS || OS2) */
  567.  
  568.   /* Try to rewrite the local header with correct information */
  569.   z->crc = crc;
  570.   z->siz = s;
  571. #if CRYPT
  572.   if (key != NULL)
  573.     z->siz += RAND_HEAD_LEN;
  574. #endif /* CRYPT */
  575.   z->len = isize;
  576. #ifdef BROKEN_FSEEK
  577.   if (!fseekable(y) || fseek(y, z->off, SEEK_SET))
  578. #else
  579.   if (fseek(y, z->off, SEEK_SET))
  580. #endif
  581.   {
  582.     if (z->how != (ush) m)
  583.        error("can't rewrite method");
  584.     if (m == STORE && q < 0)
  585.        ZIPERR(ZE_PARMS, "zip -0 not supported for I/O on pipes or devices");
  586.     if ((r = putextended(z, y)) != ZE_OK)
  587.       return r;
  588.     tempzn += 16L;
  589.     z->flg = z->lflg; /* if flg modified by inflate */
  590.   } else {
  591.      /* seek ok, ftell() should work, check compressed size */
  592. #if !defined(VMS) && !defined(CMS_MVS)
  593.     if (p - o != s) {
  594.       fprintf(mesg, " s=%ld, actual=%ld ", s, p-o);
  595.       error("incorrect compressed size");
  596.     }
  597. #endif /* !VMS && !CMS_MVS */
  598.     z->how = m;
  599.     z->ver = m == STORE ? 10 : 20;     /* Need PKUNZIP 2.0 except for store */
  600.     if ((z->flg & 1) == 0)
  601.       z->flg &= ~8; /* clear the extended local header flag */
  602.     z->lflg = z->flg;
  603.     /* rewrite the local header: */
  604.     if ((r = putlocal(z, y)) != ZE_OK)
  605.       return r;
  606.     if (fseek(y, p, SEEK_SET))
  607.       return ZE_READ;
  608.     if ((z->flg & 1) != 0) {
  609.       /* encrypted file, extended header still required */
  610.       if ((r = putextended(z, y)) != ZE_OK)
  611.         return r;
  612.       tempzn += 16L;
  613.     }
  614.   }
  615.   /* Free the local extra field which is no longer needed */
  616.   if (z->ext) {
  617.     if (z->extra != z->cextra) {
  618.       free((zvoid *)(z->extra));
  619.       z->extra = NULL;
  620.     }
  621.     z->ext = 0;
  622.   }
  623.  
  624.   /* Display statistics */
  625.   if (noisy)
  626.   {
  627.     if (verbose)
  628.       fprintf(mesg, "\t(in=%lu) (out=%lu)", isize, s);
  629.     if (m == DEFLATE)
  630.       fprintf(mesg, " (deflated %d%%)\n", percent(isize, s));
  631.     else
  632.       fprintf(mesg, " (stored 0%%)\n");
  633.     fflush(mesg);
  634.   }
  635.   return ZE_OK;
  636. }
  637.  
  638.  
  639. int file_read(buf, size)
  640.   char *buf;
  641.   unsigned size;
  642. /* Read a new buffer from the current input file, perform end-of-line
  643.  * translation, and update the crc and input file size.
  644.  * IN assertion: size >= 2 (for end-of-line translation)
  645.  */
  646. {
  647.   unsigned len;
  648.   char *b;
  649.  
  650. #if defined(MMAP) || defined(BIG_MEM)
  651.   if (remain == 0L) {
  652.     return 0;
  653.   } else if (remain > 0L) {
  654.     /* The window data is already in place. We still compute the crc
  655.      * by 32K blocks instead of once on whole file to keep a certain
  656.      * locality of reference.
  657.      */
  658.     Assert (buf == (char*)window + isize, "are you lost?");
  659.     if (size > remain) size = remain;
  660.     if (size > WSIZE) size = WSIZE; /* don't touch all pages at once */
  661.     remain -= (long) size;
  662.     len = size;
  663.   } else
  664. #endif /* MMAP || BIG_MEM */
  665.   if (translate_eol == 0) {
  666.     len = zread(ifile, buf, size);
  667.     if (len == (unsigned)EOF || len == 0) return (int)len;
  668.   } else if (translate_eol == 1) {
  669.     /* Transform LF to CR LF */
  670.     size >>= 1;
  671.     b = buf+size;
  672.     size = len = zread(ifile, b, size);
  673.     if (len == (unsigned)EOF || len == 0) return (int)len;
  674. #ifdef EBCDIC
  675.     if (aflag == ASCII)
  676.     {
  677.        do {
  678.           char c;
  679.  
  680.           if ((c = *b++) == '\n') {
  681.              *buf++ = CR; *buf++ = LF; len++;
  682.           } else {
  683.             *buf++ = (char)ascii[(uch)c];
  684.           }
  685.        } while (--size != 0);
  686.     }
  687.     else
  688. #endif /* EBCDIC */
  689.     {
  690.        do {
  691.           if ((*buf++ = *b++) == '\n') *(buf-1) = '\r', *buf++ = '\n', len++;
  692.        } while (--size != 0);
  693.     }
  694.     buf -= len;
  695.  
  696.   } else {
  697.     /* Transform CR LF to LF and suppress final ^Z */
  698.     b = buf;
  699.     size = len = zread(ifile, buf, size-1);
  700.     if (len == (unsigned)EOF || len == 0) return (int)len;
  701.     buf[len] = '\n'; /* I should check if next char is really a \n */
  702. #ifdef EBCDIC
  703.     if (aflag == ASCII)
  704.     {
  705.        do {
  706.           char c;
  707.  
  708.           if ((c = *b++) == '\r' && *b == '\n') {
  709.              len--;
  710.           } else {
  711.              *buf++ = (char)(c == '\n' ? LF : ascii[(uch)c]);
  712.           }
  713.        } while (--size != 0);
  714.     }
  715.     else
  716. #endif /* EBCDIC */
  717.     {
  718.        do {
  719.           if (( *buf++ = *b++) == '\r' && *b == '\n') buf--, len--;
  720.        } while (--size != 0);
  721.     }
  722.     if (len == 0) {
  723.        zread(ifile, buf, 1); len = 1; /* keep single \r if EOF */
  724. #ifdef EBCDIC
  725.        if (aflag == ASCII) {
  726.           *buf = (char)(*buf == '\n' ? LF : ascii[(uch)(*buf)]);
  727.        }
  728. #endif
  729.     } else {
  730.        buf -= len;
  731.        if (buf[len-1] == CTRLZ) len--; /* suppress final ^Z */
  732.     }
  733.   }
  734.   crc = crc32(crc, (uch *) buf, len);
  735.   isize += (ulg)len;
  736.   return (int)len;
  737. }
  738. #endif /* !UTIL */
  739.