summaryrefslogtreecommitdiff
path: root/libnautilus-private
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2008-05-05 09:43:48 +0000
committerTomas Bzatek <tbzatek@src.gnome.org>2008-05-05 09:43:48 +0000
commit7c53ad15b7b0ce7a9cbafd40bef35a17f67272ec (patch)
treeaec75990f983215c0df52260fa2b0c2912cf6523 /libnautilus-private
parent12d248d56567e8a68097523cf079293f11f62a78 (diff)
downloadnautilus-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.c90
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;