diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/block.c | 3 | ||||
-rw-r--r-- | src/block.h | 1 | ||||
-rw-r--r-- | src/ext4magic.8 | 32 | ||||
-rw-r--r-- | src/ext4magic.c | 81 | ||||
-rw-r--r-- | src/ext4magic.h | 1 | ||||
-rw-r--r-- | src/file_type.c | 7 | ||||
-rw-r--r-- | src/hard_link_stack.c | 6 | ||||
-rw-r--r-- | src/imap_search.c | 2 | ||||
-rw-r--r-- | src/inode.c | 6 | ||||
-rw-r--r-- | src/inode.h | 6 | ||||
-rw-r--r-- | src/journal.c | 4 | ||||
-rw-r--r-- | src/journal.h | 4 | ||||
-rw-r--r-- | src/lookup_local.c | 5 | ||||
-rw-r--r-- | src/magic.h | 4 | ||||
-rw-r--r-- | src/magic_block_scan.c | 228 | ||||
-rw-r--r-- | src/recover.c | 29 | ||||
-rw-r--r-- | src/util.c | 85 | ||||
-rw-r--r-- | src/util.h | 10 |
18 files changed, 354 insertions, 160 deletions
diff --git a/src/block.c b/src/block.c index b1db943..66bad23 100644 --- a/src/block.c +++ b/src/block.c @@ -27,7 +27,6 @@ #endif -//#include <ext2fs/ext2fs.h> #include "ext2fsP.h" #include "block.h" #include "journal.h" @@ -56,7 +55,7 @@ struct block_context { //#ifdef BLOCK_FLAG_READ_ONLY -#include <ext2fs/ext3_extents.h> +//#include <ext2fs/ext3_extents.h> struct extent_path { char *buf; int entries; diff --git a/src/block.h b/src/block.h index 9145664..97098c9 100644 --- a/src/block.h +++ b/src/block.h @@ -1,6 +1,5 @@ #ifndef BLOCK_H #define BLOCK_H - #include <ext2fs/ext2fs.h> diff --git a/src/ext4magic.8 b/src/ext4magic.8 index f9b05da..076f1a0 100644 --- a/src/ext4magic.8 +++ b/src/ext4magic.8 @@ -1,7 +1,13 @@ -.TH ext4magic 8 "Jul 2010" "version 0.1.3" "Administrations Tool" +.TH ext4magic 8 "Sep 2010" "version 0.2.0" "Administrations Tool" .SH NAME ext4magic \- allows to recover deleted files on ext3/4 filesystems .SH SYNOPSIS +.B ext4magic \-M +[\-j <journal_file>] [\-d <target_dir>] <filesystem> + +.B ext4magic \-m +[\-j <journal_file>] [\-d <target_dir>] <filesystem> + .B ext4magic [\-S|\-J|\-H|\-V|\-T] [\-x] [\-j <journal_file>] [\-B n|\-I n|\-f <file_name>|\-i <input_list>] [\-t n|[[\-a n][\-b n]]] [\-d <target_dir>] [\-R|\-r|\-L|\-l] [\-Q] <filesystem> @@ -30,6 +36,24 @@ Direct use of the Journal of a currently read-write open filesystem produce read .SH OPTIONS .B +Magic Options: (new and experimental) +These options are for a mulit-stage recover especially for file restore after delete the file system. These functions are currently only available for ext3. +Umount the file system directly after an accidentally destroy and use these options with a copy of this file system. These functions are not adequately tested in this version and can include a lot of bugs. + +.TP +.B +\-M +Try to recover all files. This option should be used if the entire Filessytem was deleted. +.TP +.B +\-m +Try to recover only all deleted files. Use this option with a partially deleted Filesystem. + + + + +.PP +.B Information Options: These options generate generic status information from the filesystem and the Journal. @@ -488,6 +512,12 @@ try to restore all files deleted last 24 hours. Write in directory "./RECOVERDIR .B + # ext4magic /dev/sda3 -M -d /home/recover + +try the new experimental multi-stage recover of all files after the filesystem is deleted with a "rm -rf *" . Write the files to "/home/recover". + + +.B # ext4magic /dev/sda3 -RQ -f user1/Dokuments -a 1274210280 -b 1274211280 -d /mnt/testrecover try to restore the directory tree "user1/Dokuments/". The "-b" timestamp you must set just before deleting files, the "-a" timestamp prevents found old file versions. This will only work well, if you've there created or deleted files bevor the "-b" timestamp. Write in directory "/mnt/testrecover/" diff --git a/src/ext4magic.c b/src/ext4magic.c index 34b3c24..50029c0 100644 --- a/src/ext4magic.c +++ b/src/ext4magic.c @@ -247,7 +247,7 @@ errout: //subfunction for main void print_modus_error(){ - char message0[] = "Warning: only input of one modus allowed [ -R | -r | -L | -l | -H ]\n"; + char message0[] = "Invalide parameter : only input of one modus allowed [ -M | -m | -R | -r | -L | -l | -H ]\n"; fprintf(stderr,"%s",message0); } @@ -258,8 +258,11 @@ int main(int argc, char *argv[]){ char* progname = argv[0]; int retval, exitval; char defaultdir[] = "RECOVERDIR" ; +time_t help_time; //FIXME : usage is not correct -const char *usage = "ext4magic [-S|-J|-H|-V|-T] [-x] [-j <journal_file>] [-B n|-I n|-f <file_name>|-i <input_list>] [-t n|[[-a n][-b n]]] [-d <target_dir>] [-R|-r|-L|-l] [-Q] <filesystem>"; +const char *usage = "\next4magic -M [-j <journal_file>] [-d <target_dir>] <filesystem> \n\ +ext4magic -m [-j <journal_file>] [-d <target_dir>] <filesystem> \n\ +ext4magic [-S|-J|-H|-V|-T] [-x] [-j <journal_file>] [-B n|-I n|-f <file_name>|-i <input_list>] [-t n|[[-a n][-b n]]] [-d <target_dir>] [-R|-r|-L|-l] [-Q] <filesystem>"; int c; int open_flags = EXT2_FLAG_SOFTSUPP_FEATURES; int exit_status = 0 ; @@ -293,21 +296,43 @@ if ( argc < 3 ) return EXIT_FAILURE; } - { + // set default Time from "now -1 day" to "now" - time_t help_time; - time( &help_time ); - t_before = (__u32) help_time; - t_after = t_before - 86400 ; - } + +time( &help_time ); +t_before = (__u32) help_time; +t_after = t_before - 86400 ; + // decode arguments -while ((c = getopt (argc, argv, "TJRLlrQSxi:t:j:f:Vd:B:b:a:I:H")) != EOF) { +while ((c = getopt (argc, argv, "TJRMLlmrQSxi:t:j:f:Vd:B:b:a:I:H")) != EOF) { switch (c) { case 'M': //not active, still in development + if(mode & RECOVER_INODE){ + print_modus_error(); + exitval = EXIT_FAILURE ; + goto errout; + } + mode |= RECOVER_INODE; + mode |= READ_JOURNAL; + recovermodus = RECOV_ALL ; + magicscan = 1; + break; + + case 'm': + //not active, still in development + if(mode & RECOVER_INODE){ + print_modus_error(); + exitval = EXIT_FAILURE ; + goto errout; + } + mode |= RECOVER_INODE; + mode |= READ_JOURNAL; + recovermodus = RECOV_DEL ; magicscan = 1; break; + case 'S': mode |= PRINT_SUPERBLOCK ; break; @@ -315,7 +340,8 @@ while ((c = getopt (argc, argv, "TJRLlrQSxi:t:j:f:Vd:B:b:a:I:H")) != EOF) { case 'H': if(mode & RECOVER_INODE){ print_modus_error(); - break; + exitval = EXIT_FAILURE ; + goto errout; } mode |= RECOVER_INODE; mode |= PRINT_HISTOGRAM ; @@ -324,7 +350,8 @@ while ((c = getopt (argc, argv, "TJRLlrQSxi:t:j:f:Vd:B:b:a:I:H")) != EOF) { case 'R': if(mode & RECOVER_INODE){ print_modus_error(); - break; + exitval = EXIT_FAILURE ; + goto errout; } mode |= RECOVER_INODE; mode |= READ_JOURNAL; @@ -334,7 +361,8 @@ while ((c = getopt (argc, argv, "TJRLlrQSxi:t:j:f:Vd:B:b:a:I:H")) != EOF) { case 'r': if(mode & RECOVER_INODE){ print_modus_error(); - break; + exitval = EXIT_FAILURE ; + goto errout; } mode |= RECOVER_INODE; mode |= READ_JOURNAL; @@ -344,7 +372,8 @@ while ((c = getopt (argc, argv, "TJRLlrQSxi:t:j:f:Vd:B:b:a:I:H")) != EOF) { case 'L': if(mode & RECOVER_INODE){ print_modus_error(); - break; + exitval = EXIT_FAILURE ; + goto errout; } mode |= RECOVER_INODE; mode |= READ_JOURNAL; @@ -354,7 +383,8 @@ while ((c = getopt (argc, argv, "TJRLlrQSxi:t:j:f:Vd:B:b:a:I:H")) != EOF) { case 'l': if(mode & RECOVER_INODE){ print_modus_error(); - break; + exitval = EXIT_FAILURE ; + goto errout; } mode |= RECOVER_INODE; mode |= READ_JOURNAL; @@ -572,8 +602,16 @@ while ((c = getopt (argc, argv, "TJRLlrQSxi:t:j:f:Vd:B:b:a:I:H")) != EOF) { // check any parameter an options // check time option if (magicscan){ - printf("Warning: Activate magic scan, may be some command line options ignored\n"); + printf("Warning: Activate magic scan function, may be some command line options ignored\n"); + mode &= MASK_MAGIC_SCAN; + inode_nr = EXT2_ROOT_INO; + t_before = (__u32) help_time; + if ((!(mode & INPUT_TIME)) || (t_after == t_before - 86400)){ + t_after = get_last_delete_time(current_fs); + mode |= INPUT_TIME; } +} + if (mode & INPUT_TIME){ @@ -888,7 +926,10 @@ if ((mode & COMMAND_INODE) && (mode & RECOVER_INODE)) // I think imap is no longer needed from here, free the allocated memory ext2fs_free_inode_bitmap(imap); imap = NULL; - magic_block_scan(des_dir, t_after); + if (!(current_fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS)) + magic_block_scan3(des_dir, t_after); + else + printf("The MAGIC Funktion is currently only for ext3 filesystems available\n"); } clear_dir_list(dir); } @@ -953,9 +994,9 @@ exitval = EXIT_SUCCESS; errout: if (current_fs) { -//FIXME in development -/* if (d_bmap){ - struct ext2fs_struct_loc_generic_bitmap *d_bmap; +/*//FIXME in development + if (bmap){ + struct ext2fs_struct_loc_generic_bitmap *d_bmap = bmap ; blockhex(stdout,(void*)d_bmap->bitmap,0,current_fs->super->s_blocks_count >> 3); }*/ if (imap) ext2fs_free_inode_bitmap(imap); @@ -970,6 +1011,8 @@ errout: } if (pathname) free(pathname); clear_link_stack(); + if (! exitval) + printf("ext4magic : EXIT_SUCCESS\n"); return exitval; } //------------------------------------------------------------------------------------------------------------------------------- diff --git a/src/ext4magic.h b/src/ext4magic.h index 31442f4..3ec5e4d 100644 --- a/src/ext4magic.h +++ b/src/ext4magic.h @@ -35,6 +35,7 @@ #define RECOVER_INODE 0x2000 #define RECOVER_LIST 0x4000 +#define MASK_MAGIC_SCAN 0x3100 // journal status flags #define JOURNAL_OPEN 0 #define JOURNAL_CLOSE 1 diff --git a/src/file_type.c b/src/file_type.c index 1f880f4..1e02cb9 100644 --- a/src/file_type.c +++ b/src/file_type.c @@ -34,9 +34,12 @@ #define ext4magic_be64_to_cpu(x) ext2fs_swab64((x)) #endif -extern ext2_filsys current_fs ; +//#define DEBUG_MAGIC_SCAN + +extern ext2_filsys current_fs ; +// index of the files corresponding magic result strings int ident_file(struct found_data_t *new, __u32 *scan, char *magic_buf, char *buf){ //Please do not modify the following lines. @@ -121,7 +124,9 @@ int ident_file(struct found_data_t *new, __u32 *scan, char *magic_buf, char *buf p_search++; } if(!flag) minor=255; +#ifdef DEBUG_MAGIC_SCAN printf("major : %d minor : %d\n", major,minor); +#endif *scan = (major <<8)| minor; return 1; } diff --git a/src/hard_link_stack.c b/src/hard_link_stack.c index b7df7ed..fde1609 100644 --- a/src/hard_link_stack.c +++ b/src/hard_link_stack.c @@ -61,7 +61,7 @@ errout: } - +// subfunction for check_find_dir() use in stage 2 of magical recover int rename_hardlink_path(char *old, char *neu){ char *newname; char *endname; @@ -81,7 +81,6 @@ int rename_hardlink_path(char *old, char *neu){ //#ifdef DEBUG fprintf(stderr,"HL-DB change %s -> %s\n",old,neu); //#endif - } head.pointer = head.pointer->next; } @@ -108,6 +107,7 @@ char* check_link_stack(ext2_ino_t inode_nr, __u32 generation){ } + static void del_link_stack(struct link_entry* entry){ if(entry->name) free(entry->name); @@ -127,6 +127,7 @@ static void del_link_stack(struct link_entry* entry){ } + int match_link_stack(ext2_ino_t inode_nr, __u32 generation){ int retval = 1; if ((head.pointer->inode_nr == inode_nr) && (head.pointer->generation == generation)){ @@ -139,6 +140,7 @@ return retval; } + void clear_link_stack(){ int d_count = 0 ; diff --git a/src/imap_search.c b/src/imap_search.c index b86ebb9..421ec9d 100644 --- a/src/imap_search.c +++ b/src/imap_search.c @@ -31,7 +31,6 @@ extern ext2_filsys current_fs; - // search inode by use imap (step1: flag 1 = only directory ; step2: flag 0 = only file) static void search_imap_inode(char* des_dir, __u32 t_after, __u32 t_before, int flag) { @@ -204,4 +203,3 @@ void imap_search(char* des_dir, __u32 t_after, __u32 t_before){ return; } - diff --git a/src/inode.c b/src/inode.c index 87c07ba..bd098aa 100644 --- a/src/inode.c +++ b/src/inode.c @@ -896,7 +896,7 @@ return retval; - +//create a new inode struct ext2_inode_large* new_inode(){ struct ext2_inode_large *inode; __u32 a_time; @@ -919,7 +919,7 @@ return inode; } - +//add a block to inode int inode_add_block(struct ext2_inode_large* inode , blk_t blk , __u32 size) { int i = 0 ; unsigned long long i_size; @@ -949,7 +949,7 @@ return 1; } - +//add the ext3 indirect Blocks to the inode blk_t inode_add_meta_block(struct ext2_inode_large* inode , blk_t blk, blk_t *last, char *buf ){ blk_t b_blk,block_count, next; blk_t count=0; diff --git a/src/inode.h b/src/inode.h index e3406f4..bcc0089 100644 --- a/src/inode.h +++ b/src/inode.h @@ -66,8 +66,10 @@ int read_journal_inode( ext2_ino_t, struct ext2_inode*, __u32);// get the first int read_time_match_inode( ext2_ino_t, struct ext2_inode*, __u32);// get the first Journal Inode by time_stamp struct ring_buf* get_j_inode_list(struct ext2_super_block*, ext2_ino_t);//fill all inode found in the Journal in the inode-ringbuffer -struct ext2_inode_large* new_inode(); -int inode_add_block(struct ext2_inode_large* , blk_t , __u32); +//functions for the magic scanner +struct ext2_inode_large* new_inode(); //create a new inode +int inode_add_block(struct ext2_inode_large* , blk_t , __u32); //add a block to inode +blk_t inode_add_meta_block(struct ext2_inode_large*, blk_t, blk_t*, char* ); //add the ext3 indirect Blocks to the inode #endif diff --git a/src/journal.c b/src/journal.c index 07006fc..e26d66b 100644 --- a/src/journal.c +++ b/src/journal.c @@ -834,7 +834,7 @@ return sum; -//create and init the the journal block bitmap +//create and init the journal block bitmap //return the count of all blockbitmap copies or 0 int init_block_bitmap_list(ext2fs_block_bitmap *d_bmap, __u32 t_after){ __u32 t; @@ -906,8 +906,6 @@ int next_block_bitmap(ext2fs_block_bitmap d_bmap){ if (jbbm.pointer->transaction < jbbm.first_trans) return 0; -// printf(" Transaction: %u ; Minimum ist %u \n", jbbm.pointer->transaction,jbbm.first_trans); - fs_bitmap = (struct ext2fs_struct_loc_generic_bitmap*) current_fs->block_map; df_bitmap = (struct ext2fs_struct_loc_generic_bitmap*) d_bmap; ext2fs_clear_block_bitmap(d_bmap); diff --git a/src/journal.h b/src/journal.h index 9a05fbc..3f3648a 100644 --- a/src/journal.h +++ b/src/journal.h @@ -29,6 +29,7 @@ typedef struct journal_descriptor_tag_s __u32 transaction; /* Transaction Sequence*/ } journal_descriptor_tag_t; + //struct for cache the block bitmap data typedef struct journal_bitmap_tag_s { @@ -38,6 +39,8 @@ typedef struct journal_bitmap_tag_s } journal_bitmap_tag_t; + +//head struct for collect the Block Bitmaps of Journal struct j_bitmap_list_t { int count; @@ -53,6 +56,7 @@ struct j_bitmap_list_t }; + void dump_journal_superblock( void); //print journal superblock extern int journal_open(char* , int );// open an extract the blocklist from journal extern int journal_close(void); // close the journal (last function in main() if the journal open) diff --git a/src/lookup_local.c b/src/lookup_local.c index b281507..9f7075c 100644 --- a/src/lookup_local.c +++ b/src/lookup_local.c @@ -26,7 +26,7 @@ #endif #include <ext2fs/ext2fs.h> -#include <ext2fs/ext2_io.h> +//#include <ext2fs/ext2_io.h> #include "ext2fsP.h" #include <ctype.h> #include <time.h> @@ -484,10 +484,7 @@ void list_dir2(ext2_ino_t ino, struct ext2_inode *inode) } - - //-------------------------------------------------- -// // local sub function // load dir-index in a dir_list struct dir_list_head_t* get_dir3(struct ext2_inode* d_inode,ext2_ino_t path_ino, ext2_ino_t ino, diff --git a/src/magic.h b/src/magic.h index a664e9a..f97122b 100644 --- a/src/magic.h +++ b/src/magic.h @@ -24,6 +24,10 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + +// this is a copie from file-5.03. (Please do not change here.) +// We need this because not all Distibution have a DEVEL packages for libmagic. + #ifndef _MAGIC_H #define _MAGIC_H diff --git a/src/magic_block_scan.c b/src/magic_block_scan.c index 7080bf6..b1e6599 100644 --- a/src/magic_block_scan.c +++ b/src/magic_block_scan.c @@ -33,13 +33,13 @@ #define MAX_RANGE 16 - +//#define DEBUG_MAGIC_SCAN extern ext2_filsys current_fs ; ext2fs_block_bitmap d_bmap = NULL ; -__u32 get_block_len(char *buf){ +static __u32 get_block_len(char *buf){ int len = current_fs->blocksize -1; while ((len >= 0) && (!(*(buf + len)))) @@ -49,7 +49,7 @@ __u32 get_block_len(char *buf){ -struct found_data_t* free_file_data(struct found_data_t* old){ +static struct found_data_t* free_file_data(struct found_data_t* old){ if(old->inode) free(old->inode); if(old->scan_result) free(old->scan_result); if(old->name) free(old->name); @@ -60,7 +60,7 @@ struct found_data_t* free_file_data(struct found_data_t* old){ -struct found_data_t* new_file_data(blk_t blk,__u32 scan,char *magic_buf, char* buf, __u32 *f){ +static struct found_data_t* new_file_data(blk_t blk,__u32 scan,char *magic_buf, char* buf, __u32 *f){ struct found_data_t *new; int str_len; __u32 name_len; @@ -107,7 +107,7 @@ return new; -struct found_data_t* recover_file_data(char *des_dir, struct found_data_t* this, __u32 *follow){ +static struct found_data_t* recover_file_data(char *des_dir, struct found_data_t* this, __u32 *follow){ recover_file(des_dir,"MAGIC_3",this->name,(struct ext2_inode*)this->inode, 0 , 1); free_file_data(this); *follow = 0; @@ -117,8 +117,10 @@ struct found_data_t* recover_file_data(char *des_dir, struct found_data_t* this, -struct found_data_t* forget_file_data(struct found_data_t* this, __u32 *p_follow){ +static struct found_data_t* forget_file_data(struct found_data_t* this, __u32 *p_follow){ +#ifdef DEBUG_MAGIC_SCAN printf("TRASH : %s : leng %lu : begin %lu\n", this->name, this->inode->i_size , this->first); +#endif free_file_data(this); *p_follow = 0; return NULL; @@ -127,7 +129,7 @@ struct found_data_t* forget_file_data(struct found_data_t* this, __u32 *p_follow -__u32 add_file_data(struct found_data_t* this, blk_t blk, __u32 scan ,__u32 *f){ +static __u32 add_file_data(struct found_data_t* this, blk_t blk, __u32 scan ,__u32 *f){ __u32 retval = 0; if (inode_add_block(this->inode , blk , current_fs->blocksize)){ @@ -140,7 +142,7 @@ return *f ; -int file_data_correct_size(struct found_data_t* this, int size){ +static int file_data_correct_size(struct found_data_t* this, int size){ unsigned long long i_size; int flag=0; @@ -156,7 +158,7 @@ int file_data_correct_size(struct found_data_t* this, int size){ -int check_file_data_end(struct found_data_t* this,char *buf){ +static int check_file_data_end(struct found_data_t* this,char *buf){ int size; int ret = 0; @@ -172,7 +174,7 @@ int check_file_data_end(struct found_data_t* this,char *buf){ //????? -int check_data_passage(char *a_buf, char *b_buf){ +static int check_data_passage(char *a_buf, char *b_buf){ int i, blocksize; int sum[4][2]; @@ -181,63 +183,18 @@ int check_data_passage(char *a_buf, char *b_buf){ } -//FIXME obsolete: must switch to FLAG=1 of func() of the filetype -int check_file_data_possible(struct found_data_t* this, __u32 scan ,char *buf){ + +static int check_file_data_possible(struct found_data_t* this, __u32 scan ,char *buf){ int ret = 0; int size ; ret = this->func(buf, &size ,scan ,1 , this); -/* switch (this->scan & M_IS_FILE){ -// case (M_TXT | M_APPLI) : - case M_TXT : - if (scan & M_TXT) ret = 1; - break; - case M_VIDEO : - case M_AUDIO : - case M_IMAGE : - if (!(scan & M_IS_META)) ret = 1; - break; - case M_APPLI : - if (!(scan & M_IS_META)) ret = 1; - break; - } - - if (!(this->scan & M_IS_FILE)) - ret = 1; */ return ret; } -int add_ext3_file_meta_data(struct found_data_t* this, char *buf, blk_t blk){ - blk_t next_meta; - blk_t last_data = 0; - next_meta = inode_add_meta_block(this->inode , blk, &last_data, buf ); - this->last = last_data; - - if (next_meta > 10 && (ext2fs_test_block_bitmap ( d_bmap, next_meta) && (! ext2fs_test_block_bitmap( bmap, next_meta)))){ - io_channel_read_blk ( current_fs->io, next_meta, 1, buf ); - - if (check_meta3_block(buf, blk, get_block_len(buf))){ - next_meta = inode_add_meta_block(this->inode , next_meta , &last_data, buf ); - this->last = last_data; - - if (next_meta > 10 && (ext2fs_test_block_bitmap ( d_bmap, next_meta) && (! ext2fs_test_block_bitmap( bmap, next_meta)))){ - io_channel_read_blk ( current_fs->io, next_meta, 1, buf ); - - if (check_meta3_block(buf, blk, get_block_len(buf))){ - next_meta = inode_add_meta_block(this->inode , next_meta , &last_data, buf ); - this->last = last_data; - } - } - } - } -return (next_meta) ? 0 : 1 ; -} - - - -int check_indirect_meta3(char *block_buf){ +static int check_indirect_meta3(char *block_buf){ blk_t *pb_block; blk_t last; int i = current_fs->blocksize/sizeof(blk_t); @@ -262,7 +219,7 @@ int check_indirect_meta3(char *block_buf){ -int check_meta3_block(char *block_buf, blk_t blk, __u32 size){ +static int check_meta3_block(char *block_buf, blk_t blk, __u32 size){ blk_t block, *pb_block; int i,j ; @@ -293,7 +250,7 @@ int check_meta3_block(char *block_buf, blk_t blk, __u32 size){ -int check_meta4_block(char *block_buf, blk_t blk, __u32 size){ +static int check_meta4_block(char *block_buf, blk_t blk, __u32 size){ __u16 *p_h16; __u16 h16; @@ -313,7 +270,7 @@ int check_meta4_block(char *block_buf, blk_t blk, __u32 size){ -int check_dir_block(char *block_buf, blk_t blk, __u32 size){ +static int check_dir_block(char *block_buf, blk_t blk, __u32 size){ struct ext2_dir_entry_2 *dir_entry; ext2_ino_t inode_nr; __u16 len; @@ -340,6 +297,60 @@ int check_dir_block(char *block_buf, blk_t blk, __u32 size){ } + +static int check_acl_block(char *block_buf, blk_t blk, __u32 size){ + __u32 *p32; + int i; + + p32 = (__u32*)block_buf; + if ((!(*p32)) || (ext2fs_le32_to_cpu(*p32) & (~ 0xEA030000))) + return 0; + p32 += 2; + if ((!(*p32)) || (ext2fs_le32_to_cpu(*p32) > 0xff)) + return 0; + p32++; + if (! (*p32)) + return 0; + p32++; + for (i = 0; i<4; i++){ + if (*p32) + return 0; + p32++; + } + return (size > (current_fs->blocksize-32)) ? 1 : 0; +} + + + + +static int add_ext3_file_meta_data(struct found_data_t* this, char *buf, blk_t blk){ + blk_t next_meta; + blk_t last_data = 0; + next_meta = inode_add_meta_block(this->inode , blk, &last_data, buf ); + this->last = last_data; + + if (next_meta > 10 && (ext2fs_test_block_bitmap ( d_bmap, next_meta) && (! ext2fs_test_block_bitmap( bmap, next_meta)))){ + io_channel_read_blk ( current_fs->io, next_meta, 1, buf ); + + if (check_meta3_block(buf, blk, get_block_len(buf))){ + next_meta = inode_add_meta_block(this->inode , next_meta , &last_data, buf ); + this->last = last_data; + + if (next_meta > 10 && (ext2fs_test_block_bitmap ( d_bmap, next_meta) && (! ext2fs_test_block_bitmap( bmap, next_meta)))){ + io_channel_read_blk ( current_fs->io, next_meta, 1, buf ); + + if (check_meta3_block(buf, blk, get_block_len(buf))){ + next_meta = inode_add_meta_block(this->inode , next_meta , &last_data, buf ); + this->last = last_data; + } + } + } + } +return (next_meta) ? 0 : 1 ; +} + + + // skip not of interest blocks : return 1 if skiped static int skip_block(blk_t *p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap ){ struct ext2fs_struct_loc_generic_bitmap *p_bmap; @@ -359,7 +370,7 @@ return flag; //magic scanner -int magic_check_block(char* buf,magic_t cookie , magic_t cookie_f, char *magic_buf, __u32 size, blk_t blk){ +static int magic_check_block(char* buf,magic_t cookie , magic_t cookie_f, char *magic_buf, __u32 size, blk_t blk){ //int count = size-1; int count = current_fs->blocksize -1 ; int *i , len; @@ -372,10 +383,10 @@ int magic_check_block(char* buf,magic_t cookie , magic_t cookie_f, char *magic_b strncpy(text,magic_buffer(cookie_f,buf , size),99); strncpy(magic_buf, magic_buffer(cookie , buf , size),99); while (count >= 0 && (*(buf+count) == 0)) count-- ; - +#ifdef DEBUG_MAGIC_SCAN printf("Scan Result : %s %d\n", magic_buf , count+1) ; printf("RESULT : %s \n",text); - +#endif if (!strncmp(text,"data",4)){ if (count == -1) { @@ -409,6 +420,10 @@ int magic_check_block(char* buf,magic_t cookie , magic_t cookie_f, char *magic_b retval = M_DIR ; goto out; } + if (check_acl_block(buf, blk, count+1)){ + retval = M_ACL ; + goto out ; + } } if (retval & M_DATA) @@ -489,9 +504,10 @@ int magic_check_block(char* buf,magic_t cookie , magic_t cookie_f, char *magic_b out: +#ifdef DEBUG_MAGIC_SCAN printf("BLOCK_SCAN : 0x%08x\n",retval & 0xffffe000); blockhex(stdout,buf,0,(count < (64)) ? count : 64 ); - +#endif retval |= (count+1); return retval; @@ -500,7 +516,7 @@ out: -struct found_data_t* soft_border(char *des_dir, char *buf, struct found_data_t* file_data, __u32* follow, blk_t blk){ +static struct found_data_t* soft_border(char *des_dir, char *buf, struct found_data_t* file_data, __u32* follow, blk_t blk){ if ( check_file_data_end(file_data, buf )) file_data = recover_file_data(des_dir, file_data, follow); else{ @@ -511,14 +527,16 @@ return file_data; } -int get_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap, char* buf){ +static int get_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap, char* buf){ blk_t begin; blk_t end; int count=1; for (begin = *p_blk; begin < ds_bmap->real_end ; begin++){ - if((!(begin & 0x7)) && skip_block(&begin, ds_bmap)) + if((!(begin & 0x7)) && skip_block(&begin, ds_bmap)){ +#ifdef DEBUG_MAGIC_SCAN printf("jump to %d \n",begin); - +#endif + } if (ext2fs_test_block_bitmap ( d_bmap, begin) && (! ext2fs_test_block_bitmap( bmap, begin))) break; } @@ -526,7 +544,7 @@ int get_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap, ch if (begin >= ds_bmap->real_end) return 0; - for (end = begin,count=1 ; count < MAX_RANGE ; ){ + for (end = begin,count=1 ; ((count < MAX_RANGE) && (end < ds_bmap->real_end)); ){ if (ext2fs_test_block_bitmap(d_bmap, end+1) && (! ext2fs_test_block_bitmap( bmap, end+1))){ end++; count++; @@ -544,15 +562,19 @@ return count; -int get_full_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap, char* buf, blk_t* p_flag){ +static int get_full_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bmap, char* buf, blk_t* p_flag){ blk_t begin; blk_t end; int count=0; int i; + errcode_t x; + for (begin = *p_blk; begin < ds_bmap->real_end ; begin++){ - if((!(begin & 0x7)) && skip_block(&begin, ds_bmap)) + if((!(begin & 0x7)) && skip_block(&begin, ds_bmap)){ +#ifdef DEBUG_MAGIC_SCAN printf("jump to %d \n",begin); - +#endif + } if (ext2fs_test_block_bitmap ( d_bmap, begin) && (! ext2fs_test_block_bitmap( bmap, begin))) break; } @@ -573,27 +595,29 @@ int get_full_range(blk_t* p_blk ,struct ext2fs_struct_loc_generic_bitmap *ds_bma else { if (i){ if (io_channel_read_blk ( current_fs->io, begin , i, buf )){ - fprintf(stderr,"ERROR: while read block %10u + %d\n",begin,count); + fprintf(stderr,"ERROR: while read block %10u + %d\n",begin,i); return 0; } + buf += (current_fs->blocksize *i); + begin = 0; + i = 0; } end++; - buf += (current_fs->blocksize *i); - begin = 0; - i = 0; } } *(p_blk+1) = end; - if (io_channel_read_blk ( current_fs->io, begin , i, buf )){ - fprintf(stderr,"ERROR: while read block %10u + %d\n",begin,count); - return 0; + if (i){ + if (io_channel_read_blk ( current_fs->io, begin , i, buf )){ + fprintf(stderr,"ERROR: while read block %10u + %d %ld\n",begin,i,count-1); + return 0; + } } return count-1; } -blk_t block_backward(blk_t blk , int count){ +static blk_t block_backward(blk_t blk , int count){ int i=count; while (i && blk){ if (ext2fs_test_block_bitmap(d_bmap, blk) && (! ext2fs_test_block_bitmap( bmap, blk))) @@ -606,8 +630,8 @@ blk_t block_backward(blk_t blk , int count){ -//magic_block_scan_main -int magic_block_scan(char* des_dir, __u32 t_after){ +//main of the magic_scan_engine for ext3 +int magic_block_scan3(char* des_dir, __u32 t_after){ magic_t cookie = 0; magic_t cookie_f = 0; struct ext2fs_struct_loc_generic_bitmap *ds_bmap; @@ -623,6 +647,7 @@ int blocksize, ds_retval,count,i,ret; __u32 scan,follow, size; +printf("MAGIC-3 :Start ext3-magic-scan search. Please wait, this may take a long time\n"); blocksize = current_fs->blocksize ; count = 0; blk[0] = 0; @@ -652,15 +677,19 @@ while (ds_retval){ count = get_range(blk ,ds_bmap, buf); while (count){ +#ifdef DEBUG_MAGIC_SCAN printf(" %d %d %d\n", blk[0],blk[1],count); +#endif for (i = 0; i< ((count>12) ? MAX_RANGE - 12 : count) ;i++){ scan = magic_check_block(buf+(i*blocksize), cookie, cookie_f , magic_buf , blocksize * ((count >=9) ? 9 : count) ,blk[0]+i); if(scan & (M_DATA | M_BLANK | M_IS_META)){ if (scan & (M_ACL | M_EXT4_META | M_DIR)) ext2fs_mark_generic_bitmap(bmap, blk[0]+i); continue; - } + } +#ifdef DEBUG_MAGIC_SCAN printf("SCAN %d : %09x : %s\n",blk[0]+i,scan,magic_buf); +#endif if (((count -i) > 12) && (ext2fs_le32_to_cpu(*(__u32*)(buf +((i+12)*blocksize))) == blk[0] + i +1 + 12)){ follow = 0; file_data = new_file_data(blk[0]+i,scan,magic_buf,buf+(i*blocksize),&follow); @@ -682,8 +711,6 @@ while (ds_retval){ else{ // no matches // In the first step we are taking nothing - -// printf(" %d not matches %d == %d \n\n\n", blk[0]+i, ext2fs_le32_to_cpu(*(buf +((i+12)*blocksize))), blk[0] + i + 12+1); } } blk[0] += (i)?i:1; @@ -694,15 +721,30 @@ while (ds_retval){ fragment_flag = 0; count = get_full_range(blk ,ds_bmap, buf,flag); while (count){ +#ifdef DEBUG_MAGIC_SCAN printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d - %d\n",flag[0],flag[1],flag[2],flag[3],flag[4],flag[5],flag[6],flag[7],flag[8],flag[9],flag[10],flag[11],flag[12],flag[13],flag[14],flag[15],count); - +#endif for (i = 0; i< ((count>12) ? MAX_RANGE - 12 : count) ;i++){ follow = 0; scan = magic_check_block(buf+(i*blocksize), cookie, cookie_f , magic_buf , blocksize ,blk[0]+i); if(scan & (M_DATA | M_BLANK | M_IS_META)){ - continue; - } + if ((!fragment_flag) && (scan & M_EXT3_META) && (check_indirect_meta3(buf+(i*blocksize)))){ +#ifdef DEBUG_MAGIC_SCAN + printf("try a fragment recover for metablock %ld\n",flag[i]); +#endif + blk[1] = block_backward(flag[i] , 12); + if (blk[1]){ + blk[0] = blk[1]; + fragment_flag = flag[i]; + goto load_new; + } + } + else + continue; + } +#ifdef DEBUG_MAGIC_SCAN printf("SCAN %d : %09x : %s\n",blk[0]+i,scan,magic_buf); +#endif if (((count -i) > 12) && (ext2fs_le32_to_cpu(*(__u32*)(buf +((i+12)*blocksize))) == flag[12+i]+1)){ file_data = new_file_data(flag[i],scan,magic_buf,buf+(i*blocksize),&follow); for(j=i; j<(12+i);j++) @@ -737,7 +779,9 @@ while (ds_retval){ j--; file_data = soft_border(des_dir,buf+(j*blocksize), file_data, &follow, flag[j]); if ((!fragment_flag) && (scan & M_EXT3_META) && (check_indirect_meta3(buf+((j+1)*blocksize)))){ +#ifdef DEBUG_MAGIC_SCAN printf("try a fragment recover for metablock %ld\n",flag[j]+1); +#endif blk[1] = block_backward(flag[j] , 12); if (blk[1]){ blk[0] = blk[1]; @@ -756,14 +800,18 @@ while (ds_retval){ file_data = recover_file_data(des_dir, file_data, &follow); } else{ - file_data = forget_file_data(file_data, &follow); + file_data = forget_file_data(file_data, &follow); +#ifdef DEBUG_MAGIC_SCAN printf("Don't recover this file, current block %d \n",blk); +#endif } break; } } if (follow){ +#ifdef DEBUG_MAGIC_SCAN printf("stop no file-end\n"); +#endif file_data = soft_border(des_dir,buf+((j-1)*blocksize), file_data, &follow, flag[j-1]); i = j - 11; } diff --git a/src/recover.c b/src/recover.c index 1a53d8e..eba48f5 100644 --- a/src/recover.c +++ b/src/recover.c @@ -67,13 +67,13 @@ struct privat { char flag; int error;}; + struct alloc_stat{ __u32 allocated; __u32 not_allocated;}; - // recover files from a "double quotes" listfile void recover_list(char *des_dir, char *input_file,__u32 t_after, __u32 t_before, int flag){ FILE *f; @@ -564,33 +564,6 @@ return retval; -/* -//FIXME: If we ever need this function, we rewrite this -int create_all_dir(char* des_dir,char* pathname, ext2_ino_t ino_nr ){ - char *fullname; - char *p1; - int retval; - - if (ino_nr == EXT2_ROOT_INO) - return 0; - - fullname = malloc(strlen(des_dir) + strlen(pathname) + 3); - if (fullname){ - p1 = pathname; - while (*p1 == '/') p1++; - strcpy(fullname,des_dir); - strcat(fullname,"/"); - strcat(fullname,p1); - retval = mkdir(fullname,S_IRWXU); - if (retval && (errno != EEXIST)) - fprintf(stderr,"Error: mkdir %s\n", fullname); - free(fullname); - } -return retval; -} -*/ - - //set all attributes for directory void set_dir_attributes(char* des_dir,char* pathname,struct ext2_inode *inode){ char *fullname; @@ -26,7 +26,7 @@ /* ext3/4 libraries */ #include <ext2fs/ext2fs.h> -#include <ext2fs/ext2_io.h> +//#include <ext2fs/ext2_io.h> #include <e2p/e2p.h> #include "util.h" @@ -264,6 +264,89 @@ return; } + +// search for a time before the last big delete job +__u32 get_last_delete_time(ext2_filsys fs) +{ +struct ext2_group_desc *gdp; +char *buf= NULL; +int zero_flag, x , retval; +__u32 blocksize , inodesize , inode_max , inode_per_group, block_count; +__u16 inode_per_block , inode_block_group, group; +blk_t block_nr; +__u32 i, c_time, d_time; +__u32 last = 0; +__u32 first; +int flag; + +struct ext2_inode_large *inode; + +blocksize = fs->blocksize; +inodesize = fs->super->s_inode_size; +inode_max = fs->super->s_inodes_count; +inode_per_group = fs->super->s_inodes_per_group; +buf = malloc(blocksize); + +inode_per_block = blocksize / inodesize; +inode_block_group = inode_per_group / inode_per_block; + +for (flag=0;flag<2;flag++){ + for (group = 0 ; group < fs->group_desc_count ; group++){ + gdp = &fs->group_desc[group]; + zero_flag = 0; + + // NEXT GROUP IF INODE NOT INIT + if (gdp->bg_flags & (EXT2_BG_INODE_UNINIT)) continue; + + // SET ZERO-FLAG IF FREE INODES == INODE/GROUP for fast ext3 + if (gdp->bg_free_inodes_count == inode_per_group) zero_flag = 1; + + for (block_nr = gdp->bg_inode_table , block_count = 0 ; + block_nr < (gdp->bg_inode_table + inode_block_group); block_nr++, block_count++) { + + // break if the first block only zero inode + if ((block_count ==1) && (zero_flag == (inode_per_block + 1))) break; + + if ( read_block ( fs , &block_nr , buf)) + return 0; + + for (i = (group * inode_per_group)+(block_count * inode_per_block) + 1 ,x = 0; + x < inode_per_block ; i++ , x++){ + + if (i >= inode_max) break; + inode = (struct ext2_inode_large*) (buf + (x*inodesize)); + c_time = ext2fs_le32_to_cpu(inode->i_ctime); + if (! c_time) { + if(zero_flag) zero_flag++ ; + continue; + } + d_time = ext2fs_le32_to_cpu(inode->i_dtime); + if (flag){ + if ((d_time > (last-300)) && (d_time < first)) + first = d_time; + } + else{ + if (d_time > last){ + last = d_time; + } + } + } + } + } +first = last; +} + + if(buf) { + free(buf); + buf = NULL; + } +return first - 1 ; +} + + + + + // add inodenumber in a collectlist void add_coll_list(ext2_ino_t ino_nr ){ ext2_ino_t *pointer; @@ -173,7 +173,15 @@ void imap_search(char* , __u32, __u32 ); // search inode by imap (step1 + step2) int check_find_dir(char*, ext2_ino_t, char*, char*); //check if the directory always recovert; then move + +//public function file_type.c +int ident_file(struct found_data_t*, __u32*, char*, char*); // index of the files corresponding magic result strings +void get_file_property(struct found_data_t*); //set the file properties and the extension + + + //public functions magic_block_scan.c -//void magic_block_scan(char* , __u32); +int magic_block_scan3(char*, __u32);//main of the magic_scan_engine for ext3 + #endif |