@@ -24,6 +24,9 @@ from pylibsshext.errors cimport LibsshSCPException
24
24
from pylibsshext.session cimport get_libssh_session
25
25
26
26
27
+ SCP_MAX_CHUNK = 65536
28
+
29
+
27
30
cdef class SCP:
28
31
def __cinit__ (self , session ):
29
32
self .session = session
@@ -122,7 +125,9 @@ cdef class SCP:
122
125
size = libssh.ssh_scp_request_get_size(scp)
123
126
mode = libssh.ssh_scp_request_get_permissions(scp)
124
127
125
- read_buffer = < char * > PyMem_Malloc(size)
128
+ # cap the buffer size to reasonable number -- libssh will not return the whole data at once anyway
129
+ read_buffer_size = min (size, SCP_MAX_CHUNK)
130
+ read_buffer = < char * > PyMem_Malloc(read_buffer_size)
126
131
if read_buffer is NULL :
127
132
raise LibsshSCPException(" Memory allocation error" )
128
133
@@ -131,14 +136,17 @@ cdef class SCP:
131
136
if rc == libssh.SSH_ERROR:
132
137
raise LibsshSCPException(" Failed to start read request: %s " % self ._get_ssh_error_str())
133
138
134
- # Read the file
135
- rc = libssh.ssh_scp_read(scp, read_buffer, size)
136
- if rc == libssh.SSH_ERROR:
137
- raise LibsshSCPException(" Error receiving file data: %s " % self ._get_ssh_error_str())
138
-
139
- py_file_bytes = read_buffer[:size]
139
+ remaining_bytes_to_read = size
140
140
with open (local_file, " wb" ) as f:
141
- f.write(py_file_bytes)
141
+ while remaining_bytes_to_read > 0 :
142
+ requested_read_bytes = min (remaining_bytes_to_read, read_buffer_size)
143
+ read_bytes = libssh.ssh_scp_read(scp, read_buffer, requested_read_bytes)
144
+ if read_bytes == libssh.SSH_ERROR:
145
+ raise LibsshSCPException(" Error receiving file data: %s " % self ._get_ssh_error_str())
146
+
147
+ py_file_bytes = read_buffer[:read_bytes]
148
+ f.write(py_file_bytes)
149
+ remaining_bytes_to_read -= read_bytes
142
150
if mode >= 0 :
143
151
os.chmod(local_file, mode)
144
152
0 commit comments