Skip to main content

DiskBlockStore

Struct DiskBlockStore 

Source
pub struct DiskBlockStore { /* private fields */ }
Expand description

File-backed block store. Uses a regular file as a virtual block device.

Uses pread/pwrite (via FileExt) for positioned I/O without seeking, which is safe for concurrent reads without a mutex on the file descriptor.

Implementations§

Source§

impl DiskBlockStore

Source

pub fn open(path: &str, block_size: usize, total_blocks: u64) -> FsResult<Self>

Open an existing file as a block store.

The file must already exist and be at least block_size * total_blocks bytes. If total_blocks is 0, it is inferred from the file size.

Source

pub fn create( path: &str, block_size: usize, total_blocks: u64, ) -> FsResult<Self>

Create a new file of the given size and open it as a block store.

Every block is filled with cryptographically random data so that unallocated blocks are indistinguishable from encrypted ones.

Examples found in repository?
examples/create_image.rs (line 28)
15fn main() {
16    let path = std::env::current_dir()
17        .unwrap()
18        .join("sample.dcfs")
19        .to_string_lossy()
20        .to_string();
21
22    // Remove leftover from a previous run, if any.
23    let _ = std::fs::remove_file(&path);
24
25    // 64 blocks × 64 KiB = 4 MiB image.
26    let total_blocks: u64 = 64;
27    let store = Arc::new(
28        DiskBlockStore::create(&path, DEFAULT_BLOCK_SIZE, total_blocks)
29            .expect("failed to create image file"),
30    );
31
32    let crypto = Arc::new(ChaChaEngine::generate().expect("failed to init crypto"));
33    let mut fs = FilesystemCore::new(store, crypto);
34
35    fs.init_filesystem().expect("init_filesystem failed");
36
37    // Create a text file.
38    fs.create_file("hello.txt").expect("create_file failed");
39    fs.write_file("hello.txt", 0, b"Hello, hex editor!")
40        .expect("write_file failed");
41
42    // Create a directory.
43    fs.create_directory("notes")
44        .expect("create_directory failed");
45
46    // Create a larger binary file so there's more to look at.
47    let pattern: Vec<u8> = (0..=255).cycle().take(200_000).collect();
48    fs.create_file("pattern.bin").expect("create_file failed");
49    fs.write_file("pattern.bin", 0, &pattern)
50        .expect("write_file failed");
51
52    fs.sync().expect("sync failed");
53
54    println!("Filesystem image written to:\n  {path}");
55    println!(
56        "  {} blocks × {} bytes = {} bytes total",
57        total_blocks,
58        DEFAULT_BLOCK_SIZE,
59        total_blocks as usize * DEFAULT_BLOCK_SIZE
60    );
61}

Trait Implementations§

Source§

impl BlockStore for DiskBlockStore

Source§

fn block_size(&self) -> usize

Block size in bytes.
Source§

fn total_blocks(&self) -> u64

Total number of blocks in the store.
Source§

fn read_block(&self, block_id: u64) -> FsResult<Vec<u8>>

Read a full block. Returns exactly block_size() bytes.
Source§

fn write_block(&self, block_id: u64, data: &[u8]) -> FsResult<()>

Write a full block. data must be exactly block_size() bytes.
Source§

fn sync(&self) -> FsResult<()>

Sync / flush all writes. No-op for in-memory stores.
Source§

fn read_blocks(&self, block_ids: &[u64]) -> FsResult<Vec<Vec<u8>>>

Read multiple blocks in one call. Read more
Source§

fn write_blocks(&self, blocks: &[(u64, &[u8])]) -> FsResult<()>

Write multiple blocks in one call. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V