HDD-Image aus Partitions-Images rekonstruieren

Problem ist folgendes:

Es gibt ein Image einer Partition (mit dd erstellt) und diese Partition soll nun in einer VM (z.B. qemu) zur Verfügung gestellt werden.

Windows benötigt eine Partitionstabelle und somit kann ein Image einer Partition nicht als Festplatte in einer VM gestartet werden. Wir werden hier am Beispiel von zwei Partitions-Images ein Festplatten-Image rekonstruieren.

Gegeben seien unsere beiden PartitionsImage-Files, welche wir mit 'dd' erstellt haben:

        root@Microknoppix:/media/backup# ls -alh *.img
        -rw-r--r-- 1 root root  21G Sep 12 06:22 sda1image.img
        -rw-r--r-- 1 root root 1,8T Sep 12 18:25 sda5image.img
      

Wir haben demnach eine primäre Partition (1) von ca. 20GB und eine erweiterte Partition von ca. 1,8TB Größe.

Schauen wir uns die Files etwas genauer an, vielleicht können wir später was mit der Ausgabe von 'file' anfangen...

        root@Microknoppix:/media/backup# file sda1image.img
        sda1image.img: x86 boot sector, Microsoft Windows XP Bootloader
        NTFS (german), code offset 0x52, OEM-ID "NTFS    ",
        sectors/cluster 8, reserved sectors 0, Media descriptor 0xf8,
        heads 255, hidden sectors 63, dos < 4.0 BootSector (0x80)
      
Dasselbe machen wir gleich mal mit dem Image der zweiten Partition:
        root@Microknoppix:/media/backup# file sda5image.img
        sda5image.img: x86 boot sector, Microsoft Windows XP Bootloader
        NTFS (german), code offset 0x52, OEM-ID "NTFS    ",
        sectors/cluster 8, reserved sectors 0, Media descriptor 0xf8,
        heads 255, hidden sectors 63, dos < 4.0 BootSector (0x80)
      

Soweit, so gut. Um die Größe der neuen Festplatten-Datei (im Folgenden HDD-Image genannt) zu bestimmen, müssen wir eine Datei haben, die mindestens so groß ist, dass sie beide Partitions-Images aufnehmen kann. Dann noch etwas Platz zur Sicherheit drauf rechnen und schon können wir eine HDD-Image-Container-Datei erstellen:

Zuerst rechnen wir also die Größe aller Partitionen zusammen:
Dazu lassen wir uns die Dateigrößen sinnvollerweise in GB anzeigen:

        root@Microknoppix:/media/backup# ls -l --block-size=G *.img
        -rw-r--r-- 1 root root   21G Sep 12 06:22 sda1image.img
        -rw-r--r-- 1 root root 1841G Sep 12 18:25 sda5image.img
      
OK, also 1841GB + 21GB = 1862GB. Wir rechnen noch ein bissel was drauf und entscheiden uns für eine Festplatten-Größe von runden 2TB. Nun erstellen wir die Container-Datei, dazu können wir getrost ein sparse-File erstellen: wir weisen dd an, keine Daten zu schreiben (count=0) aber das Datei-Ende auf die Grenze von 2TB (seek=2TB) zu setzen (dabei werden Datenblöcke in der Größe von bs gezählt, hier: bs=1 Byte)
        root@Microknoppix:/media/work# dd if=/dev/zero of=hdd.img bs=1 count=0 seek=2TB
      

Nun erstellen wir mittels fdisk eine neue Partitionstabelle innerhalb der Container-Datei:

        root@Microknoppix:/media/work# fdisk hdd.img
        Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
        Building a new DOS disklabel with disk identifier 0xd04eae36.
        Changes will remain in memory only, until you decide to write them.
        After that, of course, the previous span won't be recoverable.

        Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

        Command (m for help): p [enter]

        Disk hdd.img: 2000.0 GB, 2000000000000 bytes
        255 heads, 63 sectors/track, 243152 cylinders, total 3906250000 sectors
        Units = sectors of 1 * 512 = 512 bytes
        Sector size (logical/physical): 512 bytes / 512 bytes
        I/O size (minimum/optimal): 512 bytes / 512 bytes
        Disk identifier: 0xd04eae36

          Device Boot      Start         End      Blocks   Id  System
      
