[gvfs] [FTP] Bug 590793 - Can't copy folders over FTP
- From: Benjamin Otte <otte src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gvfs] [FTP] Bug 590793 - Can't copy folders over FTP
- Date: Thu, 6 Aug 2009 19:09:34 +0000 (UTC)
commit 21383e40e4cadf52f2bbf9ba463b9e85d02e122e
Author: Benjamin Otte <otte gnome org>
Date: Thu Aug 6 21:00:11 2009 +0200
[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.
daemon/gvfsbackendftp.c | 76 +++++++++++++++++++++++++++++++++++++++++++----
daemon/gvfsftptask.h | 1 +
2 files changed, 71 insertions(+), 6 deletions(-)
---
diff --git a/daemon/gvfsbackendftp.c b/daemon/gvfsbackendftp.c
index 0ceb78d..94e64ba 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);
}
diff --git a/daemon/gvfsftptask.h b/daemon/gvfsftptask.h
index ac0bd74..a496c0a 100644
--- a/daemon/gvfsftptask.h
+++ b/daemon/gvfsftptask.h
@@ -56,6 +56,7 @@ typedef void (* GVfsFtpErrorFunc) (GVfsFtpTask *task, gpointer data);
void g_vfs_ftp_task_done (GVfsFtpTask * task);
#define g_vfs_ftp_task_is_in_error(task) ((task)->error != NULL)
+#define g_vfs_ftp_task_error_matches(task, domain, code) (g_error_matches ((task)->error, (domain), (code)))
#define g_vfs_ftp_task_clear_error(task) (g_clear_error (&(task)->error))
void g_vfs_ftp_task_set_error_from_response (GVfsFtpTask * task,
guint response);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]