diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 444a22bc0a4..82ab732aec4 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -80,6 +80,7 @@ import java.util.stream.StreamSupport; import jdk.internal.util.ArraysSupport; import sun.nio.ch.FileChannelImpl; import sun.nio.cs.UTF_8; +import sun.nio.fs.AbstractFileSystemProvider; /** * This class consists exclusively of static methods that operate on files, @@ -2609,7 +2610,11 @@ public final class Files { * is invoked to check read access to the file. */ public static boolean isReadable(Path path) { - return isAccessible(path, AccessMode.READ); + FileSystemProvider provider = provider(path); + if (provider instanceof AbstractFileSystemProvider afsp) + return afsp.isReadable(path); + else + return isAccessible(path, AccessMode.READ); } /** @@ -2640,7 +2645,11 @@ public final class Files { * is invoked to check write access to the file. */ public static boolean isWritable(Path path) { - return isAccessible(path, AccessMode.WRITE); + FileSystemProvider provider = provider(path); + if (provider instanceof AbstractFileSystemProvider afsp) + return afsp.isWritable(path); + else + return isAccessible(path, AccessMode.WRITE); } /** @@ -2675,7 +2684,11 @@ public final class Files { * checkExec} is invoked to check execute access to the file. */ public static boolean isExecutable(Path path) { - return isAccessible(path, AccessMode.EXECUTE); + FileSystemProvider provider = provider(path); + if (provider instanceof AbstractFileSystemProvider afsp) + return afsp.isExecutable(path); + else + return isAccessible(path, AccessMode.EXECUTE); } // -- Recursive operations -- diff --git a/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java b/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java index be521c574e0..a584fd0d97a 100644 --- a/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java +++ b/src/java.base/share/classes/sun/nio/fs/AbstractFileSystemProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023, 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 @@ -25,8 +25,9 @@ package sun.nio.fs; -import java.nio.file.Path; +import java.nio.file.AccessMode; import java.nio.file.LinkOption; +import java.nio.file.Path; import java.nio.file.spi.FileSystemProvider; import java.io.IOException; import java.util.Map; @@ -115,4 +116,40 @@ public abstract class AbstractFileSystemProvider extends FileSystemProvider { * If path is empty, then an empty byte[] is returned. */ public abstract byte[] getSunPathForSocketFile(Path path); + + /** + * Tests whether a file is readable. + */ + public boolean isReadable(Path path) { + try { + checkAccess(path, AccessMode.READ); + } catch (IOException e) { + return false; + } + return true; + } + + /** + * Tests whether a file is writable. + */ + public boolean isWritable(Path path) { + try { + checkAccess(path, AccessMode.WRITE); + } catch (IOException e) { + return false; + } + return true; + } + + /** + * Tests whether a file is executable. + */ + public boolean isExecutable(Path path) { + try { + checkAccess(path, AccessMode.EXECUTE); + } catch (IOException e) { + return false; + } + return true; + } } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java index 0e488e14a7a..5a7b5d8591a 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystem.java @@ -893,7 +893,9 @@ abstract class UnixFileSystem sourceAttrs = UnixFileAttributes.get(source, false); if (sourceAttrs.isDirectory()) { // ensure source can be moved - access(source, W_OK); + int errno = access(source, W_OK); + if (errno != 0) + new UnixException(errno).rethrowAsIOException(source); } } catch (UnixException x) { x.rethrowAsIOException(source); @@ -1024,13 +1026,11 @@ abstract class UnixFileSystem // ensure source can be copied if (!sourceAttrs.isSymbolicLink() || flags.followLinks) { - try { - // the access(2) system call always follows links so it - // is suppressed if the source is an unfollowed link - access(source, R_OK); - } catch (UnixException exc) { - exc.rethrowAsIOException(source); - } + // the access(2) system call always follows links so it + // is suppressed if the source is an unfollowed link + int errno = access(source, R_OK); + if (errno != 0) + new UnixException(errno).rethrowAsIOException(source); } // get attributes of target file (don't follow links) diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java index ddb649a63c1..7f80bc49a50 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java @@ -349,11 +349,35 @@ public abstract class UnixFileSystemProvider } mode |= X_OK; } - try { - access(file, mode); - } catch (UnixException exc) { - exc.rethrowAsIOException(file); + int errno = access(file, mode); + if (errno != 0) + new UnixException(errno).rethrowAsIOException(file); + } + + @Override + public boolean isReadable(Path path) { + UnixPath file = UnixPath.toUnixPath(path); + file.checkRead(); + return access(file, R_OK) == 0; + } + + @Override + public boolean isWritable(Path path) { + UnixPath file = UnixPath.toUnixPath(path); + file.checkWrite(); + return access(file, W_OK) == 0; + } + + @Override + public boolean isExecutable(Path path) { + UnixPath file = UnixPath.toUnixPath(path); + @SuppressWarnings("removal") + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // not cached + sm.checkExec(file.getPathForPermissionCheck()); } + return access(file, X_OK) == 0; } @Override @@ -561,7 +585,7 @@ public abstract class UnixFileSystemProvider if (Util.followLinks(options)) { UnixPath file = UnixPath.toUnixPath(path); file.checkRead(); - return UnixNativeDispatcher.exists(file); + return access(file, F_OK) == 0; } else { return super.exists(path, options); } diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java index b3bc08e76aa..2404f883c9c 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, 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 @@ -597,34 +597,17 @@ class UnixNativeDispatcher { /** * access(const char* path, int amode); */ - static void access(UnixPath path, int amode) throws UnixException { + static int access(UnixPath path, int amode) { try (NativeBuffer buffer = copyToNativeBuffer(path)) { long comp = Blocker.begin(); try { - access0(buffer.address(), amode); + return access0(buffer.address(), amode); } finally { Blocker.end(comp); } } } - private static native void access0(long pathAddress, int amode) throws UnixException; - - /** - * access(constant char* path, F_OK) - * - * @return true if the file exists, false otherwise - */ - static boolean exists(UnixPath path) { - try (NativeBuffer buffer = copyToNativeBuffer(path)) { - long comp = Blocker.begin(); - try { - return exists0(buffer.address()); - } finally { - Blocker.end(comp); - } - } - } - private static native boolean exists0(long pathAddress); + private static native int access0(long pathAddress, int amode); /** * struct passwd *getpwuid(uid_t uid); diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index 6d933be4e6e..f04a6a396e4 100644 --- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -1190,7 +1190,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_realpath0(JNIEnv* env, jclass this, return result; } -JNIEXPORT void JNICALL +JNIEXPORT jint JNICALL Java_sun_nio_fs_UnixNativeDispatcher_access0(JNIEnv* env, jclass this, jlong pathAddress, jint amode) { @@ -1198,17 +1198,8 @@ Java_sun_nio_fs_UnixNativeDispatcher_access0(JNIEnv* env, jclass this, const char* path = (const char*)jlong_to_ptr(pathAddress); RESTARTABLE(access(path, (int)amode), err); - if (err == -1) { - throwUnixException(env, errno); - } -} -JNIEXPORT jboolean JNICALL -Java_sun_nio_fs_UnixNativeDispatcher_exists0(JNIEnv* env, jclass this, jlong pathAddress) { - int err; - const char* path = (const char*)jlong_to_ptr(pathAddress); - RESTARTABLE(access(path, F_OK), err); - return (err == 0) ? JNI_TRUE : JNI_FALSE; + return (err == -1) ? errno : 0; } JNIEXPORT void JNICALL