Commit 1d6b1906 by willmcgugan@gmail.com

Added option to folllow symlinks to ftpfs, patch from Andrew

parent 7efa4873
...@@ -337,6 +337,7 @@ class FTPListDataParser(object): ...@@ -337,6 +337,7 @@ class FTPListDataParser(object):
i = 0 i = 0
while (i + 3) < len(result.name): while (i + 3) < len(result.name):
if result.name[i:i+4] == ' -> ': if result.name[i:i+4] == ' -> ':
result.target = result.name[i+4:]
result.name = result.name[:i] result.name = result.name[:i]
break break
i += 1 i += 1
...@@ -891,7 +892,7 @@ class FTPFS(FS): ...@@ -891,7 +892,7 @@ class FTPFS(FS):
'file.read_and_write' : False, 'file.read_and_write' : False,
} }
def __init__(self, host='', user='', passwd='', acct='', timeout=_GLOBAL_DEFAULT_TIMEOUT, port=21, dircache=True): def __init__(self, host='', user='', passwd='', acct='', timeout=_GLOBAL_DEFAULT_TIMEOUT, port=21, dircache=True, follow_symlinks=False):
"""Connect to a FTP server. """Connect to a FTP server.
:param host: Host to connect to :param host: Host to connect to
...@@ -917,6 +918,7 @@ class FTPFS(FS): ...@@ -917,6 +918,7 @@ class FTPFS(FS):
self.timeout = timeout self.timeout = timeout
self.default_timeout = timeout is _GLOBAL_DEFAULT_TIMEOUT self.default_timeout = timeout is _GLOBAL_DEFAULT_TIMEOUT
self.use_dircache = dircache self.use_dircache = dircache
self.follow_symlinks = follow_symlinks
self.use_mlst = False self.use_mlst = False
self._lock = threading.RLock() self._lock = threading.RLock()
...@@ -1018,6 +1020,30 @@ class FTPFS(FS): ...@@ -1018,6 +1020,30 @@ class FTPFS(FS):
pass pass
self.dircache[path] = dirlist self.dircache[path] = dirlist
def is_symlink(info):
return info['try_retr'] and info['try_cwd'] and info.has_key('target')
def resolve_symlink(linkpath):
linkinfo = self.getinfo(linkpath)
if not linkinfo.has_key('resolved'):
linkinfo['resolved'] = linkpath
if is_symlink(linkinfo):
target = linkinfo['target']
base, fname = pathsplit(linkpath)
return resolve_symlink(pathjoin(base, target))
else:
return linkinfo
if self.follow_symlinks:
for name in dirlist:
if is_symlink(dirlist[name]):
target = dirlist[name]['target']
linkinfo = resolve_symlink(pathjoin(path, target))
for key in linkinfo:
if key != 'name':
dirlist[name][key] = linkinfo[key]
del dirlist[name]['target']
return dirlist return dirlist
@synchronize @synchronize
......
...@@ -434,7 +434,7 @@ examples: ...@@ -434,7 +434,7 @@ examples:
dirpath, resourcepath = pathsplit(path) dirpath, resourcepath = pathsplit(path)
url = netloc url = netloc
ftpfs = FTPFS(url, user=username or '', passwd=password or '') ftpfs = FTPFS(url, user=username or '', passwd=password or '', follow_symlinks=(fs_name_params == "symlinks"))
ftpfs.cache_hint(True) ftpfs.cache_hint(True)
if create_dir and path: if create_dir and path:
......
...@@ -16,7 +16,9 @@ from six import PY3 ...@@ -16,7 +16,9 @@ from six import PY3
try: try:
from pyftpdlib import ftpserver from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer
except ImportError: except ImportError:
if not PY3: if not PY3:
raise ImportError("Requires pyftpdlib <http://code.google.com/p/pyftpdlib/>") raise ImportError("Requires pyftpdlib <http://code.google.com/p/pyftpdlib/>")
...@@ -89,21 +91,21 @@ if __name__ == "__main__": ...@@ -89,21 +91,21 @@ if __name__ == "__main__":
# Run an ftp server that exposes a given directory # Run an ftp server that exposes a given directory
import sys import sys
authorizer = ftpserver.DummyAuthorizer() authorizer = DummyAuthorizer()
authorizer.add_user("user", "12345", sys.argv[1], perm="elradfmw") authorizer.add_user("user", "12345", sys.argv[1], perm="elradfmw")
authorizer.add_anonymous(sys.argv[1]) authorizer.add_anonymous(sys.argv[1])
def nolog(*args): #def nolog(*args):
pass # pass
ftpserver.log = nolog #ftpserver.log = nolog
ftpserver.logline = nolog #ftpserver.logline = nolog
handler = ftpserver.FTPHandler handler = FTPHandler
handler.authorizer = authorizer handler.authorizer = authorizer
address = ("127.0.0.1", int(sys.argv[2])) address = ("127.0.0.1", int(sys.argv[2]))
#print address #print address
ftpd = ftpserver.FTPServer(address, handler) ftpd = FTPServer(address, handler)
sys.stdout.write('serving\n') sys.stdout.write('serving\n')
sys.stdout.flush() sys.stdout.flush()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment