ftp transfer: mkdir, remove rename

This commit is contained in:
ChristianVisintin
2020-12-03 12:22:44 +01:00
parent acc4595ff8
commit be41314a28
2 changed files with 103 additions and 12 deletions

View File

@@ -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.
--- ---

View File

@@ -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());
} }
} }