Skip to content

Commit e7a56f6

Browse files
author
Pan
committed
Added SFTP implementation. Updated sftp stats and attributes.
1 parent e3bc292 commit e7a56f6

9 files changed

+331
-56
lines changed

.gitmodules

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
[submodule "libssh"]
2-
path = libssh
3-
url = https://git.libssh.org/projects/libssh.git

libssh

Lines changed: 0 additions & 1 deletion
This file was deleted.

ssh/c_ssh.pxd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ from posix.types cimport mode_t
2020

2121
cdef extern from "libssh/libssh.h" nogil:
2222
ctypedef long time_t
23-
ctypedef long subseconds_t
23+
ctypedef long suseconds_t
2424
cdef struct timeval:
2525
time_t tv_sec
26-
subseconds_t tv_usec
26+
suseconds_t tv_usec
2727
ctypedef unsigned char uint8_t
2828
ctypedef unsigned short uint16_t
2929
ctypedef unsigned int uint32_t

ssh/sftp.pxd

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ from session cimport Session
1919
cimport c_sftp
2020

2121

22-
cdef class SFTPStatVFS:
23-
cdef c_sftp.sftp_statvfs_t _stats
24-
25-
26-
cdef class SFTPAttributes:
27-
cdef c_sftp.sftp_attributes _attrs
28-
29-
3022
cdef class SFTP:
3123
cdef c_sftp.sftp_session _sftp
3224
cdef Session session

ssh/sftp.pyx

Lines changed: 190 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,16 @@
1414
# License along with this library; if not, write to the Free Software
1515
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130
1616

17+
from libc.stdlib cimport malloc, free
18+
1719
from session cimport Session
1820
from sftp_handles cimport SFTPFile, SFTPDir
19-
from utils cimport handle_ssh_error_codes
21+
from sftp_attributes cimport SFTPAttributes
22+
from sftp_statvfs cimport SFTPStatVFS
23+
from utils cimport handle_ssh_error_codes, to_bytes
2024

2125
cimport c_sftp
22-
23-
24-
cdef class SFTPStatVFS:
25-
26-
def __dealloc__(self):
27-
if self._stats is not NULL:
28-
c_sftp.sftp_statvfs_free(self._stats)
29-
self._stats = NULL
30-
31-
32-
cdef class SFTPAttributes:
33-
34-
def __dealloc__(self):
35-
if self._attrs is not NULL:
36-
c_sftp.sftp_attributes_free(self._attrs)
37-
self._attrs = NULL
26+
from c_ssh cimport ssh_get_error_code, timeval
3827

3928

4029
cdef class SFTP:
@@ -47,16 +36,18 @@ cdef class SFTP:
4736

4837
def __cinit__(self, Session session):
4938
self.session = session
50-
cdef int rc
51-
with nogil:
52-
rc = c_sftp.sftp_init(self._sftp)
53-
handle_ssh_error_codes(rc, self.session._session)
5439

5540
def __dealloc__(self):
5641
if self._sftp is not NULL:
5742
c_sftp.sftp_free(self._sftp)
5843
self._sftp = NULL
5944

45+
def init(self):
46+
cdef int rc
47+
with nogil:
48+
rc = c_sftp.sftp_init(self._sftp)
49+
return handle_ssh_error_codes(rc, self.session._session)
50+
6051
def get_error(self):
6152
cdef int rc
6253
with nogil:
@@ -70,62 +61,219 @@ cdef class SFTP:
7061
return rc
7162

7263
def extensions_get_name(self, unsigned int indexn):
73-
pass
64+
cdef const char *_name
65+
cdef bytes name = None
66+
with nogil:
67+
_name = c_sftp.sftp_extensions_get_name(self._sftp, indexn)
68+
if _name is not NULL:
69+
name = _name
70+
return name
7471

7572
def extensions_get_data(self, unsigned int indexn):
76-
pass
73+
cdef const char *_name
74+
cdef bytes name = None
75+
with nogil:
76+
_name = c_sftp.sftp_extensions_get_data(self._sftp, indexn)
77+
if _name is not NULL:
78+
name = _name
79+
return name
7780

7881
def extension_supported(self, name not None, data not None):
79-
pass
82+
cdef bint rc
83+
cdef bytes b_name = to_bytes(name)
84+
cdef const char *c_name = b_name
85+
cdef bytes b_data = to_bytes(data)
86+
cdef const char *c_data = b_data
87+
with nogil:
88+
rc = c_sftp.sftp_extension_supported(
89+
self._sftp, c_name, c_data)
90+
return bool(rc)
8091

