Determine whether a file is a junction (in Windows) or not?

后端 未结 4 1804
囚心锁ツ
囚心锁ツ 2021-02-13 17:47

I\'ve been searching around trying to find a way to determine if a file is a junction or not, and have not found any satisfactory answers.

First thing I tried was:

相关标签:
4条回答
  • 2021-02-13 17:51

    If you can write native code in JNA, you can directly call the Win32 API GetFileAttributes() function and check for the FILE_ATTRIBUTE_REPARSE_POINT flag (junctions are implemented as reparse points).

    Update: To differentiate between different types of reparse points, you have to retreive the ReparseTag of the actual reparse point. For a junction point, it will be set to IO_REPARSE_TAG_MOUNT_POINT (0xA0000003).

    There are two ways to retreive the ReparseTag:

    1. Use DeviceIoControl() with the FSCTL_GET_REPARSE_POINT control code to obtain an REPARSE_DATA_BUFFER struct, which as a ReparseTag field. You can see an example of an IsDirectoryJunction() implementation using this technique in the following article:

      NTFS Hard Links, Directory Junctions, and Windows Shortcuts

    2. Use FindFirstFile() to obtain a WIN32_FIND_DATA struct. If the path has the FILE_ATTRIBUTE_REPARSE_POINT attribute, the dwReserved0 field will contain the ReparseTag.

    0 讨论(0)
  • 2021-02-13 17:55

    There can be a way to do it without JNA, if you have the right java, such as Oracle jdk 8. It's dodgy, it can cease to work, but....

    You can get BasicFileAttributes interface related to the link:

    BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
    

    It can happen that this interface implementation is a class sun.nio.fs.WindowsFileAttributes. And this class has a method isReparsePoint, which returns true for both junction points and symbolic links. So you can try to use reflection and call the method:

        boolean isReparsePoint = false;
        if (DosFileAttributes.class.isInstance(attr))
            try {
                Method m = attr.getClass().getDeclaredMethod("isReparsePoint");
                m.setAccessible(true);
                isReparsePoint = (boolean) m.invoke(attr);
            } catch (Exception e) {
                // just gave it a try
            }
    

    Now you only can discover whether it really is symbolic link: Files.isSymbolicLink(path)

    If its not, but it is reparse point, then that's junction.

    0 讨论(0)
  • 2021-02-13 17:56

    With J2SE 1.7 use Java NIO

    /**
    * returns true if the Path is a Windows Junction
    */
    private static boolean isJunction(Path p) {
        boolean isJunction = false;
        try {
            isJunction = (p.compareTo(p.toRealPath()) != 0);
        } catch (IOException e) {
            e.printStackTrace(); // TODO: handleMeProperly
        }
        return isJunction;
    }
    
    0 讨论(0)
  • 2021-02-13 18:07

    While on Windows a junction's attributes have isSymbolicLink() == false, they have isOther() == true. So you could do something like:

    boolean isWindows = System.getProperty("os.name").toLowerCase().contains("windows")
    BasicFileAttributes attrs = Files.readAttributes(aPath, BasicFileAttributes.class);
    boolean isJunction = isWindows && attrs.isDirectory() && attrs.isOther();
    
    0 讨论(0)
提交回复
热议问题