srfs_core/lib.rs
1//! Simple Rust File System (core library)
2//!
3//! A simple filesystem impremented in Rust \[no_std\].
4//!
5//! This crate is a work-in-progress. It contains low-level
6//! code to work directly with block devices (see trait SyncBlockDevice).
7//!
8//! Higher-level API, dependent on \[std\], lives in crate srfs.
9//!
10//! All basic filesystem features are implemented (see ```struct SyncFileSystem```),
11//! with provisions for extensions.
12//!
13//! At the moment only synchronous interface is provided.
14//! See src/tests.rs for usage examples.
15//!
16//! TODO:
17//!
18//! * crash recovery
19//! * timestamps
20//! * async API
21//!
22//! Contributions are welcome.
23
24#![cfg_attr(not(all(feature = "std", test)), no_std)]
25
26extern crate alloc;
27
28#[cfg(any(feature = "std", test))]
29pub mod file_block_device;
30
31mod block_cache;
32mod fs_sync;
33mod layout;
34
35#[cfg(test)]
36extern crate std;
37
38#[cfg(test)]
39mod tests;
40
41pub use fs_sync::*;
42pub use layout::*;
43
44pub const BLOCK_SIZE: u64 = 4096;
45
46// The number below is somewhat arbitrary, but we don't want it to be
47// too large, as having it at, say, 2^35 will make looking up an item
48// take forever, and we don't want to stall an OS by having a bad/corrupted FS.
49pub const MAX_DIR_ENTRIES: u64 = 65536;
50pub const MAX_FILE_SIZE: u64 = MAX_BYTES_LIST_OF_LISTS_BLOCKS; // ~500G.
51
52/// See <https://en.wikipedia.org/wiki/Partition_type>.
53/// We use an arbitrary unused number here.
54pub const PARTITION_ID: u8 = 0x2d;
55
56/// Synchronous Block Device.
57pub trait SyncBlockDevice {
58 /// The number of blocks in this device.
59 fn num_blocks(&self) -> u64;
60
61 /// Read a single block into buf.
62 /// buf must be aligned to BLOCK_SIZE and of length BLOCK_SIZE.
63 fn read_block(&mut self, block_no: u64, buf: &mut [u8]) -> Result<(), FsError>;
64
65 /// Write a single block. Same alignment requirements as in read_block.
66 fn write_block(&mut self, block_no: u64, buf: &[u8]) -> Result<(), FsError>;
67}
68
69/// Initializes the block device so that it has an SFFS with a single/empty root dir.
70pub fn format(block_device: &mut dyn SyncBlockDevice) -> Result<(), FsError> {
71 fs_sync::format(block_device)
72}
73
74#[derive(Clone, Copy, Debug, PartialEq, Eq)]
75pub enum FsError {
76 AlreadyExists,
77 FsFull,
78 InvalidArgument,
79 IoError,
80 NotFound,
81 TooLarge,
82 UnsupportedVersion,
83 Utf8Error,
84 ValidationFailed,
85}