summaryrefslogtreecommitdiffstats
path: root/rsnix/src/fs.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rsnix/src/fs.rs')
-rw-r--r--rsnix/src/fs.rs76
1 files changed, 46 insertions, 30 deletions
diff --git a/rsnix/src/fs.rs b/rsnix/src/fs.rs
index 6950171..4b76e07 100644
--- a/rsnix/src/fs.rs
+++ b/rsnix/src/fs.rs
@@ -59,6 +59,7 @@ enum NodeData {
59/// op, so it stays correct as the volume changes), `cluster` the entry's 59/// op, so it stays correct as the volume changes), `cluster` the entry's
60/// own first cluster. 60/// own first cluster.
61struct DiskInfo { 61struct DiskInfo {
62 vol: usize, // index into fat::VOLS (which FAT32 volume this lives on)
62 parent: u32, 63 parent: u32,
63 name: String, 64 name: String,
64 is_dir: bool, 65 is_dir: bool,
@@ -174,21 +175,32 @@ pub fn init() -> (usize, usize) {
174 ), 175 ),
175 ); 176 );
176 177
177 // Mount the FAT32 volume at /disk when one is present. 178 // Mount every FAT32 volume under /disk/<UID>/ (UID = label-serial).
178 if crate::fat::is_mounted() { 179 let disks = crate::fat::volume_count();
179 let root_cl = crate::fat::root_cluster(); 180 if disks > 0 {
180 add( 181 let disk_dir = add(
181 "disk", 182 "disk",
182 Some(root), 183 Some(root),
183 FileType::Dir, 184 FileType::Dir,
184 NodeData::Disk(DiskInfo { 185 NodeData::Dir(Vec::new()),
185 parent: root_cl,
186 name: String::new(),
187 is_dir: true,
188 size: 0,
189 cluster: root_cl,
190 }),
191 ); 186 );
187 for vol in 0..disks {
188 let uid = String::from(crate::fat::uid(vol));
189 let root_cl = crate::fat::root_cluster(vol);
190 add(
191 &uid,
192 Some(disk_dir),
193 FileType::Dir,
194 NodeData::Disk(DiskInfo {
195 vol,
196 parent: root_cl,
197 name: String::new(),
198 is_dir: true,
199 size: 0,
200 cluster: root_cl,
201 }),
202 );
203 }
192 } 204 }
193 205
194 let dirs = nodes().iter().filter(|n| n.kind == FileType::Dir).count(); 206 let dirs = nodes().iter().filter(|n| n.kind == FileType::Dir).count();
@@ -217,14 +229,15 @@ pub fn resolve(path: &str) -> Option<usize> {
217 return None; 229 return None;
218 } 230 }
219 let mut cur = 0usize; // root 231 let mut cur = 0usize; // root
220 // (cluster, parent, name) of directories descended into under /disk. 232 // (vol, cluster, parent, name) of directories descended into under /disk.
221 let mut dstack: Vec<(u32, u32, String)> = Vec::new(); 233 let mut dstack: Vec<(usize, u32, u32, String)> = Vec::new();
222 for seg in path.split('/') { 234 for seg in path.split('/') {
223 match seg { 235 match seg {
224 "" | "." => {} 236 "" | "." => {}
225 ".." => { 237 ".." => {
226 if let Some((cl, p, n)) = dstack.pop() { 238 if let Some((vol, cl, p, n)) = dstack.pop() {
227 cur = materialize_disk(DiskInfo { 239 cur = materialize_disk(DiskInfo {
240 vol,
228 parent: p, 241 parent: p,
229 name: n, 242 name: n,
230 is_dir: true, 243 is_dir: true,
@@ -236,13 +249,14 @@ pub fn resolve(path: &str) -> Option<usize> {
236 } 249 }
237 } 250 }
238 name => { 251 name => {
239 let disk_dir: Option<u32> = match &nodes()[cur].data { 252 let disk_ctx: Option<(usize, u32)> = match &nodes()[cur].data {
240 NodeData::Disk(info) => Some(info.cluster), 253 NodeData::Disk(info) => Some((info.vol, info.cluster)),
241 _ => None, 254 _ => None,
242 }; 255 };
243 if let Some(dir_cluster) = disk_dir { 256 if let Some((vol, dir_cluster)) = disk_ctx {
244 let e = crate::fat::find(dir_cluster, name).ok()?; 257 let e = crate::fat::find(vol, dir_cluster, name).ok()?;
245 let d = DiskInfo { 258 let d = DiskInfo {
259 vol,
246 parent: dir_cluster, 260 parent: dir_cluster,
247 name: e.name.clone(), 261 name: e.name.clone(),
248 is_dir: e.is_dir, 262 is_dir: e.is_dir,
@@ -250,7 +264,7 @@ pub fn resolve(path: &str) -> Option<usize> {
250 cluster: e.cluster, 264 cluster: e.cluster,
251 }; 265 };
252 if e.is_dir { 266 if e.is_dir {
253 dstack.push((e.cluster, dir_cluster, e.name)); 267 dstack.push((vol, e.cluster, dir_cluster, e.name));
254 } 268 }
255 cur = materialize_disk(d); 269 cur = materialize_disk(d);
256 } else { 270 } else {
@@ -279,7 +293,7 @@ pub fn size(h: usize) -> u64 {
279pub fn children(h: usize) -> Vec<(String, FileType, u64)> { 293pub fn children(h: usize) -> Vec<(String, FileType, u64)> {
280 if let NodeData::Disk(i) = &nodes()[h].data { 294 if let NodeData::Disk(i) = &nodes()[h].data {
281 let cl = i.cluster; 295 let cl = i.cluster;
282 return crate::fat::list_dir(cl) 296 return crate::fat::list_dir(i.vol, cl)
283 .map(|es| { 297 .map(|es| {
284 es.into_iter() 298 es.into_iter()
285 .map(|e| { 299 .map(|e| {
@@ -357,7 +371,7 @@ pub fn read(h: usize, buf: &mut [u8], pos: u64) -> Result<usize, ()> {
357 buf[..n].copy_from_slice(&bytes[p..p + n]); 371 buf[..n].copy_from_slice(&bytes[p..p + n]);
358 Ok(n) 372 Ok(n)
359 } 373 }
360 NodeData::Disk(i) => crate::fat::read_file(i.parent, &i.name, buf, pos), 374 NodeData::Disk(i) => crate::fat::read_file(i.vol, i.parent, &i.name, buf, pos),
361 NodeData::Dir(_) => Err(()), 375 NodeData::Dir(_) => Err(()),
362 } 376 }
363} 377}
@@ -394,7 +408,7 @@ pub fn write(h: usize, buf: &[u8], pos: u64) -> Result<usize, ()> {
394 } 408 }
395 _ => Err(()), // read-only devices 409 _ => Err(()), // read-only devices
396 }, 410 },
397 NodeData::Disk(i) => crate::fat::write_file(i.parent, &i.name, buf, pos), 411 NodeData::Disk(i) => crate::fat::write_file(i.vol, i.parent, &i.name, buf, pos),
398 NodeData::Dir(_) => Err(()), 412 NodeData::Dir(_) => Err(()),
399 } 413 }
400} 414}
@@ -406,7 +420,7 @@ pub fn set_len(h: usize, len: u64) -> Result<(), ()> {
406 v.resize(len as usize, 0); 420 v.resize(len as usize, 0);
407 Ok(()) 421 Ok(())
408 } 422 }
409 NodeData::Disk(i) => crate::fat::set_len(i.parent, &i.name, len), 423 NodeData::Disk(i) => crate::fat::set_len(i.vol, i.parent, &i.name, len),
410 _ => Err(()), 424 _ => Err(()),
411 } 425 }
412} 426}
@@ -417,22 +431,23 @@ pub fn create(parent: usize, name: &str, kind: FileType) -> Result<usize, ()> {
417 return Err(()); 431 return Err(());
418 } 432 }
419 // Disk directory: create through the FAT volume. 433 // Disk directory: create through the FAT volume.
420 let disk_parent: Option<u32> = match &nodes()[parent].data { 434 let disk_parent: Option<(usize, u32)> = match &nodes()[parent].data {
421 NodeData::Disk(i) => { 435 NodeData::Disk(i) => {
422 if !i.is_dir { 436 if !i.is_dir {
423 return Err(()); 437 return Err(());
424 } 438 }
425 Some(i.cluster) 439 Some((i.vol, i.cluster))
426 } 440 }
427 _ => None, 441 _ => None,
428 }; 442 };
429 if let Some(p) = disk_parent { 443 if let Some((vol, p)) = disk_parent {
430 if crate::fat::find(p, name).is_ok() { 444 if crate::fat::find(vol, p, name).is_ok() {
431 return Err(()); 445 return Err(());
432 } 446 }
433 crate::fat::create(p, name, kind == FileType::Dir)?; 447 crate::fat::create(vol, p, name, kind == FileType::Dir)?;
434 let e = crate::fat::find(p, name)?; 448 let e = crate::fat::find(vol, p, name)?;
435 return Ok(materialize_disk(DiskInfo { 449 return Ok(materialize_disk(DiskInfo {
450 vol,
436 parent: p, 451 parent: p,
437 name: e.name, 452 name: e.name,
438 is_dir: e.is_dir, 453 is_dir: e.is_dir,
@@ -458,9 +473,10 @@ pub fn remove(h: usize) -> Result<(), ()> {
458 if i.name.is_empty() { 473 if i.name.is_empty() {
459 return Err(()); // the /disk mount itself 474 return Err(()); // the /disk mount itself
460 } 475 }
476 let vol = i.vol;
461 let p = i.parent; 477 let p = i.parent;
462 let n = i.name.clone(); 478 let n = i.name.clone();
463 return crate::fat::remove(p, &n); 479 return crate::fat::remove(vol, p, &n);
464 } 480 }
465 let parent = match nodes()[h].parent { 481 let parent = match nodes()[h].parent {
466 Some(p) => p, 482 Some(p) => p,