Skip to content

Commit 85a2b68

Browse files
author
Pan
committed
Fixed use of SCP functions in non-blocking mode. Return lissh2 errors as appropriate exceptions from scp functions. Removed SCPError exception.
1 parent 1fa7a2c commit 85a2b68

9 files changed

+481
-655
lines changed

.appveyor.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ install:
109109
- ps: ls ssh2
110110

111111
build_script:
112-
# Build the compiled extension
113112
- "%CMD_IN_ENV% ci\\appveyor\\build_zlib.bat"
114113
- "%CMD_IN_ENV% ci\\appveyor\\build_ssh2.bat"
115114
- rm -f ssh2/*.c

Changelog.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@ Changes
1414
* Windows wheels switched to OpenSSL back end.
1515
* Windows wheels include zlib and have compression enabled.
1616
* Windows wheels no MAC and no encryption options enabled, same as posix wheels.
17+
* SCP functions now raise appropriate exception for all known libssh2 error codes.
1718

18-
Note - binary wheels only.
19+
Fixes
20+
-------
21+
22+
* SCP functions could not be used in non-blocking mode.
23+
24+
Note - libssh2 changes apply to binary wheels only. For building from source `see documentation <http://ssh2-python.readthedocs.io/en/latest/installation.html#installation-from-source>`_.
1925

2026
0.11.0
2127
++++++++

setup.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,11 @@
2424

2525
ext = 'pyx' if USING_CYTHON else 'c'
2626
sources = glob('ssh2/*.%s' % (ext,))
27-
if ON_WINDOWS:
28-
# For libssh2 OpenSSL backend on Windows.
29-
_libs = ['Ws2_32', 'libssh2', 'user32',
30-
'libeay32MD', 'ssleay32MD',
31-
'zlibstatic',
32-
]
33-
else:
34-
_libs = ['ssh2']
27+
_libs = ['ssh2'] if not ON_WINDOWS else [
28+
'Ws2_32', 'libssh2', 'user32',
29+
'libeay32MD', 'ssleay32MD',
30+
'zlibstatic',
31+
]
3532

3633
# _comp_args = ["-ggdb"]
3734
_comp_args = ["-O3"] if not ON_WINDOWS else None

ssh2/exceptions.c

Lines changed: 187 additions & 219 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ssh2/exceptions.pyx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,7 @@ class ChannelEOFSentError(ChannelError):
159159
"""Raised on channel EOF errors"""
160160

161161

162-
class SCPError(SSH2Error):
163-
"""Raised on SCP errors. Base class for all SCP exceptions."""
164-
165-
166-
class SCPProtocolError(SCPError):
162+
class SCPProtocolError(SessionError):
167163
"""Raised on SCP protocol errors"""
168164

169165

ssh2/session.c

Lines changed: 266 additions & 410 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ssh2/session.pyx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ from libc.time cimport time_t
2020
from agent cimport PyAgent, agent_auth, agent_init, init_connect_agent
2121
from channel cimport PyChannel
2222
from exceptions import SessionHandshakeError, SessionStartupError, \
23-
AuthenticationError, SessionHostKeyError, SCPError, KnownHostError, \
23+
AuthenticationError, SessionHostKeyError, KnownHostError, \
2424
PublicKeyInitError, ChannelError
2525
from listener cimport PyListener
2626
from sftp cimport PySFTP
@@ -510,7 +510,8 @@ cdef class Session:
510510
channel = c_ssh2.libssh2_scp_recv(
511511
self._session, _path, statinfo._stat)
512512
if channel is NULL:
513-
raise SCPError("Error opening remote file %s for reading", path)
513+
return handle_error_codes(c_ssh2.libssh2_session_last_errno(
514+
self._session))
514515
return PyChannel(channel, self), statinfo
515516

516517
IF EMBEDDED_LIB:
@@ -532,7 +533,8 @@ cdef class Session:
532533
channel = c_ssh2.libssh2_scp_recv2(
533534
self._session, _path, fileinfo._stat)
534535
if channel is NULL:
535-
raise SCPError("Error opening remote file %s for reading", path)
536+
return handle_error_codes(c_ssh2.libssh2_session_last_errno(
537+
self._session))
536538
return PyChannel(channel, self), fileinfo
537539

538540
def scp_send(self, path not None, int mode, size_t size):
@@ -553,7 +555,8 @@ cdef class Session:
553555
channel = c_ssh2.libssh2_scp_send(
554556
self._session, _path, mode, size)
555557
if channel is NULL:
556-
raise SCPError("Error opening remote file %s for writing", path)
558+
return handle_error_codes(c_ssh2.libssh2_session_last_errno(
559+
self._session))
557560
return PyChannel(channel, self)
558561

559562
def scp_send64(self, path not None, int mode, c_ssh2.libssh2_uint64_t size,
@@ -575,7 +578,8 @@ cdef class Session:
575578
channel = c_ssh2.libssh2_scp_send64(
576579
self._session, _path, mode, size, mtime, atime)
577580
if channel is NULL:
578-
raise SCPError("Error opening remote file %s for writing", path)
581+
return handle_error_codes(c_ssh2.libssh2_session_last_errno(
582+
self._session))
579583
return PyChannel(channel, self)
580584

581585
def publickey_init(self):

tests/test_exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
ChannelError, ChannelOutOfOrderError, ChannelFailure, \
3434
ChannelRequestDenied, ChannelUnknownError, ChannelWindowExceeded, \
3535
ChannelPacketExceeded, ChannelClosedError, ChannelEOFSentError, \
36-
SCPError, SCPProtocolError, ZlibError, SocketTimeout, \
36+
SCPProtocolError, ZlibError, SocketTimeout, \
3737
RequestDeniedError, MethodNotSupported, InvalidRequestError, \
3838
InvalidPollTypeError, PublicKeyProtocolError, BufferTooSmallError, \
3939
BadUseError, CompressError, OutOfBoundaryError, SocketRecvError, \

tests/test_session.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from ssh2.channel import Channel
99
from ssh2.error_codes import LIBSSH2_ERROR_EAGAIN
1010
from ssh2.exceptions import AuthenticationError, AgentAuthenticationError, \
11-
SCPError, RequestDeniedError, InvalidRequestError, SocketSendError
11+
SCPProtocolError, RequestDeniedError, InvalidRequestError, SocketSendError
1212
from ssh2.utils import wait_socket
1313

1414

@@ -83,7 +83,7 @@ def test_scp_recv2(self):
8383
raise
8484
finally:
8585
os.unlink(remote_filename)
86-
self.assertRaises(SCPError, self.session.scp_recv2, remote_filename)
86+
self.assertRaises(SCPProtocolError, self.session.scp_recv2, remote_filename)
8787

8888
def test_scp_recv(self):
8989
self.assertEqual(self._auth(), 0)
@@ -109,7 +109,7 @@ def test_scp_recv(self):
109109
raise
110110
finally:
111111
os.unlink(remote_filename)
112-
self.assertRaises(SCPError, self.session.scp_recv, remote_filename)
112+
self.assertRaises(SCPProtocolError, self.session.scp_recv, remote_filename)
113113

114114
def test_scp_send(self):
115115
self.assertEqual(self._auth(), 0)
@@ -140,7 +140,7 @@ def test_scp_send(self):
140140
os.unlink(to_copy)
141141
except OSError:
142142
pass
143-
self.assertRaises(SCPError, self.session.scp_send,
143+
self.assertRaises(SCPProtocolError, self.session.scp_send,
144144
'/cannot_write', 1 & 777, 1)
145145

146146
@skipUnless(hasattr(Session, 'scp_send64'),
@@ -175,7 +175,7 @@ def test_scp_send64(self):
175175
os.unlink(to_copy)
176176
except OSError:
177177
pass
178-
self.assertRaises(SCPError, self.session.scp_send64,
178+
self.assertRaises(SCPProtocolError, self.session.scp_send64,
179179
'/cannot_write', 0 & 777, 1, 1, 1)
180180

181181
def test_non_blocking(self):

0 commit comments

Comments
 (0)