diff options
author | Benjamin Otte <otte@gnome.org> | 2009-08-06 21:00:11 +0200 |
---|---|---|
committer | Benjamin Otte <otte@gnome.org> | 2009-08-06 21:08:53 +0200 |
commit | 21383e40e4cadf52f2bbf9ba463b9e85d02e122e (patch) | |
tree | 2fcf622c8a57a67cceda46728cda9c37f3df8287 /daemon/gvfsbackendftp.c | |
parent | c81297016b0d089acfba393d02cb09731faa21d3 (diff) | |
download | gvfs-21383e40e4cadf52f2bbf9ba463b9e85d02e122e.tar.gz |
[FTP] Bug 590793 - Can't copy folders over FTP
Duplicate the machinery for returning the proper error when the source
is a directory from gio and use it in the pull vfunc.
Diffstat (limited to 'daemon/gvfsbackendftp.c')
-rw-r--r-- | daemon/gvfsbackendftp.c | 76 |
1 files changed, 70 insertions, 6 deletions
diff --git a/daemon/gvfsbackendftp.c b/daemon/gvfsbackendftp.c index 0ceb78d7..94e64bab 100644 --- a/daemon/gvfsbackendftp.c +++ b/daemon/gvfsbackendftp.c @@ -650,7 +650,7 @@ do_open_for_read (GVfsBackend *backend, g_vfs_ftp_task_send_and_check (&task, G_VFS_FTP_PASS_100 | G_VFS_FTP_FAIL_200, - &open_read_handlers[0], + open_read_handlers, file, NULL, "RETR %s", g_vfs_ftp_file_get_ftp_path (file)); @@ -1249,6 +1249,65 @@ ftp_output_stream_splice (GOutputStream *output, } static void +do_pull_improve_error_message (GVfsFtpTask *task, + GFile *dest, + gboolean overwrite) +{ + GFileInfo *info; + GFileType file_type; + + /* There was an error opening the source, try to set a good error for it. + * Code taken from glib's gio/gfile.c:open_source_for_copy() function */ + + if (g_vfs_ftp_task_error_matches (task, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY)) + { + /* The source is a directory, don't fail with WOULD_RECURSE immediately, + * as that is less useful to the app. Better check for errors on the + * target instead. + */ + g_vfs_ftp_task_clear_error (task); + + info = g_file_query_info (dest, G_FILE_ATTRIBUTE_STANDARD_TYPE, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + task->cancellable, &task->error); + if (info != NULL) + { + file_type = g_file_info_get_file_type (info); + g_object_unref (info); + + if (overwrite) + { + if (file_type == G_FILE_TYPE_DIRECTORY) + { + g_set_error_literal (&task->error, G_IO_ERROR, G_IO_ERROR_WOULD_MERGE, + _("Can't copy directory over directory")); + return; + } + /* continue to would_recurse error */ + } + else + { + g_set_error_literal (&task->error, G_IO_ERROR, G_IO_ERROR_EXISTS, + _("Target file already exists")); + return; + } + } + else + { + /* Error getting info from target, return that error + * (except for NOT_FOUND, which is no error here) + */ + if (!g_vfs_ftp_task_error_matches (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + return; + g_vfs_ftp_task_clear_error (task); + } + + g_set_error_literal (&task->error, G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE, + _("Can't recursively copy directory")); + } +} + +static void do_pull (GVfsBackend * backend, GVfsJobPull * job, const char * source, @@ -1258,7 +1317,9 @@ do_pull (GVfsBackend * backend, GFileProgressCallback progress_callback, gpointer progress_callback_data) { - static const GVfsFtpErrorFunc open_read_handlers[] = { error_550_is_directory, NULL }; + static const GVfsFtpErrorFunc open_read_handlers[] = { error_550_is_directory, + error_550_permission_or_not_found, + NULL }; GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend); GVfsFtpTask task = G_VFS_FTP_TASK_INIT (ftp, G_VFS_JOB (job)); GVfsFtpFile *src; @@ -1268,19 +1329,22 @@ do_pull (GVfsBackend * backend, goffset total_size = 0; src = g_vfs_ftp_file_new_from_gvfs (ftp, source); + dest = g_file_new_for_path (local_path); g_vfs_ftp_task_setup_data_connection (&task); g_vfs_ftp_task_send_and_check (&task, G_VFS_FTP_PASS_100 | G_VFS_FTP_FAIL_200, - &open_read_handlers[0], + open_read_handlers, src, NULL, "RETR %s", g_vfs_ftp_file_get_ftp_path (src)); g_vfs_ftp_task_open_data_connection (&task); if (g_vfs_ftp_task_is_in_error (&task)) - goto out; + { + do_pull_improve_error_message (&task, dest, flags & G_FILE_COPY_OVERWRITE); + goto out; + } - dest = g_file_new_for_path (local_path); if (flags & G_FILE_COPY_OVERWRITE) output = G_OUTPUT_STREAM (g_file_replace (dest, NULL, @@ -1293,7 +1357,6 @@ do_pull (GVfsBackend * backend, 0, task.cancellable, &task.error)); - g_object_unref (dest); if (output == NULL) { g_vfs_ftp_task_close_data_connection (&task); @@ -1330,6 +1393,7 @@ do_pull (GVfsBackend * backend, } out: + g_object_unref (dest); g_vfs_ftp_file_free (src); g_vfs_ftp_task_done (&task); } |