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.
Universal Disk Image Format | |
---|---|
Dateiendung: | .dmg, .udif |
MIME-Type: | application/x-apple-diskimage-udif application/x-apple-diskimage |
Magische Zahl: | 6B 6F 6C 79 hex 1.802.464.377 (koly) |
Entwickelt von: | Apple, Inc. |
Erstveröffentlichung: | 2000 |
Aktuelle Version: | 4 |
Art: | Speicherabbild, optional komprimiert und verschlüsselt |
Container für: | APM, FAT, GPT, HFS, HFS+, ISO 9660, MFS, MBR, UDF u. a. |
Enthalten in: | macOS |
Standard(s): | proprietär |
Website: | support.apple.com |
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[1] (übersetzt als „Image-Datei“[2]). UDIF ist nicht Teil von Darwin.[3]
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.[4]
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:[5]
- 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,[6] 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.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>resource-fork</key>
<dict>
<key>blkx</key>
<array>
<dict>
<key>Attributes</key>
<string>0x0050</string>
<key>CFName</key>
<string>Protective Master Boot Record (MBR : 0)</string>
<key>Data</key>
<data>
bWlza…
</data>
<key>ID</key>
<string>-1</string>
<key>Name</key>
<string>Protective Master Boot Record (MBR : 0)</string>
</dict>
</array>
<key>plst</key>
<array>
<dict>
<key>Attributes</key>
<string>0x0050</string>
<key>Data</key>
<data>
…
</data>
<key>ID</key>
<string>0</string>
<key>Name</key>
<string></string>
</dict>
</array>
</dict>
</dict>
</plist>
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:[5]
typedef struct {
uint32_t Signature; // Magic ('mish')
uint32_t Version; // Current version is 1
uint64_t SectorNumber; // Starting disk sector in this blkx descriptor
uint64_t SectorCount; // Number of disk sectors in this blkx descriptor
uint64_t DataOffset;
uint32_t BuffersNeeded;
uint32_t BlockDescriptors; // Number of descriptors
uint32_t reserved1;
uint32_t reserved2;
uint32_t reserved3;
uint32_t reserved4;
uint32_t reserved5;
uint32_t reserved6;
UDIFChecksum checksum;
uint32_t NumberOfBlockChunks;
BLKXChunkEntry [0];
} __attribute__((__packed__)) BLKXTable;
// Where each BLXKRunEntry is defined as follows:
typedef struct {
uint32_t EntryType; // Compression type used or entry type (see next table)
uint32_t Comment; // "+beg" or "+end", if EntryType is comment (0x7FFFFFFE). Else reserved.
uint64_t SectorNumber; // Start sector of this chunk
uint64_t SectorCount; // Number of sectors in this chunk
uint64_t CompressedOffset; // Start of chunk in data fork
uint64_t CompressedLength; // Count of bytes of chunk, in data fork
} __attribute__((__packed__)) BLKXChunkEntry;
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 | Länge (in Byte) | Datentyp | Inhalt | |
---|---|---|---|---|
hex | dec | |||
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.
user@Mac:~$ hdiutil imageinfo Datei.dmg | grep Format
Format Description: UDIF read-only compressed (zlib)
Format: UDZO
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.
Weblinks
hdiutil
, Teil von Mac OS X/OS X/macOS- Festplattendienstprogramm (ab Mac OS X 10.3, englisch Disk Utility), Teil von Mac OS X/OS X/macOS
- dmg2img
- dmg2iso
Einzelnachweise
- Disk Utility for Mac: disk image (englisch), Apple Support, Zitat: „A disk image (.dmg file) is a file that looks and acts like a mountable device or volume.“ Abgerufen am 1. November 2016.
- Disk Utility für Mac: Image-Datei, Apple Support, Zitat: „Eine Image-Datei (.dmg-Datei) ist eine Datei, die sich wie ein aktivierbares Gerät oder Volume verhält.“ Abgerufen am 1. November 2016.
- puredarwin.org Disk images (Memento des Originals vom 31. Oktober 2016 im Internet Archive) Info: Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäß Anleitung und entferne dann diesen Hinweis. (englisch); abgerufen am 31. Oktober 2016.
- DiskCopy 4.2, 6.0, 6.3.3, 6.4, 6.5b13 (englisch), Macintosh Repository; abgerufen am 20. Oktober 2016.
- Demystifying the DMG File Format (englisch), Jonathan Levin, 12. Juni 2013; abgerufen am 30. Oktober 2016.
- Macintosh Disk Images (englisch); abgerufen am 30. Oktober 2016.