vmgs_broker/
non_volatile_store.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Implementation of [`NonVolatileStore`] for VMGS files.
5
6use crate::VmgsClient;
7use crate::VmgsClientError;
8use crate::broker::VmgsBrokerError;
9use async_trait::async_trait;
10use thiserror::Error;
11use vmcore::non_volatile_store::NonVolatileStore;
12use vmcore::non_volatile_store::NonVolatileStoreError;
13
14/// A [`NonVolatileStore`] implementation for VMGS files.
15pub struct VmgsNonVolatileStore {
16    vmgs: VmgsClient,
17    file_id: vmgs_format::FileId,
18    encrypted: bool,
19}
20
21/// Error returned when a VMGS file is requested to be opened in encrypted mode,
22/// but the VMGS broker was not compiled with encryption support.
23#[derive(Debug, Error)]
24#[error("the vmgs_broker crate was not compiled with encryption support")]
25pub struct EncryptionNotSupported;
26
27impl VmgsNonVolatileStore {
28    /// Create a new [`NonVolatileStore`] object backed by a particular VMGS
29    /// file-id.
30    pub fn new(
31        vmgs: VmgsClient,
32        file_id: vmgs_format::FileId,
33        encrypted: bool,
34    ) -> Result<Self, EncryptionNotSupported> {
35        if encrypted && !cfg!(with_encryption) {
36            return Err(EncryptionNotSupported);
37        }
38        Ok(Self {
39            vmgs,
40            file_id,
41            encrypted,
42        })
43    }
44}
45
46#[async_trait]
47impl NonVolatileStore for VmgsNonVolatileStore {
48    async fn persist(&mut self, data: Vec<u8>) -> Result<(), NonVolatileStoreError> {
49        #[cfg(with_encryption)]
50        if self.encrypted {
51            self.vmgs
52                .write_file_encrypted(self.file_id, data)
53                .await
54                .map_err(NonVolatileStoreError::new)?;
55            return Ok(());
56        }
57
58        assert!(!self.encrypted);
59
60        self.vmgs
61            .write_file(self.file_id, data)
62            .await
63            .map_err(NonVolatileStoreError::new)?;
64
65        Ok(())
66    }
67
68    async fn restore(&mut self) -> Result<Option<Vec<u8>>, NonVolatileStoreError> {
69        match self.vmgs.read_file(self.file_id).await {
70            Ok(buf) => Ok(Some(buf)),
71            Err(VmgsClientError::Vmgs(VmgsBrokerError::FileInfoNotAllocated)) => Ok(None),
72            Err(e) => Err(NonVolatileStoreError::new(e)),
73        }
74    }
75}