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



Hello,

Hello, here comes the second part of the patch. This one is aimed to fix
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=258253.

The routines `vfs_s_find_entry_linear()' and `vfs_s_find_entry_tree()'
call `canonicalize_pathname()' on entry. This routine eats `..' path
components in certain cases. In case of ftpfs this is not desired -
the path should be kept as is since the code in direntry.c doesn't have
enough knowledge of the directory structure on the remote end. Assume that
there is a path like this on the remote server

  /path1/path2/path3

The `path2' component is a symlink to some directory and `path3' is a
symlink stored in `path2' which is relative to `path2' i.e.

  path2

        path3 -> ../some/other/path

Now, the code in direntry.c will determine that `path3' is a symlink and
will try to resolve (vfs_s_resolve_symlink) it by passing the following
path

  /path1/path2/../some/other/path

to `vfs_s_find_entry_linear' . As I've said above this routine calls
`canonicalize_pathname' on entry which will modify the path like this:

  /path1/some/other/path

Now this is clearly wrong since `path2' is a symlink and it should be
resolved first. In the case of ftpfs the code in direntry.c doesn't have
enough knowledge about physycal directory layout on the remote filesystem
so it shouldn't try to canonicalize the path. The path should be left as
is and passed to the remote end for processing.

This patch together with the previous one allow all symlinks on
ftp.uni-erlangen.de to be resolved properly. The only symlink entries that
you will see colored in red (i.e. bad) are only the really dead symlinks.
Index: vfs/direntry.c
===================================================================
RCS file: /cvsroot/mc/mc/vfs/direntry.c,v
retrieving revision 1.116
diff -u -p -r1.116 direntry.c
--- vfs/direntry.c	22 Feb 2005 18:35:23 -0000	1.116
+++ vfs/direntry.c	6 Apr 2005 14:04:54 -0000
@@ -251,7 +251,13 @@ vfs_s_find_entry_tree (struct vfs_class 
     char * const pathref = g_strdup (a_path);
     char *path = pathref;
 
-    canonicalize_pathname (path);
+    if (strncmp(me->name, "ftpfs", 5) != 0)
+	canonicalize_pathname (path);
+    else {
+	char *p = path + strlen (path) - 1;
+	while (p > path && *p == PATH_SEP)
+	    *p-- = 0;
+    }
 
     while (root) {
 	while (*path == PATH_SEP)	/* Strip leading '/' */
@@ -324,7 +330,13 @@ vfs_s_find_entry_linear (struct vfs_clas
     if (root->super->root != root)
 	vfs_die ("We have to use _real_ root. Always. Sorry.");
 
-    canonicalize_pathname (path);
+    if (strncmp (me->name, "ftpfs", 5) != 0)
+	canonicalize_pathname (path);
+    else {
+	char *p = path + strlen (path) - 1;
+	while (p > path && *p == PATH_SEP)
+	    *p-- = 0;
+    }
 
     if (!(flags & FL_DIR)) {
 	char *dirname, *name, *save;


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