Universal Disk Image Format
# Universal Disk Image Format

Das Universal Disk Image Format (UDIF) ist ein von Apple Computer, Inc. für Mac OS X entwickeltes proprietäres Dateiformat für Speicherabbilder. Es ersetzte das zuvor mit Disk Copy 6.0 eingeführte New Disk Image Format (NDIF), bei dem die Metadaten in der resource fork gespeichert waren. Bei UDIF sind alle Daten – data fork, resource fork und Metadaten – in der Datei selbst gespeichert, was den Datenaustausch über das Internet oder Macintosh-fremde Medien erleichtert.

Die erste Veröffentlichung von Mac OS X Public Beta (10.0, „Kodiak,“ 2000) beinhaltete bereits Betriebssystem-seitige Unterstützung für das Universal Disk Image Format, die mit der Dateinamenserweiterung .udif verknüpft war. Ab Mac OS X 10.2 („Jaguar,“ 2002) wird üblicherweise die Erweiterung .dmg verwendet, was Apple als „disk image“ bezeichnet (übersetzt als „Image-Datei“). UDIF ist nicht Teil von Darwin.

Unter klassischem Mac OS wird UDIF nicht unterstützt. Es existieren jedoch eine Entwicklerversion von Disk Copy 6.4 sowie die Betaversion 6.5, die unkomprimierte, unverschlüsselte UDIF-Speicherabbilder unter Mac OS 9 unterstützen.

Für weitere Betriebssysteme gibt es per Reverse Engineering entstandene Programme zum Konvertieren von UDIF-Abbildern in andere Formate.

## Integration in Mac OS X/​OS X/​macOS

Unter Mac OS X, das 2012 in OS X und 2016 in macOS umbenannt wurde, kann ein UDIF-Speicherabbild mit mehreren Programmen erstellt werden. Auf der Kommandozeile kann mit hdiutil eine UDIF-Datei erstellt und eingesehen werden. Grafisch war bis Mac OS X 10.2 („Jaguar,“ 2002) Disk Copy zuständig, das ab Mac OS X Panther (10.3, 2003) vom Festplatten-Dienstprogramm abgelöst wurde.

Ebenfalls ab Mac OS X Panther kümmert sich die DiskImageMounter.app um das einhängen von unterstützten Speicherabbildern. Bis Mac OS X Snow Leopard (10.6, 2009) werden die vom klassischen Mac OS genutzten Formate wie NDIF und Disk Copy 4.2 ebenfalls unterstützt. Mit Mac OS X Lion (10.7, 2011) entfernte Apple die Unterstützung für diese Formate.

Der DiskImageMounter kann jedoch auch einfache Speicherabbilder, wie sie etwa auch mit dd erstellt werden können, verwenden. Auch das Festplatten-Dienstprogramm kann derartige 1:1-Kopien der Daten eines Datenspeichers erstellen: diese erhalten zwar ebenfalls die Endung .dmg im Dateinamen, sind jedoch keine UDIF-Dateien.

## Aufbau

Ein UDIF-Speicherabbild besteht aus mehreren, teils komprimierten Abschnitten. Meist ist im Speicherabbild auch eine Partitionstabelle enthalten. Die Daten sind, weil Mac OS X ursprünglich für die PowerPC-Architektur entwickelt wurde, in Big Endian kodiert.

In der Regel beginnt die Datei mit dem binären Speicherabbild, gefolgt von Metadaten wie der aus NDIF bekannten Resource Fork und einer Property List, gefolgt von einem Koly-Block. Die Resource Fork ist 1:1 das, was bei NDIF noch in einem alternativen Datenstrom im Dateisystem gespeichert war. Da diese Daten nun in der Datei selbst vorgehalten werden, kann eine UDIF-Datei gefahrlos und ohne Verlust der Metadaten über das Internet oder Macintosh-fremde Medien kopiert werden. Bei neueren Versionen von Mac OS X wird die Resource Fork in dieser binären Form üblicherweise weggelassen, weil die Daten zur Gänze in der plist abgebildet sind. Die Property List (plist, übersetzt etwa Liste von Eigenschaften) liegt als 7-Bit-XML-Format vor und speichert Metadaten wie die Resource Fork und Blocklisten.

