catar/encoder.rs: allow to pass list of devices
We can use this to implement the --one-file-system like options. This is a bit more convenient, because this way we can select to include multiple devices (which is required by container backups).
This commit is contained in:
		@ -133,7 +133,7 @@ fn create_archive(param: Value, _info: &ApiMethod) -> Result<Value, Error> {
 | 
			
		||||
 | 
			
		||||
    let mut writer = std::io::BufWriter::with_capacity(1024*1024, file);
 | 
			
		||||
 | 
			
		||||
    CaTarEncoder::encode(source, &mut dir, &mut writer)?;
 | 
			
		||||
    CaTarEncoder::encode(source, &mut dir, None, &mut writer)?;
 | 
			
		||||
 | 
			
		||||
    writer.flush()?;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -40,7 +40,7 @@ fn backup_dir(
 | 
			
		||||
 | 
			
		||||
    let path = std::path::PathBuf::from(path);
 | 
			
		||||
 | 
			
		||||
    CaTarEncoder::encode(path, dir, &mut index)?;
 | 
			
		||||
    CaTarEncoder::encode(path, dir, None, &mut index)?;
 | 
			
		||||
 | 
			
		||||
    index.close()?; // commit changes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@
 | 
			
		||||
 | 
			
		||||
use failure::*;
 | 
			
		||||
use endian_trait::Endian;
 | 
			
		||||
use std::collections::HashSet;
 | 
			
		||||
 | 
			
		||||
use super::format_definition::*;
 | 
			
		||||
use super::binary_search_tree::*;
 | 
			
		||||
@ -33,11 +34,17 @@ pub struct CaTarEncoder<'a, W: Write> {
 | 
			
		||||
    writer_pos: usize,
 | 
			
		||||
    size: usize,
 | 
			
		||||
    file_copy_buffer: Vec<u8>,
 | 
			
		||||
    devices: Option<HashSet<u64>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl <'a, W: Write> CaTarEncoder<'a, W> {
 | 
			
		||||
 | 
			
		||||
    pub fn encode(path: PathBuf, dir: &mut nix::dir::Dir, writer: &'a mut W) -> Result<(), Error> {
 | 
			
		||||
    pub fn encode(
 | 
			
		||||
        path: PathBuf,
 | 
			
		||||
        dir: &mut nix::dir::Dir,
 | 
			
		||||
        device_list: Option<Vec<u64>>,
 | 
			
		||||
        writer: &'a mut W
 | 
			
		||||
    ) -> Result<(), Error> {
 | 
			
		||||
 | 
			
		||||
        const FILE_COPY_BUFFER_SIZE: usize = 1024*1024;
 | 
			
		||||
 | 
			
		||||
@ -50,6 +57,7 @@ impl <'a, W: Write> CaTarEncoder<'a, W> {
 | 
			
		||||
            writer_pos: 0,
 | 
			
		||||
            size: 0,
 | 
			
		||||
            file_copy_buffer,
 | 
			
		||||
            devices: None,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // todo: use scandirat??
 | 
			
		||||
@ -70,6 +78,13 @@ impl <'a, W: Write> CaTarEncoder<'a, W> {
 | 
			
		||||
            bail!("backup virtual file systems is disabled!");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if let Some(list) = device_list {
 | 
			
		||||
            let mut devices = HashSet::new();
 | 
			
		||||
            devices.insert(stat.st_dev); // always include archive root device
 | 
			
		||||
            for dev in list { devices.insert(dev); }
 | 
			
		||||
            me.devices = Some(devices);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        me.encode_dir(dir, &stat, magic)?;
 | 
			
		||||
 | 
			
		||||
        Ok(())
 | 
			
		||||
@ -248,7 +263,16 @@ impl <'a, W: Write> CaTarEncoder<'a, W> {
 | 
			
		||||
 | 
			
		||||
        let mut dir_count = 0;
 | 
			
		||||
 | 
			
		||||
        if !is_virtual_file_system(magic) {
 | 
			
		||||
        let mut include_children = true;
 | 
			
		||||
        if is_virtual_file_system(magic) {
 | 
			
		||||
            include_children = false;
 | 
			
		||||
        } else {
 | 
			
		||||
            if let Some(ref set) = self.devices {
 | 
			
		||||
                include_children = set.contains(&dir_stat.st_dev);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if include_children {
 | 
			
		||||
            for entry in dir.iter() {
 | 
			
		||||
                dir_count += 1;
 | 
			
		||||
                if dir_count > MAX_DIRECTORY_ENTRIES {
 | 
			
		||||
@ -399,7 +423,16 @@ impl <'a, W: Write> CaTarEncoder<'a, W> {
 | 
			
		||||
 | 
			
		||||
        self.write_entry(entry)?;
 | 
			
		||||
 | 
			
		||||
        let mut include_payload = true;
 | 
			
		||||
        if is_virtual_file_system(magic) {
 | 
			
		||||
            include_payload = false;
 | 
			
		||||
        } else {
 | 
			
		||||
            if let Some(ref set) = self.devices {
 | 
			
		||||
                include_payload = set.contains(&stat.st_dev);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if !include_payload {
 | 
			
		||||
            self.write_header(CA_FORMAT_PAYLOAD, 0)?;
 | 
			
		||||
            return Ok(());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user