summaryrefslogtreecommitdiffstats
path: root/src/dirn.c
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2011-03-05 18:47:40 +0100
committerChristophe Grenier <grenier@cgsecurity.org>2011-03-05 18:47:40 +0100
commite41e56453b799076e5001b91854ba8c37160d199 (patch)
treec21ce1de5cdcd8464143484a453e460afef48b74 /src/dirn.c
parentf2c0943a5a5d2de868a6cfefa8b2c7386b8c5393 (diff)
TestDisk: try to avoid endless directory loop when copying directory
when damaged filesystem
Diffstat (limited to 'src/dirn.c')
-rw-r--r--src/dirn.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/src/dirn.c b/src/dirn.c
index 0883064..b344bc3 100644
--- a/src/dirn.c
+++ b/src/dirn.c
@@ -403,8 +403,11 @@ Returns
-1: failed to copy some files
0: all files has been copied
*/
+#define MAX_DIR_NBR 256
static int copy_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_data, const file_data_t *dir)
{
+ static unsigned int dir_nbr=0;
+ static unsigned long int inode_known[MAX_DIR_NBR];
file_data_t *dir_list;
const unsigned int current_directory_namelength=strlen(dir_data->current_directory);
file_data_t *current_file;
@@ -413,6 +416,7 @@ static int copy_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_
int copy_ok=0;
if(dir_data->get_dir==NULL || dir_data->copy_file==NULL)
return -2;
+ inode_known[dir_nbr++]=dir->stat.st_ino;
dir_name=mkdir_local(dir_data->local_dir, dir_data->current_directory);
dir_list=dir_data->get_dir(disk, partition, dir_data, (const unsigned long int)dir->stat.st_ino);
for(current_file=dir_list;current_file!=NULL;current_file=current_file->next)
@@ -425,14 +429,25 @@ static int copy_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_
strcat(dir_data->current_directory,current_file->name);
if(LINUX_S_ISDIR(current_file->stat.st_mode)!=0)
{
- int tmp=0;
- if(current_file->stat.st_ino != dir->stat.st_ino &&
- strcmp(current_file->name,"..")!=0 && strcmp(current_file->name,".")!=0)
+ const unsigned long int new_inode=current_file->stat.st_ino;
+ unsigned int new_inode_ok=1;
+ unsigned int i;
+ if(new_inode<2)
+ new_inode_ok=0;
+ if(strcmp(current_file->name,"..")==0 || strcmp(current_file->name,".")==0)
+ new_inode_ok=0;
+ for(i=0;i<dir_nbr && new_inode_ok!=0;i++)
+ if(new_inode==inode_known[i]) /* Avoid loop */
+ new_inode_ok=0;
+ if(new_inode_ok>0)
+ {
+ int tmp;
tmp=copy_dir(disk, partition, dir_data, current_file);
- if(tmp>=-1)
- copy_ok=1;
- if(tmp<0)
- copy_bad=1;
+ if(tmp>=-1)
+ copy_ok=1;
+ if(tmp<0)
+ copy_bad=1;
+ }
}
else if(LINUX_S_ISREG(current_file->stat.st_mode)!=0)
{
@@ -450,6 +465,7 @@ static int copy_dir(disk_t *disk, const partition_t *partition, dir_data_t *dir_
delete_list_file(dir_list);
set_date(dir_name, dir->stat.st_atime, dir->stat.st_mtime);
free(dir_name);
+ dir_nbr--;
return (copy_bad>0?(copy_ok>0?-1:-2):0);
}