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+
1719from sftp_attributes cimport SFTPAttributes
1820
1921from .exceptions import SFTPHandleError
2022
21- from c_ssh cimport uint32_t, uint64_t
23+ from c_ssh cimport uint32_t, uint64_t, ssh_get_error
2224cimport c_sftp
2325
2426
2527cdef class SFTPFile:
2628
2729 def __cinit__ (self , SFTP sftp ):
2830 self .sftp = sftp
31+ self .closed = False
32+
33+ def __dealloc__ (self ):
34+ pass
2935
3036 @staticmethod
3137 cdef SFTPFile from_ptr(c_sftp.sftp_file _file, SFTP sftp):
@@ -44,28 +50,59 @@ cdef class SFTPFile:
4450
4551 def __next__ (self ):
4652 size, data = self .read()
47- while size > 0 :
48- return size
53+ if size > 0 :
54+ return size, data
4955 raise StopIteration
5056
5157 @property
5258 def sftp_session (self ):
5359 return self .sftp
5460
5561 def fstat (self ):
56- pass
62+ cdef SFTPAttributes _attrs
63+ cdef c_sftp.sftp_attributes c_attrs
64+ with nogil:
65+ c_attrs = c_sftp.sftp_fstat(self ._file)
66+ if c_attrs is NULL :
67+ raise SFTPHandleError(ssh_get_error(self .sftp.session._session))
68+ _attrs = SFTPAttributes.from_ptr(c_attrs, self .sftp)
69+ return _attrs
5770
5871 def close (self ):
59- pass
72+ cdef int rc
73+ if self .closed:
74+ return 0
75+ with nogil:
76+ rc = c_sftp.sftp_close(self ._file)
77+ if rc < 0 :
78+ raise SFTPHandleError(ssh_get_error(self .sftp.session._session))
79+ self .closed = True
80+ return rc
6081
6182 def set_nonblocking (self ):
62- pass
83+ with nogil:
84+ c_sftp.sftp_file_set_nonblocking(self ._file)
6385
6486 def set_blocking (self ):
65- pass
87+ with nogil:
88+ c_sftp.sftp_file_set_blocking(self ._file)
6689
6790 def read (self , size_t count = 1024000 ):
68- pass
91+ cdef ssize_t size
92+ cdef bytes buf = b' '
93+ cdef char * c_buf
94+ with nogil:
95+ c_buf = < char * > malloc(sizeof(char ) * count)
96+ if c_buf is NULL :
97+ with gil:
98+ raise MemoryError
99+ size = c_sftp.sftp_read(self ._file, c_buf, count)
100+ try :
101+ if size > 0 :
102+ buf = c_buf[:size]
103+ finally :
104+ free(c_buf)
105+ return size, buf
69106
70107 def async_read_begin (self , uint32_t length = 1024000 ):
71108 pass
0 commit comments