diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..2c5fad3 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,26 @@ +use std::fs::read_to_string; + +use anyhow::{Context, Result}; +use serde::Deserialize; + +#[derive(Deserialize)] +pub struct Config { + pub snapshot_tag: String, + pub snapshot_interval: String, + pub local_pool_name: String, + pub backup_pools: BackupPools, +} + +#[derive(Deserialize)] +pub struct BackupPools { + pub backup1: String, + pub backup2: String, +} + +impl Config { + pub fn read(filename: &str) -> Result { + let content = read_to_string(filename).context("reading toml file")?; + let parsed: Self = toml::from_str(&content).context("parsing toml")?; + Ok(parsed) + } +} diff --git a/src/encryption.rs b/src/encryption.rs new file mode 100644 index 0000000..072ce01 --- /dev/null +++ b/src/encryption.rs @@ -0,0 +1,45 @@ +use std::path::PathBuf; + +use anyhow::{Result, bail}; + +use crate::cmd::cryptsetup; +use crate::config; + +pub fn decrypt_backup(pools: &config::BackupPools) -> Result<(String, String)> { + let mut pathbuf = PathBuf::new(); + let mut found = false; + + let mut the_name = String::new(); + let mut the_crypt_device = String::new(); + + for (device, name) in [&pools.backup1, &pools.backup2] + .iter() + .zip(["backup1", "backup2"]) + { + pathbuf.push("/dev/disk/by-uuid/"); + pathbuf.push(device); + + if pathbuf.exists() { + found = true; + the_name = name.to_string(); + + the_crypt_device.push_str("crypt-"); + the_crypt_device.push_str(name); // content is then e.g. "crypt-backup1" + + println!("found backup disk {name}, will decrypt to {the_crypt_device}"); + break; + } + } + + if found { + cryptsetup::open(&pathbuf, &the_crypt_device)?; + Ok((the_name, the_crypt_device)) + } else { + bail!("no backup disk found") + } +} + +pub fn encrypt_backup(crypt_device: String) -> Result<()> { + println!("encrypting {crypt_device}"); + cryptsetup::close(&crypt_device) +} diff --git a/src/lib.rs b/src/lib.rs index b732169..f4dd8a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ pub mod cmd; +pub mod config; +pub mod encryption; pub mod todo; pub mod zfs; diff --git a/src/main.rs b/src/main.rs index 48165dc..bc97d41 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,22 @@ use std::env; -use std::fs::read_to_string; use std::io::stdin; -use std::path::PathBuf; use anyhow::{Context, Result, bail}; -use serde::Deserialize; -use zfs_backup::cmd::cryptsetup; use zfs_backup::cmd::zfs::zpool_import; +use zfs_backup::config; +use zfs_backup::encryption; use zfs_backup::todo; use zfs_backup::zfs::ZPool; fn main() -> Result<()> { verify_running_as_root()?; - let config = Config::read("config.toml")?; + let config = config::Config::read("config.toml")?; let local_pool = ZPool::new(&config.local_pool_name)?; // will error if pool does not exist - let (found_pool_name, crypt_device) = decrypt_backup(&config.backup_pools)?; + let (found_pool_name, crypt_device) = encryption::decrypt_backup(&config.backup_pools)?; let backup_pool = import_backup_pool(&found_pool_name)?; backup_pool.scrub()?; @@ -35,34 +33,12 @@ fn main() -> Result<()> { } backup_pool.export()?; - encrypt_backup(crypt_device)?; + encryption::encrypt_backup(crypt_device)?; println!("all done"); Ok(()) } -#[derive(Deserialize)] -struct Config { - snapshot_tag: String, - snapshot_interval: String, - local_pool_name: String, - backup_pools: BackupPools, -} - -#[derive(Deserialize)] -struct BackupPools { - backup1: String, - backup2: String, -} - -impl Config { - fn read(filename: &str) -> Result { - let content = read_to_string(filename).context("reading toml file")?; - let parsed: Self = toml::from_str(&content).context("parsing toml")?; - Ok(parsed) - } -} - /// Import the decrypted ZFS pool so that a backup can be sent. /// /// # Errors @@ -134,45 +110,6 @@ fn ask_user_confirmation(todos: &Vec) -> Result { Ok(false) } -fn decrypt_backup(pools: &BackupPools) -> Result<(String, String)> { - let mut pathbuf = PathBuf::new(); - let mut found = false; - - let mut the_name = String::new(); - let mut the_crypt_device = String::new(); - - for (device, name) in [&pools.backup1, &pools.backup2] - .iter() - .zip(["backup1", "backup2"]) - { - pathbuf.push("/dev/disk/by-uuid/"); - pathbuf.push(device); - - if pathbuf.exists() { - found = true; - the_name = name.to_string(); - - the_crypt_device.push_str("crypt-"); - the_crypt_device.push_str(name); // content is then e.g. "crypt-backup1" - - println!("found backup disk {name}, will decrypt to {the_crypt_device}"); - break; - } - } - - if found { - cryptsetup::open(&pathbuf, &the_crypt_device)?; - Ok((the_name, the_crypt_device)) - } else { - bail!("no backup disk found") - } -} - -fn encrypt_backup(crypt_device: String) -> Result<()> { - println!("encrypting {crypt_device}"); - cryptsetup::close(&crypt_device) -} - fn verify_running_as_root() -> Result<()> { let uid = env::var("USER")?; if uid != "root" {