NTFS disk recovery using Linux

Precis: recovering a broken NTFS disk using "dd" and "ntfsrestore" in Linux

February 2012

I had a machine running Windows XP, dual-boot with a small Linux partition, on a 30G IDE Maxtor drive. The drive went bad, and XP died.

I tried booting into the Linux partition using GRUB. This appeared to work, but the kernel did not completely boot. When I tried again, I got a GRUB prompt and was unable to select either operating system.

I booted a Linux rescue CD, and tried to mount the partitions without success. fdisk worked, and showed the NTFS, Linux and swap partitions. I tried fsck on the Linux partition, and got a number of I/O errors.

I took the disk and tried mounting it on two other computers, using an IDE/SATA/USB adaptor and native IDE interface. I could not see the partitions at all with fdisk.

The original computer had two drives, the failed IDE drive and a newer Western Digital SATA drive with a single NTFS partition with some user files. I decided to reinstall Windows on this SATA drive, leaving just one drive. Using the SATA/USB adaptor, I copied the user files onto another machine. I then repartitioned it to have two NTFS partitions and a Linux partition, and installed Fedora Core 9 (not the latest, or even still supported, but I had an installation DVD lying around).

My original plan was to reinstall Windows XP from scratch, then try to recover the data from the old disk somehow. Accordingly I installed XP on a 300G NTFS partition.

I then tried, on the original computer, to copy the failed NTFS partition to a Linux file with "dd". This proceeded OK but failed with an I/O error at block 2034296. I then tried to copy the partition starting at later blocks. It succeeded, starting at block 2035000, copying the rest of the partition. I now had two bits of an NTFS partition with a small gap. E.g.

dd if=/dev/sda1 of=sdb1  # aborted
dd if=/dev/sda1 of=sdb1a skip=2035000
I then made a file to fill the gap, and joined the pieces together. I could then mount the resulting file loopback:
dd if=/dev/zero count=704 of=zeroes
cat sdb1 zeroes sdb1a > XP0
mount -t ntfs -o ro,loop=/dev/loop1 XP0 /mnt/test
This worked; I could see the original system files. At this point I could have proceeded with the original idea to re-install XP from scratch and copy back the user files on C:. But that would mean re-installing all the software packages - OpenOffice, antivirus etc. etc., which I wanted to avoid.

I copied the image file back to an NTFS partition on the SATA drive, then used ntfsresize to resize it from 20G to the available 80G

dd if=XP0 of=/dev/sda4
ntfsresize /dev/sda4
Meanwhile, I had XP re-installed on the 300G partition, but the network did not work as the XP install disk did not have drivers for the motherboard chips, meaning I could not do updates or install any software. I probably have a CD somewhere, but it was easier to boot into Linux, download the motherboard driver package from the vendors website, and copy it to the NTFS partition. Then, in Windows, I installed the package and rebooted, now with networking and nVidia VGA. I was then able to see the 80G partition as the G: disk.

This looked promising - I had the complete original XP system on G:, and the new reinstalled XP on C:, booted from GRUB with the chainloader option as usual. I thought I should be able to boot G: - (hd0,4), I think in GRUB notation - with the chainloader, too. However, when I tried that, (hd0,1) came up instead. I think that a windows bootloader may have booted there, but then switched to the C: drive. The GRUB "info" documentation talks about problems with multiple Windows partitions, and suggests using the GRUB "hide" and "unhide" commands. I did not get this to work, however.

What did work, was editing the boot.ini file on the C: drive (/dev/sda1 partition) to boot a choice of operating systems, /dev/sda1 or /dev/sda4 (in Windows parlance, multi(0)disk(0)rdisk(0)partition(1) or ...partition(4). That allowed me to boot sda4 (which thinks it is C:, and sda1 is D:, or maybe E:).

I then copied the user files that had originally been on the SATA drive back onto what was now D:. D: still has a somewhat functional bootable XP system on it, taking up a couple of GB out of the 300, and I suspect that it is still involved in the boot process so that erasing it would not be a good idea.

Mission accomplished - computer working again with all the original system and user files, and more space in C: too!

Of course, it did not go quite that easily - I left out a few steps. E.g. I tried to copy the dead partition over the network using netcat on the Linux rescue disk. That worked, but was very slow, so I gave up and moved the SATA drive back to the same machine. And I tried to save time by installing a minimal Linux system without graphics, then tried to install X afterwards to get Firefox running, and got tangled in dependencies between updates and the install disk, so re-installed Linux from scratch. Unnecessary - I could easily have got the ASUS package on another computer and transferred it, and not bothered with updates or graphics as the Linux boot isn't normally used on that machine.