* eio: fix recursion by detecting link and recreating them.

SVN revision: 54123
This commit is contained in:
Cedric BAIL 2010-11-03 12:35:21 +00:00
parent c40d642b02
commit 7e9c729ce2
2 changed files with 86 additions and 13 deletions

View File

@ -124,7 +124,7 @@ _eio_dir_recursiv_ls(Ecore_Thread *thread, Eio_Dir_Copy *copy, const char *targe
const char *dir; const char *dir;
struct stat buffer; struct stat buffer;
it = eina_file_direct_ls(target); it = eina_file_stat_ls(target);
if (!it) if (!it)
{ {
eio_file_thread_error(&copy->progress.common, thread); eio_file_thread_error(&copy->progress.common, thread);
@ -136,19 +136,16 @@ _eio_dir_recursiv_ls(Ecore_Thread *thread, Eio_Dir_Copy *copy, const char *targe
switch (info->type) switch (info->type)
{ {
case EINA_FILE_UNKNOWN: case EINA_FILE_UNKNOWN:
if (stat(info->path, &buffer) != 0) eio_file_thread_error(&copy->progress.common, thread);
{ goto on_error;
eio_file_thread_error(&copy->progress.common, thread); case EINA_FILE_DIR:
goto on_error; if (lstat(info->path, &buffer) != 0)
} goto on_error;
if (S_ISDIR(buffer.st_mode)) if (S_ISDIR(buffer.st_mode))
dirs = eina_list_append(dirs, eina_stringshare_add(info->path)); dirs = eina_list_append(dirs, eina_stringshare_add(info->path));
else else /* It's a link we should not forget about it */
copy->files = eina_list_append(copy->files, eina_stringshare_add(info->path)); copy->links = eina_list_append(copy->links, eina_stringshare_add(info->path));
break;
case EINA_FILE_DIR:
dirs = eina_list_append(dirs, eina_stringshare_add(info->path));
break; break;
default: default:
copy->files = eina_list_append(copy->files, eina_stringshare_add(info->path)); copy->files = eina_list_append(copy->files, eina_stringshare_add(info->path));
@ -192,12 +189,15 @@ _eio_dir_init(Ecore_Thread *thread,
/* notify main thread of the amount of work todo */ /* notify main thread of the amount of work todo */
*step = 0; *step = 0;
*count = eina_list_count(order->files) + eina_list_count(order->dirs) * 2; *count = eina_list_count(order->files)
+ eina_list_count(order->dirs) * 2
+ eina_list_count(order->links);
eio_progress_send(thread, &order->progress, *step, *count); eio_progress_send(thread, &order->progress, *step, *count);
/* sort the content, so we create the directory in the right order */ /* sort the content, so we create the directory in the right order */
order->dirs = eina_list_sort(order->dirs, -1, eio_strcmp); order->dirs = eina_list_sort(order->dirs, -1, eio_strcmp);
order->files = eina_list_sort(order->files, -1, eio_strcmp); order->files = eina_list_sort(order->files, -1, eio_strcmp);
order->links = eina_list_sort(order->links, -1, eio_strcmp);
/* prepare stuff */ /* prepare stuff */
*length_source = eina_stringshare_strlen(order->progress.source); *length_source = eina_stringshare_strlen(order->progress.source);
@ -272,6 +272,67 @@ _eio_dir_mkdir(Ecore_Thread *thread, Eio_Dir_Copy *order,
return EINA_TRUE; return EINA_TRUE;
} }
static Eina_Bool
_eio_dir_link(Ecore_Thread *thread, Eio_Dir_Copy *order,
off_t *step, off_t count,
int length_source, int length_dest)
{
const char *link;
Eina_List *l;
char oldpath[PATH_MAX];
char target[PATH_MAX];
char buffer[PATH_MAX];
char *newpath;
/* Build once the base of the link target */
memcpy(buffer, order->progress.dest, length_dest);
buffer[length_dest] = '/';
/* recreate all links */
EINA_LIST_FOREACH(order->links, l, link)
{
ssize_t length;
/* build oldpath link */
_eio_dir_target(order, oldpath, link, length_source, length_dest);
/* read link target */
length = readlink(link, target, PATH_MAX);
if (length < 0)
goto on_error;
if (strncmp(target, order->progress.source, length_source) == 0)
{
/* The link is inside the zone to copy, so rename it */
memcpy(buffer + length_dest + 1, target + length_source, length - length_source + 1);
newpath = target;
}
else
{
/* The link is outside the zone to copy */
newpath = target;
}
/* create the link */
if (symlink(oldpath, newpath) != 0)
goto on_error;
/* inform main thread */
(*step)++;
eio_progress_send(thread, &order->progress, *step, count);
/* check for cancel request */
if (ecore_thread_check(thread))
return EINA_FALSE;
}
return EINA_TRUE;
on_error:
eio_file_thread_error(&order->progress.common, thread);
return EINA_FALSE;
}
static Eina_Bool static Eina_Bool
_eio_dir_chmod(Ecore_Thread *thread, Eio_Dir_Copy *order, _eio_dir_chmod(Ecore_Thread *thread, Eio_Dir_Copy *order,
off_t *step, off_t count, off_t *step, off_t count,
@ -332,7 +393,8 @@ _eio_dir_copy_heavy(Ecore_Thread *thread, void *data)
{ {
Eio_Dir_Copy *copy = data; Eio_Dir_Copy *copy = data;
const char *file = NULL; const char *file = NULL;
const char *dir = NULL; const char *dir;
const char *link;
Eio_File_Progress file_copy; Eio_File_Progress file_copy;
char target[PATH_MAX]; char target[PATH_MAX];
@ -386,6 +448,10 @@ _eio_dir_copy_heavy(Ecore_Thread *thread, void *data)
file_copy.dest = NULL; file_copy.dest = NULL;
file = NULL; file = NULL;
/* recreate link */
if (!_eio_dir_link(thread, copy, &step, count, length_source, length_dest))
goto on_error;
/* set directory right back */ /* set directory right back */
if (!_eio_dir_chmod(thread, copy, &step, count, length_source, length_dest, EINA_FALSE)) if (!_eio_dir_chmod(thread, copy, &step, count, length_source, length_dest, EINA_FALSE))
goto on_error; goto on_error;
@ -399,6 +465,8 @@ _eio_dir_copy_heavy(Ecore_Thread *thread, void *data)
eina_stringshare_del(file); eina_stringshare_del(file);
EINA_LIST_FREE(copy->dirs, dir) EINA_LIST_FREE(copy->dirs, dir)
eina_stringshare_del(dir); eina_stringshare_del(dir);
EINA_LIST_FREE(copy->links, link)
eina_stringshare_del(link);
if (!ecore_thread_check(thread)) if (!ecore_thread_check(thread))
eio_progress_send(thread, &copy->progress, count, count); eio_progress_send(thread, &copy->progress, count, count);
@ -526,6 +594,10 @@ _eio_dir_move_heavy(Ecore_Thread *thread, void *data)
file_move.dest = NULL; file_move.dest = NULL;
file = NULL; file = NULL;
/* recreate link */
if (!_eio_dir_link(thread, move, &step, count, length_source, length_dest))
goto on_error;
/* set directory right back */ /* set directory right back */
if (!_eio_dir_chmod(thread, move, &step, count, length_source, length_dest, EINA_TRUE)) if (!_eio_dir_chmod(thread, move, &step, count, length_source, length_dest, EINA_TRUE))
goto on_error; goto on_error;

View File

@ -149,6 +149,7 @@ struct _Eio_Dir_Copy
Eina_List *files; Eina_List *files;
Eina_List *dirs; Eina_List *dirs;
Eina_List *links;
}; };
struct _Eio_File_Chown struct _Eio_File_Chown