#include #include #include #include #include #include //#include #include /* need this for O_LARGEFILE */ #include #include #include #include "../config.h" extern char *optarg; extern int optind, opterr, optopt; #include "disk.h" #include "config.h" #include "main.h" unsigned long blocksize = 1024; unsigned long long fs_size = 0; int blocks_per_group = 0; int inodes_per_group = 0; int groups=0; unsigned long nr_blocks = 0; int blocks_per_inodetable=0; unsigned long nr_inodes = 0; /* number of FOUND inodes */ time_t NOW; int main(int argc, char * argv[]) { int i; long sb_off = -1; long sb_auto_find = -1; struct hd_geometry geo; struct stat st; NOW = time(NULL); puts (PACKAGE " " VERSION ", (c) 2000-2001 Marek Zelem, Milan Pikula\n"); #if I_CHECKED_CONFIG==0 #error "Check the src/config.h before compilation!" puts("You forgot to modify the file src/config.h before compilation!"); return -1; #endif while ((i = getopt(argc, argv, "hab:B:")) != EOF) switch (i) { case 'h': puts("Usage: e2salvage [-h] [[-a] [-b superblock]] [-B blocksize] device\n\n" " -h This help message\n" " -a Continuos search superblock if not found\n" " -b superblock Use alternative superblock\n" " -B blocksize Force blocksize when looking for superblock" ); return 0; case 'a': sb_auto_find = 0; break; case 'b': sb_off = atol(optarg); break; case 'B': blocksize = atol(optarg); break; case '?': case ':': return -1; } if (optind >= argc) { fprintf (stderr, "File or device name is required\n"); return -1; } if ((i = open(argv[optind], O_RDONLY|O_LARGEFILE)) == -1) { perror("open(O_RDONLY) failure"); return 1; } if (ioctl(i, HDIO_GETGEO, &geo) == 0) { fs_size = (unsigned long long) geo.heads * (unsigned long long) geo.sectors * (unsigned long long) geo.cylinders * 512ul; } else if (fstat64(i, &st) == 0) { fs_size = (unsigned long long) st.st_size; } else { perror("fstat() failure"); return 1; } if (fs_size == 0) { fprintf(stderr, "We don't rescue EMPTY files (yet;)\n"); return -1; } fprintf(stderr, "File `%s' successfully opened with filesize %lu bytes.\n", argv[optind], fs_size); if (sb_auto_find >= 0) sb_auto_find = sb_off; do { if (sb_auto_find >= 0 && sb_off == -1) sb_off = sb_auto_find++; if (sb_off != -1) if (!find_super(i, sb_off, blocksize)) { fprintf(stderr, "No superblock on offset %ld!\n", sb_off); sb_off = -1; } } while (sb_off == -1 && sb_auto_find >= 0); if ((sb_off == -1) && !find_super(i,-1, blocksize) && !find_super(i,8193, blocksize) && !find_super(i,16385, blocksize) ) { fprintf(stderr,"Can't find ext2 superblock\n"); return -1; } if (blocksize == 0) { fprintf(stderr, "Block size found in superblock is invalid. Falling back to 1024\n"); blocksize = 1024; } nr_blocks=fs_size/blocksize; printf ("we have found %d inodes\n", find_inodes(i)); printf ("we have found %d directory beginnings\n", find_dirs(i)); fill_blokmap(i); salvage_dir_blocks(); salvage_dir_inodes(); salvage_next_dir_blocks(); close(i); if (yesno("Write changes?")) { fprintf(stdout,"Writing changes...\n"); if ((i = open(argv[optind], O_RDWR|O_LARGEFILE)) == -1) { perror("open(O_RDWR) failure"); return 1; } write_super(i); write_inodes(i); write_dirs(i); fprintf(stdout,"Written.\n"); } return 0; }