--- old/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java 2015-05-26 12:15:28.000000000 -0700 +++ new/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java 2015-05-26 12:15:27.000000000 -0700 @@ -503,6 +503,7 @@ boolean hasCreateNew = false; boolean hasCreate = false; boolean hasAppend = false; + boolean hasTruncate = false; for (OpenOption opt: options) { if (opt == READ) throw new IllegalArgumentException("READ not allowed"); @@ -512,7 +513,11 @@ hasCreate = true; if (opt == APPEND) hasAppend = true; + if (opt == TRUNCATE_EXISTING) + hasTruncate = true; } + if (hasAppend && hasTruncate) + throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); beginRead(); // only need a readlock, the "update()" will try { // try to obtain a writelock when the os is ensureOpen(); // being closed. @@ -564,6 +569,8 @@ if (!(option instanceof StandardOpenOption)) throw new IllegalArgumentException(); } + if (options.contains(APPEND) && options.contains(TRUNCATE_EXISTING)) + throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); } // Returns a Writable/ReadByteChannel for now. Might consdier to use @@ -711,15 +718,19 @@ if (forWrite) { checkWritable(); if (e == null) { - if (!options.contains(StandardOpenOption.CREATE_NEW)) - throw new NoSuchFileException(getString(path)); + if (!options.contains(StandardOpenOption.CREATE) && + !options.contains(StandardOpenOption.CREATE_NEW)) { + throw new NoSuchFileException(getString(path)); + } } else { - if (options.contains(StandardOpenOption.CREATE_NEW)) + if (options.contains(StandardOpenOption.CREATE_NEW)) { throw new FileAlreadyExistsException(getString(path)); + } if (e.isDir()) throw new FileAlreadyExistsException("directory <" + getString(path) + "> exists"); } + options = new HashSet<>(options); options.remove(StandardOpenOption.CREATE_NEW); // for tmpfile } else if (e == null || e.isDir()) { throw new NoSuchFileException(getString(path)); --- old/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java 2015-05-26 12:15:29.000000000 -0700 +++ new/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java 2015-05-26 12:15:29.000000000 -0700 @@ -773,7 +773,7 @@ { if (options.length == 0) return zfs.newOutputStream(getResolvedPath(), - CREATE_NEW, WRITE); + CREATE, TRUNCATE_EXISTING, WRITE); return zfs.newOutputStream(getResolvedPath(), options); } --- old/test/jdk/nio/zipfs/ZFSTests.java 2015-05-26 12:15:31.000000000 -0700 +++ new/test/jdk/nio/zipfs/ZFSTests.java 2015-05-26 12:15:30.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 7156873 8040059 + * @bug 7156873 8040059 8028480 8034773 * @summary ZipFileSystem regression tests * * @run main ZFSTests @@ -30,15 +30,19 @@ */ +import java.io.OutputStream; import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.channels.*; import java.nio.file.*; -import java.util.Map; -import java.util.HashMap; +import java.nio.file.spi.*; +import java.util.*; public class ZFSTests { public static void main(String[] args) throws Throwable { test7156873(); + testOpenOptions(); } static void test7156873() throws Throwable { @@ -56,4 +60,44 @@ Files.deleteIfExists(dir); } } + + static void testOpenOptions() throws Throwable { + Path path = Paths.get("file.zip"); + try { + URI uri = URI.create("jar:" + path.toUri()); + Map env = new HashMap(); + env.put("create", "true"); + try (FileSystem fs = FileSystems.newFileSystem(uri, env)) { + FileSystemProvider fsp = fs.provider(); + Set options; + Path p = fs.getPath("test.txt"); + // 8028480 + options = EnumSet.of(StandardOpenOption.CREATE, + StandardOpenOption.WRITE, + StandardOpenOption.APPEND); + try (FileChannel ch = fsp.newFileChannel(p, options)) { + ch.write(ByteBuffer.wrap("Hello!".getBytes("ASCII"))); + } + // 8034773 + try (OutputStream os = fsp.newOutputStream(p, new OpenOption[0])) { + os.write("Hello2!".getBytes("ASCII")); + } + if (!"Hello2!".equals(new String( + Files.readAllBytes(fs.getPath("test.txt"))))) { + throw new RuntimeException("failed to open as truncate_existing"); + } + + options = EnumSet.of(StandardOpenOption.CREATE, + StandardOpenOption.APPEND, + StandardOpenOption.TRUNCATE_EXISTING); + try (FileChannel ch = fsp.newFileChannel(p, options)) { + throw new RuntimeException("expected IAE not thrown!"); + } catch (IllegalArgumentException x) { + // expected x.printStackTrace(); + } + } + } finally { + Files.deleteIfExists(path); + } + } }