Search code examples
javafileunixjvmjvm-hotspot

Read file attributes using RandomAccessFile


Is it possible to get any of the file attributes using RandomAccessFile?

By file attributes I mean Unix implementation provided in the class UnixFileAttributes:

class UnixFileAttributes
    implements PosixFileAttributes
{
    private int     st_mode;
    private long    st_ino;
    private long    st_dev;
    private long    st_rdev;
    private int     st_nlink;
    private int     st_uid;
    private int     st_gid;
    private long    st_size;
    private long    st_atime_sec;
    private long    st_atime_nsec;
    private long    st_mtime_sec;
    private long    st_mtime_nsec;
    private long    st_ctime_sec;
    private long    st_ctime_nsec;
    private long    st_birthtime_sec;

    //
}

Usage of third-party libraries is acceptable (and desirable) in case it is not possible to do that in plain Java.


Solution

  • In JDK, the only built-in bridge from Java land to fstat function is sun.nio.fs.UnixFileAttributes.get() method. This is private API, which can be called only using Reflection. But it works in all versions of OpenJDK from 7 to 14.

        public static PosixFileAttributes getAttributes(FileDescriptor fd)
                throws ReflectiveOperationException {
    
            Field f = FileDescriptor.class.getDeclaredField("fd");
            f.setAccessible(true);
    
            Class<?> cls = Class.forName("sun.nio.fs.UnixFileAttributes");
            Method m = cls.getDeclaredMethod("get", int.class);
            m.setAccessible(true);
    
            return (PosixFileAttributes) m.invoke(null, f.get(fd));
        }
    
        public static void main(String[] args) throws Exception {
            try (RandomAccessFile raf = new RandomAccessFile(args[0], "r")) {
                PosixFileAttributes attr = getAttributes(raf.getFD());
                System.out.println(attr.permissions());
            }
        }
    

    Other possible solutions would involve native libraries (JNI / JNA / JNR-FFI). But you'd still need to obtain a native fd from FileDescriptor object, either using Reflection or JNI.