[nautilus] file-operations: fail when overwriting directory with file
- From: Ernestas Kulik <ernestask src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus] file-operations: fail when overwriting directory with file
- Date: Mon, 28 Aug 2017 16:50:10 +0000 (UTC)
commit 1349a35c54dabe8db63af99898962b65e6566c10
Author: Ernestas Kulik <ernestask gnome org>
Date: Mon Jul 24 12:55:31 2017 +0300
file-operations: fail when overwriting directory with file
GIO documentation (and therefore code) mandates that copies and moves of
files over directories should fail, but Nautilus has support for such
(possibly dangerous) operations even to this day. This commit works with
the assumption that whatever backend happens to be used, it will fail as
expected and not overwrite the directory.
https://bugzilla.gnome.org/show_bug.cgi?id=773671
src/nautilus-file-operations.c | 143 ++++++++-------------------------------
1 files changed, 30 insertions(+), 113 deletions(-)
---
diff --git a/src/nautilus-file-operations.c b/src/nautilus-file-operations.c
index 3cb9335..02dabf5 100644
--- a/src/nautilus-file-operations.c
+++ b/src/nautilus-file-operations.c
@@ -4322,21 +4322,13 @@ has_fs_id (GFile *file,
static gboolean
is_dir (GFile *file)
{
- GFileInfo *info;
- gboolean res;
+ GFileType file_type;
- res = FALSE;
- info = g_file_query_info (file,
- G_FILE_ATTRIBUTE_STANDARD_TYPE,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, NULL);
- if (info)
- {
- res = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY;
- g_object_unref (info);
- }
+ file_type = g_file_query_file_type (file,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL);
- return res;
+ return file_type == G_FILE_TYPE_DIRECTORY;
}
static GFile *
@@ -4883,80 +4875,6 @@ typedef struct
GFile *source;
} DeleteExistingFileData;
-static void
-existing_file_removed_callback (GFile *file,
- GError *error,
- gpointer callback_data)
-{
- DeleteExistingFileData *data = callback_data;
- CommonJob *job;
- GFile *source;
- GFileType file_type;
- char *primary;
- char *secondary;
- char *details = NULL;
- int response;
- g_autofree gchar *basename = NULL;
- g_autofree gchar *filename = NULL;
-
- job = data->job;
- source = data->source;
-
- if (error == NULL)
- {
- nautilus_file_changes_queue_file_removed (file);
-
- return;
- }
-
- if (job_aborted (job) || job->skip_all_error)
- {
- return;
- }
-
- basename = get_basename (source);
- primary = g_strdup_printf (_("Error while copying ā%sā."), basename);
-
- file_type = g_file_query_file_type (file,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- job->cancellable);
-
- filename = g_file_get_parse_name (file);
- if (file_type == G_FILE_TYPE_DIRECTORY)
- {
- secondary = g_strdup_printf (_("Could not remove the already existing folder %s."),
- filename);
- }
- else
- {
- secondary = g_strdup_printf (_("Could not remove the already existing file %s."),
- filename);
- }
-
- details = error->message;
-
- /* set show_all to TRUE here, as we don't know how many
- * files we'll end up processing yet.
- */
- response = run_warning (job,
- primary,
- secondary,
- details,
- TRUE,
- 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;
- }
-}
-
typedef struct
{
CopyMoveJob *job;
@@ -5411,9 +5329,14 @@ retry:
if (!overwrite &&
IS_IO_ERROR (error, EXISTS))
{
+ gboolean source_is_directory;
+ gboolean destination_is_directory;
gboolean is_merge;
FileConflictResponse *response;
+ source_is_directory = is_dir (src);
+ destination_is_directory = is_dir (dest);
+
g_error_free (error);
if (unique_names)
@@ -5425,10 +5348,16 @@ retry:
is_merge = FALSE;
- if (is_dir (dest) && is_dir (src))
+ if (source_is_directory && destination_is_directory)
{
is_merge = TRUE;
}
+ else if (!source_is_directory && destination_is_directory)
+ {
+ /* Any sane backend will fail with G_IO_ERROR_IS_DIRECTORY. */
+ overwrite = TRUE;
+ goto retry;
+ }
if ((is_merge && job->merge_all) ||
(!is_merge && job->replace_all))
@@ -5488,28 +5417,6 @@ retry:
g_assert_not_reached ();
}
}
- else if (overwrite &&
- IS_IO_ERROR (error, IS_DIRECTORY))
- {
- gboolean existing_file_deleted;
- DeleteExistingFileData data;
-
- g_error_free (error);
-
- data.job = job;
- data.source = src;
-
- existing_file_deleted =
- delete_file_recursively (dest,
- job->cancellable,
- existing_file_removed_callback,
- &data);
-
- if (existing_file_deleted)
- {
- goto retry;
- }
- }
/* Needs to recurse */
else if (IS_IO_ERROR (error, WOULD_RECURSE) ||
IS_IO_ERROR (error, WOULD_MERGE))
@@ -6154,16 +6061,27 @@ retry:
else if (!overwrite &&
IS_IO_ERROR (error, EXISTS))
{
+ gboolean source_is_directory;
+ gboolean destination_is_directory;
gboolean is_merge;
FileConflictResponse *response;
+ source_is_directory = is_dir (src);
+ destination_is_directory = is_dir (dest);
+
g_error_free (error);
is_merge = FALSE;
- if (is_dir (dest) && is_dir (src))
+ if (source_is_directory && destination_is_directory)
{
is_merge = TRUE;
}
+ else if (!source_is_directory && destination_is_directory)
+ {
+ /* Any sane backend will fail with G_IO_ERROR_IS_DIRECTORY. */
+ overwrite = TRUE;
+ goto retry;
+ }
if ((is_merge && job->merge_all) ||
(!is_merge && job->replace_all))
@@ -6225,8 +6143,7 @@ retry:
}
else if (IS_IO_ERROR (error, WOULD_RECURSE) ||
IS_IO_ERROR (error, WOULD_MERGE) ||
- IS_IO_ERROR (error, NOT_SUPPORTED) ||
- (overwrite && IS_IO_ERROR (error, IS_DIRECTORY)))
+ IS_IO_ERROR (error, NOT_SUPPORTED))
{
g_error_free (error);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]