]> git.proxmox.com Git - proxmox-backup.git/blob - src/backup/data_blob_reader.rs
more clippy fixups
[proxmox-backup.git] / src / backup / data_blob_reader.rs
1 use anyhow::{bail, format_err, Error};
2 use std::sync::Arc;
3 use std::io::{Read, BufReader};
4 use proxmox::tools::io::ReadExt;
5
6 use super::*;
7
8 enum BlobReaderState<R: Read> {
9 Uncompressed { expected_crc: u32, csum_reader: ChecksumReader<R> },
10 Compressed { expected_crc: u32, decompr: zstd::stream::read::Decoder<BufReader<ChecksumReader<R>>> },
11 Encrypted { expected_crc: u32, decrypt_reader: CryptReader<BufReader<ChecksumReader<R>>> },
12 EncryptedCompressed { expected_crc: u32, decompr: zstd::stream::read::Decoder<BufReader<CryptReader<BufReader<ChecksumReader<R>>>>> },
13 }
14
15 /// Read data blobs
16 pub struct DataBlobReader<R: Read> {
17 state: BlobReaderState<R>,
18 }
19
20 // zstd_safe::DCtx is not sync but we are, since
21 // the only public interface is on mutable reference
22 unsafe impl<R: Read> Sync for DataBlobReader<R> {}
23
24 impl <R: Read> DataBlobReader<R> {
25
26 pub fn new(mut reader: R, config: Option<Arc<CryptConfig>>) -> Result<Self, Error> {
27
28 let head: DataBlobHeader = unsafe { reader.read_le_value()? };
29 match head.magic {
30 UNCOMPRESSED_BLOB_MAGIC_1_0 => {
31 let expected_crc = u32::from_le_bytes(head.crc);
32 let csum_reader = ChecksumReader::new(reader, None);
33 Ok(Self { state: BlobReaderState::Uncompressed { expected_crc, csum_reader }})
34 }
35 COMPRESSED_BLOB_MAGIC_1_0 => {
36 let expected_crc = u32::from_le_bytes(head.crc);
37 let csum_reader = ChecksumReader::new(reader, None);
38
39 let decompr = zstd::stream::read::Decoder::new(csum_reader)?;
40 Ok(Self { state: BlobReaderState::Compressed { expected_crc, decompr }})
41 }
42 ENCRYPTED_BLOB_MAGIC_1_0 => {
43 let config = config.ok_or_else(|| format_err!("unable to read encrypted blob without key"))?;
44 let expected_crc = u32::from_le_bytes(head.crc);
45 let mut iv = [0u8; 16];
46 let mut expected_tag = [0u8; 16];
47 reader.read_exact(&mut iv)?;
48 reader.read_exact(&mut expected_tag)?;
49 let csum_reader = ChecksumReader::new(reader, None);
50 let decrypt_reader = CryptReader::new(BufReader::with_capacity(64*1024, csum_reader), iv, expected_tag, config)?;
51 Ok(Self { state: BlobReaderState::Encrypted { expected_crc, decrypt_reader }})
52 }
53 ENCR_COMPR_BLOB_MAGIC_1_0 => {
54 let config = config.ok_or_else(|| format_err!("unable to read encrypted blob without key"))?;
55 let expected_crc = u32::from_le_bytes(head.crc);
56 let mut iv = [0u8; 16];
57 let mut expected_tag = [0u8; 16];
58 reader.read_exact(&mut iv)?;
59 reader.read_exact(&mut expected_tag)?;
60 let csum_reader = ChecksumReader::new(reader, None);
61 let decrypt_reader = CryptReader::new(BufReader::with_capacity(64*1024, csum_reader), iv, expected_tag, config)?;
62 let decompr = zstd::stream::read::Decoder::new(decrypt_reader)?;
63 Ok(Self { state: BlobReaderState::EncryptedCompressed { expected_crc, decompr }})
64 }
65 _ => bail!("got wrong magic number {:?}", head.magic)
66 }
67 }
68
69 pub fn finish(self) -> Result<R, Error> {
70 match self.state {
71 BlobReaderState::Uncompressed { csum_reader, expected_crc } => {
72 let (reader, crc, _) = csum_reader.finish()?;
73 if crc != expected_crc {
74 bail!("blob crc check failed");
75 }
76 Ok(reader)
77 }
78 BlobReaderState::Compressed { expected_crc, decompr } => {
79 let csum_reader = decompr.finish().into_inner();
80 let (reader, crc, _) = csum_reader.finish()?;
81 if crc != expected_crc {
82 bail!("blob crc check failed");
83 }
84 Ok(reader)
85 }
86 BlobReaderState::Encrypted { expected_crc, decrypt_reader } => {
87 let csum_reader = decrypt_reader.finish()?.into_inner();
88 let (reader, crc, _) = csum_reader.finish()?;
89 if crc != expected_crc {
90 bail!("blob crc check failed");
91 }
92 Ok(reader)
93 }
94 BlobReaderState::EncryptedCompressed { expected_crc, decompr } => {
95 let decrypt_reader = decompr.finish().into_inner();
96 let csum_reader = decrypt_reader.finish()?.into_inner();
97 let (reader, crc, _) = csum_reader.finish()?;
98 if crc != expected_crc {
99 bail!("blob crc check failed");
100 }
101 Ok(reader)
102 }
103 }
104 }
105 }
106
107 impl <R: Read> Read for DataBlobReader<R> {
108
109 fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> {
110 match &mut self.state {
111 BlobReaderState::Uncompressed { csum_reader, .. } => {
112 csum_reader.read(buf)
113 }
114 BlobReaderState::Compressed { decompr, .. } => {
115 decompr.read(buf)
116 }
117 BlobReaderState::Encrypted { decrypt_reader, .. } => {
118 decrypt_reader.read(buf)
119 }
120 BlobReaderState::EncryptedCompressed { decompr, .. } => {
121 decompr.read(buf)
122 }
123 }
124 }
125 }