Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

/p/moul/x/plan9/ns/v0

Directory · 4 Files
README.md Open

gno.land/p/moul/x/plan9/ns/v0

A Plan 9 namespace: a private, mutable mount table over ninep file trees, with bind(2)'s flags and union directories.

1import ns "gno.land/p/moul/x/plan9/ns/v0"
2
3n := ns.New(fs.Root())
4n.Bind("/usr/glenda/bin", "/bin", ns.MAFTER|ns.MCREATE)
5n.ReadDir("/bin", false)   // the concatenation of both directories

This is the idea the rest of the suite exists for. Plan 9's leverage does not come from "everything is a file", it comes from every process owning its own name-to-resource mapping, so a name can be replaced and any service can be composed, shadowed, sandboxed or mocked without the program knowing. Gno has one global tree of realm paths that looks the same to everybody; an Ns is a view of it that belongs to you.

Flags follow bind(2): MREPL replaces, MBEFORE splices the new directory in front of the old one, MAFTER behind it, and MCREATE (OR'd onto any of them) marks the union member that new files are created in.

Four Plan 9 properties are load-bearing and reproduced deliberately:

  • A union is top level only. Binding /a onto /b unions the two directories at /b; /b/c resolves in whichever member won the walk and is not itself a union unless something is bound there too.
  • A bind captures a channel, not a name. The source is resolved once, at bind time, and the file it named is what gets stored. Rebinding the source afterwards does not retroactively move the target.
  • A listing is a concatenation, duplicates and all, so shadowing stays visible. Pass unique to collapse it first-wins instead.
  • Creating in a union needs MCREATE on some member, and is refused otherwise. A plain, unbound directory takes creates with no flag at all.
  • The target of a bind must already exist, exactly as bind(1) requires.

MaxUnion (8), MaxOps (64) and ninep.MaxDepth (32) bound resolution, because each element of each member can cost a cross-realm call.

String() prints the namespace in ns(1) format: one line per binding, in application order, then the working directory.

Live demo: r/moul/x/plan9/ns gives every account one of these. Design and analysis: moul/gno-contracts#136.


Not affiliated with Plan 9. Plan 9 from Bell Labs is the work of the Computing Science Research Center at Bell Labs; the name and the marks are theirs, and the copyright is held by the Plan 9 Foundation. This package borrows the vocabulary and none of the code: it is an independent homage, asking what that ecosystem's spirit looks like on a chain. Full attribution: NOTICE.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

Dependency graph:

gno.land/p/moul/x/plan9/ns/v0 dependency graph

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.