diff options
author | btimby <btimby@67cdc799-7952-0410-af00-57a81ceafa0f> | 2012-10-18 03:03:25 +0000 |
---|---|---|
committer | btimby <btimby@67cdc799-7952-0410-af00-57a81ceafa0f> | 2012-10-18 03:03:25 +0000 |
commit | bb1702175c94ce3d3fc37f3666629b282c1e09d5 (patch) | |
tree | 54e91c773eabe2ba3904a50aafed4f81ae450689 /fs/expose | |
parent | 33160ed406688ee3ec74d23958d20158b2dc6826 (diff) | |
download | pyfilesystem-git-bb1702175c94ce3d3fc37f3666629b282c1e09d5.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.
Diffstat (limited to 'fs/expose')
-rw-r--r-- | fs/expose/ftp.py | 21 | ||||
-rw-r--r-- | fs/expose/sftp.py | 34 |
2 files changed, 53 insertions, 2 deletions
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): |