3 use std
::io
::{Write, Seek, SeekFrom}
;
4 use proxmox
::tools
::io
::WriteExt
;
8 enum BlobWriterState
<'writer
, W
: Write
> {
9 Uncompressed { csum_writer: ChecksumWriter<W> }
,
10 Compressed { compr: zstd::stream::write::Encoder<'writer, ChecksumWriter<W>> }
,
11 Encrypted { crypt_writer: CryptWriter<ChecksumWriter<W>> }
,
12 EncryptedCompressed { compr: zstd::stream::write::Encoder<'writer, CryptWriter<ChecksumWriter<W>>> }
,
16 pub struct DataBlobWriter
<'writer
, W
: Write
> {
17 state
: BlobWriterState
<'writer
, W
>,
20 impl <W
: Write
+ Seek
> DataBlobWriter
<'_
, W
> {
22 pub fn new_uncompressed(mut writer
: W
) -> Result
<Self, Error
> {
23 writer
.seek(SeekFrom
::Start(0))?
;
24 let head
= DataBlobHeader { magic: UNCOMPRESSED_BLOB_MAGIC_1_0, crc: [0; 4] }
;
26 writer
.write_le_value(head
)?
;
28 let csum_writer
= ChecksumWriter
::new(writer
, None
);
29 Ok(Self { state: BlobWriterState::Uncompressed { csum_writer }
})
32 pub fn new_compressed(mut writer
: W
) -> Result
<Self, Error
> {
33 writer
.seek(SeekFrom
::Start(0))?
;
34 let head
= DataBlobHeader { magic: COMPRESSED_BLOB_MAGIC_1_0, crc: [0; 4] }
;
36 writer
.write_le_value(head
)?
;
38 let csum_writer
= ChecksumWriter
::new(writer
, None
);
39 let compr
= zstd
::stream
::write
::Encoder
::new(csum_writer
, 1)?
;
40 Ok(Self { state: BlobWriterState::Compressed { compr }
})
43 pub fn new_encrypted(mut writer
: W
, config
: Arc
<CryptConfig
>) -> Result
<Self, Error
> {
44 writer
.seek(SeekFrom
::Start(0))?
;
45 let head
= EncryptedDataBlobHeader
{
46 head
: DataBlobHeader { magic: ENCRYPTED_BLOB_MAGIC_1_0, crc: [0; 4] }
,
51 writer
.write_le_value(head
)?
;
54 let csum_writer
= ChecksumWriter
::new(writer
, None
);
55 let crypt_writer
= CryptWriter
::new(csum_writer
, config
)?
;
56 Ok(Self { state: BlobWriterState::Encrypted { crypt_writer }
})
59 pub fn new_encrypted_compressed(mut writer
: W
, config
: Arc
<CryptConfig
>) -> Result
<Self, Error
> {
60 writer
.seek(SeekFrom
::Start(0))?
;
61 let head
= EncryptedDataBlobHeader
{
62 head
: DataBlobHeader { magic: ENCR_COMPR_BLOB_MAGIC_1_0, crc: [0; 4] }
,
67 writer
.write_le_value(head
)?
;
70 let csum_writer
= ChecksumWriter
::new(writer
, None
);
71 let crypt_writer
= CryptWriter
::new(csum_writer
, config
)?
;
72 let compr
= zstd
::stream
::write
::Encoder
::new(crypt_writer
, 1)?
;
73 Ok(Self { state: BlobWriterState::EncryptedCompressed { compr }
})
76 pub fn finish(self) -> Result
<W
, Error
> {
78 BlobWriterState
::Uncompressed { csum_writer }
=> {
80 let (mut writer
, crc
, _
) = csum_writer
.finish()?
;
81 let head
= DataBlobHeader { magic: UNCOMPRESSED_BLOB_MAGIC_1_0, crc: crc.to_le_bytes() }
;
83 writer
.seek(SeekFrom
::Start(0))?
;
85 writer
.write_le_value(head
)?
;
90 BlobWriterState
::Compressed { compr }
=> {
91 let csum_writer
= compr
.finish()?
;
92 let (mut writer
, crc
, _
) = csum_writer
.finish()?
;
94 let head
= DataBlobHeader { magic: COMPRESSED_BLOB_MAGIC_1_0, crc: crc.to_le_bytes() }
;
96 writer
.seek(SeekFrom
::Start(0))?
;
98 writer
.write_le_value(head
)?
;
103 BlobWriterState
::Encrypted { crypt_writer }
=> {
104 let (csum_writer
, iv
, tag
) = crypt_writer
.finish()?
;
105 let (mut writer
, crc
, _
) = csum_writer
.finish()?
;
107 let head
= EncryptedDataBlobHeader
{
108 head
: DataBlobHeader { magic: ENCRYPTED_BLOB_MAGIC_1_0, crc: crc.to_le_bytes() }
,
111 writer
.seek(SeekFrom
::Start(0))?
;
113 writer
.write_le_value(head
)?
;
117 BlobWriterState
::EncryptedCompressed { compr }
=> {
118 let crypt_writer
= compr
.finish()?
;
119 let (csum_writer
, iv
, tag
) = crypt_writer
.finish()?
;
120 let (mut writer
, crc
, _
) = csum_writer
.finish()?
;
122 let head
= EncryptedDataBlobHeader
{
123 head
: DataBlobHeader { magic: ENCR_COMPR_BLOB_MAGIC_1_0, crc: crc.to_le_bytes() }
,
126 writer
.seek(SeekFrom
::Start(0))?
;
128 writer
.write_le_value(head
)?
;
136 impl <W
: Write
+ Seek
> Write
for DataBlobWriter
<'_
, W
> {
138 fn write(&mut self, buf
: &[u8]) -> Result
<usize, std
::io
::Error
> {
140 BlobWriterState
::Uncompressed { ref mut csum_writer }
=> {
141 csum_writer
.write(buf
)
143 BlobWriterState
::Compressed { ref mut compr }
=> {
146 BlobWriterState
::Encrypted { ref mut crypt_writer }
=> {
147 crypt_writer
.write(buf
)
149 BlobWriterState
::EncryptedCompressed { ref mut compr }
=> {
155 fn flush(&mut self) -> Result
<(), std
::io
::Error
> {
157 BlobWriterState
::Uncompressed { ref mut csum_writer }
=> {
160 BlobWriterState
::Compressed { ref mut compr }
=> {
163 BlobWriterState
::Encrypted { ref mut crypt_writer }
=> {
166 BlobWriterState
::EncryptedCompressed { ref mut compr }
=> {