Eine UDIF-Datei kann mehrere solche Segmente enthalten, sodass pro UDIF-Datei mehrere unabhängige Speicherabbilder enthalten sein können. Ebenso kann mittels Partitionstabelle in einem Speicherabbild mehr als eine Partition enthalten sein.

Ein typischer Aufbau sieht demnach wie folgt aus:

* Speicherabbild (Data Fork), blockweise unterschiedlich komprimiert und/oder verschlüsselt
* Metadaten (Resource Fork, wurde nur bis Mac OS X 10.1 genutzt und wird ab Mac OS X Tiger 10.4.7 auch nicht mehr erstellt)
* Blocktabelle (plist; enthält auch die übrigen Daten der Resource Fork)
* Koly-Block

### Speicherabbild

Die Daten, die als Abbild eines Datenspeichers als UDIF gesichert werden, können in unterschiedlicher Form vorliegen, etwa als eine 1:1-Kopie oder als verschlüsselte Partition. Für UDIF ist nur wichtig, dass auch eine Blocktabelle und ein Koly-Block vorhanden ist, der die Form der Daten beschreibt. Meistens sind die Daten komprimiert.

Insofern ist UDIF nicht auf eine spezielle Partitionstabelle oder ein spezifisches Dateisystem festgelegt. Abbilder von ISO-9660-Medien (auch als Hybrid) wie CD-ROMs oder DVDs sind ebenso gängig wie kleine Installations-Abbilder für Mac-Applikationen, die meist aus APM- oder GPT-Partitionstabelle mit einer Datenpartition im Apple-üblichen Dateisystem HFS+ oder APFS aufgebaut sind.

### Blocktabelle

Die Blocktabelle vereinfacht durch das vorhalten von Blockadressen das Finden der richtigen Daten bzw. Partition innerhalb des Speicherabbilds. Die Liste ist als Property List in XML verfasst und enthält in den meisten Fällen eine Aufteilung in Partitionen. Unter Mac OS X/​OS X/​macOS sind die beiden meistgenutzten Partitionstabellen die Apple Partition Map, daher finden sich in der plist auch die Partitionseinträge Driver Descriptor Map und Apple_partition_map, und die GUID-Partitionstabelle, dann mit den Einträgen Protective Master Boot Record, GPT Header, GPT Partition Data, EFI System Partition. In beiden Fällen sind die Mac-typischen Partitionen vom Typ Apple_HFS und Apple_Free vorhanden, es ist aber generell jede vom Betriebssystem unterstützte Partitionstabelle und jedes unterstützte Dateisystem (mit dazugehörigem Partitionstyp) verwendbar. Für manche Dateisysteme, etwa ISO 9660 oder UDF, entfällt eine zusätzliche Partitionierung.

In jedem Fall hält die Property List für jeden Bereich, wie einer Partition oder einem Dateisystem, einen Eintrag innerhalb des blkx-Schlüssels vor, welcher die Blockliste enthält.

Durch die innerhalb des Data-Schlüssels pro Partition eigene Blockliste ergibt sich der Vorteil, dass ein einzelner Block (oder Sektor) schneller dekodiert werden kann, weil nicht die gesamte Partition dekomprimiert werden muss, sondern jeweils nur die zusammenhängenden Blöcke. Weiters bietet sich so auch die Möglichkeit, unbeschriebene (leere) Bereiche einfach wegzulassen (Zero-Fill). Auch können ohnehin schlecht komprimierbare Bereiche einfach als 1:1-Kopie unverändert gespeichert werden (RAW, unveränderte Rohdaten), was letztlich einen Geschwindigkeitsvorteil bringt.

