After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 522933 - copying or deleting a directory leads to a file not available error
copying or deleting a directory leads to a file not available error
Status: RESOLVED FIXED
Product: gvfs
Classification: Core
Component: ftp backend
git master
Other Linux
: Normal normal
: ---
Assigned To: Tomas Bzatek
gvfs-maint
: 524421 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2008-03-17 11:45 UTC by Sebastien Bacher
Modified: 2008-06-11 11:53 UTC
See Also:
GNOME target: ---
GNOME version: 2.21/2.22


Attachments
gvfs-ftp-read-directory.patch (11.79 KB, patch)
2008-05-30 15:28 UTC, Tomas Bzatek
none Details | Review
gvfs-ftp-read-directory-2.patch (4.67 KB, patch)
2008-06-10 13:51 UTC, Tomas Bzatek
none Details | Review

Description Sebastien Bacher 2008-03-17 11:45:56 UTC
Using the current gvfs svn and nautilus 2.22.0, when doing a dnd from a directory on a proftpd server nautilus returns a file not available error. It does the same when trying to delete the directory. Copying the same directory using mirror in lftp works correctly
Comment 1 WladyX 2008-04-08 16:15:31 UTC
i get this too.
Comment 2 Martin Jürgens 2008-05-27 16:53:18 UTC
yup me too
Comment 3 Justin Haygood 2008-05-27 19:04:15 UTC
*** Bug 524421 has been marked as a duplicate of this bug. ***
Comment 4 Hans Petter Jansson 2008-05-27 21:52:16 UTC
We're getting this in openSUSE too, and it seems to happen with all kinds of FTP servers.
Comment 5 Hans Petter Jansson 2008-05-27 21:52:40 UTC
The openSUES bug is

https://bugzilla.novell.com/show_bug.cgi?id=382360
Comment 6 Tomas Bzatek 2008-05-28 16:04:30 UTC
This is caused by broken backends. Any attempts to open or copy/move a directory should fail with G_IO_ERROR_IS_DIRECTORY. GIO functions and Nautilus rely on that.

Fix for gvfs-smb is now in trunk and gnome-2-22 branch. Working on FTP fix right now.
Comment 7 Tomas Bzatek 2008-05-30 15:28:33 UTC
Created attachment 111807 [details] [review]
gvfs-ftp-read-directory.patch

Proposed patch. Introducing new system of handling error 550 messages based on Benjamin's idea. So far only simple check if the target is directory has been implemented.

Please review the patch, I especially don't like keeping references to GVfsBackendFtp and processed file in the FtpConnection object but it is the easiest way to do it.
Comment 8 Benjamin Otte (Company) 2008-06-02 09:32:20 UTC
The patch gets the gist of what I want, but it looks ugly in places. Here's what I think on how to solve those:

My idea was that the error handlers should be implemented with simple ftp_connection_send() commands, that set errors automatically. So the is_directory handler would look something like this:
static void
error_550_is_directory (FtpConnection *conn, const FtpFile *file)
{
  guint response = ftp_connection_send (conn, 
                                        RESPONSE_PASS_500,
                                        "cwd %s", file);
  if (response == 550)
    {
      g_set_error (&conn->error, G_IO_ERROR, 
                   G_IO_ERROR_IS_DIRECTORY,
                   _("File is a directory"));
    }
  else if (STATUS_GROUP (response) == 5)
    {
      ftp_connection_set_error_from_response (conn, response);
    }
}
So we'd have a bunch of error handlers named error_550_$ERROR_WE_CHECK() like error_550_not_found or error_550_permission_denied that do some ftp sending magic to figure out specific things.

While writing the above code, it occured to me that we might want to have a new flag "RESPONSE_PASS_550" just for the 550 error code, which would help in quite some cases and make the above function look like this:
static void
error_550_check_directory (FtpConnection *conn, const FtpFile *file)
{
  guint response = ftp_connection_send (conn, 
                                        RESPONSE_PASS_550,
                                        "cwd %s", file);
  if (response == 550)
    {
      g_set_error (&conn->error, G_IO_ERROR, 
                   G_IO_ERROR_IS_DIRECTORY,
                   _("File is a directory"));
    }
}

I also think that we want a seperate ftp_connection_send_and_check function, that does the job of doing special 550 checks, as there's a lot of cases where those aren't needed. The code would roughly look like this:
typedef void (* Ftp550Handler) (FtpConnection *conn, const FtpFile *file);
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)
{
  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 & | == 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);
      response = 0;
    }
  return response;
}

This also solves the problem of having our 550 handling move into the response codes, which looks a bit unfortunate API wise.

And we get rid of adding more members to the FtpConnection struct, especially those that don't belong there.

Some smaller things:
- The function was called "error_550_check_directory". That's a somewhat bad choice for a name, as I don't know if it checks whether the file is or is not a directory.
- Please change the default error code for 550 to G_IO_ERROR_FAILED. "Operation failed" sounds much better than "File unavailable". And it tells us where we miss 550 checks: Whenever we get "FAILED" :)
- Your patch includes the "LIST -a" change for bad directory listings.
Comment 9 Tomas Bzatek 2008-06-10 13:51:58 UTC
Created attachment 112474 [details] [review]
gvfs-ftp-read-directory-2.patch

Modified patch, fixing all issues noted in the previous comment.
Comment 10 Benjamin Otte (Company) 2008-06-10 17:12:54 UTC
From a quick review the patch looks pretty much like I imagined it. And before I forget it: error_550_is_directory() checks for 250, not 550.
Comment 11 Tomas Bzatek 2008-06-11 11:53:26 UTC
Commited slightly modified patch to trunk and stable 2.22 branch. This fixes recursive copy of directory structure in Nautilus.

The delete issue reported in the first post might be related to bug #528347, where client apps using GIO/GVFS are unable see dot-files which are blocking directory removal as it's not empty. Otherwise deleting whole directory structure works fine in Nautilus and backend reports G_IO_ERROR_NOT_EMPTY correctly.