mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
Fix remote paths for Windows
This commit is contained in:
@@ -21,6 +21,9 @@ Released on FIXME:
|
||||
|
||||
- Bugfix:
|
||||
- [Issue 10](https://github.com/veeso/termscp/issues/10): Fixed port not being loaded from bookmarks into gui
|
||||
- [Issue 9](https://github.com/veeso/termscp/issues/9): Fixed issues related to paths on remote when using Windows
|
||||
- Dependencies:
|
||||
- Added `path-slash 0.1.4` (Windows only)
|
||||
|
||||
## 0.4.0
|
||||
|
||||
|
||||
7
Cargo.lock
generated
7
Cargo.lock
generated
@@ -930,6 +930,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "path-slash"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cacbb3c4ff353b534a67fb8d7524d00229da4cb1dc8c79f4db96e375ab5b619"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
@@ -1397,6 +1403,7 @@ dependencies = [
|
||||
"keyring",
|
||||
"lazy_static",
|
||||
"magic-crypt",
|
||||
"path-slash",
|
||||
"rand 0.8.2",
|
||||
"regex",
|
||||
"rpassword",
|
||||
|
||||
@@ -41,12 +41,18 @@ ureq = { version = "2.0.2", features = ["json"] }
|
||||
whoami = "1.1.0"
|
||||
wildmatch = "1.0.13"
|
||||
|
||||
# POSIX dependencies
|
||||
[target.'cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))'.dependencies]
|
||||
users = "0.11.0"
|
||||
|
||||
# Windows + MacOS
|
||||
[target.'cfg(any(target_os = "windows", target_os = "macos"))'.dependencies]
|
||||
keyring = "0.10.1"
|
||||
|
||||
# Windows dependencies
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
path-slash = "0.1.4"
|
||||
|
||||
# Features
|
||||
[features]
|
||||
githubActions = [] # used to run particular on github actions
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
// Dependencies
|
||||
extern crate chrono;
|
||||
extern crate ftp4;
|
||||
#[cfg(os_target = "windows")]
|
||||
extern crate path_slash;
|
||||
extern crate regex;
|
||||
|
||||
use super::{FileTransfer, FileTransferError, FileTransferErrorType};
|
||||
@@ -61,6 +63,20 @@ impl FtpFileTransfer {
|
||||
FtpFileTransfer { stream: None, ftps }
|
||||
}
|
||||
|
||||
/// ### resolve
|
||||
///
|
||||
/// Fix provided path; on Windows fixes the backslashes, converting them to slashes
|
||||
/// While on POSIX does nothing
|
||||
#[cfg(target_os = "windows")]
|
||||
fn resolve(p: &Path) -> PathBuf {
|
||||
PathBuf::from(path_slash::PathExt::to_slash_lossy(p).as_str())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
fn resolve(p: &Path) -> PathBuf {
|
||||
p.to_path_buf()
|
||||
}
|
||||
|
||||
/// ### parse_list_line
|
||||
///
|
||||
/// Parse a line of LIST command output and instantiates an FsEntry from it
|
||||
@@ -165,6 +181,7 @@ impl FtpFileTransfer {
|
||||
}
|
||||
let mut abs_path: PathBuf = PathBuf::from(path);
|
||||
abs_path.push(file_name.as_str());
|
||||
let abs_path: PathBuf = Self::resolve(abs_path.as_path());
|
||||
// get extension
|
||||
let extension: Option<String> = abs_path
|
||||
.as_path()
|
||||
@@ -253,6 +270,7 @@ impl FtpFileTransfer {
|
||||
// Get absolute path
|
||||
let mut abs_path: PathBuf = PathBuf::from(path);
|
||||
abs_path.push(file_name.as_str());
|
||||
let abs_path: PathBuf = Self::resolve(abs_path.as_path());
|
||||
// Get extension
|
||||
let extension: Option<String> = abs_path
|
||||
.as_path()
|
||||
@@ -411,9 +429,10 @@ impl FileTransfer for FtpFileTransfer {
|
||||
/// Change working directory
|
||||
|
||||
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError> {
|
||||
let dir: PathBuf = Self::resolve(dir);
|
||||
match &mut self.stream {
|
||||
Some(stream) => match stream.cwd(&dir.to_string_lossy()) {
|
||||
Ok(_) => Ok(PathBuf::from(dir)),
|
||||
Some(stream) => match stream.cwd(&dir.as_path().to_string_lossy()) {
|
||||
Ok(_) => Ok(dir),
|
||||
Err(err) => Err(FileTransferError::new_ex(
|
||||
FileTransferErrorType::ConnectionError,
|
||||
format!("{}", err),
|
||||
@@ -440,14 +459,15 @@ impl FileTransfer for FtpFileTransfer {
|
||||
/// List directory entries
|
||||
|
||||
fn list_dir(&mut self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError> {
|
||||
let dir: PathBuf = Self::resolve(path);
|
||||
match &mut self.stream {
|
||||
Some(stream) => match stream.list(Some(&path.to_string_lossy())) {
|
||||
Some(stream) => match stream.list(Some(&dir.as_path().to_string_lossy())) {
|
||||
Ok(entries) => {
|
||||
// Prepare result
|
||||
let mut result: Vec<FsEntry> = Vec::with_capacity(entries.len());
|
||||
// Iterate over entries
|
||||
for entry in entries.iter() {
|
||||
if let Ok(file) = self.parse_list_line(path, entry) {
|
||||
if let Ok(file) = self.parse_list_line(dir.as_path(), entry) {
|
||||
result.push(file);
|
||||
}
|
||||
}
|
||||
@@ -468,8 +488,9 @@ impl FileTransfer for FtpFileTransfer {
|
||||
///
|
||||
/// Make directory
|
||||
fn mkdir(&mut self, dir: &Path) -> Result<(), FileTransferError> {
|
||||
let dir: PathBuf = Self::resolve(dir);
|
||||
match &mut self.stream {
|
||||
Some(stream) => match stream.mkdir(&dir.to_string_lossy()) {
|
||||
Some(stream) => match stream.mkdir(&dir.as_path().to_string_lossy()) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(err) => Err(FileTransferError::new_ex(
|
||||
FileTransferErrorType::FileCreateDenied,
|
||||
@@ -538,6 +559,7 @@ impl FileTransfer for FtpFileTransfer {
|
||||
///
|
||||
/// Rename file or a directory
|
||||
fn rename(&mut self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> {
|
||||
let dst: PathBuf = Self::resolve(dst);
|
||||
match &mut self.stream {
|
||||
Some(stream) => {
|
||||
// Get name
|
||||
@@ -603,8 +625,9 @@ impl FileTransfer for FtpFileTransfer {
|
||||
_local: &FsFile,
|
||||
file_name: &Path,
|
||||
) -> Result<Box<dyn Write>, FileTransferError> {
|
||||
let file_name: PathBuf = Self::resolve(file_name);
|
||||
match &mut self.stream {
|
||||
Some(stream) => match stream.put_with_stream(&file_name.to_string_lossy()) {
|
||||
Some(stream) => match stream.put_with_stream(&file_name.as_path().to_string_lossy()) {
|
||||
Ok(writer) => Ok(Box::new(writer)), // NOTE: don't use BufWriter here, since already returned by the library
|
||||
Err(err) => Err(FileTransferError::new_ex(
|
||||
FileTransferErrorType::FileCreateDenied,
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
// Dependencies
|
||||
#[cfg(os_target = "windows")]
|
||||
extern crate path_slash;
|
||||
extern crate regex;
|
||||
extern crate ssh2;
|
||||
|
||||
@@ -65,6 +67,20 @@ impl ScpFileTransfer {
|
||||
}
|
||||
}
|
||||
|
||||
/// ### resolve
|
||||
///
|
||||
/// Fix provided path; on Windows fixes the backslashes, converting them to slashes
|
||||
/// While on POSIX does nothing
|
||||
#[cfg(target_os = "windows")]
|
||||
fn resolve(p: &Path) -> PathBuf {
|
||||
PathBuf::from(path_slash::PathExt::to_slash_lossy(p).as_str())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
fn resolve(p: &Path) -> PathBuf {
|
||||
p.to_path_buf()
|
||||
}
|
||||
|
||||
/// ### parse_ls_output
|
||||
///
|
||||
/// Parse a line of `ls -l` output and tokenize the output into a `FsEntry`
|
||||
@@ -174,6 +190,7 @@ impl ScpFileTransfer {
|
||||
}
|
||||
let mut abs_path: PathBuf = PathBuf::from(path);
|
||||
abs_path.push(file_name.as_str());
|
||||
let abs_path: PathBuf = Self::resolve(abs_path.as_path());
|
||||
// Get extension
|
||||
let extension: Option<String> = abs_path
|
||||
.as_path()
|
||||
@@ -448,7 +465,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
false => {
|
||||
let mut p: PathBuf = PathBuf::from(".");
|
||||
p.push(dir);
|
||||
p
|
||||
Self::resolve(p.as_path())
|
||||
}
|
||||
};
|
||||
// Change directory
|
||||
@@ -491,6 +508,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
fn copy(&mut self, src: &FsEntry, dst: &Path) -> Result<(), FileTransferError> {
|
||||
match self.is_connected() {
|
||||
true => {
|
||||
let dst: PathBuf = Self::resolve(dst);
|
||||
// Run `cp -rf`
|
||||
let p: PathBuf = self.wrkdir.clone();
|
||||
match self.perform_shell_cmd_with_path(
|
||||
@@ -534,6 +552,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
match self.is_connected() {
|
||||
true => {
|
||||
// Send ls -l to path
|
||||
let path: PathBuf = Self::resolve(path);
|
||||
let p: PathBuf = self.wrkdir.clone();
|
||||
match self.perform_shell_cmd_with_path(
|
||||
p.as_path(),
|
||||
@@ -546,7 +565,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
for line in lines.iter() {
|
||||
// First line must always be ignored
|
||||
// Parse row, if ok push to entries
|
||||
if let Ok(entry) = self.parse_ls_output(path, line) {
|
||||
if let Ok(entry) = self.parse_ls_output(path.as_path(), line) {
|
||||
entries.push(entry);
|
||||
}
|
||||
}
|
||||
@@ -571,6 +590,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
fn mkdir(&mut self, dir: &Path) -> Result<(), FileTransferError> {
|
||||
match self.is_connected() {
|
||||
true => {
|
||||
let dir: PathBuf = Self::resolve(dir);
|
||||
let p: PathBuf = self.wrkdir.clone();
|
||||
// Mkdir dir && echo 0
|
||||
match self.perform_shell_cmd_with_path(
|
||||
@@ -644,6 +664,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
match self.is_connected() {
|
||||
true => {
|
||||
// Get path
|
||||
let dst: PathBuf = Self::resolve(dst);
|
||||
let path: PathBuf = file.get_abs_path();
|
||||
let p: PathBuf = self.wrkdir.clone();
|
||||
match self.perform_shell_cmd_with_path(
|
||||
@@ -693,7 +714,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
false => {
|
||||
let mut p: PathBuf = self.wrkdir.clone();
|
||||
p.push(path);
|
||||
p
|
||||
Self::resolve(p.as_path())
|
||||
}
|
||||
};
|
||||
match self.is_connected() {
|
||||
@@ -767,6 +788,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
) -> Result<Box<dyn Write>, FileTransferError> {
|
||||
match self.session.as_ref() {
|
||||
Some(session) => {
|
||||
let file_name: PathBuf = Self::resolve(file_name);
|
||||
// Set blocking to true
|
||||
session.set_blocking(true);
|
||||
// Calculate file mode
|
||||
@@ -798,7 +820,7 @@ impl FileTransfer for ScpFileTransfer {
|
||||
Err(_) => local.size as u64, // NOTE: fallback to fsentry size
|
||||
};
|
||||
// Send file
|
||||
match session.scp_send(file_name, mode, file_size, Some(times)) {
|
||||
match session.scp_send(file_name.as_path(), mode, file_size, Some(times)) {
|
||||
Ok(channel) => Ok(Box::new(BufWriter::with_capacity(65536, channel))),
|
||||
Err(err) => Err(FileTransferError::new_ex(
|
||||
FileTransferErrorType::ProtocolError,
|
||||
@@ -1053,7 +1075,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
//#[cfg(any(target_os = "unix", target_os = "macos", target_os = "linux"))]
|
||||
fn test_filetransfer_scp_find() {
|
||||
let mut client: ScpFileTransfer = ScpFileTransfer::new(SshKeyStorage::empty());
|
||||
assert!(client
|
||||
|
||||
Reference in New Issue
Block a user