summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--paramiko/channel.py3
-rw-r--r--paramiko/sftp_attr.py19
-rw-r--r--paramiko/sftp_client.py4
-rw-r--r--paramiko/sftp_handle.py8
-rw-r--r--paramiko/sftp_server.py13
-rw-r--r--paramiko/transport.py18
6 files changed, 55 insertions, 10 deletions
diff --git a/paramiko/channel.py b/paramiko/channel.py
index 89b6e3f3..b41136c4 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 5fb45d0f..5051686f 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 '<SFTPAttributes: %s>' % 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 f4753ce9..628a9b21 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 13f7b5bf..e83f7d50 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 0b346155..e03131b3 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 4a3ab2be..5925b120 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...