summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbold <bold@cryptoguru.com>2019-12-30 19:21:30 +0100
committerWez Furlong <wez@wezfurlong.org>2020-01-18 08:40:18 -0800
commitc5d2f48aa3eab3d7159b900a66bdc17ed8e29d4e (patch)
treee9ca7591ef683118b3b37a6446352184ebfe9b4b
parent1e0f28946aeee4606376de8043a0c1da056fa05c (diff)
downloadssh2-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.rs50
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);
+ }
}
}