diff options
author | Tomas Bzatek <tbzatek@redhat.com> | 2008-05-05 09:43:48 +0000 |
---|---|---|
committer | Tomas Bzatek <tbzatek@src.gnome.org> | 2008-05-05 09:43:48 +0000 |
commit | 7c53ad15b7b0ce7a9cbafd40bef35a17f67272ec (patch) | |
tree | aec75990f983215c0df52260fa2b0c2912cf6523 /libnautilus-private | |
parent | 12d248d56567e8a68097523cf079293f11f62a78 (diff) | |
download | nautilus-7c53ad15b7b0ce7a9cbafd40bef35a17f67272ec.tar.gz |
Don't allow recursive move/copy into itself. Fixes #530720.
2008-05-05 Tomas Bzatek <tbzatek@redhat.com>
* libnautilus-private/nautilus-file-operations.c:
Don't allow recursive move/copy into itself. Fixes #530720.
svn path=/trunk/; revision=14131
Diffstat (limited to 'libnautilus-private')
-rw-r--r-- | libnautilus-private/nautilus-file-operations.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/libnautilus-private/nautilus-file-operations.c b/libnautilus-private/nautilus-file-operations.c index f997a09ce..28cae5aba 100644 --- a/libnautilus-private/nautilus-file-operations.c +++ b/libnautilus-private/nautilus-file-operations.c @@ -3221,6 +3221,26 @@ copy_file_progress_callback (goffset current_num_bytes, } } +static gboolean +test_dir_is_parent (GFile *child, GFile *root) +{ + GFile *f; + + f = g_file_dup (child); + while (f) { + if (g_file_equal (f, root)) { + g_object_unref (f); + return TRUE; + } + f = g_file_get_parent (f); + } + + if (f) { + g_object_unref (f); + } + return FALSE; +} + /* Debuting files is non-NULL only for toplevel items */ static void copy_move_file (CopyMoveJob *copy_job, @@ -3261,6 +3281,41 @@ copy_move_file (CopyMoveJob *copy_job, dest = get_target_file (src, dest_dir, same_fs); } + + /* Don't allow recursive move/copy into itself. + * (We would get a file system error if we proceeded but it is nicer to + * detect and report it at this level) */ + if (test_dir_is_parent (dest_dir, src)) { + if (job->skip_all_error) { + g_error_free (error); + goto out; + } + + /* the run_warning() frees all strings passed in automatically */ + primary = copy_job->is_move ? g_strdup (_("You cannot move a folder into itself.")) + : g_strdup (_("You cannot copy a folder into itself.")); + secondary = g_strdup (_("The destination folder is inside the source folder.")); + + response = run_warning (job, + primary, + secondary, + NULL, + GTK_STOCK_CANCEL, SKIP_ALL, SKIP, + NULL); + + if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { + abort_job (job); + } else if (response == 1) { /* skip all */ + job->skip_all_error = TRUE; + } else if (response == 2) { /* skip */ + /* do nothing */ + } else { + g_assert_not_reached (); + } + + goto out; + } + retry: error = NULL; @@ -3788,6 +3843,41 @@ move_file_prepare (CopyMoveJob *move_job, dest = get_target_file (src, dest_dir, same_fs); + + /* Don't allow recursive move/copy into itself. + * (We would get a file system error if we proceeded but it is nicer to + * detect and report it at this level) */ + if (test_dir_is_parent (dest_dir, src)) { + if (job->skip_all_error) { + g_error_free (error); + goto out; + } + + /* the run_warning() frees all strings passed in automatically */ + primary = move_job->is_move ? g_strdup (_("You cannot move a folder into itself.")) + : g_strdup (_("You cannot copy a folder into itself.")); + secondary = g_strdup (_("The destination folder is inside the source folder.")); + + response = run_warning (job, + primary, + secondary, + NULL, + GTK_STOCK_CANCEL, SKIP_ALL, SKIP, + NULL); + + if (response == 0 || response == GTK_RESPONSE_DELETE_EVENT) { + abort_job (job); + } else if (response == 1) { /* skip all */ + job->skip_all_error = TRUE; + } else if (response == 2) { /* skip */ + /* do nothing */ + } else { + g_assert_not_reached (); + } + + goto out; + } + retry: flags = G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_NO_FALLBACK_FOR_MOVE; |