src/jdk.pack/share/native/common-unpack/zip.cpp
changeset 47216 71c04702a3d5
parent 42693 6645de32a866
child 50514 2a524e603529
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 /**
       
    27  * Note: Lifted from uncrunch.c from jdk sources
       
    28  */
       
    29 #include <stdio.h>
       
    30 #include <string.h>
       
    31 #include <errno.h>
       
    32 #include <time.h>
       
    33 
       
    34 #include <stdlib.h>
       
    35 
       
    36 #ifndef _MSC_VER
       
    37 #include <strings.h>
       
    38 #endif
       
    39 
       
    40 #include "defines.h"
       
    41 #include "bytes.h"
       
    42 #include "utils.h"
       
    43 
       
    44 #include "constants.h"
       
    45 #include "unpack.h"
       
    46 
       
    47 #include "zip.h"
       
    48 
       
    49 #ifdef NO_ZLIB
       
    50 
       
    51 inline bool jar::deflate_bytes(bytes& head, bytes& tail) {
       
    52   return false;
       
    53 }
       
    54 inline uint jar::get_crc32(uint c, uchar *ptr, uint len) { return 0; }
       
    55 #define Z_NULL NULL
       
    56 
       
    57 #else // Have ZLIB
       
    58 
       
    59 #include <zlib.h>
       
    60 
       
    61 inline uint jar::get_crc32(uint c, uchar *ptr, uint len) { return crc32(c, ptr, len); }
       
    62 
       
    63 #endif // End of ZLIB
       
    64 
       
    65 #ifdef _BIG_ENDIAN
       
    66 #define SWAP_BYTES(a) \
       
    67     ((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00)
       
    68 #else
       
    69 #define SWAP_BYTES(a)  (a)
       
    70 #endif
       
    71 
       
    72 #define GET_INT_LO(a) \
       
    73     SWAP_BYTES(a & 0xFFFF)
       
    74 
       
    75 #define GET_INT_HI(a) \
       
    76     SWAP_BYTES((a >> 16) & 0xFFFF)
       
    77 
       
    78 static const ushort jarmagic[2] = { SWAP_BYTES(0xCAFE), 0 };
       
    79 
       
    80 void jar::init(unpacker* u_) {
       
    81   BYTES_OF(*this).clear();
       
    82   u = u_;
       
    83   u->jarout = this;
       
    84 }
       
    85 
       
    86 // Write data to the ZIP output stream.
       
    87 void jar::write_data(void* buff, size_t len) {
       
    88   while (len > 0) {
       
    89     int rc = (int)fwrite(buff, 1, len, jarfp);
       
    90     if (rc <= 0) {
       
    91       fprintf(u->errstrm, "Error: write on output file failed err=%d\n",errno);
       
    92       exit(1); // Called only from the native standalone unpacker
       
    93     }
       
    94     output_file_offset += rc;
       
    95     buff = ((char *)buff) + rc;
       
    96     len -= rc;
       
    97   }
       
    98 }
       
    99 
       
   100 void jar::add_to_jar_directory(const char* fname, bool store, int modtime,
       
   101                                int len, int clen, uLong crc) {
       
   102   uint fname_length = (uint)strlen(fname);
       
   103   ushort header[23];
       
   104   if (modtime == 0)  modtime = default_modtime;
       
   105   uLong dostime = get_dostime(modtime);
       
   106 
       
   107   header[0] = (ushort)SWAP_BYTES(0x4B50);
       
   108   header[1] = (ushort)SWAP_BYTES(0x0201);
       
   109   header[2] = (ushort)SWAP_BYTES(( store ) ? 0x0A : 0x14);
       
   110 
       
   111   // required version
       
   112   header[3] = (ushort)SWAP_BYTES(( store ) ? 0x0A : 0x14);
       
   113 
       
   114   // Flags - UTF-8 compression and separating crc and sizes
       
   115   // into separate headers for deflated file
       
   116   header[4] = ( store ) ? SWAP_BYTES(0x0800) : 0x0808;
       
   117 
       
   118   // Compression method 8=deflate.
       
   119   header[5] = ( store ) ? 0x0 : SWAP_BYTES(0x08);
       
   120 
       
   121   // Last modified date and time.
       
   122   header[6] = (ushort)GET_INT_LO(dostime);
       
   123   header[7] = (ushort)GET_INT_HI(dostime);
       
   124 
       
   125   // CRC
       
   126   header[8] = (ushort)GET_INT_LO(crc);
       
   127   header[9] = (ushort)GET_INT_HI(crc);
       
   128 
       
   129   // Compressed length:
       
   130   header[10] = (ushort)GET_INT_LO(clen);
       
   131   header[11] = (ushort)GET_INT_HI(clen);
       
   132 
       
   133   // Uncompressed length.
       
   134   header[12] = (ushort)GET_INT_LO(len);
       
   135   header[13] = (ushort)GET_INT_HI(len);
       
   136 
       
   137   // Filename length
       
   138   header[14] = (ushort)SWAP_BYTES(fname_length);
       
   139   // So called "extra field" length.
       
   140   // If it's the first record we must add JAR magic sequence
       
   141   header[15] = ( central_directory_count ) ? 0 : (ushort)SWAP_BYTES(4);
       
   142   // So called "comment" length.
       
   143   header[16] = 0;
       
   144   // Disk number start
       
   145   header[17] = 0;
       
   146   // File flags => binary
       
   147   header[18] = 0;
       
   148   // More file flags
       
   149   header[19] = 0;
       
   150   header[20] = 0;
       
   151   // Offset within ZIP file.
       
   152   header[21] = (ushort)GET_INT_LO(output_file_offset);
       
   153   header[22] = (ushort)GET_INT_HI(output_file_offset);
       
   154 
       
   155   // Copy the whole thing into the central directory.
       
   156   central_directory.append(header, sizeof(header));
       
   157 
       
   158   // Copy the fname to the header.
       
   159   central_directory.append(fname, fname_length);
       
   160 
       
   161   // Add jar magic for the first record
       
   162   if (central_directory_count == 0) {
       
   163     central_directory.append((void *)jarmagic, sizeof(jarmagic));
       
   164   }
       
   165 
       
   166   central_directory_count++;
       
   167 }
       
   168 
       
   169 void jar::write_jar_header(const char* fname, bool store, int modtime,
       
   170                            int len, int clen, uint crc) {
       
   171   uint fname_length = (uint)strlen(fname);
       
   172   ushort header[15];
       
   173   if (modtime == 0)  modtime = default_modtime;
       
   174   uLong dostime = get_dostime(modtime);
       
   175 
       
   176   // ZIP LOC magic.
       
   177   header[0] = (ushort)SWAP_BYTES(0x4B50);
       
   178   header[1] = (ushort)SWAP_BYTES(0x0403);
       
   179 
       
   180   // Version
       
   181   header[2] = (ushort)SWAP_BYTES(( store ) ? 0x0A : 0x14);
       
   182 
       
   183   // General purpose flags - same as in the Central Directory
       
   184   header[3] = ( store ) ? SWAP_BYTES(0x0800) : 0x0808;
       
   185 
       
   186   // Compression method = deflate
       
   187   header[4] = ( store ) ? 0x0 : SWAP_BYTES(0x08);
       
   188 
       
   189   // Last modified date and time.
       
   190   header[5] = (ushort)GET_INT_LO(dostime);
       
   191   header[6] = (ushort)GET_INT_HI(dostime);
       
   192 
       
   193   // CRC, 0 if deflated, will come separately in extra header
       
   194   header[7] = ( store ) ? (ushort)GET_INT_LO(crc) : 0;
       
   195   header[8] = ( store ) ? (ushort)GET_INT_HI(crc) : 0;
       
   196 
       
   197   // Compressed length, 0 if deflated
       
   198   header[9] = ( store ) ? (ushort)GET_INT_LO(clen) : 0;
       
   199   header[10] = ( store ) ? (ushort)GET_INT_HI(clen) : 0;
       
   200 
       
   201   // Uncompressed length, 0 if deflated
       
   202   header[11] = ( store ) ? (ushort)GET_INT_LO(len) : 0;
       
   203   header[12] = ( store ) ? (ushort)GET_INT_HI(len) : 0;
       
   204 
       
   205   // Filename length
       
   206   header[13] = (ushort)SWAP_BYTES(fname_length);
       
   207   // So called "extra field" length.
       
   208   header[14] = ( central_directory_count - 1 ) ? 0 : (ushort)SWAP_BYTES(4);
       
   209 
       
   210   // Write the LOC header to the output file.
       
   211   write_data(header, (int)sizeof(header));
       
   212 
       
   213   // Copy the fname to the header.
       
   214   write_data((char*)fname, (int)fname_length);
       
   215 
       
   216   if (central_directory_count == 1) {
       
   217     // Write JAR magic sequence
       
   218     write_data((void *)jarmagic, (int)sizeof(jarmagic));
       
   219   }
       
   220 }
       
   221 
       
   222 void jar::write_jar_extra(int len, int clen, uint crc) {
       
   223   ushort header[8];
       
   224   // Extra field signature
       
   225   header[0] = (ushort)SWAP_BYTES(0x4B50);
       
   226   header[1] = (ushort)SWAP_BYTES(0x0807);
       
   227   // CRC
       
   228   header[2] = (ushort)GET_INT_LO(crc);
       
   229   header[3] = (ushort)GET_INT_HI(crc);
       
   230   // Compressed length
       
   231   header[4] = (ushort)GET_INT_LO(clen);
       
   232   header[5] = (ushort)GET_INT_HI(clen);
       
   233   // Uncompressed length
       
   234   header[6] = (ushort)GET_INT_LO(len);
       
   235   header[7] = (ushort)GET_INT_HI(len);
       
   236 
       
   237   write_data(header, sizeof(header));
       
   238 }
       
   239 
       
   240 static const char marker_comment[] = ZIP_ARCHIVE_MARKER_COMMENT;
       
   241 
       
   242 void jar::write_central_directory() {
       
   243   bytes mc; mc.set(marker_comment);
       
   244 
       
   245   ushort header[11];
       
   246   ushort header64[38];
       
   247 
       
   248   // Create the End of Central Directory structure.
       
   249   header[0] = (ushort)SWAP_BYTES(0x4B50);
       
   250   header[1] = (ushort)SWAP_BYTES(0x0605);
       
   251   // disk numbers
       
   252   header[2] = 0;
       
   253   header[3] = 0;
       
   254   // Number of entries in central directory.
       
   255   header[4] = ( central_directory_count >= 0xffff ) ? 0xffff : (ushort)SWAP_BYTES(central_directory_count);
       
   256   header[5] = ( central_directory_count >= 0xffff ) ? 0xffff : (ushort)SWAP_BYTES(central_directory_count);
       
   257   // Size of the central directory}
       
   258   header[6] = (ushort)GET_INT_LO((int)central_directory.size());
       
   259   header[7] = (ushort)GET_INT_HI((int)central_directory.size());
       
   260   // Offset of central directory within disk.
       
   261   header[8] = (ushort)GET_INT_LO(output_file_offset);
       
   262   header[9] = (ushort)GET_INT_HI(output_file_offset);
       
   263   // zipfile comment length;
       
   264   header[10] = (ushort)SWAP_BYTES((int)mc.len);
       
   265 
       
   266   // Write the central directory.
       
   267   PRINTCR((2, "Central directory at %d\n", output_file_offset));
       
   268   write_data(central_directory.b);
       
   269 
       
   270   // If number of records exceeds the 0xFFFF we need to prepend extended
       
   271   // Zip64 End of Central Directory record and its locator to the old
       
   272   // style ECD record
       
   273   if (central_directory_count > 0xFFFF) {
       
   274     // Zip64 END signature
       
   275     header64[0] = (ushort)SWAP_BYTES(0x4B50);
       
   276     header64[1] = (ushort)0x0606;
       
   277     // Size of header (long)
       
   278     header64[2] = (ushort)SWAP_BYTES(44);;
       
   279     header64[3] = 0;
       
   280     header64[4] = 0;
       
   281     header64[5] = 0;
       
   282     // Version produced and required (short)
       
   283     header64[6] = (ushort)SWAP_BYTES(45);
       
   284     header64[7] = (ushort)SWAP_BYTES(45);
       
   285     // Current disk number (int)
       
   286     header64[8] = 0;
       
   287     header64[9] = 0;
       
   288     // Central directory start disk (int)
       
   289     header64[10] = 0;
       
   290     header64[11] = 0;
       
   291     // Count of records on disk (long)
       
   292     header64[12] = (ushort)GET_INT_LO(central_directory_count);
       
   293     header64[13] = (ushort)GET_INT_HI(central_directory_count);
       
   294     header64[14] = 0;
       
   295     header64[15] = 0;
       
   296     // Count of records totally (long)
       
   297     header64[16] = (ushort)GET_INT_LO(central_directory_count);
       
   298     header64[17] = (ushort)GET_INT_HI(central_directory_count);
       
   299     header64[18] = 0;
       
   300     header64[19] = 0;
       
   301     // Length of the central directory (long)
       
   302     header64[20] = header[6];
       
   303     header64[21] = header[7];
       
   304     header64[22] = 0;
       
   305     header64[23] = 0;
       
   306     // Offset of central directory (long)
       
   307     header64[24] = header[8];
       
   308     header64[25] = header[9];
       
   309     header64[26] = 0;
       
   310     header64[27] = 0;
       
   311     // Zip64 end of central directory locator
       
   312     // Locator signature
       
   313     header64[28] = (ushort)SWAP_BYTES(0x4B50);
       
   314     header64[29] = (ushort)SWAP_BYTES(0x0706);
       
   315     // Start disk number (int)
       
   316     header64[30] = 0;
       
   317     header64[31] = 0;
       
   318     // Offset of zip64 END record (long)
       
   319     header64[32] = (ushort)GET_INT_LO(output_file_offset);
       
   320     header64[33] = (ushort)GET_INT_HI(output_file_offset);
       
   321     header64[34] = 0;
       
   322     header64[35] = 0;
       
   323     // Total number of disks (int)
       
   324     header64[36] = (ushort)SWAP_BYTES(1);
       
   325     header64[37] = 0;
       
   326     write_data(header64, sizeof(header64));
       
   327   }
       
   328 
       
   329   // Write the End of Central Directory structure.
       
   330   PRINTCR((2, "end-of-directory at %d\n", output_file_offset));
       
   331   write_data(header, sizeof(header));
       
   332 
       
   333   PRINTCR((2, "writing zip comment\n"));
       
   334   // Write the comment.
       
   335   write_data(mc);
       
   336 }
       
   337 
       
   338 // Public API
       
   339 
       
   340 // Open a Jar file and initialize.
       
   341 void jar::openJarFile(const char* fname) {
       
   342   if (!jarfp) {
       
   343     PRINTCR((1, "jar::openJarFile: opening %s\n",fname));
       
   344     jarname = fname;
       
   345     jarfp = fopen(fname, "wb");
       
   346     if (!jarfp) {
       
   347       fprintf(u->errstrm, "Error: Could not open jar file: %s\n",fname);
       
   348       exit(3); // Called only from the native standalone unpacker
       
   349     }
       
   350   }
       
   351 }
       
   352 
       
   353 // Add a ZIP entry and copy the file data
       
   354 void jar::addJarEntry(const char* fname,
       
   355                       bool deflate_hint, int modtime,
       
   356                       bytes& head, bytes& tail) {
       
   357   int len = (int)(head.len + tail.len);
       
   358   int clen = 0;
       
   359 
       
   360   uint crc = get_crc32(0,Z_NULL,0);
       
   361   if (head.len != 0)
       
   362     crc = get_crc32(crc, (uchar *)head.ptr, (uint)head.len);
       
   363   if (tail.len != 0)
       
   364     crc = get_crc32(crc, (uchar *)tail.ptr, (uint)tail.len);
       
   365 
       
   366   bool deflate = (deflate_hint && len > 0);
       
   367 
       
   368   if (deflate) {
       
   369     if (deflate_bytes(head, tail) == false) {
       
   370       PRINTCR((2, "Reverting to store fn=%s\t%d -> %d\n",
       
   371               fname, len, deflated.size()));
       
   372       deflate = false;
       
   373     }
       
   374   }
       
   375   clen = (int)((deflate) ? deflated.size() : len);
       
   376   add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
       
   377   write_jar_header(    fname, !deflate, modtime, len, clen, crc);
       
   378 
       
   379   if (deflate) {
       
   380     write_data(deflated.b);
       
   381     // Write deflated information in extra header
       
   382     write_jar_extra(len, clen, crc);
       
   383   } else {
       
   384     write_data(head);
       
   385     write_data(tail);
       
   386   }
       
   387 }
       
   388 
       
   389 // Add a ZIP entry for a directory name no data
       
   390 void jar::addDirectoryToJarFile(const char* dir_name) {
       
   391   bool store = true;
       
   392   add_to_jar_directory((const char*)dir_name, store, default_modtime, 0, 0, 0);
       
   393   write_jar_header(    (const char*)dir_name, store, default_modtime, 0, 0, 0);
       
   394 }
       
   395 
       
   396 // Write out the central directory and close the jar file.
       
   397 void jar::closeJarFile(bool central) {
       
   398   if (jarfp) {
       
   399     fflush(jarfp);
       
   400     if (central) write_central_directory();
       
   401     fflush(jarfp);
       
   402     fclose(jarfp);
       
   403     PRINTCR((2, "jar::closeJarFile:closed jar-file\n"));
       
   404   }
       
   405   reset();
       
   406 }
       
   407 
       
   408 /* Convert the date y/n/d and time h:m:s to a four byte DOS date and
       
   409  *  time (date in high two bytes, time in low two bytes allowing magnitude
       
   410  *  comparison).
       
   411  */
       
   412 inline
       
   413 uLong jar::dostime(int y, int n, int d, int h, int m, int s) {
       
   414   return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0) :
       
   415     (((uLong)y - 1980) << 25) | ((uLong)n << 21) | ((uLong)d << 16) |
       
   416     ((uLong)h << 11) | ((uLong)m << 5) | ((uLong)s >> 1);
       
   417 }
       
   418 
       
   419 #ifdef _REENTRANT // solaris
       
   420 extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
       
   421 #else
       
   422 #define gmtime_r(t, s) gmtime(t)
       
   423 #endif
       
   424 /*
       
   425  * Return the Unix time in DOS format
       
   426  */
       
   427 uLong jar::get_dostime(int modtime) {
       
   428   // see defines.h
       
   429   if (modtime != 0 && modtime == modtime_cache)
       
   430     return dostime_cache;
       
   431   if (modtime != 0 && default_modtime == 0)
       
   432     default_modtime = modtime;  // catch a reasonable default
       
   433   time_t t = modtime;
       
   434   struct tm sbuf;
       
   435   (void)memset((void*)&sbuf,0, sizeof(sbuf));
       
   436   struct tm* s = gmtime_r(&t, &sbuf);
       
   437   if (s == NULL) {
       
   438     fprintf(u->errstrm, "Error: gmtime failure, invalid input archive\n");
       
   439     exit(-1);
       
   440   }
       
   441   modtime_cache = modtime;
       
   442   dostime_cache = dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday,
       
   443                           s->tm_hour, s->tm_min, s->tm_sec);
       
   444   //printf("modtime %d => %d\n", modtime_cache, dostime_cache);
       
   445   return dostime_cache;
       
   446 }
       
   447 
       
   448 
       
   449 
       
   450 #ifndef NO_ZLIB
       
   451 
       
   452 /* Returns true on success, and will set the clen to the compressed
       
   453    length, the caller should verify if true and clen less than the
       
   454    input data
       
   455 */
       
   456 bool jar::deflate_bytes(bytes& head, bytes& tail) {
       
   457   int len = (int)(head.len + tail.len);
       
   458 
       
   459   z_stream zs;
       
   460   BYTES_OF(zs).clear();
       
   461 
       
   462   // NOTE: the window size should always be -MAX_WBITS normally -15.
       
   463   // unzip/zipup.c and java/Deflater.c
       
   464 
       
   465   int error = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
       
   466                            -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
       
   467   if (error != Z_OK) {
       
   468     switch (error) {
       
   469     case Z_MEM_ERROR:
       
   470       PRINTCR((2, "Error: deflate error : Out of memory \n"));
       
   471       break;
       
   472     case Z_STREAM_ERROR:
       
   473       PRINTCR((2,"Error: deflate error : Invalid compression level \n"));
       
   474       break;
       
   475     case Z_VERSION_ERROR:
       
   476       PRINTCR((2,"Error: deflate error : Invalid version\n"));
       
   477       break;
       
   478     default:
       
   479       PRINTCR((2,"Error: Internal deflate error error = %d\n", error));
       
   480     }
       
   481     return false;
       
   482   }
       
   483 
       
   484   deflated.empty();
       
   485   zs.next_out  = (uchar*) deflated.grow(add_size(len, (len/2)));
       
   486   zs.avail_out = (int)deflated.size();
       
   487 
       
   488   zs.next_in = (uchar*)head.ptr;
       
   489   zs.avail_in = (int)head.len;
       
   490 
       
   491   bytes* first = &head;
       
   492   bytes* last  = &tail;
       
   493   if (last->len == 0) {
       
   494     first = null;
       
   495     last = &head;
       
   496   } else if (first->len == 0) {
       
   497     first = null;
       
   498   }
       
   499 
       
   500   if (first != null && error == Z_OK) {
       
   501     zs.next_in = (uchar*) first->ptr;
       
   502     zs.avail_in = (int)first->len;
       
   503     error = deflate(&zs, Z_NO_FLUSH);
       
   504   }
       
   505   if (error == Z_OK) {
       
   506     zs.next_in = (uchar*) last->ptr;
       
   507     zs.avail_in = (int)last->len;
       
   508     error = deflate(&zs, Z_FINISH);
       
   509   }
       
   510   if (error == Z_STREAM_END) {
       
   511     if ((int)zs.total_out > 0) {
       
   512       // Even if compressed size is bigger than uncompressed, write it
       
   513       PRINTCR((2, "deflate compressed data %d -> %d\n", len, zs.total_out));
       
   514       deflated.b.len = zs.total_out;
       
   515       deflateEnd(&zs);
       
   516       return true;
       
   517     }
       
   518     PRINTCR((2, "deflate expanded data %d -> %d\n", len, zs.total_out));
       
   519     deflateEnd(&zs);
       
   520     return false;
       
   521   }
       
   522 
       
   523   deflateEnd(&zs);
       
   524   PRINTCR((2, "Error: deflate error deflate did not finish error=%d\n",error));
       
   525   return false;
       
   526 }
       
   527 
       
   528 // Callback for fetching data from a GZIP input stream
       
   529 static jlong read_input_via_gzip(unpacker* u,
       
   530                                   void* buf, jlong minlen, jlong maxlen) {
       
   531   assert(minlen <= maxlen);  // don't talk nonsense
       
   532   jlong numread = 0;
       
   533   char* bufptr = (char*) buf;
       
   534   char* inbuf = u->gzin->inbuf;
       
   535   size_t inbuflen = sizeof(u->gzin->inbuf);
       
   536   unpacker::read_input_fn_t read_gzin_fn =
       
   537     (unpacker::read_input_fn_t) u->gzin->read_input_fn;
       
   538   z_stream& zs = *(z_stream*) u->gzin->zstream;
       
   539   while (numread < minlen) {
       
   540     int readlen = (1 << 16);  // pretty arbitrary
       
   541     if (readlen > (maxlen - numread))
       
   542       readlen = (int)(maxlen - numread);
       
   543     zs.next_out = (uchar*) bufptr;
       
   544     zs.avail_out = readlen;
       
   545     if (zs.avail_in == 0) {
       
   546       zs.avail_in = (int) read_gzin_fn(u, inbuf, 1, inbuflen);
       
   547       zs.next_in = (uchar*) inbuf;
       
   548     }
       
   549     int error = inflate(&zs, Z_NO_FLUSH);
       
   550     if (error != Z_OK && error != Z_STREAM_END) {
       
   551       u->abort("error inflating input");
       
   552       break;
       
   553     }
       
   554     int nr = readlen - zs.avail_out;
       
   555     u->gzin->gzlen += nr;
       
   556     u->gzin->gzcrc = crc32(u->gzin->gzcrc, (const unsigned char *)bufptr, nr);
       
   557     numread += nr;
       
   558     bufptr += nr;
       
   559     assert(numread <= maxlen);
       
   560     if (error == Z_STREAM_END) {
       
   561       enum { TRAILER_LEN = 8 };
       
   562       // skip 8-byte trailer
       
   563       if (zs.avail_in >= TRAILER_LEN) {
       
   564         zs.avail_in -= TRAILER_LEN;
       
   565       } else {
       
   566         // Bug: 5023768,we read past the TRAILER_LEN to see if there is
       
   567         // any extraneous data, as we don't support concatenated .gz files.
       
   568         int extra = (int) read_gzin_fn(u, inbuf, 1, inbuflen);
       
   569         zs.avail_in += extra - TRAILER_LEN;
       
   570       }
       
   571       // %%% should check for concatenated *.gz files here
       
   572       if (zs.avail_in > 0)
       
   573         u->abort("garbage after end of deflated input stream");
       
   574 
       
   575       // at this point we know there are no trailing bytes,
       
   576       // we are safe to get the crc and len.
       
   577       if (u->gzin->gzcrc != 0) {
       
   578         // Read the CRC information from the gzip container
       
   579         fseek(u->infileptr, -TRAILER_LEN, SEEK_END);
       
   580         uint filecrc;
       
   581         uint filelen;
       
   582         fread(&filecrc, sizeof(filecrc), 1, u->infileptr);
       
   583         fread(&filelen, sizeof(filelen), 1, u->infileptr);
       
   584         filecrc = SWAP_INT(filecrc);
       
   585         filelen = SWAP_INT(filelen);
       
   586         if (u->gzin->gzcrc != filecrc ||
       
   587                 // rfc1952; ISIZE is the input size modulo 2^32
       
   588                 u->gzin->gzlen != (filelen & 0xffffffff)) { // CRC error
       
   589 
       
   590           PRINTCR((1, "crc: 0x%x 0x%x\n", u->gzin->gzcrc,  filecrc));
       
   591           PRINTCR((1, "len: 0x%x 0x%x\n", u->gzin->gzlen,  filelen));
       
   592 
       
   593           if (u->jarout != null) {
       
   594             // save the file name first, if any
       
   595             const char* outfile = u->jarout->jarname;
       
   596             u->jarout->closeJarFile(false);
       
   597             if (outfile != null) {
       
   598               remove(outfile);
       
   599             }
       
   600           }
       
   601           // Print out the error and exit with return code != 0
       
   602           u->abort("CRC error, invalid compressed data.");
       
   603         }
       
   604       }
       
   605       // pop this filter off:
       
   606       u->gzin->free();
       
   607       break;
       
   608     }
       
   609   }
       
   610 
       
   611   //fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
       
   612   //        (int)minlen, (int)maxlen, (int)numread);
       
   613   return numread;
       
   614 }
       
   615 
       
   616 void gunzip::init(unpacker* u_) {
       
   617   BYTES_OF(*this).clear();
       
   618   u = u_;
       
   619   assert(u->gzin == null);  // once only, please
       
   620   read_input_fn = (void*)u->read_input_fn;
       
   621   zstream = NEW(z_stream, 1);
       
   622   u->gzin = this;
       
   623   u->read_input_fn = read_input_via_gzip;
       
   624   u->gzin->gzcrc = crc32(0, Z_NULL, 0);
       
   625   u->gzin->gzlen = 0;
       
   626 }
       
   627 
       
   628 void gunzip::start(int magic) {
       
   629   assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
       
   630   int gz_flg = (magic & 0xFF);  // keep "flg", discard other 3 bytes
       
   631   enum {
       
   632     FHCRC    = (1<<1),
       
   633     FEXTRA   = (1<<2),
       
   634     FNAME    = (1<<3),
       
   635     FCOMMENT = (1<<4)
       
   636   };
       
   637   char gz_mtime[4];
       
   638   char gz_xfl[1];
       
   639   char gz_os[1];
       
   640   char gz_extra_len[2];
       
   641   char gz_hcrc[2];
       
   642   char gz_ignore;
       
   643   // do not save extra, name, comment
       
   644   read_fixed_field(gz_mtime, sizeof(gz_mtime));
       
   645   read_fixed_field(gz_xfl, sizeof(gz_xfl));
       
   646   read_fixed_field(gz_os, sizeof(gz_os));
       
   647   if (gz_flg & FEXTRA) {
       
   648     read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
       
   649     int extra_len = gz_extra_len[0] & 0xFF;
       
   650     extra_len += (gz_extra_len[1] & 0xFF) << 8;
       
   651     for (; extra_len > 0; extra_len--) {
       
   652       read_fixed_field(&gz_ignore, 1);
       
   653     }
       
   654   }
       
   655   int null_terms = 0;
       
   656   if (gz_flg & FNAME)     null_terms++;
       
   657   if (gz_flg & FCOMMENT)  null_terms++;
       
   658   for (; null_terms; null_terms--) {
       
   659     for (;;) {
       
   660       gz_ignore = 0;
       
   661       read_fixed_field(&gz_ignore, 1);
       
   662       if (gz_ignore == 0)  break;
       
   663     }
       
   664   }
       
   665   if (gz_flg & FHCRC)
       
   666     read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
       
   667 
       
   668   if (aborting())  return;
       
   669 
       
   670   // now the input stream is ready to read into the inflater
       
   671   int error = inflateInit2((z_stream*) zstream, -MAX_WBITS);
       
   672   if (error != Z_OK) { abort("cannot create input"); return; }
       
   673 }
       
   674 
       
   675 void gunzip::free() {
       
   676   assert(u->gzin == this);
       
   677   u->gzin = null;
       
   678   u->read_input_fn = (unpacker::read_input_fn_t) this->read_input_fn;
       
   679   inflateEnd((z_stream*) zstream);
       
   680   mtrace('f', zstream, 0);
       
   681   ::free(zstream);
       
   682   zstream = null;
       
   683   mtrace('f', this, 0);
       
   684   ::free(this);
       
   685 }
       
   686 
       
   687 void gunzip::read_fixed_field(char* buf, size_t buflen) {
       
   688   if (aborting())  return;
       
   689   jlong nr = ((unpacker::read_input_fn_t)read_input_fn)
       
   690     (u, buf, buflen, buflen);
       
   691   if ((size_t)nr != buflen)
       
   692     u->abort("short stream header");
       
   693 }
       
   694 
       
   695 #else // NO_ZLIB
       
   696 
       
   697 void gunzip::free() {
       
   698 }
       
   699 
       
   700 #endif // NO_ZLIB