summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2013-12-21 18:18:55 +0100
committerChristophe Grenier <grenier@cgsecurity.org>2013-12-21 18:18:55 +0100
commitb47b36998a17dccb922bc8a9591c8071f951c14f (patch)
tree9702e81b4ad3b3ac7c7933390711ff869e76f7b5 /src
parent5f4faee1f6f82fb3667653a951714c80932522db (diff)
Remove loc field from struct file_recovery_struct, use location instead
Diffstat (limited to 'src')
-rw-r--r--src/dfxml.c47
-rw-r--r--src/filegen.h3
-rw-r--r--src/phbf.c33
-rw-r--r--src/photorec.c530
-rw-r--r--src/photorec.h5
-rw-r--r--src/pnext.h19
-rw-r--r--src/psearchn.c46
-rw-r--r--src/qpsearch.cpp42
8 files changed, 361 insertions, 364 deletions
diff --git a/src/dfxml.c b/src/dfxml.c
index ce9c1e5..fa63292 100644
--- a/src/dfxml.c
+++ b/src/dfxml.c
@@ -329,51 +329,4 @@ void xml_log_file_recovered(const file_recovery_t *file_recovery)
xml_pop("byte_runs");
xml_pop("fileobject");
}
-
-static void xml_log_file_recovered2_aux(const alloc_data_t *space, const alloc_data_t *file, const uint64_t file_size)
-{
- const struct td_list_head *tmp;
- uint64_t size=0;
- for(tmp=&file->list; tmp!=&space->list; tmp=tmp->next)
- {
- const alloc_data_t *element=td_list_entry_const(tmp, const alloc_data_t, list);
- if(size >= file_size)
- return ;
- if(element->data>0)
- {
- const uint64_t len=element->end - element->start + 1;
- if(size + len < file_size)
- {
- xml_printf("<byte_run offset='%llu' img_offset='%llu' len='%llu'/>\n",
- (long long unsigned)size,
- (long long unsigned)element->start,
- (long long unsigned)len);
- size+=len;
- }
- else
- {
- xml_printf("<byte_run offset='%llu' img_offset='%llu' len='%llu'/>\n",
- (long long unsigned)size,
- (long long unsigned)element->start,
- (long long unsigned)(file_size - size));
- return ;
- }
- }
- }
-}
-
-void xml_log_file_recovered2(const alloc_data_t *space, const file_recovery_t *file_recovery)
-{
- if(xml_handle==NULL)
- return;
- if(file_recovery==NULL || file_recovery->filename[0]=='\0')
- return;
- xml_push("fileobject", "");
- xml_out2s("filename", relative_name(file_recovery->filename));
- xml_out2i("filesize", file_recovery->file_size);
- xml_push("byte_runs", "");
- xml_log_file_recovered2_aux(space, file_recovery->loc, file_recovery->file_size);
- xml_pop("byte_runs");
- xml_pop("fileobject");
-}
#endif
diff --git a/src/filegen.h b/src/filegen.h
index cef597b..0b85f7b 100644
--- a/src/filegen.h
+++ b/src/filegen.h
@@ -66,7 +66,6 @@ struct file_recovery_struct
{
char filename[2048];
alloc_list_t location;
- alloc_data_t *loc;
file_stat_t *file_stat;
FILE *handle;
time_t time;
@@ -79,7 +78,7 @@ struct file_recovery_struct
uint64_t extra; /* extra bytes between offset_ok and offset_error */
uint64_t calculated_file_size;
data_check_t (*data_check)(const unsigned char*buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
- /* It can modify file_recovery->calculated_file_size, not must not modify file_recovery->file_size */
+ /* data_check modifies file_recovery->calculated_file_size but not must alter file_recovery->file_size */
void (*file_check)(file_recovery_t *file_recovery);
void (*file_rename)(const char *old_filename);
uint64_t checkpoint_offset;
diff --git a/src/phbf.c b/src/phbf.c
index e0d6b77..68045fe 100644
--- a/src/phbf.c
+++ b/src/phbf.c
@@ -79,31 +79,6 @@ typedef enum { BF_OK=0, BF_STOP=1, BF_EACCES=2, BF_ENOSPC=3, BF_FRAG_FOUND=4, BF
static pstatus_t photorec_bf_aux(struct ph_param *params, file_recovery_t *file_recovery, alloc_data_t *list_search_space, alloc_data_t *start_search_space, const int phase);
static bf_status_t photorec_bf_frag(struct ph_param *params, file_recovery_t *file_recovery, alloc_data_t *list_search_space, alloc_data_t *start_search_space, const int phase, alloc_data_t **current_search_space, uint64_t *offset, unsigned char *buffer, unsigned char *block_buffer, const unsigned int frag);
-#ifdef DEBUG_BF
-static void list_space_used(const file_recovery_t *file_recovery, const unsigned int sector_size)
-{
- struct td_list_head *tmp;
- uint64_t file_size=0;
- if(file_recovery->filename==NULL)
- return;
- log_info("%s\t",file_recovery->filename);
- td_list_for_each(tmp, &file_recovery->location.list)
- {
- const alloc_list_t *element=td_list_entry(tmp, alloc_list_t, list);
- if(element->data>0)
- {
- log_info(" %lu-%lu", (unsigned long)(element->start/sector_size), (unsigned long)(element->end/sector_size));
- file_size+=(element->end-element->start+1);
- }
- else
- {
- log_info(" (%lu-%lu)", (unsigned long)(element->start/sector_size), (unsigned long)(element->end/sector_size));
- }
- }
- log_info("\n");
-}
-#endif
-
static inline void file_recovery_cpy(file_recovery_t *dst, file_recovery_t *src)
{
memcpy(dst, src, sizeof(*dst));
@@ -428,7 +403,7 @@ static bf_status_t photorec_bf_pad(struct ph_param *params, file_recovery_t *fil
}
#ifdef DEBUG_BF
log_trace("BF ");
- list_space_used(file_recovery, 512);
+ file_block_log(file_recovery, 512);
#endif
file_size_backup=file_recovery->file_size;
file_recovery->flags=1;
@@ -470,7 +445,7 @@ static bf_status_t photorec_bf_pad(struct ph_param *params, file_recovery_t *fil
(unsigned long long)file_offset,
(unsigned long long)file_recovery->offset_error,
blocksize);
- list_space_used(file_recovery, 512);
+ file_block_log(file_recovery, 512);
#endif
return BF_FRAG_FOUND;
}
@@ -648,7 +623,7 @@ static bf_status_t photorec_bf_frag(struct ph_param *params, file_recovery_t *fi
log_info("photorec_bf_aux %s split file at %llu\n",
file_recovery->filename,
(long long unsigned)file_offset);
- // list_space_used(file_recovery, 512);
+ // file_block_log(file_recovery, 512);
#endif
/* Get the last block added to the file */
extrablock_offset=0;
@@ -833,7 +808,7 @@ static pstatus_t photorec_bf_aux(struct ph_param *params, file_recovery_t *file_
file_recovery->offset_error=file_recovery->file_size;
#ifdef DEBUG_BF
log_trace("BF Amorce ");
- list_space_used(file_recovery, 512);
+ file_block_log(file_recovery, 512);
log_trace("\n");
#endif
ind_stop=photorec_bf_frag(params, file_recovery, list_search_space, start_search_space, phase, &current_search_space, &offset, buffer, block_buffer, 0);
diff --git a/src/photorec.c b/src/photorec.c
index af7bb99..6384576 100644
--- a/src/photorec.c
+++ b/src/photorec.c
@@ -61,40 +61,25 @@
static void update_search_space(const file_recovery_t *file_recovery, alloc_data_t *list_search_space, alloc_data_t **new_current_search_space, uint64_t *offset, const unsigned int blocksize);
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 alloc_data_t *file_truncate(alloc_data_t *space, file_recovery_t *file, const unsigned int sector_size, const unsigned int blocksize);
-static alloc_data_t *file_error(alloc_data_t *space, file_recovery_t *file, const unsigned int blocksize);
static void list_free_add(const file_recovery_t *file_recovery, alloc_data_t *list_search_space);
-static void list_space_used(const file_recovery_t *file_recovery, const unsigned int sector_size);
+void file_block_truncate_zero(const file_recovery_t *file_recovery, alloc_data_t *list_search_space);
+void file_block_truncate(const file_recovery_t *file_recovery, alloc_data_t *list_search_space, const unsigned int blocksize, const uint64_t file_size);
-static void list_space_used(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)
{
struct td_list_head *tmp;
- uint64_t file_size=0;
- uint64_t file_size_on_disk=0;
if(file_recovery->filename[0]=='\0')
return;
log_info("%s\t",file_recovery->filename);
td_list_for_each(tmp, &file_recovery->location.list)
{
const alloc_list_t *element=td_list_entry(tmp, alloc_list_t, list);
- file_size_on_disk+=(element->end-element->start+1);
if(element->data>0)
- {
log_info(" %lu-%lu", (unsigned long)(element->start/sector_size), (unsigned long)(element->end/sector_size));
- file_size+=(element->end-element->start+1);
- }
else
- {
log_info(" (%lu-%lu)", (unsigned long)(element->start/sector_size), (unsigned long)(element->end/sector_size));
- }
}
log_info("\n");
- /*
- log_trace("list file_size %lu, file_size_on_disk %lu\n",
- (unsigned long)file_size, (unsigned long)file_size_on_disk);
- log_trace("file_size %lu, file_size_on_disk %lu\n",
- (unsigned long)file_recovery->file_size, (unsigned long)file_recovery->file_size_on_disk);
- */
}
static void list_free_add(const file_recovery_t *file_recovery, alloc_data_t *list_search_space)
@@ -548,7 +533,7 @@ void update_blocksize(unsigned int blocksize, alloc_data_t *list_search_space, c
uint64_t free_list_allocation_end=0;
-static void free_list_allocation(alloc_list_t *list_allocation)
+void file_block_free(alloc_list_t *list_allocation)
{
struct td_list_head *tmp = NULL;
struct td_list_head *tmp_next = NULL;
@@ -569,26 +554,24 @@ static void free_list_allocation(alloc_list_t *list_allocation)
static void file_finish_aux(file_recovery_t *file_recovery, struct ph_param *params, const int paranoid)
{
if(params->status!=STATUS_EXT2_ON_SAVE_EVERYTHING &&
- params->status!=STATUS_EXT2_OFF_SAVE_EVERYTHING)
- {
- if(file_recovery->file_stat!=NULL && file_recovery->file_check!=NULL && paranoid>0)
+ params->status!=STATUS_EXT2_OFF_SAVE_EVERYTHING &&
+ file_recovery->file_stat!=NULL && file_recovery->file_check!=NULL && paranoid>0)
{ /* Check if recovered file is valid */
file_recovery->file_check(file_recovery);
}
- /* FIXME: need to adapt read_size to volume size to avoid this */
- if(file_recovery->file_size > params->disk->disk_size)
- file_recovery->file_size = params->disk->disk_size;
- if(file_recovery->file_size > params->disk->disk_real_size)
- file_recovery->file_size = params->disk->disk_real_size;
- if(file_recovery->file_stat!=NULL && file_recovery->file_size> 0 &&
- file_recovery->file_size < file_recovery->min_filesize)
- {
- log_info("File too small ( %llu < %llu), reject it\n",
- (long long unsigned) file_recovery->file_size,
- (long long unsigned) file_recovery->min_filesize);
- file_recovery->file_size=0;
- file_recovery->file_size_on_disk=0;
- }
+ /* FIXME: need to adapt read_size to volume size to avoid this */
+ if(file_recovery->file_size > params->disk->disk_size)
+ file_recovery->file_size = params->disk->disk_size;
+ if(file_recovery->file_size > params->disk->disk_real_size)
+ file_recovery->file_size = params->disk->disk_real_size;
+ if(file_recovery->file_stat!=NULL && file_recovery->file_size> 0 &&
+ file_recovery->file_size < file_recovery->min_filesize)
+ {
+ log_info("File too small ( %llu < %llu), reject it\n",
+ (long long unsigned) file_recovery->file_size,
+ (long long unsigned) file_recovery->min_filesize);
+ file_recovery->file_size=0;
+ file_recovery->file_size_on_disk=0;
}
if(file_recovery->file_size==0)
{
@@ -596,31 +579,29 @@ static void file_finish_aux(file_recovery_t *file_recovery, struct ph_param *par
file_recovery->handle=NULL;
/* File is zero-length; erase it */
unlink(file_recovery->filename);
+ return;
}
- else
- {
#ifdef HAVE_FTRUNCATE
- fflush(file_recovery->handle);
- if(ftruncate(fileno(file_recovery->handle), file_recovery->file_size)<0)
- {
- log_critical("ftruncate failed.\n");
- }
+ fflush(file_recovery->handle);
+ if(ftruncate(fileno(file_recovery->handle), file_recovery->file_size)<0)
+ {
+ log_critical("ftruncate failed.\n");
+ }
#endif
- fclose(file_recovery->handle);
- file_recovery->handle=NULL;
- if(file_recovery->time!=0 && file_recovery->time!=(time_t)-1)
- set_date(file_recovery->filename, file_recovery->time, file_recovery->time);
- if(file_recovery->file_rename!=NULL)
- file_recovery->file_rename(file_recovery->filename);
- if((++params->file_nbr)%MAX_FILES_PER_DIR==0)
- {
- params->dir_num=photorec_mkdir(params->recup_dir, params->dir_num+1);
- }
- if(params->status!=STATUS_EXT2_ON_SAVE_EVERYTHING &&
- params->status!=STATUS_EXT2_OFF_SAVE_EVERYTHING &&
- file_recovery->file_stat!=NULL)
- file_recovery->file_stat->recovered++;
+ fclose(file_recovery->handle);
+ file_recovery->handle=NULL;
+ if(file_recovery->time!=0 && file_recovery->time!=(time_t)-1)
+ set_date(file_recovery->filename, file_recovery->time, file_recovery->time);
+ if(file_recovery->file_rename!=NULL)
+ file_recovery->file_rename(file_recovery->filename);
+ if((++params->file_nbr)%MAX_FILES_PER_DIR==0)
+ {
+ params->dir_num=photorec_mkdir(params->recup_dir, params->dir_num+1);
}
+ if(params->status!=STATUS_EXT2_ON_SAVE_EVERYTHING &&
+ params->status!=STATUS_EXT2_OFF_SAVE_EVERYTHING &&
+ file_recovery->file_stat!=NULL)
+ file_recovery->file_stat->recovered++;
}
/** file_finish()
@@ -639,50 +620,33 @@ static void file_finish_aux(file_recovery_t *file_recovery, struct ph_param *par
int file_finish(file_recovery_t *file_recovery, struct ph_param *params,
alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset)
{
- int file_recovered=0;
-#ifdef DEBUG_FILE_FINISH
- log_debug("file_finish start %lu (%lu-%lu)\n", (long unsigned int)((*offset)/params->blocksize),
- (unsigned long int)((*current_search_space)->start/params->blocksize),
- (unsigned long int)((*current_search_space)->end/params->blocksize));
- log_debug("file_recovery->offset_error=%llu\n", (long long unsigned)file_recovery->offset_error);
- log_debug("file_recovery->handle %s NULL\n", (file_recovery->handle!=NULL?"!=":"=="));
- info_list_search_space(list_search_space, NULL, DEFAULT_SECTOR_SIZE, 0, 1);
-#endif
+ if(file_recovery->file_stat==NULL)
+ return 0;
if(file_recovery->handle)
file_finish_aux(file_recovery, params, 1);
- if(file_recovery->file_stat!=NULL)
+ if(file_recovery->file_size==0)
{
list_truncate(&file_recovery->location,file_recovery->file_size);
- if(file_recovery->file_size==0)
- {
- /* File hasn't been sucessfully recovered, remember where it begins */
- list_free_add(file_recovery, list_search_space);
- if((*current_search_space)!=list_search_space &&
- !((*current_search_space)->start <= *offset && *offset <= (*current_search_space)->end))
- *current_search_space=td_list_entry((*current_search_space)->list.next, alloc_data_t, list);
- }
- else
- {
- list_space_used(file_recovery, params->disk->sector_size);
-#ifdef ENABLE_DFXML
- xml_log_file_recovered(file_recovery);
-#endif
- update_search_space(file_recovery, list_search_space, current_search_space, offset, params->blocksize);
- file_recovered=1; /* note that file was recovered */
- }
- free_list_allocation(&file_recovery->location);
- }
- if(file_recovery->file_size==0 && file_recovery->offset_error!=0)
- file_recovered = -1;
- else
+ /* File hasn't been sucessfully recovered, remember where it begins */
+ list_free_add(file_recovery, list_search_space);
+ if((*current_search_space)!=list_search_space &&
+ !((*current_search_space)->start <= *offset && *offset <= (*current_search_space)->end))
+ *current_search_space=td_list_entry((*current_search_space)->list.next, alloc_data_t, list);
+ file_block_free(&file_recovery->location);
+ if(file_recovery->offset_error!=0)
+ return -1;
reset_file_recovery(file_recovery);
-#ifdef DEBUG_FILE_FINISH
- log_debug("file_finish end %lu (%lu-%lu)\n\n", (long unsigned int)((*offset)/params->blocksize),
- (unsigned long int)((*current_search_space)->start/params->blocksize),
- (unsigned long int)((*current_search_space)->end/params->blocksize));
- info_list_search_space(list_search_space, NULL, DEFAULT_SECTOR_SIZE, 0, 1);
+ return 0;
+ }
+ list_truncate(&file_recovery->location,file_recovery->file_size);
+ file_block_log(file_recovery, params->disk->sector_size);
+#ifdef ENABLE_DFXML
+ xml_log_file_recovered(file_recovery);
#endif
- return file_recovered;
+ update_search_space(file_recovery, list_search_space, current_search_space, offset, params->blocksize);
+ file_block_free(&file_recovery->location);
+ reset_file_recovery(file_recovery);
+ return 1;
}
/* file_finish2()
@@ -698,52 +662,26 @@ int file_finish(file_recovery_t *file_recovery, struct ph_param *params,
0: file not recovered
1: file recovered
*/
-int file_finish2(file_recovery_t *file_recovery, struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset)
+int file_finish2(file_recovery_t *file_recovery, struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space)
{
- int file_recovered=0;
-#ifdef DEBUG_FILE_FINISH
- log_debug("file_recovery->offset_error=%llu\n", (long long unsigned)file_recovery->offset_error);
- log_debug("file_recovery->handle %s NULL\n", (file_recovery->handle!=NULL?"!=":"=="));
- info_list_search_space(list_search_space, NULL, DEFAULT_SECTOR_SIZE, 0, 1);
-#endif
+ if(file_recovery->file_stat==NULL)
+ return 0;
if(file_recovery->handle)
file_finish_aux(file_recovery, params, options->paranoid);
- if(file_recovery->file_stat!=NULL)
- {
- if(file_recovery->file_size==0)
- {
- /* File hasn't been sucessfully recovered */
- if(file_recovery->offset_error>0)
- {
- alloc_data_t *datanext=file_error(list_search_space, file_recovery, params->blocksize);
- if(datanext!=NULL)
- {
- *current_search_space=datanext;
- *offset=datanext->start;
- file_recovered=-1;
- }
- }
- }
- else
- {
-#ifdef ENABLE_DFXML
- xml_log_file_recovered2(list_search_space, file_recovery);
-#endif
- *current_search_space=file_truncate(list_search_space, file_recovery, params->disk->sector_size, params->blocksize);
- *offset=(*current_search_space)->start;
- file_recovered=1;
- }
- free_list_allocation(&file_recovery->location);
- }
- if(file_recovery->file_size==0 && file_recovery->offset_error!=0)
+ if(file_recovery->file_size==0)
{
- }
- else
+ file_block_truncate_zero(file_recovery, list_search_space);
reset_file_recovery(file_recovery);
-#ifdef DEBUG_FILE_FINISH
- info_list_search_space(list_search_space, NULL, DEFAULT_SECTOR_SIZE, 0, 1);
+ return 0;
+ }
+ file_block_truncate(file_recovery, list_search_space, params->blocksize, file_recovery->file_size);
+ file_block_log(file_recovery, params->disk->sector_size);
+#ifdef ENABLE_DFXML
+ xml_log_file_recovered(file_recovery);
#endif
- return file_recovered;
+ file_block_free(&file_recovery->location);
+ reset_file_recovery(file_recovery);
+ return 1;
}
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)
@@ -778,114 +716,6 @@ void info_list_search_space(const alloc_data_t *list_search_space, const alloc_d
(keep_corrupted_file>0?"but saved":"and rejected"));
}
-static alloc_data_t *file_truncate_aux(alloc_data_t *space, alloc_data_t *file, const uint64_t file_size, const unsigned int sector_size, const unsigned int blocksize)
-{
- struct td_list_head *tmp;
- struct td_list_head *next;
- uint64_t size=0;
- const uint64_t file_size_on_disk=(file_size+blocksize-1)/blocksize*blocksize;
- for(tmp=&file->list, next=tmp->next; tmp!=&space->list; tmp=next, next=tmp->next)
- {
- alloc_data_t *element=td_list_entry(tmp, alloc_data_t, list);
- if(size >= file_size)
- return element;
- if(element->data>0)
- {
- const uint64_t len=element->end - element->start + 1;
- if(size + len <= file_size_on_disk)
- {
- size+=len;
- log_info(" %lu-%lu", (unsigned long)(element->start/sector_size), (unsigned long)(element->end/sector_size));
- td_list_del(tmp);
- free(element);
- }
- else
- {
- log_info(" %lu-%lu",
- (unsigned long)(element->start/sector_size),
- (unsigned long)((element->start + file_size_on_disk - size - 1)/sector_size));
- element->start+=file_size_on_disk - size;
- element->file_stat=NULL;
- element->data=1;
- return element;
- }
- }
- else
- {
- log_info(" (%lu-%lu)", (unsigned long)(element->start/sector_size), (unsigned long)(element->end/sector_size));
- td_list_del(tmp);
- free(element);
- }
- }
- return space;
-}
-
-static alloc_data_t *file_truncate(alloc_data_t *space, file_recovery_t *file, const unsigned int sector_size, const unsigned int blocksize)
-{
- alloc_data_t *datanext;
- if(file->filename[0]!='\0')
- log_info("%s\t", file->filename);
- else
- log_info("?\t");
- datanext=file_truncate_aux(space, file->loc, file->file_size, sector_size, blocksize);
- log_info("\n");
- return datanext;
-}
-
-static alloc_data_t *file_error_aux(alloc_data_t *space, alloc_data_t *file, const uint64_t file_size, const unsigned int blocksize)
-{
- struct td_list_head *tmp;
- struct td_list_head *next;
- uint64_t size=0;
- const uint64_t file_size_on_disk=file_size/blocksize*blocksize;
- for(tmp=&file->list, next=tmp->next; tmp!=&space->list; tmp=next, next=tmp->next)
- {
- alloc_data_t *element=td_list_entry(tmp, alloc_data_t, list);
- if(size >= file_size)
- return NULL;
- if(element->data>0)
- {
- if(size + (element->end-element->start+1) <= file_size_on_disk)
- {
- size=size + (element->end-element->start+1);
- }
- else if(file_size_on_disk > size)
- {
- if(element->file_stat==NULL)
- return NULL;
- if(next!=&space->list)
- {
- alloc_data_t *new_element;
- new_element=td_list_entry(next, alloc_data_t, list);
- if(element->end+1==new_element->start && new_element->file_stat==NULL)
- {
- new_element->start-=file_size_on_disk - size;
- element->end=new_element->start - 1;
- return new_element;
- }
- }
- {
- alloc_data_t *new_element;
- new_element=(alloc_data_t*)MALLOC(sizeof(*new_element));
- memcpy(new_element, element, sizeof(*new_element));
- new_element->start+=file_size_on_disk - size;
- new_element->file_stat=NULL;
- new_element->data=1;
- td_list_add(&new_element->list, &element->list);
- element->end=new_element->start - 1;
- return new_element;
- }
- }
- }
- }
- return NULL;
-}
-
-static alloc_data_t *file_error(alloc_data_t *space, file_recovery_t *file, const unsigned int blocksize)
-{
- return file_error_aux(space, file->loc, file->offset_error, blocksize);
-}
-
void free_search_space(alloc_data_t *list_search_space)
{
struct td_list_head *search_walker = NULL;
@@ -1059,3 +889,217 @@ list_part_t *init_list_part(disk_t *disk, const struct ph_options *options)
}
return list_part;
}
+
+/* file_block_remove_from_sp: remove block from list_search_space, update offset and new_current_search_space in consequence */
+static int file_block_remove_from_sp(alloc_data_t *list_search_space, alloc_data_t **new_current_search_space, uint64_t *offset, const unsigned int blocksize)
+{
+ struct td_list_head *search_walker = NULL;
+ td_list_for_each(search_walker, &list_search_space->list)
+ {
+ alloc_data_t *tmp;
+ tmp=td_list_entry(search_walker, alloc_data_t, list);
+ if(tmp->start <= *offset &&
+ *offset + blocksize - 1 <= tmp->end)
+ {
+ if(tmp->start == *offset)
+ {
+ tmp->start+=blocksize;
+ *offset += blocksize;
+ tmp->file_stat=NULL;
+ if(tmp->start < tmp->end)
+ return 0;
+ *new_current_search_space=td_list_entry(tmp->list.next, alloc_data_t, list);
+ *offset=(*new_current_search_space)->start;
+ td_list_del(search_walker);
+ free(tmp);
+ return 0;
+ }
+ if(*offset + blocksize == tmp->end)
+ {
+ tmp->end-=blocksize;
+ *new_current_search_space=td_list_entry(tmp->list.next, alloc_data_t, list);
+ *offset=(*new_current_search_space)->start;
+ return 0;
+ }
+ {
+ alloc_data_t *new_sp;
+ new_sp=(alloc_data_t*)MALLOC(sizeof(*new_sp));
+ new_sp->start=*offset + blocksize;
+ new_sp->end=tmp->end;
+ new_sp->file_stat=NULL;
+ new_sp->data=tmp->data;
+ new_sp->list.prev=&new_sp->list;
+ new_sp->list.next=&new_sp->list;
+ tmp->end=*offset - 1;
+ td_list_add(&new_sp->list, &tmp->list);
+ *new_current_search_space=new_sp;
+ *offset += blocksize;
+ }
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static inline void file_block_add_to_file(alloc_list_t *list, const uint64_t offset, const uint64_t blocksize, const unsigned int data)
+{
+ if(!td_list_empty(&list->list))
+ {
+ alloc_list_t *prev=td_list_entry(list->list.prev, alloc_list_t, list);
+ if(prev->end+1==offset && prev->data==data)
+ {
+ prev->end=offset+blocksize-1;
+ return ;
+ }
+ }
+ {
+ alloc_list_t *new_list=(alloc_list_t *)MALLOC(sizeof(*new_list));
+ new_list->start=offset;
+ new_list->end=offset+blocksize-1;
+ new_list->data=data;
+ td_list_add_tail(&new_list->list, &list->list);
+ }
+}
+
+void file_block_append(file_recovery_t *file_recovery, alloc_data_t *list_search_space, alloc_data_t **new_current_search_space, uint64_t *offset, const unsigned int blocksize, const unsigned int data)
+{
+ file_block_add_to_file(&file_recovery->location, *offset, blocksize, data);
+ file_block_remove_from_sp(list_search_space, new_current_search_space, offset, blocksize);
+}
+
+static void file_block_truncate_aux(const uint64_t start, const uint64_t end, alloc_data_t *list_search_space)
+{
+ struct td_list_head *search_walker = NULL;
+ if(start >= end)
+ return ;
+ td_list_for_each(search_walker, &list_search_space->list)
+ {
+ alloc_data_t *tmp;
+ tmp=td_list_entry(search_walker, alloc_data_t, list);
+ if(tmp->start == end + 1 && tmp->file_stat==NULL)
+ {
+ tmp->start=start;
+ return;
+ }
+ if(tmp->end + 1 == start)
+ {
+ tmp->end=end;
+ return;
+ }
+ if(end < tmp->start)
+ {
+ alloc_data_t *new_sp;
+ new_sp=(alloc_data_t*)MALLOC(sizeof(*new_sp));
+ new_sp->start=start;
+ new_sp->end=end;
+ new_sp->file_stat=NULL;
+ new_sp->data=1;
+ new_sp->list.prev=&new_sp->list;
+ new_sp->list.next=&new_sp->list;
+ td_list_add(&new_sp->list, tmp->list.prev);
+ return;
+ }
+ }
+ {
+ alloc_data_t *new_sp;
+ new_sp=(alloc_data_t*)MALLOC(sizeof(*new_sp));
+ new_sp->start=start;
+ new_sp->end=end;
+ new_sp->file_stat=NULL;
+ new_sp->data=1;
+ new_sp->list.prev=&new_sp->list;
+ new_sp->list.next=&new_sp->list;
+ td_list_add_tail(&new_sp->list, &list_search_space->list);
+ }
+}
+
+static void file_block_truncate_zero_aux(const uint64_t start, const uint64_t end, alloc_data_t *list_search_space, file_stat_t *file_stat)
+{
+ struct td_list_head *search_walker = NULL;
+ if(start >= end)
+ return ;
+ td_list_for_each(search_walker, &list_search_space->list)
+ {
+ alloc_data_t *tmp;
+ tmp=td_list_entry(search_walker, alloc_data_t, list);
+ if(tmp->start == end + 1 && tmp->file_stat==NULL)
+ {
+ tmp->start=start;
+ tmp->file_stat=file_stat;
+ return;
+ }
+ if(end < tmp->start)
+ {
+ alloc_data_t *new_sp;
+ new_sp=(alloc_data_t*)MALLOC(sizeof(*new_sp));
+ new_sp->start=start;
+ new_sp->end=end;
+ new_sp->file_stat=file_stat;
+ new_sp->data=1;
+ new_sp->list.prev=&new_sp->list;
+ new_sp->list.next=&new_sp->list;
+ td_list_add(&new_sp->list, tmp->list.prev);
+ return;
+ }
+ }
+ {
+ alloc_data_t *new_sp;
+ new_sp=(alloc_data_t*)MALLOC(sizeof(*new_sp));
+ new_sp->start=start;
+ new_sp->end=end;
+ new_sp->file_stat=file_stat;
+ new_sp->data=1;
+ new_sp->list.prev=&new_sp->list;
+ new_sp->list.next=&new_sp->list;
+ td_list_add_tail(&new_sp->list, &list_search_space->list);
+ }
+}
+
+void file_block_truncate_zero(const file_recovery_t *file_recovery, alloc_data_t *list_search_space)
+{
+ struct td_list_head *tmp;
+ struct td_list_head *next;
+ int first=1;
+ td_list_for_each_safe(tmp, next, &file_recovery->location.list)
+ {
+ alloc_list_t *element=td_list_entry(tmp, alloc_list_t, list);
+ if(first)
+ {
+ file_block_truncate_zero_aux(element->start, element->end, list_search_space, file_recovery->file_stat);
+ first=1;
+ }
+ else
+ file_block_truncate_aux(element->start, element->end, list_search_space);
+ td_list_del(tmp);
+ free(element);
+ }
+}
+
+void file_block_truncate(const file_recovery_t *file_recovery, alloc_data_t *list_search_space, const unsigned int blocksize, const uint64_t file_size)
+{
+ struct td_list_head *tmp;
+ struct td_list_head *next;
+ uint64_t size=0;
+ td_list_for_each_safe(tmp, next, &file_recovery->location.list)
+ {
+ alloc_list_t *element=td_list_entry(tmp, alloc_list_t, list);
+ if(size>=file_size)
+ {
+ file_block_truncate_aux(element->start, element->end, list_search_space);
+ td_list_del(tmp);
+ free(element);
+ }
+ else if(element->data>0)
+ {
+ if(size + element->end - element->start + 1 > file_size)
+ {
+ const uint64_t diff=(file_size - size + blocksize - 1) / blocksize * blocksize;
+ file_block_truncate_aux(element->start + diff, element->end, list_search_space);
+ element->end-=element->end - element->start + 1 - diff;
+ size=file_size;
+ }
+ else
+ size+=(element->end-element->start+1);
+ }
+ }
+}
diff --git a/src/photorec.h b/src/photorec.h
index 70a7853..31598ad 100644
--- a/src/photorec.h
+++ b/src/photorec.h
@@ -66,7 +66,7 @@ struct ph_param
int get_prev_file_header(alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset);
int file_finish(file_recovery_t *file_recovery, struct ph_param *params,
alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset);
-int file_finish2(file_recovery_t *file_recovery, struct ph_param *params, const struct ph_options *options, alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset);
+int file_finish2(file_recovery_t *file_recovery, struct ph_param *params, const struct ph_options *options, 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);
@@ -86,6 +86,9 @@ void params_reset(struct ph_param *params, const struct ph_options *options);
const char *status_to_name(const photorec_status_t status);
void status_inc(struct ph_param *params, const struct ph_options *options);
list_part_t *init_list_part(disk_t *disk, const struct ph_options *options);
+void file_block_log(const file_recovery_t *file_recovery, const unsigned int sector_size);
+void file_block_free(alloc_list_t *list_allocation);
+void file_block_append(file_recovery_t *file_recovery, alloc_data_t *list_search_space, alloc_data_t **new_current_search_space, uint64_t *offset, const unsigned int blocksize, const unsigned int data);
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
diff --git a/src/pnext.h b/src/pnext.h
index fe2ce19..20088d6 100644
--- a/src/pnext.h
+++ b/src/pnext.h
@@ -71,3 +71,22 @@ void get_next_sector(alloc_data_t *list_search_space, alloc_data_t **current_sea
else
get_next_header(list_search_space, current_search_space, offset);
}
+
+static inline void get_prev_header(alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset, const unsigned int blocksize)
+{
+ if((*current_search_space) != list_search_space)
+ *current_search_space=td_list_entry((*current_search_space)->list.prev, alloc_data_t, list);
+ *offset=(*current_search_space)->end + 1 - blocksize;
+}
+
+static inline void get_prev_sector(alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset, const unsigned int blocksize)
+{
+ if((*current_search_space) == list_search_space)
+ {
+ return ;
+ }
+ if((*offset) >= (*current_search_space)->start + blocksize)
+ *offset-=blocksize;
+ else
+ get_prev_header(list_search_space, current_search_space, offset, blocksize);
+}
diff --git a/src/psearchn.c b/src/psearchn.c
index f4ae0f1..536feb7 100644
--- a/src/psearchn.c
+++ b/src/psearchn.c
@@ -150,6 +150,7 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
{
int file_recovered=0;
uint64_t old_offset=offset;
+ int res=DC_SCAN;
#ifdef DEBUG
log_debug("sector %llu\n",
(unsigned long long)((offset-params->partition->part_offset)/params->disk->sector_size));
@@ -188,6 +189,7 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
{
struct td_list_head *tmp;
const file_check_list_t *pos=td_list_entry(tmpl, file_check_list_t, list);
+ file_recovery_new.location.start=offset;
td_list_for_each(tmp, &pos->file_checks[buffer[pos->offset]].list)
{
const file_check_t *file_check=td_list_entry(tmp, file_check_t, list);
@@ -203,17 +205,15 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
}
if(file_recovery_new.file_stat!=NULL && file_recovery_new.file_stat->file_hint!=NULL)
{
- current_search_space=file_found(current_search_space, offset, file_recovery_new.file_stat);
- file_recovery_new.loc=current_search_space;
file_recovery_new.location.start=offset;
- if(options->verbose > 1)
- log_trace("A known header has been found, recovery of the previous file is finished\n");
+ if(file_recovery.file_stat!=NULL)
{
- file_recovered=file_finish2(&file_recovery, params, options, list_search_space, &current_search_space, &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, list_search_space);
+ if(options->lowmem > 0)
+ forget(list_search_space,current_search_space);
}
- reset_file_recovery(&file_recovery);
- if(options->lowmem > 0)
- forget(list_search_space,current_search_space);
if(file_recovered==0)
{
file_recovery_cpy(&file_recovery, &file_recovery_new);
@@ -266,13 +266,13 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
}
if(file_recovery.file_stat!=NULL)
{
- int res=DC_CONTINUE;
/* try to skip ext2/ext3 indirect block */
if((params->status==STATUS_EXT2_ON || params->status==STATUS_EXT2_ON_SAVE_EVERYTHING) &&
file_recovery.file_size_on_disk>=12*blocksize &&
ind_block(buffer,blocksize)!=0)
{
- current_search_space=file_add_data(current_search_space, offset, 0);
+ file_block_append(&file_recovery, list_search_space, &current_search_space, &offset, blocksize, 0);
+ res=DC_CONTINUE;
file_recovery.file_size_on_disk+=blocksize;
if(options->verbose > 1)
{
@@ -304,9 +304,11 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
}
if(ind_stop==PSTATUS_OK)
{
- current_search_space=file_add_data(current_search_space, offset, 1);
+ file_block_append(&file_recovery, list_search_space, &current_search_space, &offset, blocksize, 1);
if(file_recovery.data_check!=NULL)
res=file_recovery.data_check(buffer_olddata,2*blocksize,&file_recovery);
+ else
+ res=DC_CONTINUE;
file_recovery.file_size+=blocksize;
file_recovery.file_size_on_disk+=blocksize;
if(res==DC_STOP)
@@ -322,16 +324,15 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
log_verbose("File should not be bigger than %llu, stop adding data\n",
(long long unsigned)file_recovery.file_stat->file_hint->max_filesize);
}
- if(res!=DC_STOP && res!=DC_ERROR && file_recovery.file_size + blocksize >= PHOTOREC_MAX_SIZE_32 && is_fat(params->partition))
+ if(res!=DC_STOP && res!=DC_ERROR && file_recovery.file_size + blocksize >= PHOTOREC_MAX_SIZE_32 && is_fat(params->partition))
{
- res=DC_STOP;
+ res=DC_STOP;
log_verbose("File should not be bigger than %llu, stop adding data\n",
(long long unsigned)file_recovery.file_stat->file_hint->max_filesize);
}
if(res==DC_STOP || res==DC_ERROR)
{
- file_recovered=file_finish2(&file_recovery, params, options, list_search_space, &current_search_space, &offset);
- reset_file_recovery(&file_recovery);
+ file_recovered=file_finish2(&file_recovery, params, options, list_search_space);
if(options->lowmem > 0)
forget(list_search_space,current_search_space);
}
@@ -343,9 +344,12 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
}
else if(file_recovered==0)
{
- get_next_sector(list_search_space, &current_search_space,&offset,blocksize);
- if(offset > offset_before_back)
- back=0;
+ if(res==DC_SCAN)
+ {
+ get_next_sector(list_search_space, &current_search_space,&offset,blocksize);
+ if(offset > offset_before_back)
+ back=0;
+ }
}
else if(file_recovered>0)
{
@@ -364,8 +368,7 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
current_search_space, current_search_space->list.prev, current_search_space->list.next);
log_trace("End of media\n");
#endif
- file_recovered=file_finish2(&file_recovery, params, options, list_search_space, &current_search_space, &offset);
- reset_file_recovery(&file_recovery);
+ file_recovered=file_finish2(&file_recovery, params, options, list_search_space);
if(options->lowmem > 0)
forget(list_search_space,current_search_space);
}
@@ -398,8 +401,7 @@ pstatus_t photorec_aux(struct ph_param *params, const struct ph_options *options
}
if(ind_stop==PSTATUS_OK)
{
- time_t current_time;
- current_time=time(NULL);
+ const time_t current_time=time(NULL);
if(current_time>previous_time)
{
previous_time=current_time;
diff --git a/src/qpsearch.cpp b/src/qpsearch.cpp
index 87962f3..8e4e93e 100644
--- a/src/qpsearch.cpp
+++ b/src/qpsearch.cpp
@@ -57,6 +57,7 @@
#include "fat_dir.h"
#include "list.h"
#include "filegen.h"
+#include "photorec.h"
#include "sessionp.h"
#include "log.h"
#include "file_tar.h"
@@ -144,6 +145,7 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space)
params->disk->pread(params->disk, buffer, READ_SIZE, offset);
while(current_search_space!=list_search_space)
{
+ data_check_t res=DC_SCAN;
int file_recovered=0;
uint64_t old_offset=offset;
#ifdef DEBUG
@@ -199,17 +201,15 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space)
}
if(file_recovery_new.file_stat!=NULL && file_recovery_new.file_stat->file_hint!=NULL)
{
- current_search_space=file_found(current_search_space, offset, file_recovery_new.file_stat);
- file_recovery_new.loc=current_search_space;
file_recovery_new.location.start=offset;
- if(options->verbose > 1)
- log_trace("A known header has been found, recovery of the previous file is finished\n");
+ if(file_recovery.file_stat!=NULL)
{
- file_recovered=file_finish2(&file_recovery, params, options, list_search_space, &current_search_space, &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, list_search_space);
+ if(options->lowmem > 0)
+ forget(list_search_space,current_search_space);
}
- reset_file_recovery(&file_recovery);
- if(options->lowmem > 0)
- forget(list_search_space,current_search_space);
if(file_recovered==0)
{
file_recovery_cpy(&file_recovery, &file_recovery_new);
@@ -262,13 +262,13 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space)
}
if(file_recovery.file_stat!=NULL)
{
- data_check_t res=DC_CONTINUE;
/* try to skip ext2/ext3 indirect block */
if((params->status==STATUS_EXT2_ON || params->status==STATUS_EXT2_ON_SAVE_EVERYTHING) &&
file_recovery.file_size_on_disk>=12*blocksize &&
ind_block(buffer,blocksize)!=0)
{
- current_search_space=file_add_data(current_search_space, offset, 0);
+ file_block_append(&file_recovery, list_search_space, &current_search_space, &offset, blocksize, 0);
+ res=DC_CONTINUE;
file_recovery.file_size_on_disk+=blocksize;
if(options->verbose > 1)
{
@@ -300,9 +300,11 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space)
}
if(ind_stop==PSTATUS_OK)
{
- current_search_space=file_add_data(current_search_space, offset, 1);
+ file_block_append(&file_recovery, list_search_space, &current_search_space, &offset, blocksize, 1);
if(file_recovery.data_check!=NULL)
res=file_recovery.data_check(buffer_olddata,2*blocksize,&file_recovery);
+ else
+ res=DC_CONTINUE;
file_recovery.file_size+=blocksize;
file_recovery.file_size_on_disk+=blocksize;
if(res==DC_STOP)
@@ -326,8 +328,7 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space)
}
if(res==DC_STOP || res==DC_ERROR)
{
- file_recovered=file_finish2(&file_recovery, params, options, list_search_space, &current_search_space, &offset);
- reset_file_recovery(&file_recovery);
+ file_recovered=file_finish2(&file_recovery, params, options, list_search_space);
if(options->lowmem > 0)
forget(list_search_space,current_search_space);
}
@@ -339,9 +340,12 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space)
}
else if(file_recovered==0)
{
- get_next_sector(list_search_space, &current_search_space,&offset,blocksize);
- if(offset > offset_before_back)
- back=0;
+ if(res==DC_SCAN)
+ {
+ get_next_sector(list_search_space, &current_search_space,&offset,blocksize);
+ if(offset > offset_before_back)
+ back=0;
+ }
}
else if(file_recovered>0)
{
@@ -360,8 +364,7 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space)
current_search_space, current_search_space->list.prev, current_search_space->list.next);
log_trace("End of media\n");
#endif
- file_recovered=file_finish2(&file_recovery, params, options, list_search_space, &current_search_space, &offset);
- reset_file_recovery(&file_recovery);
+ file_recovered=file_finish2(&file_recovery, params, options, list_search_space);
if(options->lowmem > 0)
forget(list_search_space,current_search_space);
}
@@ -388,8 +391,7 @@ pstatus_t QPhotorec::photorec_aux(alloc_data_t *list_search_space)
}
if(ind_stop==PSTATUS_OK)
{
- time_t current_time;
- current_time=time(NULL);
+ const time_t current_time=time(NULL);
if(current_time > previous_time)
{
previous_time=current_time;