mirror of
https://github.com/MidnightCommander/mc
synced 2025-01-18 09:19:24 +03:00
Merge branch '1393_copy_dir_dir_memleak'
* 1393_copy_dir_dir_memleak: Fixed memory leak in copy_dir_dir().
This commit is contained in:
commit
ebf4c000e2
60
src/file.c
60
src/file.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user