Forks und Attribute: Metadaten in HFS+

Es fing ganz harmlos an. Bei der Erweiterung meines Backup-Konzepts sollte rsync eine Rolle spielen, und ich erinnerte mich dunkel, dass Apples Dateisystem HFS+ irgendwelche Metadaten unterstützt, die bei einem Transfer verloren gehen könnten. Eine Google-Suche bestätigte meine Befürchtung, dass das alles nicht so einfach ist:

Mac OS X uses the HFS+ filesystem, by default. HFS+ files are often composed of a data fork, a resource fork, and Finder metadata. The data and resource forks contain what you normally think of when you think of file information: data, program code, etc. Finder metadata includes information like file type and creator, comments, modification dates, locked and invisible status, and Finder colors. Traditional UNIX filesystems only store a single stream of file data (the HFS+ equivalent of the data fork). Mac OS X (or Darwin, more precisely) is a genuine BSD UNIX, but with a nontraditional filesystem. Because of this, standard UNIX tools can only see certain portions of OS X files.

The difficulties caused by HFS/HFS+ aren't new. Early Mac users of BBSes and the Internet had the same problems when uploading files from a Mac for storage by other operating systems. Since the foreign OS had no way to store the additional HFS data, the uploads would be incomplete/useless. To solve this problem, Apple and others invented conversion formats that collected the full set of file information into a single data stream. Examples (some with varying and/or additional design goals) include AppleSingle, AppleDouble, MacBinary, BinHex, and Stuffit.

The relatively new development is OS X. Now that Mac users can run decades of software written for traditional UNIX machines, some of that software needs to be updated to work properly with HFS+ files.

One such standard UNIX tool is rsync, an excellent file synchronization utility which is also great for use as filesystem backup software. Rsync builds and runs without errors on OS X, but because it is unaware of resource forks and other metadata, it creates incomplete (and therefore corrupt) backups.

Good heavens! Korrupte Backups! Glücklicherweise hatte der oben ausführlich zitierte Mr. Reynhout einen Patch für rsync entwickelt, der

will make rsync HFS+ metadata-aware. Resource forks and Finder metadata are assembled on the sender into an ephemeral file in standard AppleDouble format, before being sent to the destination.

This method preserves disk space on both sides, with zero redundant data and only a small amount of overhead per file (~100 bytes of AppleDouble headers for each file that has a resource fork and/or HFS+ metadata). It works with any destination filesystem and operating system (tested with Solaris and Linux), and even with older or unpatched versions of rsync.

Sogar die Restaurierung der Resource Forks ist relativ einfach (/System/Library/CoreServices/FixupResourceForks MyBackupFolder).

Im Gegensatz dazu unterstützt rsync auch in der aktuellen Version 3.0.6 (die nicht mit Snow Leopard geliefert wird) nur die Übertragung von Resource Forks und Extended Attributes – um die Speicherung müssen sich die beteiligten Dateisysteme selbst kümmern. Worauf man sich im Fall von ext3 nicht unbedingt verlassen kann:

rsync: rsync_xal_set: lsetxattr("Backup/clientdata.sparsebundle","user.com.apple.FinderInfo") failed: Operation not supported (95)

So richtig Lust auf eine Neukompilierung des Linux-Kernels hatte ich nicht. Welche lebenswichtigen Daten sind überhaupt außerhalb des Data Forks gespeichert? Was ist ein Resource Fork, und was sind Extended Attributes?

Die Definition verschiedener Forks (a.k.a. Alternate Data Streams) in einem Dateisystem ist eine Methode, verschiedene Arten von Informationen in einem Dateiobjekt zu speichern. Apple unterstützt in allen eigenen Dateisystemen (MFS/HFS/HFS+) neben dem Data Fork einen Resource Fork zur Speicherung von Metadaten in beliebigem Umfang. Der Resource Fork kann größer sein als der Data Fork. Im Fall der Schriftdateien im klassischen Mac OS sind sogar alle relevanten Informationen im Resource Fork enthalten.

Auch Extended Attributes dienen der Speicherung von Metadaten, sind aber anders als Forks usually limited in size to a value significantly smaller than the maximum file size. Unter Mac OS X werden die Name-Wert-Paare der Extended Attributes im B-Tree des Dateisystems gespeichert und lassen sich über das Dienstprogramm xattr auslesen und verändern.

Generell schien die Bedeutung des Resource Forks seit der Einführung von Mac OS X stark abzunehmen, während die Extended Attributes (ab Mac OS X 10.4) eine immer größere Rolle spielten. Selbst der ehrwürdige Resource Fork wurde zu einem Attribut namens com.apple.ResourceFork degradiert. Just als sich der gnädige Nebel des Vergessens über den Resource Fork senken wollte, erschien Snow Leopard, und John Siracusa machte in seiner umfangreichen Rezension eine interessante Beobachtung. Die neuen komprimierten Anwendungen enthielten neben einem äußerst umfangreichen Wert für com.apple.ResourceFork auch diese Information:

% hfsdebug /Applications/Mail.app/Contents/MacOS/Mail ... compression magic = cmpf compression type = 4 (resource fork has compressed data) uncompressed size = 7500336 bytes

Diese Beobachtung stellte auch die Behauptung in Frage, der wichtigste Unterschied zwischen Fork und Attribut sei die Größenbeschränkung. Zwar können Attribute angeblich nur einen B-Tree-Knoten umfassen, aber Mr. Siracusa mutmaßte schon vor einigen Jahren in einem Kommentar:

There’s no hard limit on attribute sizes. The 4K limit is only a recommendation.

As for the resource fork, my guess is that, like type and creator codes, they can be accessed via extended attributes but the actual data is still stored in the same old place(s). In other words, the EAs for these items are merely proxies. But that’s just a guess…

Das wäre also geklärt. Aber welche Metadaten waren für meine Zwecke relevant? Das einzige Mac-Objekt in meinem Backup war ein verschlüsseltes Sparse Bundle. Und siehe da: Ein Sparse Bundle kann bei Verlust des Bundle Bits im Attribut com.apple.FinderInfo nicht mehr per Doppelklick geöffnet werden, sondern erscheint als schnöder Dateiordner! Natürlich hielt das Netz jede Menge Lösungen bereit:

Pragmatisch
Erstellen eines neuen Sparse Bundles und Kopieren des Bundle-Inhalts
Umständlich
Öffnen des Sparse Bundles im Terminal mit hdiutil
Elegant
Setzen des Bundle Bits mit SetFile aus Apples Developer Tools
Obsessiv
Kompilation eines eigenen Skripts zum Setzen des Bundle Bits

Allerdings stellte sich heraus, dass Snow Leopard sehr gut auf das Bundle Bit verzichten kann und alle Ordner mit der Erweiterung .sparsebundle automatisch mit dem DiskImageMounter öffnet. Anders ausgedrückt: Nachdem ich jetzt genau weiß, wo und wie Metadaten mit HFS+ gespeichert werden, kann ich sie ignorieren. Heureka.