pub struct FilesystemCore { /* private fields */ }Expand description
The main filesystem core. Owns the block store, crypto, codec, allocator, and transaction manager. Provides high-level filesystem operations.
Implementations§
Source§impl FilesystemCore
impl FilesystemCore
Sourcepub fn new(store: Arc<dyn BlockStore>, crypto: Arc<dyn CryptoEngine>) -> Self
pub fn new(store: Arc<dyn BlockStore>, crypto: Arc<dyn CryptoEngine>) -> Self
Create a new FilesystemCore backed by the given store and crypto engine.
Examples found in repository?
15fn main() {
16 let path = std::env::current_dir()
17 .unwrap()
18 .join("sample.dcfs")
19 .to_string_lossy()
20 .to_string();
21
22 // Remove leftover from a previous run, if any.
23 let _ = std::fs::remove_file(&path);
24
25 // 64 blocks × 64 KiB = 4 MiB image.
26 let total_blocks: u64 = 64;
27 let store = Arc::new(
28 DiskBlockStore::create(&path, DEFAULT_BLOCK_SIZE, total_blocks)
29 .expect("failed to create image file"),
30 );
31
32 let crypto = Arc::new(ChaChaEngine::generate().expect("failed to init crypto"));
33 let mut fs = FilesystemCore::new(store, crypto);
34
35 fs.init_filesystem().expect("init_filesystem failed");
36
37 // Create a text file.
38 fs.create_file("hello.txt").expect("create_file failed");
39 fs.write_file("hello.txt", 0, b"Hello, hex editor!")
40 .expect("write_file failed");
41
42 // Create a directory.
43 fs.create_directory("notes")
44 .expect("create_directory failed");
45
46 // Create a larger binary file so there's more to look at.
47 let pattern: Vec<u8> = (0..=255).cycle().take(200_000).collect();
48 fs.create_file("pattern.bin").expect("create_file failed");
49 fs.write_file("pattern.bin", 0, &pattern)
50 .expect("write_file failed");
51
52 fs.sync().expect("sync failed");
53
54 println!("Filesystem image written to:\n {path}");
55 println!(
56 " {} blocks × {} bytes = {} bytes total",
57 total_blocks,
58 DEFAULT_BLOCK_SIZE,
59 total_blocks as usize * DEFAULT_BLOCK_SIZE
60 );
61}More examples
22fn main() {
23 let args: Vec<String> = std::env::args().collect();
24
25 let mut addr = "127.0.0.1:9100";
26 let mut server_name = "localhost";
27 let mut cert = "certs/client.pem";
28 let mut key = "certs/client-key.pem";
29 let mut ca = "certs/ca.pem";
30 let mut master_key_hex = "";
31 let mut init = false;
32
33 let mut i = 1;
34 while i < args.len() {
35 match args[i].as_str() {
36 "--addr" => {
37 addr = &args[i + 1];
38 i += 2;
39 }
40 "--server-name" => {
41 server_name = &args[i + 1];
42 i += 2;
43 }
44 "--cert" => {
45 cert = &args[i + 1];
46 i += 2;
47 }
48 "--key" => {
49 key = &args[i + 1];
50 i += 2;
51 }
52 "--ca" => {
53 ca = &args[i + 1];
54 i += 2;
55 }
56 "--master-key" => {
57 master_key_hex = &args[i + 1];
58 i += 2;
59 }
60 "--init" => {
61 init = true;
62 i += 1;
63 }
64 other => {
65 eprintln!("unknown argument: {other}");
66 std::process::exit(1);
67 }
68 }
69 }
70
71 if master_key_hex.is_empty() || master_key_hex.len() != 64 {
72 eprintln!("--master-key must be a 64-character hex string (32 bytes)");
73 std::process::exit(1);
74 }
75
76 let master_key: Vec<u8> = (0..32)
77 .map(|i| u8::from_str_radix(&master_key_hex[i * 2..i * 2 + 2], 16).unwrap())
78 .collect();
79
80 // ── Connect ─────────────────────────────────────────────
81 println!("Connecting to {addr} (SNI: {server_name})...");
82 let net = NetworkBlockStore::connect(
83 addr,
84 server_name,
85 Path::new(cert),
86 Path::new(key),
87 Path::new(ca),
88 )
89 .expect("failed to connect to server");
90
91 println!(
92 "Connected: {} blocks × {} bytes ({} MiB)",
93 net.total_blocks(),
94 net.block_size(),
95 net.total_blocks() as usize * net.block_size() / (1024 * 1024)
96 );
97
98 // ── Wrap with cache ─────────────────────────────────────
99 let store = Arc::new(CachedBlockStore::new(net, 1024));
100 let crypto = Arc::new(ChaChaEngine::new(&master_key).expect("invalid master key"));
101 let mut fs = FilesystemCore::new(store.clone(), crypto);
102
103 // ── Mount or init ───────────────────────────────────────
104 if init {
105 println!("Initializing new filesystem...");
106 fs.init_filesystem().expect("init_filesystem failed");
107 } else {
108 println!("Mounting existing filesystem...");
109 fs.open().expect("open failed");
110 }
111
112 // ── Demo operations ─────────────────────────────────────
113 println!("\nCreating file 'hello.txt'...");
114 match fs.create_file("hello.txt") {
115 Ok(()) => {}
116 Err(e) => println!(" (skipped: {e})"),
117 }
118
119 fs.write_file("hello.txt", 0, b"Hello from the network!")
120 .expect("write failed");
121
122 let data = fs.read_file("hello.txt", 0, 4096).expect("read failed");
123 println!("Read back: {:?}", String::from_utf8_lossy(&data));
124
125 println!("\nListing root directory:");
126 for entry in fs.list_directory().expect("list failed") {
127 println!(
128 " {:?} {:>10} bytes {}",
129 entry.kind, entry.size, entry.name
130 );
131 }
132
133 // ── Sync ────────────────────────────────────────────────
134 fs.sync().expect("sync failed");
135 println!("\nAll data synced to server.");
136}Sourcepub fn init_filesystem(&mut self) -> FsResult<()>
pub fn init_filesystem(&mut self) -> FsResult<()>
Initialize a brand-new filesystem on the block store. Writes the storage header, creates the root directory, and commits.
Examples found in repository?
15fn main() {
16 let path = std::env::current_dir()
17 .unwrap()
18 .join("sample.dcfs")
19 .to_string_lossy()
20 .to_string();
21
22 // Remove leftover from a previous run, if any.
23 let _ = std::fs::remove_file(&path);
24
25 // 64 blocks × 64 KiB = 4 MiB image.
26 let total_blocks: u64 = 64;
27 let store = Arc::new(
28 DiskBlockStore::create(&path, DEFAULT_BLOCK_SIZE, total_blocks)
29 .expect("failed to create image file"),
30 );
31
32 let crypto = Arc::new(ChaChaEngine::generate().expect("failed to init crypto"));
33 let mut fs = FilesystemCore::new(store, crypto);
34
35 fs.init_filesystem().expect("init_filesystem failed");
36
37 // Create a text file.
38 fs.create_file("hello.txt").expect("create_file failed");
39 fs.write_file("hello.txt", 0, b"Hello, hex editor!")
40 .expect("write_file failed");
41
42 // Create a directory.
43 fs.create_directory("notes")
44 .expect("create_directory failed");
45
46 // Create a larger binary file so there's more to look at.
47 let pattern: Vec<u8> = (0..=255).cycle().take(200_000).collect();
48 fs.create_file("pattern.bin").expect("create_file failed");
49 fs.write_file("pattern.bin", 0, &pattern)
50 .expect("write_file failed");
51
52 fs.sync().expect("sync failed");
53
54 println!("Filesystem image written to:\n {path}");
55 println!(
56 " {} blocks × {} bytes = {} bytes total",
57 total_blocks,
58 DEFAULT_BLOCK_SIZE,
59 total_blocks as usize * DEFAULT_BLOCK_SIZE
60 );
61}More examples
22fn main() {
23 let args: Vec<String> = std::env::args().collect();
24
25 let mut addr = "127.0.0.1:9100";
26 let mut server_name = "localhost";
27 let mut cert = "certs/client.pem";
28 let mut key = "certs/client-key.pem";
29 let mut ca = "certs/ca.pem";
30 let mut master_key_hex = "";
31 let mut init = false;
32
33 let mut i = 1;
34 while i < args.len() {
35 match args[i].as_str() {
36 "--addr" => {
37 addr = &args[i + 1];
38 i += 2;
39 }
40 "--server-name" => {
41 server_name = &args[i + 1];
42 i += 2;
43 }
44 "--cert" => {
45 cert = &args[i + 1];
46 i += 2;
47 }
48 "--key" => {
49 key = &args[i + 1];
50 i += 2;
51 }
52 "--ca" => {
53 ca = &args[i + 1];
54 i += 2;
55 }
56 "--master-key" => {
57 master_key_hex = &args[i + 1];
58 i += 2;
59 }
60 "--init" => {
61 init = true;
62 i += 1;
63 }
64 other => {
65 eprintln!("unknown argument: {other}");
66 std::process::exit(1);
67 }
68 }
69 }
70
71 if master_key_hex.is_empty() || master_key_hex.len() != 64 {
72 eprintln!("--master-key must be a 64-character hex string (32 bytes)");
73 std::process::exit(1);
74 }
75
76 let master_key: Vec<u8> = (0..32)
77 .map(|i| u8::from_str_radix(&master_key_hex[i * 2..i * 2 + 2], 16).unwrap())
78 .collect();
79
80 // ── Connect ─────────────────────────────────────────────
81 println!("Connecting to {addr} (SNI: {server_name})...");
82 let net = NetworkBlockStore::connect(
83 addr,
84 server_name,
85 Path::new(cert),
86 Path::new(key),
87 Path::new(ca),
88 )
89 .expect("failed to connect to server");
90
91 println!(
92 "Connected: {} blocks × {} bytes ({} MiB)",
93 net.total_blocks(),
94 net.block_size(),
95 net.total_blocks() as usize * net.block_size() / (1024 * 1024)
96 );
97
98 // ── Wrap with cache ─────────────────────────────────────
99 let store = Arc::new(CachedBlockStore::new(net, 1024));
100 let crypto = Arc::new(ChaChaEngine::new(&master_key).expect("invalid master key"));
101 let mut fs = FilesystemCore::new(store.clone(), crypto);
102
103 // ── Mount or init ───────────────────────────────────────
104 if init {
105 println!("Initializing new filesystem...");
106 fs.init_filesystem().expect("init_filesystem failed");
107 } else {
108 println!("Mounting existing filesystem...");
109 fs.open().expect("open failed");
110 }
111
112 // ── Demo operations ─────────────────────────────────────
113 println!("\nCreating file 'hello.txt'...");
114 match fs.create_file("hello.txt") {
115 Ok(()) => {}
116 Err(e) => println!(" (skipped: {e})"),
117 }
118
119 fs.write_file("hello.txt", 0, b"Hello from the network!")
120 .expect("write failed");
121
122 let data = fs.read_file("hello.txt", 0, 4096).expect("read failed");
123 println!("Read back: {:?}", String::from_utf8_lossy(&data));
124
125 println!("\nListing root directory:");
126 for entry in fs.list_directory().expect("list failed") {
127 println!(
128 " {:?} {:>10} bytes {}",
129 entry.kind, entry.size, entry.name
130 );
131 }
132
133 // ── Sync ────────────────────────────────────────────────
134 fs.sync().expect("sync failed");
135 println!("\nAll data synced to server.");
136}Sourcepub fn open(&mut self) -> FsResult<()>
pub fn open(&mut self) -> FsResult<()>
Open / mount an existing filesystem by recovering the latest root pointer.
Examples found in repository?
22fn main() {
23 let args: Vec<String> = std::env::args().collect();
24
25 let mut addr = "127.0.0.1:9100";
26 let mut server_name = "localhost";
27 let mut cert = "certs/client.pem";
28 let mut key = "certs/client-key.pem";
29 let mut ca = "certs/ca.pem";
30 let mut master_key_hex = "";
31 let mut init = false;
32
33 let mut i = 1;
34 while i < args.len() {
35 match args[i].as_str() {
36 "--addr" => {
37 addr = &args[i + 1];
38 i += 2;
39 }
40 "--server-name" => {
41 server_name = &args[i + 1];
42 i += 2;
43 }
44 "--cert" => {
45 cert = &args[i + 1];
46 i += 2;
47 }
48 "--key" => {
49 key = &args[i + 1];
50 i += 2;
51 }
52 "--ca" => {
53 ca = &args[i + 1];
54 i += 2;
55 }
56 "--master-key" => {
57 master_key_hex = &args[i + 1];
58 i += 2;
59 }
60 "--init" => {
61 init = true;
62 i += 1;
63 }
64 other => {
65 eprintln!("unknown argument: {other}");
66 std::process::exit(1);
67 }
68 }
69 }
70
71 if master_key_hex.is_empty() || master_key_hex.len() != 64 {
72 eprintln!("--master-key must be a 64-character hex string (32 bytes)");
73 std::process::exit(1);
74 }
75
76 let master_key: Vec<u8> = (0..32)
77 .map(|i| u8::from_str_radix(&master_key_hex[i * 2..i * 2 + 2], 16).unwrap())
78 .collect();
79
80 // ── Connect ─────────────────────────────────────────────
81 println!("Connecting to {addr} (SNI: {server_name})...");
82 let net = NetworkBlockStore::connect(
83 addr,
84 server_name,
85 Path::new(cert),
86 Path::new(key),
87 Path::new(ca),
88 )
89 .expect("failed to connect to server");
90
91 println!(
92 "Connected: {} blocks × {} bytes ({} MiB)",
93 net.total_blocks(),
94 net.block_size(),
95 net.total_blocks() as usize * net.block_size() / (1024 * 1024)
96 );
97
98 // ── Wrap with cache ─────────────────────────────────────
99 let store = Arc::new(CachedBlockStore::new(net, 1024));
100 let crypto = Arc::new(ChaChaEngine::new(&master_key).expect("invalid master key"));
101 let mut fs = FilesystemCore::new(store.clone(), crypto);
102
103 // ── Mount or init ───────────────────────────────────────
104 if init {
105 println!("Initializing new filesystem...");
106 fs.init_filesystem().expect("init_filesystem failed");
107 } else {
108 println!("Mounting existing filesystem...");
109 fs.open().expect("open failed");
110 }
111
112 // ── Demo operations ─────────────────────────────────────
113 println!("\nCreating file 'hello.txt'...");
114 match fs.create_file("hello.txt") {
115 Ok(()) => {}
116 Err(e) => println!(" (skipped: {e})"),
117 }
118
119 fs.write_file("hello.txt", 0, b"Hello from the network!")
120 .expect("write failed");
121
122 let data = fs.read_file("hello.txt", 0, 4096).expect("read failed");
123 println!("Read back: {:?}", String::from_utf8_lossy(&data));
124
125 println!("\nListing root directory:");
126 for entry in fs.list_directory().expect("list failed") {
127 println!(
128 " {:?} {:>10} bytes {}",
129 entry.kind, entry.size, entry.name
130 );
131 }
132
133 // ── Sync ────────────────────────────────────────────────
134 fs.sync().expect("sync failed");
135 println!("\nAll data synced to server.");
136}Sourcepub fn create_file(&mut self, name: &str) -> FsResult<()>
pub fn create_file(&mut self, name: &str) -> FsResult<()>
Create a new empty file in the given directory (by inode ref). For V1, only root directory is supported.
Examples found in repository?
15fn main() {
16 let path = std::env::current_dir()
17 .unwrap()
18 .join("sample.dcfs")
19 .to_string_lossy()
20 .to_string();
21
22 // Remove leftover from a previous run, if any.
23 let _ = std::fs::remove_file(&path);
24
25 // 64 blocks × 64 KiB = 4 MiB image.
26 let total_blocks: u64 = 64;
27 let store = Arc::new(
28 DiskBlockStore::create(&path, DEFAULT_BLOCK_SIZE, total_blocks)
29 .expect("failed to create image file"),
30 );
31
32 let crypto = Arc::new(ChaChaEngine::generate().expect("failed to init crypto"));
33 let mut fs = FilesystemCore::new(store, crypto);
34
35 fs.init_filesystem().expect("init_filesystem failed");
36
37 // Create a text file.
38 fs.create_file("hello.txt").expect("create_file failed");
39 fs.write_file("hello.txt", 0, b"Hello, hex editor!")
40 .expect("write_file failed");
41
42 // Create a directory.
43 fs.create_directory("notes")
44 .expect("create_directory failed");
45
46 // Create a larger binary file so there's more to look at.
47 let pattern: Vec<u8> = (0..=255).cycle().take(200_000).collect();
48 fs.create_file("pattern.bin").expect("create_file failed");
49 fs.write_file("pattern.bin", 0, &pattern)
50 .expect("write_file failed");
51
52 fs.sync().expect("sync failed");
53
54 println!("Filesystem image written to:\n {path}");
55 println!(
56 " {} blocks × {} bytes = {} bytes total",
57 total_blocks,
58 DEFAULT_BLOCK_SIZE,
59 total_blocks as usize * DEFAULT_BLOCK_SIZE
60 );
61}More examples
22fn main() {
23 let args: Vec<String> = std::env::args().collect();
24
25 let mut addr = "127.0.0.1:9100";
26 let mut server_name = "localhost";
27 let mut cert = "certs/client.pem";
28 let mut key = "certs/client-key.pem";
29 let mut ca = "certs/ca.pem";
30 let mut master_key_hex = "";
31 let mut init = false;
32
33 let mut i = 1;
34 while i < args.len() {
35 match args[i].as_str() {
36 "--addr" => {
37 addr = &args[i + 1];
38 i += 2;
39 }
40 "--server-name" => {
41 server_name = &args[i + 1];
42 i += 2;
43 }
44 "--cert" => {
45 cert = &args[i + 1];
46 i += 2;
47 }
48 "--key" => {
49 key = &args[i + 1];
50 i += 2;
51 }
52 "--ca" => {
53 ca = &args[i + 1];
54 i += 2;
55 }
56 "--master-key" => {
57 master_key_hex = &args[i + 1];
58 i += 2;
59 }
60 "--init" => {
61 init = true;
62 i += 1;
63 }
64 other => {
65 eprintln!("unknown argument: {other}");
66 std::process::exit(1);
67 }
68 }
69 }
70
71 if master_key_hex.is_empty() || master_key_hex.len() != 64 {
72 eprintln!("--master-key must be a 64-character hex string (32 bytes)");
73 std::process::exit(1);
74 }
75
76 let master_key: Vec<u8> = (0..32)
77 .map(|i| u8::from_str_radix(&master_key_hex[i * 2..i * 2 + 2], 16).unwrap())
78 .collect();
79
80 // ── Connect ─────────────────────────────────────────────
81 println!("Connecting to {addr} (SNI: {server_name})...");
82 let net = NetworkBlockStore::connect(
83 addr,
84 server_name,
85 Path::new(cert),
86 Path::new(key),
87 Path::new(ca),
88 )
89 .expect("failed to connect to server");
90
91 println!(
92 "Connected: {} blocks × {} bytes ({} MiB)",
93 net.total_blocks(),
94 net.block_size(),
95 net.total_blocks() as usize * net.block_size() / (1024 * 1024)
96 );
97
98 // ── Wrap with cache ─────────────────────────────────────
99 let store = Arc::new(CachedBlockStore::new(net, 1024));
100 let crypto = Arc::new(ChaChaEngine::new(&master_key).expect("invalid master key"));
101 let mut fs = FilesystemCore::new(store.clone(), crypto);
102
103 // ── Mount or init ───────────────────────────────────────
104 if init {
105 println!("Initializing new filesystem...");
106 fs.init_filesystem().expect("init_filesystem failed");
107 } else {
108 println!("Mounting existing filesystem...");
109 fs.open().expect("open failed");
110 }
111
112 // ── Demo operations ─────────────────────────────────────
113 println!("\nCreating file 'hello.txt'...");
114 match fs.create_file("hello.txt") {
115 Ok(()) => {}
116 Err(e) => println!(" (skipped: {e})"),
117 }
118
119 fs.write_file("hello.txt", 0, b"Hello from the network!")
120 .expect("write failed");
121
122 let data = fs.read_file("hello.txt", 0, 4096).expect("read failed");
123 println!("Read back: {:?}", String::from_utf8_lossy(&data));
124
125 println!("\nListing root directory:");
126 for entry in fs.list_directory().expect("list failed") {
127 println!(
128 " {:?} {:>10} bytes {}",
129 entry.kind, entry.size, entry.name
130 );
131 }
132
133 // ── Sync ────────────────────────────────────────────────
134 fs.sync().expect("sync failed");
135 println!("\nAll data synced to server.");
136}Sourcepub fn write_file(
&mut self,
name: &str,
offset: u64,
data: &[u8],
) -> FsResult<()>
pub fn write_file( &mut self, name: &str, offset: u64, data: &[u8], ) -> FsResult<()>
Write data to a file. For V1, this replaces the entire file content (single chunk only if it fits in one block).
Examples found in repository?
15fn main() {
16 let path = std::env::current_dir()
17 .unwrap()
18 .join("sample.dcfs")
19 .to_string_lossy()
20 .to_string();
21
22 // Remove leftover from a previous run, if any.
23 let _ = std::fs::remove_file(&path);
24
25 // 64 blocks × 64 KiB = 4 MiB image.
26 let total_blocks: u64 = 64;
27 let store = Arc::new(
28 DiskBlockStore::create(&path, DEFAULT_BLOCK_SIZE, total_blocks)
29 .expect("failed to create image file"),
30 );
31
32 let crypto = Arc::new(ChaChaEngine::generate().expect("failed to init crypto"));
33 let mut fs = FilesystemCore::new(store, crypto);
34
35 fs.init_filesystem().expect("init_filesystem failed");
36
37 // Create a text file.
38 fs.create_file("hello.txt").expect("create_file failed");
39 fs.write_file("hello.txt", 0, b"Hello, hex editor!")
40 .expect("write_file failed");
41
42 // Create a directory.
43 fs.create_directory("notes")
44 .expect("create_directory failed");
45
46 // Create a larger binary file so there's more to look at.
47 let pattern: Vec<u8> = (0..=255).cycle().take(200_000).collect();
48 fs.create_file("pattern.bin").expect("create_file failed");
49 fs.write_file("pattern.bin", 0, &pattern)
50 .expect("write_file failed");
51
52 fs.sync().expect("sync failed");
53
54 println!("Filesystem image written to:\n {path}");
55 println!(
56 " {} blocks × {} bytes = {} bytes total",
57 total_blocks,
58 DEFAULT_BLOCK_SIZE,
59 total_blocks as usize * DEFAULT_BLOCK_SIZE
60 );
61}More examples
22fn main() {
23 let args: Vec<String> = std::env::args().collect();
24
25 let mut addr = "127.0.0.1:9100";
26 let mut server_name = "localhost";
27 let mut cert = "certs/client.pem";
28 let mut key = "certs/client-key.pem";
29 let mut ca = "certs/ca.pem";
30 let mut master_key_hex = "";
31 let mut init = false;
32
33 let mut i = 1;
34 while i < args.len() {
35 match args[i].as_str() {
36 "--addr" => {
37 addr = &args[i + 1];
38 i += 2;
39 }
40 "--server-name" => {
41 server_name = &args[i + 1];
42 i += 2;
43 }
44 "--cert" => {
45 cert = &args[i + 1];
46 i += 2;
47 }
48 "--key" => {
49 key = &args[i + 1];
50 i += 2;
51 }
52 "--ca" => {
53 ca = &args[i + 1];
54 i += 2;
55 }
56 "--master-key" => {
57 master_key_hex = &args[i + 1];
58 i += 2;
59 }
60 "--init" => {
61 init = true;
62 i += 1;
63 }
64 other => {
65 eprintln!("unknown argument: {other}");
66 std::process::exit(1);
67 }
68 }
69 }
70
71 if master_key_hex.is_empty() || master_key_hex.len() != 64 {
72 eprintln!("--master-key must be a 64-character hex string (32 bytes)");
73 std::process::exit(1);
74 }
75
76 let master_key: Vec<u8> = (0..32)
77 .map(|i| u8::from_str_radix(&master_key_hex[i * 2..i * 2 + 2], 16).unwrap())
78 .collect();
79
80 // ── Connect ─────────────────────────────────────────────
81 println!("Connecting to {addr} (SNI: {server_name})...");
82 let net = NetworkBlockStore::connect(
83 addr,
84 server_name,
85 Path::new(cert),
86 Path::new(key),
87 Path::new(ca),
88 )
89 .expect("failed to connect to server");
90
91 println!(
92 "Connected: {} blocks × {} bytes ({} MiB)",
93 net.total_blocks(),
94 net.block_size(),
95 net.total_blocks() as usize * net.block_size() / (1024 * 1024)
96 );
97
98 // ── Wrap with cache ─────────────────────────────────────
99 let store = Arc::new(CachedBlockStore::new(net, 1024));
100 let crypto = Arc::new(ChaChaEngine::new(&master_key).expect("invalid master key"));
101 let mut fs = FilesystemCore::new(store.clone(), crypto);
102
103 // ── Mount or init ───────────────────────────────────────
104 if init {
105 println!("Initializing new filesystem...");
106 fs.init_filesystem().expect("init_filesystem failed");
107 } else {
108 println!("Mounting existing filesystem...");
109 fs.open().expect("open failed");
110 }
111
112 // ── Demo operations ─────────────────────────────────────
113 println!("\nCreating file 'hello.txt'...");
114 match fs.create_file("hello.txt") {
115 Ok(()) => {}
116 Err(e) => println!(" (skipped: {e})"),
117 }
118
119 fs.write_file("hello.txt", 0, b"Hello from the network!")
120 .expect("write failed");
121
122 let data = fs.read_file("hello.txt", 0, 4096).expect("read failed");
123 println!("Read back: {:?}", String::from_utf8_lossy(&data));
124
125 println!("\nListing root directory:");
126 for entry in fs.list_directory().expect("list failed") {
127 println!(
128 " {:?} {:>10} bytes {}",
129 entry.kind, entry.size, entry.name
130 );
131 }
132
133 // ── Sync ────────────────────────────────────────────────
134 fs.sync().expect("sync failed");
135 println!("\nAll data synced to server.");
136}Sourcepub fn read_file(
&self,
name: &str,
offset: u64,
len: usize,
) -> FsResult<Vec<u8>>
pub fn read_file( &self, name: &str, offset: u64, len: usize, ) -> FsResult<Vec<u8>>
Read file data. Returns the requested slice of the file.
Examples found in repository?
22fn main() {
23 let args: Vec<String> = std::env::args().collect();
24
25 let mut addr = "127.0.0.1:9100";
26 let mut server_name = "localhost";
27 let mut cert = "certs/client.pem";
28 let mut key = "certs/client-key.pem";
29 let mut ca = "certs/ca.pem";
30 let mut master_key_hex = "";
31 let mut init = false;
32
33 let mut i = 1;
34 while i < args.len() {
35 match args[i].as_str() {
36 "--addr" => {
37 addr = &args[i + 1];
38 i += 2;
39 }
40 "--server-name" => {
41 server_name = &args[i + 1];
42 i += 2;
43 }
44 "--cert" => {
45 cert = &args[i + 1];
46 i += 2;
47 }
48 "--key" => {
49 key = &args[i + 1];
50 i += 2;
51 }
52 "--ca" => {
53 ca = &args[i + 1];
54 i += 2;
55 }
56 "--master-key" => {
57 master_key_hex = &args[i + 1];
58 i += 2;
59 }
60 "--init" => {
61 init = true;
62 i += 1;
63 }
64 other => {
65 eprintln!("unknown argument: {other}");
66 std::process::exit(1);
67 }
68 }
69 }
70
71 if master_key_hex.is_empty() || master_key_hex.len() != 64 {
72 eprintln!("--master-key must be a 64-character hex string (32 bytes)");
73 std::process::exit(1);
74 }
75
76 let master_key: Vec<u8> = (0..32)
77 .map(|i| u8::from_str_radix(&master_key_hex[i * 2..i * 2 + 2], 16).unwrap())
78 .collect();
79
80 // ── Connect ─────────────────────────────────────────────
81 println!("Connecting to {addr} (SNI: {server_name})...");
82 let net = NetworkBlockStore::connect(
83 addr,
84 server_name,
85 Path::new(cert),
86 Path::new(key),
87 Path::new(ca),
88 )
89 .expect("failed to connect to server");
90
91 println!(
92 "Connected: {} blocks × {} bytes ({} MiB)",
93 net.total_blocks(),
94 net.block_size(),
95 net.total_blocks() as usize * net.block_size() / (1024 * 1024)
96 );
97
98 // ── Wrap with cache ─────────────────────────────────────
99 let store = Arc::new(CachedBlockStore::new(net, 1024));
100 let crypto = Arc::new(ChaChaEngine::new(&master_key).expect("invalid master key"));
101 let mut fs = FilesystemCore::new(store.clone(), crypto);
102
103 // ── Mount or init ───────────────────────────────────────
104 if init {
105 println!("Initializing new filesystem...");
106 fs.init_filesystem().expect("init_filesystem failed");
107 } else {
108 println!("Mounting existing filesystem...");
109 fs.open().expect("open failed");
110 }
111
112 // ── Demo operations ─────────────────────────────────────
113 println!("\nCreating file 'hello.txt'...");
114 match fs.create_file("hello.txt") {
115 Ok(()) => {}
116 Err(e) => println!(" (skipped: {e})"),
117 }
118
119 fs.write_file("hello.txt", 0, b"Hello from the network!")
120 .expect("write failed");
121
122 let data = fs.read_file("hello.txt", 0, 4096).expect("read failed");
123 println!("Read back: {:?}", String::from_utf8_lossy(&data));
124
125 println!("\nListing root directory:");
126 for entry in fs.list_directory().expect("list failed") {
127 println!(
128 " {:?} {:>10} bytes {}",
129 entry.kind, entry.size, entry.name
130 );
131 }
132
133 // ── Sync ────────────────────────────────────────────────
134 fs.sync().expect("sync failed");
135 println!("\nAll data synced to server.");
136}Sourcepub fn list_directory(&self) -> FsResult<Vec<DirListEntry>>
pub fn list_directory(&self) -> FsResult<Vec<DirListEntry>>
List entries in the root directory.
Examples found in repository?
22fn main() {
23 let args: Vec<String> = std::env::args().collect();
24
25 let mut addr = "127.0.0.1:9100";
26 let mut server_name = "localhost";
27 let mut cert = "certs/client.pem";
28 let mut key = "certs/client-key.pem";
29 let mut ca = "certs/ca.pem";
30 let mut master_key_hex = "";
31 let mut init = false;
32
33 let mut i = 1;
34 while i < args.len() {
35 match args[i].as_str() {
36 "--addr" => {
37 addr = &args[i + 1];
38 i += 2;
39 }
40 "--server-name" => {
41 server_name = &args[i + 1];
42 i += 2;
43 }
44 "--cert" => {
45 cert = &args[i + 1];
46 i += 2;
47 }
48 "--key" => {
49 key = &args[i + 1];
50 i += 2;
51 }
52 "--ca" => {
53 ca = &args[i + 1];
54 i += 2;
55 }
56 "--master-key" => {
57 master_key_hex = &args[i + 1];
58 i += 2;
59 }
60 "--init" => {
61 init = true;
62 i += 1;
63 }
64 other => {
65 eprintln!("unknown argument: {other}");
66 std::process::exit(1);
67 }
68 }
69 }
70
71 if master_key_hex.is_empty() || master_key_hex.len() != 64 {
72 eprintln!("--master-key must be a 64-character hex string (32 bytes)");
73 std::process::exit(1);
74 }
75
76 let master_key: Vec<u8> = (0..32)
77 .map(|i| u8::from_str_radix(&master_key_hex[i * 2..i * 2 + 2], 16).unwrap())
78 .collect();
79
80 // ── Connect ─────────────────────────────────────────────
81 println!("Connecting to {addr} (SNI: {server_name})...");
82 let net = NetworkBlockStore::connect(
83 addr,
84 server_name,
85 Path::new(cert),
86 Path::new(key),
87 Path::new(ca),
88 )
89 .expect("failed to connect to server");
90
91 println!(
92 "Connected: {} blocks × {} bytes ({} MiB)",
93 net.total_blocks(),
94 net.block_size(),
95 net.total_blocks() as usize * net.block_size() / (1024 * 1024)
96 );
97
98 // ── Wrap with cache ─────────────────────────────────────
99 let store = Arc::new(CachedBlockStore::new(net, 1024));
100 let crypto = Arc::new(ChaChaEngine::new(&master_key).expect("invalid master key"));
101 let mut fs = FilesystemCore::new(store.clone(), crypto);
102
103 // ── Mount or init ───────────────────────────────────────
104 if init {
105 println!("Initializing new filesystem...");
106 fs.init_filesystem().expect("init_filesystem failed");
107 } else {
108 println!("Mounting existing filesystem...");
109 fs.open().expect("open failed");
110 }
111
112 // ── Demo operations ─────────────────────────────────────
113 println!("\nCreating file 'hello.txt'...");
114 match fs.create_file("hello.txt") {
115 Ok(()) => {}
116 Err(e) => println!(" (skipped: {e})"),
117 }
118
119 fs.write_file("hello.txt", 0, b"Hello from the network!")
120 .expect("write failed");
121
122 let data = fs.read_file("hello.txt", 0, 4096).expect("read failed");
123 println!("Read back: {:?}", String::from_utf8_lossy(&data));
124
125 println!("\nListing root directory:");
126 for entry in fs.list_directory().expect("list failed") {
127 println!(
128 " {:?} {:>10} bytes {}",
129 entry.kind, entry.size, entry.name
130 );
131 }
132
133 // ── Sync ────────────────────────────────────────────────
134 fs.sync().expect("sync failed");
135 println!("\nAll data synced to server.");
136}Sourcepub fn create_directory(&mut self, name: &str) -> FsResult<()>
pub fn create_directory(&mut self, name: &str) -> FsResult<()>
Create a subdirectory in the root directory.
Examples found in repository?
15fn main() {
16 let path = std::env::current_dir()
17 .unwrap()
18 .join("sample.dcfs")
19 .to_string_lossy()
20 .to_string();
21
22 // Remove leftover from a previous run, if any.
23 let _ = std::fs::remove_file(&path);
24
25 // 64 blocks × 64 KiB = 4 MiB image.
26 let total_blocks: u64 = 64;
27 let store = Arc::new(
28 DiskBlockStore::create(&path, DEFAULT_BLOCK_SIZE, total_blocks)
29 .expect("failed to create image file"),
30 );
31
32 let crypto = Arc::new(ChaChaEngine::generate().expect("failed to init crypto"));
33 let mut fs = FilesystemCore::new(store, crypto);
34
35 fs.init_filesystem().expect("init_filesystem failed");
36
37 // Create a text file.
38 fs.create_file("hello.txt").expect("create_file failed");
39 fs.write_file("hello.txt", 0, b"Hello, hex editor!")
40 .expect("write_file failed");
41
42 // Create a directory.
43 fs.create_directory("notes")
44 .expect("create_directory failed");
45
46 // Create a larger binary file so there's more to look at.
47 let pattern: Vec<u8> = (0..=255).cycle().take(200_000).collect();
48 fs.create_file("pattern.bin").expect("create_file failed");
49 fs.write_file("pattern.bin", 0, &pattern)
50 .expect("write_file failed");
51
52 fs.sync().expect("sync failed");
53
54 println!("Filesystem image written to:\n {path}");
55 println!(
56 " {} blocks × {} bytes = {} bytes total",
57 total_blocks,
58 DEFAULT_BLOCK_SIZE,
59 total_blocks as usize * DEFAULT_BLOCK_SIZE
60 );
61}Sourcepub fn remove_file(&mut self, name: &str) -> FsResult<()>
pub fn remove_file(&mut self, name: &str) -> FsResult<()>
Remove a file from the root directory.
Sourcepub fn rename(&mut self, old_name: &str, new_name: &str) -> FsResult<()>
pub fn rename(&mut self, old_name: &str, new_name: &str) -> FsResult<()>
Rename a file or directory within the root directory.
Sourcepub fn sync(&self) -> FsResult<()>
pub fn sync(&self) -> FsResult<()>
Sync / flush. Calls through to the block store sync.
Examples found in repository?
15fn main() {
16 let path = std::env::current_dir()
17 .unwrap()
18 .join("sample.dcfs")
19 .to_string_lossy()
20 .to_string();
21
22 // Remove leftover from a previous run, if any.
23 let _ = std::fs::remove_file(&path);
24
25 // 64 blocks × 64 KiB = 4 MiB image.
26 let total_blocks: u64 = 64;
27 let store = Arc::new(
28 DiskBlockStore::create(&path, DEFAULT_BLOCK_SIZE, total_blocks)
29 .expect("failed to create image file"),
30 );
31
32 let crypto = Arc::new(ChaChaEngine::generate().expect("failed to init crypto"));
33 let mut fs = FilesystemCore::new(store, crypto);
34
35 fs.init_filesystem().expect("init_filesystem failed");
36
37 // Create a text file.
38 fs.create_file("hello.txt").expect("create_file failed");
39 fs.write_file("hello.txt", 0, b"Hello, hex editor!")
40 .expect("write_file failed");
41
42 // Create a directory.
43 fs.create_directory("notes")
44 .expect("create_directory failed");
45
46 // Create a larger binary file so there's more to look at.
47 let pattern: Vec<u8> = (0..=255).cycle().take(200_000).collect();
48 fs.create_file("pattern.bin").expect("create_file failed");
49 fs.write_file("pattern.bin", 0, &pattern)
50 .expect("write_file failed");
51
52 fs.sync().expect("sync failed");
53
54 println!("Filesystem image written to:\n {path}");
55 println!(
56 " {} blocks × {} bytes = {} bytes total",
57 total_blocks,
58 DEFAULT_BLOCK_SIZE,
59 total_blocks as usize * DEFAULT_BLOCK_SIZE
60 );
61}More examples
22fn main() {
23 let args: Vec<String> = std::env::args().collect();
24
25 let mut addr = "127.0.0.1:9100";
26 let mut server_name = "localhost";
27 let mut cert = "certs/client.pem";
28 let mut key = "certs/client-key.pem";
29 let mut ca = "certs/ca.pem";
30 let mut master_key_hex = "";
31 let mut init = false;
32
33 let mut i = 1;
34 while i < args.len() {
35 match args[i].as_str() {
36 "--addr" => {
37 addr = &args[i + 1];
38 i += 2;
39 }
40 "--server-name" => {
41 server_name = &args[i + 1];
42 i += 2;
43 }
44 "--cert" => {
45 cert = &args[i + 1];
46 i += 2;
47 }
48 "--key" => {
49 key = &args[i + 1];
50 i += 2;
51 }
52 "--ca" => {
53 ca = &args[i + 1];
54 i += 2;
55 }
56 "--master-key" => {
57 master_key_hex = &args[i + 1];
58 i += 2;
59 }
60 "--init" => {
61 init = true;
62 i += 1;
63 }
64 other => {
65 eprintln!("unknown argument: {other}");
66 std::process::exit(1);
67 }
68 }
69 }
70
71 if master_key_hex.is_empty() || master_key_hex.len() != 64 {
72 eprintln!("--master-key must be a 64-character hex string (32 bytes)");
73 std::process::exit(1);
74 }
75
76 let master_key: Vec<u8> = (0..32)
77 .map(|i| u8::from_str_radix(&master_key_hex[i * 2..i * 2 + 2], 16).unwrap())
78 .collect();
79
80 // ── Connect ─────────────────────────────────────────────
81 println!("Connecting to {addr} (SNI: {server_name})...");
82 let net = NetworkBlockStore::connect(
83 addr,
84 server_name,
85 Path::new(cert),
86 Path::new(key),
87 Path::new(ca),
88 )
89 .expect("failed to connect to server");
90
91 println!(
92 "Connected: {} blocks × {} bytes ({} MiB)",
93 net.total_blocks(),
94 net.block_size(),
95 net.total_blocks() as usize * net.block_size() / (1024 * 1024)
96 );
97
98 // ── Wrap with cache ─────────────────────────────────────
99 let store = Arc::new(CachedBlockStore::new(net, 1024));
100 let crypto = Arc::new(ChaChaEngine::new(&master_key).expect("invalid master key"));
101 let mut fs = FilesystemCore::new(store.clone(), crypto);
102
103 // ── Mount or init ───────────────────────────────────────
104 if init {
105 println!("Initializing new filesystem...");
106 fs.init_filesystem().expect("init_filesystem failed");
107 } else {
108 println!("Mounting existing filesystem...");
109 fs.open().expect("open failed");
110 }
111
112 // ── Demo operations ─────────────────────────────────────
113 println!("\nCreating file 'hello.txt'...");
114 match fs.create_file("hello.txt") {
115 Ok(()) => {}
116 Err(e) => println!(" (skipped: {e})"),
117 }
118
119 fs.write_file("hello.txt", 0, b"Hello from the network!")
120 .expect("write failed");
121
122 let data = fs.read_file("hello.txt", 0, 4096).expect("read failed");
123 println!("Read back: {:?}", String::from_utf8_lossy(&data));
124
125 println!("\nListing root directory:");
126 for entry in fs.list_directory().expect("list failed") {
127 println!(
128 " {:?} {:>10} bytes {}",
129 entry.kind, entry.size, entry.name
130 );
131 }
132
133 // ── Sync ────────────────────────────────────────────────
134 fs.sync().expect("sync failed");
135 println!("\nAll data synced to server.");
136}