Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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:

Files.isSymbolicLink(aPath)

It detects only symbolic links not the files referred to as junctions in Windows.

Also tried the solution proposed here (using JNA library): Stackoverflow question (3249117) , but it never returned true on any of the files I know to be junctions.

The only way I've found to determine which files are junctions is the following command run in windows command prompt:

DIR /S /A:L

On my computer it returns 66 folders, wheras Files.isSymbolicLink(aPath) returned only 2. So I suppose I could find a way to utilize this, but I don't think it would be very effiecient when traversing a filetree.

Is there any way to do this using the standard java library, or alternativly JNA?

like image 316
Martin Avatar asked Dec 05 '12 22:12

Martin


People also ask

How do you tell if a directory is a junction?

In the Windows command line From the Windows command line, you can quickly identify if a directory is a junction using the dir command. The picture at the beginning of this page shows a directory as a junction, displaying <JUNCTION> instead of <DIR>.

What is a junction folder in Windows?

A junction (also called a soft link) differs from a hard link in that the storage objects it references are separate directories, and a junction can link directories located on different local volumes on the same computer. Otherwise, junctions operate identically to hard links.

What is a DOS Junction?

An MS-DOS device name is a junction that points to the path of an MS-DOS device. These junctions make up the MS-DOS device namespace. Call the DefineDosDevice and SetVolumeMountPoint functions to create and modify these junctions.

Is a directory junction or symlink?

Junction Links works only for directories. Symbolic Links works for both directories and files. Junctions links work only for the absolute path. Symbolic Links works for both absolute and relative path.


2 Answers

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.

like image 188
jan.supol Avatar answered Sep 19 '22 12:09

jan.supol


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.

like image 41
Remy Lebeau Avatar answered Sep 21 '22 12:09

Remy Lebeau