[PATCH]: Improve symlink handling in ftpfs - Part 1


This is the first part of a patch which will greatly improve handling of
symlinks on ftp servers. This change is pretty simple - it just makes the
more robust method, for listing the contents of a directory, the default.
This method is currently disabled  - I assume this is done to save the
processing of an extra command (CWD). Although it is possible to enable it
by manually editing ~/.mc/ini and changing the value of the
`ftpfs_first_cd_then_ls' option, this option is not documented and it
would be quite hard for the end user to benefit from it. Having said the
above I vote for this change in behaviour which would cost the overhead of
an  extra command but it will give the end user better handling of symlinks
to directories.

Now, what's wrong with the current default method i.e. LIST /some/path
instead of CWD /some/path followed by LIST:

[ptsekov baba-meca build]$ ftp ftp.chg.ru
Connected to ftp.chg.ru (
220 ChgNet FTP server ready.
Name (ftp.chg.ru:ptsekov): anonymous
331 Guest login ok, send your complete e-mail address as password.
230-    Welcome to FTP.Chg.RU - the biggest Russian ftp-archive
230 Guest login ok, access restrictions apply
Remote system type is UNIX.
Using binary mode to transfer files.

  So here is this particular link of interest:

ftp> ls
227 Entering Passive Mode (193,233,9,194,232,120)
150 Opening ASCII mode data connection for /bin/ls.
total 60060
lrwxr-xr-x   1 0    wheel        17 Mar  4  2003 debian -> /pub/Linux/debian
226 Transfer complete.

  When loading a directory MC would call `mc_stat()' on entries which
  appear to be symlinks - note that `mc_stat' implies that information
  which is retrieved is for the target of the symlink and not the symlink
  itself. In the case of ftpfs this would result first in a call to
  `vfs_s_find_entry_linear()' with and argument of `/pub/Linux' and
  if that succeeds, a call will me made to `vfs_s_find_entry_tree()' with
  an argument of `debian'. `vfs_s_find_entry_linear()' will load the
  directory entries for the given path and `vfs_s_find_entry_linear()'
  will see if the last component is a file, a directory or maybe a
  symlink by comparing it to the entries loaded by `vfs_s_find_entry_linear()'.
  Now with the current default method of getting the contents of a
  directory the following command will be issued:

ftp> ls /pub/Linux/.
227 Entering Passive Mode (193,233,9,194,254,139)
150 Opening ASCII mode data connection for /bin/ls.
lrwxr-xr-x  1 0  wheel  11 Nov 20 16:54 /pub/Linux -> ../.1/Linux
226 Transfer complete.

  As you see this is not what one would expect. It turns out that the
  entry `Linux' inside `pub' is a symlink. Now many ftp server will just
  resolve it and return the contents of the target directory, but not this
  particular one. There are other cases which will fail too - I can post
  if required. Now if use switch the default method to the one that I
  propose. Two commands will be issued but the directory listing will be
  retrieved correctly:

ftp> cd /pub/Linux
250 CWD command successful.
ftp> ls
227 Entering Passive Mode (193,233,9,194,185,91)
150 Opening ASCII mode data connection for /bin/ls.
total 118
drwxrwxr-x    8 3000   3000    512 Apr  6 02:40 debian

Now on this particular there is a way to go without even with the LIST
method only - you have to turn off `ftpfs_use_unix_list_options' in you
~/.mc/ini but this doesn't work everywhere. I think that the only
plausible solution is to use the CWD + LIST commands.

There is another patch for ftpfs coming but I have to polish it first. It
fixes http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=258253. Andrew, if
you are reading the list - please comment.
Index: vfs/ftpfs.c
RCS file: /cvsroot/mc/mc/vfs/ftpfs.c,v
retrieving revision 1.176
diff -u -p -r1.176 ftpfs.c
--- vfs/ftpfs.c	22 Feb 2005 18:35:23 -0000	1.176
+++ vfs/ftpfs.c	5 Apr 2005 18:13:23 -0000
@@ -117,7 +117,7 @@ int ftpfs_use_passive_connections = 1;
 int ftpfs_use_unix_list_options = 1;
 /* First "CWD <path>", then "LIST -la ." */
-int ftpfs_first_cd_then_ls;
+int ftpfs_first_cd_then_ls = 1;
 /* Use the ~/.netrc */
 int use_netrc = 1;

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]