Desugared library nio: Support Dos
Bug: b/260383569
Change-Id: Ia37fcdb0ad3229318ab4cf5451fdd12c198d5c58
diff --git a/src/library_desugar/java/j$/nio/file/attribute/DosFileAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/DosFileAttributeView.java
new file mode 100644
index 0000000..899c1e0
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/DosFileAttributeView.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package j$.nio.file.attribute;
+
+public class DosFileAttributeView extends FileAttributeView {}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/DosFileAttributes.java b/src/library_desugar/java/j$/nio/file/attribute/DosFileAttributes.java
new file mode 100644
index 0000000..ae2200c
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/DosFileAttributes.java
@@ -0,0 +1,7 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package j$.nio.file.attribute;
+
+public class DosFileAttributes {}
diff --git a/src/library_desugar/java/java/nio/file/FileApiFlips.java b/src/library_desugar/java/java/nio/file/FileApiFlips.java
index 9c8a46a..24a8d31 100644
--- a/src/library_desugar/java/java/nio/file/FileApiFlips.java
+++ b/src/library_desugar/java/java/nio/file/FileApiFlips.java
@@ -32,6 +32,9 @@
if (attributesClass == java.nio.file.attribute.PosixFileAttributes.class) {
return j$.nio.file.attribute.PosixFileAttributes.class;
}
+ if (attributesClass == java.nio.file.attribute.DosFileAttributes.class) {
+ return j$.nio.file.attribute.DosFileAttributes.class;
+ }
throw exception("java.nio.file.attribute.BasicFileAttributes", attributesClass);
}
@@ -57,6 +60,9 @@
if (attributeView == java.nio.file.attribute.FileOwnerAttributeView.class) {
return j$.nio.file.attribute.FileOwnerAttributeView.class;
}
+ if (attributeView == java.nio.file.attribute.DosFileAttributeView.class) {
+ return j$.nio.file.attribute.DosFileAttributeView.class;
+ }
throw exception("java.nio.file.attribute.FileAttributeView", attributeView);
}
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
index 244aa34..c102e5e 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
@@ -263,9 +263,11 @@
"java.nio.file.attribute.FileStoreAttributeView",
"java.nio.file.attribute.PosixFilePermission",
"java.nio.file.attribute.BasicFileAttributes",
+ "java.nio.file.attribute.DosFileAttributes",
"java.nio.file.attribute.PosixFileAttributes",
"java.nio.file.attribute.FileAttributeView",
"java.nio.file.attribute.FileOwnerAttributeView",
+ "java.nio.file.attribute.DosFileAttributeView",
"java.nio.file.attribute.PosixFileAttributeView",
"java.nio.file.attribute.BasicFileAttributeView"
],
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FilesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FilesTest.java
index 5ae7b6c..5222f94 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FilesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FilesTest.java
@@ -6,6 +6,8 @@
import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
+import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper.DexVm.Version;
@@ -25,12 +27,17 @@
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
+import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.DosFileAttributeView;
+import java.nio.file.attribute.DosFileAttributes;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -45,47 +52,45 @@
@RunWith(Parameterized.class)
public class FilesTest extends DesugaredLibraryTestBase {
- private static final String END_EXPECTED_RESULT =
- StringUtils.lines("tmp", "/", "true", "This", "is", "fun!");
- private static final String EXPECTED_RESULT_DESUGARING_FILE_SYSTEM =
+ private static final String EXPECTED_RESULT_FORMAT =
StringUtils.lines(
- "bytes written: 11",
- "String written: Hello World",
- "bytes read: 11",
- "String read: Hello World",
- "bytes read: 11",
- "String read: Hello World",
- "null",
- "true",
- "unsupported",
- "j$.nio.file.attribute")
- + END_EXPECTED_RESULT;
- private static final String EXPECTED_RESULT_PLATFORM_FILE_SYSTEM_DESUGARING =
- StringUtils.lines(
- "bytes written: 11",
- "String written: Hello World",
- "bytes read: 11",
- "String read: Hello World",
- "bytes read: 11",
- "String read: Hello World",
- "true",
- "true",
- "true",
- "j$.nio.file.attribute")
- + END_EXPECTED_RESULT;
- private static final String EXPECTED_RESULT_PLATFORM_FILE_SYSTEM =
- StringUtils.lines(
- "bytes written: 11",
- "String written: Hello World",
- "bytes read: 11",
- "String read: Hello World",
- "bytes read: 11",
- "String read: Hello World",
- "true",
- "true",
- "true",
- "java.nio.file.attribute")
- + END_EXPECTED_RESULT;
+ "bytes written: 11",
+ "String written: Hello World",
+ "bytes read: 11",
+ "String read: Hello World",
+ "bytes read: 11",
+ "String read: Hello World",
+ "true",
+ "%s",
+ "null",
+ "true",
+ "%s",
+ "unsupported",
+ "tmp",
+ "/",
+ "true",
+ "This",
+ "is",
+ "fun!",
+ "%s",
+ "%s",
+ "%s",
+ "%s");
+ private static final List<String> EXPECTED_RESULT_POSIX =
+ ImmutableList.of(
+ "true",
+ "true",
+ "Succeeded with POSIX RO:false",
+ "Successfully set RO with POSIX",
+ "Succeeded with POSIX RO:true");
+ private static final List<String> EXPECTED_RESULT_DESUGARING_NON_POSIX =
+ ImmutableList.of(
+ "null",
+ "unsupported",
+ "Fail to understand if the file is read-only: class"
+ + " java.lang.UnsupportedOperationException",
+ "Fail to set file as read-only: class java.lang.UnsupportedOperationException",
+ "NotSet");
private final TestParameters parameters;
private final LibraryDesugaringSpecification libraryDesugaringSpecification;
@@ -113,13 +118,21 @@
this.compilationSpecification = compilationSpecification;
}
+ private static String computeExpectedResult(boolean supportPosix, boolean j$nioClasses) {
+ List<String> strings =
+ new ArrayList<>(
+ supportPosix ? EXPECTED_RESULT_POSIX : EXPECTED_RESULT_DESUGARING_NON_POSIX);
+ strings.add(j$nioClasses ? "j$.nio.file.attribute" : "java.nio.file.attribute");
+ return String.format(EXPECTED_RESULT_FORMAT, strings.toArray());
+ }
+
private String getExpectedResult() {
if (libraryDesugaringSpecification.usesPlatformFileSystem(parameters)) {
return libraryDesugaringSpecification.hasNioFileDesugaring(parameters)
- ? EXPECTED_RESULT_PLATFORM_FILE_SYSTEM_DESUGARING
- : EXPECTED_RESULT_PLATFORM_FILE_SYSTEM;
+ ? computeExpectedResult(true, true)
+ : computeExpectedResult(true, false);
}
- return EXPECTED_RESULT_DESUGARING_FILE_SYSTEM;
+ return computeExpectedResult(false, true);
}
@Test
@@ -141,9 +154,78 @@
readThroughFileChannelAPI(path);
attributeAccess(path);
Files.setAttribute(path, "basic:lastModifiedTime", FileTime.from(Instant.EPOCH));
- fspMethodsWithGeneric(path);
pathGeneric();
lines(path);
+ readOnlyTest(path);
+ fspMethodsWithGeneric(path);
+ }
+
+ private static void readOnlyTest(Path path) {
+ isReadOnly(path);
+ if (setReadOnly(path)) {
+ isReadOnly(path);
+ } else {
+ System.out.println("NotSet");
+ }
+ }
+
+ private static boolean isReadOnly(Path path) {
+ try {
+ // DOS attempt.
+ try {
+ DosFileAttributeView dosFileAttributeView =
+ Files.getFileAttributeView(path, DosFileAttributeView.class);
+ if (dosFileAttributeView != null && dosFileAttributeView.readAttributes() != null) {
+ boolean readOnly = dosFileAttributeView.readAttributes().isReadOnly();
+ System.out.println("Succeeded with DOS RO:" + readOnly);
+ return readOnly;
+ }
+ } catch (IOException ignored) {
+ }
+ // Posix attempt.
+ Set<PosixFilePermission> posixFilePermissions = Files.getPosixFilePermissions(path);
+ boolean readOnly =
+ posixFilePermissions.contains(OWNER_READ)
+ && !posixFilePermissions.contains(OWNER_WRITE);
+ System.out.println("Succeeded with POSIX RO:" + readOnly);
+ return readOnly;
+
+ } catch (Throwable t) {
+ System.out.println("Fail to understand if the file is read-only: " + t.getClass());
+ return false;
+ }
+ }
+
+ /** Common pattern to set a file as read-only: Try on Dos, on failure, retry on Posix. */
+ private static boolean setReadOnly(Path path) {
+ try {
+
+ // DOS attempt.
+ try {
+ DosFileAttributeView dosFileAttributeView =
+ Files.getFileAttributeView(path, DosFileAttributeView.class);
+ if (dosFileAttributeView != null) {
+ dosFileAttributeView.setReadOnly(true);
+ System.out.println("Successfully set RO with DOS");
+ return true;
+ }
+ } catch (IOException ignored) {
+ }
+
+ // Posix attempt.
+ Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(path);
+ List<PosixFilePermission> readPermissions = Arrays.asList(OWNER_READ);
+ List<PosixFilePermission> writePermissions = Arrays.asList(PosixFilePermission.OWNER_WRITE);
+ permissions.addAll(readPermissions);
+ permissions.removeAll(writePermissions);
+ Files.setPosixFilePermissions(path, permissions);
+ System.out.println("Successfully set RO with POSIX");
+ return true;
+
+ } catch (Throwable t) {
+ System.out.println("Fail to set file as read-only: " + t.getClass());
+ return false;
+ }
}
private static void pathGeneric() throws IOException {
@@ -163,14 +245,33 @@
}
private static void attributeAccess(Path path) throws IOException {
- PosixFileAttributeView view = Files.getFileAttributeView(path, PosixFileAttributeView.class);
- if (view != null) {
- System.out.println(
- view.readAttributes().permissions().contains(PosixFilePermission.OWNER_READ));
+ BasicFileAttributeView basicView =
+ Files.getFileAttributeView(path, BasicFileAttributeView.class);
+ if (basicView != null) {
+ System.out.println(basicView.readAttributes().isRegularFile());
} else {
System.out.println("null");
}
+ PosixFileAttributeView posixView =
+ Files.getFileAttributeView(path, PosixFileAttributeView.class);
+ if (posixView != null) {
+ System.out.println(posixView.readAttributes().permissions().contains(OWNER_READ));
+ } else {
+ System.out.println("null");
+ }
+
+ try {
+ DosFileAttributeView dosView = Files.getFileAttributeView(path, DosFileAttributeView.class);
+ if (dosView != null) {
+ System.out.println(dosView.readAttributes().isReadOnly());
+ } else {
+ System.out.println("null");
+ }
+ } catch (UnsupportedOperationException e) {
+ System.out.println("unsupported");
+ }
+
BasicFileAttributes attributes = Files.readAttributes(path, BasicFileAttributes.class);
if (attributes != null) {
System.out.println(attributes.isRegularFile());
@@ -181,8 +282,18 @@
try {
PosixFileAttributes posixAttributes = Files.readAttributes(path, PosixFileAttributes.class);
if (posixAttributes != null) {
- System.out.println(
- posixAttributes.permissions().contains(PosixFilePermission.OWNER_READ));
+ System.out.println(posixAttributes.permissions().contains(OWNER_READ));
+ } else {
+ System.out.println("null");
+ }
+ } catch (UnsupportedOperationException e) {
+ System.out.println("unsupported");
+ }
+
+ try {
+ DosFileAttributes dosFileAttributes = Files.readAttributes(path, DosFileAttributes.class);
+ if (dosFileAttributes != null) {
+ System.out.println(dosFileAttributes.isReadOnly());
} else {
System.out.println("null");
}