]> git.proxmox.com Git - proxmox-backup.git/blob - pbs-datastore/src/checksum_writer.rs
pbs-tools: drop borrow module
[proxmox-backup.git] / pbs-datastore / src / checksum_writer.rs
1 use std::sync::Arc;
2 use std::io::Write;
3
4 use anyhow::{Error};
5
6 use proxmox_borrow::Tied;
7
8 use pbs_tools::crypt_config::CryptConfig;
9
10 pub struct ChecksumWriter<W> {
11 writer: W,
12 hasher: crc32fast::Hasher,
13 signer: Option<Tied<Arc<CryptConfig>, openssl::sign::Signer<'static>>>,
14 }
15
16 impl <W: Write> ChecksumWriter<W> {
17
18 pub fn new(writer: W, config: Option<Arc<CryptConfig>>) -> Self {
19 let hasher = crc32fast::Hasher::new();
20 let signer = match config {
21 Some(config) => {
22 let tied_signer = Tied::new(config, |config| {
23 Box::new(unsafe { (*config).data_signer() })
24 });
25 Some(tied_signer)
26 }
27 None => None,
28 };
29 Self { writer, hasher, signer }
30 }
31
32 pub fn finish(mut self) -> Result<(W, u32, Option<[u8; 32]>), Error> {
33 let crc = self.hasher.finalize();
34
35 if let Some(ref mut signer) = self.signer {
36 let mut tag = [0u8; 32];
37 signer.sign(&mut tag)?;
38 Ok((self.writer, crc, Some(tag)))
39 } else {
40 Ok((self.writer, crc, None))
41 }
42 }
43 }
44
45 impl <W: Write> Write for ChecksumWriter<W> {
46
47 fn write(&mut self, buf: &[u8]) -> Result<usize, std::io::Error> {
48 self.hasher.update(buf);
49 if let Some(ref mut signer) = self.signer {
50 signer.update(buf)
51 .map_err(|err| {
52 std::io::Error::new(
53 std::io::ErrorKind::Other,
54 format!("hmac update failed - {}", err))
55 })?;
56 }
57 self.writer.write(buf)
58 }
59
60 fn flush(&mut self) -> Result<(), std::io::Error> {
61 self.writer.flush()
62 }
63 }