Der Bereich innerhalb <key>Data</key> <data> … </data> </key> beinhaltet die Base64-kodierte Blockliste. Diese beginnt immer mit der Signatur mish, was in Base64-Kodierung bWlza ergibt. Da die Anzahl der Blöcke unvorherbestimmt ist, führt sich die Liste so lange fort, bis ein Eintrag vom Typ 0xffffffff den letzten Block markiert. Die Struktur der Blockliste sieht in C wie folgt aus:

Folgende Blocktypen der Variable EntryType konnten als blxx-Typ bisher reverse-engineered werden:

| blxx-Typ (Hex) | Schema | Beschreibung | Einführung |
| - | - | - | - |
| 0x00000000 | – | Zero-Fill, weggelassen (keine Daten gespeichert) – ein Bereich, in dem nur Nullen stehen (leere Blöcke) | Mac OS X 10.0 („Cheetah,“ 2001) |
| 0x00000001 | UDRW, UDRO | RAW bzw. NULL compression, unkomprimierte Rohdaten | Mac OS X 10.0 („Cheetah,“ 2001) |
| 0x00000002 | – | unbekannt, ignoriert | – |
| ? | UDRo | schreibgeschützt (nur-lesend, obsolet) | ? |
| ? | UDCo | komprimiert (obsolet) | ? |
| 0x80000004 | UDCO | Apple Data Compression (ADC), komprimiert | Mac OS X 10.0 („Cheetah,“ 2001) |
| 0x80000005 | UDZO | zLib data compression, komprimiert | Mac OS X 10.1 („Puma,“ 2001) |
| 0x80000006 | UDBZ | bz2lib data compression, komprimiert | Mac OS X Tiger (10.4, 2005) |
| 0x80000007 | ULFO | LZFSE data compression, komprimiert | OS X El Capitan (10.11, 2015) |
| 0x7ffffffe | – | keine Blöcke, sondern ein Kommentar (+beg und +end) | – |
| 0xffffffff | – | keine Blöcke – markiert als letzter Eintrag das Ende der blxx-Liste | – |

### Koly-Block

Als letzten 512-Byte-Block enthält ein .dmg üblicherweise einen Koly-Block, der nach seiner Signatur benannt ist. Darin stehen die wesentlichen Sprungadressen für den Aufbau des UDIF-Speicherabbilds.

