mirror of
https://github.com/veeso/termscp.git
synced 2025-12-07 09:36:00 -08:00
ftp transfer: mkdir, remove rename
This commit is contained in:
@@ -107,7 +107,7 @@ TODO:
|
|||||||
## Upcoming Features
|
## Upcoming Features
|
||||||
|
|
||||||
- **File viewer**: possibility to show in a popup the file content from the explorer.
|
- **File viewer**: possibility to show in a popup the file content from the explorer.
|
||||||
- **Replacement of OpenSSL**: OpenSSL is kinda an annoying stuff, especially for Windows. Unfortunately rust-ftp requires OpenSSL to build. I'm working on replacing it on [rust-fpt](https://github.com/ChristianVisintin/rust-ftp/tree/rust-tls). If you want to give me a hand, feel free to contribute.
|
- **OpenSSL Replacement**: OpenSSL is kinda an annoying stuff, especially for Windows. Unfortunately rust-ftp requires OpenSSL to build. I'm working on replacing it on [rust-ftp](https://github.com/ChristianVisintin/rust-ftp/tree/rust-tls). If you want to give me a hand, feel free to contribute.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ impl FileTransfer for FtpFileTransfer {
|
|||||||
|
|
||||||
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError> {
|
fn change_dir(&mut self, dir: &Path) -> Result<PathBuf, FileTransferError> {
|
||||||
match self.stream {
|
match self.stream {
|
||||||
Some(stream) => match stream.cwd(&dir.as_os_str().to_string_lossy()) {
|
Some(stream) => match stream.cwd(&dir.to_string_lossy()) {
|
||||||
Ok(_) => Ok(PathBuf::from(dir)),
|
Ok(_) => Ok(PathBuf::from(dir)),
|
||||||
Err(err) => Err(FileTransferError::new_ex(
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
FileTransferErrorType::ConnectionError,
|
FileTransferErrorType::ConnectionError,
|
||||||
@@ -341,7 +341,7 @@ impl FileTransfer for FtpFileTransfer {
|
|||||||
|
|
||||||
fn list_dir(&self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError> {
|
fn list_dir(&self, path: &Path) -> Result<Vec<FsEntry>, FileTransferError> {
|
||||||
match self.stream {
|
match self.stream {
|
||||||
Some(stream) => match stream.list(Some(&path.as_os_str().to_string_lossy())) {
|
Some(stream) => match stream.list(Some(&path.to_string_lossy())) {
|
||||||
Ok(entries) => {
|
Ok(entries) => {
|
||||||
// Prepare result
|
// Prepare result
|
||||||
let mut result: Vec<FsEntry> = Vec::with_capacity(entries.len());
|
let mut result: Vec<FsEntry> = Vec::with_capacity(entries.len());
|
||||||
@@ -369,7 +369,13 @@ impl FileTransfer for FtpFileTransfer {
|
|||||||
/// Make directory
|
/// Make directory
|
||||||
fn mkdir(&self, dir: &Path) -> Result<(), FileTransferError> {
|
fn mkdir(&self, dir: &Path) -> Result<(), FileTransferError> {
|
||||||
match self.stream {
|
match self.stream {
|
||||||
Some(stream) => {}
|
Some(stream) => match stream.mkdir(&dir.to_string_lossy()) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::DirStatFailed,
|
||||||
|
format!("{}", err),
|
||||||
|
)),
|
||||||
|
},
|
||||||
None => Err(FileTransferError::new(
|
None => Err(FileTransferError::new(
|
||||||
FileTransferErrorType::UninitializedSession,
|
FileTransferErrorType::UninitializedSession,
|
||||||
)),
|
)),
|
||||||
@@ -379,9 +385,49 @@ impl FileTransfer for FtpFileTransfer {
|
|||||||
/// ### remove
|
/// ### remove
|
||||||
///
|
///
|
||||||
/// Remove a file or a directory
|
/// Remove a file or a directory
|
||||||
fn remove(&self, file: &FsEntry) -> Result<(), FileTransferError> {
|
fn remove(&self, fsentry: &FsEntry) -> Result<(), FileTransferError> {
|
||||||
match self.stream {
|
match self.stream {
|
||||||
Some(stream) => {}
|
Some(stream) => match fsentry {
|
||||||
|
// Match fs entry...
|
||||||
|
FsEntry::File(file) => {
|
||||||
|
// Remove file directly
|
||||||
|
match stream.rm(file.name.as_ref()) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::DirStatFailed,
|
||||||
|
format!("{}", err),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FsEntry::Directory(dir) => {
|
||||||
|
// Get directory files
|
||||||
|
match self.list_dir(dir.abs_path.as_path()) {
|
||||||
|
Ok(files) => {
|
||||||
|
// Remove recursively files
|
||||||
|
for file in files.iter() {
|
||||||
|
if let Err(err) = self.remove(&file) {
|
||||||
|
return Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::DirStatFailed,
|
||||||
|
format!("{}", err),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Once all files in directory have been deleted, remove directory
|
||||||
|
match stream.rmdir(dir.name.as_str()) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::DirStatFailed,
|
||||||
|
format!("{}", err),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::DirStatFailed,
|
||||||
|
format!("{}", err),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
None => Err(FileTransferError::new(
|
None => Err(FileTransferError::new(
|
||||||
FileTransferErrorType::UninitializedSession,
|
FileTransferErrorType::UninitializedSession,
|
||||||
)),
|
)),
|
||||||
@@ -393,7 +439,30 @@ impl FileTransfer for FtpFileTransfer {
|
|||||||
/// Rename file or a directory
|
/// Rename file or a directory
|
||||||
fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> {
|
fn rename(&self, file: &FsEntry, dst: &Path) -> Result<(), FileTransferError> {
|
||||||
match self.stream {
|
match self.stream {
|
||||||
Some(stream) => {}
|
Some(stream) => {
|
||||||
|
// Get name
|
||||||
|
let src_name: String = match file {
|
||||||
|
FsEntry::Directory(dir) => dir.name.clone(),
|
||||||
|
FsEntry::File(file) => file.name.clone(),
|
||||||
|
};
|
||||||
|
let dst_name: PathBuf = match dst.file_name() {
|
||||||
|
Some(p) => PathBuf::from(p),
|
||||||
|
None => {
|
||||||
|
return Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::FileCreateDenied,
|
||||||
|
String::from("Invalid destination name"),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Only names are supported
|
||||||
|
match stream.rename(src_name.as_str(), &dst_name.as_path().to_string_lossy()) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(err) => Err(FileTransferError::new_ex(
|
||||||
|
FileTransferErrorType::DirStatFailed,
|
||||||
|
format!("{}", err),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
None => Err(FileTransferError::new(
|
None => Err(FileTransferError::new(
|
||||||
FileTransferErrorType::UninitializedSession,
|
FileTransferErrorType::UninitializedSession,
|
||||||
)),
|
)),
|
||||||
@@ -463,7 +532,13 @@ mod tests {
|
|||||||
fn test_filetransfer_ftp_parse_list_line() {
|
fn test_filetransfer_ftp_parse_list_line() {
|
||||||
let ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
let ftp: FtpFileTransfer = FtpFileTransfer::new(false);
|
||||||
// Simple file
|
// Simple file
|
||||||
let fs_entry: FsEntry = ftp.parse_list_line(PathBuf::from("/tmp").as_path(), "-rw-rw-r-- 1 root dialout 8192 Nov 5 2018 omar.txt").ok().unwrap();
|
let fs_entry: FsEntry = ftp
|
||||||
|
.parse_list_line(
|
||||||
|
PathBuf::from("/tmp").as_path(),
|
||||||
|
"-rw-rw-r-- 1 root dialout 8192 Nov 5 2018 omar.txt",
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.unwrap();
|
||||||
if let FsEntry::File(file) = fs_entry {
|
if let FsEntry::File(file) = fs_entry {
|
||||||
assert_eq!(file.abs_path, PathBuf::from("/tmp/omar.txt"));
|
assert_eq!(file.abs_path, PathBuf::from("/tmp/omar.txt"));
|
||||||
assert_eq!(file.name, String::from("omar.txt"));
|
assert_eq!(file.name, String::from("omar.txt"));
|
||||||
@@ -479,7 +554,13 @@ mod tests {
|
|||||||
panic!("Expected file, got directory");
|
panic!("Expected file, got directory");
|
||||||
}
|
}
|
||||||
// Simple file with number as gid, uid
|
// Simple file with number as gid, uid
|
||||||
let fs_entry: FsEntry = ftp.parse_list_line(PathBuf::from("/tmp").as_path(), "-rwxr-xr-x 1 0 9 4096 Nov 5 16:32 omar.txt").ok().unwrap();
|
let fs_entry: FsEntry = ftp
|
||||||
|
.parse_list_line(
|
||||||
|
PathBuf::from("/tmp").as_path(),
|
||||||
|
"-rwxr-xr-x 1 0 9 4096 Nov 5 16:32 omar.txt",
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.unwrap();
|
||||||
if let FsEntry::File(file) = fs_entry {
|
if let FsEntry::File(file) = fs_entry {
|
||||||
assert_eq!(file.abs_path, PathBuf::from("/tmp/omar.txt"));
|
assert_eq!(file.abs_path, PathBuf::from("/tmp/omar.txt"));
|
||||||
assert_eq!(file.name, String::from("omar.txt"));
|
assert_eq!(file.name, String::from("omar.txt"));
|
||||||
@@ -495,7 +576,13 @@ mod tests {
|
|||||||
panic!("Expected file, got directory");
|
panic!("Expected file, got directory");
|
||||||
}
|
}
|
||||||
// Directory
|
// Directory
|
||||||
let fs_entry: FsEntry = ftp.parse_list_line(PathBuf::from("/tmp").as_path(), "drwxrwxr-x 1 0 9 4096 Nov 5 2018 docs").ok().unwrap();
|
let fs_entry: FsEntry = ftp
|
||||||
|
.parse_list_line(
|
||||||
|
PathBuf::from("/tmp").as_path(),
|
||||||
|
"drwxrwxr-x 1 0 9 4096 Nov 5 2018 docs",
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.unwrap();
|
||||||
if let FsEntry::Directory(dir) = fs_entry {
|
if let FsEntry::Directory(dir) = fs_entry {
|
||||||
assert_eq!(dir.abs_path, PathBuf::from("/tmp/docs"));
|
assert_eq!(dir.abs_path, PathBuf::from("/tmp/docs"));
|
||||||
assert_eq!(dir.name, String::from("docs"));
|
assert_eq!(dir.name, String::from("docs"));
|
||||||
@@ -511,7 +598,11 @@ mod tests {
|
|||||||
panic!("Expected directory, got directory");
|
panic!("Expected directory, got directory");
|
||||||
}
|
}
|
||||||
// Error
|
// Error
|
||||||
assert!(ftp.parse_list_line(PathBuf::from("/").as_path(), "drwxrwxr-x 1 0 9 Nov 5 2018 docs").is_err());
|
assert!(ftp
|
||||||
|
.parse_list_line(
|
||||||
|
PathBuf::from("/").as_path(),
|
||||||
|
"drwxrwxr-x 1 0 9 Nov 5 2018 docs"
|
||||||
|
)
|
||||||
|
.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user