Skip to content

Commit 325a241

Browse files
committed
scp: Read large files by chunks
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
1 parent 4011c51 commit 325a241

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

src/pylibsshext/scp.pyx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ from pylibsshext.errors cimport LibsshSCPException
2424
from pylibsshext.session cimport get_libssh_session
2525

2626

27+
SCP_MAX_CHUNK = 65536
28+
29+
2730
cdef class SCP:
2831
def __cinit__(self, session):
2932
self.session = session
@@ -122,7 +125,9 @@ cdef class SCP:
122125
size = libssh.ssh_scp_request_get_size(scp)
123126
mode = libssh.ssh_scp_request_get_permissions(scp)
124127

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)
126131
if read_buffer is NULL:
127132
raise LibsshSCPException("Memory allocation error")
128133

@@ -131,14 +136,17 @@ cdef class SCP:
131136
if rc == libssh.SSH_ERROR:
132137
raise LibsshSCPException("Failed to start read request: %s" % self._get_ssh_error_str())
133138

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
140140
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
142150
if mode >= 0:
143151
os.chmod(local_file, mode)
144152

0 commit comments

Comments
 (0)