From 8878a5f3c28e02796af01bab91532dd05a3624f2 Mon Sep 17 00:00:00 2001 From: Robey Pointer Date: Mon, 17 Jan 2005 10:09:09 +0000 Subject: [PATCH] [project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-140] more flexible logging some tweaks to make channels etc follow the logger setting of their parent transport, so that setting the log channel for a paramiko transport will cause all sub-logging to branch out from that channel. also, close all open file handles when the sftp server ends. --- paramiko/channel.py | 3 ++- paramiko/sftp_attr.py | 19 +++++++++++++++++++ paramiko/sftp_client.py | 4 +++- paramiko/sftp_handle.py | 8 ++++---- paramiko/sftp_server.py | 13 +++++++++++-- paramiko/transport.py | 18 ++++++++++++++++-- 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/paramiko/channel.py b/paramiko/channel.py index 89b6e3f..b41136c 100644 --- a/paramiko/channel.py +++ b/paramiko/channel.py @@ -281,7 +281,7 @@ class Channel (object): @type name: str """ self.name = name - self.logger = logging.getLogger('paramiko.chan.' + name) + self.logger = logging.getLogger(self.transport.get_log_channel() + '.' + self.name) def get_name(self): """ @@ -758,6 +758,7 @@ class Channel (object): def _set_transport(self, transport): self.transport = transport + self.logger = logging.getLogger(self.transport.get_log_channel() + '.' + self.name) def _set_window(self, window_size, max_packet_size): self.in_window_size = window_size diff --git a/paramiko/sftp_attr.py b/paramiko/sftp_attr.py index 5fb45d0..5051686 100644 --- a/paramiko/sftp_attr.py +++ b/paramiko/sftp_attr.py @@ -78,6 +78,9 @@ class SFTPAttributes (object): return attr from_stat = classmethod(from_stat) + def __repr__(self): + return '' % self._debug_str() + ### internals... @@ -138,6 +141,22 @@ class SFTPAttributes (object): msg.add_string(val) return + def _debug_str(self): + out = '[ ' + if hasattr(self, 'st_size'): + out += 'size=%d ' % self.st_size + if hasattr(self, 'st_uid') or hasattr(self, 'st_gid'): + out += 'uid=%d gid=%d ' % (getattr(self, 'st_uid', 0), getattr(self, 'st_gid', 0)) + if hasattr(self, 'st_mode'): + out += 'mode=%d ' % self.st_mode + if hasattr(self, 'st_atime') or hasattr(self, 'st_mtime'): + out += 'atime=%d mtime=%d ' % (getattr(self, 'st_atime', 0), + getattr(self, 'st_mtime', 0)) + for k, v in self.attr.iteritems(): + out += '"%s"=%s ' % (str(k), repr(v)) + out += ']' + return out + def _rwx(n, suid, sticky=False): if suid: suid = 2 diff --git a/paramiko/sftp_client.py b/paramiko/sftp_client.py index f4753ce..628a9b2 100644 --- a/paramiko/sftp_client.py +++ b/paramiko/sftp_client.py @@ -50,7 +50,9 @@ class SFTPClient (BaseSFTP): self.request_number = 1 if type(sock) is Channel: # override default logger - self.logger = logging.getLogger('paramiko.chan.' + sock.get_name() + '.sftp') + transport = self.sock.get_transport() + self.logger = logging.getLogger(transport.get_log_channel() + '.' + + self.sock.get_name() + '.sftp') self._send_version() def from_transport(selfclass, t): diff --git a/paramiko/sftp_handle.py b/paramiko/sftp_handle.py index 13f7b5b..e83f7d5 100644 --- a/paramiko/sftp_handle.py +++ b/paramiko/sftp_handle.py @@ -29,9 +29,9 @@ from sftp import * class SFTPHandle (object): """ - Abstract object representing a handle to an open file (or folder) on - the server. Each handle has a string representation used by the client - to refer to the underlying file. + Abstract object representing a handle to an open file (or folder) in an + SFTP server implementation. Each handle has a string representation used + by the client to refer to the underlying file. Server implementations can (and should) subclass SFTPHandle to implement features of a file handle, like L{stat} or L{chattr}. @@ -138,7 +138,7 @@ class SFTPHandle (object): it's called on an open file instead of a path. @return: an attributes object for the given file, or an SFTP error - code (like L{SFTP_PERMISSION_DENIED}). + code (like L{SFTP_PERMISSION_DENIED}). @rtype: L{SFTPAttributes} I{or error code} """ return SFTP_OP_UNSUPPORTED diff --git a/paramiko/sftp_server.py b/paramiko/sftp_server.py index 0b34615..e03131b 100644 --- a/paramiko/sftp_server.py +++ b/paramiko/sftp_server.py @@ -58,7 +58,9 @@ class SFTPServer (BaseSFTP, SubsystemHandler): BaseSFTP.__init__(self) SubsystemHandler.__init__(self, channel, name) self.ultra_debug = True - self.logger = logging.getLogger('paramiko.chan.' + channel.get_name() + '.sftp') + transport = channel.get_transport() + self.logger = logging.getLogger(transport.get_log_channel() + '.' + + channel.get_name() + '.sftp') self.next_handle = 1 # map of handle-string to SFTPHandle for files & folders: self.file_table = { } @@ -88,6 +90,13 @@ class SFTPServer (BaseSFTP, SubsystemHandler): def finish_subsystem(self): self.server.session_ended() + # close any file handles that were left open (so we can return them to the OS quickly) + for f in self.file_table.itervalues(): + f.close() + for f in self.folder_table.itervalues(): + f.close() + self.file_table = {} + self.folder_table = {} def convert_errno(e): """ @@ -121,7 +130,7 @@ class SFTPServer (BaseSFTP, SubsystemHandler): requests into local file operations. @param filename: name of the file to alter (should usually be an - absolute path). + absolute path). @type filename: str @param attr: attributes to change. @type attr: L{SFTPAttributes} diff --git a/paramiko/transport.py b/paramiko/transport.py index 4a3ab2b..5925b12 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -237,12 +237,13 @@ class BaseTransport (threading.Thread): self.channels = { } # (id -> Channel) self.channel_events = { } # (id -> Event) self.channel_counter = 1 - self.logger = logging.getLogger('paramiko.transport') self.window_size = 65536 self.max_packet_size = 32768 self.ultra_debug = False self.saved_exception = None self.clear_to_send = threading.Event() + self.log_name = 'paramiko.transport' + self.logger = logging.getLogger(self.log_name) # used for noticing when to re-key: self.received_bytes = 0 self.received_packets = 0 @@ -783,15 +784,28 @@ class BaseTransport (threading.Thread): """ Set the channel for this transport's logging. The default is C{"paramiko.transport"} but it can be set to anything you want. - (See the C{logging} module for more info.) + (See the C{logging} module for more info.) SSH Channels will log + to a sub-channel of the one specified. @param name: new channel name for logging. @type name: str @since: 1.1 """ + self.log_name = name self.logger = logging.getLogger(name) + def get_log_channel(self): + """ + Return the channel name used for this transport's logging. + + @return: channel name. + @rtype: str + + @since: 1.2 + """ + return self.log_name + ### internals...