From: Wolfgang Bumiller Date: Wed, 4 Mar 2020 15:39:07 +0000 (+0100) Subject: examples/pxarcmd: acreate archives recursively X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=21e2b2fa9bf49ea0294ffdce981b8d3ddc8e0e77;p=pxar.git examples/pxarcmd: acreate archives recursively Signed-off-by: Wolfgang Bumiller --- diff --git a/examples/pxarcmd.rs b/examples/pxarcmd.rs index e15f83e..9b1073e 100644 --- a/examples/pxarcmd.rs +++ b/examples/pxarcmd.rs @@ -7,7 +7,7 @@ use std::path::Path; use failure::{bail, format_err, Error}; use pxar::accessor::Accessor; -use pxar::encoder::Encoder; +use pxar::encoder::{Encoder, SeqWrite}; use pxar::{Metadata, Stat}; fn main() -> Result<(), Error> { @@ -64,21 +64,20 @@ fn cmd_create(mut args: std::env::ArgsOs) -> Result<(), Error> { .next() .ok_or_else(|| format_err!("expected a file name"))?; - let mut encoder = Encoder::create( - file, - &Stat::default() - .mode(0o644) - .set_dir() - .uid(1000) - .gid(1000) - .into(), - )?; - - for path in args { - let (mut file, file_size, meta) = open_file(&path)?; - encoder.add_file(&meta, &path, file_size, &mut file)?; + let dir_path = args + .next() + .ok_or_else(|| format_err!("expected a directory"))?; + + if args.next().is_some() { + bail!("too many parameters, there can only be a single root directory in a pxar archive"); } + // we use "simple" directory traversal without `openat()` + let meta = Metadata::from(std::fs::metadata(&dir_path)?); + let dir = std::fs::read_dir(dir_path)?; + + let mut encoder = Encoder::create(file, &meta)?; + add_directory(&mut encoder, dir)?; encoder.finish(); Ok(()) @@ -90,3 +89,39 @@ fn open_file>(path: P) -> io::Result<(File, u64, Metadata)> { let file_size = meta.len(); Ok((file, file_size, meta.into())) } + +fn add_directory<'a, T: SeqWrite + 'a>( + encoder: &mut Encoder, + dir: std::fs::ReadDir, +) -> Result<(), Error> { + for file in dir { + let file = file?; + let file_name = file.file_name(); + if file_name == "." || file_name == ".." { + continue; + } + + println!("{:?}", file.path()); + + let file_type = file.file_type()?; + let file_meta = file.metadata()?; + let meta = Metadata::from(&file_meta); + if file_type.is_dir() { + let mut dir = encoder.create_directory(file_name, &meta)?; + add_directory(&mut dir, std::fs::read_dir(file.path())?)?; + dir.finish(); + } else if file_type.is_symlink() { + todo!("symlink handling"); + } else if file_type.is_file() { + encoder.add_file( + &meta, + file_name, + file_meta.len(), + &mut File::open(file.path())?, + )?; + } else { + todo!("special file handling"); + } + } + Ok(()) +}