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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

README.md

3.33 Kb · 73 lines

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

A Plan 9 shaped file abstraction for gno: File, Mutable, Qid, Stat, Perm, the 9P error set, and lexical path handling.

1import ninep "gno.land/p/moul/x/plan9/ninep/v0"
2
3type File interface {
4	Stat() Stat
5	Walk(name string) (File, error)      // exactly one element
6	Read(off, count int64) (string, error)
7	ReadDir() ([]Stat, error)
8}

This implements the semantics of 9P2000, not its wire format. There is no socket on a chain: the VM call is the transport. What survives the translation is the part that made 9P useful, namely that every resource answers the same four questions, so a client written today can browse a file server deployed tomorrow.

One interface, not two. 9P reads a directory with the same Tread it uses for a file, so splitting File from Dir would be less faithful, and a single interface means no type assertion across a realm boundary.

File is read-only, on purpose. A crossing write method would mint the caller's realm frame for the callee, which is the confused-deputy shape that r/gov/dao's Executor relies on deliberately and p/nt/grc20's Teller refuses deliberately. So mutation lives in a separate Mutable, which is only safe on a tree your own realm owns. That is what makes it safe to hand a File to a stranger's namespace.

Deliberate divergences, each one forced:

  • Data is a string, not []byte. Every consumer on this chain is text and Render returns a string.
  • Mtime is a block height. It is the only clock every validating node agrees on.
  • There is no open/clunk. Without a session there are no fids, so Walk returns the file itself and nothing has to be released.
  • .. never reaches a server. Clean resolves it lexically first, per Lexical File Names in Plan 9, so .. undoes the name you typed rather than the directory you landed in.
  • MaxDepth caps a walk at 32 elements. Resolution can cost one cross-realm call per element, so depth is bounded rather than trusted.

Used by memfs (a RAM server), synfs (a computed server), ns (namespaces) and rc (the shell). 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.

🧪 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.