Can the contents of a partition be recovered after partition table is overwritten?

I ran a command to make my external hdd bootable knowing that it was risky considering the command itself did not allow me to specify a partition to which to write. (In hindsight, I would now call this a stupid decision - but at the time, I tried this command:)

$ sudo dd if=/Users/MyUser/Downloads/Fedora-17-x86_64-Live-Desktop.iso \
> of=/dev/disk1 bs=1m

For which the output I received was:

645+0 records in
645+0 records out
676331520 bytes transferred in 98.578444 secs (6860846 bytes/sec)

I knew right away that it was fishy since /dev/disk1 was split into three partitions, all of which were hfs. Since it's next to impossible to find good information on making a bootable partition from an external USB device, I tried this in spite of the risks.

I did no further writing to my external HDD after this point, since now the only partition I see when I mount the drive is 'Fedora 17.'

What is the likelihood of recovering the files I had stored in my Backup partition? And how should I have done this in the first place?


NOTE: This is how my partitions were before I tried dd.

$ diskutil list
/dev/disk0
#:                       TYPE NAME                    SIZE       IDENTIFIER
0:      GUID_partition_scheme                        *160.0 GB   disk0
1:                        EFI                         209.7 MB   disk0s1
2:                  Apple_HFS Macintosh HD            159.7 GB   disk0s2
/dev/disk1
#:                       TYPE NAME                    SIZE       IDENTIFIER
0:      GUID_partition_scheme                        *1.0 TB     disk1
1:                        EFI                         209.7 MB   disk1s1
2:                  Apple_HFS Linux                   50.0 GB    disk1s2
3:                  Apple_HFS Backup                  500.0 GB   disk1s3
4:                  Apple_HFS Misc                    449.6 GB   disk1s4

Quick and Simple: Since it's a GPT disk you can run gpart recover /dev/disk1 to fix the table. You blew away the first ~700MB of the drive, so any partitions touching that area are gone too (more or less). The rest of the disk should be fine. I'm not sure if OSX comes with gpart, so you may need to download it somewhere.

The longer details: Concerning the partition(s) that were only partially overwritten, some of the files may be recoverable. The tools to do so are much more complicated and you'll be wanting to find someone who really knows what they're doing for this. If you're concerned with any of these files don't even try anything except unplugging the drive. Also, the overwritten data can probably be recovered by a data recovery service, but this would cost tens of thousands of dollars.

Also, if this was a MBR disk you'd be completely hosed unless you happen to know the exact size and offsets of all partitions. This information can be printed from fdisk, but it's best to simply not make mistakes like this.


According to your output, you copied 645MB to disk, which means the EFI and first ~440MB of the Linux partition were overwritten. Your Backup and Misc partitions were not modified, so the data in them can be recovered... if you can find them.

This may be relatively easy1. GUID partition tables are stored at both the beginning and end of the drive, so as long as OS X didn't overwrite the ones at the end, you can use them to find your data.

1 Relative to searching for HFS headers manually, the following commands are quite easy. However, this process is delicate, and if you accidentally write back the wrong data it could make things worse.


First, you need to determine the number of sectors on your drive. In Terminal, run diskutil info disk1 (or whatever your disk is currently connected as), and look for the Total Size section. It should list the exact number of sectors, and below that the sector size. I will call these values N and S, respectively.

Then, run these commands, replacing disk1, N and S as appropriate. This will copy the last block off of your drive to a file named partition_header.hex. Then it prints some data from that file.

sudo dd if=/dev/disk1 of=partition_header.hex bs=S skip=$((N-1)) count=1
od -cN 8 partition_header.hex
od -tx4 -N 8 -j 72 partition_header.hex
-d -tu4 -N 4 -j 84 partition_header.hex

The output for the three od commands should look similar to this:

0000000    E   F   I       P   A   R   T      
0000110          xxxxxxxx        yyyyyyyy        
0000124              ssss               

If the output from the first command does not match that first line, your partition tables have been overwritten. See my suggestions at the end. The values xxxxxxxx and yyyyyyyy are two hexadecimal numbers. They should be numbers and letters between a and f, and they tell you where the actual partition data is stored. The value ssss is a number which tells you the size of a partition entry. Run this command to get the partition data, replacing disk1, S, xxxxxxxx, yyyyyyyy, and ssss (note that the x after the 0 is literal). If ssss is more than 1/4 S, you may need to increase the count parameter, but this is unlikely.

