Friday, July 22, 2016

Xcode 8 Illegal Hard Links Prevent Cloning

After I installed Xcode 8 Beta 3, I could no longer back up my hard drive. SuperDuper reported errors like:

Error creating hard link /Volumes/HD Clone 14A/Applications/Xcode-beta.app/Contents/Applications/Accessibility Inspector.app/Contents/Frameworks/AccessibilityAudit.framework/Versions/A/Resources/en.lproj/AuditIssues.strings to /Volumes/HD Clone 14A/Applications/Xcode-beta.app/Contents/Applications/Accessibility Inspector.app/Contents/Resources/en.lproj/AuditIssues.strings for inode (null)

Cloning HD, error creating hard link for file in Xcode-beta.app.

At first I thought that the drive was damaged, but the error still occurred after reformatting it. SuperDuper’s Dave Nanian:

Structure became illegal (hard link into app bundle) in 10.10.3 - break link by duplicating file...

I assume they just did this in the latest beta. (It was previously an issue with Retrospect & Anaconda.)

Indeed, Xcode-beta.app does contain a hard-linked file:

ls -l /Applications/Xcode-beta.app/Contents/Applications/Accessibility\ Inspector.app/Contents/Frameworks/AccessibilityAudit.framework/Resources/en.lproj/
total 48
-rw-r--r--@ 2 mjt  staff   6141 Jul 14 18:08 AuditIssues.strings
-rw-r--r--@ 1 mjt  staff     42 Jul 14 18:08 Localizable.strings
-rw-r--r--@ 1 mjt  staff  10726 Jul 14 18:08 LocalizableOSX.strings

Note the “2” for “AuditIssues.strings”. Here are the two files with the same inode:

find /Applications/Xcode-beta.app/ -name AuditIssues.strings -print -exec stat -f "%i" {} \;
/Applications/Xcode-beta.app/Contents/Applications/Accessibility Inspector.app/Contents/Frameworks/AccessibilityAudit.framework/Versions/A/Resources/en.lproj/AuditIssues.strings
38530212
/Applications/Xcode-beta.app/Contents/Applications/Accessibility Inspector.app/Contents/Resources/en.lproj/AuditIssues.strings
38530212

The fix is to make the two files independent copies:

cd "/Applications/Xcode-beta.app/Contents/Applications/Accessibility Inspector.app/Contents/Resources/en.lproj/"
mv AuditIssues.strings AuditIssues.strings.old
cp AuditIssues.strings.old AuditIssues.strings
rm AuditIssues.strings.old

Now the files have different inodes:

find /Applications/Xcode-beta.app/ -name AuditIssues.strings -print -exec stat -f "%i" {} \;
/Applications/Xcode-beta.app/Contents/Applications/Accessibility Inspector.app/Contents/Frameworks/AccessibilityAudit.framework/Versions/A/Resources/en.lproj/AuditIssues.strings
38530212
/Applications/Xcode-beta.app/Contents/Applications/Accessibility Inspector.app/Contents/Resources/en.lproj/AuditIssues.strings
39006606

Update (2016-07-22): Mike Bombich (developer of Carbon Copy Cloner) on the similar issue with Anaconda:

This turns out to be an issue specific to *.app/Contents/PkgInfo and *.app/Contents/Resources/*.lproj files. OS X does not want to permit the creation of a hard link between one of these items in an application bundle to another file in a non-application-bundle folder. I was unable to find an explanation for this behavior in Apple’s documentation, nor in the source code for HFS or the OS X kernel.

4 Comments RSS · Twitter

What makes that hard link "illegal"?

So, I know it's still early days, but is it reasonable to assume if Apple doesn't correct course on this, it's the end of cloning utilities?

@Clark I’m not entirely sure what the rules are, but it sounds like a security restriction. If you could have a hard link to a file inside an app bundle, you could modify it from another file that has laxer permissions and therefore change the behavior of the app.

@Chucky Seems like the cloning utilities could, at worst, work around it by duplicating the file instead of hard linking it. Also, there may be a way for them to create this structure in an allowed way (e.g. different order of operations), as Archive Utility evidently did when expanding the .xip archive to Xcode-beta.app.

Those specific files/folders Mike mentioned come with "omit" (or at least "optional") in apps that use Xcode's standard resource rules. Could be related -- changing some of those things (via hard link, which means you don't necessarily need access to /Applications, for example) wouldn't break the app's code seal.

Leave a Comment