jdk/src/share/classes/java/util/zip/ZipOutputStream.java
changeset 2438 21c111b51aa8
parent 1228 1515928f48cd
child 2592 ef26f663a2ba
equal deleted inserted replaced
2436:ae4667371301 2438:21c111b51aa8
     1 /*
     1 /*
     2  * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
    27 
    27 
    28 import java.io.OutputStream;
    28 import java.io.OutputStream;
    29 import java.io.IOException;
    29 import java.io.IOException;
    30 import java.util.Vector;
    30 import java.util.Vector;
    31 import java.util.HashSet;
    31 import java.util.HashSet;
       
    32 import static java.util.zip.ZipConstants64.*;
    32 
    33 
    33 /**
    34 /**
    34  * This class implements an output stream filter for writing files in the
    35  * This class implements an output stream filter for writing files in the
    35  * ZIP file format. Includes support for both compressed and uncompressed
    36  * ZIP file format. Includes support for both compressed and uncompressed
    36  * entries.
    37  * entries.
   341      * Writes local file (LOC) header for specified entry.
   342      * Writes local file (LOC) header for specified entry.
   342      */
   343      */
   343     private void writeLOC(XEntry xentry) throws IOException {
   344     private void writeLOC(XEntry xentry) throws IOException {
   344         ZipEntry e = xentry.entry;
   345         ZipEntry e = xentry.entry;
   345         int flag = xentry.flag;
   346         int flag = xentry.flag;
       
   347         int elen = (e.extra != null) ? e.extra.length : 0;
       
   348         boolean hasZip64 = false;
       
   349 
   346         writeInt(LOCSIG);           // LOC header signature
   350         writeInt(LOCSIG);           // LOC header signature
   347         writeShort(version(e));     // version needed to extract
   351 
   348         writeShort(flag);           // general purpose bit flag
       
   349         writeShort(e.method);       // compression method
       
   350         writeInt(e.time);           // last modification time
       
   351         if ((flag & 8) == 8) {
   352         if ((flag & 8) == 8) {
       
   353             writeShort(version(e));     // version needed to extract
       
   354             writeShort(flag);           // general purpose bit flag
       
   355             writeShort(e.method);       // compression method
       
   356             writeInt(e.time);           // last modification time
       
   357 
   352             // store size, uncompressed size, and crc-32 in data descriptor
   358             // store size, uncompressed size, and crc-32 in data descriptor
   353             // immediately following compressed entry data
   359             // immediately following compressed entry data
   354             writeInt(0);
   360             writeInt(0);
   355             writeInt(0);
   361             writeInt(0);
   356             writeInt(0);
   362             writeInt(0);
   357         } else {
   363         } else {
   358             writeInt(e.crc);        // crc-32
   364             if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) {
   359             writeInt(e.csize);      // compressed size
   365                 hasZip64 = true;
   360             writeInt(e.size);       // uncompressed size
   366                 writeShort(45);         // ver 4.5 for zip64
       
   367             } else {
       
   368                 writeShort(version(e)); // version needed to extract
       
   369             }
       
   370             writeShort(flag);           // general purpose bit flag
       
   371             writeShort(e.method);       // compression method
       
   372             writeInt(e.time);           // last modification time
       
   373             writeInt(e.crc);            // crc-32
       
   374             if (hasZip64) {
       
   375                 writeInt(ZIP64_MAGICVAL);
       
   376                 writeInt(ZIP64_MAGICVAL);
       
   377                 elen += 20;        //headid(2) + size(2) + size(8) + csize(8)
       
   378             } else {
       
   379                 writeInt(e.csize);  // compressed size
       
   380                 writeInt(e.size);   // uncompressed size
       
   381             }
   361         }
   382         }
   362         byte[] nameBytes = getUTF8Bytes(e.name);
   383         byte[] nameBytes = getUTF8Bytes(e.name);
   363         writeShort(nameBytes.length);
   384         writeShort(nameBytes.length);
   364         writeShort(e.extra != null ? e.extra.length : 0);
   385         writeShort(elen);
   365         writeBytes(nameBytes, 0, nameBytes.length);
   386         writeBytes(nameBytes, 0, nameBytes.length);
       
   387         if (hasZip64) {
       
   388             writeShort(ZIP64_EXTID);
       
   389             writeShort(16);
       
   390             writeLong(e.size);
       
   391             writeLong(e.csize);
       
   392         }
   366         if (e.extra != null) {
   393         if (e.extra != null) {
   367             writeBytes(e.extra, 0, e.extra.length);
   394             writeBytes(e.extra, 0, e.extra.length);
   368         }
   395         }
   369         locoff = written;
   396         locoff = written;
   370     }
   397     }
   373      * Writes extra data descriptor (EXT) for specified entry.
   400      * Writes extra data descriptor (EXT) for specified entry.
   374      */
   401      */
   375     private void writeEXT(ZipEntry e) throws IOException {
   402     private void writeEXT(ZipEntry e) throws IOException {
   376         writeInt(EXTSIG);           // EXT header signature
   403         writeInt(EXTSIG);           // EXT header signature
   377         writeInt(e.crc);            // crc-32
   404         writeInt(e.crc);            // crc-32
   378         writeInt(e.csize);          // compressed size
   405         if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) {
   379         writeInt(e.size);           // uncompressed size
   406             writeLong(e.csize);
       
   407             writeLong(e.size);
       
   408         } else {
       
   409             writeInt(e.csize);          // compressed size
       
   410             writeInt(e.size);           // uncompressed size
       
   411         }
   380     }
   412     }
   381 
   413 
   382     /*
   414     /*
   383      * Write central directory (CEN) header for specified entry.
   415      * Write central directory (CEN) header for specified entry.
   384      * REMIND: add support for file attributes
   416      * REMIND: add support for file attributes
   385      */
   417      */
   386     private void writeCEN(XEntry xentry) throws IOException {
   418     private void writeCEN(XEntry xentry) throws IOException {
   387         ZipEntry e  = xentry.entry;
   419         ZipEntry e  = xentry.entry;
   388         int flag = xentry.flag;
   420         int flag = xentry.flag;
   389         int version = version(e);
   421         int version = version(e);
       
   422 
       
   423         long csize = e.csize;
       
   424         long size = e.size;
       
   425         long offset = xentry.offset;
       
   426         int e64len = 0;
       
   427         boolean hasZip64 = false;
       
   428         if (e.csize >= ZIP64_MAGICVAL) {
       
   429             csize = ZIP64_MAGICVAL;
       
   430             e64len += 8;              // csize(8)
       
   431             hasZip64 = true;
       
   432         }
       
   433         if (e.size >= ZIP64_MAGICVAL) {
       
   434             size = ZIP64_MAGICVAL;    // size(8)
       
   435             e64len += 8;
       
   436             hasZip64 = true;
       
   437         }
       
   438         if (xentry.offset >= ZIP64_MAGICVAL) {
       
   439             offset = ZIP64_MAGICVAL;
       
   440             e64len += 8;              // offset(8)
       
   441             hasZip64 = true;
       
   442         }
   390         writeInt(CENSIG);           // CEN header signature
   443         writeInt(CENSIG);           // CEN header signature
   391         writeShort(version);        // version made by
   444         if (hasZip64) {
   392         writeShort(version);        // version needed to extract
   445             writeShort(45);         // ver 4.5 for zip64
       
   446             writeShort(45);
       
   447         } else {
       
   448             writeShort(version);    // version made by
       
   449             writeShort(version);    // version needed to extract
       
   450         }
   393         writeShort(flag);           // general purpose bit flag
   451         writeShort(flag);           // general purpose bit flag
   394         writeShort(e.method);       // compression method
   452         writeShort(e.method);       // compression method
   395         writeInt(e.time);           // last modification time
   453         writeInt(e.time);           // last modification time
   396         writeInt(e.crc);            // crc-32
   454         writeInt(e.crc);            // crc-32
   397         writeInt(e.csize);          // compressed size
   455         writeInt(csize);            // compressed size
   398         writeInt(e.size);           // uncompressed size
   456         writeInt(size);             // uncompressed size
   399         byte[] nameBytes = getUTF8Bytes(e.name);
   457         byte[] nameBytes = getUTF8Bytes(e.name);
   400         writeShort(nameBytes.length);
   458         writeShort(nameBytes.length);
   401         writeShort(e.extra != null ? e.extra.length : 0);
   459         if (hasZip64) {
       
   460             // + headid(2) + datasize(2)
       
   461             writeShort(e64len + 4 + (e.extra != null ? e.extra.length : 0));
       
   462         } else {
       
   463             writeShort(e.extra != null ? e.extra.length : 0);
       
   464         }
   402         byte[] commentBytes;
   465         byte[] commentBytes;
   403         if (e.comment != null) {
   466         if (e.comment != null) {
   404             commentBytes = getUTF8Bytes(e.comment);
   467             commentBytes = getUTF8Bytes(e.comment);
   405             writeShort(commentBytes.length);
   468             writeShort(commentBytes.length);
   406         } else {
   469         } else {
   408             writeShort(0);
   471             writeShort(0);
   409         }
   472         }
   410         writeShort(0);              // starting disk number
   473         writeShort(0);              // starting disk number
   411         writeShort(0);              // internal file attributes (unused)
   474         writeShort(0);              // internal file attributes (unused)
   412         writeInt(0);                // external file attributes (unused)
   475         writeInt(0);                // external file attributes (unused)
   413         writeInt(xentry.offset);    // relative offset of local header
   476         writeInt(offset);           // relative offset of local header
   414         writeBytes(nameBytes, 0, nameBytes.length);
   477         writeBytes(nameBytes, 0, nameBytes.length);
       
   478         if (hasZip64) {
       
   479             writeShort(ZIP64_EXTID);// Zip64 extra
       
   480             writeShort(e64len);
       
   481             if (size == ZIP64_MAGICVAL)
       
   482                 writeLong(e.size);
       
   483             if (csize == ZIP64_MAGICVAL)
       
   484                 writeLong(e.csize);
       
   485             if (offset == ZIP64_MAGICVAL)
       
   486                 writeLong(xentry.offset);
       
   487         }
   415         if (e.extra != null) {
   488         if (e.extra != null) {
   416             writeBytes(e.extra, 0, e.extra.length);
   489             writeBytes(e.extra, 0, e.extra.length);
   417         }
   490         }
   418         if (commentBytes != null) {
   491         if (commentBytes != null) {
   419             writeBytes(commentBytes, 0, commentBytes.length);
   492             writeBytes(commentBytes, 0, commentBytes.length);
   422 
   495 
   423     /*
   496     /*
   424      * Writes end of central directory (END) header.
   497      * Writes end of central directory (END) header.
   425      */
   498      */
   426     private void writeEND(long off, long len) throws IOException {
   499     private void writeEND(long off, long len) throws IOException {
       
   500         boolean hasZip64 = false;
       
   501         long xlen = len;
       
   502         long xoff = off;
       
   503         if (xlen >= ZIP64_MAGICVAL) {
       
   504             xlen = ZIP64_MAGICVAL;
       
   505             hasZip64 = true;
       
   506         }
       
   507         if (xoff >= ZIP64_MAGICVAL) {
       
   508             xoff = ZIP64_MAGICVAL;
       
   509             hasZip64 = true;
       
   510         }
   427         int count = xentries.size();
   511         int count = xentries.size();
   428         writeInt(ENDSIG);           // END record signature
   512         if (count >= ZIP64_MAGICCOUNT) {
   429         writeShort(0);              // number of this disk
   513             count = ZIP64_MAGICCOUNT;
   430         writeShort(0);              // central directory start disk
   514             hasZip64 = true;
   431         writeShort(count);          // number of directory entries on disk
   515         }
   432         writeShort(count);          // total number of directory entries
   516         if (hasZip64) {
   433         writeInt(len);              // length of central directory
   517             long off64 = written;
   434         writeInt(off);              // offset of central directory
   518             //zip64 end of central directory record
   435         if (comment != null) {      // zip file comment
   519             writeInt(ZIP64_ENDSIG);        // zip64 END record signature
       
   520             writeLong(ZIP64_ENDHDR - 12);  // size of zip64 end
       
   521             writeShort(45);                // version made by
       
   522             writeShort(45);                // version needed to extract
       
   523             writeInt(0);                   // number of this disk
       
   524             writeInt(0);                   // central directory start disk
       
   525             writeLong(xentries.size());    // number of directory entires on disk
       
   526             writeLong(xentries.size());    // number of directory entires
       
   527             writeLong(len);                // length of central directory
       
   528             writeLong(off);                // offset of central directory
       
   529 
       
   530             //zip64 end of central directory locator
       
   531             writeInt(ZIP64_LOCSIG);        // zip64 END locator signature
       
   532             writeInt(0);                   // zip64 END start disk
       
   533             writeLong(off64);              // offset of zip64 END
       
   534             writeInt(1);                   // total number of disks (?)
       
   535         }
       
   536         writeInt(ENDSIG);                 // END record signature
       
   537         writeShort(0);                    // number of this disk
       
   538         writeShort(0);                    // central directory start disk
       
   539         writeShort(count);                // number of directory entries on disk
       
   540         writeShort(count);                // total number of directory entries
       
   541         writeInt(xlen);                   // length of central directory
       
   542         writeInt(xoff);                   // offset of central directory
       
   543         if (comment != null) {            // zip file comment
   436             byte[] b = getUTF8Bytes(comment);
   544             byte[] b = getUTF8Bytes(comment);
   437             writeShort(b.length);
   545             writeShort(b.length);
   438             writeBytes(b, 0, b.length);
   546             writeBytes(b, 0, b.length);
   439         } else {
   547         } else {
   440             writeShort(0);
   548             writeShort(0);
   459         out.write((int)((v >>>  0) & 0xff));
   567         out.write((int)((v >>>  0) & 0xff));
   460         out.write((int)((v >>>  8) & 0xff));
   568         out.write((int)((v >>>  8) & 0xff));
   461         out.write((int)((v >>> 16) & 0xff));
   569         out.write((int)((v >>> 16) & 0xff));
   462         out.write((int)((v >>> 24) & 0xff));
   570         out.write((int)((v >>> 24) & 0xff));
   463         written += 4;
   571         written += 4;
       
   572     }
       
   573 
       
   574     /*
       
   575      * Writes a 64-bit int to the output stream in little-endian byte order.
       
   576      */
       
   577     private void writeLong(long v) throws IOException {
       
   578         OutputStream out = this.out;
       
   579         out.write((int)((v >>>  0) & 0xff));
       
   580         out.write((int)((v >>>  8) & 0xff));
       
   581         out.write((int)((v >>> 16) & 0xff));
       
   582         out.write((int)((v >>> 24) & 0xff));
       
   583         out.write((int)((v >>> 32) & 0xff));
       
   584         out.write((int)((v >>> 40) & 0xff));
       
   585         out.write((int)((v >>> 48) & 0xff));
       
   586         out.write((int)((v >>> 56) & 0xff));
       
   587         written += 8;
   464     }
   588     }
   465 
   589 
   466     /*
   590     /*
   467      * Writes an array of bytes to the output stream.
   591      * Writes an array of bytes to the output stream.
   468      */
   592      */