diff options
-rw-r--r-- | paramiko/sftp.py | 18 | ||||
-rw-r--r-- | paramiko/transport.py | 16 |
2 files changed, 25 insertions, 9 deletions
diff --git a/paramiko/sftp.py b/paramiko/sftp.py index 0e7f48f7..d5948ed9 100644 --- a/paramiko/sftp.py +++ b/paramiko/sftp.py @@ -15,7 +15,7 @@ # details. # # You should have received a copy of the GNU Lesser General Public License -# along with Foobar; if not, write to the Free Software Foundation, Inc., +# along with Paramiko; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. import struct, socket @@ -121,6 +121,11 @@ class SFTPError (Exception): class SFTPFile (BufferedFile): + + # some sftp servers will choke if you send read/write requests larger than + # this size. + MAX_REQUEST_SIZE = 32768 + def __init__(self, sftp, handle, mode='r', bufsize=-1): BufferedFile.__init__(self) self.sftp = sftp @@ -143,16 +148,23 @@ class SFTPFile (BufferedFile): self.sftp._request(CMD_CLOSE, self.handle) def _read(self, size): + size = min(size, self.MAX_REQUEST_SIZE) t, msg = self.sftp._request(CMD_READ, self.handle, long(self._realpos), int(size)) if t != CMD_DATA: raise SFTPError('Expected data') return msg.get_string() def _write(self, data): - t, msg = self.sftp._request(CMD_WRITE, self.handle, long(self._realpos), str(data)) + offset = 0 + while offset < len(data): + chunk = min(len(data) - offset, self.MAX_REQUEST_SIZE) + t, msg = self.sftp._request(CMD_WRITE, self.handle, long(self._realpos + offset), + str(data[offset : offset + chunk])) + offset += chunk return len(data) def seek(self, offset, whence=0): + self.flush() if whence == self.SEEK_SET: self._realpos = self._pos = offset elif whence == self.SEEK_CUR: @@ -160,7 +172,7 @@ class SFTPFile (BufferedFile): self._pos += offset else: self._realpos = self._pos = self._get_size() + offset - self._rbuffer = self._wbuffer = '' + self._rbuffer = '' def stat(self): """ diff --git a/paramiko/transport.py b/paramiko/transport.py index ac3560cd..06f75801 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -15,7 +15,7 @@ # details. # # You should have received a copy of the GNU Lesser General Public License -# along with Foobar; if not, write to the Free Software Foundation, Inc., +# along with Paramiko; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. """ @@ -162,8 +162,8 @@ class BaseTransport (threading.Thread): self.channel_counter = 1 self.logger = logging.getLogger('paramiko.transport') self.window_size = 65536 - self.max_packet_size = 8192 - self.ultra_debug = 0 + self.max_packet_size = 32768 + self.ultra_debug = False self.saved_exception = None # used for noticing when to re-key: self.received_bytes = 0 @@ -792,7 +792,9 @@ class BaseTransport (threading.Thread): def _send_message(self, data): # FIXME: should we check for rekeying here too? # encrypt this sucka - packet = self._build_packet(str(data)) + data = str(data) + self._log(DEBUG, 'Write packet $%x, length %d' % (ord(data[0]), len(data))) + packet = self._build_packet(data) if self.ultra_debug: self._log(DEBUG, util.format_binary(packet, 'OUT: ')) if self.engine_out != None: @@ -861,8 +863,10 @@ class BaseTransport (threading.Thread): self.received_packets_overflow += 1 if self.received_packets_overflow >= 20: raise SSHException('Remote transport is ignoring rekey requests') - - return ord(payload[0]), msg + + cmd = ord(payload[0]) + self._log(DEBUG, 'Read packet $%x, length %d' % (cmd, len(payload))) + return cmd, msg def _set_K_H(self, k, h): "used by a kex object to set the K (root key) and H (exchange hash)" |