8192
def opendir(self, path not None):
82-
pass
93+
cdef SFTPDir _dir
94+
cdef c_sftp.sftp_dir c_dir
95+
cdef bytes b_path = to_bytes(path)
96+
cdef const char *c_path = b_path
97+
with nogil:
98+
c_dir = c_sftp.sftp_opendir(self._sftp, c_path)
99+
if c_dir is NULL:
100+
return handle_ssh_error_codes(
101+
ssh_get_error_code(self.session._session),
102+
self.session._session)
103+
_dir = SFTPDir.from_ptr(c_dir, self)
104+
return _dir
83105

84106
def stat(self, path not None):
85-
pass
107+
cdef SFTPAttributes _attrs
108+
cdef c_sftp.sftp_attributes c_attrs
109+
cdef bytes b_path = to_bytes(path)
110+
cdef const char *c_path = b_path
111+
with nogil:
112+
c_attrs = c_sftp.sftp_stat(self._sftp, c_path)
113+
if c_attrs is NULL:
114+
return handle_ssh_error_codes(
115+
ssh_get_error_code(self.session._session),
116+
self.session._session)
117+
_attrs = SFTPAttributes.from_ptr(c_attrs, self)
118+
return _attrs
86119

87120
def lstat(self, path not None):
88-
pass
121+
cdef SFTPAttributes _attrs
122+
cdef c_sftp.sftp_attributes c_attrs
123+
cdef bytes b_path = to_bytes(path)
124+
cdef const char *c_path = b_path
125+
with nogil:
126+
c_attrs = c_sftp.sftp_lstat(self._sftp, c_path)
127+
if c_attrs is NULL:
128+
return handle_ssh_error_codes(
129+
ssh_get_error_code(self.session._session),
130+
self.session._session)
131+
_attrs = SFTPAttributes.from_ptr(c_attrs, self)
132+
return _attrs
89133

90134
def open(self, path not None, int accesstype, c_sftp.mode_t mode):
91-
pass
135+
cdef bytes b_path = to_bytes(path)
136+
cdef const char *c_path = b_path
137+
cdef SFTPFile _file
138+
cdef c_sftp.sftp_file c_file
139+
with nogil:
140+
c_file = c_sftp.sftp_open(self._sftp, c_path, accesstype, mode)
141+
if c_file is NULL:
142+
return handle_ssh_error_codes(
143+
ssh_get_error_code(self.session._session),
144+
self.session._session)
145+
_file = SFTPFile.from_ptr(c_file, self)
146+
return _file
92147

93148
def unlink(self, path not None):
94-
pass
149+
cdef bytes b_path = to_bytes(path)
150+
cdef const char *c_path = b_path
151+
cdef int rc
152+
with nogil:
153+
rc = c_sftp.sftp_unlink(self._sftp, c_path)
154+
return handle_ssh_error_codes(rc, self.session._session)
95155

96156
def rmdir(self, path not None):
97-
pass
157+
cdef bytes b_path = to_bytes(path)
158+
cdef const char *c_path = b_path
159+
cdef int rc
160+
with nogil:
161+
rc = c_sftp.sftp_rmdir(self._sftp, c_path)
162+
return handle_ssh_error_codes(rc, self.session._session)
98163

99164
def mkdir(self, path not None, c_sftp.mode_t mode):
100-
pass
165+
cdef bytes b_path = to_bytes(path)
166+
cdef const char *c_path = b_path
167+
cdef int rc
168+
with nogil:
169+
rc = c_sftp.sftp_mkdir(self._sftp, c_path, mode)
170+
return handle_ssh_error_codes(rc, self.session._session)
101171

102172
def rename(self, original not None, newname not None):
103-
pass
173+
cdef bytes b_orig = to_bytes(original)
174+
cdef const char *c_orig = b_orig
175+
cdef bytes b_newname = to_bytes(newname)
176+
cdef const char *c_newname = b_newname
177+
cdef int rc
178+
with nogil:
179+
rc = c_sftp.sftp_rename(self._sftp, c_orig, c_newname)
180+
return handle_ssh_error_codes(rc, self.session._session)
104181

105182
def setstat(self, path not None, SFTPAttributes attr):
106-
pass
183+
cdef bytes b_path = to_bytes(path)
184+
cdef const char *c_path = b_path
185+
cdef int rc
186+
with nogil:
187+
rc = c_sftp.sftp_setstat(self._sftp, c_path, attr._attrs)
188+
return handle_ssh_error_codes(rc, self.session._session)
107189

108190
def chown(self, path not None,
109191
c_sftp.uid_t owner, c_sftp.gid_t group):
110-
pass
192+
cdef bytes b_path = to_bytes(path)
193+
cdef const char *c_path = b_path
194+
cdef int rc
195+
with nogil:
196+
rc = c_sftp.sftp_chown(self._sftp, c_path, owner, group)
197+
return handle_ssh_error_codes(rc, self.session._session)
111198

