summaryrefslogtreecommitdiffstats
path: root/rsnix/src/fs.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rsnix/src/fs.rs84
1 files changed, 63 insertions, 21 deletions
diff --git a/rsnix/src/fs.rs b/rsnix/src/fs.rs
index 063560a..b560bfa 100644
--- a/rsnix/src/fs.rs
+++ b/rsnix/src/fs.rs
@@ -183,33 +183,75 @@ pub fn init() -> (usize, usize) {
183 ); 183 );
184 184
185 // Mount every FAT32 volume under /disk/<UID>/ (UID = label-serial). 185 // Mount every FAT32 volume under /disk/<UID>/ (UID = label-serial).
186 let disks = crate::fat::volume_count(); 186 // `rescan_disks()` also keeps this table current after hotplug events.
187 if disks > 0 { 187 let _ = rescan_disks();
188 let disk_dir = add("disk", Some(root), FileType::Dir, NodeData::Dir(Vec::new()));
189 for vol in 0..disks {
190 let uid = String::from(crate::fat::uid(vol));
191 let root_cl = crate::fat::root_cluster(vol);
192 add(
193 &uid,
194 Some(disk_dir),
195 FileType::Dir,
196 NodeData::Disk(DiskInfo {
197 vol,
198 parent: root_cl,
199 name: String::new(),
200 is_dir: true,
201 size: 0,
202 cluster: root_cl,
203 }),
204 );
205 }
206 }
207 188
208 let dirs = nodes().iter().filter(|n| n.kind == FileType::Dir).count(); 189 let dirs = nodes().iter().filter(|n| n.kind == FileType::Dir).count();
209 let files = nodes().len() - dirs; 190 let files = nodes().len() - dirs;
210 (dirs, files) 191 (dirs, files)
211} 192}
212 193
194/// (Re)sync the /disk mount table with the FAT volumes: create the /disk
195/// dir lazily, ensure a mount node for every mounted volume (refreshing
196/// its backing info), and tombstone nodes whose volume was unmounted.
197/// Returns (added, removed) node ops.
198pub fn rescan_disks() -> (usize, usize) {
199 let mut added = 0usize;
200 let mut removed = 0usize;
201 let disk_dir = match lookup(0, "disk") {
202 Some(h) => h,
203 None => add("disk", Some(0), FileType::Dir, NodeData::Dir(Vec::new())),
204 };
205 for vol in 0..crate::fat::volume_count() {
206 if !crate::fat::is_mounted(vol) {
207 continue;
208 }
209 let uid = String::from(crate::fat::uid(vol));
210 let root_cl = crate::fat::root_cluster(vol);
211 match lookup(disk_dir, &uid) {
212 Some(h) => {
213 // Refresh the backing info in case the volume's slot moved.
214 if let NodeData::Disk(i) = &mut nodes()[h].data {
215 i.vol = vol;
216 i.parent = root_cl;
217 i.cluster = root_cl;
218 }
219 nodes()[h].removed = false;
220 }
221 None => {
222 add(
223 &uid,
224 Some(disk_dir),
225 FileType::Dir,
226 NodeData::Disk(DiskInfo {
227 vol,
228 parent: root_cl,
229 name: String::new(),
230 is_dir: true,
231 size: 0,
232 cluster: root_cl,
233 }),
234 );
235 added += 1;
236 }
237 }
238 }
239 if let NodeData::Dir(v) = &nodes()[disk_dir].data {
240 for &c in v.clone().iter() {
241 if nodes()[c].removed {
242 continue;
243 }
244 if let NodeData::Disk(i) = &nodes()[c].data
245 && !crate::fat::is_mounted(i.vol)
246 {
247 nodes()[c].removed = true;
248 removed += 1;
249 }
250 }
251 }
252 (added, removed)
253}
254
213fn lookup(dir: usize, name: &str) -> Option<usize> { 255fn lookup(dir: usize, name: &str) -> Option<usize> {
214 let children = match &nodes()[dir].data { 256 let children = match &nodes()[dir].data {
215 NodeData::Dir(v) => v.clone(), 257 NodeData::Dir(v) => v.clone(),