Package paramiko :: Module sftp
[frames] | no frames]

Source Code for Module paramiko.sftp

  1  # Copyright (C) 2003-2007  Robey Pointer <robeypointer@gmail.com> 
  2  # 
  3  # This file is part of paramiko. 
  4  # 
  5  # Paramiko is free software; you can redistribute it and/or modify it under the 
  6  # terms of the GNU Lesser General Public License as published by the Free 
  7  # Software Foundation; either version 2.1 of the License, or (at your option) 
  8  # any later version. 
  9  # 
 10  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY 
 11  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
 12  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more 
 13  # details. 
 14  # 
 15  # You should have received a copy of the GNU Lesser General Public License 
 16  # along with Paramiko; if not, write to the Free Software Foundation, Inc., 
 17  # 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. 
 18   
 19  import select 
 20  import socket 
 21  import struct 
 22   
 23  from paramiko.common import * 
 24  from paramiko import util 
 25  from paramiko.channel import Channel 
 26  from paramiko.message import Message 
 27   
 28   
 29  CMD_INIT, CMD_VERSION, CMD_OPEN, CMD_CLOSE, CMD_READ, CMD_WRITE, CMD_LSTAT, CMD_FSTAT, \ 
 30             CMD_SETSTAT, CMD_FSETSTAT, CMD_OPENDIR, CMD_READDIR, CMD_REMOVE, CMD_MKDIR, \ 
 31             CMD_RMDIR, CMD_REALPATH, CMD_STAT, CMD_RENAME, CMD_READLINK, CMD_SYMLINK \ 
 32             = range(1, 21) 
 33  CMD_STATUS, CMD_HANDLE, CMD_DATA, CMD_NAME, CMD_ATTRS = range(101, 106) 
 34  CMD_EXTENDED, CMD_EXTENDED_REPLY = range(200, 202) 
 35   
 36  SFTP_OK = 0 
 37  SFTP_EOF, SFTP_NO_SUCH_FILE, SFTP_PERMISSION_DENIED, SFTP_FAILURE, SFTP_BAD_MESSAGE, \ 
 38           SFTP_NO_CONNECTION, SFTP_CONNECTION_LOST, SFTP_OP_UNSUPPORTED = range(1, 9) 
 39   
 40  SFTP_DESC = [ 'Success', 
 41                'End of file', 
 42                'No such file', 
 43                'Permission denied', 
 44                'Failure', 
 45                'Bad message', 
 46                'No connection', 
 47                'Connection lost', 
 48                'Operation unsupported' ] 
 49   
 50  SFTP_FLAG_READ = 0x1 
 51  SFTP_FLAG_WRITE = 0x2 
 52  SFTP_FLAG_APPEND = 0x4 
 53  SFTP_FLAG_CREATE = 0x8 
 54  SFTP_FLAG_TRUNC = 0x10 
 55  SFTP_FLAG_EXCL = 0x20 
 56   
 57  _VERSION = 3 
 58   
 59   
 60  # for debugging 
 61  CMD_NAMES = { 
 62      CMD_INIT: 'init', 
 63      CMD_VERSION: 'version', 
 64      CMD_OPEN: 'open', 
 65      CMD_CLOSE: 'close', 
 66      CMD_READ: 'read', 
 67      CMD_WRITE: 'write', 
 68      CMD_LSTAT: 'lstat', 
 69      CMD_FSTAT: 'fstat', 
 70      CMD_SETSTAT: 'setstat', 
 71      CMD_FSETSTAT: 'fsetstat', 
 72      CMD_OPENDIR: 'opendir', 
 73      CMD_READDIR: 'readdir', 
 74      CMD_REMOVE: 'remove', 
 75      CMD_MKDIR: 'mkdir', 
 76      CMD_RMDIR: 'rmdir', 
 77      CMD_REALPATH: 'realpath', 
 78      CMD_STAT: 'stat', 
 79      CMD_RENAME: 'rename', 
 80      CMD_READLINK: 'readlink', 
 81      CMD_SYMLINK: 'symlink', 
 82      CMD_STATUS: 'status', 
 83      CMD_HANDLE: 'handle', 
 84      CMD_DATA: 'data', 
 85      CMD_NAME: 'name', 
 86      CMD_ATTRS: 'attrs', 
 87      CMD_EXTENDED: 'extended', 
 88      CMD_EXTENDED_REPLY: 'extended_reply' 
 89      } 
 90   
 91   
