From a07f9b6fc8b265f8e1b83cbf3421ef8502a6290a Mon Sep 17 00:00:00 2001 From: Christophe Grenier Date: Sun, 5 Apr 2015 11:55:23 +0200 Subject: [PATCH] PhotoRec: do not always try to complete the recovery of the previous file when a file is recovered --- src/photorec.c | 21 ++++++------ src/photorec.h | 3 +- src/psearchn.c | 86 +++++++++++++++++++++++--------------------------- 3 files changed, 54 insertions(+), 56 deletions(-) diff --git a/src/photorec.c b/src/photorec.c index 5ba878b8..895a2ce3 100644 --- a/src/photorec.c +++ b/src/photorec.c @@ -61,7 +61,7 @@ static void update_search_space_aux(alloc_data_t *list_search_space, uint64_t start, uint64_t end, alloc_data_t **new_current_search_space, uint64_t *offset); static void file_block_truncate_zero(const file_recovery_t *file_recovery, alloc_data_t *list_search_space); -static void file_block_truncate(const file_recovery_t *file_recovery, alloc_data_t *list_search_space, const unsigned int blocksize); +static int file_block_truncate(const file_recovery_t *file_recovery, alloc_data_t *list_search_space, const unsigned int blocksize); void file_block_log(const file_recovery_t *file_recovery, const unsigned int sector_size) { @@ -595,7 +595,7 @@ static void file_finish_aux(file_recovery_t *file_recovery, struct ph_param *par file_recovery->file_stat->recovered++; } -/** file_finish() +/** file_finish_bf() @param file_recovery - @param struct ph_param *params @param alloc_data_t *list_search_space @@ -642,30 +642,30 @@ int file_finish_bf(file_recovery_t *file_recovery, struct ph_param *params, @param alloc_data_t *list_search_space @returns: - -1: file not recovered, file_size=0 offset_error!=0 0: file not recovered 1: file recovered */ -int file_finish2(file_recovery_t *file_recovery, struct ph_param *params, const int paranoid, alloc_data_t *list_search_space) +pfstatus_t file_finish2(file_recovery_t *file_recovery, struct ph_param *params, const int paranoid, alloc_data_t *list_search_space) { + int file_truncated; if(file_recovery->file_stat==NULL) - return 0; + return PFSTATUS_BAD; if(file_recovery->handle) file_finish_aux(file_recovery, params, (paranoid==0?0:1)); if(file_recovery->file_size==0) { file_block_truncate_zero(file_recovery, list_search_space); reset_file_recovery(file_recovery); - return 0; + return PFSTATUS_BAD; } - file_block_truncate(file_recovery, list_search_space, params->blocksize); + file_truncated=file_block_truncate(file_recovery, list_search_space, params->blocksize); file_block_log(file_recovery, params->disk->sector_size); #ifdef ENABLE_DFXML xml_log_file_recovered(file_recovery); #endif file_block_free(&file_recovery->location); reset_file_recovery(file_recovery); - return 1; + return (file_truncated>0?PFSTATUS_OK_TRUNCATED:PFSTATUS_OK); } void info_list_search_space(const alloc_data_t *list_search_space, const alloc_data_t *current_search_space, const unsigned int sector_size, const int keep_corrupted_file, const int verbose) @@ -1067,11 +1067,12 @@ static void file_block_truncate_zero(const file_recovery_t *file_recovery, alloc } } -static void file_block_truncate(const file_recovery_t *file_recovery, alloc_data_t *list_search_space, const unsigned int blocksize) +static int file_block_truncate(const file_recovery_t *file_recovery, alloc_data_t *list_search_space, const unsigned int blocksize) { struct td_list_head *tmp; struct td_list_head *next; uint64_t size=0; + int file_truncated=0; td_list_for_each_safe(tmp, next, &file_recovery->location.list) { alloc_list_t *element=td_list_entry(tmp, alloc_list_t, list); @@ -1080,6 +1081,7 @@ static void file_block_truncate(const file_recovery_t *file_recovery, alloc_data file_block_truncate_aux(element->start, element->end, list_search_space); td_list_del(tmp); free(element); + file_truncated=1; } else if(element->data>0) { @@ -1094,6 +1096,7 @@ static void file_block_truncate(const file_recovery_t *file_recovery, alloc_data size+=(element->end-element->start+1); } } + return file_truncated; } static uint64_t file_offset_end(const file_recovery_t *file_recovery) diff --git a/src/photorec.h b/src/photorec.h index 422a15fc..544c6894 100644 --- a/src/photorec.h +++ b/src/photorec.h @@ -32,6 +32,7 @@ enum photorec_status { STATUS_FIND_OFFSET, STATUS_UNFORMAT, STATUS_EXT2_ON, STAT typedef enum photorec_status photorec_status_t; typedef enum { PSTATUS_OK=0, PSTATUS_STOP=1, PSTATUS_EACCES=2, PSTATUS_ENOSPC=3} pstatus_t; +typedef enum { PFSTATUS_BAD=0, PFSTATUS_OK=1, PFSTATUS_OK_TRUNCATED=2} pfstatus_t; struct ph_options { @@ -67,7 +68,7 @@ void get_prev_location(alloc_data_t *list_search_space, alloc_data_t **current_s int get_prev_file_header(alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset); int file_finish_bf(file_recovery_t *file_recovery, struct ph_param *params, alloc_data_t *list_search_space); -int file_finish2(file_recovery_t *file_recovery, struct ph_param *params, const int paranoid, alloc_data_t *list_search_space); +pfstatus_t file_finish2(file_recovery_t *file_recovery, struct ph_param *params, const int paranoid, alloc_data_t *list_search_space); void write_stats_log(const file_stat_t *file_stats); void update_stats(file_stat_t *file_stats, alloc_data_t *list_search_space); partition_t *new_whole_disk(const disk_t *disk_car); diff --git a/src/psearchn.c b/src/psearchn.c index a92e6789..4e04cb5c 100644 --- a/src/psearchn.c +++ b/src/psearchn.c @@ -142,47 +142,40 @@ static pstatus_t photorec_new_file(file_recovery_t *file_recovery, struct ph_par return PSTATUS_OK; } -static pstatus_t photorec_header_found(file_recovery_t *file_recovery_new, file_recovery_t *file_recovery, struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space, const unsigned char *buffer, int *file_recovered, alloc_data_t **current_search_space, uint64_t *offset) +static pstatus_t photorec_header_found(file_recovery_t *file_recovery_new, file_recovery_t *file_recovery, struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space, const unsigned char *buffer, pfstatus_t *file_recovered, const uint64_t offset) { - if(file_recovery_new->file_stat!=NULL && file_recovery_new->file_stat->file_hint!=NULL) + *file_recovered=PFSTATUS_BAD; + if(file_recovery_new->file_stat==NULL || file_recovery_new->file_stat->file_hint==NULL) + return PSTATUS_OK; + file_recovery_new->location.start=offset; + if(file_recovery->file_stat!=NULL) { - file_recovery_new->location.start=*offset; - if(file_recovery->file_stat!=NULL) - { - if(options->verbose > 1) - log_trace("A known header has been found, recovery of the previous file is finished\n"); - *file_recovered=file_finish2(file_recovery, params, options->paranoid, list_search_space); - if(*file_recovered==1) - get_prev_location(list_search_space, current_search_space, offset, file_recovery->location.start); - if(options->lowmem > 0) - forget(list_search_space, *current_search_space); - } - if(*file_recovered==0) - { - file_recovery_cpy(file_recovery, file_recovery_new); - if(options->verbose > 1) - { - log_info("%s header found at sector %lu\n", - ((file_recovery->extension!=NULL && file_recovery->extension[0]!='\0')? - file_recovery->extension:file_recovery->file_stat->file_hint->description), - (unsigned long)((file_recovery->location.start-params->partition->part_offset)/params->disk->sector_size)); - log_info("file_recovery->location.start=%lu\n", - (unsigned long)(file_recovery->location.start/params->disk->sector_size)); - } - - if(file_recovery->file_stat->file_hint==&file_hint_dir && options->verbose > 0) - { /* FAT directory found, list the file */ - const unsigned int blocksize=params->blocksize; - const unsigned int read_size=(blocksize>65536?blocksize:65536); - photorec_dir_fat(buffer, read_size, file_recovery->location.start/params->disk->sector_size); - } - return photorec_new_file(file_recovery, params, *offset); - } + if(options->verbose > 1) + log_trace("A known header has been found, recovery of the previous file is finished\n"); + *file_recovered=file_finish2(file_recovery, params, options->paranoid, list_search_space); + if(*file_recovered==PFSTATUS_OK_TRUNCATED) + return PSTATUS_OK; } - return PSTATUS_OK; + file_recovery_cpy(file_recovery, file_recovery_new); + if(options->verbose > 1) + { + log_info("%s header found at sector %lu\n", + ((file_recovery->extension!=NULL && file_recovery->extension[0]!='\0')? + file_recovery->extension:file_recovery->file_stat->file_hint->description), + (unsigned long)((file_recovery->location.start-params->partition->part_offset)/params->disk->sector_size)); + log_info("file_recovery->location.start=%lu\n", + (unsigned long)(file_recovery->location.start/params->disk->sector_size)); + } + if(file_recovery->file_stat->file_hint==&file_hint_dir && options->verbose > 0) + { /* FAT directory found, list the file */ + const unsigned int blocksize=params->blocksize; + const unsigned int read_size=(blocksize>65536?blocksize:65536); + photorec_dir_fat(buffer, read_size, file_recovery->location.start/params->disk->sector_size); + } + return photorec_new_file(file_recovery, params, offset); } -inline static pstatus_t photorec_check_header(file_recovery_t *file_recovery, struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space, const unsigned char *buffer, int *file_recovered, alloc_data_t **current_search_space, uint64_t *offset) +inline static pstatus_t photorec_check_header(file_recovery_t *file_recovery, struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space, const unsigned char *buffer, pfstatus_t *file_recovered, const uint64_t offset) { const struct td_list_head *tmpl; const unsigned int blocksize=params->blocksize; @@ -199,12 +192,12 @@ inline static pstatus_t photorec_check_header(file_recovery_t *file_recovery, st if(options->verbose > 1) { log_verbose("Currently saving a tar file, sector %lu.\n", - (unsigned long)((*offset-params->partition->part_offset)/params->disk->sector_size)); + (unsigned long)((offset-params->partition->part_offset)/params->disk->sector_size)); } return PSTATUS_OK; } file_recovery_new.file_stat=NULL; - file_recovery_new.location.start=*offset; + file_recovery_new.location.start=offset; td_list_for_each(tmpl, &file_check_list.list) { const struct td_list_head *tmp; @@ -216,7 +209,7 @@ inline static pstatus_t photorec_check_header(file_recovery_t *file_recovery, st file_check->header_check(buffer, read_size, 0, file_recovery, &file_recovery_new)!=0) { file_recovery_new.file_stat=file_check->file_stat; - return photorec_header_found(&file_recovery_new, file_recovery, params, options, list_search_space, buffer, file_recovered, current_search_space, offset); + return photorec_header_found(&file_recovery_new, file_recovery, params, options, list_search_space, buffer, file_recovered, offset); } } } @@ -264,7 +257,7 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options params->disk->pread(params->disk, buffer, READ_SIZE, offset); while(current_search_space!=list_search_space) { - int file_recovered=0; + pfstatus_t file_recovered=PFSTATUS_BAD; uint64_t old_offset=offset; int res=DC_SCAN; #ifdef DEBUG @@ -280,7 +273,7 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options exit(1); } #endif - ind_stop=photorec_check_header(&file_recovery, params, options, list_search_space, buffer, &file_recovered, ¤t_search_space, &offset); + ind_stop=photorec_check_header(&file_recovery, params, options, list_search_space, buffer, &file_recovered, offset); if(file_recovery.file_stat!=NULL) { /* try to skip ext2/ext3 indirect block */ @@ -359,7 +352,7 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options log_info("PhotoRec has been stopped\n"); current_search_space=list_search_space; } - else if(file_recovered==0) + else if(file_recovered==PFSTATUS_BAD) { if(res==DC_SCAN) { @@ -368,7 +361,8 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options back=0; } } - else if(file_recovered>0) + else if(file_recovered==PFSTATUS_OK_TRUNCATED || + (file_recovered==PFSTATUS_OK && file_recovery.file_stat==NULL)) { /* try to recover the previous file, otherwise stay at the current location */ offset_before_back=offset; @@ -389,18 +383,18 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options log_trace("End of media\n"); #endif file_recovered=file_finish2(&file_recovery, params, options->paranoid, list_search_space); - if(file_recovered==1) + if(file_recovered!=PFSTATUS_BAD) get_prev_location(list_search_space, ¤t_search_space, &offset, file_recovery.location.start); if(options->lowmem > 0) forget(list_search_space,current_search_space); } buffer_olddata+=blocksize; buffer+=blocksize; - if(file_recovered==1 || + if(file_recovered!=PFSTATUS_BAD || old_offset+blocksize!=offset || buffer+read_size>buffer_start+buffer_size) { - if(file_recovered==1) + if(file_recovered!=PFSTATUS_BAD) memset(buffer_start,0,blocksize); else memcpy(buffer_start,buffer_olddata,blocksize);