src/backup/dynamic_index.rs: compute checksum over the index
This commit is contained in:
		@ -28,7 +28,9 @@ pub struct DynamicIndexHeader {
 | 
				
			|||||||
    pub version: u32,
 | 
					    pub version: u32,
 | 
				
			||||||
    pub uuid: [u8; 16],
 | 
					    pub uuid: [u8; 16],
 | 
				
			||||||
    pub ctime: u64,
 | 
					    pub ctime: u64,
 | 
				
			||||||
    reserved: [u8; 4056], // overall size is one page (4096 bytes)
 | 
					    /// Sha256 over the index ``SHA256(offset1||digest1||offset2||digest2||...)``
 | 
				
			||||||
 | 
					    pub index_csum: [u8; 32],
 | 
				
			||||||
 | 
					    reserved: [u8; 4024], // overall size is one page (4096 bytes)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -41,6 +43,7 @@ pub struct DynamicIndexReader {
 | 
				
			|||||||
    index_entries: usize,
 | 
					    index_entries: usize,
 | 
				
			||||||
    pub uuid: [u8; 16],
 | 
					    pub uuid: [u8; 16],
 | 
				
			||||||
    pub ctime: u64,
 | 
					    pub ctime: u64,
 | 
				
			||||||
 | 
					    pub index_csum: [u8; 32],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// `index` is mmap()ed which cannot be thread-local so should be sendable
 | 
					// `index` is mmap()ed which cannot be thread-local so should be sendable
 | 
				
			||||||
@ -119,6 +122,7 @@ impl DynamicIndexReader {
 | 
				
			|||||||
            index_entries: index_size/40,
 | 
					            index_entries: index_size/40,
 | 
				
			||||||
            ctime,
 | 
					            ctime,
 | 
				
			||||||
            uuid: header.uuid,
 | 
					            uuid: header.uuid,
 | 
				
			||||||
 | 
					            index_csum: header.index_csum,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -382,6 +386,7 @@ pub struct DynamicIndexWriter {
 | 
				
			|||||||
    closed: bool,
 | 
					    closed: bool,
 | 
				
			||||||
    filename: PathBuf,
 | 
					    filename: PathBuf,
 | 
				
			||||||
    tmp_filename: PathBuf,
 | 
					    tmp_filename: PathBuf,
 | 
				
			||||||
 | 
					    csum: Option<openssl::sha::Sha256>,
 | 
				
			||||||
    pub uuid: [u8; 16],
 | 
					    pub uuid: [u8; 16],
 | 
				
			||||||
    pub ctime: u64,
 | 
					    pub ctime: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -429,8 +434,12 @@ impl DynamicIndexWriter {
 | 
				
			|||||||
        header.ctime = u64::to_le(ctime);
 | 
					        header.ctime = u64::to_le(ctime);
 | 
				
			||||||
        header.uuid = *uuid.as_bytes();
 | 
					        header.uuid = *uuid.as_bytes();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        header.index_csum = [0u8; 32];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        writer.write_all(&buffer)?;
 | 
					        writer.write_all(&buffer)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let csum = Some(openssl::sha::Sha256::new());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(Self {
 | 
					        Ok(Self {
 | 
				
			||||||
            store,
 | 
					            store,
 | 
				
			||||||
            _lock: shared_lock,
 | 
					            _lock: shared_lock,
 | 
				
			||||||
@ -440,6 +449,7 @@ impl DynamicIndexWriter {
 | 
				
			|||||||
            tmp_filename: tmp_path,
 | 
					            tmp_filename: tmp_path,
 | 
				
			||||||
            ctime,
 | 
					            ctime,
 | 
				
			||||||
            uuid: *uuid.as_bytes(),
 | 
					            uuid: *uuid.as_bytes(),
 | 
				
			||||||
 | 
					            csum,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -448,7 +458,7 @@ impl DynamicIndexWriter {
 | 
				
			|||||||
        self.store.insert_chunk(chunk)
 | 
					        self.store.insert_chunk(chunk)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn close(&mut self)  -> Result<(), Error> {
 | 
					    pub fn close(&mut self)  -> Result<[u8; 32], Error> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.closed {
 | 
					        if self.closed {
 | 
				
			||||||
            bail!("cannot close already closed archive index file {:?}", self.filename);
 | 
					            bail!("cannot close already closed archive index file {:?}", self.filename);
 | 
				
			||||||
@ -458,11 +468,23 @@ impl DynamicIndexWriter {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.writer.flush()?;
 | 
					        self.writer.flush()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        use std::io::Seek;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let csum_offset = proxmox::tools::offsetof!(DynamicIndexHeader, index_csum);
 | 
				
			||||||
 | 
					        self.writer.seek(std::io::SeekFrom::Start(csum_offset as u64))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let csum = self.csum.take().unwrap();
 | 
				
			||||||
 | 
					        let index_csum = csum.finish();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.writer.write_all(&index_csum)?;
 | 
				
			||||||
 | 
					        self.writer.flush()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Err(err) = std::fs::rename(&self.tmp_filename, &self.filename) {
 | 
					        if let Err(err) = std::fs::rename(&self.tmp_filename, &self.filename) {
 | 
				
			||||||
            bail!("Atomic rename file {:?} failed - {}", self.filename, err);
 | 
					            bail!("Atomic rename file {:?} failed - {}", self.filename, err);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(())
 | 
					        Ok(index_csum)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // fixme: rename to add_digest
 | 
					    // fixme: rename to add_digest
 | 
				
			||||||
@ -470,7 +492,15 @@ impl DynamicIndexWriter {
 | 
				
			|||||||
        if self.closed {
 | 
					        if self.closed {
 | 
				
			||||||
            bail!("cannot write to closed dynamic index file {:?}", self.filename);
 | 
					            bail!("cannot write to closed dynamic index file {:?}", self.filename);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.writer.write(unsafe { &std::mem::transmute::<u64, [u8;8]>(offset.to_le()) })?;
 | 
					
 | 
				
			||||||
 | 
					        let offset_le: &[u8; 8] = unsafe { &std::mem::transmute::<u64, [u8;8]>(offset.to_le()) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if let Some(ref mut csum) = self.csum {
 | 
				
			||||||
 | 
					            csum.update(offset_le);
 | 
				
			||||||
 | 
					            csum.update(digest);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.writer.write(offset_le)?;
 | 
				
			||||||
        self.writer.write(digest)?;
 | 
					        self.writer.write(digest)?;
 | 
				
			||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user