Merge branch '1393_copy_dir_dir_memleak'

* 1393_copy_dir_dir_memleak:
  Fixed memory leak in copy_dir_dir().
This commit is contained in:
Andrew Borodin 2009-07-03 13:16:11 +04:00
commit ebf4c000e2

View File

@ -774,12 +774,14 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
struct dirent *next; struct dirent *next;
struct stat buf, cbuf; struct stat buf, cbuf;
DIR *reading; DIR *reading;
char *path, *mdpath, *dest_file, *dest_dir; char *dest_dir = NULL;
FileProgressStatus return_status = FILE_CONT; FileProgressStatus return_status = FILE_CONT;
struct utimbuf utb; struct utimbuf utb;
struct link *lp; struct link *lp;
char *d; char *d;
d = strutils_shell_unescape (_d);
/* First get the mode of the source dir */ /* First get the mode of the source dir */
retry_src_stat: retry_src_stat:
if ((*ctx->stat_func) (s, &cbuf)) { if ((*ctx->stat_func) (s, &cbuf)) {
@ -787,18 +789,17 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
file_error (_(" Cannot stat source directory \"%s\" \n %s "), s); file_error (_(" Cannot stat source directory \"%s\" \n %s "), s);
if (return_status == FILE_RETRY) if (return_status == FILE_RETRY)
goto retry_src_stat; goto retry_src_stat;
return return_status; goto ret_fast;
} }
if (is_in_linklist (dest_dirs, s, &cbuf)) { if (is_in_linklist (dest_dirs, s, &cbuf)) {
/* Don't copy a directory we created before (we don't want to copy /* Don't copy a directory we created before (we don't want to copy
infinitely if a directory is copied into itself) */ infinitely if a directory is copied into itself) */
/* FIXME: should there be an error message and FILE_SKIP? - Norbert */ /* FIXME: should there be an error message and FILE_SKIP? - Norbert */
return FILE_CONT; return_status = FILE_CONT;
goto ret_fast;
} }
d = strutils_shell_unescape (_d);
/* Hmm, hardlink to directory??? - Norbert */ /* Hmm, hardlink to directory??? - Norbert */
/* FIXME: In this step we should do something /* FIXME: In this step we should do something
in case the destination already exist */ in case the destination already exist */
@ -806,8 +807,7 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
if (ctx->preserve && cbuf.st_nlink > 1 if (ctx->preserve && cbuf.st_nlink > 1
&& check_hardlinks (s, d, &cbuf) == 1) { && check_hardlinks (s, d, &cbuf) == 1) {
/* We have made a hardlink - no more processing is necessary */ /* We have made a hardlink - no more processing is necessary */
g_free(d); goto ret_fast;
return return_status;
} }
if (!S_ISDIR (cbuf.st_mode)) { if (!S_ISDIR (cbuf.st_mode)) {
@ -815,16 +815,15 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
file_error (_(" Source \"%s\" is not a directory \n %s "), s); file_error (_(" Source \"%s\" is not a directory \n %s "), s);
if (return_status == FILE_RETRY) if (return_status == FILE_RETRY)
goto retry_src_stat; goto retry_src_stat;
g_free(d); goto ret_fast;
return return_status;
} }
if (is_in_linklist (parent_dirs, s, &cbuf)) { if (is_in_linklist (parent_dirs, s, &cbuf)) {
/* we found a cyclic symbolic link */ /* we found a cyclic symbolic link */
message (D_ERROR, MSG_ERROR, message (D_ERROR, MSG_ERROR,
_(" Cannot copy cyclic symbolic link \n `%s' "), s); _(" Cannot copy cyclic symbolic link \n `%s' "), s);
g_free(d); return_status = FILE_SKIP;
return FILE_SKIP; goto ret_fast;
} }
lp = g_new (struct link, 1); lp = g_new (struct link, 1);
@ -838,15 +837,14 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
/* Now, check if the dest dir exists, if not, create it. */ /* Now, check if the dest dir exists, if not, create it. */
if (mc_stat (d, &buf)) { if (mc_stat (d, &buf)) {
/* Here the dir doesn't exist : make it ! */ /* Here the dir doesn't exist : make it ! */
if (move_over) { if (move_over) {
if (mc_rename (s, d) == 0) { if (mc_rename (s, d) == 0) {
g_free (parent_dirs); return_status = FILE_CONT;
g_free(d); goto ret;
return FILE_CONT;
} }
} }
dest_dir = g_strdup (d); dest_dir = d;
d = NULL;
} else { } else {
/* /*
* If the destination directory exists, we want to copy the whole * If the destination directory exists, we want to copy the whole
@ -861,15 +859,14 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
_(" Destination \"%s\" must be a directory \n %s "), d); _(" Destination \"%s\" must be a directory \n %s "), d);
if (return_status == FILE_RETRY) if (return_status == FILE_RETRY)
goto retry_dst_stat; goto retry_dst_stat;
g_free (parent_dirs); goto ret;
g_free(d);
return return_status;
} }
/* Dive into subdir if exists */ /* Dive into subdir if exists */
if (toplevel && ctx->dive_into_subdirs) { if (toplevel && ctx->dive_into_subdirs) {
dest_dir = concat_dir_and_file (d, x_basename (s)); dest_dir = concat_dir_and_file (d, x_basename (s));
} else { } else {
dest_dir = g_strdup (d); dest_dir = d;
d = NULL;
goto dont_mkdir; goto dont_mkdir;
} }
} }
@ -899,13 +896,14 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
dont_mkdir: dont_mkdir:
/* open the source dir for reading */ /* open the source dir for reading */
if ((reading = mc_opendir (s)) == 0) { reading = mc_opendir (s);
if (reading == NULL)
goto ret; goto ret;
}
while ((next = mc_readdir (reading)) && return_status != FILE_ABORT) { while ((next = mc_readdir (reading)) && return_status != FILE_ABORT) {
char *path;
/* /*
* Now, we don't want '.' and '..' to be created / copied at any time * Now, we don't want '.' and '..' to be created / copied at any time
*/ */
if (!strcmp (next->d_name, ".")) if (!strcmp (next->d_name, "."))
continue; continue;
@ -917,6 +915,8 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
(*ctx->stat_func) (path, &buf); (*ctx->stat_func) (path, &buf);
if (S_ISDIR (buf.st_mode)) { if (S_ISDIR (buf.st_mode)) {
char *mdpath;
mdpath = concat_dir_and_file (dest_dir, next->d_name); mdpath = concat_dir_and_file (dest_dir, next->d_name);
/* /*
* From here, we just intend to recursively copy subdirs, not * From here, we just intend to recursively copy subdirs, not
@ -928,6 +928,8 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
parent_dirs, progress_count, progress_bytes); parent_dirs, progress_count, progress_bytes);
g_free (mdpath); g_free (mdpath);
} else { } else {
char *dest_file;
dest_file = concat_dir_and_file (dest_dir, x_basename (path)); dest_file = concat_dir_and_file (dest_dir, x_basename (path));
return_status = copy_file_file (ctx, path, dest_file, 1, return_status = copy_file_file (ctx, path, dest_file, 1,
progress_count, progress_bytes, 0); progress_count, progress_bytes, 0);
@ -936,11 +938,12 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
if (delete && return_status == FILE_CONT) { if (delete && return_status == FILE_CONT) {
if (ctx->erase_at_end) { if (ctx->erase_at_end) {
static struct link *tail; static struct link *tail;
lp = g_malloc (sizeof (struct link) + strlen (path)); size_t len = strlen (path);
strcpy (lp->name, path); lp = g_malloc (sizeof (struct link) + len);
strncpy (lp->name, path, len + 1);
lp->st_mode = buf.st_mode; lp->st_mode = buf.st_mode;
lp->next = 0; lp->next = NULL;
if (erase_list) { if (erase_list != NULL) {
tail->next = lp; tail->next = lp;
tail = lp; tail = lp;
} else } else
@ -971,7 +974,8 @@ copy_dir_dir (FileOpContext *ctx, const char *s, const char *_d, int toplevel,
ret: ret:
g_free (dest_dir); g_free (dest_dir);
g_free (parent_dirs); g_free (parent_dirs);
g_free(d); ret_fast:
g_free (d);
return return_status; return return_status;
} }