embeddenator_cli/commands/
mount.rs1#[cfg(feature = "fuse")]
4use anyhow::Result;
5#[cfg(feature = "fuse")]
6use embeddenator_fs::embrfs::{EmbrFS, DEFAULT_CHUNK_SIZE};
7#[cfg(feature = "fuse")]
8use embeddenator_fs::fuse_shim::{EngramFS, MountOptions, mount};
9#[cfg(feature = "fuse")]
10use embeddenator_vsa::ReversibleVSAConfig;
11#[cfg(feature = "fuse")]
12use std::path::PathBuf;
13
14#[cfg(feature = "fuse")]
15pub fn handle_mount(
16 engram: PathBuf,
17 manifest: PathBuf,
18 mountpoint: PathBuf,
19 allow_other: bool,
20 _foreground: bool,
21 verbose: bool,
22) -> Result<()> {
23 if verbose {
24 println!(
25 "Embeddenator v{} - FUSE Mount",
26 env!("CARGO_PKG_VERSION")
27 );
28 println!("============================");
29 }
30
31 let engram_data = EmbrFS::load_engram(&engram)?;
33 let manifest_data = EmbrFS::load_manifest(&manifest)?;
34 let config = ReversibleVSAConfig::default();
35
36 if verbose {
37 println!("Loaded engram: {}", engram.display());
38 println!("Loaded manifest: {} files", manifest_data.files.len());
39 }
40
41 let fuse_fs = EngramFS::new(true);
43
44 for file_entry in &manifest_data.files {
45 let mut reconstructed = Vec::new();
47
48 for &chunk_id in &file_entry.chunks {
49 if let Some(chunk_vec) = engram_data.codebook.get(&chunk_id) {
50 let decoded = chunk_vec.decode_data(
53 &config,
54 Some(&file_entry.path),
55 DEFAULT_CHUNK_SIZE,
56 );
57
58 let chunk_data = if let Some(corrected) =
60 engram_data.corrections.apply(chunk_id as u64, &decoded)
61 {
62 corrected
63 } else {
64 decoded
66 };
67
68 reconstructed.extend_from_slice(&chunk_data);
69 }
70 }
71
72 reconstructed.truncate(file_entry.size);
74
75 if let Err(e) = fuse_fs.add_file(&file_entry.path, reconstructed) {
77 if verbose {
78 eprintln!("Warning: Failed to add {}: {}", file_entry.path, e);
79 }
80 }
81 }
82
83 if verbose {
84 println!(
85 "Populated {} files into FUSE filesystem",
86 fuse_fs.file_count()
87 );
88 println!("Total size: {} bytes", fuse_fs.total_size());
89 println!("Mounting at: {}", mountpoint.display());
90 println!();
91 }
92
93 if !mountpoint.exists() {
95 anyhow::bail!("Mountpoint does not exist: {}", mountpoint.display());
96 }
97
98 let options = MountOptions {
100 read_only: true,
101 allow_other,
102 allow_root: !allow_other,
103 fsname: format!("engram:{}", engram.display()),
104 };
105
106 println!("EngramFS mounted at {}", mountpoint.display());
108 println!(
109 "Use 'fusermount -u {}' to unmount",
110 mountpoint.display()
111 );
112
113 mount(fuse_fs, &mountpoint, options)?;
114
115 if verbose {
116 println!("\nUnmounted.");
117 }
118
119 Ok(())
120}
121
122#[cfg(not(feature = "fuse"))]
123pub fn handle_mount(
124 _engram: std::path::PathBuf,
125 _manifest: std::path::PathBuf,
126 _mountpoint: std::path::PathBuf,
127 _allow_other: bool,
128 _foreground: bool,
129 _verbose: bool,
130) -> anyhow::Result<()> {
131 anyhow::bail!("FUSE support not enabled. Build with --features fuse")
132}