|
@@ -914,6 +914,7 @@ SeekableByteChannel newByteChannel(byte[] path, |
|
|
checkWritable(); |
|
|
beginRead(); // only need a read lock, the "update()" will obtain |
|
|
// the write lock when the channel is closed |
|
|
ensureOpen(); |
|
|
try { |
|
|
Entry e = getEntry(path); |
|
|
if (e != null) { |
|
@@ -1075,7 +1076,7 @@ public long read(ByteBuffer[] dsts, int offset, int length) |
|
|
} |
|
|
public int write(ByteBuffer src, long position) |
|
|
throws IOException |
|
|
{ |
|
|
{ |
|
|
return fch.write(src, position); |
|
|
} |
|
|
public MappedByteBuffer map(MapMode mode, |
|
@@ -1114,10 +1115,6 @@ protected void implCloseChannel() throws IOException { |
|
|
private Set<InputStream> streams = |
|
|
Collections.synchronizedSet(new HashSet<>()); |
|
|
|
|
|
// the ex-channel and ex-path that need to close when their outstanding |
|
|
// input streams are all closed by the obtainers. |
|
|
private final Set<ExistingChannelCloser> exChClosers = new HashSet<>(); |
|
|
|
|
|
private final Set<Path> tmppaths = Collections.synchronizedSet(new HashSet<>()); |
|
|
private Path getTempPathForEntry(byte[] path) throws IOException { |
|
|
Path tmpPath = createTempFileInSameDirectoryAs(zfpath); |
|
@@ -1711,14 +1708,6 @@ private void writeTo(Entry e, OutputStream os) throws IOException { |
|
|
|
|
|
// sync the zip file system, if there is any update |
|
|
private void sync() throws IOException { |
|
|
// check ex-closer |
|
|
if (!exChClosers.isEmpty()) { |
|
|
for (ExistingChannelCloser ecc : exChClosers) { |
|
|
if (ecc.closeAndDeleteIfDone()) { |
|
|
exChClosers.remove(ecc); |
|
|
} |
|
|
} |
|
|
} |
|
|
if (!hasUpdate) |
|
|
return; |
|
|
PosixFileAttributes attrs = getPosixAttributes(zfpath); |
|
@@ -1781,22 +1770,8 @@ private void sync() throws IOException { |
|
|
end.cenlen = written - end.cenoff; |
|
|
end.write(os, written, forceEnd64); |
|
|
} |
|
|
if (!streams.isEmpty()) { |
|
|
// |
|
|
// There are outstanding input streams open on existing "ch", |
|
|
// so, don't close the "cha" and delete the "file for now, let |
|
|
// the "ex-channel-closer" to handle them |
|
|
Path path = createTempFileInSameDirectoryAs(zfpath); |
|
|
ExistingChannelCloser ecc = new ExistingChannelCloser(path, |
|
|
ch, |
|
|
streams); |
|
|
Files.move(zfpath, path, REPLACE_EXISTING); |
|
|
exChClosers.add(ecc); |
|
|
streams = Collections.synchronizedSet(new HashSet<>()); |
|
|
} else { |
|
|
ch.close(); |
|
|
Files.delete(zfpath); |
|
|
} |
|
|
ch.close(); |
|
|
Files.delete(zfpath); |
|
|
|
|
|
// Set the POSIX permissions of the original Zip File if available |
|
|
// before moving the temp file |
|
@@ -3141,36 +3116,6 @@ public GroupPrincipal group() { |
|
|
} |
|
|
} |
|
|
|
|
|
private static class ExistingChannelCloser { |
|
|
private final Path path; |
|
|
private final SeekableByteChannel ch; |
|
|
private final Set<InputStream> streams; |
|
|
ExistingChannelCloser(Path path, |
|
|
SeekableByteChannel ch, |
|
|
Set<InputStream> streams) { |
|
|
this.path = path; |
|
|
this.ch = ch; |
|
|
this.streams = streams; |
|
|
} |
|
|
|
|
|
/** |
|
|
* If there are no more outstanding streams, close the channel and |
|
|
* delete the backing file |
|
|
* |
|
|
* @return true if we're done and closed the backing file, |
|
|
* otherwise false |
|
|
* @throws IOException |
|
|
*/ |
|
|
private boolean closeAndDeleteIfDone() throws IOException { |
|
|
if (streams.isEmpty()) { |
|
|
ch.close(); |
|
|
Files.delete(path); |
|
|
return true; |
|
|
} |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
// purely for parent lookup, so we don't have to copy the parent |
|
|
// name every time |
|
|
static class ParentLookup extends IndexNode { |
|
|