diff options
author | bold <bold@cryptoguru.com> | 2019-12-30 19:21:30 +0100 |
---|---|---|
committer | Wez Furlong <wez@wezfurlong.org> | 2020-01-18 08:40:18 -0800 |
commit | c5d2f48aa3eab3d7159b900a66bdc17ed8e29d4e (patch) | |
tree | e9ca7591ef683118b3b37a6446352184ebfe9b4b | |
parent | 1e0f28946aeee4606376de8043a0c1da056fa05c (diff) | |
download | ssh2-rs-c5d2f48aa3eab3d7159b900a66bdc17ed8e29d4e.zip |
add shutdown and close methods
This commit exposes the `shutdown` method of `Sft` and `close` method of
`File` to free resources. Previously this was done synchronously and
therefor not usable in async wrappers.
Whith the methods exposed they can be polled until success. If
successful a flag is set to notify the destructor that no resources
need to be freed anymore.
However, if resources were not cleaned up by calling `close` or
`shutdown` the destructor will clean up synchronously.
-rw-r--r-- | src/sftp.rs | 50 |
1 files changed, 48 insertions, 2 deletions
diff --git a/src/sftp.rs b/src/sftp.rs index e899cf7..6cf6712 100644 --- a/src/sftp.rs +++ b/src/sftp.rs @@ -14,6 +14,7 @@ use {raw, Error, SessionInner}; pub struct Sftp { raw: *mut raw::LIBSSH2_SFTP, _sess: Arc<SessionInner>, + closed: bool, } /// A file handle to an SFTP connection. @@ -26,6 +27,7 @@ pub struct Sftp { pub struct File<'sftp> { raw: *mut raw::LIBSSH2_SFTP_HANDLE, sftp: &'sftp Sftp, + closed: bool, } /// Metadata information about a remote file. @@ -113,6 +115,7 @@ impl Sftp { Ok(Self { raw, _sess: Arc::clone(sess), + closed: false, }) } } @@ -371,11 +374,32 @@ impl Sftp { Err(Error::from_errno(rc)) } } + + /// Shuts the sftp connection down. + /// + /// This should not be called manually since the destructor takes care of it. + /// However, it is useful for async wrappers that take care of async destruction. + pub fn shutdown(&mut self) -> Result<(), Error> { + if !self.closed { + self.rc(unsafe { raw::libssh2_sftp_shutdown(self.raw) })?; + // set flag for destructor that we don't need to close the file anymore + self.closed = true; + } + Ok(()) + } } impl Drop for Sftp { fn drop(&mut self) { - unsafe { assert_eq!(raw::libssh2_sftp_shutdown(self.raw), 0) } + if !self.closed { + let rc = loop { + let rc = unsafe { raw::libssh2_sftp_shutdown(self.raw) }; + if rc != raw::LIBSSH2_ERROR_EAGAIN { + break rc; + } + }; + assert_eq!(rc, 0); + } } } @@ -388,6 +412,7 @@ impl<'sftp> File<'sftp> { File { raw: raw, sftp: sftp, + closed: false, } } @@ -470,6 +495,19 @@ impl<'sftp> File<'sftp> { pub fn fsync(&mut self) -> Result<(), Error> { self.sftp.rc(unsafe { raw::libssh2_sftp_fsync(self.raw) }) } + + /// This function closes the file. + /// + /// This should not be called manually since the destructor takes care of it. + /// However, it is useful for async wrappers that take care of async destruction. + pub fn close(&mut self) -> Result<(), Error> { + if !self.closed { + self.sftp.rc(unsafe { raw::libssh2_sftp_close_handle(self.raw) })?; + // set flag for destructor that we don't need to close the file anymore + self.closed = true; + } + Ok(()) + } } impl<'sftp> Read for File<'sftp> { @@ -534,7 +572,15 @@ impl<'sftp> Seek for File<'sftp> { impl<'sftp> Drop for File<'sftp> { fn drop(&mut self) { - unsafe { assert_eq!(raw::libssh2_sftp_close_handle(self.raw), 0) } + if !self.closed { + let rc = loop { + let rc = unsafe { raw::libssh2_sftp_close_handle(self.raw) }; + if rc != raw::LIBSSH2_ERROR_EAGAIN { + break rc; + } + }; + assert_eq!(rc, 0); + } } } |