Last Week on My Mac: Breaking the link

The more you look at them, the more links become the most complex and confusing of simple concepts in computing. I started the last couple of weeks with a simple summary learned progressively over the last thirty years: symlinks for the command line and shell scripts, Aliases for the GUI, and hard links only when you really must and know how to use them.

Then as I researched for and wrote up my series of articles here, several of you came back with excellent (and greatly valued) comments which made me question whether those rules of thumb were right. I went back and looked again, and again, and their simplicity was lost. As symlinks work fine in the Finder too, why not use them more, instead of Aliases?

After more experimentation and examination of their practical use, I came back to my original rules of thumb, elaborating them into tables which I published here just over a week ago. I thought the topic was done.

Then came more comments, particularly those from David Charlap, which brought me what seemed a sudden insight: of course, with a symlink you get to specify the path used for the link. So you have a choice between using relative and absolute paths, in many cases at least. Like an alchemist who had just created their first small lump of gold-coloured goo, I wondered why I hadn’t read more about this choice before.

I went back and re-read the man page for the ln command, and Wikipedia’s long entry on symbolic links, and couldn’t find any useful discussion of the merits of using relative and absolute paths for the link, and wondered why this insight hadn’t been passed on there too. Only when I looked yet again at where symlinks work best did the self-evident truth emerge from behind the clouds.

Classical examples of where symlinks work well, and are widely used, include:

  • Inside frameworks and similar structured folders, where only relative paths are used. If the internal structure of the framework becomes disrupted, it ceases to work, but absolute paths would prevent the framework from residing anywhere else.
  • At the root level of your file system, to point to key directories within /private. Those are all protected by SIP, and disruption is devastating anyway. Although the paths are strictly speaking relative (they don’t start with a slash), they are in effect absolute because /private is a top level directory.
  • Linking fixed locations from your Home folder to those on an external volume. Because they’re on a volume mounted in /Volumes, these can only use absolute paths of course.

In each case, there isn’t any real option as to the type of path used. It’s either determined by the purpose of the link, or architectural.

I was then distracted by Thomas Tempelmann’s suggestion for a utility to refresh Aliases and identify those that are broken. This brought with it a more worrying insight: most of the Aliases on my boot volume, even those inside /Library, are broken. Apple’s ingenious composite of symbolic and hard link, crafted to make it more robust when it’s moved or paths change, and served in the friendly GUI, hasn’t solved the problems of links after all.

The underlying problem is that Aliases don’t update themselves quietly when you’re not looking. Most, perhaps all, of those broken Aliases have been migrated across from older Macs. But in that migration, they don’t seem to have become refreshed, nor checked to see whether they are broken.

Unlike good friends, Finder Aliases don’t keep well when left alone. Let’s say that you create an Alias to a working folder buried deep somewhere in your ~/Documents folder. Over time, things get moved around and renamed. When that Alias lies unused and (most significantly) unresolved, it will still work so long as its fallback resolution mechanisms work too. In the meantime, it remains half broken, as its symlink part, the absolute path, no longer exists.

When that unused and unrefreshed Alias is copied over to another volume, perhaps when you migrate to your next Mac or clone that volume to another, the second half of the resolution mechanism in that Alias breaks too: on a different volume, the unique inode and file numbers for the item to which it points are also now broken. Try to resolve it, and macOS cannot find its original item.

I can’t find any current documentation which details those operations which cause a Finder Alias to update its internal information. As they changed substantially in macOS 10.12, when Apple ceased maintaining most of its systematic guides, it’s now a matter of trial and error. As far as I can tell from inspecting the opaque and undocumented information stored within an Alias, simply accessing it using NSURL.bookmarkData(withContentsOf:) and resolving that with URL.init(resolvingBookmarkData:bookmarkDataIsStale:) seems to do the trick.

To look at what the Alias is currently pointing to, you have to open it, which could of course cause it to resolve and try to update its internal data. Even selecting an Alias in an Open File dialog can be sufficient to cause it to resolve and update its contents.

There is a need for a utility to refresh Aliases and check them for broken links. Alifix is a step on the way, and I hope will address this need and more. But it also demonstrates how right I was when I opened the first article in that series with the words:
If there’s one topic which is most likely to bring confusion it’s the different types of links and aliases available in Unix-like file systems, and macOS running on APFS is no exception.

And I’m still not sure that I’m any the wiser.