2
votes

Windows 7/NTFS and later has both symbolic links and junctions, and they are subtly different. (See this excellent set of posts). For logging (and debugging) purposes, I need to be able to resolve the target of a junction on a remote file server. There have been some posts on this topic, but they apply to resolving a junction as the local machine see it.

On \\FileServer, we have a directory G:\Shared that is shared out as PublicShare, so it apears on the network as \\FileServer\PublicShare. Within that directory are sub-directories G:\Shared\SubDir1 and G:\Shared\SubDir2. Also within that directory is a junction G:\Shared\Junc that points to either G:\Shared\SubDir1 or G:\Shared\SubDir2. (The target can change.) Thus, on \\FileServer, one sees

\\FileServer\PublicShare\SubDir1
\\FileServer\PublicShare\SubDir2
\\FileServer\PublicShare\Junc

On a client machine where \\FileServer\PublicShare is mounted (mapped in Windows lingo) as M:\, one thus sees M:\SubDir1, M:\SubDir2, M:\Junc. If, on that client machine, you open a console (cmd.exe) and do dir M:\, Windows gives a nice listing which shows that M:\Junc is a junction and includes the target, G:\Shared\SubDirX, of the junction.

M:\>dir
 Volume in drive M is XXXXXXXXX
 Volume Serial Number is XXXX-XXXX

 Directory of M:\

09/05/2014  07:30 PM    <DIR>          .
09/05/2014  07:30 PM    <DIR>          ..
09/05/2014  01:36 PM    <JUNCTION>     Junc [G:\Shared\SubDir1]
09/06/2014  12:55 PM    <DIR>          SubDir1
09/05/2014  05:15 PM    <DIR>          SubDir2
               0 File(s)              0 bytes
               3 Dir(s)  1,895,493,492,736 bytes free

M:\>

Thus, the target of such a junction is clearly available to a client. Does anyone know how to obtain this information programatically, e.g. which system api to call??? Thanks.

2
My understanding is that there is no API; you have to read the reparse point information (using FILE_FLAG_OPEN_REPARSE_POINT) and parse it yourself. As far as I know, the format of the reparse information for a junction point isn't documented, but I imagine it would be reasonably straightforward to reverse engineer.Harry Johnston
If I am on the client machine, do I have access to the reparse point information? Don't forget, the junction is on the file server, and the junction (reparse-point) is handled and processed on the server side. Handling a reparse-point is not that difficult - the source to sysinternal's "junction.exe" is available (or at least it was, since I have a copy). You have me thinking though. Maybe you are correct.David I. McIntosh
@HarryJohnston: You were correct. All I needed to do was try sysinternal's junction.exe - it gives me the information I want. Post you comment as an answer and I will "accept" it as an answer. Thanks.David I. McIntosh
You did the heavy lifting, it would be more appropriate for you to post an answer yourself. (Preferably with code, or sufficient details to allow future readers to write their own. I may be wrong, but I don't think the source to junction.exe is publicly available any more.)Harry Johnston

2 Answers

1
votes

This does the trick:

fsutil reparsepoint query "M:\Junc"

and it seems very reliable.

0
votes

If you don't want to parse the output of C:\Windows\System32\fsutil.exe, you could simply use DIR:

for /f "usebackq delims=[] tokens=2" %i in ( `dir M:\^|findstr JUNCTION` ) do set RES=%i

Notes:

  • M:\: you need to display the subfolders (and junctions) of the parent folder of the JUNCTION (in this case: M:\)
  • findstr: if you have several junctions and want to resolve a specific one, add a |findstr foldername to isolate the right line,
  • delims=[]: that will divide the output 09/05/2014 01:36 PM <JUNCTION> Junc [G:\Shared\SubDir1] into 3 tokens:
    • 09/05/2014 01:36 PM <JUNCTION> Junc
    • G:\Shared\SubDir1
    • "<empty>"
  • tokens=2: only the second token ("G:\Shared\SubDir1") is of interest
  • %i: if you run that command in a .bat script, double the '%': %%i in and res=%%i