From 1a7302e5c5a71b688053c00bf263e4312e56a648 Mon Sep 17 00:00:00 2001 From: Slack Date: Sun, 25 Nov 2012 13:39:44 +0400 Subject: [PATCH 1/3] Ticket #2924: attributes of existing directories are never preserved. If superuser copies a directory tree (e.g. from a safe backup location (with sane permission, owner, group, timestamp) over an existing tree, any attributes are not preserved. All destination dirs retain all their existing attributes instead of change attributes from source. Signed-off-by: Andrew Borodin --- src/filemanager/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 3854eae2c..cec8a39ca 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -2053,6 +2053,7 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con { dest_dir = d; d = NULL; + dest_dir_vpath = vfs_path_from_str (dest_dir); goto dont_mkdir; } } @@ -2078,6 +2079,7 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con lp->dev = buf.st_dev; dest_dirs = g_slist_prepend (dest_dirs, lp); + dont_mkdir: if (ctx->preserve_uidgid) { while (mc_chown (dest_dir_vpath, cbuf.st_uid, cbuf.st_gid) != 0) @@ -2096,7 +2098,6 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con } } - dont_mkdir: /* open the source dir for reading */ reading = mc_opendir (src_vpath); if (reading == NULL) From 22a9e2bc0eb8e14f93fe3e90c6dc07e7fdbcec21 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Sun, 25 Nov 2012 13:49:20 +0400 Subject: [PATCH 2/3] (copy_dir_dir): refactoring: get rid of goto dont_mkdir. Signed-off-by: Andrew Borodin --- src/filemanager/file.c | 45 ++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index cec8a39ca..9940a1470 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -1932,6 +1932,7 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con struct link *lp; char *d; vfs_path_t *src_vpath, *dst_vpath, *dest_dir_vpath = NULL; + gboolean do_mkdir = TRUE; d = g_strdup (_d); @@ -2046,40 +2047,42 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con } /* Dive into subdir if exists */ if (toplevel && ctx->dive_into_subdirs) - { dest_dir = mc_build_filename (d, x_basename (s), NULL); - } else { dest_dir = d; d = NULL; - dest_dir_vpath = vfs_path_from_str (dest_dir); - goto dont_mkdir; + do_mkdir = FALSE; } } + dest_dir_vpath = vfs_path_from_str (dest_dir); - while (my_mkdir (dest_dir_vpath, (cbuf.st_mode & ctx->umask_kill) | S_IRWXU) != 0) + + if (do_mkdir) { - if (ctx->skip_all) - return_status = FILE_SKIPALL; - else + while (my_mkdir (dest_dir_vpath, (cbuf.st_mode & ctx->umask_kill) | S_IRWXU) != 0) { - return_status = file_error (_("Cannot create target directory \"%s\"\n%s"), dest_dir); - if (return_status == FILE_SKIPALL) - ctx->skip_all = TRUE; + if (ctx->skip_all) + return_status = FILE_SKIPALL; + else + { + return_status = + file_error (_("Cannot create target directory \"%s\"\n%s"), dest_dir); + if (return_status == FILE_SKIPALL) + ctx->skip_all = TRUE; + } + if (return_status != FILE_RETRY) + goto ret; } - if (return_status != FILE_RETRY) - goto ret; + + lp = g_new0 (struct link, 1); + mc_stat (dest_dir_vpath, &buf); + lp->vfs = vfs_path_get_by_index (dest_dir_vpath, -1)->class; + lp->ino = buf.st_ino; + lp->dev = buf.st_dev; + dest_dirs = g_slist_prepend (dest_dirs, lp); } - lp = g_new0 (struct link, 1); - mc_stat (dest_dir_vpath, &buf); - lp->vfs = vfs_path_get_by_index (dest_dir_vpath, -1)->class; - lp->ino = buf.st_ino; - lp->dev = buf.st_dev; - dest_dirs = g_slist_prepend (dest_dirs, lp); - - dont_mkdir: if (ctx->preserve_uidgid) { while (mc_chown (dest_dir_vpath, cbuf.st_uid, cbuf.st_gid) != 0) From 6e6b2c9912a9ff1d2fc98212795f9045c47e5b12 Mon Sep 17 00:00:00 2001 From: Andrew Borodin Date: Thu, 29 Nov 2012 11:47:57 +0400 Subject: [PATCH 3/3] (copy_dir_dir): get rid of extra string duplication. Signed-off-by: Andrew Borodin --- src/filemanager/file.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 9940a1470..b2c5b9ea0 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -1920,7 +1920,7 @@ copy_file_file (FileOpTotalContext * tctx, FileOpContext * ctx, function calls */ FileProgressStatus -copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, const char *_d, +copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, const char *d, gboolean toplevel, gboolean move_over, gboolean do_delete, GSList * parent_dirs) { struct dirent *next; @@ -1930,14 +1930,11 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con FileProgressStatus return_status = FILE_CONT; struct utimbuf utb; struct link *lp; - char *d; vfs_path_t *src_vpath, *dst_vpath, *dest_dir_vpath = NULL; gboolean do_mkdir = TRUE; - d = g_strdup (_d); - src_vpath = vfs_path_from_str (s); - dst_vpath = vfs_path_from_str (_d); + dst_vpath = vfs_path_from_str (d); /* First get the mode of the source dir */ @@ -2018,8 +2015,7 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con goto ret; } } - dest_dir = d; - d = NULL; + dest_dir = g_strdup (d); } else { @@ -2050,8 +2046,7 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con dest_dir = mc_build_filename (d, x_basename (s), NULL); else { - dest_dir = d; - d = NULL; + dest_dir = g_strdup (d); do_mkdir = FALSE; } } @@ -2186,7 +2181,6 @@ copy_dir_dir (FileOpTotalContext * tctx, FileOpContext * ctx, const char *s, con free_link (parent_dirs->data); g_slist_free_1 (parent_dirs); ret_fast: - g_free (d); vfs_path_free (src_vpath); vfs_path_free (dst_vpath); return return_status;