Aliases and Bookmarks are smarter than you think

The ideal link to a file or folder would update itself according to changes in the location of that link and the original to which it points. To a certain degree, macOS Finder Aliases and Bookmarks try to do that when they can. This article explains how this works in Mojave, and introduces another new version of Precize which makes it simple to examine the internal data in Finder Aliases.

There are three main types of link available in macOS: a hard link is an additional reference to a file made in the file system directory, and tolerates movement of the item to which it points or the link itself within the same volume. A symbolic link is just a file containing the path to the item to which it links, so moving either the link or the original item will usually break its link unless that path happens to be absolute.

One of the claimed advantages of Finder Aliases, and their parent Bookmarks, is their robustness in the face of change. Because they can use both an absolute path and the unique inode number to resolve the location of the item to which they point, they should be much more reliable than symbolic links, and easier to use than hard links. Indeed, since System 7 in 1991, they have been the only form of link which can be created in the GUI of Mac OS and macOS, the others requiring command line access.

Because Aliases and Bookmarks are opaque data structures in macOS, it has been hard to see them working. I recently released version 1.5 of my free tool Precize which opens up the information contained within them, but required their contents to be pasted in using Base-64 encoding. For Bookmarks that is fine, as that’s how they normally occur in property lists, but I then realised that it was not so simple for a Finder Alias. I have addressed that in a new version of Precize, which now opens Aliases directly.

precise1602

Inside Aliases and Bookmarks

Finder Aliases are one form of Bookmark, packaged to exist as a discrete file. You can also save another form of Bookmark to disk files, which are the kind generated and resolved by my command tool alisma; although functionally fully compatible with Finder Aliases, they are not internally identical. There’s at least one other form of Bookmark which is normally found encoded in Base-64 inside property lists, particularly those of Launch Services.

Finder Aliases and Bookmarks saved as files have 3 more fields of data in them, including NSURLLocalizedNameKey which contains a localised form of the file/folder name, NSURLIsPackageKey to indicate whether the item pointed to is a package, and _NSURLTypeBindingKey which appears to specify data bindings including the characters dnib and text???? (for a text file) or rdif (for a folder). Bookmarks contain an additional field _NSURLBookmarkSecurityScopeCryptoKeyKey which isn’t found in Finder Aliases, and appears to relate to Security Scoping for sandboxed apps.

Resolving Aliases

When studying the contents of orphaned Finder Aliases and Bookmarks, whose original items had been removed, I noticed that some contained paths not to the original location of the item, but to it after it had been placed in the Trash, but others had retained the original location instead. A little further experimentation confirmed an interesting aspect of their behaviour: resolving an Alias or Bookmark will cause its saved paths to be updated if they have changed.

Precize obtains internal information about Aliases and Bookmarks using NSURL.resourceValues(forKeys:fromBookmarkData:) before it attempts to resolve them using URL.init(resolvingBookmarkData:bookmarkDataIsStale:), setting the latter of these arguments to true. What appears to happen is that Bookmark resolution (at least when bookmarkDataIsStale is set to true) causes the Alias to be updated if required.

This is easily tested using this new version of Precize. Create a file and make an Alias to it, then check the paths shown in that Alias: they will point correctly to the original file or folder. Then put the original file in the Trash and empty it immediately, and inspect the Alias again. The path shown for the file should remain unchanged.

Repeat that, but this time don’t empty the Trash before checking the alias in Precize: you should see the alias is now pointing at the file in the Trash.

Spoofing

Alias resolution uses the path stored in an Alias first, but isn’t always as easily spoofed as a symbolic link. A symbolic link contains no information about the file or folder to which it points, and all you have to do to spoof it is replace the item at that path with another.

This is quite complex to demonstrate, but experimenting with different substitutes for a file which has been trashed and the trash emptied shows that Aliases often don’t accept substitute files simply on the basis of their path. Rejection is more likely when the Alias has already been broken with the last known path to the Trash. One trick which can then fool the resolver is to put the substitute file in the Trash, then move it back to where the original file was already.

Given the information stored in an Alias about the file or folder to which it points, this is perhaps not surprising: the resolver has a lot more to work with than just the path, volume and inode number, and does appear to use that additional information to ensure that, most of the time, the link between the alias and original will work, and it won’t be fobbed off by another item posing as the original.

I will continue to explore the Alias resolver, with the aim of providing more insight into its algorithm in a future article.

For now, you too can explore Finder Aliases in this version 1.6 of Precize, available from here: precize16
and from Downloads above.

How to open an Alias

Finally, a little insight into how this new feature works.

Opening a Finder Alias is quite a conundrum, as in normal circumstances the Open File dialog will follow its link rather than opening the Alias file itself. If you want to do this, you need to set NSOpenPanel().resolvesAliases to false.

The next hurdle is obtaining the Alias data itself. If you read it in as Data and then try converting it as a Bookmark, that is sadly doomed to failure as the data in an Alias file isn’t in a normal Bookmark structure. Instead, you have to use NSURL.bookmarkData(withContentsOf:) to return the Data in Bookmark format, which can then be converted as Data.base64EncodedString(options: []) to a Base-64 format String for display. Although there may be other ways – and I tried quite a few of them! – only that sequence delivers a functional Bookmark which can then be resolved using URL.init(resolvingBookmarkData:bookmarkDataIsStale:).