PhotoRec: do not always try to complete the recovery of the previous file when a file is recovered

This commit is contained in:
Christophe Grenier 2015-04-05 11:55:23 +02:00
parent 5f6fd9e8b3
commit a07f9b6fc8
3 changed files with 54 additions and 56 deletions

View file

@ -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 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_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) 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_recovery->file_stat->recovered++;
} }
/** file_finish() /** file_finish_bf()
@param file_recovery - @param file_recovery -
@param struct ph_param *params @param struct ph_param *params
@param alloc_data_t *list_search_space @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 @param alloc_data_t *list_search_space
@returns: @returns:
-1: file not recovered, file_size=0 offset_error!=0
0: file not recovered 0: file not recovered
1: file 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) if(file_recovery->file_stat==NULL)
return 0; return PFSTATUS_BAD;
if(file_recovery->handle) if(file_recovery->handle)
file_finish_aux(file_recovery, params, (paranoid==0?0:1)); file_finish_aux(file_recovery, params, (paranoid==0?0:1));
if(file_recovery->file_size==0) if(file_recovery->file_size==0)
{ {
file_block_truncate_zero(file_recovery, list_search_space); file_block_truncate_zero(file_recovery, list_search_space);
reset_file_recovery(file_recovery); 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); file_block_log(file_recovery, params->disk->sector_size);
#ifdef ENABLE_DFXML #ifdef ENABLE_DFXML
xml_log_file_recovered(file_recovery); xml_log_file_recovered(file_recovery);
#endif #endif
file_block_free(&file_recovery->location); file_block_free(&file_recovery->location);
reset_file_recovery(file_recovery); 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) 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 *tmp;
struct td_list_head *next; struct td_list_head *next;
uint64_t size=0; uint64_t size=0;
int file_truncated=0;
td_list_for_each_safe(tmp, next, &file_recovery->location.list) td_list_for_each_safe(tmp, next, &file_recovery->location.list)
{ {
alloc_list_t *element=td_list_entry(tmp, alloc_list_t, 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); file_block_truncate_aux(element->start, element->end, list_search_space);
td_list_del(tmp); td_list_del(tmp);
free(element); free(element);
file_truncated=1;
} }
else if(element->data>0) 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); size+=(element->end-element->start+1);
} }
} }
return file_truncated;
} }
static uint64_t file_offset_end(const file_recovery_t *file_recovery) static uint64_t file_offset_end(const file_recovery_t *file_recovery)

View file

@ -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 photorec_status photorec_status_t;
typedef enum { PSTATUS_OK=0, PSTATUS_STOP=1, PSTATUS_EACCES=2, PSTATUS_ENOSPC=3} pstatus_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 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 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, int file_finish_bf(file_recovery_t *file_recovery, struct ph_param *params,
alloc_data_t *list_search_space); 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 write_stats_log(const file_stat_t *file_stats);
void update_stats(file_stat_t *file_stats, alloc_data_t *list_search_space); void update_stats(file_stat_t *file_stats, alloc_data_t *list_search_space);
partition_t *new_whole_disk(const disk_t *disk_car); partition_t *new_whole_disk(const disk_t *disk_car);

View file

@ -142,47 +142,40 @@ static pstatus_t photorec_new_file(file_recovery_t *file_recovery, struct ph_par
return PSTATUS_OK; 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(options->verbose > 1)
if(file_recovery->file_stat!=NULL) 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(options->verbose > 1) if(*file_recovered==PFSTATUS_OK_TRUNCATED)
log_trace("A known header has been found, recovery of the previous file is finished\n"); return PSTATUS_OK;
*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);
}
} }
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 struct td_list_head *tmpl;
const unsigned int blocksize=params->blocksize; 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) if(options->verbose > 1)
{ {
log_verbose("Currently saving a tar file, sector %lu.\n", 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; return PSTATUS_OK;
} }
file_recovery_new.file_stat=NULL; 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) td_list_for_each(tmpl, &file_check_list.list)
{ {
const struct td_list_head *tmp; 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_check->header_check(buffer, read_size, 0, file_recovery, &file_recovery_new)!=0)
{ {
file_recovery_new.file_stat=file_check->file_stat; 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); params->disk->pread(params->disk, buffer, READ_SIZE, offset);
while(current_search_space!=list_search_space) while(current_search_space!=list_search_space)
{ {
int file_recovered=0; pfstatus_t file_recovered=PFSTATUS_BAD;
uint64_t old_offset=offset; uint64_t old_offset=offset;
int res=DC_SCAN; int res=DC_SCAN;
#ifdef DEBUG #ifdef DEBUG
@ -280,7 +273,7 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
exit(1); exit(1);
} }
#endif #endif
ind_stop=photorec_check_header(&file_recovery, params, options, list_search_space, buffer, &file_recovered, &current_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) if(file_recovery.file_stat!=NULL)
{ {
/* try to skip ext2/ext3 indirect block */ /* 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"); log_info("PhotoRec has been stopped\n");
current_search_space=list_search_space; current_search_space=list_search_space;
} }
else if(file_recovered==0) else if(file_recovered==PFSTATUS_BAD)
{ {
if(res==DC_SCAN) if(res==DC_SCAN)
{ {
@ -368,7 +361,8 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
back=0; 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 */ /* try to recover the previous file, otherwise stay at the current location */
offset_before_back=offset; 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"); log_trace("End of media\n");
#endif #endif
file_recovered=file_finish2(&file_recovery, params, options->paranoid, list_search_space); 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, &current_search_space, &offset, file_recovery.location.start); get_prev_location(list_search_space, &current_search_space, &offset, file_recovery.location.start);
if(options->lowmem > 0) if(options->lowmem > 0)
forget(list_search_space,current_search_space); forget(list_search_space,current_search_space);
} }
buffer_olddata+=blocksize; buffer_olddata+=blocksize;
buffer+=blocksize; buffer+=blocksize;
if(file_recovered==1 || if(file_recovered!=PFSTATUS_BAD ||
old_offset+blocksize!=offset || old_offset+blocksize!=offset ||
buffer+read_size>buffer_start+buffer_size) buffer+read_size>buffer_start+buffer_size)
{ {
if(file_recovered==1) if(file_recovered!=PFSTATUS_BAD)
memset(buffer_start,0,blocksize); memset(buffer_start,0,blocksize);
else else
memcpy(buffer_start,buffer_olddata,blocksize); memcpy(buffer_start,buffer_olddata,blocksize);