diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-01 15:52:44 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-01 15:52:44 +0100 |
| commit | 316a2a239446fe927e35b029b651cbeb08ff3f48 (patch) | |
| tree | c16bcc30c25c9eaad99445d2a30b703f43c0d091 /rsnix/src | |
| parent | bins: read user args from argv[1..]; fix date year digit (diff) | |
| download | rs-dos-316a2a239446fe927e35b029b651cbeb08ff3f48.tar.gz rs-dos-316a2a239446fe927e35b029b651cbeb08ff3f48.zip | |
fs: /bin alias for the system volume
ADR 0006 deferred root-path unification because it "needs VFS
bind/alias machinery". Implement the /bin half: paths whose first
component is `bin` are rewritten to the first mounted volume whose
root has a \bin directory, so `ls /bin/cli`, `cat /bin/cli/x.efi` and
a binary's own fs_resolve("/bin/cli/x.efi") work without knowing the
volume UID.
The alias is transparent — it creates no node, so `ls /` keeps its old
listing and /bin simply does not exist when no system volume is
mounted — and allocates nothing for non-matching paths. exec::resolve
keeps its per-file volume scan (stricter for multiple volumes).
Update ADR 0006 to record the decision and what remains deferred
(\etc and friends at the root).
Diffstat (limited to 'rsnix/src')
| -rw-r--r-- | rsnix/src/fs.rs | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/rsnix/src/fs.rs b/rsnix/src/fs.rs index 3585c00..a3bae6d 100644 --- a/rsnix/src/fs.rs +++ b/rsnix/src/fs.rs | |||
| @@ -274,12 +274,53 @@ fn lookup(dir: usize, name: &str) -> Option<usize> { | |||
| 274 | None | 274 | None |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | /// `/bin` alias for the system volume (ADR 0006): the binaries actually | ||
| 278 | /// live on the FAT volume at `\<vol>\bin\<kind>\`, but `/bin` is the | ||
| 279 | /// stable user-facing path. When the first path component is `bin`, the | ||
| 280 | /// path is rewritten to the first mounted volume whose root has a `\bin` | ||
| 281 | /// directory — so `ls /bin/cli` and a binary's own | ||
| 282 | /// `fs_resolve("/bin/cli/x.efi")` work without knowing the volume UID. | ||
| 283 | /// Every other path returns `None` here without allocating. (The alias is | ||
| 284 | /// transparent: `ls /` does not list `bin`, and with no system volume | ||
| 285 | /// mounted `/bin` simply does not exist.) | ||
| 286 | fn alias_bin(path: &str) -> Option<String> { | ||
| 287 | let p = path.trim_start_matches('/'); | ||
| 288 | let p = p.trim_start_matches("./"); // tolerate a leading ./ prefix | ||
| 289 | let first = match p.find('/') { | ||
| 290 | Some(i) => &p[..i], | ||
| 291 | None => p, | ||
| 292 | }; | ||
| 293 | if first != "bin" { | ||
| 294 | return None; | ||
| 295 | } | ||
| 296 | for vol in 0..crate::fat::volume_count() { | ||
| 297 | if !crate::fat::is_mounted(vol) { | ||
| 298 | continue; | ||
| 299 | } | ||
| 300 | if crate::fat::find(vol, crate::fat::root_cluster(vol), "bin").is_err() { | ||
| 301 | continue; // volume has no \bin root — not the system volume | ||
| 302 | } | ||
| 303 | let uid = String::from(crate::fat::uid(vol)); | ||
| 304 | return Some(alloc::format!("/disk/{}/{}", uid, p)); | ||
| 305 | } | ||
| 306 | None | ||
| 307 | } | ||
| 308 | |||
| 277 | /// Resolve an absolute path (supports `.` and `..`). Paths under | 309 | /// Resolve an absolute path (supports `.` and `..`). Paths under |
| 278 | /// `/disk` walk the mounted FAT32 volume through ephemeral Disk nodes. | 310 | /// `/disk` walk the mounted FAT32 volume through ephemeral Disk nodes. |
| 311 | /// A leading `bin` component goes through the `/bin` alias first. | ||
| 279 | pub fn resolve(path: &str) -> Option<usize> { | 312 | pub fn resolve(path: &str) -> Option<usize> { |
| 280 | if nodes().is_empty() { | 313 | if nodes().is_empty() { |
| 281 | return None; | 314 | return None; |
| 282 | } | 315 | } |
| 316 | let aliased; | ||
| 317 | let path = match alias_bin(path) { | ||
| 318 | Some(p) => { | ||
| 319 | aliased = p; | ||
| 320 | aliased.as_str() | ||
| 321 | } | ||
| 322 | None => path, | ||
| 323 | }; | ||
| 283 | let mut cur = 0usize; // root | 324 | let mut cur = 0usize; // root |
| 284 | // (vol, cluster, parent, name) of directories descended into under /disk. | 325 | // (vol, cluster, parent, name) of directories descended into under /disk. |
| 285 | let mut dstack: Vec<(usize, u32, u32, String)> = Vec::new(); | 326 | let mut dstack: Vec<(usize, u32, u32, String)> = Vec::new(); |
