mstrap
mstrap

Reputation: 17443

How to retrieve Java NIO PosixFilePermission during a Files.walkFileTree?

On Unix, Files.walkFileTree will callback FileVisitor.visitFile with BasicFileAttributes which are actually sun.nio.fs.UnixFileAttributes$UnixAsBasicFileAttributes. As the debugger shows, the wrapped UnixFileAttributes already contain permission information (st_mode field is populated). Is there a (graceful) way to unwrap the UnixFileAttributes$UnixAsBasicFileAttributes in order to get at least PosixFileAttributes so the permissions will be accessible? Reflection does not work for me, but results in an IllegalAccessError when trying to invoke UnixFileAttributes$UnixAsBasicFileAttributes.unwrap.

Also, I want to avoid to explicitly call Files.getPosixFilePermissions(file) for every reported file as this gives roughly 10% overhead for my test cases.

Upvotes: 4

Views: 269

Answers (1)

Mark Jeronimus
Mark Jeronimus

Reputation: 9543

In my Java, there's a package-private method just to unwrap the wrapped attributes. No guarantee that any Java will contain this method. For now this works for me and I hope it does for you too.

enter image description here

I can call this method with the following code.

You came very close with your attempt at Java 9: How to retrieve the ctime in FileVisitor.visitFile()?. I simplified it a bit for this question.

try {
    Class<?> basicFileAttributesClass = Class.forName("java.nio.file.attribute.BasicFileAttributes");
    Class<?> unixFileAttributesClass  = Class.forName("sun.nio.fs.UnixFileAttributes");

    Method toUnixFileAttributesMethod =
            unixFileAttributesClass.getDeclaredMethod("toUnixFileAttributes", basicFileAttributesClass);
    toUnixFileAttributesMethod.setAccessible(true);

    attrs = (BasicFileAttributes)toUnixFileAttributesMethod.invoke(unixFileAttributesClass, attrs);
} catch (ReflectiveOperationException ex) {
    throw new RuntimeException(ex);
}

For Java 9 and up, the setAccessible() checks module permissions, which your module doesn't have. This can be unlocked with the VM option --add-opens java.base/sun.nio.fs=ALL-UNNAMED.

Upvotes: 2

Related Questions