92 -class SFTPError (Exception):
93 pass
94 95
96 -class BaseSFTP (object):
97 - def __init__(self):
98 self.logger = util.get_logger('paramiko.sftp') 99 self.sock = None 100 self.ultra_debug = False
101 102 103 ### internals... 104 105
106 - def _send_version(self):
107 self._send_packet(CMD_INIT, struct.pack('>I', _VERSION)) 108 t, data = self._read_packet() 109 if t != CMD_VERSION: 110 raise SFTPError('Incompatible sftp protocol') 111 version = struct.unpack('>I', data[:4])[0] 112 # if version != _VERSION: 113 # raise SFTPError('Incompatible sftp protocol') 114 return version
115
116 - def _send_server_version(self):
117 # winscp will freak out if the server sends version info before the 118 # client finishes sending INIT. 119 t, data = self._read_packet() 120 if t != CMD_INIT: 121 raise SFTPError('Incompatible sftp protocol') 122 version = struct.unpack('>I', data[:4])[0] 123 # advertise that we support "check-file" 124 extension_pairs = [ 'check-file', 'md5,sha1' ] 125 msg = Message() 126 msg.add_int(_VERSION) 127 msg.add(*extension_pairs) 128 self._send_packet(CMD_VERSION, str(msg)) 129 return version
130
131 - def _log(self, level, msg, *args):
132 self.logger.log(level, msg, *args)
133
134 - def _write_all(self, out):
135 while len(out) > 0: 136 n = self.sock.send(out) 137 if n <= 0: 138 raise EOFError() 139 if n == len(out): 140 return 141 out = out[n:] 142 return
143
144 - def _read_all(self, n):
145 out = '' 146 while n > 0: 147 if isinstance(self.sock, socket.socket): 148 # sometimes sftp is used directly over a socket instead of 149 # through a paramiko channel. in this case, check periodically 150 # if the socket is closed. (for some reason, recv() won't ever 151 # return or raise an exception, but calling select on a closed 152 # socket will.) 153 while True: 154 read, write, err = select.select([ self.sock ], [], [], 0.1) 155 if len(read) > 0: 156 x = self.sock.recv(n) 157 break 158 else: 159 x = self.sock.recv(n) 160 161 if len(x) == 0: 162 raise EOFError() 163 out += x 164 n -= len(x) 165 return out
166
167 - def _send_packet(self, t, packet):
168 #self._log(DEBUG2, 'write: %s (len=%d)' % (CMD_NAMES.get(t, '0x%02x' % t), len(packet))) 169 out = struct.pack('>I', len(packet) + 1) + chr(t) + packet 170 if self.ultra_debug: 171 self._log(DEBUG, util.format_binary(out, 'OUT: ')) 172 self._write_all(out)
173
174 - def _read_packet(self):
175 x = self._read_all(4) 176 # most sftp servers won't accept packets larger than about 32k, so 177 # anything with the high byte set (> 16MB) is just garbage. 178 if x[0] != '\x00': 179 raise SFTPError('Garbage packet received') 180 size = struct.unpack('>I', x)[0] 181 data = self._read_all(size) 182 if self.ultra_debug: 183 self._log(DEBUG, util.format_binary(data, 'IN: ')); 184 if size > 0: 185 t = ord(data[0]) 186 #self._log(DEBUG2, 'read: %s (len=%d)' % (CMD_NAMES.get(t), '0x%02x' % t, len(data)-1)) 187 return t, data[1:] 188 return 0, ''
189