Universal Disk Image Format

Dateiformat

Das Universal Disk Image Format (UDIF) ist ein von Apple Computer, Inc. für Mac OS X entwickeltes proprietäres Dateiformat für Image-Dateien. 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: Image-Datei, 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
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-Images 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

Bearbeiten

Unter Mac OS X, das 2012 in OS X und 2016 in macOS umbenannt wurde, kann ein UDIF-Image 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 Image-Dateien. 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 Abbilddateien, 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.

Ein UDIF-Abbild besteht aus mehreren, teils komprimierten Abschnitten. Meist ist im Image 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 Abbild, 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 Abbilder enthalten sein können. Ebenso kann mittels Partitionstabelle in einem Abbild mehr als eine Partition enthalten sein.

Ein typischer Aufbau sieht demnach wie folgt aus:[5]

  1. Abbild der Daten (Data Fork), blockweise unterschiedlich komprimiert und/oder verschlüsselt
  2. 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)
  3. Blocktabelle (plist; enthält auch die übrigen Daten der Resource Fork)
  4. Koly-Block

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

Bearbeiten

Die Blocktabelle vereinfacht durch das vorhalten von Blockadressen das Finden der richtigen Daten bzw. Partition innerhalb des Abbilds. 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

Bearbeiten

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 der UDIF-Datei.

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) Abbilds 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 Abbilds.
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

Bearbeiten

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, ist eine inhaltsbasierte Erkennung einer UDIF-Datei über die verbreiteten Methode, den Header zu analysieren, nicht möglich. So werden Dateien mit der Endung .dmg oder .udif mit dem Unix-Kommando file nicht als UDIF erkannt, stattdessen gibt das Kommando die Art der (komprimierten) Daten am Beginn der Datei selbst an, etwa VAX COFF executable, zlib compressed data oder bzip2 compressed data, was jedoch ein Produkt des Zufalls ist und keine Aussage über die im Abbild enthaltenen Daten zulässt.

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

Bearbeiten

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.

Bearbeiten

Einzelnachweise

Bearbeiten
  1. 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.
  2. 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.
  3. 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.@1@2Vorlage:Webachiv/IABot/www.puredarwin.org (englisch); abgerufen am 31. Oktober 2016.
  4. DiskCopy 4.2, 6.0, 6.3.3, 6.4, 6.5b13 (englisch), Macintosh Repository; abgerufen am 20. Oktober 2016.
  5. a b Demystifying the DMG File Format (englisch), Jonathan Levin, 12. Juni 2013; abgerufen am 30. Oktober 2016.
  6. Macintosh Disk Images (englisch); abgerufen am 30. Oktober 2016.