Saving files from a (potentially) failing hard drive
I recently helped a friend whose laptop had taken some physical damage, and the laptop’s hard drive seemed to have some issues after that.
This was a classic situation with important files on the disk and no backups. The disk included OS installation, so booting from it and copying files to an external device seemed a bit too risky. I then promised to try to back up the files carefully as it seemed that the disk and its content could be lost soon.
Probe an image, not the disk
Like said, the state of the disk I had to work with was potentially unstable, so I wanted to minimize the need to work direct with it.
First, I removed the disk from my friend’s laptop and connected it to my laptop using a USB-SATA adapter. Then I took an image of the whole disk using GNU ddrescue.
sudo ddrescue /dev/sdb /srv/disk_image.raw /srv/log_file --try-again --force --verbose
To be honest, I’m not sure if these ddrescue options were optimal for this scenario, but at least I was able to copy the whole drive. See ddrescue’s man page to see different options.
Next, I created a copy of the image to make sure that I don’t need to try to create a new image if I screw something up.
sudo dd if=/srv/disk_image.raw of=/srv/disk_image.raw.original
Find and mount the partition(s)
Now I had to find the partition where the needed data is, so I can mount it from the image, and try to copy all files in it.
Some command outputs in the below sections are not from the actual image I was working with, but as I’m writing this post afterward, I created a small dummy file to demonstrate these parts of the process.
Find a partition
Listing partitions with fdisk -l <image file>
:
$ sudo fdisk -l disk_image.raw
Disk disk_image.raw: 1000 MiB, 1048576000 bytes, 2048000 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
Disklabel type: dos
Disk identifier: 0x65a4907d
Device Boot Start End Sectors Size Id Type
disk_image.raw1 2048 817151 815104 398M 7 HPFS/NTFS/exFAT
disk_image.raw2 817152 2047999 1230848 601M 7 HPFS/NTFS/exFAT
Sometimes it might be clear which partition is the “target” and sometimes not. For this demonstration, with this dummy image file, let’s just say that I knew that the second partition is the one which content I needed to access.
With the above information, it’s possible to calculate the start sector of the targeted partition: 512*817152=418381824
.
Mounting partitions from the disk image
The disk image file needs to be attached to a loop device, so it can be mounted as a block device. losetup -a
can be used to check what loop devices already exist. mknod
can be used to create a new loop device.
sudo mknod -m640 /dev/loop9 b 7 8
sudo losetup -o 418381824 /dev/loop9 disk_image.raw
sudo mount /dev/loop9 /mnt/
Notice that -o 418381824
is the partition’s start sector which I calculated previously.
Now as I have the partition mounted I can just regularly copy files from the mountpoint with some tool like rsync
:
rsync -vr /mnt/ /dest/path
Some pointers
Even though I used a dummy image file in this post, the case with my friend’s disk worked out the same way that there eventually were no issues while working with the disk and the image. If you have a case where the situation is not this good then you may want to check, for example, TestDisk from CGSecurity.
When creating disk images, remember to verify that your destination has enough space for the image.