From a56e545824e0cdce4bbfbdf9fc54aa7405194cd9 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Thu, 21 Aug 2014 12:17:31 +0200 Subject: [PATCH] Fix crash when changing owner of file Cherry picked commits from git master: ab6aa9aca1c25c34e3f1aece63efbe05a2984397 bfa2d63249a1f5de986f7f1ad21d79920fa4947f f7d1394a03e6d02cd5c67f9c85a142e33f14566f https://bugzilla.redhat.com/show_bug.cgi?id=1090999 --- libnautilus-private/nautilus-file.c | 3 +- src/nautilus-properties-window.c | 354 +++++++++++++++++------------------- 2 files changed, 164 insertions(+), 193 deletions(-) diff --git a/libnautilus-private/nautilus-file.c b/libnautilus-private/nautilus-file.c index 5e837f6..efef296 100644 --- a/libnautilus-private/nautilus-file.c +++ b/libnautilus-private/nautilus-file.c @@ -5670,7 +5670,8 @@ nautilus_file_get_owner_as_string (NautilusFile *file, gboolean include_real_nam return NULL; } - if (file->details->uid == getuid ()) { + if (include_real_name && + file->details->uid == getuid ()) { /* Translators: "Me" is used to indicate the file is owned by me (the current user) */ user_name = g_strdup (_("Me")); } else if (file->details->owner_real == NULL) { diff --git a/src/nautilus-properties-window.c b/src/nautilus-properties-window.c index 6793b7a..7a81ddd 100644 --- a/src/nautilus-properties-window.c +++ b/src/nautilus-properties-window.c @@ -89,6 +89,22 @@ static GHashTable *windows; static GHashTable *pending_lists; +typedef struct { + NautilusFile *file; + char *owner; + GtkWindow *window; + unsigned int timeout; + gboolean cancelled; +} OwnerChange; + +typedef struct { + NautilusFile *file; + char *group; + GtkWindow *window; + unsigned int timeout; + gboolean cancelled; +} GroupChange; + struct NautilusPropertiesWindowDetails { GList *original_files; GList *target_files; @@ -112,12 +128,8 @@ struct NautilusPropertiesWindowDetails { guint update_directory_contents_timeout_id; guint update_files_timeout_id; - NautilusFile *group_change_file; - char *group_change_group; - unsigned int group_change_timeout; - NautilusFile *owner_change_file; - char *owner_change_owner; - unsigned int owner_change_timeout; + GroupChange *group_change; + OwnerChange *owner_change; GList *permission_buttons; GList *permission_combos; @@ -208,8 +220,8 @@ static void properties_window_update (NautilusPropertiesWindow *win GList *files); static void is_directory_ready_callback (NautilusFile *file, gpointer data); -static void cancel_group_change_callback (NautilusPropertiesWindow *window); -static void cancel_owner_change_callback (NautilusPropertiesWindow *window); +static void cancel_group_change_callback (GroupChange *change); +static void cancel_owner_change_callback (OwnerChange *change); static void parent_widget_destroyed_callback (GtkWidget *widget, gpointer callback_data); static void select_image_button_callback (GtkWidget *widget, @@ -1363,78 +1375,70 @@ attach_ellipsizing_value_field (NautilusPropertiesWindow *window, } static void +group_change_free (GroupChange *change) +{ + nautilus_file_unref (change->file); + g_free (change->group); + g_object_unref (change->window); + + g_free (change); +} + +static void group_change_callback (NautilusFile *file, GFile *res_loc, GError *error, - NautilusPropertiesWindow *window) + GroupChange *change) { - char *group; - - g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window)); - g_assert (window->details->group_change_file == file); + NautilusPropertiesWindow *window; - group = window->details->group_change_group; - g_assert (group != NULL); + g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (change->window)); + g_assert (NAUTILUS_IS_FILE (change->file)); + g_assert (change->group != NULL); - /* Report the error if it's an error. */ - eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window); - nautilus_report_error_setting_group (file, error, GTK_WINDOW (window)); + if (!change->cancelled) { + /* Report the error if it's an error. */ + eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, change); + nautilus_report_error_setting_group (change->file, error, change->window); + } - nautilus_file_unref (file); - g_free (group); + window = NAUTILUS_PROPERTIES_WINDOW(change->window); + if (window->details->group_change == change) { + window->details->group_change = NULL; + } - window->details->group_change_file = NULL; - window->details->group_change_group = NULL; - g_object_unref (G_OBJECT (window)); + group_change_free (change); } static void -cancel_group_change_callback (NautilusPropertiesWindow *window) +cancel_group_change_callback (GroupChange *change) { - NautilusFile *file; - char *group; + g_assert (NAUTILUS_IS_FILE (change->file)); + g_assert (change->group != NULL); - file = window->details->group_change_file; - g_assert (NAUTILUS_IS_FILE (file)); - - group = window->details->group_change_group; - g_assert (group != NULL); - - nautilus_file_cancel (file, (NautilusFileOperationCallback) group_change_callback, window); - - g_free (group); - nautilus_file_unref (file); - - window->details->group_change_file = NULL; - window->details->group_change_group = NULL; - g_object_unref (window); + change->cancelled = TRUE; + nautilus_file_cancel (change->file, (NautilusFileOperationCallback) group_change_callback, change); } static gboolean -schedule_group_change_timeout (NautilusPropertiesWindow *window) +schedule_group_change_timeout (GroupChange *change) { - NautilusFile *file; - char *group; + g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (change->window)); + g_assert (NAUTILUS_IS_FILE (change->file)); + g_assert (change->group != NULL); - g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window)); - - file = window->details->group_change_file; - g_assert (NAUTILUS_IS_FILE (file)); - - group = window->details->group_change_group; - g_assert (group != NULL); + change->timeout = 0; eel_timed_wait_start ((EelCancelCallback) cancel_group_change_callback, - window, + change, _("Cancel Group Change?"), - GTK_WINDOW (window)); + change->window); nautilus_file_set_group - (file, group, - (NautilusFileOperationCallback) group_change_callback, window); + (change->file, change->group, + (NautilusFileOperationCallback) group_change_callback, change); - window->details->group_change_timeout = 0; return FALSE; } @@ -1443,55 +1447,45 @@ schedule_group_change (NautilusPropertiesWindow *window, NautilusFile *file, const char *group) { + GroupChange *change; + g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window)); - g_assert (window->details->group_change_group == NULL); - g_assert (window->details->group_change_file == NULL); + g_assert (window->details->group_change == NULL); g_assert (NAUTILUS_IS_FILE (file)); - window->details->group_change_file = nautilus_file_ref (file); - window->details->group_change_group = g_strdup (group); - g_object_ref (G_OBJECT (window)); - window->details->group_change_timeout = + change = g_new0 (GroupChange, 1); + + change->file = nautilus_file_ref (file); + change->group = g_strdup (group); + change->window = g_object_ref (G_OBJECT (window)); + change->timeout = g_timeout_add (CHOWN_CHGRP_TIMEOUT, (GSourceFunc) schedule_group_change_timeout, - window); + change); + + window->details->group_change = change; } static void unschedule_or_cancel_group_change (NautilusPropertiesWindow *window) { - NautilusFile *file; - char *group; + GroupChange *change; g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window)); - file = window->details->group_change_file; - group = window->details->group_change_group; - - g_assert ((file == NULL && group == NULL) || - (file != NULL && group != NULL)); + change = window->details->group_change; - if (file != NULL) { - g_assert (NAUTILUS_IS_FILE (file)); - - if (window->details->group_change_timeout == 0) { - nautilus_file_cancel (file, - (NautilusFileOperationCallback) group_change_callback, window); - eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, window); + if (change != NULL) { + if (change->timeout == 0) { + /* The operation was started, cancel it and let the operation callback free the change */ + cancel_group_change_callback (change); + eel_timed_wait_stop ((EelCancelCallback) cancel_group_change_callback, change); + } else { + g_source_remove (change->timeout); + group_change_free (change); } - nautilus_file_unref (file); - g_free (group); - - window->details->group_change_file = NULL; - window->details->group_change_group = NULL; - g_object_unref (G_OBJECT (window)); - } - - if (window->details->group_change_timeout > 0) { - g_assert (file != NULL); - g_source_remove (window->details->group_change_timeout); - window->details->group_change_timeout = 0; + window->details->group_change = NULL; } } @@ -1713,18 +1707,18 @@ combo_box_row_separator_func (GtkTreeModel *model, static GtkComboBox * attach_combo_box (GtkGrid *grid, GtkWidget *sibling, - gboolean two_columns) + gboolean three_columns) { GtkWidget *combo_box; GtkWidget *aligner; - if (!two_columns) { + if (!three_columns) { combo_box = gtk_combo_box_text_new (); } else { GtkTreeModel *model; GtkCellRenderer *renderer; - model = GTK_TREE_MODEL (gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING)); + model = GTK_TREE_MODEL (gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING)); combo_box = gtk_combo_box_new_with_model (model); g_object_unref (G_OBJECT (model)); @@ -1778,78 +1772,70 @@ attach_group_combo_box (GtkGrid *grid, } static void +owner_change_free (OwnerChange *change) +{ + nautilus_file_unref (change->file); + g_free (change->owner); + g_object_unref (change->window); + + g_free (change); +} + +static void owner_change_callback (NautilusFile *file, GFile *result_location, GError *error, - NautilusPropertiesWindow *window) + OwnerChange *change) { - char *owner; - - g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window)); - g_assert (window->details->owner_change_file == file); + NautilusPropertiesWindow *window; - owner = window->details->owner_change_owner; - g_assert (owner != NULL); + g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (change->window)); + g_assert (NAUTILUS_IS_FILE (change->file)); + g_assert (change->owner != NULL); - /* Report the error if it's an error. */ - eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window); - nautilus_report_error_setting_owner (file, error, GTK_WINDOW (window)); + if (!change->cancelled) { + /* Report the error if it's an error. */ + eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, change); + nautilus_report_error_setting_owner (file, error, change->window); + } - nautilus_file_unref (file); - g_free (owner); + window = NAUTILUS_PROPERTIES_WINDOW(change->window); + if (window->details->owner_change == change) { + window->details->owner_change = NULL; + } - window->details->owner_change_file = NULL; - window->details->owner_change_owner = NULL; - g_object_unref (G_OBJECT (window)); + owner_change_free (change); } static void -cancel_owner_change_callback (NautilusPropertiesWindow *window) +cancel_owner_change_callback (OwnerChange *change) { - NautilusFile *file; - char *owner; - - file = window->details->owner_change_file; - g_assert (NAUTILUS_IS_FILE (file)); - - owner = window->details->owner_change_owner; - g_assert (owner != NULL); - - nautilus_file_cancel (file, (NautilusFileOperationCallback) owner_change_callback, window); - - nautilus_file_unref (file); - g_free (owner); + g_assert (NAUTILUS_IS_FILE (change->file)); + g_assert (change->owner != NULL); - window->details->owner_change_file = NULL; - window->details->owner_change_owner = NULL; - g_object_unref (window); + change->cancelled = TRUE; + nautilus_file_cancel (change->file, (NautilusFileOperationCallback) owner_change_callback, change); } static gboolean -schedule_owner_change_timeout (NautilusPropertiesWindow *window) +schedule_owner_change_timeout (OwnerChange *change) { - NautilusFile *file; - char *owner; - - g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window)); - - file = window->details->owner_change_file; - g_assert (NAUTILUS_IS_FILE (file)); + g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (change->window)); + g_assert (NAUTILUS_IS_FILE (change->file)); + g_assert (change->owner != NULL); - owner = window->details->owner_change_owner; - g_assert (owner != NULL); + change->timeout = 0; eel_timed_wait_start ((EelCancelCallback) cancel_owner_change_callback, - window, + change, _("Cancel Owner Change?"), - GTK_WINDOW (window)); + change->window); nautilus_file_set_owner - (file, owner, - (NautilusFileOperationCallback) owner_change_callback, window); + (change->file, change->owner, + (NautilusFileOperationCallback) owner_change_callback, change); - window->details->owner_change_timeout = 0; return FALSE; } @@ -1858,55 +1844,47 @@ schedule_owner_change (NautilusPropertiesWindow *window, NautilusFile *file, const char *owner) { + OwnerChange *change; + g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window)); - g_assert (window->details->owner_change_owner == NULL); - g_assert (window->details->owner_change_file == NULL); + g_assert (window->details->owner_change == NULL); g_assert (NAUTILUS_IS_FILE (file)); - window->details->owner_change_file = nautilus_file_ref (file); - window->details->owner_change_owner = g_strdup (owner); - g_object_ref (G_OBJECT (window)); - window->details->owner_change_timeout = + change = g_new0 (OwnerChange, 1); + + change->file = nautilus_file_ref (file); + change->owner = g_strdup (owner); + change->window = g_object_ref (G_OBJECT (window)); + change->timeout = g_timeout_add (CHOWN_CHGRP_TIMEOUT, (GSourceFunc) schedule_owner_change_timeout, - window); + change); + + window->details->owner_change = change; } static void unschedule_or_cancel_owner_change (NautilusPropertiesWindow *window) { - NautilusFile *file; - char *owner; + OwnerChange *change; g_assert (NAUTILUS_IS_PROPERTIES_WINDOW (window)); - file = window->details->owner_change_file; - owner = window->details->owner_change_owner; + change = window->details->owner_change; - g_assert ((file == NULL && owner == NULL) || - (file != NULL && owner != NULL)); + if (change != NULL) { + g_assert (NAUTILUS_IS_FILE (change->file)); - if (file != NULL) { - g_assert (NAUTILUS_IS_FILE (file)); - - if (window->details->owner_change_timeout == 0) { - nautilus_file_cancel (file, - (NautilusFileOperationCallback) owner_change_callback, window); - eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, window); + if (change->timeout == 0) { + /* The operation was started, cancel it and let the operation callback free the change */ + cancel_owner_change_callback (change); + eel_timed_wait_stop ((EelCancelCallback) cancel_owner_change_callback, change); + } else { + g_source_remove (change->timeout); + owner_change_free (change); } - nautilus_file_unref (file); - g_free (owner); - - window->details->owner_change_file = NULL; - window->details->owner_change_owner = NULL; - g_object_unref (G_OBJECT (window)); - } - - if (window->details->owner_change_timeout > 0) { - g_assert (file != NULL); - g_source_remove (window->details->owner_change_timeout); - window->details->owner_change_timeout = 0; + window->details->owner_change = NULL; } } @@ -1914,20 +1892,15 @@ static void changed_owner_callback (GtkComboBox *combo_box, NautilusFile* file) { NautilusPropertiesWindow *window; - char *owner_text; - char **name_array; char *new_owner; char *cur_owner; g_assert (GTK_IS_COMBO_BOX (combo_box)); g_assert (NAUTILUS_IS_FILE (file)); - owner_text = combo_box_get_active_entry (combo_box, 0); - if (! owner_text) + new_owner = combo_box_get_active_entry (combo_box, 2); + if (! new_owner) return; - name_array = g_strsplit (owner_text, " - ", 2); - new_owner = name_array[0]; - g_free (owner_text); cur_owner = nautilus_file_get_owner_name (file); if (strcmp (new_owner, cur_owner) != 0) { @@ -1937,7 +1910,7 @@ changed_owner_callback (GtkComboBox *combo_box, NautilusFile* file) unschedule_or_cancel_owner_change (window); schedule_owner_change (window, file, new_owner); } - g_strfreev (name_array); + g_free (new_owner); g_free (cur_owner); } @@ -1951,6 +1924,7 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file) GtkTreeIter iter; char *user_name; char *owner_name; + char *nice_owner_name; int user_index; int owner_index; char **name_array; @@ -1980,7 +1954,7 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file) user_name = (char *)node->data; name_array = g_strsplit (user_name, "\n", 2); - if (name_array[1] != NULL) { + if (name_array[1] != NULL && *name_array[1] != 0) { combo_text = g_strdup_printf ("%s - %s", name_array[0], name_array[1]); } else { combo_text = g_strdup (name_array[0]); @@ -1990,6 +1964,7 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file) gtk_list_store_set (store, &iter, 0, combo_text, 1, user_name, + 2, name_array[0], -1); g_strfreev (name_array); @@ -1997,8 +1972,9 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file) } } - owner_name = nautilus_file_get_string_attribute (file, "owner"); - owner_index = tree_model_get_entry_index (model, 0, owner_name); + owner_name = nautilus_file_get_owner_name (file); + owner_index = tree_model_get_entry_index (model, 2, owner_name); + nice_owner_name = nautilus_file_get_string_attribute (file, "owner"); /* If owner wasn't in list, we prepend it (with a separator). * This can happen if the owner is an id with no matching @@ -2011,30 +1987,24 @@ synch_user_menu (GtkComboBox *combo_box, NautilusFile *file) gtk_list_store_set (store, &iter, 0, "-", 1, NULL, + 2, NULL, -1); } - name_array = g_strsplit (owner_name, " - ", 2); - if (name_array[1] != NULL) { - user_name = g_strdup_printf ("%s\n%s", name_array[0], name_array[1]); - } else { - user_name = g_strdup (name_array[0]); - } owner_index = 0; gtk_list_store_prepend (store, &iter); gtk_list_store_set (store, &iter, - 0, owner_name, - 1, user_name, + 0, nice_owner_name, + 1, owner_name, + 2, owner_name, -1); - - g_free (user_name); - g_strfreev (name_array); } gtk_combo_box_set_active (combo_box, owner_index); g_free (owner_name); + g_free (nice_owner_name); g_list_free_full (users, g_free); } -- 2.0.4