mirror of
https://gitlab.sectorq.eu/jaydee/omv_backup.git
synced 2025-07-03 00:23:06 +02:00
added v3
This commit is contained in:
224
venv/lib/python3.11/site-packages/paramiko/sftp.py
Normal file
224
venv/lib/python3.11/site-packages/paramiko/sftp.py
Normal file
@ -0,0 +1,224 @@
|
||||
# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
|
||||
#
|
||||
# This file is part of paramiko.
|
||||
#
|
||||
# Paramiko is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License as published by the Free
|
||||
# Software Foundation; either version 2.1 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
import select
|
||||
import socket
|
||||
import struct
|
||||
|
||||
from paramiko import util
|
||||
from paramiko.common import DEBUG, byte_chr, byte_ord
|
||||
from paramiko.message import Message
|
||||
|
||||
|
||||
(
|
||||
CMD_INIT,
|
||||
CMD_VERSION,
|
||||
CMD_OPEN,
|
||||
CMD_CLOSE,
|
||||
CMD_READ,
|
||||
CMD_WRITE,
|
||||
CMD_LSTAT,
|
||||
CMD_FSTAT,
|
||||
CMD_SETSTAT,
|
||||
CMD_FSETSTAT,
|
||||
CMD_OPENDIR,
|
||||
CMD_READDIR,
|
||||
CMD_REMOVE,
|
||||
CMD_MKDIR,
|
||||
CMD_RMDIR,
|
||||
CMD_REALPATH,
|
||||
CMD_STAT,
|
||||
CMD_RENAME,
|
||||
CMD_READLINK,
|
||||
CMD_SYMLINK,
|
||||
) = range(1, 21)
|
||||
(CMD_STATUS, CMD_HANDLE, CMD_DATA, CMD_NAME, CMD_ATTRS) = range(101, 106)
|
||||
(CMD_EXTENDED, CMD_EXTENDED_REPLY) = range(200, 202)
|
||||
|
||||
SFTP_OK = 0
|
||||
(
|
||||
SFTP_EOF,
|
||||
SFTP_NO_SUCH_FILE,
|
||||
SFTP_PERMISSION_DENIED,
|
||||
SFTP_FAILURE,
|
||||
SFTP_BAD_MESSAGE,
|
||||
SFTP_NO_CONNECTION,
|
||||
SFTP_CONNECTION_LOST,
|
||||
SFTP_OP_UNSUPPORTED,
|
||||
) = range(1, 9)
|
||||
|
||||
SFTP_DESC = [
|
||||
"Success",
|
||||
"End of file",
|
||||
"No such file",
|
||||
"Permission denied",
|
||||
"Failure",
|
||||
"Bad message",
|
||||
"No connection",
|
||||
"Connection lost",
|
||||
"Operation unsupported",
|
||||
]
|
||||
|
||||
SFTP_FLAG_READ = 0x1
|
||||
SFTP_FLAG_WRITE = 0x2
|
||||
SFTP_FLAG_APPEND = 0x4
|
||||
SFTP_FLAG_CREATE = 0x8
|
||||
SFTP_FLAG_TRUNC = 0x10
|
||||
SFTP_FLAG_EXCL = 0x20
|
||||
|
||||
_VERSION = 3
|
||||
|
||||
|
||||
# for debugging
|
||||
CMD_NAMES = {
|
||||
CMD_INIT: "init",
|
||||
CMD_VERSION: "version",
|
||||
CMD_OPEN: "open",
|
||||
CMD_CLOSE: "close",
|
||||
CMD_READ: "read",
|
||||
CMD_WRITE: "write",
|
||||
CMD_LSTAT: "lstat",
|
||||
CMD_FSTAT: "fstat",
|
||||
CMD_SETSTAT: "setstat",
|
||||
CMD_FSETSTAT: "fsetstat",
|
||||
CMD_OPENDIR: "opendir",
|
||||
CMD_READDIR: "readdir",
|
||||
CMD_REMOVE: "remove",
|
||||
CMD_MKDIR: "mkdir",
|
||||
CMD_RMDIR: "rmdir",
|
||||
CMD_REALPATH: "realpath",
|
||||
CMD_STAT: "stat",
|
||||
CMD_RENAME: "rename",
|
||||
CMD_READLINK: "readlink",
|
||||
CMD_SYMLINK: "symlink",
|
||||
CMD_STATUS: "status",
|
||||
CMD_HANDLE: "handle",
|
||||
CMD_DATA: "data",
|
||||
CMD_NAME: "name",
|
||||
CMD_ATTRS: "attrs",
|
||||
CMD_EXTENDED: "extended",
|
||||
CMD_EXTENDED_REPLY: "extended_reply",
|
||||
}
|
||||
|
||||
|
||||
# TODO: rewrite SFTP file/server modules' overly-flexible "make a request with
|
||||
# xyz components" so we don't need this very silly method of signaling whether
|
||||
# a given Python integer should be 32- or 64-bit.
|
||||
# NOTE: this only became an issue when dropping Python 2 support; prior to
|
||||
# doing so, we had to support actual-longs, which served as that signal. This
|
||||
# is simply recreating that structure in a more tightly scoped fashion.
|
||||
class int64(int):
|
||||
pass
|
||||
|
||||
|
||||
class SFTPError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BaseSFTP:
|
||||
def __init__(self):
|
||||
self.logger = util.get_logger("paramiko.sftp")
|
||||
self.sock = None
|
||||
self.ultra_debug = False
|
||||
|
||||
# ...internals...
|
||||
|
||||
def _send_version(self):
|
||||
m = Message()
|
||||
m.add_int(_VERSION)
|
||||
self._send_packet(CMD_INIT, m)
|
||||
t, data = self._read_packet()
|
||||
if t != CMD_VERSION:
|
||||
raise SFTPError("Incompatible sftp protocol")
|
||||
version = struct.unpack(">I", data[:4])[0]
|
||||
# if version != _VERSION:
|
||||
# raise SFTPError('Incompatible sftp protocol')
|
||||
return version
|
||||
|
||||
def _send_server_version(self):
|
||||
# winscp will freak out if the server sends version info before the
|
||||
# client finishes sending INIT.
|
||||
t, data = self._read_packet()
|
||||
if t != CMD_INIT:
|
||||
raise SFTPError("Incompatible sftp protocol")
|
||||
version = struct.unpack(">I", data[:4])[0]
|
||||
# advertise that we support "check-file"
|
||||
extension_pairs = ["check-file", "md5,sha1"]
|
||||
msg = Message()
|
||||
msg.add_int(_VERSION)
|
||||
msg.add(*extension_pairs)
|
||||
self._send_packet(CMD_VERSION, msg)
|
||||
return version
|
||||
|
||||
def _log(self, level, msg, *args):
|
||||
self.logger.log(level, msg, *args)
|
||||
|
||||
def _write_all(self, out):
|
||||
while len(out) > 0:
|
||||
n = self.sock.send(out)
|
||||
if n <= 0:
|
||||
raise EOFError()
|
||||
if n == len(out):
|
||||
return
|
||||
out = out[n:]
|
||||
return
|
||||
|
||||
def _read_all(self, n):
|
||||
out = bytes()
|
||||
while n > 0:
|
||||
if isinstance(self.sock, socket.socket):
|
||||
# sometimes sftp is used directly over a socket instead of
|
||||
# through a paramiko channel. in this case, check periodically
|
||||
# if the socket is closed. (for some reason, recv() won't ever
|
||||
# return or raise an exception, but calling select on a closed
|
||||
# socket will.)
|
||||
while True:
|
||||
read, write, err = select.select([self.sock], [], [], 0.1)
|
||||
if len(read) > 0:
|
||||
x = self.sock.recv(n)
|
||||
break
|
||||
else:
|
||||
x = self.sock.recv(n)
|
||||
|
||||
if len(x) == 0:
|
||||
raise EOFError()
|
||||
out += x
|
||||
n -= len(x)
|
||||
return out
|
||||
|
||||
def _send_packet(self, t, packet):
|
||||
packet = packet.asbytes()
|
||||
out = struct.pack(">I", len(packet) + 1) + byte_chr(t) + packet
|
||||
if self.ultra_debug:
|
||||
self._log(DEBUG, util.format_binary(out, "OUT: "))
|
||||
self._write_all(out)
|
||||
|
||||
def _read_packet(self):
|
||||
x = self._read_all(4)
|
||||
# most sftp servers won't accept packets larger than about 32k, so
|
||||
# anything with the high byte set (> 16MB) is just garbage.
|
||||
if byte_ord(x[0]):
|
||||
raise SFTPError("Garbage packet received")
|
||||
size = struct.unpack(">I", x)[0]
|
||||
data = self._read_all(size)
|
||||
if self.ultra_debug:
|
||||
self._log(DEBUG, util.format_binary(data, "IN: "))
|
||||
if size > 0:
|
||||
t = byte_ord(data[0])
|
||||
return t, data[1:]
|
||||
return 0, bytes()
|
Reference in New Issue
Block a user