Determine whether a file is a junction (in Windows) or not?
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
:
Use
DeviceIoControl()
with theFSCTL_GET_REPARSE_POINT
control code to obtain anREPARSE_DATA_BUFFER
struct, which as aReparseTag
field. You can see an example of anIsDirectoryJunction()
implementation using this technique in the following article:NTFS Hard Links, Directory Junctions, and Windows Shortcuts
Use
FindFirstFile()
to obtain aWIN32_FIND_DATA
struct. If the path has theFILE_ATTRIBUTE_REPARSE_POINT
attribute, thedwReserved0
field will contain theReparseTag
.
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.