| Offset | Offset | Länge (in Byte) | Datentyp | Inhalt |
| - | - | - | - | - |
| hex | dec | Länge (in Byte) | Datentyp | Inhalt |
| 00 00 | 0 | 4 | char | Signature, die Magische Zahl des Trailers markiert den Start des Koly-Blocks. Die hexadezimale Zahl 6B 6F 6C 79 ergibt den Text koly. |
| 00 04 | 4 | 4 | uint32_t | Version, die UDIF-Versionsnummer; üblicherweise 4. |
| 00 08 | 8 | 4 | uint32_t | HeaderSize, die Größe des Koly-Blocks; hat immer den Wert 512. |
| 00 0C | 12 | 4 | uint32_t | Flags |
| 00 10 | 16 | 8 | uint64_t | RunningDataForkOffset |
| 00 18 | 24 | 8 | uint64_t | DataForkOffset, die Offset-Adresse der Daten in der UDIF-Datei. Normalerweise 0, da die Daten am Beginn liegen. |
| 00 20 | 32 | 8 | uint64_t | DataForkLength, die Größe des (komprimierten, verschlüsselten) Speicherabbilds in der UDIF-Datei, in Bytes. |
| 00 28 | 40 | 8 | uint64_t | RsrcForkOffset, die Offset-Adresse für Metadaten, wenn vorhanden. |
| 00 30 | 48 | 8 | uint64_t | RsrcForkLength, die Größe der Metadaten in Bytes, wenn vorhanden. |
| 00 38 | 56 | 4 | uint32_t | SegmentNumber, Nummer des Segments; normalerweise 1, kann auch 0 sein. |
| 00 3C | 60 | 4 | uint32_t | SegmentCount, Anzahl der Segmente; normalerweise 1 (kann auch 0 sein). |
| 00 40 | 64 | 16 | uuid_t | SegmentID, 128-Bit GUID des Segments (wenn SegmentNumber nicht 0 ist). |
| 00 50 | 80 | 4 | uint32_t | DataChecksumSize, Informationen über die Prüfsumme. |
| 00 54 | 84 | 132 | 32 × uint32_t | DataChecksum, bis zu 128 Bytes große Prüfsumme der Daten (Data Fork). |
| 00 D8 | 216 | 8 | uint64_t | XMLOffset, Offset-Adresse vom Beginn der Datei zur plist (Property List, im XML-Format). |
| 00 E0 | 224 | 8 | uint64_t | XMLLength, die Größe der plist in Bytes. |
| 00 E8 | 232 | 120 | 120 × uint8_t | reserved (nicht genutzt) |
| 01 60 | 352 | 4 | uint32_t | ChecksumSize, Informationen über die Prüfsumme des unkomprimierten Speicherabbilds. |
| 01 64 | 356 | 132 | 32 × uint32_t | Checksum, bis zu 128 Bytes große Prüfsumme der unkomprimierten Daten. |
| 01 E8 | 488 | 4 | uint32_t | ImageVariant, normalerweise 1. |
| 01 EC | 492 | 8 | uint64_t | SectorCount, Anzahl der Sektoren des unkomprimierten Speicherabbilds. |
| 01 F4 | 500 | 4 | uint32_t | reserved (unbenutzt) |
| 01 F8 | 504 | 4 | uint32_t | reserved (unbenutzt) |
| 01 FC | 508 | 4 | uint32_t | reserved (unbenutzt) |

Da der Koly-Block so gut wie immer am Ende der Datei steht, kann man ihn relativ einfach nutzen, um die Property List zu finden: Die Werte für XMLOffset und XMLLength geben die Position der plist in der UDIF-Datei an.

## Erkennung

Da sich die Information, dass es sich um eine Datei im Universal Disk Image Format handelt, als Koly-Block am Ende der Datei nach den unterschiedlichsten binären Daten befindet, wird eine Datei mit der Endung .dmg oder .udif mit dem Unix-Kommando file nicht als UDIF erkannt. Stattdessen gibt file die Art der Daten am Beginn der Datei an, etwa zlib compressed data oder bzip2 compressed data. Oft kommt es jedoch auch zu einer falschen Erkennung, beispielsweise VAX COFF executable.

Unter macOS gibt das Kommando hdiutil imageinfo Datei.dmg genaue Informationen zur UDIF-Datei (im Beispiel mit dem Dateinamen Datei.dmg) aus.

## Kompatibilität

Allgemein können keine UDIF-Dateien in älteren Mac-OS-X-Versionen verwendet werden, wenn diese den benutzten Kompressionsalgorithmus oder die genutzte Partitionstabelle oder das genutzte Dateisystem nicht unterstützen. Auf anderen Betriebssystemen sind die proprietären Kompressionsverfahren ADC und LZFSE nicht verfügbar, sodass nur zLib- und bz2-komprimierte Daten behandelt werden können.

Unter den ganz alten Versionen von Mac OS X, 10.0 („Cheetah,“ 2001) und 10.1 („Puma,“ 2001), werden nur UDIF-Dateien mit vorhandener Resource Fork unterstützt. Ab Mac OS X Tiger 10.4.7 (Juni 2006) werden allerdings beim Erstellen einer UDIF-Datei die Felder RsrcForkOffset und RsrcForkLength im Koly-Block nicht mehr automatisch befüllt, was damit erstellte UDIF-Abbilder folgerichtig mit Mac OS X vor 10.2 („Jaguar,“ 2002) inkompatibel macht.

