-
-
Save countingpine/0fd04b99058ebc910fefc910606ae6d0 to your computer and use it in GitHub Desktop.
/* ext2scan: | |
* Scans an input stream, sector by sector, for something that looks like an ext{2,3,4} partition. | |
* It does this by looking for a magic WORD, 0xEF53, at a known offset into the sector. | |
* For random data, this will occur by chance around once per 32MB of data, so we also | |
* check whether the first two sectors are all zeros, which is commonly true for ext partitions. | |
* | |
* Compile with: | |
* gcc ./ext2scan.c -o ./ext2scan | |
* | |
* Example usage: | |
* dd if=/dev/sda [skip=$START_SECTOR] | ./ext2scan [$START_SECTOR] | |
* | |
* Or for more speed, use a larger block size: | |
* dd if=/dev/sda bs=1M [iflag=skip_bytes skip=$(($START_SECTOR*512))] | ./ext2scan [$START_SECTOR] | |
* | |
* References: | |
* - http://unix.stackexchange.com/questions/103919/how-do-i-find-the-offset-of-an-ext4-filesystem | |
* - http://uranus.chrysocome.net/explore2fs/es2fs.htm | |
*/ | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <string.h> | |
int main(int arg_c, char **arg_v) { | |
unsigned char const MAGIC[2] = {0x53, 0xef}; | |
unsigned char const ZEROS[512] = {0}; | |
char buf[4][512]; | |
int empty1, empty2; | |
long long int sector = 0; | |
long long int offset = 0; | |
if (arg_c == 2) sscanf(arg_v[1], "%lld", &offset); | |
while (read(STDIN_FILENO, buf[sector&3], 512) > 0) { | |
if (!memcmp(buf[sector&3] + 0x38, MAGIC, 2)) { | |
printf("Found a possible ext partition at sector %lld", offset+sector-2); | |
empty1 = !memcmp(buf[(sector-2)&3], ZEROS, 512); | |
empty2 = !memcmp(buf[(sector-1)&3], ZEROS, 512); | |
if (empty1 && empty2) printf(" (first two sectors are empty :)\n"); | |
else if (empty1) printf(" (first sector only is empty)\n"); | |
else if (empty2) printf(" (second sector only is empty)\n"); | |
else printf(" (first two sectors are non-empty)\n"); | |
} | |
sector++; | |
} | |
} |
This helped me so much! I had an MBR partition table and a couple of NTFS partitions created over my originally GPT + ext4 hard drive, so I had to find out the original first sector, and no valid superblock could be found by fsck.ext
when I tried probable values (like the default suggested by gdisk
, 1024, 2048, etc.).
Running this gave me a lot of potential backup superblocks to search through, so I had to read up on ext4 superblocks to narrow this set down.
I ended up modifying this to check that superblock creator OS is Linux. This gave me, in just a few seconds of scanning, a bunch of backup superblocks backups exactly (no false positives whatsoever). I derived the proper first sector of the file system from that, created a partition starting at this sector using gdisk
, got a proper partition size from dumpe2fs -o superblock=XXX
, recreated the partition with gdisk
using the discovered partition length, and could successfully run fsck.ext4
on it afterwards. My data is back! (Well, most of it).
Here is the forked version I used https://gist.github.com/futpib/cfb04a9843b8f176d5c2ed3364fc8527. Hope it helps someone! Note that it prints superblock backup offsets in 4096 byte sectors, not in 512 byte sectors like the original.
@futpib What does "gdisk
ed it" mean? (more comments at your modified gist, thanks!)
@jsarenik I edited my comment. Hope it helps.
@countingpine Thank you so much. This saved me a ton of time tonight!