diff options
Diffstat (limited to '')
| -rw-r--r-- | rsnix/src/fs.rs | 84 |
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. | ||
| 198 | pub 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 | |||
| 213 | fn lookup(dir: usize, name: &str) -> Option<usize> { | 255 | fn 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(), |
