diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2024-02-13 17:54:03 +0100 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2024-02-13 17:54:03 +0100 |
commit | fa6d350c9f40b68bc58b937c98ab3c4890617f02 (patch) | |
tree | 9781bf465ccac9493ef33b88636b7b76e6722a59 | |
parent | 86d53c781bef28b317b5afb59aaaef84b1092d84 (diff) |
fix snapshot and backup dirs not pointing to the correct mountpoint in server mode
-rw-r--r-- | hbak/src/main.rs | 14 | ||||
-rw-r--r-- | hbak_common/src/proto.rs | 59 | ||||
-rw-r--r-- | hbak_common/src/system.rs | 12 | ||||
-rw-r--r-- | hbakd/src/main.rs | 12 |
4 files changed, 64 insertions, 33 deletions
diff --git a/hbak/src/main.rs b/hbak/src/main.rs index 51c6e17..9ea0332 100644 --- a/hbak/src/main.rs +++ b/hbak/src/main.rs @@ -382,11 +382,12 @@ fn sync( return Err(RemoteError::AccessDenied); } - if snapshot.backup_path().exists() { + if snapshot.backup_path(Mode::Client).exists() { return Err(RemoteError::Immutable); } - let file = File::create(snapshot.streaming_path()).map_err(|_| RemoteError::RxError)?; + let file = File::create(snapshot.streaming_path(Mode::Client)) + .map_err(|_| RemoteError::RxError)?; println!("Receiving {} from {}", snapshot, remote_node.address); @@ -394,8 +395,11 @@ fn sync( }; let rx_finish = |snapshot: Snapshot| { - fs::rename(snapshot.streaming_path(), snapshot.backup_path()) - .map_err(|_| RemoteError::RxError)?; + fs::rename( + snapshot.streaming_path(Mode::Client), + snapshot.backup_path(Mode::Client), + ) + .map_err(|_| RemoteError::RxError)?; println!("Received {} from {}", snapshot, remote_node.address); @@ -445,7 +449,7 @@ fn restore(local_node: &LocalNode, address: &str, subvols: &[String]) -> Result< return Err(RemoteError::AccessDenied); } - if snapshot.snapshot_path().exists() { + if snapshot.snapshot_path(Mode::Client).exists() { return Err(RemoteError::Immutable); } diff --git a/hbak_common/src/proto.rs b/hbak_common/src/proto.rs index a7d7da9..d4c4708 100644 --- a/hbak_common/src/proto.rs +++ b/hbak_common/src/proto.rs @@ -14,8 +14,10 @@ use chrono::prelude::*; use serde::{Deserialize, Serialize}; use sys_mount::{Mount, UnmountDrop, UnmountFlags}; -pub const SNAPSHOT_DIR: &str = "/mnt/hbak/snapshots"; -pub const BACKUP_DIR: &str = "/mnt/hbak/backups"; +pub const SNAPSHOT_DIR_C: &str = "/mnt/hbak/snapshots"; +pub const SNAPSHOT_DIR_S: &str = "/mnt/hbakd/snapshots"; +pub const BACKUP_DIR_C: &str = "/mnt/hbak/backups"; +pub const BACKUP_DIR_S: &str = "/mnt/hbakd/backups"; /// A `Snapshot` uniquely identifies a full or incremental btrfs snapshot /// of a node via the node name, subvolume name and creation date. @@ -53,10 +55,10 @@ impl Snapshot { /// Converts the `Snapshot` to its local storage location, /// i.e. a member of the `/mnt/hbak/snapshots` directory /// of its node's own snapshots. - pub fn snapshot_path(&self) -> PathBuf { + pub fn snapshot_path(&self, mode: Mode) -> PathBuf { let mut path_buf = PathBuf::new(); - path_buf.push(SNAPSHOT_DIR); + path_buf.push(mode.snapshot_dir()); path_buf.push(self.to_string()); path_buf @@ -65,10 +67,10 @@ impl Snapshot { /// Converts the `Snapshot` to its remote storage location, /// i.e. a member of the `/mnt/hbak/backups` directory /// where other nodes may store it. - pub fn backup_path(&self) -> PathBuf { + pub fn backup_path(&self, mode: Mode) -> PathBuf { let mut path_buf = PathBuf::new(); - path_buf.push(BACKUP_DIR); + path_buf.push(mode.backup_dir()); path_buf.push(self.to_string()); path_buf @@ -83,10 +85,10 @@ impl Snapshot { /// This behavior allows partial or failed transmissions to be retried /// and is used to prevent (malicious) overwriting of existing snapshots /// that have fully been written. - pub fn streaming_path(&self) -> PathBuf { + pub fn streaming_path(&self, mode: Mode) -> PathBuf { let mut path_buf = PathBuf::new(); - path_buf.push(BACKUP_DIR); + path_buf.push(mode.backup_dir()); path_buf.push(format!("{self}.part")); path_buf @@ -283,12 +285,28 @@ impl Mode { Self::Server => MOUNTPOINTS, } } + + /// Returns the correct snapshot directory for the `Mode`. + pub fn snapshot_dir(&self) -> &'static str { + match self { + Self::Client => SNAPSHOT_DIR_C, + Self::Server => SNAPSHOT_DIR_S, + } + } + + /// Returns the correct backup directory for the `Mode`. + pub fn backup_dir(&self) -> &'static str { + match self { + Self::Client => SNAPSHOT_DIR_C, + Self::Server => SNAPSHOT_DIR_S, + } + } } /// A `LocalNode` represents the current machine. pub struct LocalNode { config: NodeConfig, - mountpoint: &'static str, + mode: Mode, _btrfs: UnmountDrop<Mount>, } @@ -305,7 +323,7 @@ impl LocalNode { Ok(Self { config, - mountpoint, + mode, _btrfs: Mount::builder().data("compress=zstd").mount_autodrop( device, mountpoint, @@ -319,6 +337,11 @@ impl LocalNode { &self.config } + /// Returns the [`Mode`] (network client or server) of the `LocalNode`. + pub fn mode(&self) -> Mode { + self.mode + } + /// Reports whether the `LocalNode` is the origin of the specified subvolume. pub fn owns_subvol(&self, subvol: &String) -> bool { self.config().subvols.contains(subvol) @@ -340,14 +363,14 @@ impl LocalNode { return Err(LocalNodeError::ForeignSubvolume(subvol)); } - let src = Path::new(self.mountpoint).join(&subvol); + let src = Path::new(self.mode.mountpoint()).join(&subvol); let snapshot = Snapshot { node_name: self.name().to_string(), subvol, is_incremental, taken: Utc::now().naive_utc(), }; - let dst = snapshot.snapshot_path(); + let dst = snapshot.snapshot_path(self.mode); if dst.exists() { return Err(LocalNodeError::SnapshotExists(snapshot)); @@ -375,7 +398,7 @@ impl LocalNode { return Err(LocalNodeError::ForeignSubvolume(subvol)); } - let snapshots = fs::read_dir(SNAPSHOT_DIR)?; + let snapshots = fs::read_dir(self.mode.snapshot_dir())?; let mut all_snapshots = Vec::new(); for snapshot in snapshots { all_snapshots.push(Snapshot::try_from(&*snapshot?.path())?); @@ -437,7 +460,7 @@ impl LocalNode { &self, snapshot: &Snapshot, ) -> Result<SnapshotStream<BufReader<ChildStdout>>, LocalNodeError> { - let src = snapshot.snapshot_path(); + let src = snapshot.snapshot_path(self.mode); let cmd = Command::new("btrfs") .arg("send") .arg("--compressed-data") @@ -468,7 +491,7 @@ impl LocalNode { } else { Ok(Box::new(BufReader::with_capacity( CHUNKSIZE, - File::open(snapshot.backup_path())?, + File::open(snapshot.backup_path(self.mode))?, ))) } } @@ -480,7 +503,7 @@ impl LocalNode { mut stream: SnapshotStream<B>, snapshot: &Snapshot, ) -> Result<(), LocalNodeError> { - let dst = snapshot.backup_path(); + let dst = snapshot.backup_path(self.mode); let mut file = BufWriter::with_capacity(CHUNKSIZE, File::create(dst)?); io::copy(&mut stream, &mut file)?; @@ -492,7 +515,7 @@ impl LocalNode { pub fn all_backups(&self, volume: Option<&Volume>) -> Result<Vec<Snapshot>, LocalNodeError> { let mut all_backups = Vec::new(); - let backups = fs::read_dir(BACKUP_DIR)?; + let backups = fs::read_dir(self.mode.backup_dir())?; for backup in backups { let backup = backup?; @@ -636,7 +659,7 @@ impl LocalNode { pub fn recover( &self, ) -> Result<(Child, RecoveryStream<BufWriter<ChildStdin>, &str>), LocalNodeError> { - let dst = SNAPSHOT_DIR; + let dst = self.mode.snapshot_dir(); let mut cmd = Command::new("btrfs") .arg("receive") .arg(dst) diff --git a/hbak_common/src/system.rs b/hbak_common/src/system.rs index 408c415..1f0c9d4 100644 --- a/hbak_common/src/system.rs +++ b/hbak_common/src/system.rs @@ -1,5 +1,5 @@ use crate::config::NodeConfig; -use crate::proto::{BACKUP_DIR, SNAPSHOT_DIR}; +use crate::proto::{BACKUP_DIR_C, SNAPSHOT_DIR_C}; use crate::LocalNodeError; use std::fs; @@ -61,7 +61,7 @@ fn init_btrfs(device: &str) -> Result<(), LocalNodeError> { if !Command::new("btrfs") .arg("subvolume") .arg("create") - .arg(SNAPSHOT_DIR) + .arg(SNAPSHOT_DIR_C) .spawn()? .wait()? .success() @@ -72,7 +72,7 @@ fn init_btrfs(device: &str) -> Result<(), LocalNodeError> { if !Command::new("btrfs") .arg("subvolume") .arg("create") - .arg(BACKUP_DIR) + .arg(BACKUP_DIR_C) .spawn()? .wait()? .success() @@ -113,7 +113,7 @@ fn deinit_btrfs() -> Result<(), LocalNodeError> { if !Command::new("btrfs") .arg("subvolume") .arg("delete") - .arg(BACKUP_DIR) + .arg(BACKUP_DIR_C) .spawn()? .wait()? .success() @@ -125,7 +125,7 @@ fn deinit_btrfs() -> Result<(), LocalNodeError> { .arg("subvolume") .arg("list") .arg("-o") - .arg(SNAPSHOT_DIR) + .arg(SNAPSHOT_DIR_C) .output()?; if !output.status.success() { return Err(LocalNodeError::BtrfsCmd); @@ -156,7 +156,7 @@ fn deinit_btrfs() -> Result<(), LocalNodeError> { if !Command::new("btrfs") .arg("subvolume") .arg("delete") - .arg(SNAPSHOT_DIR) + .arg(SNAPSHOT_DIR_C) .spawn()? .wait()? .success() diff --git a/hbakd/src/main.rs b/hbakd/src/main.rs index 87763df..c1427fc 100644 --- a/hbakd/src/main.rs +++ b/hbakd/src/main.rs @@ -141,11 +141,12 @@ fn handle_client(local_node: &LocalNode, stream: TcpStream) -> Result<(), Networ return Err(RemoteError::AccessDenied); } - if snapshot.backup_path().exists() { + if snapshot.backup_path(Mode::Server).exists() { return Err(RemoteError::Immutable); } - let file = File::create(snapshot.streaming_path()).map_err(|_| RemoteError::RxError)?; + let file = File::create(snapshot.streaming_path(Mode::Server)) + .map_err(|_| RemoteError::RxError)?; println!( "[info] <{}@{}> Receiving {}", @@ -156,8 +157,11 @@ fn handle_client(local_node: &LocalNode, stream: TcpStream) -> Result<(), Networ }; let rx_finish = |snapshot: Snapshot| { - fs::rename(snapshot.streaming_path(), snapshot.backup_path()) - .map_err(|_| RemoteError::RxError)?; + fs::rename( + snapshot.streaming_path(Mode::Server), + snapshot.backup_path(Mode::Server), + ) + .map_err(|_| RemoteError::RxError)?; println!( "[info] <{}@{}> Received {}", |