< prev index next >
src/java.base/share/classes/java/util/zip/ZipOutputStream.java
Print this page
rev 51866 : 6194856: Zip Files lose ALL ownership and permissions of the files
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -23,18 +23,20 @@
* questions.
*/
package java.util.zip;
-import java.io.OutputStream;
+import static java.util.zip.ZipConstants64.*;
+import static java.util.zip.ZipUtils.*;
+
import java.io.IOException;
+import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
-import java.util.Vector;
import java.util.HashSet;
-import static java.util.zip.ZipConstants64.*;
-import static java.util.zip.ZipUtils.*;
+import java.util.Vector;
+
import sun.security.action.GetPropertyAction;
/**
* This class implements an output stream filter for writing files in the
* ZIP file format. Includes support for both compressed and uncompressed
@@ -65,10 +67,12 @@
this.entry = entry;
this.offset = offset;
}
}
+ private static int VERSION_BASE_UNIX = ZipFile.FILE_ATTRIBUTES_UNIX << 8;
+
private XEntry current;
private Vector<XEntry> xentries = new Vector<>();
private HashSet<String> names = new HashSet<>();
private CRC32 crc = new CRC32();
private long written = 0;
@@ -79,19 +83,33 @@
private boolean closed = false;
private final ZipCoder zc;
- private static int version(ZipEntry e) throws ZipException {
+ private static int version(ZipEntry e, boolean zip64)
+ throws ZipException
+ {
+ if (zip64) {
+ return 45;
+ }
switch (e.method) {
case DEFLATED: return 20;
case STORED: return 10;
default: throw new ZipException("unsupported compression method");
}
}
/**
+ * Adds information about compatibility of file attribute information
+ * to a version value.
+ */
+ private static int versionMadeBy(ZipEntry e, int version) {
+ return (e.posixPerms < 0) ? version :
+ VERSION_BASE_UNIX | (version & 0xff);
+ }
+
+ /**
* Checks to make sure that this stream has not been closed.
*/
private void ensureOpen() throws IOException {
if (closed) {
throw new IOException("Stream closed");
@@ -384,36 +402,34 @@
* Writes local file (LOC) header for specified entry.
*/
private void writeLOC(XEntry xentry) throws IOException {
ZipEntry e = xentry.entry;
int flag = e.flag;
- boolean hasZip64 = false;
+ boolean zip64 = false;
int elen = getExtraLen(e.extra);
writeInt(LOCSIG); // LOC header signature
if ((flag & 8) == 8) {
- writeShort(version(e)); // version needed to extract
+ writeShort(version(e, zip64)); // version needed to extract
writeShort(flag); // general purpose bit flag
writeShort(e.method); // compression method
writeInt(e.xdostime); // last modification time
// store size, uncompressed size, and crc-32 in data descriptor
// immediately following compressed entry data
writeInt(0);
writeInt(0);
writeInt(0);
} else {
if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) {
- hasZip64 = true;
- writeShort(45); // ver 4.5 for zip64
- } else {
- writeShort(version(e)); // version needed to extract
+ zip64 = true;
}
+ writeShort(version(e, zip64)); // version needed to extract
writeShort(flag); // general purpose bit flag
writeShort(e.method); // compression method
writeInt(e.xdostime); // last modification time
writeInt(e.crc); // crc-32
- if (hasZip64) {
+ if (zip64) {
writeInt(ZIP64_MAGICVAL);
writeInt(ZIP64_MAGICVAL);
elen += 20; //headid(2) + size(2) + size(8) + csize(8)
} else {
writeInt(e.csize); // compressed size
@@ -453,11 +469,11 @@
elen += (elenEXTT + 5); // headid(2) + size(2) + flag(1) + data
}
}
writeShort(elen);
writeBytes(nameBytes, 0, nameBytes.length);
- if (hasZip64) {
+ if (zip64) {
writeShort(ZIP64_EXTID);
writeShort(16);
writeLong(e.size);
writeLong(e.csize);
}
@@ -510,54 +526,49 @@
/*
* Write central directory (CEN) header for specified entry.
* REMIND: add support for file attributes
*/
private void writeCEN(XEntry xentry) throws IOException {
- ZipEntry e = xentry.entry;
+ ZipEntry e = xentry.entry;
int flag = e.flag;
- int version = version(e);
long csize = e.csize;
long size = e.size;
long offset = xentry.offset;
int elenZIP64 = 0;
- boolean hasZip64 = false;
-
+ boolean zip64 = false;
if (e.csize >= ZIP64_MAGICVAL) {
csize = ZIP64_MAGICVAL;
- elenZIP64 += 8; // csize(8)
- hasZip64 = true;
+ elenZIP64 += 8; // csize(8)
+ zip64 = true;
}
if (e.size >= ZIP64_MAGICVAL) {
size = ZIP64_MAGICVAL; // size(8)
elenZIP64 += 8;
- hasZip64 = true;
+ zip64 = true;
}
if (xentry.offset >= ZIP64_MAGICVAL) {
offset = ZIP64_MAGICVAL;
- elenZIP64 += 8; // offset(8)
- hasZip64 = true;
+ elenZIP64 += 8; // offset(8)
+ zip64 = true;
}
+ int version = version(e, zip64);
+
writeInt(CENSIG); // CEN header signature
- if (hasZip64) {
- writeShort(45); // ver 4.5 for zip64
- writeShort(45);
- } else {
- writeShort(version); // version made by
- writeShort(version); // version needed to extract
- }
+ writeShort(versionMadeBy(e, version)); // version made by
+ writeShort(version); // version needed to extract
writeShort(flag); // general purpose bit flag
writeShort(e.method); // compression method
writeInt(e.xdostime); // last modification time
writeInt(e.crc); // crc-32
writeInt(csize); // compressed size
writeInt(size); // uncompressed size
byte[] nameBytes = zc.getBytes(e.name);
writeShort(nameBytes.length);
int elen = getExtraLen(e.extra);
- if (hasZip64) {
- elen += (elenZIP64 + 4);// + headid(2) + datasize(2)
+ if (zip64) {
+ elen += (elenZIP64 + 4); // + headid(2) + datasize(2)
}
// cen info-zip extended timestamp only outputs mtime
// but set the flag for a/ctime, if present in loc
int flagEXTT = 0;
long umtime = -1;
@@ -596,16 +607,18 @@
commentBytes = null;
writeShort(0);
}
writeShort(0); // starting disk number
writeShort(0); // internal file attributes (unused)
- writeInt(0); // external file attributes (unused)
+ writeInt(e.posixPerms > 0 ? e.posixPerms << 16 : 0); // external file
+ // attributes, used for storing posix
+ // permissions
writeInt(offset); // relative offset of local header
writeBytes(nameBytes, 0, nameBytes.length);
// take care of EXTID_ZIP64 and EXTID_EXTT
- if (hasZip64) {
+ if (zip64) {
writeShort(ZIP64_EXTID);// Zip64 extra
writeShort(elenZIP64);
if (size == ZIP64_MAGICVAL)
writeLong(e.size);
if (csize == ZIP64_MAGICVAL)
@@ -648,29 +661,29 @@
/*
* Writes end of central directory (END) header.
*/
private void writeEND(long off, long len) throws IOException {
- boolean hasZip64 = false;
+ boolean zip64 = false;
long xlen = len;
long xoff = off;
if (xlen >= ZIP64_MAGICVAL) {
xlen = ZIP64_MAGICVAL;
- hasZip64 = true;
+ zip64 = true;
}
if (xoff >= ZIP64_MAGICVAL) {
xoff = ZIP64_MAGICVAL;
- hasZip64 = true;
+ zip64 = true;
}
int count = xentries.size();
if (count >= ZIP64_MAGICCOUNT) {
- hasZip64 |= !inhibitZip64;
- if (hasZip64) {
+ zip64 |= !inhibitZip64;
+ if (zip64) {
count = ZIP64_MAGICCOUNT;
}
}
- if (hasZip64) {
+ if (zip64) {
long off64 = written;
//zip64 end of central directory record
writeInt(ZIP64_ENDSIG); // zip64 END record signature
writeLong(ZIP64_ENDHDR - 12); // size of zip64 end
writeShort(45); // version made by
< prev index next >