diff --git a/src/backup/datastore.rs b/src/backup/datastore.rs index 5184055d..355f6526 100644 --- a/src/backup/datastore.rs +++ b/src/backup/datastore.rs @@ -62,9 +62,9 @@ impl DataStore { }) } - pub fn create_image_writer>(&mut self, filename: P, size: usize, chunk_size: usize) -> Result { + pub fn create_image_writer>(&self, filename: P, size: usize, chunk_size: usize) -> Result { - let index = ImageIndexWriter::create(&mut self.chunk_store, filename.as_ref(), size, chunk_size)?; + let index = ImageIndexWriter::create(&self.chunk_store, filename.as_ref(), size, chunk_size)?; Ok(index) } diff --git a/src/backup/image_index.rs b/src/backup/image_index.rs index 2372698e..6a028e30 100644 --- a/src/backup/image_index.rs +++ b/src/backup/image_index.rs @@ -131,7 +131,7 @@ impl <'a> ImageIndexReader<'a> { } pub struct ImageIndexWriter<'a> { - store: &'a mut ChunkStore, + store: &'a ChunkStore, filename: PathBuf, tmp_filename: PathBuf, chunk_size: usize, @@ -153,7 +153,7 @@ impl <'a> Drop for ImageIndexWriter<'a> { impl <'a> ImageIndexWriter<'a> { - pub fn create(store: &'a mut ChunkStore, path: &Path, size: usize, chunk_size: usize) -> Result { + pub fn create(store: &'a ChunkStore, path: &Path, size: usize, chunk_size: usize) -> Result { let full_path = store.relative_path(path); let mut tmp_path = full_path.clone(); diff --git a/src/bin/backup-client.rs b/src/bin/backup-client.rs index 06e0b03e..0931b937 100644 --- a/src/bin/backup-client.rs +++ b/src/bin/backup-client.rs @@ -17,7 +17,48 @@ fn required_string_param<'a>(param: &'a Value, name: &str) -> &'a str { param[name].as_str().expect(&format!("missing parameter '{}'", name)) } -fn backup_file(param: Value, _info: &ApiMethod) -> Result { +fn backup_dir(datastore: &DataStore, file: &std::fs::File, target: &str, chunk_size: usize) -> Result<(), Error> { + + let mut target = std::path::PathBuf::from(target); + + if let Some(ext) = target.extension() { + if ext != "aidx" { + bail!("got wrong file extension - expected '.aidx'"); + } + } else { + target.set_extension("aidx"); + } + + bail!("not implemented"); + + Ok(()) +} + +fn backup_image(datastore: &DataStore, file: &std::fs::File, size: usize, target: &str, chunk_size: usize) -> Result<(), Error> { + + let mut target = std::path::PathBuf::from(target); + + if let Some(ext) = target.extension() { + if ext != "iidx" { + bail!("got wrong file extension - expected '.iidx'"); + } + } else { + target.set_extension("iidx"); + } + + let mut index = datastore.create_image_writer(&target, size, chunk_size)?; + + tools::file_chunker(file, chunk_size, |pos, chunk| { + index.add_chunk(pos, chunk)?; + Ok(true) + })?; + + index.close()?; // commit changes + + Ok(()) +} + +fn create_backup(param: Value, _info: &ApiMethod) -> Result { let filename = required_string_param(¶m, "filename"); let store = required_string_param(¶m, "store"); @@ -35,40 +76,33 @@ fn backup_file(param: Value, _info: &ApiMethod) -> Result { } } - let mut datastore = DataStore::open(store)?; + let datastore = DataStore::open(store)?; - println!("Backup file '{}' to '{}'", filename, store); + let file = std::fs::File::open(filename)?; + let stat = nix::sys::stat::fstat(file.as_raw_fd())?; - let mut target = std::path::PathBuf::from(target); - if let Some(ext) = target.extension() { - if ext != "iidx" { - bail!("got wrong file extension - expected '.iidx'"); - } - } else { - target.set_extension("iidx"); - } + if (stat.st_mode & libc::S_IFDIR) != 0 { + println!("Backup directory '{}' to '{}'", filename, store); + + backup_dir(&datastore, &file, &target, chunk_size)?; + + } else if (stat.st_mode & (libc::S_IFREG|libc::S_IFBLK)) != 0 { + println!("Backup file '{}' to '{}'", filename, store); - { - let file = std::fs::File::open(filename)?; - let stat = nix::sys::stat::fstat(file.as_raw_fd())?; if stat.st_size <= 0 { bail!("got strange file size '{}'", stat.st_size); } let size = stat.st_size as usize; - let mut index = datastore.create_image_writer(&target, size, chunk_size)?; + backup_image(&datastore, &file, size, &target, chunk_size)?; - tools::file_chunker(file, chunk_size, |pos, chunk| { - index.add_chunk(pos, chunk)?; - Ok(true) - })?; + let idx = datastore.open_image_reader(target)?; + idx.print_info(); - index.close()?; // commit changes + } else { + bail!("unsupported file type (expected a directory, file or block device)"); } //datastore.garbage_collection()?; - let idx = datastore.open_image_reader(target)?; - idx.print_info(); - Ok(Value::Null) } @@ -77,9 +111,9 @@ fn main() { let cmd_def = CliCommand::new( ApiMethod::new( - backup_file, - ObjectSchema::new("Create backup from file.") - .required("filename", StringSchema::new("Source file name.")) + create_backup, + ObjectSchema::new("Create backup.") + .required("filename", StringSchema::new("Source name (file or directory name)")) .required("store", StringSchema::new("Datastore name.")) .required("target", StringSchema::new("Target name.")) .optional(