From 37b48a9fd645d38ab50bb33066acdaf868529d95 Mon Sep 17 00:00:00 2001 From: Christophe Grenier Date: Sat, 17 Mar 2018 10:25:05 +0100 Subject: [PATCH] QPhotoRec: update the algo to match the one from PhotoRec --- src/Makefile.am | 4 +- src/photorec_check_header.h | 166 +++++++++++++++++++++++++++++++++++ src/psearchn.c | 152 +------------------------------- src/qpsearch.cpp | 168 +++++------------------------------- src/sessionp.c | 10 +++ src/sessionp.h | 1 + 6 files changed, 205 insertions(+), 296 deletions(-) create mode 100644 src/photorec_check_header.h diff --git a/src/Makefile.am b/src/Makefile.am index 6da1704c..8dc50416 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -360,7 +360,7 @@ photorec_C = photorec.c phcfg.c addpart.c chgarch.c dir.c exfatp.c ext2grp.c ex photorec_H = photorec.h phcfg.h addpart.h chgarch.h dir.h exfatp.h ext2grp.h ext2p.h ext2_dir.h ext2_inc.h fat_dir.h fatp.h file_found.h geometry.h memmem.h ntfs_dir.h ntfsp.h ntfs_inc.h pdisksel.h phcli.h poptions.h sessionp.h setdate.h dfxml.h photorec_ncurses_C = addpartn.c askloc.c chgarchn.c chgtype.c chgtypen.c fat_cluster.c fat_unformat.c geometryn.c hiddenn.c intrfn.c nodisk.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c pbanner.c pblocksize.c pdiskseln.c pfree_whole.c phbf.c phbs.c phnc.c phrecn.c ppartseln.c psearchn.c -photorec_ncurses_H = addpartn.h askloc.h chgarchn.h chgtype.h chgtypen.h fat_cluster.h fat_unformat.h geometryn.h hiddenn.h intrfn.h nodisk.h parti386n.h partgptn.h partmacn.h partsunn.h partxboxn.h pblocksize.h pdiskseln.h pfree_whole.h pnext.h phbf.h phbs.h phnc.h phrecn.h ppartseln.h psearch.h psearchn.h +photorec_ncurses_H = addpartn.h askloc.h chgarchn.h chgtype.h chgtypen.h fat_cluster.h fat_unformat.h geometryn.h hiddenn.h intrfn.h nodisk.h parti386n.h partgptn.h partmacn.h partsunn.h partxboxn.h pblocksize.h pdiskseln.h pfree_whole.h pnext.h phbf.h phbs.h phnc.h phrecn.h ppartseln.h psearch.h psearchn.h photorec_check_header.h QT_TS = \ lang/qphotorec.ca.ts \ @@ -375,7 +375,7 @@ photorec_SOURCES = phmain.c $(photorec_C) $(photorec_H) $(photorec_ncurses_C) $( photorecf_SOURCES = phmain.c $(photorec_C) $(photorec_H) $(photorec_ncurses_C) $(photorec_ncurses_H) $(file_C) $(file_H) $(base_C) $(base_H) partgptro.c $(fs_C) $(fs_H) $(ICON_PHOTOREC) suspend.c -qphotorec_SOURCES = qmainrec.cpp qphotorec.cpp qphotorec.h qphotorec.qrc qphotorec_locale.qrc qphbs.cpp qpsearch.cpp psearch.h chgtype.c chgtype.h $(photorec_C) $(photorec_H) $(file_C) $(file_H) $(base_C) $(base_H) partgptro.c $(fs_C) $(fs_H) $(ICON_QPHOTOREC) suspend_no.c $(QT_TS) +qphotorec_SOURCES = qmainrec.cpp qphotorec.cpp qphotorec.h qphotorec.qrc qphotorec_locale.qrc qphbs.cpp qpsearch.cpp photorec_check_header.h psearch.h chgtype.c chgtype.h $(photorec_C) $(photorec_H) $(file_C) $(file_H) $(base_C) $(base_H) partgptro.c $(fs_C) $(fs_H) $(ICON_QPHOTOREC) suspend_no.c $(QT_TS) nodist_qphotorec_SOURCES = moc_qphotorec.cpp rcc_qphotorec.cpp rcc_qphotorec_locale.cpp diff --git a/src/photorec_check_header.h b/src/photorec_check_header.h new file mode 100644 index 00000000..7767ca18 --- /dev/null +++ b/src/photorec_check_header.h @@ -0,0 +1,166 @@ +/* + + File: photorec_check_header.h + + Copyright (C) 2002-2018 Christophe GRENIER + + This software is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write the Free Software Foundation, Inc., 51 + Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + */ +#ifdef __cplusplus +extern "C" { +#endif +extern const file_hint_t file_hint_tar; +extern const file_hint_t file_hint_dir; +extern file_check_list_t file_check_list; + +#if defined(__CYGWIN__) || defined(__MINGW32__) +/* Live antivirus protection may open file as soon as they are created by * + * PhotoRec. PhotoRec will not be able to overwrite a file as long as the * + * antivirus is scanning it, so let's wait a little bit if the creation * + * failed. */ + +#ifndef HAVE_SLEEP +#define sleep(x) Sleep((x)*1000) +#endif + +static FILE *fopen_with_retry(const char *path, const char *mode) +{ + FILE *handle; + if((handle=fopen(path, mode))!=NULL) + return handle; +#ifdef __MINGW32__ + Sleep(1000); +#else + sleep(1); +#endif + if((handle=fopen(path, mode))!=NULL) + return handle; +#ifdef __MINGW32__ + Sleep(2000); +#else + sleep(2); +#endif + if((handle=fopen(path, mode))!=NULL) + return handle; + return NULL; +} +#endif + +static void photorec_dir_fat(const unsigned char *buffer, const unsigned int read_size, const unsigned long long sector) +{ + file_info_t dir_list; + TD_INIT_LIST_HEAD(&dir_list.list); + dir_fat_aux(buffer, read_size, 0, &dir_list); + if(!td_list_empty(&dir_list.list)) + { + log_info("Sector %llu\n", sector); + dir_aff_log(NULL, &dir_list); + delete_list_file(&dir_list); + } +} + +static pstatus_t photorec_new_file(file_recovery_t *file_recovery, struct ph_param *params, const uint64_t offset) +{ + set_filename(file_recovery, params); + if(file_recovery->file_stat->file_hint->recover==1) + { +#if defined(__CYGWIN__) || defined(__MINGW32__) + file_recovery->handle=fopen_with_retry(file_recovery->filename,"w+b"); +#else + file_recovery->handle=fopen(file_recovery->filename,"w+b"); +#endif + if(!file_recovery->handle) + { + log_critical("Cannot create file %s: %s\n", file_recovery->filename, strerror(errno)); + params->offset=offset; + return PSTATUS_EACCES; + } + } + 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, pfstatus_t *file_recovered, const uint64_t offset) +{ + *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) + { + 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; + } + 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, pfstatus_t *file_recovered, const uint64_t offset) +{ + const struct td_list_head *tmpl; + const unsigned int blocksize=params->blocksize; + const unsigned int read_size=(blocksize>65536?blocksize:65536); + file_recovery_t file_recovery_new; + file_recovery_new.blocksize=blocksize; + if(file_recovery->file_stat!=NULL && file_recovery->file_stat->file_hint==&file_hint_tar && + header_check_tar(buffer-0x200,0x200, 0, file_recovery, &file_recovery_new)) + { /* Currently saving a tar, do not check the data for know header */ + 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)); + } + return PSTATUS_OK; + } + file_recovery_new.file_stat=NULL; + file_recovery_new.location.start=offset; + td_list_for_each(tmpl, &file_check_list.list) + { + const struct td_list_head *tmp; + const file_check_list_t *pos=td_list_entry_const(tmpl, const file_check_list_t, list); + td_list_for_each(tmp, &pos->file_checks[buffer[pos->offset]].list) + { + const file_check_t *file_check=td_list_entry_const(tmp, const file_check_t, list); + if((file_check->length==0 || memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0) && + 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, offset); + } + } + } + return PSTATUS_OK; +} +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif diff --git a/src/psearchn.c b/src/psearchn.c index 52805bb7..562a707b 100644 --- a/src/psearchn.c +++ b/src/psearchn.c @@ -68,147 +68,8 @@ #include "phnc.h" #endif #include "psearchn.h" - +#include "photorec_check_header.h" #define READ_SIZE 1024*512 -extern const file_hint_t file_hint_tar; -extern const file_hint_t file_hint_dir; -extern file_check_list_t file_check_list; - -#if defined(__CYGWIN__) || defined(__MINGW32__) -/* Live antivirus protection may open file as soon as they are created by * - * PhotoRec. PhotoRec will not be able to overwrite a file as long as the * - * antivirus is scanning it, so let's wait a little bit if the creation * - * failed. */ - -#ifndef HAVE_SLEEP -#define sleep(x) Sleep((x)*1000) -#endif - -static FILE *fopen_with_retry(const char *path, const char *mode) -{ - FILE *handle; - if((handle=fopen(path, mode))!=NULL) - return handle; -#ifdef __MINGW32__ - Sleep(1000); -#else - sleep(1); -#endif - if((handle=fopen(path, mode))!=NULL) - return handle; -#ifdef __MINGW32__ - Sleep(2000); -#else - sleep(2); -#endif - if((handle=fopen(path, mode))!=NULL) - return handle; - return NULL; -} -#endif - -static void photorec_dir_fat(const unsigned char *buffer, const unsigned int read_size, const unsigned long long sector) -{ - file_info_t dir_list; - TD_INIT_LIST_HEAD(&dir_list.list); - dir_fat_aux(buffer, read_size, 0, &dir_list); - if(!td_list_empty(&dir_list.list)) - { - log_info("Sector %llu\n", sector); - dir_aff_log(NULL, &dir_list); - delete_list_file(&dir_list); - } -} - -static pstatus_t photorec_new_file(file_recovery_t *file_recovery, struct ph_param *params, const uint64_t offset) -{ - set_filename(file_recovery, params); - if(file_recovery->file_stat->file_hint->recover==1) - { -#if defined(__CYGWIN__) || defined(__MINGW32__) - file_recovery->handle=fopen_with_retry(file_recovery->filename,"w+b"); -#else - file_recovery->handle=fopen(file_recovery->filename,"w+b"); -#endif - if(!file_recovery->handle) - { - log_critical("Cannot create file %s: %s\n", file_recovery->filename, strerror(errno)); - params->offset=offset; - return PSTATUS_EACCES; - } - } - 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, pfstatus_t *file_recovered, const uint64_t offset) -{ - *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) - { - 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; - } - 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, pfstatus_t *file_recovered, const uint64_t offset) -{ - const struct td_list_head *tmpl; - const unsigned int blocksize=params->blocksize; - const unsigned int read_size=(blocksize>65536?blocksize:65536); - file_recovery_t file_recovery_new; - file_recovery_new.blocksize=blocksize; - if(file_recovery->file_stat!=NULL && file_recovery->file_stat->file_hint==&file_hint_tar && - header_check_tar(buffer-0x200,0x200, 0, file_recovery, &file_recovery_new)) - { /* Currently saving a tar, do not check the data for know header */ - 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)); - } - return PSTATUS_OK; - } - file_recovery_new.file_stat=NULL; - file_recovery_new.location.start=offset; - td_list_for_each(tmpl, &file_check_list.list) - { - const struct td_list_head *tmp; - const file_check_list_t *pos=td_list_entry_const(tmpl, const file_check_list_t, list); - td_list_for_each(tmp, &pos->file_checks[buffer[pos->offset]].list) - { - const file_check_t *file_check=td_list_entry_const(tmp, const file_check_t, list); - if((file_check->length==0 || memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0) && - 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, offset); - } - } - } - return PSTATUS_OK; -} pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space) { @@ -422,15 +283,6 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options ind_stop=photorec_progressbar(stdscr, params->pass, params, offset, current_time); #endif params->offset=offset; - if(current_time >= next_checkpoint) - { - time_t new_time; - /* Save current progress */ - session_save(list_search_space, params, options); - new_time=time(NULL); - /* If it takes more then 30s to save the session, save every 15 minutes instead of every 5 minutes */ - next_checkpoint=new_time+(current_time+30= next_checkpoint) + next_checkpoint=regular_session_save(list_search_space, params, options, current_time); } } } diff --git a/src/qpsearch.cpp b/src/qpsearch.cpp index 753427af..952fc8f4 100644 --- a/src/qpsearch.cpp +++ b/src/qpsearch.cpp @@ -65,44 +65,8 @@ #include "file_found.h" #include "psearch.h" #include "qphotorec.h" - +#include "photorec_check_header.h" #define READ_SIZE 1024*512 -extern const file_hint_t file_hint_tar; -extern const file_hint_t file_hint_dir; -extern file_check_list_t file_check_list; - -#if defined(__CYGWIN__) || defined(__MINGW32__) -/* Live antivirus protection may open file as soon as they are created by * - * PhotoRec. PhotoRec will not be able to overwrite a file as long as the * - * antivirus is scanning it, so let's wait a little bit if the creation * - * failed. */ - -#ifndef HAVE_SLEEP -#define sleep(x) Sleep((x)*1000) -#endif - -static FILE *fopen_with_retry(const char *path, const char *mode) -{ - FILE *handle; - if((handle=fopen(path, mode))!=NULL) - return handle; -#ifdef __MINGW32__ - Sleep(1000); -#else - sleep(1); -#endif - if((handle=fopen(path, mode))!=NULL) - return handle; -#ifdef __MINGW32__ - Sleep(2000); -#else - sleep(2); -#endif - if((handle=fopen(path, mode))!=NULL) - return handle; - return NULL; -} -#endif pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space) { @@ -132,7 +96,7 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space) previous_time=start_time; next_checkpoint=start_time+5*60; memset(buffer_olddata,0,blocksize); - current_search_space=td_list_entry(list_search_space->list.next, alloc_data_t, list); + current_search_space=td_list_first_entry(&list_search_space->list, alloc_data_t, list); offset=set_search_start(params, ¤t_search_space, list_search_space); if(options->verbose > 0) info_list_search_space(list_search_space, current_search_space, params->disk->sector_size, 0, options->verbose); @@ -143,11 +107,12 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space) (unsigned long long)((params->partition->part_size-1)/params->disk->sector_size)); } params->disk->pread(params->disk, buffer, READ_SIZE, offset); + header_ignored(NULL); while(current_search_space!=list_search_space) { - data_check_t res=DC_SCAN; - int file_recovered=0; + pfstatus_t file_recovered=PFSTATUS_BAD; uint64_t old_offset=offset; + data_check_t res=DC_SCAN; #ifdef DEBUG log_debug("sector %llu\n", (unsigned long long)((offset-params->partition->part_offset)/params->disk->sector_size)); @@ -161,98 +126,7 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space) exit(1); } #endif - { - file_recovery_t file_recovery_new; - file_recovery_new.blocksize=blocksize; - if(file_recovery.file_stat!=NULL && file_recovery.file_stat->file_hint==&file_hint_tar && - header_check_tar(buffer-0x200,0x200,0,&file_recovery,&file_recovery_new)) - { /* Currently saving a tar, do not check the data for know header */ - 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)); - } - } - else - { - struct td_list_head *tmpl; - file_recovery_new.file_stat=NULL; - td_list_for_each(tmpl, &file_check_list.list) - { - struct td_list_head *tmp; - const file_check_list_t *tmp2=td_list_entry(tmpl, file_check_list_t, list); - td_list_for_each(tmp, &tmp2->file_checks[buffer[tmp2->offset]].list) - { - const file_check_t *file_check=td_list_entry(tmp, file_check_t, list); - if((file_check->length==0 || memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0) && - file_check->header_check(buffer, read_size, 0, &file_recovery, &file_recovery_new)!=0) - { - file_recovery_new.file_stat=file_check->file_stat; - break; - } - } - if(file_recovery_new.file_stat!=NULL) - break; - } - if(file_recovery_new.file_stat!=NULL && file_recovery_new.file_stat->file_hint!=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(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 */ - file_info_t dir_list; - TD_INIT_LIST_HEAD(&dir_list.list); - dir_fat_aux(buffer, read_size, 0, &dir_list); - if(!td_list_empty(&dir_list.list)) - { - log_info("Sector %lu\n", - (unsigned long)(file_recovery.location.start/params->disk->sector_size)); - dir_aff_log(NULL, &dir_list); - delete_list_file(&dir_list); - } - } - } - } - } - if(file_recovery.file_stat!=NULL && file_recovery.handle==NULL) - { - set_filename(&file_recovery, params); - if(file_recovery.file_stat->file_hint->recover==1) - { -#if defined(__CYGWIN__) || defined(__MINGW32__) - file_recovery.handle=fopen_with_retry(file_recovery.filename,"w+b"); -#else - file_recovery.handle=fopen(file_recovery.filename,"w+b"); -#endif - if(!file_recovery.handle) - { - log_critical("Cannot create file %s: %s\n", file_recovery.filename, strerror(errno)); - ind_stop=PSTATUS_EACCES; - params->offset=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 */ @@ -319,6 +193,8 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space) } if(res==DC_STOP || res==DC_ERROR) { + if(res==DC_ERROR) + file_recovery.file_size=0; file_recovered=file_finish2(&file_recovery, params, options->paranoid, list_search_space); if(options->lowmem > 0) forget(list_search_space,current_search_space); @@ -327,9 +203,11 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space) if(ind_stop!=PSTATUS_OK) { log_info("PhotoRec has been stopped\n"); - current_search_space=list_search_space; + file_recovery_aborted(&file_recovery, params, list_search_space); + free(buffer_start); + return ind_stop; } - else if(file_recovered==PFSTATUS_BAD) + if(file_recovered==PFSTATUS_BAD) { if(res==DC_SCAN) { @@ -360,16 +238,18 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space) log_trace("End of media\n"); #endif file_recovered=file_finish2(&file_recovery, params, options->paranoid, list_search_space); + if(file_recovered!=PFSTATUS_BAD) + get_prev_location_smart(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); @@ -391,18 +271,16 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space) { previous_time=current_time; QCoreApplication::processEvents(); + params->offset=offset; if(stop_the_recovery) - ind_stop=PSTATUS_STOP; - if(file_recovery.file_stat!=NULL) - params->offset=file_recovery.location.start; - else - params->offset=offset; - if(current_time >= next_checkpoint) { - /* Save current progress */ - session_save(list_search_space, params, options); - next_checkpoint=current_time+5*60; + log_info("QPhotoRec has been stopped\n"); + file_recovery_aborted(&file_recovery, params, list_search_space); + free(buffer_start); + return PSTATUS_STOP; } + if(current_time >= next_checkpoint) + next_checkpoint=regular_session_save(list_search_space, params, options, current_time); } } } diff --git a/src/sessionp.c b/src/sessionp.c index 29024293..7d8c39de 100644 --- a/src/sessionp.c +++ b/src/sessionp.c @@ -317,3 +317,13 @@ int session_save(alloc_data_t *list_free_space, struct ph_param *params, const fclose(f_session); return 0; } + +time_t regular_session_save(alloc_data_t *list_free_space, struct ph_param *params, const struct ph_options *options, time_t current_time) +{ + time_t new_time; + /* Save current progress */ + session_save(list_free_space, params, options); + new_time=time(NULL); + /* If it takes more then 30s to save the session, save every 15 minutes instead of every 5 minutes */ + return new_time+(current_time+30