Hier ist nun die Angabe der units= von essentieller Bedeutung. Sie gibt an, in welcher Größen-Einheit wir die Partitionsgrenzen angeben werden.
Hier werden Blöcke von 1 × 512 Bytes verwendet.

Mit dieser Info ermitteln wir die Anzahl der 512-Byte-Blöcke, die wir für die Partitionen allokieren müssen:

        root@Microknoppix:/media/work# ls -al --block-size=512 ../backup/*.img
        
        -rw-r--r-- 1 root root   41945652 Sep 12 06:22 ../backup/sda1image.img
        -rw-r--r-- 1 root root 3860371242 Sep 12 18:25 ../backup/sda5image.img
      
Für die erste Partition brauchen wir also 41.945.652 512-Byte-Blöcke, für die andere werden 3.860.371.242 512-Byte-Blöcke benötigt. Mit diesen Werten werden wir nun die Partitionen erstellen. Wichtig ist, dass der letzte Sektor mit dem +-Präfix erstellt wird, was fdisk anweist diesen Wert auf den angegebenen Start-Sektor zu addieren:
      Command (m for help): n [enter]
      Partition type:
         p   primary (0 primary, 0 extended, 4 free)
         e   extended
      Select (default p): p [enter]
      Partition number (1-4, default 1): 1 [enter]
      First sector (2048-3906249999, default 2048): [enter]
      Using default value 2048
      Last sector, +sectors or +size{K,M,G} (2048-3906249999, default 3906249999): +41945652 [enter]
      

In unserem Fall sah die Partitionierung also so aus, dass innerhalb der zweiten erweiterten Partition eine fünfte lag. Dann erstellen wir die logische Partition 5 wie die erste:

        Command (m for help): n [enter]
        Partition type:
           p   primary (1 primary, 1 extended, 2 free)
           l   logical (numbered from 5)
        Select (default p): l [enter]
        Adding logical partition 5
        First sector (41949749-3906249999, default 41949749):[enter]
        Using default value 41949749
        Last sector, +sectors or +size{K,M,G} (41949749-3906249999, default 3906249999): +3860371242 [enter]
      
anschliessend betrachten wir das Ergebnis unserer Arbeit:
        Command (m for help): p [enter]
        
        Disk hdd.img: 2000.0 GB, 2000000000000 bytes
        255 heads, 63 sectors/track, 243152 cylinders, total 3906250000 sectors
        Units = sectors of 1 * 512 = 512 bytes
        Sector size (logical/physical): 512 bytes / 512 bytes
        I/O size (minimum/optimal): 512 bytes / 512 bytes
        Disk identifier: 0xd04eae36

          Device   Boot      Start         End      Blocks   Id  System
        hdd.img1            2048    41947700    20972826+  83  Linux
        hdd.img2        41947701  3906249999  1932151149+   5  Extended
        hdd.img5        41949749  2189433396  1073741824   83  Linux
      

Die Start-Sektoren werden für uns noch wichtig sein, denn wir müssen im nächsten Schritt die Partitions-Images an genau diese Positionen schreiben. Die Angabe von conv=notrunc weist dd an, die Ausgabe-Datei nach dem Schreiben der Daten nicht zu kürzen.

        root@Microknoppix:/media/work# dd if=../backup/sda1image.img of=hdd.img obs=512 seek=2048 conv=notrunc ibs=1M
      

Ein alternativer Weg ist die Benutzung eines loop-Devices. Dabei wird ein Loop-Device erstellt, welches an der Position des Partitionsbeginns in der HDD-Img ansetzt. Wir kopieren auf diese Weise mal die andere Partition. Der Parameter -o gibt das Start-Offset innerhalb der Container-Datei an:

        root@Microknoppix:/media/work# losetup -o $((512 * 41949749)) /dev/loop3 hdd.img
      
dann kann die Partition mit dd zurückgeschrieben werden:
        root@Microknoppix:/media/work# dd if=../backup/sda5image.img of=/dev/loop3
      
Nachdem nun das Loop-Device ausgehängt wurde, sollte der neue Container als Festplattendatei für eine virtuelle Maschine benutzt werden können.