See files.
Last active
August 2, 2025 12:58
-
-
Save rarensu/fc664da955f9f3a6d57eba3a4632bede to your computer and use it in GitHub Desktop.
Examples for modular fuse components for fuser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[test] | |
| fn test_encryptfs_read() { | |
| // Prepare ciphertext | |
| let key = vec![1, 2, 3, 4, 5, 6, 7, 8]; | |
| let plaintext = b"hello world"; | |
| let ciphertext = simple_crypt::encrypt(plaintext, &key).expect("Encryption failed"); | |
| // Prepare a read request | |
| let req = RequestMeta { | |
| unique: 1, | |
| uid: 1000, | |
| gid: 1000, | |
| pid: 1000, | |
| }; | |
| let fh = 1u64; | |
| let offset = 0i64; | |
| let size = ciphertext.len() as u32; | |
| let flags_i32 = 0i32; | |
| let lock_owner = None; | |
| // Setup AssertFS to expect a read() and return the prepared ciphertext | |
| let mut assert_fs = AssertFS::new(); | |
| assert_fs.set_read_in(req, 1, fh, offset, size, flags_i32, lock_owner); | |
| assert_fs.set_read_out(Ok(Bytes::from(ciphertext))); | |
| // Setup EncryptFS with AssertFS as inner filesystem | |
| let mut encrypt_fs = EncryptFS::new(key.clone(), new_fs_box(assert_fs)); | |
| // Perform the read operation | |
| let read_result = encrypt_fs.read(req, 1, fh, offset, size, flags_i32, lock_owner); | |
| // Assert that the decrypted data matches the original plaintext | |
| assert!(read_result.is_ok()); | |
| let decrypted_data = read_result.unwrap(); | |
| assert_eq!(decrypted_data.as_ref(), plaintext); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Example six-layer filesystem by Richard Lawrence 2025/07/30 | |
| /* | |
| 1 BranchFS | |
| 2 ├─ MonitorFS | |
| 3 │ └─ CacheFS | |
| 4 │ └─ EncryptFS | |
| 5 │ └─ BindFS | |
| 6 └─ EmptyFS | |
| */ | |
| use std::{path::PathBuf, time::Duration}; | |
| use fuser::{MountOption}; | |
| use log::info; | |
| use clap::Parser; | |
| use fuse_components::{ | |
| BranchFS, BindFS, MonitorFS, CacheFS, EncryptFS, EmptyFS, | |
| new_fs_box, new_fs_layer_box | |
| }; | |
| #[derive(Parser, Debug)] | |
| #[command(author = "Richard Lawrence", version = "0.1", about = "Fuse Layered Filesystem", long_about = None)] | |
| struct Args { | |
| /// The path to the mount point | |
| #[arg(short, long = "mountpoint")] | |
| mountpoint: String, | |
| /// The path to the underlying directory for BindFS | |
| #[arg(short, long = "bind-path")] | |
| bind_path: String, | |
| /// Password for the EncryptFS | |
| #[arg(short, long = "password")] | |
| password: String, | |
| } | |
| /// Helper function to build example six-layer filesystem | |
| fn construct_six_layer_filesystem(bind_path: PathBuf, password: Vec<u8>) -> BranchFS { | |
| // Outer filesystem layer is a BranchFS | |
| /* 1 */ | |
| let mut outer_fs = BranchFS::default(); | |
| // Nested branch containing layers 2,3,4,5 | |
| let nested_branch = new_fs_box( | |
| /* 2 */ | |
| MonitorFS { | |
| name: "before cache".to_owned(), | |
| inner: new_fs_layer_box( | |
| /* 3 */ | |
| CacheFS::new( | |
| Duration::new(10, 0), | |
| 128, | |
| 128, | |
| 128, | |
| new_fs_layer_box( | |
| /* 4 */ | |
| EncryptFS::new( | |
| Vec::from(password), | |
| new_fs_box( | |
| /* 5 */ | |
| BindFS::new(bind_path) | |
| ) | |
| ) | |
| ) | |
| ) | |
| ) | |
| } | |
| ); | |
| /* 6 */ | |
| let empty_branch = new_fs_box(EmptyFS); | |
| // Mount the nested branch at the root of the filesystem (overwrites default) | |
| outer_fs.insert_branch(0, nested_branch, PathBuf::from("")); | |
| // Mount the empty branch under a subdirectory named "empty" | |
| outer_fs.insert_branch(1, empty_branch, PathBuf::from("empty")); | |
| // Return | |
| outer_fs | |
| } | |
| fn main() -> Result<(), i32> { | |
| env_logger::init(); | |
| let args = Args::parse(); | |
| let mountpoint = PathBuf::from(&args.mountpoint); | |
| let bind_path = PathBuf::from(&args.bind_path); | |
| let password= Vec::from(args.password); | |
| info!("Building filesystem with bind path {:?} (and secret password)", bind_path); | |
| let fs = construct_six_layer_filesystem(bind_path, password); | |
| let options = vec![ | |
| MountOption::FSName("fuse example".to_string()), | |
| ]; | |
| info!("Mounting filesystem at {:?}", mountpoint); | |
| let mut session = fuser::Session::new(fs, &mountpoint, &options).unwrap(); | |
| // wait for the session to finish | |
| session.run_with_notifications().unwrap(); | |
| info!("Filesystem unmounted"); | |
| Ok(()) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment