diff --git a/file-roller-2.31.0-gvfs-fuse.patch b/file-roller-2.31.0-gvfs-fuse.patch new file mode 100644 index 0000000..836b34c --- /dev/null +++ b/file-roller-2.31.0-gvfs-fuse.patch @@ -0,0 +1,1217 @@ +From 33c21fc3647af32de5a9c9d49e33765a526910f5 Mon Sep 17 00:00:00 2001 +From: Tomas Bzatek +Date: Wed, 12 May 2010 11:54:29 +0000 +Subject: Bring back support for file caching when gvfs-fuse-daemon is not available + +The commit 73fa5d77a60861cd35c6f3425d27c88061af081c introduced trouble +when user was trying to work with archives on remote GIO mounts and +not having the fuse daemon running. This led to segfaults and error messages. + +Please see bug #617769 for details. +--- +diff --git a/src/fr-archive.c b/src/fr-archive.c +index e4a1259..adf9976 100644 +--- a/src/fr-archive.c ++++ b/src/fr-archive.c +@@ -114,16 +114,51 @@ struct _FrArchivePrivData { + FakeLoadFunc add_is_stoppable_func; /* Returns whether the add operation is + * stoppable. */ + gpointer add_is_stoppable_data; +- GCancellable *cancellable; ++ GCancellable *cancellable; + char *temp_dir; + gboolean continue_adding_dropped_items; + DroppedItemsData *dropped_items_data; + ++ char *temp_extraction_dir; + char *extraction_destination; ++ gboolean remote_extraction; + gboolean extract_here; + }; + + ++typedef struct { ++ FrArchive *archive; ++ char *uri; ++ FrAction action; ++ GList *file_list; ++ char *base_uri; ++ char *dest_dir; ++ gboolean update; ++ char *tmp_dir; ++ guint source_id; ++ char *password; ++ gboolean encrypt_header; ++ FrCompression compression; ++ guint volume_size; ++} XferData; ++ ++ ++static void ++xfer_data_free (XferData *data) ++{ ++ if (data == NULL) ++ return; ++ ++ g_free (data->uri); ++ g_free (data->password); ++ path_list_free (data->file_list); ++ g_free (data->base_uri); ++ g_free (data->dest_dir); ++ g_free (data->tmp_dir); ++ g_free (data); ++} ++ ++ + #define MAX_CHUNK_LEN (NCARGS * 2 / 3) /* Max command line length */ + #define UNKNOWN_TYPE "application/octet-stream" + #define SAME_FS (FALSE) +@@ -322,6 +357,8 @@ static void + fr_archive_init (FrArchive *archive) + { + archive->file = NULL; ++ archive->local_copy = NULL; ++ archive->is_remote = FALSE; + archive->command = NULL; + archive->is_compressed_file = FALSE; + archive->can_create_compressed_file = FALSE; +@@ -333,6 +370,7 @@ fr_archive_init (FrArchive *archive) + archive->priv->add_is_stoppable_data = NULL; + + archive->priv->extraction_destination = NULL; ++ archive->priv->temp_extraction_dir = NULL; + archive->priv->cancellable = g_cancellable_new (); + + archive->process = fr_process_new (); +@@ -350,18 +388,73 @@ fr_archive_new (void) + } + + ++static GFile * ++get_local_copy_for_file (GFile *remote_file) ++{ ++ char *temp_dir; ++ GFile *local_copy = NULL; ++ ++ temp_dir = get_temp_work_dir (NULL); ++ if (temp_dir != NULL) { ++ char *archive_name; ++ char *local_path; ++ ++ archive_name = g_file_get_basename (remote_file); ++ local_path = g_build_filename (temp_dir, archive_name, NULL); ++ local_copy = g_file_new_for_path (local_path); ++ ++ g_free (local_path); ++ g_free (archive_name); ++ } ++ g_free (temp_dir); ++ ++ return local_copy; ++} ++ ++ + static void + fr_archive_set_uri (FrArchive *archive, + const char *uri) + { ++ if ((archive->local_copy != NULL) && archive->is_remote) { ++ GFile *temp_folder; ++ GError *err = NULL; ++ ++ g_file_delete (archive->local_copy, NULL, &err); ++ if (err != NULL) { ++ g_warning ("Failed to delete the local copy: %s", err->message); ++ g_clear_error (&err); ++ } ++ ++ temp_folder = g_file_get_parent (archive->local_copy); ++ g_file_delete (temp_folder, NULL, &err); ++ if (err != NULL) { ++ g_warning ("Failed to delete temp folder: %s", err->message); ++ g_clear_error (&err); ++ } ++ ++ g_object_unref (temp_folder); ++ } ++ + if (archive->file != NULL) { + g_object_unref (archive->file); + archive->file = NULL; + } ++ if (archive->local_copy != NULL) { ++ g_object_unref (archive->local_copy); ++ archive->local_copy = NULL; ++ } + archive->content_type = NULL; + +- if (uri != NULL) +- archive->file = g_file_new_for_uri (uri); ++ if (uri == NULL) ++ return; ++ ++ archive->file = g_file_new_for_uri (uri); ++ archive->is_remote = ! g_file_has_uri_scheme (archive->file, "file"); ++ if (archive->is_remote) ++ archive->local_copy = get_local_copy_for_file (archive->file); ++ else ++ archive->local_copy = g_file_dup (archive->file); + } + + +@@ -395,6 +488,7 @@ fr_archive_finalize (GObject *object) + dropped_items_data_free (archive->priv->dropped_items_data); + archive->priv->dropped_items_data = NULL; + } ++ g_free (archive->priv->temp_extraction_dir); + g_free (archive->priv->extraction_destination); + g_free (archive->priv); + +@@ -501,7 +595,7 @@ create_command_from_type (FrArchive *archive, + if (command_type == 0) + return FALSE; + +- filename = g_file_get_path (archive->file); ++ filename = g_file_get_path (archive->local_copy); + archive->command = FR_COMMAND (g_object_new (command_type, + "process", archive->process, + "filename", filename, +@@ -588,6 +682,79 @@ action_started (FrCommand *command, + } + + ++/* -- copy_to_remote_location -- */ ++ ++ ++static void ++fr_archive_copy_done (FrArchive *archive, ++ FrAction action, ++ GError *error) ++{ ++ FrProcErrorType error_type = FR_PROC_ERROR_NONE; ++ const char *error_details = NULL; ++ ++ if (error != NULL) { ++ error_type = (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) ? FR_PROC_ERROR_STOPPED : FR_PROC_ERROR_GENERIC); ++ error_details = error->message; ++ } ++ fr_archive_action_completed (archive, action, error_type, error_details); ++} ++ ++ ++static void ++copy_to_remote_location_done (GError *error, ++ gpointer user_data) ++{ ++ XferData *xfer_data = user_data; ++ ++ fr_archive_copy_done (xfer_data->archive, xfer_data->action, error); ++ xfer_data_free (xfer_data); ++} ++ ++ ++static void ++copy_to_remote_location_progress (goffset current_file, ++ goffset total_files, ++ GFile *source, ++ GFile *destination, ++ goffset current_num_bytes, ++ goffset total_num_bytes, ++ gpointer user_data) ++{ ++ XferData *xfer_data = user_data; ++ ++ g_signal_emit (G_OBJECT (xfer_data->archive), ++ fr_archive_signals[PROGRESS], ++ 0, ++ (double) current_num_bytes / total_num_bytes); ++} ++ ++ ++static void ++copy_to_remote_location (FrArchive *archive, ++ FrAction action) ++{ ++ XferData *xfer_data; ++ ++ xfer_data = g_new0 (XferData, 1); ++ xfer_data->archive = archive; ++ xfer_data->action = action; ++ ++ g_copy_file_async (archive->local_copy, ++ archive->file, ++ G_FILE_COPY_OVERWRITE, ++ G_PRIORITY_DEFAULT, ++ archive->priv->cancellable, ++ copy_to_remote_location_progress, ++ xfer_data, ++ copy_to_remote_location_done, ++ xfer_data); ++} ++ ++ ++/* -- copy_extracted_files_to_destination -- */ ++ ++ + static void + move_here (FrArchive *archive) + { +@@ -656,6 +823,61 @@ move_here (FrArchive *archive) + } + + ++static void ++copy_extracted_files_done (GError *error, ++ gpointer user_data) ++{ ++ FrArchive *archive = user_data; ++ ++ remove_local_directory (archive->priv->temp_extraction_dir); ++ g_free (archive->priv->temp_extraction_dir); ++ archive->priv->temp_extraction_dir = NULL; ++ ++ fr_archive_action_completed (archive, ++ FR_ACTION_COPYING_FILES_TO_REMOTE, ++ FR_PROC_ERROR_NONE, ++ NULL); ++ ++ if ((error == NULL) && (archive->priv->extract_here)) ++ move_here (archive); ++ ++ fr_archive_copy_done (archive, FR_ACTION_EXTRACTING_FILES, error); ++} ++ ++ ++static void ++copy_extracted_files_progress (goffset current_file, ++ goffset total_files, ++ GFile *source, ++ GFile *destination, ++ goffset current_num_bytes, ++ goffset total_num_bytes, ++ gpointer user_data) ++{ ++ FrArchive *archive = user_data; ++ ++ g_signal_emit (G_OBJECT (archive), ++ fr_archive_signals[PROGRESS], ++ 0, ++ (double) current_file / (total_files + 1)); ++} ++ ++ ++static void ++copy_extracted_files_to_destination (FrArchive *archive) ++{ ++ g_directory_copy_async (archive->priv->temp_extraction_dir, ++ archive->priv->extraction_destination, ++ G_FILE_COPY_OVERWRITE, ++ G_PRIORITY_DEFAULT, ++ archive->priv->cancellable, ++ copy_extracted_files_progress, ++ archive, ++ copy_extracted_files_done, ++ archive); ++} ++ ++ + static void add_dropped_items (DroppedItemsData *data); + + +@@ -672,6 +894,11 @@ fr_archive_change_name (FrArchive *archive, + g_object_unref (archive->file); + archive->file = g_file_get_child (parent, name); + g_object_unref (parent); ++ ++ parent = g_file_get_parent (archive->local_copy); ++ g_object_unref (archive->local_copy); ++ archive->local_copy = g_file_get_child (parent, name); ++ g_object_unref (parent); + } + + +@@ -686,6 +913,15 @@ action_performed (FrCommand *command, + #endif + + switch (action) { ++ case FR_ACTION_DELETING_FILES: ++ if (error->type == FR_PROC_ERROR_NONE) { ++ if (! g_file_has_uri_scheme (archive->file, "file")) { ++ copy_to_remote_location (archive, action); ++ return; ++ } ++ } ++ break; ++ + case FR_ACTION_ADDING_FILES: + if (error->type == FR_PROC_ERROR_NONE) { + fr_archive_remove_temp_work_dir (archive); +@@ -701,15 +937,33 @@ action_performed (FrCommand *command, + * original name */ + if (archive->command->multi_volume) + fr_archive_change_name (archive, archive->command->filename); ++ if (! g_file_has_uri_scheme (archive->file, "file")) { ++ copy_to_remote_location (archive, action); ++ return; ++ } + } + break; + + case FR_ACTION_EXTRACTING_FILES: + if (error->type == FR_PROC_ERROR_NONE) { +- if (archive->priv->extract_here) ++ if (archive->priv->remote_extraction) { ++ copy_extracted_files_to_destination (archive); ++ return; ++ } ++ else if (archive->priv->extract_here) + move_here (archive); + } + else { ++ /* if an error occurred during extraction remove the ++ * temp extraction dir, if used. */ ++ g_print ("action_performed: ERROR!\n"); ++ ++ if ((archive->priv->remote_extraction) && (archive->priv->temp_extraction_dir != NULL)) { ++ remove_local_directory (archive->priv->temp_extraction_dir); ++ g_free (archive->priv->temp_extraction_dir); ++ archive->priv->temp_extraction_dir = NULL; ++ } ++ + if (archive->priv->extract_here) + remove_directory (archive->priv->extraction_destination); + } +@@ -817,7 +1071,7 @@ fr_archive_create (FrArchive *archive, + + tmp_command = archive->command; + +- mime_type = get_mime_type_from_filename (archive->file); ++ mime_type = get_mime_type_from_filename (archive->local_copy); + if (! create_command_to_create_archive (archive, mime_type)) { + archive->command = tmp_command; + return FALSE; +@@ -878,11 +1132,11 @@ load_local_archive (FrArchive *archive, + + tmp_command = archive->command; + +- mime_type = get_mime_type_from_filename (archive->file); ++ mime_type = get_mime_type_from_filename (archive->local_copy); + if (! create_command_to_load_archive (archive, mime_type)) { +- mime_type = get_mime_type_from_content (archive->file); ++ mime_type = get_mime_type_from_content (archive->local_copy); + if (! create_command_to_load_archive (archive, mime_type)) { +- mime_type = get_mime_type_from_magic_numbers (archive->file); ++ mime_type = get_mime_type_from_magic_numbers (archive->local_copy); + if (! create_command_to_load_archive (archive, mime_type)) { + archive->command = tmp_command; + archive->content_type = mime_type; +@@ -921,6 +1175,86 @@ load_local_archive (FrArchive *archive, + } + + ++static void ++copy_remote_file_done (GError *error, ++ gpointer user_data) ++{ ++ XferData *xfer_data = user_data; ++ ++ if (error != NULL) ++ fr_archive_copy_done (xfer_data->archive, FR_ACTION_LOADING_ARCHIVE, error); ++ else ++ load_local_archive (xfer_data->archive, xfer_data->password); ++ xfer_data_free (xfer_data); ++} ++ ++ ++static void ++copy_remote_file_progress (goffset current_file, ++ goffset total_files, ++ GFile *source, ++ GFile *destination, ++ goffset current_num_bytes, ++ goffset total_num_bytes, ++ gpointer user_data) ++{ ++ XferData *xfer_data = user_data; ++ ++ g_signal_emit (G_OBJECT (xfer_data->archive), ++ fr_archive_signals[PROGRESS], ++ 0, ++ (double) current_num_bytes / total_num_bytes); ++} ++ ++ ++static gboolean ++copy_remote_file_done_cb (gpointer user_data) ++{ ++ XferData *xfer_data = user_data; ++ ++ g_source_remove (xfer_data->source_id); ++ copy_remote_file_done (NULL, xfer_data); ++ return FALSE; ++} ++ ++ ++static void ++copy_remote_file (FrArchive *archive, ++ const char *password) ++{ ++ XferData *xfer_data; ++ ++ if (! g_file_query_exists (archive->file, NULL)) { ++ GError *error; ++ error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("The file doesn't exist")); ++ fr_archive_copy_done (archive, FR_ACTION_LOADING_ARCHIVE, error); ++ g_error_free (error); ++ return; ++ } ++ ++ xfer_data = g_new0 (XferData, 1); ++ xfer_data->archive = archive; ++ xfer_data->uri = g_file_get_uri (archive->file); ++ if (password != NULL) ++ xfer_data->password = g_strdup (password); ++ ++ if (! archive->is_remote) { ++ xfer_data->source_id = g_idle_add (copy_remote_file_done_cb, xfer_data); ++ return; ++ } ++ ++ g_copy_file_async (archive->file, ++ archive->local_copy, ++ G_FILE_COPY_OVERWRITE, ++ G_PRIORITY_DEFAULT, ++ archive->priv->cancellable, ++ copy_remote_file_progress, ++ xfer_data, ++ copy_remote_file_done, ++ xfer_data); ++} ++ ++ + gboolean + fr_archive_load (FrArchive *archive, + const char *uri, +@@ -934,7 +1268,7 @@ fr_archive_load (FrArchive *archive, + FR_ACTION_LOADING_ARCHIVE); + + fr_archive_set_uri (archive, uri); +- load_local_archive (archive, password); ++ copy_remote_file (archive, password); + + return TRUE; + } +@@ -953,7 +1287,7 @@ fr_archive_load_local (FrArchive *archive, + FR_ACTION_LOADING_ARCHIVE); + + fr_archive_set_uri (archive, uri); +- load_local_archive (archive, password); ++ copy_remote_file (archive, password); + + return TRUE; + } +@@ -1120,18 +1454,12 @@ convert_to_local_file_list (GList *file_list) + GList *scan; + + for (scan = file_list; scan; scan = scan->next) { +- GFile *file; +- char *uri = scan->data; +- char *local_filename; +- +- file = g_file_new_for_uri (uri); +- local_filename = g_file_get_path (file); +- if (local_filename == NULL) +- local_filename = g_strdup (uri); ++ char *uri = scan->data; ++ char *local_filename; ++ ++ local_filename = g_uri_unescape_string (uri, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH); + if (local_filename != NULL) + local_file_list = g_list_prepend (local_file_list, local_filename); +- +- g_object_unref (file); + } + + return local_file_list; +@@ -1446,6 +1774,145 @@ fr_archive_add_local_files (FrArchive *archive, + } + + ++static void ++copy_remote_files_done (GError *error, ++ gpointer user_data) ++{ ++ XferData *xfer_data = user_data; ++ ++ fr_archive_copy_done (xfer_data->archive, FR_ACTION_COPYING_FILES_FROM_REMOTE, error); ++ ++ if (error == NULL) ++ fr_archive_add_local_files (xfer_data->archive, ++ xfer_data->file_list, ++ xfer_data->tmp_dir, ++ xfer_data->dest_dir, ++ FALSE, ++ xfer_data->password, ++ xfer_data->encrypt_header, ++ xfer_data->compression, ++ xfer_data->volume_size); ++ xfer_data_free (xfer_data); ++} ++ ++ ++static void ++copy_remote_files_progress (goffset current_file, ++ goffset total_files, ++ GFile *source, ++ GFile *destination, ++ goffset current_num_bytes, ++ goffset total_num_bytes, ++ gpointer user_data) ++{ ++ XferData *xfer_data = user_data; ++ ++ g_signal_emit (G_OBJECT (xfer_data->archive), ++ fr_archive_signals[PROGRESS], ++ 0, ++ (double) current_file / (total_files + 1)); ++} ++ ++ ++static void ++copy_remote_files (FrArchive *archive, ++ GList *file_list, ++ const char *base_uri, ++ const char *dest_dir, ++ gboolean update, ++ const char *password, ++ gboolean encrypt_header, ++ FrCompression compression, ++ guint volume_size, ++ const char *tmp_dir) ++{ ++ GList *sources = NULL, *destinations = NULL; ++ GHashTable *created_folders; ++ GList *scan; ++ XferData *xfer_data; ++ ++ created_folders = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL); ++ for (scan = file_list; scan; scan = scan->next) { ++ char *partial_filename = scan->data; ++ char *local_uri; ++ char *local_folder_uri; ++ char *remote_uri; ++ ++ local_uri = g_strconcat ("file://", tmp_dir, "/", partial_filename, NULL); ++ local_folder_uri = remove_level_from_path (local_uri); ++ if (g_hash_table_lookup (created_folders, local_folder_uri) == NULL) { ++ GError *error = NULL; ++ if (! ensure_dir_exists (local_folder_uri, 0755, &error)) { ++ g_free (local_folder_uri); ++ g_free (local_uri); ++ gio_file_list_free (sources); ++ gio_file_list_free (destinations); ++ g_hash_table_destroy (created_folders); ++ ++ fr_archive_action_completed (archive, ++ FR_ACTION_COPYING_FILES_FROM_REMOTE, ++ FR_PROC_ERROR_GENERIC, ++ error->message); ++ g_clear_error (&error); ++ return; ++ } ++ ++ g_hash_table_insert (created_folders, local_folder_uri, GINT_TO_POINTER (1)); ++ } ++ else ++ g_free (local_folder_uri); ++ ++ remote_uri = g_strconcat (base_uri, "/", partial_filename, NULL); ++ sources = g_list_append (sources, g_file_new_for_uri (remote_uri)); ++ g_free (remote_uri); ++ ++ destinations = g_list_append (destinations, g_file_new_for_uri (local_uri)); ++ g_free (local_uri); ++ } ++ g_hash_table_destroy (created_folders); ++ ++ xfer_data = g_new0 (XferData, 1); ++ xfer_data->archive = archive; ++ xfer_data->file_list = path_list_dup (file_list); ++ xfer_data->base_uri = g_strdup (base_uri); ++ xfer_data->dest_dir = g_strdup (dest_dir); ++ xfer_data->update = update; ++ xfer_data->dest_dir = g_strdup (dest_dir); ++ xfer_data->password = g_strdup (password); ++ xfer_data->encrypt_header = encrypt_header; ++ xfer_data->compression = compression; ++ xfer_data->volume_size = volume_size; ++ xfer_data->tmp_dir = g_strdup (tmp_dir); ++ ++ g_signal_emit (G_OBJECT (archive), ++ fr_archive_signals[START], ++ 0, ++ FR_ACTION_COPYING_FILES_FROM_REMOTE); ++ ++ g_copy_files_async (sources, ++ destinations, ++ G_FILE_COPY_OVERWRITE, ++ G_PRIORITY_DEFAULT, ++ archive->priv->cancellable, ++ copy_remote_files_progress, ++ xfer_data, ++ copy_remote_files_done, ++ xfer_data); ++ ++ gio_file_list_free (sources); ++ gio_file_list_free (destinations); ++} ++ ++ ++static char * ++fr_archive_get_temp_work_dir (FrArchive *archive) ++{ ++ fr_archive_remove_temp_work_dir (archive); ++ archive->priv->temp_dir = get_temp_work_dir (NULL); ++ return archive->priv->temp_dir; ++} ++ ++ + void + fr_archive_add_files (FrArchive *archive, + GList *file_list, +@@ -1457,23 +1924,30 @@ fr_archive_add_files (FrArchive *archive, + FrCompression compression, + guint volume_size) + { +- GFile *file; +- char *local_dir; +- +- file = g_file_new_for_uri (base_dir); +- local_dir = g_file_get_path (file); +- fr_archive_add_local_files (archive, +- file_list, +- local_dir, +- dest_dir, +- update, +- password, +- encrypt_header, +- compression, +- volume_size); +- +- g_free (local_dir); +- g_object_unref (file); ++ if (uri_is_local (base_dir)) { ++ char *local_dir = g_filename_from_uri (base_dir, NULL, NULL); ++ fr_archive_add_local_files (archive, ++ file_list, ++ local_dir, ++ dest_dir, ++ update, ++ password, ++ encrypt_header, ++ compression, ++ volume_size); ++ g_free (local_dir); ++ } ++ else ++ copy_remote_files (archive, ++ file_list, ++ base_dir, ++ dest_dir, ++ update, ++ password, ++ encrypt_header, ++ compression, ++ volume_size, ++ fr_archive_get_temp_work_dir (archive)); + } + + +@@ -2675,25 +3149,38 @@ fr_archive_extract (FrArchive *archive, + gboolean junk_paths, + const char *password) + { +- GFile *file; +- char *local_destination; +- + g_free (archive->priv->extraction_destination); + archive->priv->extraction_destination = g_strdup (destination); + +- file = g_file_new_for_uri (destination); +- local_destination = g_file_get_path (file); +- fr_archive_extract_to_local (archive, +- file_list, +- local_destination, +- base_dir, +- skip_older, +- overwrite, +- junk_paths, +- password); +- +- g_free (local_destination); +- g_object_unref (file); ++ g_free (archive->priv->temp_extraction_dir); ++ archive->priv->temp_extraction_dir = NULL; ++ ++ archive->priv->remote_extraction = ! uri_is_local (destination); ++ if (archive->priv->remote_extraction) { ++ archive->priv->temp_extraction_dir = get_temp_work_dir (NULL); ++ fr_archive_extract_to_local (archive, ++ file_list, ++ archive->priv->temp_extraction_dir, ++ base_dir, ++ skip_older, ++ overwrite, ++ junk_paths, ++ password); ++ } ++ else { ++ char *local_destination; ++ ++ local_destination = g_filename_from_uri (destination, NULL, NULL); ++ fr_archive_extract_to_local (archive, ++ file_list, ++ local_destination, ++ base_dir, ++ skip_older, ++ overwrite, ++ junk_paths, ++ password); ++ g_free (local_destination); ++ } + } + + +diff --git a/src/fr-archive.h b/src/fr-archive.h +index 2c485a2..530e49e 100644 +--- a/src/fr-archive.h ++++ b/src/fr-archive.h +@@ -44,6 +44,8 @@ struct _FrArchive { + GObject __parent; + + GFile *file; ++ GFile *local_copy; ++ gboolean is_remote; + const char *content_type; + FrCommand *command; + FrProcess *process; +diff --git a/src/fr-window.c b/src/fr-window.c +index 8eeb833..d8fb08e 100644 +--- a/src/fr-window.c ++++ b/src/fr-window.c +@@ -4226,14 +4226,14 @@ get_selection_data_from_clipboard_data (FrWindow *window, + FrClipboardData *data) + { + GString *list; +- char *archive_uri; ++ char *local_filename; + GList *scan; + + list = g_string_new (NULL); + +- archive_uri = g_file_get_uri (window->archive->file); +- g_string_append (list, archive_uri); +- g_free (archive_uri); ++ local_filename = g_file_get_uri (window->archive->local_copy); ++ g_string_append (list, local_filename); ++ g_free (local_filename); + + g_string_append (list, "\r\n"); + if (window->priv->password != NULL) +diff --git a/src/gio-utils.c b/src/gio-utils.c +index f94e94f..7886b2e 100644 +--- a/src/gio-utils.c ++++ b/src/gio-utils.c +@@ -127,7 +127,7 @@ filter_empty (Filter *filter) + + + typedef struct { +- char *base_directory; ++ GFile *base_directory; + gboolean recursive; + gboolean follow_links; + StartDirCallback start_dir_func; +@@ -153,7 +153,8 @@ for_each_child_data_free (ForEachChildData *fec) + if (fec == NULL) + return; + +- g_free (fec->base_directory); ++ if (fec->base_directory != NULL) ++ g_object_unref (fec->base_directory); + if (fec->current != NULL) + g_object_unref (fec->current); + if (fec->already_visited) +@@ -172,7 +173,7 @@ for_each_child_done_cb (gpointer user_data) + g_source_remove (fec->source_id); + if (fec->current != NULL) { + g_object_unref (fec->current); +- fec->current = NULL; ++ fec->current = NULL; + } + if (fec->done_func) + fec->done_func (fec->error, fec->user_data); +@@ -212,8 +213,8 @@ for_each_child_start (ForEachChildData *fec) + + + static void +-for_each_child_set_current (ForEachChildData *fec, +- const char *directory) ++for_each_child_set_current_uri (ForEachChildData *fec, ++ const char *directory) + { + if (fec->current != NULL) + g_object_unref (fec->current); +@@ -222,6 +223,15 @@ for_each_child_set_current (ForEachChildData *fec, + + + static void ++for_each_child_set_current (ForEachChildData *fec, ++ GFile *directory) ++{ ++ if (fec->current != NULL) ++ g_object_unref (fec->current); ++ fec->current = g_file_dup (directory); ++} ++ ++static void + for_each_child_start_next_sub_directory (ForEachChildData *fec) + { + char *sub_directory = NULL; +@@ -236,7 +246,7 @@ for_each_child_start_next_sub_directory (ForEachChildData *fec) + } + + if (sub_directory != NULL) { +- for_each_child_set_current (fec, sub_directory); ++ for_each_child_set_current_uri (fec, sub_directory); + for_each_child_start (fec); + } + else +@@ -276,7 +286,6 @@ for_each_child_next_files_ready (GObject *source_object, + { + ForEachChildData *fec = user_data; + GList *children, *scan; +- char *current_directory; + + children = g_file_enumerator_next_files_finish (fec->enumerator, + result, +@@ -291,16 +300,16 @@ for_each_child_next_files_ready (GObject *source_object, + return; + } + +- current_directory = g_file_get_uri (fec->current); + for (scan = children; scan; scan = scan->next) { + GFileInfo *child_info = scan->data; +- char *name, *uri; ++ GFile *f; ++ char *uri; + +- name = g_uri_escape_string (g_file_info_get_name (child_info), G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT, FALSE); +- uri = g_strconcat (current_directory, "/", name, NULL); ++ f = g_file_get_child (fec->current, g_file_info_get_name (child_info)); ++ uri = g_file_get_uri (f); + + if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY) { +- /* avoid to visit a directory more than ones */ ++ /* avoid to visit a directory more than once */ + + if (g_hash_table_lookup (fec->already_visited, uri) == NULL) { + char *sub_directory; +@@ -314,9 +323,8 @@ for_each_child_next_files_ready (GObject *source_object, + fec->for_each_file_func (uri, child_info, fec->user_data); + + g_free (uri); +- g_free (name); ++ g_object_unref (f); + } +- g_free (current_directory); + + g_file_enumerator_next_files_async (fec->enumerator, + N_FILES_PER_REQUEST, +@@ -404,7 +412,7 @@ for_each_child_start_current (ForEachChildData *fec) + * Each callback uses the same @user_data additional parameter. + */ + void +-g_directory_foreach_child (const char *directory, ++g_directory_foreach_child (GFile *directory, + gboolean recursive, + gboolean follow_links, + GCancellable *cancellable, +@@ -419,7 +427,7 @@ g_directory_foreach_child (const char *directory, + + fec = g_new0 (ForEachChildData, 1); + +- fec->base_directory = g_strdup (directory); ++ fec->base_directory = g_object_ref (directory); + fec->recursive = recursive; + fec->follow_links = follow_links; + fec->cancellable = cancellable; +@@ -443,8 +451,8 @@ g_directory_foreach_child (const char *directory, + typedef struct { + GList *files; + GList *dirs; +- char *directory; +- char *base_dir; ++ GFile *directory; ++ GFile *base_dir; + GCancellable *cancellable; + ListReadyCallback done_func; + gpointer done_data; +@@ -469,8 +477,10 @@ get_file_list_data_free (GetFileListData *gfl) + path_list_free (gfl->files); + path_list_free (gfl->dirs); + path_list_free (gfl->to_visit); +- g_free (gfl->directory); +- g_free (gfl->base_dir); ++ if (gfl->directory != NULL) ++ g_object_unref (gfl->directory); ++ if (gfl->base_dir != NULL) ++ g_object_unref (gfl->base_dir); + g_free (gfl); + } + +@@ -479,27 +489,25 @@ get_file_list_data_free (GetFileListData *gfl) + + + static GList* +-get_relative_file_list (GList *rel_list, +- GList *file_list, +- const char *base_dir) ++get_relative_file_list (GList *rel_list, ++ GList *file_list, ++ GFile *base_dir) + { + GList *scan; +- int base_len; + + if (base_dir == NULL) + return NULL; + +- base_len = 0; +- if (strcmp (base_dir, "/") != 0) +- base_len = strlen (base_dir); +- + for (scan = file_list; scan; scan = scan->next) { +- char *full_path = scan->data; +- +- if (path_in_path (base_dir, full_path)) { +- char *rel_path = g_uri_unescape_string (full_path + base_len + 1, NULL); +- rel_list = g_list_prepend (rel_list, rel_path); +- } ++ char *full_path = scan->data; ++ GFile *f; ++ char *relative_path; ++ ++ f = g_file_new_for_commandline_arg (full_path); ++ relative_path = g_file_get_relative_path (base_dir, f); ++ if (relative_path != NULL) ++ rel_list = g_list_prepend (rel_list, relative_path); ++ g_object_unref (f); + } + + return rel_list; +@@ -565,6 +573,7 @@ get_file_list_done (GError *error, + GetFileListData *gfl = user_data; + GHashTable *h_dirs; + GList *scan; ++ char *uri; + + gfl->files = g_list_reverse (gfl->files); + gfl->dirs = g_list_reverse (gfl->dirs); +@@ -582,7 +591,7 @@ get_file_list_done (GError *error, + if (gfl->base_dir != NULL) { + char *dir; + +- dir = g_strdup (gfl->base_dir); ++ dir = g_file_get_uri (gfl->base_dir); + gfl->dirs = g_list_prepend (gfl->dirs, dir); + g_hash_table_insert (h_dirs, dir, GINT_TO_POINTER (1)); + } +@@ -594,11 +603,13 @@ get_file_list_done (GError *error, + for (scan = gfl->dirs; scan; scan = scan->next) + g_hash_table_insert (h_dirs, (char*)scan->data, GINT_TO_POINTER (1)); + +- gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, gfl->base_dir, gfl->files, FALSE)); ++ uri = g_file_get_uri (gfl->base_dir); ++ gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, uri, gfl->files, FALSE)); + + if (filter_empty (gfl->include_filter)) +- gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, gfl->base_dir, gfl->dirs, TRUE)); ++ gfl->dirs = g_list_concat (gfl->dirs, get_dir_list_from_file_list (h_dirs, uri, gfl->dirs, TRUE)); + ++ g_free (uri); + /**/ + + if (error == NULL) { +@@ -680,8 +691,8 @@ g_directory_list_async (const char *directory, + FilterOptions filter_options; + + gfl = g_new0 (GetFileListData, 1); +- gfl->directory = g_strdup (directory); +- gfl->base_dir = g_strdup (base_dir); ++ gfl->directory = g_file_new_for_commandline_arg (directory); ++ gfl->base_dir = g_file_new_for_commandline_arg (base_dir); + gfl->done_func = done_func; + gfl->done_data = done_data; + +@@ -696,7 +707,7 @@ g_directory_list_async (const char *directory, + gfl->exclude_filter = filter_new (exclude_files, ignorecase ? FILTER_IGNORECASE : FILTER_DEFAULT); + gfl->exclude_folders_filter = filter_new (exclude_folders, ignorecase ? FILTER_IGNORECASE : FILTER_DEFAULT); + +- g_directory_foreach_child (directory, ++ g_directory_foreach_child (gfl->directory, + recursive, + follow_links, + cancellable, +@@ -756,7 +767,9 @@ static void + get_items_for_current_dir (GetFileListData *gfl) + { + const char *directory_name; ++ GFile *directory_file; + char *directory_uri; ++ char *base_dir_uri; + + if (gfl->current_dir == NULL) { + if (gfl->done_func) { +@@ -770,19 +783,20 @@ get_items_for_current_dir (GetFileListData *gfl) + } + + directory_name = file_name_from_path ((char*) gfl->current_dir->data); +- if (strcmp (gfl->base_dir, "/") == 0) +- directory_uri = g_strconcat (gfl->base_dir, directory_name, NULL); +- else +- directory_uri = g_strconcat (gfl->base_dir, "/", directory_name, NULL); ++ directory_file = g_file_get_child (gfl->base_dir, directory_name); ++ directory_uri = g_file_get_uri (directory_file); ++ base_dir_uri = g_file_get_uri (gfl->base_dir); + + g_directory_list_all_async (directory_uri, +- gfl->base_dir, ++ base_dir_uri, + TRUE, + gfl->cancellable, +- get_items_for_current_dir_done, +- gfl); ++ get_items_for_current_dir_done, ++ gfl); + + g_free (directory_uri); ++ g_free (base_dir_uri); ++ g_object_unref (directory_file); + } + + +@@ -800,7 +814,7 @@ g_list_items_async (GList *items, + g_return_if_fail (base_dir != NULL); + + gfl = g_new0 (GetFileListData, 1); +- gfl->base_dir = g_strdup (base_dir); ++ gfl->base_dir = g_file_new_for_commandline_arg (base_dir); + gfl->cancellable = cancellable; + gfl->done_func = done_func; + gfl->done_data = done_data; +@@ -916,6 +930,19 @@ g_copy_files_ready_cb (GObject *source_object, + GError *error = NULL; + + if (! g_file_copy_finish (source, result, &error)) { ++ /* source and target are directories, ignore the error */ ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE)) ++ g_clear_error (&error); ++ /* source is directory, create target directory */ ++ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE)) { ++ g_clear_error (&error); ++ g_file_make_directory ((GFile*) cfd->destination->data, ++ cfd->cancellable, ++ &error); ++ } ++ } ++ ++ if (error) { + if (cfd->callback) + cfd->callback (error, cfd->user_data); + g_clear_error (&error); +@@ -1123,8 +1150,8 @@ child_data_free (ChildData *child) + + + typedef struct { +- char *source; +- char *destination; ++ GFile *source; ++ GFile *destination; + GFileCopyFlags flags; + int io_priority; + GCancellable *cancellable; +@@ -1149,8 +1176,10 @@ directory_copy_data_free (DirectoryCopyData *dcd) + if (dcd == NULL) + return; + +- g_free (dcd->source); +- g_free (dcd->destination); ++ if (dcd->source != NULL) ++ g_object_unref (dcd->source); ++ if (dcd->destination != NULL) ++ g_object_unref (dcd->destination); + if (dcd->current_source != NULL) { + g_object_unref (dcd->current_source); + dcd->current_source = NULL; +@@ -1161,7 +1190,6 @@ directory_copy_data_free (DirectoryCopyData *dcd) + } + g_list_foreach (dcd->to_copy, (GFunc) child_data_free, NULL); + g_list_free (dcd->to_copy); +- g_object_unref (dcd->cancellable); + g_free (dcd); + } + +@@ -1187,15 +1215,19 @@ static GFile * + get_destination_for_uri (DirectoryCopyData *dcd, + const char *uri) + { +- char *destination_uri; ++ GFile *f_uri; + GFile *destination_file; ++ char *relative_path; + +- if (strlen (uri) <= strlen (dcd->source)) +- return NULL; ++ f_uri = g_file_new_for_uri (uri); ++ relative_path = g_file_get_relative_path (dcd->source, f_uri); ++ if (relative_path != NULL) ++ destination_file = g_file_resolve_relative_path (dcd->destination, relative_path); ++ else ++ destination_file = g_file_dup (dcd->destination); + +- destination_uri = g_strconcat (dcd->destination, "/", uri + strlen (dcd->source) + 1, NULL); +- destination_file = g_file_new_for_uri (destination_uri); +- g_free (destination_uri); ++ g_free (relative_path); ++ g_object_unref (f_uri); + + return destination_file; + } +@@ -1417,9 +1449,10 @@ g_directory_copy_async (const char *source, + { + DirectoryCopyData *dcd; + ++ /* Creating GFile objects here will save us lot of effort in path construction */ + dcd = g_new0 (DirectoryCopyData, 1); +- dcd->source = g_strdup (source); +- dcd->destination = g_strdup (destination); ++ dcd->source = g_file_new_for_commandline_arg (source); ++ dcd->destination = g_file_new_for_commandline_arg (destination); + dcd->flags = flags; + dcd->io_priority = io_priority; + dcd->cancellable = cancellable; +diff --git a/src/gio-utils.h b/src/gio-utils.h +index 4cd0a49..7dfe306 100644 +--- a/src/gio-utils.h ++++ b/src/gio-utils.h +@@ -58,7 +58,7 @@ typedef void (*CopyDoneCallback) (GError *error, + + /* asynchronous recursive list functions */ + +-void g_directory_foreach_child (const char *directory, ++void g_directory_foreach_child (GFile *directory, + gboolean recursive, + gboolean follow_links, + GCancellable *cancellable, +-- +cgit v0.8.3.1 diff --git a/file-roller.spec b/file-roller.spec index cddcbde..9837f73 100644 --- a/file-roller.spec +++ b/file-roller.spec @@ -11,7 +11,7 @@ Summary: Tool for viewing and creating archives Name: file-roller Version: 2.30.1.1 -Release: 2%{?dist} +Release: 3%{?dist} License: GPLv2+ Group: Applications/Archiving URL: http://download.gnome.org/sources/file-roller/ @@ -43,6 +43,10 @@ Conflicts: nautilus < 2.2.0 # https://bugzilla.gnome.org/show_bug.cgi?id=617840 Patch0: tar7z.patch +# from master +# http://bugzilla.gnome.org/show_bug.cgi?id=617769 +Patch1: file-roller-2.31.0-gvfs-fuse.patch + %description File Roller is an application for creating and viewing archives files, such as tar or zip files. @@ -50,6 +54,7 @@ such as tar or zip files. %prep %setup -q %patch0 -p1 -b .tarz7 +%patch1 -p1 -b .gvfs-fuse %build %configure --disable-scrollkeeper \ @@ -111,6 +116,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{_datadir}/icons/hicolor/scalable/apps/file-roller.svg %changelog +* Mon May 17 2010 Tomas Bzatek 2.30.1.1-3 +- Fix archive handling on remote GIO mounts without running fuse daemon (#527045, #518510) + * Wed May 5 2010 Matthias Clasen 2.30.1.1-2 - Don't crash when creating .tar.7z archives