Friday, October 5, 2012

Windows Symbolic Links and File Sharing

Symbolic Links, Hard Links, and Junction Points are useful tools for an experienced administrator to manipulate the file system to bring things in different locations under a single logical tree. Symbolic Links have been posssible to create since Windows 2000 (using the linkd.exe, mountvol.exe, and delrp.exe utilities from the Windows 2000 Resource kit), but only in the most recent versions of Windows (Windows Vista, Windows 7, Windows 8, Windows Server 2008, Windows Server 2008 R2, and Windows Server 2012) has the mklink utility been provided with the OS to create symbolic links. The original functionality in Windows 2000 was called the NTFS reparse point, which is basically just a file system object with extended information. This functionality isn't particularly well known, but it is useful in a wide variety of scenarios.

By default, users in the local administrators group have the ability to create symbolic links, but this permission can be granted by modifying the "Create Symbolic Links" user right:



There are a lot of potential uses for symbolic links, but some of the ones that I've dealt with are:
  • A static content directory in IIS needs to be available at multiple points in the site/application tree so that pages do not need to use absolute or relative references that point outside of the current logical directory or a particular piece of content needs to appear at multiple points in the site.
  • A user wants to double click a folder in the "My Documents" folder and be able to access the root of the C: drive (note that this is not a shortcut)
  • A developer needs to create a separate tree that includes files used for unit tests, but wants changes to the "primary" source tree to be instantaneously propagated to the tree used for unit testing (I've used this one myself during the development of complex Latex/pdf documents that need to be generated with ASP.Net)
  • Scripts need to be developed that access other parts of the filesystem from a single folder.
  • The same file needs to be accessed by multiple names
Now that we understand what they are and some of the use cases, let's look at how to create/use them. The basic syntax of the command is

c:\symlinktest>mklink 
Creates a symbolic link. 
 
MKLINK [[/D] | [/H] | [/J]] Link Target
 
        /D      Creates a directory symbolic link.  Default is a file
                symbolic link. 
        /H      Creates a hard link instead of a symbolic link. 
        /J      Creates a Directory Junction. 
        Link    specifies the new symbolic link name. 
        Target  specifies the path (relative or absolute) that the new link
                refers to.  

Directory Hard Link

Long story short, you can't make a directory hard link. The mklink utility doesn't give a particular error, just "access is denied:"

c:\symlinktest>mklink /H test2 test
Access is denied.

c:\symlinktest>mklink /D /H test2 test
Access is denied.

Why can't a directory hard link be created? Because each directory has a pointer to its parent directory. In the case of a hard link, there would be ambiguity as to what the parent directory actually is because the hard link is actually another entry in the master file table (MFT). Directory hard links would also create the possibility of infinite recursion through the filesystem.

File Hard Link


Hard links create an additional pointer in the master file table (MFT) for a particular file, but with a different name. Hard links can be deleted, but the file will not be deleted until all of the hard links that reference the file are gone. When a hard link is created, the target has to exist (because it points to an existing file). Additionally, the file and the hard link have to exist on the same volume (this is the same as the Linux/UNIX world since Windows is POSIX compliant).

In this example, I created a file (important.txt) that I want to edit by another name (important2.txt),

c:\symlinktest>mklink /H important2.txt important.txt
Hardlink created for important2.txt <<===>> important.txt

Looking at the directory, the files look the same (and they are the same). Permissions are set on the file object, so changing the permissions on one hard link changes it on both of them.

 Directory of c:\symlinktest

10/05/2012  02:17 PM    <DIR>          .
10/05/2012  02:17 PM    <DIR>          ..
10/05/2012  02:10 PM                 0 important.txt
10/05/2012  02:10 PM                 0 important2.txt
10/05/2012  02:02 PM    <SYMLINKD>     system32 [c:\windows\system32]
10/05/2012  01:57 PM    <DIR>          test
10/05/2012  01:58 PM    <SYMLINKD>     test2 [test]
               2 File(s)              0 bytes
               5 Dir(s)  694,212,771,840 bytes free

From a file sharing perspective, a hard link can exist to a file outside of the root of the share (but on the same storage volume on the server) and be accessible to users who have share/NTFS permissions to the file.

File Symbolic Link


NTFS file symbolic links are filesystem objects that are different from shortcuts (.lnk files), but point to either a relative or absolute path of a file. These links are created without the /H option with mklink,

c:\symlinktest>mklink important2.txt ..\symlinktest\important.txt
symbolic link created for important2.txt <<===>> ..\symlinktest\important.txt

c:\symlinktest>mklink important3.txt c:\symlinktest\important.txt
symbolic link created for important3.txt <<===>> c:\symlinktest\important.txt

Looking at the links,
...
10/05/2012  02:10 PM                 0 important.txt
10/05/2012  02:33 PM    <SYMLINK>      important2.txt [..\symlinktest\important.txt]
10/05/2012  02:33 PM    <SYMLINK>      important3.txt [c:\symlinktest\important.txt]
...

In Windows Explorer, these look like shortcuts, but aren't.



The properties are greyed out and cannot be edited. Symbolic links do not have to point to a target that exists and can point between drive letters and volumes. From a file sharing perspective, a symbolic link that points outside of the shared directory structure is inaccessible (Errors like 'Operation not supported' and 'the network path was not found' are common). Relative path symbolic links that point to files within the same share structure are accessible, as are symbolic links that point to UNC shares, but this has a tendency to create a lot of complexity in a file sharing environment. Additionally, remote-remote and remote-local symlinks are disabled on clients by default. See below for more details.

Directory Symbolic Link


The Directory symbolic link is essentially the same as the file symbolic link, but the target is a directory instead. Here is a brief example:

c:\symlinktest>mklink /D test2 test
symbolic link created for test2 <<===>> test

Directory of c:\symlinktest

10/05/2012  02:17 PM    <DIR>          .
10/05/2012  02:17 PM    <DIR>          ..
10/05/2012  02:10 PM                 0 important.txt
10/05/2012  02:10 PM                 0 important2.txt
10/05/2012  01:57 PM    <DIR>          test
10/05/2012  01:58 PM    <SYMLINKD>     test2 [test]
               2 File(s)              0 bytes
               4 Dir(s)  694,212,771,840 bytes free


Directory Junction Point


Junction points act more like hard links than symbolic links and are specifically for directories. They are created with the /J option of mklink and they can be traversed just like a directory. Remote-Remote symbolic links (see below) do not need to be enabled because it is not technically a symbolic link, but rather a file object that allows a directory to be linked at multiple points in the filesystem. 

As an example, we will create a ZZZ folder that traverses to c:\windows:

c:\symlinktest>mklink /J ZZZ c:\windows
Junction created for ZZZ <<===>> c:\windows

c:\symlinktest>dir
...
10/05/2012  03:10 PM    <JUNCTION>     ZZZ [c:\windows]
               4 File(s)     19,577,576 bytes
               8 Dir(s)  694,211,403,776 bytes free

Accessing this junction from a share allows the server's c:\windows directory to be traversed, even though only the c:\symlinktest folder is shared. If the user has administrative permissions, then they can change files remotely.

If you make an error and create one for a file, it'll create, but won't work:

c:\symlinktest>mklink /J test.exe  FEPInstall.exe
Junction created for test.exe <<===>> FEPInstall.exe

Accessing the test.exe folder will fail with "The directory name is invalid"


Deleting a Symbolic Link

You can delete a symbolic link or junction point the same way that any other file can be deleted (Remote-Item in PowerShell, del in cmd, or right click -> delete in Windows explorer).

Dealing with "The symbolic link cannot be followed because its type is disabled"


As a security measure, symbolic links on file shares are not followed. You can see what the current behavior is by running  fsutil behavior query SymlinkEvaluation:

Here is the default behavior for symlinks:

c:\symlinktest>fsutil behavior query SymlinkEvaluation
Local to local symbolic links are enabled.
Local to remote symbolic links are enabled.
Remote to local symbolic links are disabled.
Remote to remote symbolic links are disabled.

To enable remote-remote symlinks, run fsutil behavior set SymlinkEvaluation R2R:1

c:\symlinktest>fsutil behavior set SymlinkEvaluation R2R:1

c:\symlinktest>fsutil behavior query SymlinkEvaluation
Local to local symbolic links are enabled.
Local to remote symbolic links are enabled.
Remote to local symbolic links are disabled.
Remote to remote symbolic links are enabled.

I wouldn't recommend enabling remote to local symlinks, but this is also possible.

Dealing with "Location is Not Available"



"Location is not available: %s refers to a location that is unavailable. It could be on a hard drive on this computer, or on a network. Check to make sure that the disk is properly inserted, or that you are connected to the Internet or your network, and then try again. If it still cannot be located, the information might have been moved to a different location"

If you get this error, your link isn't pointing to the right place, or the user has a different view (ex. mounting a share farther down in the tree than he/she should be) than the link was put in place to support. Look at the link and make sure it points to the right place. Access the share as the user and see if the path that the link references actually exists from the end user's perspective.

1 comment:

  1. Thanks for the post and information! I think education is important for us so we must prepare the best education for our generation by sharing such great information with each other!
    online tutoring

    ReplyDelete