use ftp::FtpStream; use std::path::PathBuf; use crate::config::RemoteBackupConfig; use crate::error; use crate::error::AlbatrossError; use crate::remote::{PathLocation, RemoteBackupSite}; /// 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: &RemoteBackupConfig) -> error::Result { let ftp_config = config .ftp .as_ref() .ok_or_else(|| AlbatrossError::RemoteConfigError("FTP".to_string()))?; let mut ftp_stream = FtpStream::connect(&ftp_config.server_addr)?; ftp_stream.login(&ftp_config.username, &ftp_config.password)?; Ok(Self { stream: ftp_stream, target_dir: ftp_config.remote_dir.clone(), backups_to_keep: config.backups_to_keep as usize, }) } } 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 } }