Add rust zfsbackup

This commit is contained in:
2026-04-25 01:33:15 +02:00
commit 5f3369cf46
4 changed files with 113 additions and 0 deletions

6
Cargo.toml Normal file
View File

@@ -0,0 +1,6 @@
[package]
name = "zfsbackup"
version = "0.1.0"
edition = "2024"
[dependencies]

19
src/command.rs Normal file
View File

@@ -0,0 +1,19 @@
pub fn exec_command(command: &Vec<String>) -> Result<(), String> {
if command.is_empty() {
return Err("Command is empty".to_string());
}
let mut cmd = std::process::Command::new(&command[0]);
if command.len() > 1 {
cmd.args(&command[1..]);
}
let output = cmd.output().map_err(|e| e.to_string())?;
if !output.status.success() {
return Err(format!(
"Command {:?} failed with status {}: {}",
command,
output.status,
String::from_utf8_lossy(&output.stderr)
));
}
Ok(())
}

83
src/lib.rs Normal file
View File

@@ -0,0 +1,83 @@
mod command;
pub struct JobBuilder {
sources: Vec<String>,
target: String,
source_zfs_command: Vec<String>,
target_zfs_command: Vec<String>,
dryrun: bool,
}
fn parse_command(commandstr: &str) -> Vec<String> {
commandstr
.split_whitespace()
.map(|s| s.to_string())
.collect()
}
impl JobBuilder {
pub fn new(sources: Vec<String>, target: String) -> Self {
JobBuilder {
sources,
target,
source_zfs_command: vec!["zfs".to_string()],
target_zfs_command: vec!["zfs".to_string()],
dryrun: false,
}
}
pub fn source_zfs_command(mut self, commandstr: &str) -> Self {
let command: Vec<String>;
command = parse_command(commandstr);
self.source_zfs_command = command;
self
}
pub fn target_zfs_command(mut self, commandstr: &str) -> Self {
let command: Vec<String>;
command = parse_command(commandstr);
self.target_zfs_command = command;
self
}
pub fn zfs_command(mut self, commandstr: &str) -> Self {
let command: Vec<String>;
command = parse_command(commandstr);
self.source_zfs_command = command.clone();
self.target_zfs_command = command;
self
}
pub fn dryrun(mut self) -> Self {
self.dryrun = true;
self
}
pub fn build(self) -> Job {
for source in &self.sources {
let mut cmd = self.source_zfs_command.clone();
let mut args = vec!["list".to_string(), source.clone()];
cmd.append(&mut args);
match command::exec_command(&cmd) {
Ok(_) => (),
Err(e) => panic!("Cannot list source dataset {}: {}", source, e),
}
println!("Source: {}", source);
}
Job {
datasets: vec!["dataset1".to_string(), "dataset2".to_string()],
target: self.target,
source_zfs_command: self.source_zfs_command,
target_zfs_command: self.target_zfs_command,
dryrun: self.dryrun,
}
}
}
pub struct Job {
datasets: Vec<String>,
target: String,
source_zfs_command: Vec<String>,
target_zfs_command: Vec<String>,
dryrun: bool,
}

5
src/main.rs Normal file
View File

@@ -0,0 +1,5 @@
use zfsbackup::JobBuilder;
fn main() {
let job = JobBuilder::new(vec!["chonk".to_string()], "backup".to_string()).build();
}