1
# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
3
# This file is part of paramiko.
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)
10
# Paramiko is distributed 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
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.
23
from paramiko import util
24
from paramiko.common import asbytes, DEBUG
25
from paramiko.message import Message
26
from paramiko.py3compat import byte_chr, byte_ord
29
CMD_INIT, CMD_VERSION, CMD_OPEN, CMD_CLOSE, CMD_READ, CMD_WRITE, CMD_LSTAT, \
30
CMD_FSTAT, CMD_SETSTAT, CMD_FSETSTAT, CMD_OPENDIR, CMD_READDIR, \
31
CMD_REMOVE, CMD_MKDIR, CMD_RMDIR, CMD_REALPATH, CMD_STAT, CMD_RENAME, \
32
CMD_READLINK, CMD_SYMLINK = 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)
37
SFTP_EOF, SFTP_NO_SUCH_FILE, SFTP_PERMISSION_DENIED, SFTP_FAILURE, \
38
SFTP_BAD_MESSAGE, SFTP_NO_CONNECTION, SFTP_CONNECTION_LOST, \
39
SFTP_OP_UNSUPPORTED = range(1, 9)
41
SFTP_DESC = ['Success',
49
'Operation unsupported']
53
SFTP_FLAG_APPEND = 0x4
54
SFTP_FLAG_CREATE = 0x8
55
SFTP_FLAG_TRUNC = 0x10
64
CMD_VERSION: 'version',
71
CMD_SETSTAT: 'setstat',
72
CMD_FSETSTAT: 'fsetstat',
73
CMD_OPENDIR: 'opendir',
74
CMD_READDIR: 'readdir',
78
CMD_REALPATH: 'realpath',
81
CMD_READLINK: 'readlink',
82
CMD_SYMLINK: 'symlink',
88
CMD_EXTENDED: 'extended',
89
CMD_EXTENDED_REPLY: 'extended_reply'
93
class SFTPError (Exception):
97
class BaseSFTP (object):
99
self.logger = util.get_logger('paramiko.sftp')
101
self.ultra_debug = False
105
def _send_version(self):
106
self._send_packet(CMD_INIT, struct.pack('>I', _VERSION))
107
t, data = self._read_packet()
109
raise SFTPError('Incompatible sftp protocol')
110
version = struct.unpack('>I', data[:4])[0]
111
# if version != _VERSION:
112
# raise SFTPError('Incompatible sftp protocol')
115
def _send_server_version(self):
116
# winscp will freak out if the server sends version info before the
117
# client finishes sending INIT.
118
t, data = self._read_packet()
120
raise SFTPError('Incompatible sftp protocol')
121
version = struct.unpack('>I', data[:4])[0]
122
# advertise that we support "check-file"
123
extension_pairs = ['check-file', 'md5,sha1']
125
msg.add_int(_VERSION)
126
msg.add(*extension_pairs)
127
self._send_packet(CMD_VERSION, msg)
130
def _log(self, level, msg, *args):
131
self.logger.log(level, msg, *args)
133
def _write_all(self, out):
135
n = self.sock.send(out)
143
def _read_all(self, n):
146
if isinstance(self.sock, socket.socket):
147
# sometimes sftp is used directly over a socket instead of
148
# through a paramiko channel. in this case, check periodically
149
# if the socket is closed. (for some reason, recv() won't ever
150
# return or raise an exception, but calling select on a closed
153
read, write, err = select.select([self.sock], [], [], 0.1)
155
x = self.sock.recv(n)
158
x = self.sock.recv(n)
166
def _send_packet(self, t, packet):
167
packet = asbytes(packet)
168
out = struct.pack('>I', len(packet) + 1) + byte_chr(t) + packet
170
self._log(DEBUG, util.format_binary(out, 'OUT: '))
173
def _read_packet(self):
174
x = self._read_all(4)
175
# most sftp servers won't accept packets larger than about 32k, so
176
# anything with the high byte set (> 16MB) is just garbage.
178
raise SFTPError('Garbage packet received')
179
size = struct.unpack('>I', x)[0]
180
data = self._read_all(size)
182
self._log(DEBUG, util.format_binary(data, 'IN: '))
184
t = byte_ord(data[0])