Recently I had the task of recovering files from a 1TB hard disk in an iMac that was on its last legs – bad sectors, clicking and would not boot. Many passes, especially in reverse, of ddrescue saved all but 8 sectors.
(As an aside, BTRFS is absolutely fantastic for storing ddrescue images – the transparent compression makes things considerably smaller, especially if there’s lots of free space.)
Recovering the files from the ddrescue image was simple enough:
losetup --partscan /dev/loop0 myimage.img (lsblk) mount /dev/loop0p1 /mnt
But I wanted to take it one step further and breathe life back into the iMac. I had two initial plans:
Plan A: Shrink the partition using the only free software solution I could find – gparted – then dd everything to the SSD. Insanely the CLI equivalent (parted) does not supporting partition resizing. Passing /dev/loop0 as an argument allowed it to function against the image directly. I used a BTRFS snapshot to ensure I had a copy of the original image.
Plan B: Fresh install macOS (far harder than it should be, this workaround is a godsend) and rsync files across.
Neither of these inital plans seemed great – plan A was unlikely to boot as some key sectors were hosed, and plan B isn’t the best end result.
It was halfway through resizing the partition for plan A that I came up with plan C: Migration Assistant. I had to come up with a way of getting the disk image exposed to this. It was then I learned that a .dmg is just a raw dd image at heart. The only challenge that remained was how to transport the image to the iMac – didn’t have any large external disks handy. It was then I discovered a crazy feature of hdiutil: it can mount .dmgs over http! A quick installation of an http server later and this was all I needed to kick migration assistant into life:
hdiutil attach http://mybox/myimage.img
Too easy to be true! Thank you to whatever Apple kernel developer added http support for image mounting.
(Probably possible to do over smb, and faster/easier, but I couldn’t get the iMac to connect to a smb share, some nonsense error about smb protocol not being supported)