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