Repository: google/OpenSK
File: libraries/persistent_store/src/file.rs (Rust)

Code before:
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! File-backed persistent flash storage for virtual authenticator.
//!
//! [`FileStorage`] implements the flash [`Storage`] interface but doesn't interface with an
//! actual flash storage. Instead it uses a host-based file to persist the storage state.

use crate::{BufferOptions, Storage, StorageIndex, StorageResult};
use alloc::borrow::Cow;
use core::cell::RefCell;
use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;

/// Simulates a flash storage using a host-based file.
///
/// This is usable for emulating authenticator hardware on VM hypervisor's host OS
pub struct FileStorage {
    // Options of the storage
    buffer_options: BufferOptions,

    /// File for persisting contents of the storage
    /// Reading data from File requires mutable reference, as seeking and reading data
    /// changes file's current position.
    /// All operations on backing file internally always first seek to needed position,
    /// so it's safe to borrow mutable reference to backing file for the time of operation.
    backing_file_ref: RefCell<File>,
}

const PAGE_SIZE: usize = 0x1000;
const NUM_PAGES: usize = 20;

impl FileStorage {
    pub fn new(path: &Path) -> StorageResult<FileStorage> {
        let buffer_options = BufferOptions {
            word_size: 4,
            page_size: PAGE_SIZE,
            max_word_writes: 2,
            max_page_erases: 10000,
            strict_mode: true,
        };

        let mut backing_file_ref = RefCell::new(
            OpenOptions::new()
                .read(true)

Review comment (suggestion):
Let's define our own `FileOptions` with only `word_size` and `page_size`. The rest is only useful for tests. Let's also add `num_pages`.

Code after:
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! File-backed persistent flash storage for virtual authenticator.
//!
//! [`FileStorage`] implements the flash [`Storage`] interface but doesn't interface with an
//! actual flash storage. Instead it uses a host-based file to persist the storage state.

use crate::{Storage, StorageIndex, StorageResult};
use alloc::borrow::Cow;
use core::cell::RefCell;
use std::fs::{File, OpenOptions};
use std::io::{Read, Seek, SeekFrom, Write};
use std::path::Path;

/// Simulates a flash storage using a host-based file.
///
/// This is usable for emulating authenticator hardware on VM hypervisor's host OS.
pub struct FileStorage {
    // Options of the storage.
    options: FileOptions,

    /// File for persisting contents of the storage.
    ///
    /// Reading data from File requires mutable reference, as seeking and reading data
    /// changes file's current position.
    ///
    /// All operations on backing file internally always first seek to needed position,
    /// so it's safe to borrow mutable reference to backing file for the time of operation.
    file: RefCell<File>,
}

/// Options for file-backed storage.
pub struct FileOptions {
    /// Size of a word in bytes.
    pub word_size: usize,

    /// Size of a page in bytes.
    pub page_size: usize,

    /// Number of pages in storage.
    pub num_pages: usize,
}

impl FileStorage {
    pub fn new(path: &Path, options: FileOptions) -> StorageResult<FileStorage> {