From acee2f135e284b8ad245942a5622323989108391 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Thu, 12 Jun 2008 09:25:23 +0000 Subject: [PATCH] - Fix transfer of whole directories from FTP (#448560) --- gvfs-ftp-read-directory-2.patch | 154 ++++++++++++++++++++++++++++++++ gvfs.spec | 10 ++- 2 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 gvfs-ftp-read-directory-2.patch diff --git a/gvfs-ftp-read-directory-2.patch b/gvfs-ftp-read-directory-2.patch new file mode 100644 index 0000000..29db6f1 --- /dev/null +++ b/gvfs-ftp-read-directory-2.patch @@ -0,0 +1,154 @@ +Index: daemon/gvfsbackendftp.c +=================================================================== +--- daemon/gvfsbackendftp.c (revision 1801) ++++ daemon/gvfsbackendftp.c (working copy) +@@ -134,6 +134,8 @@ + + #define STATUS_GROUP(status) ((status) / 100) + ++typedef void (* Ftp550Handler) (FtpConnection *conn, const FtpFile *file); ++ + /*** FTP CONNECTION ***/ + + struct _FtpConnection +@@ -249,8 +251,8 @@ + case 550: /* Requested action not taken. File unavailable (e.g., file not found, no access). */ + /* FIXME: This is a lot of different errors. So we have to pretend to + * be smart here. */ +- code = G_IO_ERROR_NOT_FOUND; +- msg = _("File unavailable"); ++ code = G_IO_ERROR_FAILED; ++ msg = _("Operation failed"); + break; + case 451: /* Requested action aborted: local error in processing. */ + code = G_IO_ERROR_FAILED; +@@ -297,6 +299,7 @@ + * RESPONSE_PASS_300: Don't treat 3XX responses, but return them + * RESPONSE_PASS_400: Don't treat 4XX responses, but return them + * RESPONSE_PASS_500: Don't treat 5XX responses, but return them ++ * RESPONSE_PASS_550: Don't treat 550 responses, but return them + * RESPONSE_FAIL_200: Fail on a 2XX response + */ + +@@ -305,7 +308,8 @@ + RESPONSE_PASS_300 = (1 << 1), + RESPONSE_PASS_400 = (1 << 2), + RESPONSE_PASS_500 = (1 << 3), +- RESPONSE_FAIL_200 = (1 << 4) ++ RESPONSE_PASS_550 = (1 << 4), ++ RESPONSE_FAIL_200 = (1 << 5) + } ResponseFlags; + + /** +@@ -459,7 +463,7 @@ + return 0; + break; + case 5: +- if (flags & RESPONSE_PASS_500) ++ if ((flags & RESPONSE_PASS_500) || (response == 550 && (flags & RESPONSE_PASS_550))) + break; + ftp_connection_set_error_from_response (conn, response); + return 0; +@@ -564,6 +568,57 @@ + } + + static void ++ftp_connection_check_file (FtpConnection *conn, ++ const Ftp550Handler *handlers, ++ const FtpFile *file) ++{ ++ while (*handlers && !ftp_connection_in_error (conn)) ++ { ++ (*handlers) (conn, file); ++ handlers++; ++ } ++} ++ ++static guint ++ftp_connection_send_and_check (FtpConnection *conn, ++ ResponseFlags flags, ++ const Ftp550Handler *handlers, ++ const FtpFile *file, ++ const char *format, ++ ...) G_GNUC_PRINTF (5, 6); ++static guint ++ftp_connection_send_and_check (FtpConnection *conn, ++ ResponseFlags flags, ++ const Ftp550Handler *handlers, ++ const FtpFile *file, ++ const char *format, ++ ...) ++{ ++ va_list varargs; ++ guint response; ++ ++ /* check that there's no 550 handling used - don't allow bad use of API */ ++ g_return_val_if_fail ((flags & RESPONSE_PASS_550) == 0, 0); ++ g_return_val_if_fail (handlers != NULL, 0); ++ g_return_val_if_fail (file != NULL, 0); ++ ++ va_start (varargs, format); ++ response = ftp_connection_sendv (conn, ++ flags | RESPONSE_PASS_550, ++ format, ++ varargs); ++ va_end (varargs); ++ if (response == 550) ++ { ++ ftp_connection_check_file (conn, handlers, file); ++ if (!ftp_connection_in_error (conn)) ++ ftp_connection_set_error_from_response (conn, response); ++ response = 0; ++ } ++ return response; ++} ++ ++static void + ftp_connection_parse_features (FtpConnection *conn) + { + struct { +@@ -1461,6 +1516,21 @@ + } + + static void ++error_550_is_directory (FtpConnection *conn, const FtpFile *file) ++{ ++ guint response = ftp_connection_send (conn, ++ RESPONSE_PASS_550, ++ "CWD %s", file); ++ ++ if (STATUS_GROUP (response) == 2) ++ { ++ g_set_error (&conn->error, G_IO_ERROR, ++ G_IO_ERROR_IS_DIRECTORY, ++ _("File is directory")); ++ } ++} ++ ++static void + do_open_for_read (GVfsBackend *backend, + GVfsJobOpenForRead *job, + const char *filename) +@@ -1468,6 +1538,7 @@ + GVfsBackendFtp *ftp = G_VFS_BACKEND_FTP (backend); + FtpConnection *conn; + FtpFile *file; ++ static const Ftp550Handler open_read_handlers[] = { error_550_is_directory, NULL }; + + conn = g_vfs_backend_ftp_pop_connection (ftp, G_VFS_JOB (job)); + if (!conn) +@@ -1476,9 +1547,11 @@ + ftp_connection_ensure_data_connection (conn); + + file = ftp_filename_from_gvfs_path (conn, filename); +- ftp_connection_send (conn, +- RESPONSE_PASS_100 | RESPONSE_FAIL_200, +- "RETR %s", file); ++ ftp_connection_send_and_check (conn, ++ RESPONSE_PASS_100 | RESPONSE_FAIL_200, ++ &open_read_handlers[0], ++ file, ++ "RETR %s", file); + g_free (file); + + if (ftp_connection_in_error (conn)) diff --git a/gvfs.spec b/gvfs.spec index 9e84bac..6b04fb5 100644 --- a/gvfs.spec +++ b/gvfs.spec @@ -1,7 +1,7 @@ Summary: Backends for the gio framework in GLib Name: gvfs Version: 0.99.1 -Release: 1%{?dist} +Release: 2%{?dist} License: LGPLv2+ Group: System Environment/Libraries URL: http://www.gtk.org @@ -37,6 +37,10 @@ BuildRequires: automake autoconf BuildRequires: libtool Patch1: gvfs-0.2.2-archive-integration.patch +# http://bugzilla.gnome.org/show_bug.cgi?id=522933 +Patch2: gvfs-ftp-read-directory-2.patch + + %description The gvfs package provides backend implementations for the gio framework in GLib. It includes ftp, sftp, cifs. @@ -65,6 +69,7 @@ to access the gvfs filesystems. %prep %setup -q %patch1 -p0 -b .archive-integration +%patch2 -p0 -b .recurse-dir %build @@ -179,6 +184,9 @@ update-desktop-database &> /dev/null ||: %changelog +* Thu Jun 12 2008 Tomas Bzatek - 0.99.1-2 +- Fix transfer of whole directories from FTP (#448560) + * Tue Jun 3 2008 Matthias Clasen - 0.99.1-1 - Update to 0.99.1