74 lines
2.2 KiB
Rust
74 lines
2.2 KiB
Rust
use crate::backup::get_time_from_file_name;
|
|
use crate::config::RemoteBackupConfig;
|
|
use crate::error::{AlbatrossError, Result};
|
|
use ssh2::Session;
|
|
use std::net::TcpStream;
|
|
use std::path::PathBuf;
|
|
|
|
/// Open an SSH session
|
|
fn open_ssh_session(remote_config: &RemoteBackupConfig) -> Result<Session> {
|
|
let tcp = TcpStream::connect(&remote_config.sftp_server_addr)?;
|
|
let mut sess = Session::new()?;
|
|
sess.set_tcp_stream(tcp);
|
|
sess.handshake().unwrap();
|
|
|
|
if let Some(password) = &remote_config.password {
|
|
sess.userauth_password(&remote_config.username, password)?;
|
|
} else if let Some(key) = &remote_config.private_key {
|
|
let public_key = remote_config.public_key.as_deref();
|
|
sess.userauth_pubkey_file(&remote_config.username, public_key, key, None)?;
|
|
} else {
|
|
return Err(AlbatrossError::NoSSHAuth);
|
|
}
|
|
|
|
Ok(sess)
|
|
}
|
|
|
|
/// Handle remote backup of a file
|
|
pub fn remote_backup(file: PathBuf, remote_config: &RemoteBackupConfig) -> Result<()> {
|
|
let sess = open_ssh_session(remote_config)?;
|
|
|
|
let remote_path = remote_config.remote_dir.join(file.file_name().unwrap());
|
|
|
|
let mut local_file = std::fs::File::open(&file)?;
|
|
|
|
let sftp = sess.sftp()?;
|
|
|
|
let mut remote_file = sftp.create(&remote_path)?;
|
|
|
|
std::io::copy(&mut local_file, &mut remote_file)?;
|
|
|
|
let files = sftp.readdir(&remote_config.remote_dir)?;
|
|
|
|
let mut backups: Vec<PathBuf> = files
|
|
.into_iter()
|
|
.map(|(file, _)| file)
|
|
.filter(|file| {
|
|
if let Some(ext) = file.extension() {
|
|
ext == "gz"
|
|
} else {
|
|
false
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
backups.sort_by(|file_a, file_b| {
|
|
let time_a =
|
|
get_time_from_file_name(file_a.file_name().unwrap().to_str().unwrap()).unwrap();
|
|
let time_b =
|
|
get_time_from_file_name(file_b.file_name().unwrap().to_str().unwrap()).unwrap();
|
|
|
|
time_b.cmp(&time_a)
|
|
});
|
|
|
|
if backups.len() > remote_config.backups_to_keep as usize {
|
|
for _ in 0..(backups.len() - remote_config.backups_to_keep as usize) {
|
|
if let Some(backup_path) = backups.pop() {
|
|
sftp.unlink(&*backup_path)?;
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|