sudo dd if=/dev/disk1 of=partition_entry.hex bs=S skip=$((0xyyyyyyyyxxxxxxxx)) count=1
od -tc -N 8 -j $((56+2*ssss)) partition_entry.hex
od -tc -N 8 -j $((56+3*ssss)) partition_entry.hex

The last two commands print the beginning of the names of the third and fourth partitions, with each letter followed by \0 (due to the encoding on disk). If your partition table is still valid, these should be "Back" and "Misc". If so, it is time to get the entire partition table and make the necessary modifications to store it at the other end of the drive. Run these two commands to get the proper header LBAs and total number of partition entries:

od -tx1 -N 16 -j 24 partition_header.hex
od -td4 -N 4 -j 80 partition_header.hex

The first command returns aa bb cc dd ee ff gg hh ii jj kk ll mm oo pp qq. Most likely, ii is 01 and jj through qq are 00. The second command returns nnnn, most likely 128. Now we can read the entire partition table, instead of just the first few. Run this command, making the proper substitutions:

sudo dd if=/dev/disk1 of=partition_entry.hex bs=ssss skip=$((0xyyyyyyyyxxxxxxxx * S / ssss)) count=nnnn

Now we need to make some changes to the header since the data will be stored at a different location.

printf '\xii\xjj\xkk\xll\xmm\xoo\xpp\xqq\xaa\xbb\xcc\xdd\xee\xff\xgg\xhh' | dd of=partition_header.hex bs=8 seek=3 count=2 conv=notrunc
printf '\x02\x00\x00\x00\x00\x00\x00\x00' | dd of=partition_header.hex bs=8 seek=9 count=1 conv=notrunc

The first command swaps the current header and other header addresses. Sorry about replacing each byte separately, but I didn't know of an easier way. The second command writes the new address of the entry data. The value 2 I used is assuming that ii was 1 and jj through qq were 0. If they have other values, just increase the whole thing by one and use that instead. The only thing we need now is the right MBR, which is not on your disk since it isn't part of the partition table. Luckily, you can use the one from your internal drive, so you need to copy that into a file.

sudo dd if=/dev/disk0 of=drive_mbr.hex bs=512 count=1

Now that we have all of the data, we can write it out. First, unmount the Fedora volume if it is mounted.

diskutil unmountDisk disk1

Then, copy each piece to the beginning of the drive. Be sure to make the proper substitutions in these commands, writing to the wrong disk would not be good.

sudo dd if=partition_entry.hex of=/dev/disk1 bs=S seek=2 count=nnnn
sudo dd if=partition_header.hex of=/dev/disk1 bs=S seek=1 count=1
sudo dd if=drive_mbr.hex of=/dev/disk1 bs=512 count=1

The seek values are based on the assumption that ii through qq matched the likely values. If they do not, use $((0xqqppoommllkkjjii)) for the second command and $((0xqqppoommllkkjjii+1)) for the first.

After you perform these commands, OS X will probably reload the drive automatically and load the partitions. If it doesn't, just disconnect and reconnect it. The Linux partition will most likely fail to mount, since its header was overwritten, but the other two will hopefully work fine. Even so, I would still suggest copying your data off of the drive and reformatting it, or at the very least copying the EFI partition data from your internal drive over.


If your partition table is corrupted:

The option which is most likely to be successful is to manually search for the HFS headers at the beginning of your backup partition. The format of a HFS volume is described here. Basically, you will need to calculate the approximate offset of the partition into the drive using the partition map you have, then search each sector in the area looking for the volume header. You could probably write a script to search for you.

Another option would be to use file recovery software. I don't know what software is available which would handle this situation, so there's not a lot I can say about it.


Having done this myself:

# dd if=freebsd.img of=/dev/hda

at some point in the past (oops! I meant fd0!) I can pretty much guarantee that the contents of disk1s1 and disk1s2 are trashed.

But disk1s3 and disk1s4 will be just fine! You just need to figure out what the partition table is supposed to be and correct it.

I suggest recovering from the GPT backup at the end of the disk or just searching for the filesystem markers to determine where they are supposed to be.