use ftp::FtpStream; use std::path::PathBuf; use crate::error; use crate::remote::{PathLocation, RemoteBackupSite}; use crate::config::remote::FTPConfig; /// FTP Remote Site pub struct FTPBackup { /// FTP command stream stream: FtpStream, /// Remote target directory target_dir: PathBuf, /// Number of backups to keep backups_to_keep: usize, } impl FTPBackup { /// New FTPBackup pub fn new(config: &FTPConfig, backups_to_keep: usize) -> error::Result { let mut ftp_stream = FtpStream::connect(&config.server_addr)?; ftp_stream.login(&config.username, &config.password)?; Ok(Self { stream: ftp_stream, target_dir: config.remote_dir.clone(), backups_to_keep, }) } } impl Drop for FTPBackup { fn drop(&mut self) { self.stream.quit().ok(); } } impl RemoteBackupSite for FTPBackup { type FileType = PathLocation; fn backup_to_remote(&mut self, file: PathBuf) -> error::Result<()> { let mut local_file = std::fs::File::open(&file)?; let location = self.target_dir.join(file.file_name().unwrap()); self.stream .put(location.to_str().unwrap(), &mut local_file)?; Ok(()) } fn get_backups(&mut self) -> error::Result> { let files = self.stream.nlst(Some(self.target_dir.to_str().unwrap()))?; Ok(files .into_iter() .filter_map(|file| Self::FileType::new(PathBuf::from(file))) .collect()) } fn remove_backup(&mut self, backup: Self::FileType) -> error::Result<()> { Ok(self.stream.rm(backup.location.to_str().unwrap())?) } fn backups_to_keep(&self) -> usize { self.backups_to_keep } }