FileTransferResult

This commit is contained in:
veeso
2021-09-10 20:58:26 +02:00
parent 1f115dea92
commit f69489fc8f
6 changed files with 108 additions and 99 deletions

View File

@@ -62,15 +62,6 @@ pub struct FileTransferError {
msg: Option<String>, msg: Option<String>,
} }
impl FileTransferError {
/// ### kind
///
/// Returns the error kind
pub fn kind(&self) -> FileTransferErrorType {
self.code
}
}
/// ## FileTransferErrorType /// ## FileTransferErrorType
/// ///
/// FileTransferErrorType defines the possible errors available for a file transfer /// FileTransferErrorType defines the possible errors available for a file transfer
@@ -118,6 +109,13 @@ impl FileTransferError {
err.msg = Some(msg); err.msg = Some(msg);
err err
} }
/// ### kind
///
/// Returns the error kind
pub fn kind(&self) -> FileTransferErrorType {
self.code
}
} }
impl std::fmt::Display for FileTransferError { impl std::fmt::Display for FileTransferError {
@@ -129,6 +127,11 @@ impl std::fmt::Display for FileTransferError {
} }
} }
/// ## FileTransferResult
///
/// Result type returned by a `FileTransfer` implementation
pub type FileTransferResult<T> = Result<T, FileTransferError>;
/// ## FileTransfer /// ## FileTransfer
/// ///
/// File transfer trait must be implemented by all the file transfers and defines the method used by a generic file transfer /// File transfer trait must be implemented by all the file transfers and defines the method used by a generic file transfer
@@ -137,12 +140,12 @@ pub trait FileTransfer {
/// ///
/// Connect to the remote server /// Connect to the remote server
/// Can return banner / welcome message on success /// Can return banner / welcome message on success
fn connect(&mut self, params: &ProtocolParams) -> Result<Option<String>, FileTransferError>; fn connect(&mut self, params: &ProtocolParams) -> FileTransferResult<Option<String>>;
/// ### disconnect /// ### disconnect
/// ///
/// Disconnect from the remote server /// Disconnect from the remote server
fn disconnect(&mut self) -> Result<(), FileTransferError>; fn disconnect(&mut self) -> FileTransferResult<()>;
/// ### is_connected /// ### is_connected
/// ///
@@ -153,50 +156,50 @@ pub trait FileTransfer {
/// ///
/// Print working directory /// Print working directory
fn pwd(&mut self) -> Result<PathBuf, FileTransferError>; fn pwd(&mut self) -> FileTransferResult<PathBuf>;
/// ### change_dir /// ### change_dir
/// ///
/// Change working directory /// Change working directory
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError>; fn change_dir(&mut self, dir: &Path) -> FileTransferResult<PathBuf>;
/// ### copy /// ### copy
/// ///
/// Copy file to destination /// Copy file to destination
fn copy(&mut self, src: &FsEntry, dst: &Path) -> Result<(), FileTransferError>; fn copy(&mut self, src: &FsEntry, dst: &Path) -> FileTransferResult<()>;
/// ### list_dir /// ### list_dir
/// ///
/// List directory entries /// List directory entries
fn list_dir(&mut self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError>; fn list_dir(&mut self, path: &Path) -> FileTransferResult<Vec<FsEntry>>;
/// ### mkdir /// ### mkdir
/// ///
/// Make directory /// Make directory
/// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists` /// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists`
fn mkdir(&mut self, dir: &Path) -> Result<(), FileTransferError>; fn mkdir(&mut self, dir: &Path) -> FileTransferResult<()>;
/// ### remove /// ### remove
/// ///
/// Remove a file or a directory /// Remove a file or a directory
fn remove(&mut self, file: &FsEntry) -> Result<(), FileTransferError>; fn remove(&mut self, file: &FsEntry) -> FileTransferResult<()>;
/// ### rename /// ### rename
/// ///
/// Rename file or a directory /// Rename file or a directory
fn rename(&mut self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError>; fn rename(&mut self, file: &FsEntry, dst: &Path) -> FileTransferResult<()>;
/// ### stat /// ### stat
/// ///
/// Stat file and return FsEntry /// Stat file and return FsEntry
fn stat(&mut self, path: &Path) -> Result<FsEntry, FileTransferError>; fn stat(&mut self, path: &Path) -> FileTransferResult<FsEntry>;
/// ### exec /// ### exec
/// ///
/// Execute a command on remote host /// Execute a command on remote host
fn exec(&mut self, cmd: &str) -> Result<String, FileTransferError>; fn exec(&mut self, cmd: &str) -> FileTransferResult<String>;
/// ### send_file /// ### send_file
/// ///
@@ -209,7 +212,7 @@ pub trait FileTransfer {
&mut self, &mut self,
_local: &FsFile, _local: &FsFile,
_file_name: &Path, _file_name: &Path,
) -> Result<Box<dyn Write>, FileTransferError> { ) -> FileTransferResult<Box<dyn Write>> {
Err(FileTransferError::new( Err(FileTransferError::new(
FileTransferErrorType::UnsupportedFeature, FileTransferErrorType::UnsupportedFeature,
)) ))
@@ -220,7 +223,7 @@ pub trait FileTransfer {
/// Receive file from remote with provided name /// Receive file from remote with provided name
/// Returns file and its size /// Returns file and its size
/// By default returns unsupported feature /// By default returns unsupported feature
fn recv_file(&mut self, _file: &FsFile) -> Result<Box<dyn Read>, FileTransferError> { fn recv_file(&mut self, _file: &FsFile) -> FileTransferResult<Box<dyn Read>> {
Err(FileTransferError::new( Err(FileTransferError::new(
FileTransferErrorType::UnsupportedFeature, FileTransferErrorType::UnsupportedFeature,
)) ))
@@ -234,7 +237,7 @@ pub trait FileTransfer {
/// This is necessary for some protocols such as FTP. /// This is necessary for some protocols such as FTP.
/// You must call this method each time you want to finalize the write of the remote file. /// You must call this method each time you want to finalize the write of the remote file.
/// By default this function returns already `Ok(())` /// By default this function returns already `Ok(())`
fn on_sent(&mut self, _writable: Box<dyn Write>) -> Result<(), FileTransferError> { fn on_sent(&mut self, _writable: Box<dyn Write>) -> FileTransferResult<()> {
Ok(()) Ok(())
} }
@@ -246,7 +249,7 @@ pub trait FileTransfer {
/// This mighe be necessary for some protocols. /// This mighe be necessary for some protocols.
/// You must call this method each time you want to finalize the read of the remote file. /// You must call this method each time you want to finalize the read of the remote file.
/// By default this function returns already `Ok(())` /// By default this function returns already `Ok(())`
fn on_recv(&mut self, _readable: Box<dyn Read>) -> Result<(), FileTransferError> { fn on_recv(&mut self, _readable: Box<dyn Read>) -> FileTransferResult<()> {
Ok(()) Ok(())
} }
@@ -262,7 +265,7 @@ pub trait FileTransfer {
src: &FsFile, src: &FsFile,
dest: &Path, dest: &Path,
mut reader: Box<dyn Read>, mut reader: Box<dyn Read>,
) -> Result<(), FileTransferError> { ) -> FileTransferResult<()> {
match self.is_connected() { match self.is_connected() {
true => { true => {
let mut stream = self.send_file(src, dest)?; let mut stream = self.send_file(src, dest)?;
@@ -285,7 +288,7 @@ pub trait FileTransfer {
/// If the function returns error kind() `UnsupportedFeature`, then he should call this function. /// If the function returns error kind() `UnsupportedFeature`, then he should call this function.
/// For safety reasons this function doesn't accept the `Write` trait, but the destination path. /// For safety reasons this function doesn't accept the `Write` trait, but the destination path.
/// By default this function uses the streams function to copy content from reader to writer /// By default this function uses the streams function to copy content from reader to writer
fn recv_file_wno_stream(&mut self, src: &FsFile, dest: &Path) -> Result<(), FileTransferError> { fn recv_file_wno_stream(&mut self, src: &FsFile, dest: &Path) -> FileTransferResult<()> {
match self.is_connected() { match self.is_connected() {
true => { true => {
let mut writer = File::create(dest).map_err(|e| { let mut writer = File::create(dest).map_err(|e| {
@@ -315,7 +318,7 @@ pub trait FileTransfer {
/// ///
/// Find files from current directory (in all subdirectories) whose name matches the provided search /// Find files from current directory (in all subdirectories) whose name matches the provided search
/// Search supports wildcards ('?', '*') /// Search supports wildcards ('?', '*')
fn find(&mut self, search: &str) -> Result<Vec<FsEntry>, FileTransferError> { fn find(&mut self, search: &str) -> FileTransferResult<Vec<FsEntry>> {
match self.is_connected() { match self.is_connected() {
true => { true => {
// Starting from current directory, iter dir // Starting from current directory, iter dir
@@ -335,11 +338,7 @@ pub trait FileTransfer {
/// Search recursively in `dir` for file matching the wildcard. /// Search recursively in `dir` for file matching the wildcard.
/// NOTE: DON'T RE-IMPLEMENT THIS FUNCTION, unless the file transfer provides a faster way to do so /// NOTE: DON'T RE-IMPLEMENT THIS FUNCTION, unless the file transfer provides a faster way to do so
/// NOTE: don't call this method from outside; consider it as private /// NOTE: don't call this method from outside; consider it as private
fn iter_search( fn iter_search(&mut self, dir: &Path, filter: &WildMatch) -> FileTransferResult<Vec<FsEntry>> {
&mut self,
dir: &Path,
filter: &WildMatch,
) -> Result<Vec<FsEntry>, FileTransferError> {
let mut drained: Vec<FsEntry> = Vec::new(); let mut drained: Vec<FsEntry> = Vec::new();
// Scan directory // Scan directory
match self.list_dir(dir) { match self.list_dir(dir) {

View File

@@ -25,7 +25,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
use super::{FileTransfer, FileTransferError, FileTransferErrorType, ProtocolParams}; use super::{
FileTransfer, FileTransferError, FileTransferErrorType, FileTransferResult, ProtocolParams,
};
use crate::fs::{FsDirectory, FsEntry, FsFile, UnixPex}; use crate::fs::{FsDirectory, FsEntry, FsFile, UnixPex};
use crate::utils::fmt::shadow_password; use crate::utils::fmt::shadow_password;
use crate::utils::path; use crate::utils::path;
@@ -178,7 +180,7 @@ impl FileTransfer for FtpFileTransfer {
/// ///
/// Connect to the remote server /// Connect to the remote server
fn connect(&mut self, params: &ProtocolParams) -> Result<Option<String>, FileTransferError> { fn connect(&mut self, params: &ProtocolParams) -> FileTransferResult<Option<String>> {
let params = match params.generic_params() { let params = match params.generic_params() {
Some(params) => params, Some(params) => params,
None => return Err(FileTransferError::new(FileTransferErrorType::BadAddress)), None => return Err(FileTransferError::new(FileTransferErrorType::BadAddress)),
@@ -270,7 +272,7 @@ impl FileTransfer for FtpFileTransfer {
/// ///
/// Disconnect from the remote server /// Disconnect from the remote server
fn disconnect(&mut self) -> Result<(), FileTransferError> { fn disconnect(&mut self) -> FileTransferResult<()> {
info!("Disconnecting from FTP server..."); info!("Disconnecting from FTP server...");
match &mut self.stream { match &mut self.stream {
Some(stream) => match stream.quit() { Some(stream) => match stream.quit() {
@@ -300,7 +302,7 @@ impl FileTransfer for FtpFileTransfer {
/// ///
/// Print working directory /// Print working directory
fn pwd(&mut self) -> Result<PathBuf, FileTransferError> { fn pwd(&mut self) -> FileTransferResult<PathBuf> {
info!("PWD"); info!("PWD");
match &mut self.stream { match &mut self.stream {
Some(stream) => match stream.pwd() { Some(stream) => match stream.pwd() {
@@ -320,7 +322,7 @@ impl FileTransfer for FtpFileTransfer {
/// ///
/// Change working directory /// Change working directory
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError> { fn change_dir(&mut self, dir: &Path) -> FileTransferResult<PathBuf> {
let dir: PathBuf = Self::resolve(dir); let dir: PathBuf = Self::resolve(dir);
info!("Changing directory to {}", dir.display()); info!("Changing directory to {}", dir.display());
match &mut self.stream { match &mut self.stream {
@@ -340,7 +342,7 @@ impl FileTransfer for FtpFileTransfer {
/// ### copy /// ### copy
/// ///
/// Copy file to destination /// Copy file to destination
fn copy(&mut self, _src: &FsEntry, _dst: &Path) -> Result<(), FileTransferError> { fn copy(&mut self, _src: &FsEntry, _dst: &Path) -> FileTransferResult<()> {
// FTP doesn't support file copy // FTP doesn't support file copy
debug!("COPY issues (will fail, since unsupported)"); debug!("COPY issues (will fail, since unsupported)");
Err(FileTransferError::new( Err(FileTransferError::new(
@@ -352,7 +354,7 @@ impl FileTransfer for FtpFileTransfer {
/// ///
/// List directory entries /// List directory entries
fn list_dir(&mut self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError> { fn list_dir(&mut self, path: &Path) -> FileTransferResult<Vec<FsEntry>> {
let dir: PathBuf = Self::resolve(path); let dir: PathBuf = Self::resolve(path);
info!("LIST dir {}", dir.display()); info!("LIST dir {}", dir.display());
match &mut self.stream { match &mut self.stream {
@@ -376,7 +378,7 @@ impl FileTransfer for FtpFileTransfer {
/// ### mkdir /// ### mkdir
/// ///
/// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists` /// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists`
fn mkdir(&mut self, dir: &Path) -> Result<(), FileTransferError> { fn mkdir(&mut self, dir: &Path) -> FileTransferResult<()> {
let dir: PathBuf = Self::resolve(dir); let dir: PathBuf = Self::resolve(dir);
info!("MKDIR {}", dir.display()); info!("MKDIR {}", dir.display());
match &mut self.stream { match &mut self.stream {
@@ -406,7 +408,7 @@ impl FileTransfer for FtpFileTransfer {
/// ### remove /// ### remove
/// ///
/// Remove a file or a directory /// Remove a file or a directory
fn remove(&mut self, fsentry: &FsEntry) -> Result<(), FileTransferError> { fn remove(&mut self, fsentry: &FsEntry) -> FileTransferResult<()> {
if self.stream.is_none() { if self.stream.is_none() {
return Err(FileTransferError::new( return Err(FileTransferError::new(
FileTransferErrorType::UninitializedSession, FileTransferErrorType::UninitializedSession,
@@ -493,7 +495,7 @@ impl FileTransfer for FtpFileTransfer {
/// ### rename /// ### rename
/// ///
/// Rename file or a directory /// Rename file or a directory
fn rename(&mut self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> { fn rename(&mut self, file: &FsEntry, dst: &Path) -> FileTransferResult<()> {
let dst: PathBuf = Self::resolve(dst); let dst: PathBuf = Self::resolve(dst);
info!( info!(
"Renaming {} to {}", "Renaming {} to {}",
@@ -525,7 +527,7 @@ impl FileTransfer for FtpFileTransfer {
/// ### stat /// ### stat
/// ///
/// Stat file and return FsEntry /// Stat file and return FsEntry
fn stat(&mut self, _path: &Path) -> Result<FsEntry, FileTransferError> { fn stat(&mut self, _path: &Path) -> FileTransferResult<FsEntry> {
match &mut self.stream { match &mut self.stream {
Some(_) => Err(FileTransferError::new( Some(_) => Err(FileTransferError::new(
FileTransferErrorType::UnsupportedFeature, FileTransferErrorType::UnsupportedFeature,
@@ -539,7 +541,7 @@ impl FileTransfer for FtpFileTransfer {
/// ### exec /// ### exec
/// ///
/// Execute a command on remote host /// Execute a command on remote host
fn exec(&mut self, _cmd: &str) -> Result<String, FileTransferError> { fn exec(&mut self, _cmd: &str) -> FileTransferResult<String> {
Err(FileTransferError::new( Err(FileTransferError::new(
FileTransferErrorType::UnsupportedFeature, FileTransferErrorType::UnsupportedFeature,
)) ))
@@ -555,7 +557,7 @@ impl FileTransfer for FtpFileTransfer {
&mut self, &mut self,
_local: &FsFile, _local: &FsFile,
file_name: &Path, file_name: &Path,
) -> Result<Box<dyn Write>, FileTransferError> { ) -> FileTransferResult<Box<dyn Write>> {
let file_name: PathBuf = Self::resolve(file_name); let file_name: PathBuf = Self::resolve(file_name);
info!("Sending file {}", file_name.display()); info!("Sending file {}", file_name.display());
match &mut self.stream { match &mut self.stream {
@@ -576,7 +578,7 @@ impl FileTransfer for FtpFileTransfer {
/// ///
/// Receive file from remote with provided name /// Receive file from remote with provided name
/// Returns file and its size /// Returns file and its size
fn recv_file(&mut self, file: &FsFile) -> Result<Box<dyn Read>, FileTransferError> { fn recv_file(&mut self, file: &FsFile) -> FileTransferResult<Box<dyn Read>> {
info!("Receiving file {}", file.abs_path.display()); info!("Receiving file {}", file.abs_path.display());
match &mut self.stream { match &mut self.stream {
Some(stream) => match stream.retr_as_stream(&file.abs_path.as_path().to_string_lossy()) Some(stream) => match stream.retr_as_stream(&file.abs_path.as_path().to_string_lossy())
@@ -600,7 +602,7 @@ impl FileTransfer for FtpFileTransfer {
/// The purpose of this method is to finalize the connection with the peer when writing data. /// The purpose of this method is to finalize the connection with the peer when writing data.
/// This is necessary for some protocols such as FTP. /// This is necessary for some protocols such as FTP.
/// You must call this method each time you want to finalize the write of the remote file. /// You must call this method each time you want to finalize the write of the remote file.
fn on_sent(&mut self, writable: Box<dyn Write>) -> Result<(), FileTransferError> { fn on_sent(&mut self, writable: Box<dyn Write>) -> FileTransferResult<()> {
info!("Finalizing put stream"); info!("Finalizing put stream");
match &mut self.stream { match &mut self.stream {
Some(stream) => match stream.finalize_put_stream(writable) { Some(stream) => match stream.finalize_put_stream(writable) {
@@ -623,7 +625,7 @@ impl FileTransfer for FtpFileTransfer {
/// The purpose of this method is to finalize the connection with the peer when reading data. /// The purpose of this method is to finalize the connection with the peer when reading data.
/// This mighe be necessary for some protocols. /// This mighe be necessary for some protocols.
/// You must call this method each time you want to finalize the read of the remote file. /// You must call this method each time you want to finalize the read of the remote file.
fn on_recv(&mut self, readable: Box<dyn Read>) -> Result<(), FileTransferError> { fn on_recv(&mut self, readable: Box<dyn Read>) -> FileTransferResult<()> {
info!("Finalizing get"); info!("Finalizing get");
match &mut self.stream { match &mut self.stream {
Some(stream) => match stream.finalize_retr_stream(readable) { Some(stream) => match stream.finalize_retr_stream(readable) {

View File

@@ -3,7 +3,9 @@
//! This module exposes all the file transfers supported by termscp //! This module exposes all the file transfers supported by termscp
// -- import // -- import
use super::{FileTransfer, FileTransferError, FileTransferErrorType, ProtocolParams}; use super::{
FileTransfer, FileTransferError, FileTransferErrorType, FileTransferResult, ProtocolParams,
};
// -- modules // -- modules
mod ftp; mod ftp;

View File

@@ -29,7 +29,9 @@
mod object; mod object;
// Locals // Locals
use super::{FileTransfer, FileTransferError, FileTransferErrorType, ProtocolParams}; use super::{
FileTransfer, FileTransferError, FileTransferErrorType, FileTransferResult, ProtocolParams,
};
use crate::fs::{FsDirectory, FsEntry, FsFile}; use crate::fs::{FsDirectory, FsEntry, FsFile};
use crate::utils::path; use crate::utils::path;
use object::S3Object; use object::S3Object;
@@ -64,7 +66,7 @@ impl S3FileTransfer {
/// ### list_objects /// ### list_objects
/// ///
/// List objects contained in `p` path /// List objects contained in `p` path
fn list_objects(&self, p: &Path, list_dir: bool) -> Result<Vec<S3Object>, FileTransferError> { fn list_objects(&self, p: &Path, list_dir: bool) -> FileTransferResult<Vec<S3Object>> {
// Make path relative // Make path relative
let key: String = Self::fmt_path(p, list_dir); let key: String = Self::fmt_path(p, list_dir);
debug!("Query list directory {}; key: {}", p.display(), key); debug!("Query list directory {}; key: {}", p.display(), key);
@@ -74,7 +76,7 @@ impl S3FileTransfer {
/// ### stat_object /// ### stat_object
/// ///
/// Stat an s3 object /// Stat an s3 object
fn stat_object(&self, p: &Path) -> Result<S3Object, FileTransferError> { fn stat_object(&self, p: &Path) -> FileTransferResult<S3Object> {
let key: String = Self::fmt_path(p, false); let key: String = Self::fmt_path(p, false);
debug!("Query stat object {}; key: {}", p.display(), key); debug!("Query stat object {}; key: {}", p.display(), key);
let objects = self.query_objects(key, false)?; let objects = self.query_objects(key, false)?;
@@ -100,7 +102,7 @@ impl S3FileTransfer {
&self, &self,
key: String, key: String,
only_direct_children: bool, only_direct_children: bool,
) -> Result<Vec<S3Object>, FileTransferError> { ) -> FileTransferResult<Vec<S3Object>> {
let results = self.bucket.as_ref().unwrap().list(key.clone(), None); let results = self.bucket.as_ref().unwrap().list(key.clone(), None);
match results { match results {
Ok(entries) => { Ok(entries) => {
@@ -200,7 +202,7 @@ impl FileTransfer for S3FileTransfer {
/// ///
/// Connect to the remote server /// Connect to the remote server
/// Can return banner / welcome message on success /// Can return banner / welcome message on success
fn connect(&mut self, params: &ProtocolParams) -> Result<Option<String>, FileTransferError> { fn connect(&mut self, params: &ProtocolParams) -> FileTransferResult<Option<String>> {
// Verify parameters are S3 // Verify parameters are S3
let params = match params.s3_params() { let params = match params.s3_params() {
Some(params) => params, Some(params) => params,
@@ -242,7 +244,7 @@ impl FileTransfer for S3FileTransfer {
/// ### disconnect /// ### disconnect
/// ///
/// Disconnect from the remote server /// Disconnect from the remote server
fn disconnect(&mut self) -> Result<(), FileTransferError> { fn disconnect(&mut self) -> FileTransferResult<()> {
info!("Disconnecting from S3 bucket..."); info!("Disconnecting from S3 bucket...");
match self.bucket.take() { match self.bucket.take() {
Some(bucket) => { Some(bucket) => {
@@ -265,7 +267,7 @@ impl FileTransfer for S3FileTransfer {
/// ### pwd /// ### pwd
/// ///
/// Print working directory /// Print working directory
fn pwd(&mut self) -> Result<PathBuf, FileTransferError> { fn pwd(&mut self) -> FileTransferResult<PathBuf> {
info!("PWD"); info!("PWD");
match self.is_connected() { match self.is_connected() {
true => Ok(self.wrkdir.clone()), true => Ok(self.wrkdir.clone()),
@@ -278,7 +280,7 @@ impl FileTransfer for S3FileTransfer {
/// ### change_dir /// ### change_dir
/// ///
/// Change working directory /// Change working directory
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError> { fn change_dir(&mut self, dir: &Path) -> FileTransferResult<PathBuf> {
match &self.bucket.is_some() { match &self.bucket.is_some() {
true => { true => {
// Always allow entering root // Always allow entering root
@@ -315,7 +317,7 @@ impl FileTransfer for S3FileTransfer {
/// ### copy /// ### copy
/// ///
/// Copy file to destination /// Copy file to destination
fn copy(&mut self, _src: &FsEntry, _dst: &Path) -> Result<(), FileTransferError> { fn copy(&mut self, _src: &FsEntry, _dst: &Path) -> FileTransferResult<()> {
Err(FileTransferError::new( Err(FileTransferError::new(
FileTransferErrorType::UnsupportedFeature, FileTransferErrorType::UnsupportedFeature,
)) ))
@@ -324,7 +326,7 @@ impl FileTransfer for S3FileTransfer {
/// ### list_dir /// ### list_dir
/// ///
/// List directory entries /// List directory entries
fn list_dir(&mut self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError> { fn list_dir(&mut self, path: &Path) -> FileTransferResult<Vec<FsEntry>> {
match self.is_connected() { match self.is_connected() {
true => self true => self
.list_objects(path, true) .list_objects(path, true)
@@ -339,7 +341,7 @@ impl FileTransfer for S3FileTransfer {
/// ///
/// Make directory /// Make directory
/// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists` /// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists`
fn mkdir(&mut self, dir: &Path) -> Result<(), FileTransferError> { fn mkdir(&mut self, dir: &Path) -> FileTransferResult<()> {
match &self.bucket { match &self.bucket {
Some(bucket) => { Some(bucket) => {
let dir: String = Self::fmt_path(self.resolve(dir).as_path(), true); let dir: String = Self::fmt_path(self.resolve(dir).as_path(), true);
@@ -373,7 +375,7 @@ impl FileTransfer for S3FileTransfer {
/// ### remove /// ### remove
/// ///
/// Remove a file or a directory /// Remove a file or a directory
fn remove(&mut self, file: &FsEntry) -> Result<(), FileTransferError> { fn remove(&mut self, file: &FsEntry) -> FileTransferResult<()> {
let path = Self::fmt_path( let path = Self::fmt_path(
path::diff_paths(file.get_abs_path(), &Path::new("/")) path::diff_paths(file.get_abs_path(), &Path::new("/"))
.unwrap_or_default() .unwrap_or_default()
@@ -397,7 +399,7 @@ impl FileTransfer for S3FileTransfer {
/// ### rename /// ### rename
/// ///
/// Rename file or a directory /// Rename file or a directory
fn rename(&mut self, _file: &FsEntry, _dst: &Path) -> Result<(), FileTransferError> { fn rename(&mut self, _file: &FsEntry, _dst: &Path) -> FileTransferResult<()> {
Err(FileTransferError::new( Err(FileTransferError::new(
FileTransferErrorType::UnsupportedFeature, FileTransferErrorType::UnsupportedFeature,
)) ))
@@ -406,7 +408,7 @@ impl FileTransfer for S3FileTransfer {
/// ### stat /// ### stat
/// ///
/// Stat file and return FsEntry /// Stat file and return FsEntry
fn stat(&mut self, p: &Path) -> Result<FsEntry, FileTransferError> { fn stat(&mut self, p: &Path) -> FileTransferResult<FsEntry> {
match self.is_connected() { match self.is_connected() {
true => { true => {
// First try as a "file" // First try as a "file"
@@ -428,7 +430,7 @@ impl FileTransfer for S3FileTransfer {
/// ### exec /// ### exec
/// ///
/// Execute a command on remote host /// Execute a command on remote host
fn exec(&mut self, _cmd: &str) -> Result<String, FileTransferError> { fn exec(&mut self, _cmd: &str) -> FileTransferResult<String> {
Err(FileTransferError::new( Err(FileTransferError::new(
FileTransferErrorType::UnsupportedFeature, FileTransferErrorType::UnsupportedFeature,
)) ))
@@ -446,7 +448,7 @@ impl FileTransfer for S3FileTransfer {
_src: &FsFile, _src: &FsFile,
dest: &Path, dest: &Path,
mut reader: Box<dyn Read>, mut reader: Box<dyn Read>,
) -> Result<(), FileTransferError> { ) -> FileTransferResult<()> {
match &mut self.bucket { match &mut self.bucket {
Some(bucket) => { Some(bucket) => {
let key = Self::fmt_path(dest, false); let key = Self::fmt_path(dest, false);
@@ -474,7 +476,7 @@ impl FileTransfer for S3FileTransfer {
/// The developer implementing the filetransfer user should FIRST try with `send_file` followed by `on_sent` /// The developer implementing the filetransfer user should FIRST try with `send_file` followed by `on_sent`
/// If the function returns error kind() `UnsupportedFeature`, then he should call this function. /// If the function returns error kind() `UnsupportedFeature`, then he should call this function.
/// By default this function uses the streams function to copy content from reader to writer /// By default this function uses the streams function to copy content from reader to writer
fn recv_file_wno_stream(&mut self, src: &FsFile, dest: &Path) -> Result<(), FileTransferError> { fn recv_file_wno_stream(&mut self, src: &FsFile, dest: &Path) -> FileTransferResult<()> {
match &mut self.bucket { match &mut self.bucket {
Some(bucket) => { Some(bucket) => {
let mut writer = File::create(dest).map_err(|e| { let mut writer = File::create(dest).map_err(|e| {

View File

@@ -26,7 +26,9 @@
* SOFTWARE. * SOFTWARE.
*/ */
// Locals // Locals
use super::{FileTransfer, FileTransferError, FileTransferErrorType, ProtocolParams}; use super::{
FileTransfer, FileTransferError, FileTransferErrorType, FileTransferResult, ProtocolParams,
};
use crate::fs::{FsDirectory, FsEntry, FsFile, UnixPex}; use crate::fs::{FsDirectory, FsEntry, FsFile, UnixPex};
use crate::system::sshkey_storage::SshKeyStorage; use crate::system::sshkey_storage::SshKeyStorage;
use crate::utils::fmt::{fmt_time, shadow_password}; use crate::utils::fmt::{fmt_time, shadow_password};
@@ -278,7 +280,7 @@ impl ScpFileTransfer {
&mut self, &mut self,
path: &Path, path: &Path,
cmd: &str, cmd: &str,
) -> Result<String, FileTransferError> { ) -> FileTransferResult<String> {
self.perform_shell_cmd(format!("cd \"{}\"; {}", path.display(), cmd).as_str()) self.perform_shell_cmd(format!("cd \"{}\"; {}", path.display(), cmd).as_str())
} }
@@ -286,7 +288,7 @@ impl ScpFileTransfer {
/// ///
/// Perform a shell command and read the output from shell /// Perform a shell command and read the output from shell
/// This operation is, obviously, blocking. /// This operation is, obviously, blocking.
fn perform_shell_cmd(&mut self, cmd: &str) -> Result<String, FileTransferError> { fn perform_shell_cmd(&mut self, cmd: &str) -> FileTransferResult<String> {
match self.session.as_mut() { match self.session.as_mut() {
Some(session) => { Some(session) => {
debug!("Running command: {}", cmd); debug!("Running command: {}", cmd);
@@ -333,7 +335,7 @@ impl FileTransfer for ScpFileTransfer {
/// ### connect /// ### connect
/// ///
/// Connect to the remote server /// Connect to the remote server
fn connect(&mut self, params: &ProtocolParams) -> Result<Option<String>, FileTransferError> { fn connect(&mut self, params: &ProtocolParams) -> FileTransferResult<Option<String>> {
let params = match params.generic_params() { let params = match params.generic_params() {
Some(params) => params, Some(params) => params,
None => return Err(FileTransferError::new(FileTransferErrorType::BadAddress)), None => return Err(FileTransferError::new(FileTransferErrorType::BadAddress)),
@@ -472,7 +474,7 @@ impl FileTransfer for ScpFileTransfer {
/// ### disconnect /// ### disconnect
/// ///
/// Disconnect from the remote server /// Disconnect from the remote server
fn disconnect(&mut self) -> Result<(), FileTransferError> { fn disconnect(&mut self) -> FileTransferResult<()> {
info!("Disconnecting from remote..."); info!("Disconnecting from remote...");
match self.session.as_ref() { match self.session.as_ref() {
Some(session) => { Some(session) => {
@@ -506,7 +508,7 @@ impl FileTransfer for ScpFileTransfer {
/// ///
/// Print working directory /// Print working directory
fn pwd(&mut self) -> Result<PathBuf, FileTransferError> { fn pwd(&mut self) -> FileTransferResult<PathBuf> {
info!("PWD: {}", self.wrkdir.display()); info!("PWD: {}", self.wrkdir.display());
match self.is_connected() { match self.is_connected() {
true => Ok(self.wrkdir.clone()), true => Ok(self.wrkdir.clone()),
@@ -520,7 +522,7 @@ impl FileTransfer for ScpFileTransfer {
/// ///
/// Change working directory /// Change working directory
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError> { fn change_dir(&mut self, dir: &Path) -> FileTransferResult<PathBuf> {
match self.is_connected() { match self.is_connected() {
true => { true => {
let p: PathBuf = self.wrkdir.clone(); let p: PathBuf = self.wrkdir.clone();
@@ -564,7 +566,7 @@ impl FileTransfer for ScpFileTransfer {
/// ### copy /// ### copy
/// ///
/// Copy file to destination /// Copy file to destination
fn copy(&mut self, src: &FsEntry, dst: &Path) -> Result<(), FileTransferError> { fn copy(&mut self, src: &FsEntry, dst: &Path) -> FileTransferResult<()> {
match self.is_connected() { match self.is_connected() {
true => { true => {
let dst: PathBuf = Self::resolve(dst); let dst: PathBuf = Self::resolve(dst);
@@ -612,7 +614,7 @@ impl FileTransfer for ScpFileTransfer {
/// ///
/// List directory entries /// List directory entries
fn list_dir(&mut self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError> { fn list_dir(&mut self, path: &Path) -> FileTransferResult<Vec<FsEntry>> {
match self.is_connected() { match self.is_connected() {
true => { true => {
// Send ls -l to path // Send ls -l to path
@@ -657,7 +659,7 @@ impl FileTransfer for ScpFileTransfer {
/// ///
/// Make directory /// Make directory
/// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists` /// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists`
fn mkdir(&mut self, dir: &Path) -> Result<(), FileTransferError> { fn mkdir(&mut self, dir: &Path) -> FileTransferResult<()> {
match self.is_connected() { match self.is_connected() {
true => { true => {
let dir: PathBuf = Self::resolve(dir); let dir: PathBuf = Self::resolve(dir);
@@ -703,7 +705,7 @@ impl FileTransfer for ScpFileTransfer {
/// ### remove /// ### remove
/// ///
/// Remove a file or a directory /// Remove a file or a directory
fn remove(&mut self, file: &FsEntry) -> Result<(), FileTransferError> { fn remove(&mut self, file: &FsEntry) -> FileTransferResult<()> {
// Yay, we have rm -rf here :D // Yay, we have rm -rf here :D
match self.is_connected() { match self.is_connected() {
true => { true => {
@@ -741,7 +743,7 @@ impl FileTransfer for ScpFileTransfer {
/// ### rename /// ### rename
/// ///
/// Rename file or a directory /// Rename file or a directory
fn rename(&mut self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> { fn rename(&mut self, file: &FsEntry, dst: &Path) -> FileTransferResult<()> {
match self.is_connected() { match self.is_connected() {
true => { true => {
// Get path // Get path
@@ -784,7 +786,7 @@ impl FileTransfer for ScpFileTransfer {
/// ### stat /// ### stat
/// ///
/// Stat file and return FsEntry /// Stat file and return FsEntry
fn stat(&mut self, path: &Path) -> Result<FsEntry, FileTransferError> { fn stat(&mut self, path: &Path) -> FileTransferResult<FsEntry> {
let path: PathBuf = Self::absolutize(self.wrkdir.as_path(), path); let path: PathBuf = Self::absolutize(self.wrkdir.as_path(), path);
match self.is_connected() { match self.is_connected() {
true => { true => {
@@ -829,7 +831,7 @@ impl FileTransfer for ScpFileTransfer {
/// ### exec /// ### exec
/// ///
/// Execute a command on remote host /// Execute a command on remote host
fn exec(&mut self, cmd: &str) -> Result<String, FileTransferError> { fn exec(&mut self, cmd: &str) -> FileTransferResult<String> {
match self.is_connected() { match self.is_connected() {
true => { true => {
let p: PathBuf = self.wrkdir.clone(); let p: PathBuf = self.wrkdir.clone();
@@ -858,7 +860,7 @@ impl FileTransfer for ScpFileTransfer {
&mut self, &mut self,
local: &FsFile, local: &FsFile,
file_name: &Path, file_name: &Path,
) -> Result<Box<dyn Write>, FileTransferError> { ) -> FileTransferResult<Box<dyn Write>> {
match self.session.as_ref() { match self.session.as_ref() {
Some(session) => { Some(session) => {
let file_name: PathBuf = Self::absolutize(self.wrkdir.as_path(), file_name); let file_name: PathBuf = Self::absolutize(self.wrkdir.as_path(), file_name);
@@ -925,7 +927,7 @@ impl FileTransfer for ScpFileTransfer {
/// ///
/// Receive file from remote with provided name /// Receive file from remote with provided name
/// Returns file and its size /// Returns file and its size
fn recv_file(&mut self, file: &FsFile) -> Result<Box<dyn Read>, FileTransferError> { fn recv_file(&mut self, file: &FsFile) -> FileTransferResult<Box<dyn Read>> {
match self.session.as_ref() { match self.session.as_ref() {
Some(session) => { Some(session) => {
info!("Receiving file {}", file.abs_path.display()); info!("Receiving file {}", file.abs_path.display());

View File

@@ -26,7 +26,9 @@
* SOFTWARE. * SOFTWARE.
*/ */
// Locals // Locals
use super::{FileTransfer, FileTransferError, FileTransferErrorType, ProtocolParams}; use super::{
FileTransfer, FileTransferError, FileTransferErrorType, FileTransferResult, ProtocolParams,
};
use crate::fs::{FsDirectory, FsEntry, FsFile, UnixPex}; use crate::fs::{FsDirectory, FsEntry, FsFile, UnixPex};
use crate::system::sshkey_storage::SshKeyStorage; use crate::system::sshkey_storage::SshKeyStorage;
use crate::utils::fmt::{fmt_time, shadow_password}; use crate::utils::fmt::{fmt_time, shadow_password};
@@ -64,7 +66,7 @@ impl SftpFileTransfer {
/// ### get_abs_path /// ### get_abs_path
/// ///
/// Get absolute path from path argument and check if it exists /// Get absolute path from path argument and check if it exists
fn get_remote_path(&self, p: &Path) -> Result<PathBuf, FileTransferError> { fn get_remote_path(&self, p: &Path) -> FileTransferResult<PathBuf> {
match p.is_relative() { match p.is_relative() {
true => { true => {
let mut root: PathBuf = self.wrkdir.clone(); let mut root: PathBuf = self.wrkdir.clone();
@@ -202,7 +204,7 @@ impl SftpFileTransfer {
/// ### perform_shell_cmd_with /// ### perform_shell_cmd_with
/// ///
/// Perform a shell command, but change directory to specified path first /// Perform a shell command, but change directory to specified path first
fn perform_shell_cmd_with_path(&mut self, cmd: &str) -> Result<String, FileTransferError> { fn perform_shell_cmd_with_path(&mut self, cmd: &str) -> FileTransferResult<String> {
self.perform_shell_cmd(format!("cd \"{}\"; {}", self.wrkdir.display(), cmd).as_str()) self.perform_shell_cmd(format!("cd \"{}\"; {}", self.wrkdir.display(), cmd).as_str())
} }
@@ -210,7 +212,7 @@ impl SftpFileTransfer {
/// ///
/// Perform a shell command and read the output from shell /// Perform a shell command and read the output from shell
/// This operation is, obviously, blocking. /// This operation is, obviously, blocking.
fn perform_shell_cmd(&mut self, cmd: &str) -> Result<String, FileTransferError> { fn perform_shell_cmd(&mut self, cmd: &str) -> FileTransferResult<String> {
match self.session.as_mut() { match self.session.as_mut() {
Some(session) => { Some(session) => {
// Create channel // Create channel
@@ -257,7 +259,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### connect /// ### connect
/// ///
/// Connect to the remote server /// Connect to the remote server
fn connect(&mut self, params: &ProtocolParams) -> Result<Option<String>, FileTransferError> { fn connect(&mut self, params: &ProtocolParams) -> FileTransferResult<Option<String>> {
let params = match params.generic_params() { let params = match params.generic_params() {
Some(params) => params, Some(params) => params,
None => return Err(FileTransferError::new(FileTransferErrorType::BadAddress)), None => return Err(FileTransferError::new(FileTransferErrorType::BadAddress)),
@@ -413,7 +415,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### disconnect /// ### disconnect
/// ///
/// Disconnect from the remote server /// Disconnect from the remote server
fn disconnect(&mut self) -> Result<(), FileTransferError> { fn disconnect(&mut self) -> FileTransferResult<()> {
info!("Disconnecting from remote..."); info!("Disconnecting from remote...");
match self.session.as_ref() { match self.session.as_ref() {
Some(session) => { Some(session) => {
@@ -447,7 +449,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### pwd /// ### pwd
/// ///
/// Print working directory /// Print working directory
fn pwd(&mut self) -> Result<PathBuf, FileTransferError> { fn pwd(&mut self) -> FileTransferResult<PathBuf> {
info!("PWD: {}", self.wrkdir.display()); info!("PWD: {}", self.wrkdir.display());
match self.sftp { match self.sftp {
Some(_) => Ok(self.wrkdir.clone()), Some(_) => Ok(self.wrkdir.clone()),
@@ -460,7 +462,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### change_dir /// ### change_dir
/// ///
/// Change working directory /// Change working directory
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError> { fn change_dir(&mut self, dir: &Path) -> FileTransferResult<PathBuf> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
Some(_) => { Some(_) => {
// Change working directory // Change working directory
@@ -477,7 +479,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### copy /// ### copy
/// ///
/// Copy file to destination /// Copy file to destination
fn copy(&mut self, src: &FsEntry, dst: &Path) -> Result<(), FileTransferError> { fn copy(&mut self, src: &FsEntry, dst: &Path) -> FileTransferResult<()> {
// NOTE: use SCP command to perform copy (UNSAFE) // NOTE: use SCP command to perform copy (UNSAFE)
match self.is_connected() { match self.is_connected() {
true => { true => {
@@ -523,7 +525,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### list_dir /// ### list_dir
/// ///
/// List directory entries /// List directory entries
fn list_dir(&mut self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError> { fn list_dir(&mut self, path: &Path) -> FileTransferResult<Vec<FsEntry>> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
Some(sftp) => { Some(sftp) => {
// Get path // Get path
@@ -556,7 +558,7 @@ impl FileTransfer for SftpFileTransfer {
/// ///
/// Make directory /// Make directory
/// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists` /// In case the directory already exists, it must return an Error of kind `FileTransferErrorType::DirectoryAlreadyExists`
fn mkdir(&mut self, dir: &Path) -> Result<(), FileTransferError> { fn mkdir(&mut self, dir: &Path) -> FileTransferResult<()> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
Some(sftp) => { Some(sftp) => {
// Make directory // Make directory
@@ -586,7 +588,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### remove /// ### remove
/// ///
/// Remove a file or a directory /// Remove a file or a directory
fn remove(&mut self, file: &FsEntry) -> Result<(), FileTransferError> { fn remove(&mut self, file: &FsEntry) -> FileTransferResult<()> {
if self.sftp.is_none() { if self.sftp.is_none() {
return Err(FileTransferError::new( return Err(FileTransferError::new(
FileTransferErrorType::UninitializedSession, FileTransferErrorType::UninitializedSession,
@@ -630,7 +632,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### rename /// ### rename
/// ///
/// Rename file or a directory /// Rename file or a directory
fn rename(&mut self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> { fn rename(&mut self, file: &FsEntry, dst: &Path) -> FileTransferResult<()> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
None => Err(FileTransferError::new( None => Err(FileTransferError::new(
FileTransferErrorType::UninitializedSession, FileTransferErrorType::UninitializedSession,
@@ -659,7 +661,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### stat /// ### stat
/// ///
/// Stat file and return FsEntry /// Stat file and return FsEntry
fn stat(&mut self, path: &Path) -> Result<FsEntry, FileTransferError> { fn stat(&mut self, path: &Path) -> FileTransferResult<FsEntry> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
Some(sftp) => { Some(sftp) => {
// Get path // Get path
@@ -683,7 +685,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### exec /// ### exec
/// ///
/// Execute a command on remote host /// Execute a command on remote host
fn exec(&mut self, cmd: &str) -> Result<String, FileTransferError> { fn exec(&mut self, cmd: &str) -> FileTransferResult<String> {
info!("Executing command {}", cmd); info!("Executing command {}", cmd);
match self.is_connected() { match self.is_connected() {
true => match self.perform_shell_cmd_with_path(cmd) { true => match self.perform_shell_cmd_with_path(cmd) {
@@ -708,7 +710,7 @@ impl FileTransfer for SftpFileTransfer {
&mut self, &mut self,
local: &FsFile, local: &FsFile,
file_name: &Path, file_name: &Path,
) -> Result<Box<dyn Write>, FileTransferError> { ) -> FileTransferResult<Box<dyn Write>> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
None => Err(FileTransferError::new( None => Err(FileTransferError::new(
FileTransferErrorType::UninitializedSession, FileTransferErrorType::UninitializedSession,
@@ -749,7 +751,7 @@ impl FileTransfer for SftpFileTransfer {
/// ### recv_file /// ### recv_file
/// ///
/// Receive file from remote with provided name /// Receive file from remote with provided name
fn recv_file(&mut self, file: &FsFile) -> Result<Box<dyn Read>, FileTransferError> { fn recv_file(&mut self, file: &FsFile) -> FileTransferResult<Box<dyn Read>> {
match self.sftp.as_ref() { match self.sftp.as_ref() {
None => Err(FileTransferError::new( None => Err(FileTransferError::new(
FileTransferErrorType::UninitializedSession, FileTransferErrorType::UninitializedSession,