Simulating Symlinks for Windows XP/2003

April 7th, 2011 Categories: CoApp

(cross-posted from the mailing list)

As I mentioned in my last post, CoApp’s design relies heavily on the use of Symbolic Links (symlinks)—a feature which is implemented fairly well in Windows Vista and beyond, but is missing in earlier versions of Windows.

Cygwin tried to work around the limitation by using shortcuts (.LNK files), which are files used by the Windows Shell for all the shortcuts in the start menu.  Not a bad way to go, but unfortunately, not very compatible with a lot of things, since most programs don’t specially recognize .LNK files, although the POSIX emulation in cygwin did.

I was thinkin’ that any acceptable solution should work with as much software as possible, without requiring special understanding, nor should any additional software be required (ie, a filter driver of some sort).

Our options then, are somewhat limited. On Windows XP and Windows Server 2003 we *do* have features like junctions (like symlinks, but only for directories, and only on the same volume), hard links (where more than one directory entry points to the same physical file) and alternate streams (the ability to store extra data with a file).

Hmmm.

Junctions seem to work fairly well for directories, with the caveat that actually manipulating junctions requires some tricky code with DeviceIOControl calls.

 

For file symlinks, I’ve used NTFS hardlinks, but when I create the link, I store some additional metadata with the file itself in an alternate stream (under the name “legacySymlinkInfo”) which allows tools to find out what the canonical filename really is, and also to find out what other files are linked to the same physical file.

Of course, non-CoApp software could still manipulate these files for little regard as to their status as ‘symlinks’, so the legacySymlinkInfo really can’t always be relied upon. But we can make a pretty good effort to ‘clean-as-we-go’ to keep that information up-to-date. If a file gets renamed or moved, the metadata may not be entirely accurate, so when we check the data, we make an attempt to validate that it is accurate, and update it with what we know. If it sounds like this is dodgy, I wouldn’t disagree, but in practice this seems to work really well.

 

Lastly, we need to be able to redirect a symlink, even when it is in use.  This seems trivial enough to do with junctions, but with files, we have to resort to moving the file out of the way, and creating a new linked file (which we can do, even if the file locked).

 

Admittedly, there are a few limitations that this design has:

Symlinks are only supported on the local system (no cross volume links, nor can they link to UNC paths)

Symlinks must be absolute references (not linking to relative paths)

The relationship between the linked file and the canonical file is potentially ephemeral, but simple examination of the files allows us to rebuild the information.

In the worst case scenario, if files get unlinked, they still work as regular files.

 

Luckily, CoApp’s requirements for what symbolic links need to do doesn’t have to be as flexible as full blown symlinks, and these limitations are not a hindrance at all.

I’ve just added this code to the CoApp toolkit (written in C#), and I’ll be playing with it quite a bit over the next few weeks. Once I’m sure that everything works as I like, if there is interest, I may implement a pure native version of the code so that other utilities and software can do the same thing and play nice too.


You can either comment here, come join mailing list (join the team at https://launchpad.net/~coapp-developers) and continue the conversation!

Tags: , , ,
  • Jeff Hardy

    What about WinXP/FAT32 systems? Not supported?

  • http://fearthecowboy.com Garrett

    With regards to symlinks, no absolutely no support on FAT volumes.

    For CoApp V1, I’m not doing any testing on FAT systems at all; and without hardlink, symlink or junction support, CoApp packages won’t install correctly to FAT volumes.

    For CoApp V2 (somewhat down the road), where we aim to also support ‘portable’ installs of applications (by using local SxS support for shared libraries, etc), packages should be able to install into a FAT volume.

  • http://pasamio.com Sam Moffatt

    One of the problems with junction points is that explorer doesn’t handle them like symlinks are handled and deleting it using any other tool will result in the original files being deleted first and then the junction point being removed.

    How will you protect it from being interfered with by other applications?

    • http://fearthecowboy.com Garrett

      Funny, junctions do work just fine in Explorer for me, just as I’d expect. What problems are you finding?

      And really, the idea is that people generally shouldn’t be deleting applications by simply removing files out of c:\program files , and they shouldn’t delete out of c:\apps either… that’s why we have Add/remove programs.

      I’m not sure what ‘interference’ you’re expecting.

  • Bert

    I have a few remarks:

    - Junction points *do* support cross-volume links. They just do not support relative paths.
    - In Windows XP junctions are kinda dangerous because explorer does not understand them. If you delete a junction from explorer the files in the junction target directory get deleted as well.

    • http://fearthecowboy.com Garrett

      I’ve just retested deleting a junction point on XP via explorer. It does not delete the contents.

      Even if it did; the deletion of files or symlinks without using the package manager (or add/remove programs) is a foolish and insane idea, and I would have no problem telling them “don’t do that” and “too bad for you” if they did.