Expand description
Mutable File System (MFS) for Helia
This module provides a mutable file system layer on top of UnixFS, allowing users to work with IPFS content using familiar file system operations.
§Overview
MFS (Mutable File System) provides a POSIX-like interface for interacting with IPFS content. While IPFS content is inherently immutable, MFS maintains a mutable “view” into the content-addressed data by tracking the root CID of your file system tree and updating it as you make changes.
§Core Concepts
- Immutable Content: All UnixFS content is stored immutably using content-addressed CIDs. When you modify a file, a new CID is created.
- Mutable Root: MFS tracks a single “root” CID that represents your current file system state. This root is updated after each modification.
- Directory Chains: Modifying any file requires updating its parent directory, which requires updating that directory’s parent, all the way to the root.
§Supported Operations
- mkdir - Create directories (like
mkdir -p) - write_bytes - Write files from byte slices
- ls - List directory contents
- stat - Get file/directory metadata
- cp - Copy files or directories
- mv - Move/rename files or directories
- rm - Remove files or directories
- root_cid - Get the current root CID
- flush - Ensure changes are persisted
§Example Usage
use helia_mfs::{mfs, MfsInterface};
use rust_helia::create_helia_default;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a Helia node
let helia = Arc::new(create_helia_default().await?);
// Create an MFS instance
let fs = mfs(helia);
// Create a directory
fs.mkdir("/documents").await?;
// Write a file
fs.write_bytes("/documents/hello.txt", b"Hello, IPFS!").await?;
// List contents
let entries = fs.ls("/documents").await?;
for entry in entries {
println!("{}: {} bytes", entry.name, entry.size);
}
// Copy a file
fs.cp("/documents/hello.txt", "/documents/hello_copy.txt").await?;
// Move a file
fs.mv("/documents/hello_copy.txt", "/backup.txt").await?;
// Remove a file
fs.rm("/backup.txt", false).await?;
// Get the root CID (represents your entire file system)
if let Some(root) = fs.root_cid().await {
println!("File system root: {}", root);
}
Ok(())
}§Performance Considerations
- Copy Operations: Copying files is O(1) in space - only directory metadata is copied, not the actual file content.
- Deep Paths: Operations on deeply nested paths require updating the entire directory chain from the modified file up to the root.
- Large Directories: Listing and modifying large directories may be slow as all entries must be loaded into memory.
§Thread Safety
All MFS operations are thread-safe and can be called concurrently from multiple
tasks. The root CID is protected by an RwLock to ensure consistency.
§Error Handling
Operations return Result<T, MfsError> where MfsError provides detailed
information about what went wrong. Common errors include:
InvalidPath- Malformed or invalid pathsNotFound- File or directory doesn’t existUnixFs- Underlying UnixFS operation failed
§Limitations
- No Metadata Updates: Operations like
touch()(update timestamps) andchmod()(change permissions) would require recreating content with new metadata, which is not yet implemented. - No Streaming: Large files must fit in memory during write operations.
- No Transactions: Operations are not transactional beyond atomic
mv().
Structs§
- Default
Mfs - Default MFS implementation
- MfsPath
- Represents a parsed MFS path
Enums§
- MfsError
- Error types for MFS operations
Traits§
- MfsInterface
- Trait defining the MFS interface
Functions§
- mfs
- Create an MFS instance