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
51inline bool jar::deflate_bytes(bytes& head, bytes& tail) {
52  return false;
53}
54inline 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
61inline 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
78static const ushort jarmagic[2] = { SWAP_BYTES(0xCAFE), 0 };
79
80void 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.
87void 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
100void 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
169void 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
222void 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
240static const char marker_comment[] = ZIP_ARCHIVE_MARKER_COMMENT;
241
242void 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.
341void 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
354void 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
390void 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.
397void 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 */
412inline
413uLong 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
420extern "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 */
427uLong 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*/
456bool 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
529static 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
616void 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
628void 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
675void 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
687void 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
697void gunzip::free() {
698}
699
700#endif // NO_ZLIB
701