# HG changeset patch # User sherman # Date 1421945505 28800 # Node ID bdb3c1d3a975555ab9d177e8d3cd6528f32bec32 # Parent 44e28eba3922168110230d2085574ce796feb175 8069211: (zipfs) ZipFileSystem creates corrupted zip if entry output stream gets closed more than once Summary: to synchronize the write and close methods of the entry output stream Reviewed-by: alanb diff -r 44e28eba3922 -r bdb3c1d3a975 jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java --- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Thu Jan 22 12:33:05 2015 +0000 +++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Thu Jan 22 08:51:45 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 201, 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 @@ -1533,6 +1533,7 @@ private CRC32 crc; private Entry e; private long written; + private boolean isClosed = false; EntryOutputStream(Entry e, OutputStream os) throws IOException @@ -1545,9 +1546,14 @@ } @Override - public void write(byte b[], int off, int len) throws IOException { + public synchronized void write(byte b[], int off, int len) + throws IOException + { if (e.type != Entry.FILECH) // only from sync ensureOpen(); + if (isClosed) { + throw new IOException("Stream closed"); + } if (off < 0 || len < 0 || off > b.length - len) { throw new IndexOutOfBoundsException(); } else if (len == 0) { @@ -1568,7 +1574,11 @@ } @Override - public void close() throws IOException { + public synchronized void close() throws IOException { + if (isClosed) { + return; + } + isClosed = true; // TBD ensureOpen(); switch (e.method) { case METHOD_DEFLATED: diff -r 44e28eba3922 -r bdb3c1d3a975 jdk/test/jdk/nio/zipfs/ZipFSTester.java --- a/jdk/test/jdk/nio/zipfs/ZipFSTester.java Thu Jan 22 12:33:05 2015 +0000 +++ b/jdk/test/jdk/nio/zipfs/ZipFSTester.java Thu Jan 22 08:51:45 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2015, 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 @@ -45,6 +45,7 @@ import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.spi.FileSystemProvider; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; @@ -67,7 +68,7 @@ * * @test * @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596 - * 7157656 8002390 7012868 7012856 8015728 8038500 8040059 + * 7157656 8002390 7012868 7012856 8015728 8038500 8040059 8069211 * @summary Test Zip filesystem provider * @run main ZipFSTester * @run main/othervm/java.security.policy=test.policy ZipFSTester @@ -89,6 +90,7 @@ test2(fs); // more tests } testTime(jarFile); + test8069211(); } static void test0(FileSystem fs) @@ -416,6 +418,29 @@ Files.delete(fsPath); } + static void test8069211() throws Exception { + // create a new filesystem, copy this file into it + Map env = new HashMap(); + env.put("create", "true"); + Path fsPath = getTempPath(); + try (FileSystem fs = newZipFileSystem(fsPath, env);) { + OutputStream out = Files.newOutputStream(fs.getPath("/foo")); + out.write("hello".getBytes()); + out.close(); + out.close(); + } + try (FileSystem fs = newZipFileSystem(fsPath, new HashMap())) { + if (!Arrays.equals(Files.readAllBytes(fs.getPath("/foo")), + "hello".getBytes())) { + throw new RuntimeException("entry close() failed"); + } + } catch (Exception x) { + throw new RuntimeException("entry close() failed", x); + } finally { + Files.delete(fsPath); + } + } + private static FileSystem newZipFileSystem(Path path, Map env) throws Exception {