112199
def chmod(self, path not None, c_sftp.mode_t mode):
113-
pass
200+
cdef bytes b_path = to_bytes(path)
201+
cdef const char *c_path = b_path
202+
cdef int rc
203+
with nogil:
204+
rc = c_sftp.sftp_chmod(self._sftp, c_path, mode)
205+
return handle_ssh_error_codes(rc, self.session._session)
114206

115-
def utimes(self, path not None, times):
116-
pass
207+
def utimes(self, path not None, long seconds, long microseconds):
208+
cdef bytes b_path = to_bytes(path)
209+
cdef const char *c_path = b_path
210+
cdef int rc
211+
cdef timeval *_val
212+
with nogil:
213+
_val = <timeval *>malloc(sizeof(timeval))
214+
if _val is NULL:
215+
with gil:
216+
raise MemoryError
217+
_val.tv_sec = seconds
218+
_val.tv_usec = microseconds
219+
rc = c_sftp.sftp_utimes(self._sftp, c_path, _val)
220+
free(_val)
221+
return handle_ssh_error_codes(rc, self.session._session)
117222

118223
def symlink(self, source not None, dest not None):
119-
pass
224+
cdef bytes b_source = to_bytes(source)
225+
cdef const char *c_source = b_source
226+
cdef bytes b_dest = to_bytes(dest)
227+
cdef const char *c_dest = b_dest
228+
cdef int rc
229+
with nogil:
230+
rc = c_sftp.sftp_symlink(self._sftp, c_source, c_dest)
231+
return handle_ssh_error_codes(rc, self.session._session)
120232

121233
def readlink(self, path not None):
122-
pass
234+
cdef bytes b_path = to_bytes(path)
235+
cdef const char *c_path = b_path
236+
cdef char *_link
237+
cdef bytes b_link
238+
with nogil:
239+
_link = c_sftp.sftp_readlink(self._sftp, c_path)
240+
if _link is NULL:
241+
return handle_ssh_error_codes(
242+
ssh_get_error_code(self.session._session),
243+
self.session._session)
244+
b_link = _link
245+
return b_link
123246

124247
def statvfs(self, path not None):
125-
pass
248+
cdef bytes b_path = to_bytes(path)
249+
cdef const char *c_path = b_path
250+
cdef SFTPStatVFS vfs
251+
cdef c_sftp.sftp_statvfs_t c_vfs
252+
with nogil:
253+
c_vfs = c_sftp.sftp_statvfs(self._sftp, c_path)
254+
if c_vfs is NULL:
255+
return handle_ssh_error_codes(
256+
ssh_get_error_code(self.session._session),
257+
self.session._session)
258+
vfs = SFTPStatVFS.from_ptr(c_vfs, self)
259+
return vfs
126260

127261
def canonicalize_path(self, path not None):
128-
pass
262+
cdef bytes b_path = to_bytes(path)
263+
cdef const char *c_path = b_path
264+
cdef char *_rpath
265+
cdef bytes b_rpath
266+
with nogil:
267+
_rpath = c_sftp.sftp_canonicalize_path(self._sftp, c_path)
268+
if _rpath is NULL:
269+
return handle_ssh_error_codes(
270+
ssh_get_error_code(self.session._session),
271+
self.session._session)
272+
b_rpath = _rpath
273+
return b_rpath
129274

130275
def server_version(self):
131-
pass
276+
cdef int rc
277+
with nogil:
278+
rc = c_sftp.sftp_server_version(self._sftp)
279+
return rc

ssh/sftp_attributes.pxd

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# This file is part of ssh-python.
2+
# Copyright (C) 2018 Panos Kittenis
3+
#
4+
# This library is free software; you can redistribute it and/or
5+
# modify it under the terms of the GNU Lesser General Public
6+
# License as published by the Free Software Foundation, version 2.1.
7+
#
8+
# This library is distributed in the hope that it will be useful,
9+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11+
# Lesser General Public License for more details.
12+
#
13+
# You should have received a copy of the GNU Lesser General Public
14+
# License along with this library; if not, write to the Free Software
15+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130
16+
17+
from sftp cimport SFTP
18+
19+
cimport c_sftp
20+
21+
22+
cdef class SFTPAttributes:
23+
cdef c_sftp.sftp_attributes _attrs
24+
cdef SFTP sftp
25+
26+
@staticmethod
27+
cdef SFTPAttributes from_ptr(c_sftp.sftp_attributes attrs, SFTP sftp)

0 commit comments

Comments
 (0)