|
|
| |
static void list_free_add(const file_recovery_t *file_recovery, alloc_data_t *list_search_space) | static void list_free_add(const file_recovery_t *file_recovery, alloc_data_t *list_search_space) |
{ | { |
struct list_head *search_walker = NULL; |
struct td_list_head *search_walker = NULL; |
#ifdef DEBUG_FREE | #ifdef DEBUG_FREE |
log_trace("list_free_add %lu\n",(long unsigned)(file_recovery->location.start/512)); | log_trace("list_free_add %lu\n",(long unsigned)(file_recovery->location.start/512)); |
#endif | #endif |
list_for_each(search_walker, &list_search_space->list) |
td_list_for_each(search_walker, &list_search_space->list) |
{ | { |
alloc_data_t *current_search_space; | alloc_data_t *current_search_space; |
current_search_space=list_entry(search_walker, alloc_data_t, list); |
current_search_space=td_list_entry(search_walker, alloc_data_t, list); |
if(current_search_space->start < file_recovery->location.start && file_recovery->location.start < current_search_space->end) | if(current_search_space->start < file_recovery->location.start && file_recovery->location.start < current_search_space->end) |
{ | { |
alloc_data_t *new_free_space; | alloc_data_t *new_free_space; |
|
|
new_free_space->end=current_search_space->end; | new_free_space->end=current_search_space->end; |
new_free_space->file_stat=NULL; | new_free_space->file_stat=NULL; |
current_search_space->end=file_recovery->location.start-1; | current_search_space->end=file_recovery->location.start-1; |
list_add(&new_free_space->list, search_walker); |
td_list_add(&new_free_space->list, search_walker); |
} | } |
if(current_search_space->start==file_recovery->location.start) | if(current_search_space->start==file_recovery->location.start) |
{ | { |
|
|
static alloc_data_t *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 alloc_data_t *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) |
{ | { |
const alloc_list_t *element; | const alloc_list_t *element; |
struct list_head *search_walker = NULL; |
struct td_list_head *search_walker = NULL; |
#ifdef DEBUG_UPDATE_SEARCH_SPACE | #ifdef DEBUG_UPDATE_SEARCH_SPACE |
log_trace("update_search_space\n"); | log_trace("update_search_space\n"); |
list_for_each(search_walker, &list_search_space->list) |
td_list_for_each(search_walker, &list_search_space->list) |
{ | { |
alloc_data_t *cur_free_space; | alloc_data_t *cur_free_space; |
cur_free_space=list_entry(search_walker, alloc_data_t, list); |
cur_free_space=td_list_entry(search_walker, alloc_data_t, list); |
log_trace(" %llu-%llu",(long long unsigned)(cur_free_space->start/512), | log_trace(" %llu-%llu",(long long unsigned)(cur_free_space->start/512), |
(long long unsigned)(cur_free_space->end/512)); | (long long unsigned)(cur_free_space->end/512)); |
} | } |
log_trace("\n"); | log_trace("\n"); |
#endif | #endif |
list_for_each(search_walker, &list_search_space->list) |
td_list_for_each(search_walker, &list_search_space->list) |
{ | { |
alloc_data_t *current_search_space; | alloc_data_t *current_search_space; |
current_search_space=list_entry(search_walker, alloc_data_t, list); |
current_search_space=td_list_entry(search_walker, alloc_data_t, list); |
if(current_search_space->start <= file_recovery->location.start && | if(current_search_space->start <= file_recovery->location.start && |
file_recovery->location.start <= current_search_space->end) | file_recovery->location.start <= current_search_space->end) |
{ | { |
|
|
| |
static alloc_data_t *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 *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) |
{ | { |
struct list_head *search_walker = NULL; |
struct td_list_head *search_walker = NULL; |
#ifdef DEBUG_UPDATE_SEARCH_SPACE | #ifdef DEBUG_UPDATE_SEARCH_SPACE |
log_trace("update_search_space_aux offset=%llu remove [%llu-%llu]\n", | log_trace("update_search_space_aux offset=%llu remove [%llu-%llu]\n", |
(long long unsigned)((*offset)/512), | (long long unsigned)((*offset)/512), |
|
|
#endif | #endif |
if(start >= end) | if(start >= end) |
return list_search_space; | return list_search_space; |
list_for_each(search_walker, &list_search_space->list) |
td_list_for_each(search_walker, &list_search_space->list) |
{ | { |
alloc_data_t *current_search_space; | alloc_data_t *current_search_space; |
current_search_space=list_entry(search_walker, alloc_data_t, list); |
current_search_space=td_list_entry(search_walker, alloc_data_t, list); |
#ifdef DEBUG_UPDATE_SEARCH_SPACE | #ifdef DEBUG_UPDATE_SEARCH_SPACE |
log_trace("update_search_space_aux offset=%llu remove [%llu-%llu] in [%llu-%llu]\n", | log_trace("update_search_space_aux offset=%llu remove [%llu-%llu] in [%llu-%llu]\n", |
(long long unsigned)((*offset)/512), | (long long unsigned)((*offset)/512), |
|
|
/* current_search_space->start==start current_search_space->end<=end */ | /* current_search_space->start==start current_search_space->end<=end */ |
start=current_search_space->end+1; | start=current_search_space->end+1; |
if(list_search_space==current_search_space) | if(list_search_space==current_search_space) |
list_search_space=list_entry(current_search_space->list.next, alloc_data_t, list); |
list_search_space=td_list_entry(current_search_space->list.next, alloc_data_t, list); |
if(offset!=NULL && new_current_search_space!=NULL && | if(offset!=NULL && new_current_search_space!=NULL && |
current_search_space->start<=*offset && *offset<=current_search_space->end) | current_search_space->start<=*offset && *offset<=current_search_space->end) |
{ | { |
*new_current_search_space=list_entry(current_search_space->list.next, alloc_data_t, list); |
*new_current_search_space=td_list_entry(current_search_space->list.next, alloc_data_t, list); |
*offset=(*new_current_search_space)->start; | *offset=(*new_current_search_space)->start; |
} | } |
list_del(search_walker); |
td_list_del(search_walker); |
free(current_search_space); | free(current_search_space); |
return update_search_space_aux(list_search_space, start,end, new_current_search_space, offset); | return update_search_space_aux(list_search_space, start,end, new_current_search_space, offset); |
} | } |
|
|
if(offset!=NULL && new_current_search_space!=NULL && | if(offset!=NULL && new_current_search_space!=NULL && |
start<=*offset && *offset<=current_search_space->end) | start<=*offset && *offset<=current_search_space->end) |
{ | { |
*new_current_search_space=list_entry(current_search_space->list.next, alloc_data_t, list); |
*new_current_search_space=td_list_entry(current_search_space->list.next, alloc_data_t, list); |
*offset=(*new_current_search_space)->start; | *offset=(*new_current_search_space)->start; |
} | } |
current_search_space->end=start-1; | current_search_space->end=start-1; |
|
|
/* start<=current_search_space->start current_search_space->end==end */ | /* start<=current_search_space->start current_search_space->end==end */ |
end=current_search_space->start-1; | end=current_search_space->start-1; |
if(list_search_space==current_search_space) | if(list_search_space==current_search_space) |
list_search_space=list_entry(current_search_space->list.next, alloc_data_t, list); |
list_search_space=td_list_entry(current_search_space->list.next, alloc_data_t, list); |
if(offset!=NULL && new_current_search_space!=NULL && | if(offset!=NULL && new_current_search_space!=NULL && |
current_search_space->start<=*offset && *offset<=current_search_space->end) | current_search_space->start<=*offset && *offset<=current_search_space->end) |
{ | { |
*new_current_search_space=list_entry(current_search_space->list.next, alloc_data_t, list); |
*new_current_search_space=td_list_entry(current_search_space->list.next, alloc_data_t, list); |
*offset=(*new_current_search_space)->start; | *offset=(*new_current_search_space)->start; |
} | } |
list_del(search_walker); |
td_list_del(search_walker); |
free(current_search_space); | free(current_search_space); |
return update_search_space_aux(list_search_space, start,end, new_current_search_space, offset); | return update_search_space_aux(list_search_space, start,end, new_current_search_space, offset); |
} | } |
|
|
new_free_space->end=current_search_space->end; | new_free_space->end=current_search_space->end; |
new_free_space->file_stat=NULL; | new_free_space->file_stat=NULL; |
current_search_space->end=start-1; | current_search_space->end=start-1; |
list_add(&new_free_space->list,search_walker); |
td_list_add(&new_free_space->list,search_walker); |
if(offset!=NULL && new_current_search_space!=NULL && | if(offset!=NULL && new_current_search_space!=NULL && |
new_free_space->start<=*offset && *offset<=new_free_space->end) | new_free_space->start<=*offset && *offset<=new_free_space->end) |
{ | { |
|
|
| |
void free_list_search_space(alloc_data_t *list_search_space) | void free_list_search_space(alloc_data_t *list_search_space) |
{ | { |
struct list_head *search_walker = NULL; |
struct td_list_head *search_walker = NULL; |
struct list_head *search_walker_next = NULL; |
struct td_list_head *search_walker_next = NULL; |
list_for_each_safe(search_walker,search_walker_next,&list_search_space->list) |
td_list_for_each_safe(search_walker,search_walker_next,&list_search_space->list) |
{ | { |
alloc_data_t *current_search_space; | alloc_data_t *current_search_space; |
current_search_space=list_entry(search_walker, alloc_data_t, list); |
current_search_space=td_list_entry(search_walker, alloc_data_t, list); |
list_del(search_walker); |
td_list_del(search_walker); |
free(current_search_space); | free(current_search_space); |
} | } |
} | } |
|
|
static void get_prev_header(alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset) | static void get_prev_header(alloc_data_t *list_search_space, alloc_data_t **current_search_space, uint64_t *offset) |
{ | { |
if((*current_search_space) != list_search_space) | if((*current_search_space) != list_search_space) |
*current_search_space=list_entry((*current_search_space)->list.prev, alloc_data_t, list); |
*current_search_space=td_list_entry((*current_search_space)->list.prev, alloc_data_t, list); |
*offset=(*current_search_space)->start; | *offset=(*current_search_space)->start; |
} | } |
#endif | #endif |
|
|
alloc_data_t *file_space=*current_search_space; | alloc_data_t *file_space=*current_search_space; |
for(nbr=0;nbr<5;nbr++) | for(nbr=0;nbr<5;nbr++) |
{ | { |
file_space=list_entry(file_space->list.prev, alloc_data_t, list); |
file_space=td_list_entry(file_space->list.prev, alloc_data_t, list); |
if(file_space==list_search_space) | if(file_space==list_search_space) |
return -1; | return -1; |
if(file_space->file_stat!=NULL) | if(file_space->file_stat!=NULL) |
|
|
| |
void forget(alloc_data_t *list_search_space, alloc_data_t *current_search_space) | void forget(alloc_data_t *list_search_space, alloc_data_t *current_search_space) |
{ | { |
struct list_head *search_walker = NULL; |
struct td_list_head *search_walker = NULL; |
struct list_head *prev= NULL; |
struct td_list_head *prev= NULL; |
int nbr=0; | int nbr=0; |
if(current_search_space==list_search_space) | if(current_search_space==list_search_space) |
return ; | return ; |
|
|
if(nbr>10000) | if(nbr>10000) |
{ | { |
alloc_data_t *tmp; | alloc_data_t *tmp; |
tmp=list_entry(search_walker, alloc_data_t, list); |
tmp=td_list_entry(search_walker, alloc_data_t, list); |
list_del(&tmp->list); |
td_list_del(&tmp->list); |
free(tmp); | free(tmp); |
} | } |
else | else |
|
|
| |
void list_cluster_free(list_cluster_t *list_cluster) | void list_cluster_free(list_cluster_t *list_cluster) |
{ | { |
struct list_head *dir_walker = NULL; |
struct td_list_head *dir_walker = NULL; |
struct list_head *dir_walker_next = NULL; |
struct td_list_head *dir_walker_next = NULL; |
list_for_each_safe(dir_walker,dir_walker_next,&list_cluster->list) |
td_list_for_each_safe(dir_walker,dir_walker_next,&list_cluster->list) |
{ | { |
list_cluster_t *info; | list_cluster_t *info; |
info=list_entry(dir_walker, list_cluster_t, list); |
info=td_list_entry(dir_walker, list_cluster_t, list); |
delete_list_file(info->dir_list); | delete_list_file(info->dir_list); |
list_del(dir_walker); |
td_list_del(dir_walker); |
free(info); | free(info); |
} | } |
} | } |
|
|
| |
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) |
{ | { |
struct list_head *search_walker = NULL; |
struct td_list_head *search_walker = NULL; |
int i; | int i; |
/* Reset */ | /* Reset */ |
for(i=0;file_stats[i].file_hint!=NULL;i++) | for(i=0;file_stats[i].file_hint!=NULL;i++) |
file_stats[i].not_recovered=0; | file_stats[i].not_recovered=0; |
/* Update */ | /* Update */ |
list_for_each(search_walker, &list_search_space->list) |
td_list_for_each(search_walker, &list_search_space->list) |
{ | { |
alloc_data_t *current_search_space; | alloc_data_t *current_search_space; |
current_search_space=list_entry(search_walker, alloc_data_t, list); |
current_search_space=td_list_entry(search_walker, alloc_data_t, list); |
if(current_search_space->file_stat!=NULL) | if(current_search_space->file_stat!=NULL) |
{ | { |
current_search_space->file_stat->not_recovered++; | current_search_space->file_stat->not_recovered++; |
|
|
unsigned int nbr_max=0; | unsigned int nbr_max=0; |
for(cluster_size=default_blocksize;cluster_size<=128*512;cluster_size*=2) | for(cluster_size=default_blocksize;cluster_size<=128*512;cluster_size*=2) |
{ | { |
struct list_head *dir_walker = NULL; |
struct td_list_head *dir_walker = NULL; |
cluster_offset_t cluster_offset[1000]; | cluster_offset_t cluster_offset[1000]; |
unsigned int nbr_sol=0; | unsigned int nbr_sol=0; |
list_for_each(dir_walker,&list_cluster->list) |
td_list_for_each(dir_walker,&list_cluster->list) |
{ | { |
list_cluster_t *info; | list_cluster_t *info; |
info=list_entry(dir_walker, list_cluster_t, list); |
info=td_list_entry(dir_walker, list_cluster_t, list); |
if(info->cluster>=2 && (info->cluster-2)*cluster_size<info->offset) | if(info->cluster>=2 && (info->cluster-2)*cluster_size<info->offset) |
{ | { |
unsigned int sol_cur; | unsigned int sol_cur; |
|
|
int blocksize_ok=0; | int blocksize_ok=0; |
unsigned int blocksize; | unsigned int blocksize; |
*offset=0; | *offset=0; |
if(list_empty(&list_file->list)) |
if(td_list_empty(&list_file->list)) |
return default_blocksize; | return default_blocksize; |
for(blocksize=128*512;blocksize>=default_blocksize && blocksize_ok==0;blocksize=blocksize>>1) | for(blocksize=128*512;blocksize>=default_blocksize && blocksize_ok==0;blocksize=blocksize>>1) |
{ | { |
struct list_head *search_walker = NULL; |
struct td_list_head *search_walker = NULL; |
blocksize_ok=1; | blocksize_ok=1; |
{ | { |
alloc_data_t *tmp; | alloc_data_t *tmp; |
tmp=list_entry(list_file->list.next, alloc_data_t, list); |
tmp=td_list_entry(list_file->list.next, alloc_data_t, list); |
*offset=tmp->start%blocksize; | *offset=tmp->start%blocksize; |
} | } |
for(search_walker=list_file->list.next; | for(search_walker=list_file->list.next; |
|
|
search_walker=search_walker->next) | search_walker=search_walker->next) |
{ | { |
alloc_data_t *current_file; | alloc_data_t *current_file; |
current_file=list_entry(search_walker, alloc_data_t, list); |
current_file=td_list_entry(search_walker, alloc_data_t, list); |
if(current_file->start%blocksize!=*offset) | if(current_file->start%blocksize!=*offset) |
blocksize_ok=0; | blocksize_ok=0; |
} | } |
|
|
| |
alloc_data_t * update_blocksize(unsigned int blocksize, alloc_data_t *list_search_space, const uint64_t offset) | alloc_data_t * update_blocksize(unsigned int blocksize, alloc_data_t *list_search_space, const uint64_t offset) |
{ | { |
struct list_head *search_walker = NULL; |
struct td_list_head *search_walker = NULL; |
struct list_head *search_walker_next = NULL; |
struct td_list_head *search_walker_next = NULL; |
list_for_each_safe(search_walker,search_walker_next,&list_search_space->list) |
td_list_for_each_safe(search_walker,search_walker_next,&list_search_space->list) |
{ | { |
alloc_data_t *current_search_space; | alloc_data_t *current_search_space; |
current_search_space=list_entry(search_walker, alloc_data_t, list); |
current_search_space=td_list_entry(search_walker, alloc_data_t, list); |
current_search_space->start=(current_search_space->start-offset%blocksize+blocksize-1)/blocksize*blocksize+offset%blocksize; | current_search_space->start=(current_search_space->start-offset%blocksize+blocksize-1)/blocksize*blocksize+offset%blocksize; |
if(current_search_space->start>current_search_space->end) | if(current_search_space->start>current_search_space->end) |
{ | { |
list_del(search_walker); |
td_list_del(search_walker); |
if(list_search_space==current_search_space) | if(list_search_space==current_search_space) |
list_search_space=list_entry(search_walker_next, alloc_data_t, list); |
list_search_space=td_list_entry(search_walker_next, alloc_data_t, list); |
free(current_search_space); | free(current_search_space); |
} | } |
} | } |
|
|
list_free_add(file_recovery, list_search_space); | list_free_add(file_recovery, list_search_space); |
if((*current_search_space)!=list_search_space && | if((*current_search_space)!=list_search_space && |
!((*current_search_space)->start <= *offset && *offset <= (*current_search_space)->end)) | !((*current_search_space)->start <= *offset && *offset <= (*current_search_space)->end)) |
*current_search_space=list_entry((*current_search_space)->list.next, alloc_data_t, list); |
*current_search_space=td_list_entry((*current_search_space)->list.next, alloc_data_t, list); |
} | } |
else if(status!=STATUS_EXT2_ON_SAVE_EVERYTHING && status!=STATUS_EXT2_OFF_SAVE_EVERYTHING && status!=STATUS_FIND_OFFSET) | else if(status!=STATUS_EXT2_ON_SAVE_EVERYTHING && status!=STATUS_EXT2_OFF_SAVE_EVERYTHING && status!=STATUS_FIND_OFFSET) |
{ | { |
list_search_space=update_search_space(file_recovery,list_search_space,current_search_space,offset,blocksize); | list_search_space=update_search_space(file_recovery,list_search_space,current_search_space,offset,blocksize); |
file_recovered=1; | file_recovered=1; |
} | } |
list_delete(file_recovery->location.next); |
td_list_delete(file_recovery->location.next); |
file_recovery->location.next=NULL; | file_recovery->location.next=NULL; |
} | } |
if(file_recovery->file_size==0 && file_recovery->offset_error!=0) | if(file_recovery->file_size==0 && file_recovery->offset_error!=0) |