Fix java.util.zip.ZipFile with OPEN_DELETE.
openJdk java.util.zip.ZipFile with OPEN_DELETE flag
uses unlink to remove the file just after it's opened.
This is causing trouble on /storage partition, we
can read/write unlinked file easily, but lseek seems
to fail with ENOENT.
This change introduces alternative implementation that
doesn't use unlink before closing the file.
Bug: 28901232
Bug: 28950284
Change-Id: I871a84e9a14bc1b4b9d5b0faa207579e27bcfc81
diff --git a/ojluni/src/main/java/java/util/zip/ZipFile.java b/ojluni/src/main/java/java/util/zip/ZipFile.java
index 0535a0e..e6624af 100755
--- a/ojluni/src/main/java/java/util/zip/ZipFile.java
+++ b/ojluni/src/main/java/java/util/zip/ZipFile.java
@@ -68,6 +68,10 @@
private final CloseGuard guard = CloseGuard.get();
+ // Android changed, needed for alternative OPEN_DELETE implementation
+ // that doesn't use unlink before closing the file.
+ private final File fileToRemoveOnClose;
+
private static final int STORED = ZipEntry.STORED;
private static final int DEFLATED = ZipEntry.DEFLATED;
@@ -204,13 +208,10 @@
throw new ZipException("File too short to be a zip file: " + file.length());
}
String name = file.getPath();
- SecurityManager sm = System.getSecurityManager();
- if (sm != null) {
- sm.checkRead(name);
- if ((mode & OPEN_DELETE) != 0) {
- sm.checkDelete(name);
- }
- }
+
+ // Android changed, handle OPEN_DELETE case in #close().
+ fileToRemoveOnClose = ((mode & OPEN_DELETE) != 0) ? file : null;
+
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
@@ -616,6 +617,11 @@
close(zf);
}
+
+ // Android-changed, explicit delete for OPEN_DELETE ZipFile.
+ if (fileToRemoveOnClose != null) {
+ fileToRemoveOnClose.delete();
+ }
}
}
diff --git a/ojluni/src/main/native/java_util_zip_ZipFile.c b/ojluni/src/main/native/java_util_zip_ZipFile.c
index a57e20e..7280d97 100644
--- a/ojluni/src/main/native/java_util_zip_ZipFile.c
+++ b/ojluni/src/main/native/java_util_zip_ZipFile.c
@@ -95,7 +95,8 @@
jzfile *zip = 0;
if (mode & OPEN_READ) flag |= O_RDONLY;
- if (mode & OPEN_DELETE) flag |= JVM_O_DELETE;
+ // Android changed, JVM_O_DELETE/unlink is problematic, see b/28901232.
+ //if (mode & OPEN_DELETE) flag |= JVM_O_DELETE;
if (path != 0) {
zip = ZIP_Get_From_Cache(path, &msg, lastModified);
diff --git a/ojluni/src/main/native/jvm_md.h b/ojluni/src/main/native/jvm_md.h
index 390e89c..a366445 100755
--- a/ojluni/src/main/native/jvm_md.h
+++ b/ojluni/src/main/native/jvm_md.h
@@ -75,6 +75,8 @@
#define JVM_O_O_APPEND O_APPEND
#define JVM_O_EXCL O_EXCL
#define JVM_O_CREAT O_CREAT
+// JVM_O_DELETE use is discouraged (until b/28950284 is fixed),
+// may cause bugs on some filesystems.
#define JVM_O_DELETE 0x10000
/* Signals */