summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbtimby <btimby@67cdc799-7952-0410-af00-57a81ceafa0f>2012-10-18 03:03:25 +0000
committerbtimby <btimby@67cdc799-7952-0410-af00-57a81ceafa0f>2012-10-18 03:03:25 +0000
commitb4e858df0e66579d1bf298e53dc13b00fa3bf90e (patch)
tree54e91c773eabe2ba3904a50aafed4f81ae450689
parentd913814dd969892f2e3025f160fe4e488b3a98b5 (diff)
downloadpyfilesystem-b4e858df0e66579d1bf298e53dc13b00fa3bf90e.tar.gz
Be less heavy-handed, setting the reference to None will do.
Ensure that pyfs file systems are closed when use with ftp and sftp daemons. git-svn-id: http://pyfilesystem.googlecode.com/svn/trunk@824 67cdc799-7952-0410-af00-57a81ceafa0f
-rw-r--r--fs/contrib/archivefs.py2
-rw-r--r--fs/expose/ftp.py21
-rw-r--r--fs/expose/sftp.py34
3 files changed, 54 insertions, 3 deletions
diff --git a/fs/contrib/archivefs.py b/fs/contrib/archivefs.py
index 780f1bb..cb3b4af 100644
--- a/fs/contrib/archivefs.py
+++ b/fs/contrib/archivefs.py
@@ -187,7 +187,7 @@ class ArchiveMountFS(mountfs.MountFS):
def close(self):
# Close and delete references to any other fs instances.
self.rootfs.close()
- del self.rootfs
+ self.rootfs = None
super(ArchiveMountFS, self).close()
def ismount(self, path):
diff --git a/fs/expose/ftp.py b/fs/expose/ftp.py
index 55f9ce5..b2dcb42 100644
--- a/fs/expose/ftp.py
+++ b/fs/expose/ftp.py
@@ -78,6 +78,12 @@ class FTPFS(ftpserver.AbstractedFS):
self.encoding = encoding
super(FTPFS, self).__init__(root, cmd_channel)
+ def close(self):
+ # Close and dereference the pyfs file system.
+ if self.fs:
+ self.fs.close()
+ self.fs = None
+
def validpath(self, path):
try:
normpath(path)
@@ -207,6 +213,19 @@ class FTPFS(ftpserver.AbstractedFS):
return True
+class FTPFSHandler(ftpserver.FTPHandler):
+ """
+ An FTPHandler class that closes the filesystem when done.
+ """
+
+ def close(self):
+ # Close the FTPFS instance, it will close the pyfs file system.
+ if self.fs:
+ self.fs.close()
+ super(FTPFSHandler, self).close()
+
+
+
class FTPFSFactory(object):
"""
A factory class which can hold a reference to a file system object and
@@ -247,7 +266,7 @@ def serve_fs(fs, addr, port):
combo.
"""
from pyftpdlib.contrib.authorizers import UnixAuthorizer
- ftp_handler = ftpserver.FTPHandler
+ ftp_handler = FTPFSHandler
ftp_handler.authorizer = ftpserver.DummyAuthorizer()
ftp_handler.authorizer.add_anonymous('/')
ftp_handler.abstracted_fs = FTPFSFactory(fs)
diff --git a/fs/expose/sftp.py b/fs/expose/sftp.py
index 7abd359..bd05fcb 100644
--- a/fs/expose/sftp.py
+++ b/fs/expose/sftp.py
@@ -103,6 +103,11 @@ class SFTPServerInterface(paramiko.SFTPServerInterface):
self.encoding = encoding
super(SFTPServerInterface,self).__init__(server, *args, **kwds)
+ def close(self):
+ # Close the pyfs file system and dereference it.
+ self.fs.close()
+ self.fs = None
+
@report_sftp_errors
def open(self, path, flags, attr):
return SFTPHandle(self, path, flags)
@@ -247,6 +252,17 @@ class SFTPHandle(paramiko.SFTPHandle):
return self.owner.chattr(self.path, attr)
+class SFTPServer(paramiko.SFTPServer):
+ """
+ An SFTPServer class that closes the filesystem when done.
+ """
+
+ def finish_subsystem(self):
+ # Close the SFTPServerInterface, it will close the pyfs file system.
+ self.server.close()
+ super(SFTPServer, self).finish_subsystem()
+
+
class SFTPRequestHandler(SocketServer.BaseRequestHandler):
"""SocketServer RequestHandler subclass for BaseSFTPServer.
@@ -254,6 +270,9 @@ class SFTPRequestHandler(SocketServer.BaseRequestHandler):
sftp subsystem, and hands off to the transport's own request handling
thread.
"""
+ timeout = 60
+ auth_timeout = 60
+
def setup(self):
"""
Creates the SSH transport. Sets security options.
@@ -264,13 +283,26 @@ class SFTPRequestHandler(SocketServer.BaseRequestHandler):
so.digests = ('hmac-sha1', )
so.compression = ('zlib@openssh.com', 'none')
self.transport.add_server_key(self.server.host_key)
- self.transport.set_subsystem_handler("sftp", paramiko.SFTPServer, SFTPServerInterface, self.server.fs, encoding=self.server.encoding)
+ self.transport.set_subsystem_handler("sftp", SFTPServer, SFTPServerInterface, self.server.fs, encoding=self.server.encoding)
def handle(self):
"""
Start the paramiko server, this will start a thread to handle the connection.
"""
self.transport.start_server(server=BaseServerInterface())
+ # TODO: I like the code below _in theory_ but it does not work as I expected.
+ # Figure out how to actually time out a new client if they fail to auth in a
+ # certain amount of time.
+ #chan = self.transport.accept(self.auth_timeout)
+ #if chan is None:
+ # self.transport.close()
+
+ def handle_timeout(self):
+ try:
+ self.transport.close()
+ finally:
+ super(SFTPRequestHandler, self).handle_timeout()
+
class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):