How to resize an image created using dd which contains a block-by-block copy of the Mac drive

disk-utilityhard drivehfs+

I created a copy of a working (but getting a few disk errors) 1TB spinning disk drive using dd. I can mount the image (hdiutil attach or just double click in Finder) no problem and see the files on the main HFS+ volume. However, I don't see the other partitions which I know are there (EFI, Recovery HD). I know these are there because if I restore the image directly to a physical drive, they are there.

However, I would like to restore this image to a 480GB SSD (smaller), so I need to shrink the main/large HFS+ partition of the image. There is plenty of free space in the partition (700GB) so this should be feasible.

I have tried converting the image to a read-write image (hdiutil convert -format UDRW) or a sparse bundle (hdiutil convert -format UDSB – results in a 200GB file).

The read-write image won't resize:
hdiutil: resize request is below minimum size allowed.

Running hdiutil compact on the sparse bundle won't shrink it:
Reclaimed 0 bytes out of 796.9 GB possible.

What is the correct way to accomplish resizing the main/large HFS+ partition in the full disk image?

Best Answer

In my opinion this may be possible but it's not effective because to accomplish this you would have to extract and shrink one part of the dd raw image and then reassemble all three parts. Additionally you have to manipulate the gpt partition table inside the reassembled raw dd image by hex-editing it. Then you have to dd back the image.

Instead do the following which is significantly less time consuming and probably less error-prone:

  • Partition your new disk with 3 partitions: EFI, main system volume and a Recovery HD partition
  • Since EFI and recovery partition have fixed sizes and defined start blocks you can simply dd the EFI and the Recovery HD in your dd raw image to the respective partitions of your new SSD
  • To copy the content of the old main volume, mount the dd raw image and rsync the content to the new main volume.

Here I assume you have an external disk with a full OS X (El Capitan) to prepare the SSD. All device names/identifiers or sizes are just examples and may differ from your actual environment/results.

Preparing your new SSD:

  • Open Disk Utility and erase the new disk (Name: SSD/Format: OS X Extended (Journaled)/Scheme: GUID Partition table)
  • Open Terminal and enter diskutil list. The result should be (the sizes may slightly differ from yours):

    /dev/disk0 (internal, physical):
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:      GUID_partition_scheme                        *480.0 GB   disk0
       1:                        EFI EFI                     209.7 MB   disk0s1
       2:                  Apple_HFS SSD                     479.6 GB   disk0s2
    /dev/disk1...
    
  • In Terminal enter sudo gpt -r show disk0. The result should be (the sizes may slightly differ from yours):

          start       size  index  contents
              0          1         PMBR
              1          1         Pri GPT header
              2         32         Pri GPT table
             34          6         
             40     409600      1  GPT part - C12A7328-F81F-11D2-BA4B-00A0C93EC93B
         409640  936755120      2  GPT part - 48465300-0000-11AA-AA11-00306543ECAC
      937164760     262151         
      937426911         32         Sec GPT table
      937426943          1         Sec GPT header
    
  • Now unmount disk0 and remove the second partition:

    diskutil umountDisk disk0
    sudo gpt remove -i 2 disk0
    
  • Add the recovery partition. The recovery partition always has the size 1269536 blocks and starts at total size of the disk in blocks - 1269576 blocks (in my example that's: 937426944 - 1269576 = 936157368)

    sudo gpt add -i 3 -b 936157368 -s 1269536 -t 426F6F74-0000-11AA-AA11-00306543ECAC disk0
    
  • Enter sudo gpt -r show disk0 again to show the new partition:

          start       size  index  contents
              0          1         PMBR
              1          1         Pri GPT header
              2         32         Pri GPT table
             34          6         
             40     409600      1  GPT part - C12A7328-F81F-11D2-BA4B-00A0C93EC93B
         409640  935747728         
      936157368    1269536      3  GPT part - 426F6F74-0000-11AA-AA11-00306543ECAC
      937426904          7         
      937426911         32         Sec GPT table
      937426943          1         Sec GPT header
    
  • In the empty space between partition i=1 and i=3 add a new partition. The start block and the size are given by the data found above:

    sudo gpt add -i 2 -b 409640 -s 935747728 -t 48465300-0000-11AA-AA11-00306543ECAC disk0
    
  • Unmount disk0 and format the new volume:

    diskutil umountDisk disk0
    sudo newfs_hfs -J -v "SSD" /dev/disk0s2
    

Restoring your data:

  • Mount your raw disk image by double-clicking it.
  • Enter diskutil list. You should see a new entry similar to this one:

    /dev/disk0 (internal, physical):
    ...
    /dev/disk3 (disk image):
       #:                       TYPE NAME                    SIZE       IDENTIFIER
       0:      GUID_partition_scheme                        +1.0 TB     disk3
       1:                        EFI EFI                     209.7 MB   disk3s1
       2:                  Apple_HFS Macintosh HD            1.0 TB     disk3s2
       3:                 Apple_Boot Recovery HD             650.0 MB   disk3s3
    
  • dd the EFI and the Recovery HD from the image to the SSD:

    sudo dd if=/dev/disk3s1 of=/dev/disk0s1 bs=4096
    diskutil umountDisk disk0
    sudo dd if=/dev/disk3s3 of=/dev/disk0s3 bs=4096
    
  • mount the main volume of the SSD:

    diskutil mount disk0s2
    
  • rsync the content of the main volume of the disk image (which should be visible on your desktop in contrary to the EFI/Recovery HD partitions) to the main SSD volume:

    sudo rsync -a /Volumes/Volume_name_of_Diskimage/ /Volumes/SSD
    

This is a very basic rsync command example. You may refine the rsync command (options/exclusions) according to this or this linked scripts.


Please check all device names in the various command containing dd or gptthoroughly or you will delete or overwrite important partitions/data unwantedly.