8147588: Jar file and Zip file not removed in spite of the OPEN_DELETE flag
authorsherman
Mon, 23 May 2016 12:53:56 -0700
changeset 38466 4bcf5f2bb351
parent 38465 587c3935e850
child 38467 172e0c9007a6
8147588: Jar file and Zip file not removed in spite of the OPEN_DELETE flag Reviewed-by: alanb
jdk/src/java.base/share/classes/java/io/RandomAccessFile.java
jdk/src/java.base/share/classes/java/util/zip/ZipFile.java
jdk/src/java.base/share/classes/jdk/internal/misc/JavaIORandomAccessFileAccess.java
jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java
jdk/src/java.base/share/native/libjava/RandomAccessFile.c
--- a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java	Mon May 23 12:57:40 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java	Mon May 23 12:53:56 2016 -0700
@@ -27,6 +27,8 @@
 
 import java.nio.channels.FileChannel;
 import java.util.concurrent.atomic.AtomicBoolean;
+import jdk.internal.misc.JavaIORandomAccessFileAccess;
+import jdk.internal.misc.SharedSecrets;
 import sun.nio.ch.FileChannelImpl;
 
 
@@ -75,6 +77,7 @@
     private static final int O_RDWR =   2;
     private static final int O_SYNC =   4;
     private static final int O_DSYNC =  8;
+    private static final int O_TEMPORARY =  16;
 
     /**
      * Creates a random access file stream to read from, and optionally
@@ -203,6 +206,12 @@
     public RandomAccessFile(File file, String mode)
         throws FileNotFoundException
     {
+        this(file, mode, false);
+    }
+
+    private RandomAccessFile(File file, String mode, boolean openAndDelete)
+        throws FileNotFoundException
+    {
         String name = (file != null ? file.getPath() : null);
         int imode = -1;
         if (mode.equals("r"))
@@ -219,6 +228,8 @@
                     imode = -1;
             }
         }
+        if (openAndDelete)
+            imode |= O_TEMPORARY;
         if (imode < 0)
             throw new IllegalArgumentException("Illegal mode \"" + mode
                                                + "\" must be one of "
@@ -1165,5 +1176,15 @@
 
     static {
         initIDs();
+        SharedSecrets.setJavaIORandomAccessFileAccess(new JavaIORandomAccessFileAccess()
+        {
+            // This is for j.u.z.ZipFile.OPEN_DELETE. The O_TEMPORARY flag
+            // is only implemented/supported on windows.
+            public RandomAccessFile openAndDelete(File file, String mode)
+                throws IOException
+            {
+                return new RandomAccessFile(file, mode, true);
+            }
+        });
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java	Mon May 23 12:57:40 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java	Mon May 23 12:53:56 2016 -0700
@@ -54,6 +54,8 @@
 import java.util.stream.StreamSupport;
 import jdk.internal.misc.JavaUtilZipFileAccess;
 import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.JavaIORandomAccessFileAccess;
+import jdk.internal.misc.VM;
 import jdk.internal.perf.PerfCounter;
 
 import static java.util.zip.ZipConstants.*;
@@ -805,19 +807,6 @@
         }
     }
 
-    static {
-        SharedSecrets.setJavaUtilZipFileAccess(
-            new JavaUtilZipFileAccess() {
-                public boolean startsWithLocHeader(ZipFile zip) {
-                    return zip.zsrc.startsWithLoc;
-                }
-                public String[] getMetaInfEntryNames(ZipFile zip) {
-                    return zip.getMetaInfEntryNames();
-                }
-             }
-        );
-    }
-
     /**
      * Returns an array of strings representing the names of all entries
      * that begin with "META-INF/" (case ignored). This method is used
@@ -842,6 +831,21 @@
         }
     }
 
+    private static boolean isWindows;
+    static {
+        SharedSecrets.setJavaUtilZipFileAccess(
+            new JavaUtilZipFileAccess() {
+                public boolean startsWithLocHeader(ZipFile zip) {
+                    return zip.zsrc.startsWithLoc;
+                }
+                public String[] getMetaInfEntryNames(ZipFile zip) {
+                    return zip.getMetaInfEntryNames();
+                }
+             }
+        );
+        isWindows = VM.getSavedProperty("os.name").contains("Windows");
+    }
+
     private static class Source {
         private final Key key;               // the key in files
         private int refs = 1;
@@ -956,9 +960,16 @@
 
         private Source(Key key, boolean toDelete) throws IOException {
             this.key = key;
-            this.zfile = new RandomAccessFile(key.file, "r");
             if (toDelete) {
-                key.file.delete();
+                if (isWindows) {
+                    this.zfile = SharedSecrets.getJavaIORandomAccessFileAccess()
+                                              .openAndDelete(key.file, "r");
+                } else {
+                    this.zfile = new RandomAccessFile(key.file, "r");
+                    key.file.delete();
+                }
+            } else {
+                this.zfile = new RandomAccessFile(key.file, "r");
             }
             try {
                 initCEN(-1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaIORandomAccessFileAccess.java	Mon May 23 12:53:56 2016 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, 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
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.misc;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+public interface JavaIORandomAccessFileAccess {
+    public RandomAccessFile openAndDelete(File file, String mode)
+        throws IOException;
+}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java	Mon May 23 12:57:40 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java	Mon May 23 12:53:56 2016 -0700
@@ -30,6 +30,7 @@
 import java.io.Console;
 import java.io.FileDescriptor;
 import java.io.ObjectInputStream;
+import java.io.RandomAccessFile;
 import java.security.ProtectionDomain;
 import java.security.AccessController;
 
@@ -64,6 +65,7 @@
     private static JavaAWTFontAccess javaAWTFontAccess;
     private static JavaBeansAccess javaBeansAccess;
     private static JavaObjectInputStreamAccess javaObjectInputStreamAccess;
+    private static JavaIORandomAccessFileAccess javaIORandomAccessFileAccess;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
         if (javaUtilJarAccess == null) {
@@ -274,4 +276,15 @@
     public static void setJavaObjectInputStreamAccess(JavaObjectInputStreamAccess access) {
         javaObjectInputStreamAccess = access;
     }
+
+    public static void setJavaIORandomAccessFileAccess(JavaIORandomAccessFileAccess jirafa) {
+        javaIORandomAccessFileAccess = jirafa;
+    }
+
+    public static JavaIORandomAccessFileAccess getJavaIORandomAccessFileAccess() {
+        if (javaIORandomAccessFileAccess == null) {
+            unsafe.ensureClassInitialized(RandomAccessFile.class);
+        }
+        return javaIORandomAccessFileAccess;
+    }
 }
--- a/jdk/src/java.base/share/native/libjava/RandomAccessFile.c	Mon May 23 12:57:40 2016 +0100
+++ b/jdk/src/java.base/share/native/libjava/RandomAccessFile.c	Mon May 23 12:53:56 2016 -0700
@@ -60,6 +60,10 @@
         else if (mode & java_io_RandomAccessFile_O_DSYNC)
             flags |= O_DSYNC;
     }
+#ifdef WIN32
+    if (mode & java_io_RandomAccessFile_O_TEMPORARY)
+        flags |= O_TEMPORARY;
+#endif
     fileOpen(env, this, path, raf_fd, flags);
 }