mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
File transfer exec command
This commit is contained in:
@@ -581,6 +581,15 @@ impl FileTransfer for FtpFileTransfer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ### exec
|
||||||
|
///
|
||||||
|
/// Execute a command on remote host
|
||||||
|
fn exec(&mut self, _cmd: &str) -> Result<String, FileTransferError> {
|
||||||
|
Err(FileTransferError::new(
|
||||||
|
FileTransferErrorType::UnsupportedFeature,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
/// ### send_file
|
/// ### send_file
|
||||||
///
|
///
|
||||||
/// Send file to remote
|
/// Send file to remote
|
||||||
@@ -1068,6 +1077,19 @@ mod tests {
|
|||||||
assert!(ftp.disconnect().is_ok());
|
assert!(ftp.disconnect().is_ok());
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_filetransfer_ftp_exec() {
|
||||||
|
let mut ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||||
|
// Connect
|
||||||
|
assert!(ftp
|
||||||
|
.connect(String::from("speedtest.tele2.net"), 21, None, None)
|
||||||
|
.is_ok());
|
||||||
|
// Pwd
|
||||||
|
assert!(ftp.exec("echo 1;").is_err());
|
||||||
|
// Disconnect
|
||||||
|
assert!(ftp.disconnect().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_filetransfer_ftp_uninitialized() {
|
fn test_filetransfer_ftp_uninitialized() {
|
||||||
let file: FsFile = FsFile {
|
let file: FsFile = FsFile {
|
||||||
|
|||||||
@@ -189,6 +189,11 @@ pub trait FileTransfer {
|
|||||||
/// 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) -> Result<FsEntry, FileTransferError>;
|
||||||
|
|
||||||
|
/// ### exec
|
||||||
|
///
|
||||||
|
/// Execute a command on remote host
|
||||||
|
fn exec(&mut self, cmd: &str) -> Result<String, FileTransferError>;
|
||||||
|
|
||||||
/// ### send_file
|
/// ### send_file
|
||||||
///
|
///
|
||||||
/// Send file to remote
|
/// Send file to remote
|
||||||
|
|||||||
@@ -737,6 +737,27 @@ impl FileTransfer for ScpFileTransfer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ### exec
|
||||||
|
///
|
||||||
|
/// Execute a command on remote host
|
||||||
|
fn exec(&mut self, cmd: &str) -> Result<String, FileTransferError> {
|
||||||
|
match self.is_connected() {
|
||||||
|
true => {
|
||||||
|
let p: PathBuf = self.wrkdir.clone();
|
||||||
|
match self.perform_shell_cmd_with_path(p.as_path(), cmd) {
|
||||||
|
Ok(output) => Ok(output),
|
||||||
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::ProtocolError,
|
||||||
|
format!("{}", err),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false => Err(FileTransferError::new(
|
||||||
|
FileTransferErrorType::UninitializedSession,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// ### send_file
|
/// ### send_file
|
||||||
///
|
///
|
||||||
/// Send file to remote
|
/// Send file to remote
|
||||||
@@ -1016,6 +1037,25 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_filetransfer_scp_exec() {
|
||||||
|
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||||
|
assert!(client
|
||||||
|
.connect(
|
||||||
|
String::from("test.rebex.net"),
|
||||||
|
22,
|
||||||
|
Some(String::from("demo")),
|
||||||
|
Some(String::from("password"))
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
|
// Check session and scp
|
||||||
|
assert!(client.session.is_some());
|
||||||
|
// Exec
|
||||||
|
assert_eq!(client.exec("echo 5").ok().unwrap().as_str(), "5\n");
|
||||||
|
// Disconnect
|
||||||
|
assert!(client.disconnect().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_filetransfer_scp_recv() {
|
fn test_filetransfer_scp_recv() {
|
||||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ use crate::fs::{FsDirectory, FsEntry, FsFile};
|
|||||||
use crate::system::sshkey_storage::SshKeyStorage;
|
use crate::system::sshkey_storage::SshKeyStorage;
|
||||||
|
|
||||||
// Includes
|
// Includes
|
||||||
use ssh2::{FileStat, OpenFlags, OpenType, Session, Sftp};
|
use ssh2::{Channel, FileStat, OpenFlags, OpenType, Session, Sftp};
|
||||||
use std::io::{BufReader, BufWriter, Read, Write};
|
use std::io::{BufReader, BufWriter, Read, Write};
|
||||||
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
|
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@@ -189,6 +189,57 @@ impl SftpFileTransfer {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ### perform_shell_cmd_with
|
||||||
|
///
|
||||||
|
/// Perform a shell command, but change directory to specified path first
|
||||||
|
fn perform_shell_cmd_with_path(&mut self, cmd: &str) -> Result<String, FileTransferError> {
|
||||||
|
self.perform_shell_cmd(format!("cd \"{}\"; {}", self.wrkdir.display(), cmd).as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ### perform_shell_cmd
|
||||||
|
///
|
||||||
|
/// Perform a shell command and read the output from shell
|
||||||
|
/// This operation is, obviously, blocking.
|
||||||
|
fn perform_shell_cmd(&mut self, cmd: &str) -> Result<String, FileTransferError> {
|
||||||
|
match self.session.as_mut() {
|
||||||
|
Some(session) => {
|
||||||
|
// Create channel
|
||||||
|
let mut channel: Channel = match session.channel_session() {
|
||||||
|
Ok(ch) => ch,
|
||||||
|
Err(err) => {
|
||||||
|
return Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::ProtocolError,
|
||||||
|
format!("Could not open channel: {}", err),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Execute command
|
||||||
|
if let Err(err) = channel.exec(cmd) {
|
||||||
|
return Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::ProtocolError,
|
||||||
|
format!("Could not execute command \"{}\": {}", cmd, err),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// Read output
|
||||||
|
let mut output: String = String::new();
|
||||||
|
match channel.read_to_string(&mut output) {
|
||||||
|
Ok(_) => {
|
||||||
|
// Wait close
|
||||||
|
let _ = channel.wait_close();
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::ProtocolError,
|
||||||
|
format!("Could not read output: {}", err),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => Err(FileTransferError::new(
|
||||||
|
FileTransferErrorType::UninitializedSession,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileTransfer for SftpFileTransfer {
|
impl FileTransfer for SftpFileTransfer {
|
||||||
@@ -547,6 +598,26 @@ impl FileTransfer for SftpFileTransfer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ### exec
|
||||||
|
///
|
||||||
|
/// Execute a command on remote host
|
||||||
|
fn exec(&mut self, cmd: &str) -> Result<String, FileTransferError> {
|
||||||
|
match self.is_connected() {
|
||||||
|
true => {
|
||||||
|
match self.perform_shell_cmd_with_path(cmd) {
|
||||||
|
Ok(output) => Ok(output),
|
||||||
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::ProtocolError,
|
||||||
|
format!("{}", err),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false => Err(FileTransferError::new(
|
||||||
|
FileTransferErrorType::UninitializedSession,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// ### send_file
|
/// ### send_file
|
||||||
///
|
///
|
||||||
/// Send file to remote
|
/// Send file to remote
|
||||||
@@ -856,6 +927,25 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_filetransfer_sftp_exec() {
|
||||||
|
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||||
|
assert!(client
|
||||||
|
.connect(
|
||||||
|
String::from("test.rebex.net"),
|
||||||
|
22,
|
||||||
|
Some(String::from("demo")),
|
||||||
|
Some(String::from("password"))
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
|
// Check session and scp
|
||||||
|
assert!(client.session.is_some());
|
||||||
|
// Exec
|
||||||
|
assert_eq!(client.exec("echo 5").ok().unwrap().as_str(), "5\n");
|
||||||
|
// Disconnect
|
||||||
|
assert!(client.disconnect().is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_filetransfer_sftp_recv() {
|
fn test_filetransfer_sftp_recv() {
|
||||||
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
let mut client: SftpFileTransfer = SftpFileTransfer::new(SshKeyStorage::empty());
|
||||||
|
|||||||
Reference in New Issue
Block a user