# gizfs:fs

POSIX metadata is one deterministic semantic client of the range journal. apply sees committed commands only. Immutable data uploads are not visible until this owner validates receipts and publishes an inode revision.

```gizlang
import * as Fs from "gizfs:fs";
```

## Types

### `Limits`

```gizlang
type Limits = { inodes: i64; entries: i64; handles: i64; extents: i64; operations: i64; fileBytes: i64; logicalBytes: i64; sessions: i64; }
```

The most of each kind a file system state holds: inodes, entries, handles, extents, operations, bytes and sessions.

- `inodes`: `i64`
- `entries`: `i64`
- `handles`: `i64`
- `extents`: `i64`
- `operations`: `i64`
- `fileBytes`: `i64`
- `logicalBytes`: `i64`
- `sessions`: `i64`

### `Attribute`

```gizlang
type Attribute = { name: string; value: bytes; }
```

One extended attribute: its name and value.

- `name`: `string`
- `value`: `bytes`

### `Inode`

```gizlang
type Inode = { id: i64; generation: i64; revision: i64; kind: string; parent: i64; uid: i64; gid: i64; mode: i64; links: i64; size: i64; accessed: i64; modified: i64; changed: i64; target: string; extents: Store.Spans; attributes: Vec<Attribute>; tier: i64; quota: i64; }
```

Authoritative Unix nanoseconds; adapters must check conversions before submitting commands.
tier: 0 when the extents hold the bytes of the file. Else the bytes are in the tier file of the file on its node
(Store.tierName), as of tier version TIER (Op.tier), and the extents are the copy that the last seal left.
quota: the quota root whose limit the bytes of a file count against (0: only the volume's): the directory that has
the limit, which is its own root, and everything made in it (Quota).

- `id`: `i64`
- `generation`: `i64`
- `revision`: `i64`
- `kind`: `string`
- `parent`: `i64`
- `uid`: `i64`
- `gid`: `i64`
- `mode`: `i64`
- `links`: `i64`
- `size`: `i64`
- `accessed`: `i64`
- `modified`: `i64`
- `changed`: `i64`
- `target`: `string`
- `extents`: `_gizlang_lib_fs__store.Spans`
- `attributes`: `Vec<M61.Attribute>`
- `tier`: `i64`
- `quota`: `i64`

### `Entry`

```gizlang
type Entry = { parent: i64; name: string; inode: i64; }
```

A directory entry: the parent directory, the name and the inode it names.

- `parent`: `i64`
- `name`: `string`
- `inode`: `i64`

### `Handle`

```gizlang
type Handle = { id: i64; inode: i64; generation: i64; session: string; read: bool; write: bool; append: bool; }
```

An open handle: its inode, generation, session and access modes.

- `id`: `i64`
- `inode`: `i64`
- `generation`: `i64`
- `session`: `string`
- `read`: `bool`
- `write`: `bool`
- `append`: `bool`

### `Lock`

```gizlang
type Lock = { inode: i64; session: string; owner: i64; profile: string; pid: i64; start: i64; end: i64; exclusive: bool; }
```

A held byte-range lock of one owner of a session on an inode.

- `inode`: `i64`
- `session`: `string`
- `owner`: `i64`
- `profile`: `string`
- `pid`: `i64`
- `start`: `i64`
- `end`: `i64`
- `exclusive`: `bool`

### `LockRequest`

```gizlang
type LockRequest = { handle: i64; owner: i64; profile: string; start: i64; length: i64; exclusive: bool; pid: i64; }
```

A request for a byte-range lock on an open handle.

- `handle`: `i64`
- `owner`: `i64`
- `profile`: `string`
- `start`: `i64`
- `length`: `i64`
- `exclusive`: `bool`
- `pid`: `i64`

### `SetAttributes`

```gizlang
type SetAttributes = { mode: Option<i64>; uid: Option<i64>; gid: Option<i64>; size: Option<i64>; accessed: Option<i64>; modified: Option<i64>; accessedNow: bool; modifiedNow: bool; }
```

The attributes a setattr changes; an absent field stays.

- `mode`: `_gizlang_sdk_core.Option<i64>`
- `uid`: `_gizlang_sdk_core.Option<i64>`
- `gid`: `_gizlang_sdk_core.Option<i64>`
- `size`: `_gizlang_sdk_core.Option<i64>`
- `accessed`: `_gizlang_sdk_core.Option<i64>`
- `modified`: `_gizlang_sdk_core.Option<i64>`
- `accessedNow`: `bool`
- `modifiedNow`: `bool`

### `Outcome`

```gizlang
type Outcome = { error: i64; value: i64; revision: i64; }
```

The result of an operation: a negated errno or 0, its value and the revision it made.

- `error`: `i64`
- `value`: `i64`
- `revision`: `i64`

### `Operation`

```gizlang
type Operation = { session: string; id: string; digest: bytes; outcome: Outcome; lock: Option<LockRequest>; sequence: i64; terminalCut: i64; }
```

id is the decimal text of sequence; the GFSS4 grammar encodes only sequence.

- `session`: `string`
- `id`: `string`
- `digest`: `bytes`
- `outcome`: `M61.Outcome`
- `lock`: `_gizlang_sdk_core.Option<M61.LockRequest>`
- `sequence`: `i64`
- `terminalCut`: `i64`

### `SessionToken`

```gizlang
type SessionToken = { history: string; incarnation: i64; session: string; }
```

A session of a client: its history, incarnation and name.

- `history`: `string`
- `incarnation`: `i64`
- `session`: `string`

### `SessionOffer`

```gizlang
type SessionOffer = { history: string; incarnation: i64; }
```

The history and incarnation a new session takes.

- `history`: `string`
- `incarnation`: `i64`

### `Session`

```gizlang
type Session = { token: SessionToken; uid: i64; gid: i64; phase: string; generation: i64; controlDigest: bytes; duration: i64; floor: i64; observed: i64; pruneAfter: bytes; pruneThrough: bytes; resumed: Option<SessionToken>; resumedHandles: Vec<i64>; abandon: bool; ceiling: i64; issuedDigest: bytes; resumeDigest: bytes; resumeGeneration: i64; }
```

The state of a client session: its owner, phase, lease and resume data.

- `token`: `M61.SessionToken`
- `uid`: `i64`
- `gid`: `i64`
- `phase`: `string`
- `generation`: `i64`
- `controlDigest`: `bytes`
- `duration`: `i64`
- `floor`: `i64`
- `observed`: `i64`
- `pruneAfter`: `bytes`
- `pruneThrough`: `bytes`
- `resumed`: `_gizlang_sdk_core.Option<M61.SessionToken>`
- `resumedHandles`: `Vec<i64>`
- `abandon`: `bool`
- `ceiling`: `i64`
- `issuedDigest`: `bytes`
- `resumeDigest`: `bytes`
- `resumeGeneration`: `i64`

### `Receipt`

```gizlang
type Receipt = { outcome: Outcome; terminal: Option<Journal.Position>; fenced: bool; }
```

The receipt of a command: its outcome, its journal position and whether a newer session fenced it.

- `outcome`: `M61.Outcome`
- `terminal`: `_gizlang_sdk_core.Option<gizlang_journal.Position>`
- `fenced`: `bool`

### `HandleMapping`

```gizlang
type HandleMapping = { source: i64; target: i64; }
```

A handle of a resumed session (source) and its new number (target).

- `source`: `i64`
- `target`: `i64`

### `Resume`

```gizlang
type Resume = { token: SessionToken; handles: Vec<HandleMapping>; }
```

A resumed session and the numbers of its handles.

- `token`: `M61.SessionToken`
- `handles`: `Vec<M61.HandleMapping>`

### `SessionPage`

```gizlang
type SessionPage = { rows: Vec<Session>; next: bytes; }
```

One page of sessions and the key of the next page.

- `rows`: `Vec<M61.Session>`
- `next`: `bytes`

### `SessionControl`

```gizlang
type SessionControl = | { kind: "begin"; duration: i64; } | { kind: "renew"; expected: i64; acknowledgement: Journal.Acknowledgement; } | { kind: "acknowledge"; expected: i64; acknowledgement: Journal.Acknowledgement; } | { kind: "expire"; expected: i64; } | { kind: "prune"; expected: i64; } | { kind: "retire"; expected: i64; abandon: bool; } | { kind: "resume"; source: SessionToken; expected: i64; uid: i64; gid: i64; duration: i64; }
```

A change of a session's lease: begin, renew, acknowledge, expire, prune, retire or resume.

- `begin`
- `renew`
- `acknowledge`
- `expire`
- `prune`
- `retire`
- `resume`

### `RootDelta`

```gizlang
type RootDelta = { inode: i64; revision: i64; roots: Store.Roots; edit: Option<ManifestEdit>; }
```

Transient affected-root projection; revision zero removes an inode source.

- `inode`: `i64`
- `revision`: `i64`
- `roots`: `_gizlang_lib_fs__store.Roots`
- `edit`: `_gizlang_sdk_core.Option<M61.ManifestEdit>`

### `Work`

```gizlang
type Work = { nodes: i64; slots: i64; examined: i64; }
```

The work of the state's indexes: nodes, slots and the entries examined.

- `nodes`: `i64`
- `slots`: `i64`
- `examined`: `i64`

### `ManifestEdit`

```gizlang
type ManifestEdit = { before: Store.Spans; ranges: Vec<Store.ExtentRange>; delta: Option<Store.BlobDelta>; }
```

Transient publication delta captured by the sole content mutation owner: the spans before the command, and the
disjoint ranges it changed, each of whole spans before and after it. DELTA is the blobs of the spans the commands
changed when each of them was a write (Store.Spans.edit): the root index applies it and walks no span.

- `before`: `_gizlang_lib_fs__store.Spans`
- `ranges`: `Vec<_gizlang_lib_fs__store.ExtentRange>`
- `delta`: `_gizlang_sdk_core.Option<_gizlang_lib_fs__store.BlobDelta>`

### `State`

```gizlang
type State = { policy: Durability; limits: Limits; epoch: i64; next: i64; charged: i64; inodes: Catalog<Inode>; entries: Catalog<Entry>; handles: Catalog<Handle>; locks: Catalog<Lock>; operations: Catalog<Operation>; indexes: Ref<Indexes>; changed: Vec<i64>; removed: Vec<i64>; reap: Vec<i64>; wake: Vec<i64>; encoded: i64; beforeBytes: Map<i64, i64>; history: string; nextSession: i64; cut: i64; sessions: Catalog<Session>; ready: bool; pages: Option<Ref<NativePages>>; manifestEdits: Ref<Map<i64, ManifestEdit>>; quotas: Vec<Quota>; }
```

The replicated state of a file system: its inodes, entries, handles, locks, sessions and their indexes.

- `policy`: `_gizlang_lib_fs__store.Durability`
- `limits`: `M61.Limits`
- `epoch`: `i64`
- `next`: `i64`
- `charged`: `i64`
- `inodes`: `_gizlang_lib_fs__catalog.Catalog<M61.Inode>`
- `entries`: `_gizlang_lib_fs__catalog.Catalog<M61.Entry>`
- `handles`: `_gizlang_lib_fs__catalog.Catalog<M61.Handle>`
- `locks`: `_gizlang_lib_fs__catalog.Catalog<M61.Lock>`
- `operations`: `_gizlang_lib_fs__catalog.Catalog<M61.Operation>`
- `indexes`: `Ref<M61.Indexes>`
- `changed`: `Vec<i64>`
- `removed`: `Vec<i64>`
- `reap`: `Vec<i64>`
- `wake`: `Vec<i64>`
- `encoded`: `i64`
- `beforeBytes`: `_gizlang_sdk_collections.Map<i64, i64>`
- `history`: `string`
- `nextSession`: `i64`
- `cut`: `i64`
- `sessions`: `_gizlang_lib_fs__catalog.Catalog<M61.Session>`
- `ready`: `bool`
- `pages`: `_gizlang_sdk_core.Option<Ref<M60.NativePages>>`
- `manifestEdits`: `Ref<_gizlang_sdk_collections.Map<i64, M61.ManifestEdit>>`
- `quotas`: `Vec<M61.Quota>`

### `Quota`

```gizlang
type Quota = { root: i64; limit: i64; charged: i64; }
```

The limit of the file bytes under directory ROOT, and the bytes that count against it: those of each file whose
quota is ROOT (Inode.quota). The volume is root 0: its record is limits.logicalBytes and charged. A write grows a
file when both its root and the volume have room (room: EDQUOT, then ENOSPC). The administrator, or the owner of the
namespace root, gives a limit with the xattr QUOTA_ATTRIBUTE (changeQuota): to an empty directory under no other
root, which becomes a root, or a new limit to a root. A rename or a link to a directory of another root is EXDEV.

- `root`: `i64`
- `limit`: `i64`
- `charged`: `i64`

### `StorePiece`

```gizlang
type StorePiece = { offset: i64; length: i64; }
```

One piece of a stored write: LENGTH bytes at OFFSET of the file, the next LENGTH bytes of its data. A flush sends
the small writes it holds as the pieces of one stored write: one command and one blob, not one for each write.

- `offset`: `i64`
- `length`: `i64`

### `Op`

```gizlang
type Op = | { kind: "create"; parent: i64; name: string; of: string; mode: i64; target: string; } | { kind: "open"; inode: i64; read: bool; write: bool; append: bool; } | { kind: "close"; handle: i64; } | { kind: "write"; handle: i64; offset: i64; blob: Store.Identity; proof: Vec<Store.Receipt>; } | { kind: "store"; handle: i64; pieces: Vec<StorePiece>; data: bytes; blob: Option<Store.Identity>; } | { kind: "truncate"; handle: i64; size: i64; } | { kind: "punch"; handle: i64; offset: i64; length: i64; } | { kind: "link"; inode: i64; parent: i64; name: string; } | { kind: "unlink"; parent: i64; name: string; directory: bool; } | { kind: "rename"; parent: i64; name: string; targetParent: i64; targetName: string; flags: i64; } | { kind: "chmod"; inode: i64; mode: i64; } | { kind: "chown"; inode: i64; uid: i64; gid: i64; } | { kind: "xattr"; inode: i64; name: string; value: bytes; remove: bool; } | { kind: "lock"; handle: i64; owner: i64; start: i64; length: i64; exclusive: bool; release: bool; } | { kind: "endSession"; session: string; } | { kind: "clone"; inode: i64; parent: i64; name: string; } | { kind: "copyFile"; source: i64; target: i64; } | { kind: "openFile"; inode: i64; read: bool; write: bool; append: bool; truncate: bool; } | { kind: "createOpen"; parent: i64; name: string; mode: i64; read: bool; write: bool; append: bool; exclusive: bool; truncate: bool; } | { kind: "setattr"; inode: i64; handle: i64; changes: SetAttributes; } | { kind: "setxattr"; inode: i64; name: string; value: bytes; flags: i64; } | { kind: "lockOwned"; handle: i64; owner: i64; profile: string; start: i64; length: i64; exclusive: bool; release: bool; pid: i64; } | { kind: "closeOwned"; handle: i64; owner: i64; } | { kind: "releaseLocks"; handle: i64; owner: i64; profile: string; } | { kind: "endOwner"; owner: i64; } | { kind: "access"; handle: i64; } | { kind: "lockWait"; request: LockRequest; } | { kind: "cancelLock"; request: i64; } | { kind: "reserve"; count: i64; } | { kind: "make"; id: i64; parent: i64; name: string; of: string; mode: i64; target: string; } | { kind: "delegate"; inode: i64; release: bool; } | { kind: "tier"; inode: i64; version: i64; size: i64; } | { kind: "band"; band: i64; } | { kind: "junction"; parent: i64; name: string; id: i64; phase: i64; } | { kind: "moving"; release: bool; } | { kind: "batch"; ops: Vec<Op>; } | { kind: "session"; control: SessionControl; }
```

A file system operation of a command.

- `create`
- `open`
- `close`
- `write`
- `store`
- `truncate`
- `punch`
- `link`
- `unlink`
- `rename`
- `chmod`
- `chown`
- `xattr`
- `lock`
- `endSession`
- `clone`
- `copyFile`
- `openFile`
- `createOpen`
- `setattr`
- `setxattr`
- `lockOwned`
- `closeOwned`
- `releaseLocks`
- `endOwner`
- `access`
- `lockWait`
- `cancelLock`
- `reserve`
- `make`
- `delegate`
- `tier`
- `band`
- `junction`
- `moving`
- `batch`
- `session`

### `Command`

```gizlang
type Command = { sequence: i64; session: string; epoch: i64; uid: i64; gid: i64; now: i64; op: Op; history: string; incarnation: i64; }
```

now is authenticated execution time in Unix nanoseconds, not a client-supplied clock.

- `sequence`: `i64`
- `session`: `string`
- `epoch`: `i64`
- `uid`: `i64`
- `gid`: `i64`
- `now`: `i64`
- `op`: `M61.Op`
- `history`: `string`
- `incarnation`: `i64`

### `Listing`

```gizlang
type Listing = { revision: i64; entries: Vec<Entry>; inodes: Vec<Inode>; next: string; }
```

inodes[i] is the inode of entries[i]: a mount shows a listing with its attributes and asks for none of them.

- `revision`: `i64`
- `entries`: `Vec<M61.Entry>`
- `inodes`: `Vec<M61.Inode>`
- `next`: `string`

## Functions

### `bandOf`

```gizlang
function bandOf(id: i64): i64
```

The band of an inode or handle number (BAND_BITS).

Effects: fail.

### `band`

```gizlang
function band(state: State): i64
```

The band of the range of STATE. Its next number never leaves its band (idsLeft).

Effects: fail.

### `remoteInode`

```gizlang
function remoteInode(id: i64): Inode
```

What a lookup or a listing shows for file or directory ID of another range: no attributes; the client reads them
there.

Effects: fail, write.

### `limits`

```gizlang
function limits(): Limits
```

The default Limits.

### `nativeLimits`

```gizlang
function nativeLimits(): Limits
```

Native rows/extents are disk bounded; per-session handles remain admitted.

### `kindValid`

```gizlang
function kindValid(kind: string): bool
```

The kinds of inode: a file, a directory, a symbolic link, and the two nodes whose use is the kernel's (a unix-domain
socket and a named pipe): no bytes, no device number, no user extended attributes.

### `attributes`

```gizlang
function attributes(): SetAttributes
```

A SetAttributes that changes nothing.

### `quotaOf`

```gizlang
function quotaOf(state: State, id: i64): Quota
```

The limit and the charged bytes of the quota root of inode ID: its own when it is a root, else that of the directory
it is in (0 the volume's). What a mount answers statfs with in that directory (Volume CAPACITY).

Effects: fail, read, write, console, io.

### `storeOp`

```gizlang
function storeOp(handle: i64, offset: i64, data: bytes): Op
```

A stored write of DATA at OFFSET (one piece).

Effects: fail.

### `storedLimit`

```gizlang
function storedLimit(policy: Durability): i64
```

The largest stored write of a range: a whole chunk (Store.MAX_CHUNK) on one node, else STORED_WRITE_BYTES. On one
node a write of up to 1 MiB is one commit: one log sync after one syncfs of its blob (Volume.logged), which a group
commit shares. With more nodes a larger write goes from the client to each owner at once (Client.place) and the
log commits only its identity and receipts: the leader reads, copies and relays no data bytes.

### `batchable`

```gizlang
function batchable(op: Op): bool
```

The ops a batch holds: the changes a mount answers before their commit (fuse.giz Back), none with a handle, a
lock or a session, and stored writes that stay in the entry.

### `storesBytes`

```gizlang
function storesBytes(op: Op): bool
```

True when OP, or an op of its batch, is a stored write.

Effects: fail.

### `newState`

```gizlang
function newState(policy: Durability, bounds: Limits, uid: i64, gid: i64, history: string): State throws string
```

A new, empty state with the root directory owned by UID and GID.

Effects: fail, read, write, console, io.

### `inodeOfHandle`

```gizlang
function inodeOfHandle(state: State, handle: i64): i64
```

The inode of the open HANDLE, or -1.

Effects: fail, read, write, console, io.

### `historyValid`

```gizlang
function historyValid(history: string): bool
```

Whether HISTORY is a valid history name.

Effects: fail.

### `sameToken`

```gizlang
function sameToken(a: SessionToken, b: SessionToken): bool
```

Whether A and B name the same session incarnation.

### `offerSession`

```gizlang
function offerSession(state: State): SessionOffer throws i64
```

The history and incarnation a new session of STATE takes.

Effects: fail.

### `requestCeiling`

```gizlang
function requestCeiling(state: State, token: SessionToken): i64 throws i64
```

The highest command sequence the session TOKEN may send.

Effects: fail, read, write, console, io.

### `sessionPage`

```gizlang
function sessionPage(state: State, after: bytes, count: i64, budget: i64, uid: i64): SessionPage throws i64
```

Administrator selection exposes historical recovery authority, never a live
handle grant. Canonical rows and their byte grammar stay at this owner.

Effects: fail, read, write, console, io.

### `sessionStatus`

```gizlang
function sessionStatus(state: State, token: SessionToken, uid: i64, gid: i64): Session throws i64
```

The session TOKEN as UID and GID may see it.

Effects: fail, read, write, console, io.

### `authorize`

```gizlang
function authorize(state: State, token: SessionToken, uid: i64, gid: i64): bool throws i64
```

Read-only selectors and cached directory adapters use this same owner check.

Effects: fail, read, write, console, io.

### `resumedSession`

```gizlang
function resumedSession(state: State, source: SessionToken, uid: i64): Resume throws i64
```

Mapping is an immutable recovery receipt; closing a resumed handle does not
erase which open description the administrator resumed.

Effects: fail, read, write, console, io.

### `pendingCount`

```gizlang
function pendingCount(state: State): i64
```

The lock requests that wait.

Effects: fail, read.

### `work`

```gizlang
function work(state: State): Work
```

The work of the state's indexes.

Effects: fail, read.

### `xattrNameValid`

```gizlang
function xattrNameValid(name: string): bool
```

Whether NAME is a valid extended attribute name.

Effects: fail.

### `blockedBy`

```gizlang
function blockedBy(state: State, command: Command): Vec<i64>
```

The delegated directories that refuse COMMAND: another session holds the names that it changes. And the files whose
bytes it changes, which another session holds, or which are in a tier file that the session does not hold.

Effects: fail, read, write, console, io.

### `tiered`

```gizlang
function tiered(state: State, limit: i64): Vec<i64>
```

The files whose bytes are in tier files (Inode.tier), up to LIMIT: a backup or a second node takes the extents.

Effects: fail, read, write, console, io.

### `delegatedElsewhere`

```gizlang
function delegatedElsewhere(state: State, id: i64, session: string): bool
```

Another session than SESSION holds the names of directory ID (Op.delegate).

Effects: fail, read, write, console, io.

### `madeInode`

```gizlang
function madeInode(id: i64, dir: Inode, kind: string, uid: i64, gid: i64, mode: i64, target: string, now: i64): Inode
```

The inode that a create of KIND in directory DIR makes: a set-group-ID directory gives its group, and its bit to a
directory. A mount that answers a create itself shows the same (fuse.giz, Adapter.make).

Effects: fail, write.

### `requestDigest`

```gizlang
function requestDigest(tenant: string, command: Command): bytes
```

The digest an operation record keeps of its command. A stored write is digested with the identity of its bytes in
their place, so its bytes are hashed once (Volume.resolveStored) for the digest, the extent and the kept blob.

Effects: fail.

### `advanceCut`

```gizlang
function advanceCut(state: mut State, position: Journal.Position): bool throws i64
```

Volume forwards every committed range index, including non-FS entries, so
acknowledged cuts refer to the common journal rather than FS-only traffic.

Effects: fail.

### `commitHistory`

```gizlang
function commitHistory(state: mut State, history: string, position: Journal.Position): bool throws i64
```

The first range identity is itself a committed consensus decision.

Effects: fail.

### `replay`

```gizlang
function replay(state: State, command: Command): Result<Option<Outcome>, i64>
```

The outcome of COMMAND when it was applied already, none when it is new, or ESTALE when it is not valid.

Effects: fail, read, write, console, io.

### `apply`

```gizlang
function apply(state: mut State, command: Command, position: Journal.Position): Outcome
```

Applies COMMAND at POSITION and returns its outcome.

Effects: fail, read, write, console, io.

### `stat`

```gizlang
function stat(state: State, id: i64): Inode throws i64
```

The inode ID.

Effects: fail, read, write, console, io.

### `lookup`

```gizlang
function lookup(state: State, parent: i64, name: string, uid: i64, gid: i64): Inode throws i64
```

The inode that NAME in directory PARENT names, as UID and GID may see it.

Effects: fail, read, write, console, io.

### `list`

```gizlang
function list(state: State, parent: i64, revision: i64, after: string, count: i64, uid: i64, gid: i64): Listing throws i64
```

Resumable lexical cookies are revision-bound; mutation requires a restart.

Effects: fail, read, write, console, io.

### `read`

```gizlang
function read(state: State, token: SessionToken, handle: i64, offset: i64, count: i64, fetch: (blob: Store.Identity) => Result<bytes, string>): Result<bytes, i64>
```

COUNT bytes at OFFSET of the open HANDLE.

Effects: fail, read, write, console, io.

### `readRange`

```gizlang
function readRange(state: State, token: SessionToken, handle: i64, offset: i64, count: i64, read: (blob: Store.Identity, start: i64, count: i64) => Result<bytes, string>): bytes throws i64
```

COUNT bytes at OFFSET of the open HANDLE, with stored pieces read by READ.

Effects: fail, read, write, console, io.

### `readableHandle`

```gizlang
function readableHandle(state: State, token: SessionToken, handle: i64): Inode throws i64
```

The file that HANDLE of the session reads.

Effects: fail, read, write, console, io.

### `readInode`

```gizlang
function readInode(state: State, token: SessionToken, id: i64, offset: i64, count: i64, uid: i64, gid: i64, read: (blob: Store.Identity, start: i64, count: i64) => Result<bytes, string>): bytes throws i64
```

Reads the file ID for a session that holds no handle of it: a mount's read-only open (no commit to open or close
it). The session must be active, and its principal must be allowed to read the file now, as openFile checks. Inode
ids are never used again, so a removed file is ENOENT.

Effects: fail, read, write, console, io.

### `readableInode`

```gizlang
function readableInode(state: State, token: SessionToken, id: i64, uid: i64, gid: i64): Inode throws i64
```

The file ID, which the session's principal UID GID may read (readInode).

Effects: fail, read, write, console, io.

### `readPieces`

```gizlang
function readPieces(state: State, inode: Inode, offset: i64, count: i64): Vec<Store.RangePiece> throws i64
```

The pieces of a read of COUNT bytes at OFFSET of INODE, up to its size (Store.readPiece reads each).

Effects: fail, read, write, console, io.

### `accessStale`

```gizlang
function accessStale(inode: Inode, now: i64): bool
```

Whether the access time of INODE is to be updated (relatime).

Effects: fail.

### `openedInode`

```gizlang
function openedInode(state: State, token: SessionToken, handle: i64): Inode throws i64
```

The inode of the open HANDLE of the session TOKEN.

Effects: fail, read, write, console, io.

### `changedInode`

```gizlang
function changedInode(state: State, token: SessionToken, op: Op, outcome: Outcome): Option<Inode>
```

The inode a successful OP made or changed, for its reply: a mount answers CREATE, MKNOD, MKDIR, SYMLINK, LINK and
SETATTR with it and asks for no stat. TOKEN is the session that holds the handles OP names.

Effects: fail, read, write, console, io.

### `writeAdmission`

```gizlang
function writeAdmission(state: State, token: SessionToken, handle: i64): bool throws i64
```

Whether the open HANDLE of the session TOKEN may write now.

Effects: fail, read, write, console, io.

### `getxattr`

```gizlang
function getxattr(state: State, id: i64, name: string, uid: i64, gid: i64): bytes throws i64
```

The value of the extended attribute NAME of inode ID.

Effects: fail, read, write, console, io.

### `listxattr`

```gizlang
function listxattr(state: State, id: i64, uid: i64, gid: i64): Vec<string> throws i64
```

The extended attribute names of inode ID.

Effects: fail, read, write, console, io.

### `getlock`

```gizlang
function getlock(state: State, token: SessionToken, handle: i64, owner: i64, profile: string, start: i64, length: i64, exclusive: bool): Result<Option<Lock>, i64>
```

The lock that conflicts with a request on HANDLE, if any (fcntl F_GETLK).

Effects: fail, read, write, console, io.

### `receipt`

```gizlang
function receipt(state: State, token: SessionToken, sequence: i64, uid: i64, gid: i64): Receipt throws i64
```

The receipt of command SEQUENCE of the session TOKEN.

Effects: fail, read, write, console, io.

### `commandReceipt`

```gizlang
function commandReceipt(state: State, command: Command): Receipt throws i64
```

A mutation response may reuse a retained receipt only for that exact payload.
Status-by-sequence remains a separate query and cannot certify a changed retry.

Effects: fail, read, write, console, io.

### `lockStatus`

```gizlang
function lockStatus(state: State, token: SessionToken, sequence: i64, uid: i64, gid: i64): Receipt throws i64
```

Resolves the original lock request. A canceled or granted terminal outcome
never changes on retry, and reading status never adds operation records.

Effects: fail, read, write, console, io.

### `roots`

```gizlang
function roots(state: State): Vec<Store.Identity>
```

Live namespace roots include unlinked open files until the final close.

Effects: fail, read, write, console, io.

### `rootDelta`

```gizlang
function rootDelta(state: State): Vec<RootDelta>
```

Hot publication consumes only IDs emitted by canonical mutation points.
Restore uses roots/full catalog rebuilding; this transient projection never
scans unrelated inode extents or participates in a snapshot encoding.

Effects: fail, read, write, console, io.

### `formats`

```gizlang
function formats(): Vec<Format>
```

The on-disk formats this module reads and writes.

Effects: fail.

### `encodeCommand`

```gizlang
function encodeCommand(command: Command): bytes
```

The bytes of COMMAND.

Effects: fail.

### `writeCommand`

```gizlang
function writeCommand(out: mut bytes, command: Command): void
```

Appends the encoding of COMMAND to OUT: a log entry writes its tag and the command into one buffer, so a stored
write's bytes are copied once, not into the command and then into the entry.

Effects: fail.

### `decodeCommand`

```gizlang
function decodeCommand(data: bytes): Command throws string
```

The command DATA holds.

Effects: fail, read, write, console, io.

### `writeToken`

```gizlang
function writeToken(out: mut bytes, token: SessionToken): void
```

Writes TOKEN to OUT.

Effects: fail.

### `writeInode`

```gizlang
function writeInode(out: mut bytes, inode: Inode): void
```

Writes INODE to OUT.

Effects: fail, read.

### `encodeState`

```gizlang
function encodeState(state: State): bytes
```

The bytes of STATE (a snapshot).

Effects: fail, read, write, console, io.

### `nativeImage`

```gizlang
function nativeImage(data: bytes): bool
```

Whether DATA is a snapshot of a native state.

Effects: fail.

### `nativePageBytes`

```gizlang
function nativePageBytes(data: bytes): i64 throws string
```

The page bytes of the native snapshot DATA.

Effects: fail, read, write, console, io.

### `writeSession`

```gizlang
function writeSession(out: mut bytes, session: Session): void
```

Writes SESSION to OUT.

Effects: fail.

### `writeFsReceipt`

```gizlang
function writeFsReceipt(out: mut bytes, receipt: Receipt): void
```

Writes RECEIPT to OUT.

Effects: fail.

### `encodedSize`

```gizlang
function encodedSize(state: State): i64
```

The bytes of the snapshot of STATE. A native state counts the roots of its pages as they are: they encode in as many
bytes as the roots of a snapshot, which write the pending changes of each command (nativeStateBytes).

Effects: fail, read, write, console, io.

### `decodeState`

```gizlang
function decodeState(data: bytes, policy: Durability, bounds: Limits): State throws string
```

The state the snapshot DATA holds.

Effects: fail, read, write, console, io.

### `branchState`

```gizlang
function branchState(source: State, history: string, uid: i64): State throws string
```

Explicit writable branch: retain source open descriptions and historical
outcomes, remove stale lock authority, and require fresh issued resume tokens.
Ordinary snapshot installation never calls this operation.

Effects: fail, read, write, console, io.

### `validateState`

```gizlang
function validateState(state: State): bool throws string
```

A digest is insufficient if a snapshot encodes impossible references.

Effects: fail, read, write, console, io.

### `newNativeState`

```gizlang
function newNativeState(policy: Durability, bounds: Limits, uid: i64, gid: i64, history: string, owner: Ref<NativePages>): State throws string
```

A new, empty state whose tables are pages that OWNER keeps.

Effects: fail, read, write, console, io.

### `pageState`

```gizlang
function pageState(source: State, owner: Ref<NativePages>): State throws string
```

The state of SOURCE in the pages of OWNER: one explicit migration of a bounded old snapshot, or a page compaction
of a native state (Volume.compactPages), which copies only what its rows reach. All derived indexes are rebuilt from
their semantic owners; old slot addresses are never imported. A native state goes into pages of another owner, with
no delta of a commit; extents in the inode row stay there (placedExtents).

Effects: fail, read, write, console, io.

### `encodeNativeState`

```gizlang
function encodeNativeState(state: State): bytes throws string
```

The bytes of the native STATE (a snapshot).

Effects: fail, read, write, console, io.

### `nativeFiles`

```gizlang
function nativeFiles(state: State): NativeFiles throws string
```

The files of the native STATE.

Effects: fail, read, write, console, io.

### `decodeNativeState`

```gizlang
function decodeNativeState(data: bytes, policy: Durability, bounds: Limits, owner: Ref<NativePages>): State throws string
```

The native state the snapshot DATA holds, its pages kept by OWNER.

Effects: fail, read, write, console, io.

## Methods

### `Reader.sessionToken`

```gizlang
function Reader.sessionToken(self: mut Reader): SessionToken
```

Reads a SessionToken.

Effects: fail, read, write, console, io.

### `Reader.inode`

```gizlang
function Reader.inode(self: mut Reader): Inode
```

Reads an Inode.

Effects: fail, read, write, console, io.

### `Reader.inodeWithPages`

```gizlang
function Reader.inodeWithPages(self: mut Reader, owner: Option<Ref<NativePages>>): Inode
```

Reads an Inode whose pages OWNER keeps, if any.

Effects: fail, read, write, console, io.

### `Reader.session`

```gizlang
function Reader.session(self: mut Reader, bounds: Limits): Session
```

Reads a Session within BOUNDS.

Effects: fail, read, write, console, io.

### `Reader.fsReceipt`

```gizlang
function Reader.fsReceipt(self: mut Reader): Receipt
```

Reads a Receipt.

Effects: fail, read, write, console, io.

## Constants

### `EPERM`

```gizlang
const EPERM = -1
```

The errno EPERM, negated: the operation is not permitted.

### `ENOENT`

```gizlang
const ENOENT = -2
```

The errno ENOENT, negated: no such file or directory.

### `EINTR`

```gizlang
const EINTR = -4
```

The errno EINTR, negated: the call was interrupted.

### `EIO`

```gizlang
const EIO = -5
```

The errno EIO, negated: an input or output error.

### `EBADF`

```gizlang
const EBADF = -9
```

The errno EBADF, negated: the handle is not open.

### `EAGAIN`

```gizlang
const EAGAIN = -11
```

The errno EAGAIN, negated: try again (a lock is held).

### `EACCES`

```gizlang
const EACCES = -13
```

The errno EACCES, negated: permission denied.

### `EEXIST`

```gizlang
const EEXIST = -17
```

The errno EEXIST, negated: the name exists.

### `ENOTDIR`

```gizlang
const ENOTDIR = -20
```

The errno ENOTDIR, negated: not a directory.

### `EISDIR`

```gizlang
const EISDIR = -21
```

The errno EISDIR, negated: a directory.

### `EINVAL`

```gizlang
const EINVAL = -22
```

The errno EINVAL, negated: an invalid argument.

### `ENOSPC`

```gizlang
const ENOSPC = -28
```

The errno ENOSPC, negated: no space left (a limit of Limits).

### `EDEADLK`

```gizlang
const EDEADLK = -35
```

The errno EDEADLK, negated: a lock wait would deadlock.

### `ENODATA`

```gizlang
const ENODATA = -61
```

The errno ENODATA, negated: no such extended attribute.

### `ENOTEMPTY`

```gizlang
const ENOTEMPTY = -39
```

The errno ENOTEMPTY, negated: the directory is not empty.

### `ELOOP`

```gizlang
const ELOOP = -40
```

The errno ELOOP, negated: too many symbolic links.

### `EINPROGRESS`

```gizlang
const EINPROGRESS = -115
```

The errno EINPROGRESS, negated: the operation is still in progress.

### `ENOTSUP`

```gizlang
const ENOTSUP = -95
```

The errno ENOTSUP, negated: the operation is not supported.

### `ESTALE`

```gizlang
const ESTALE = -116
```

The errno ESTALE, negated: the session or handle is stale.

### `EBUSY`

```gizlang
const EBUSY = -16
```

The errno EBUSY, negated: the resource is busy.

### `EXDEV`

```gizlang
const EXDEV = -18
```

The errno EXDEV, negated: the rename crosses ranges.

### `EDQUOT`

```gizlang
const EDQUOT = -122
```

A quota root's limit refuses the bytes (Quota).

### `RENAME_NOREPLACE`

```gizlang
const RENAME_NOREPLACE = 1
```

The flag of Op.rename that refuses to replace a name at the target (renameat2 RENAME_NOREPLACE).

### `BAND_BITS`

```gizlang
const BAND_BITS = 40
```

The inode and handle numbers of a range are a band: BAND << BAND_BITS on (Ranges). Band 0 holds the namespace root.
A file or directory that a directory of another range names (Op.junction) has an anchor here instead of a name.

### `MAX_BAND`

```gizlang
const MAX_BAND = 4194304
```

The bands: band << BAND_BITS stays far under the largest i64.

### `ANCHOR`

```gizlang
const ANCHOR = 0
```

The parent of the anchors: the entry string(ID) under ANCHOR keeps file or directory ID while a directory of
another range names it, and the inode has that directory as its parent. No inode has this number, so no path shows
an anchor.

### `REMOTE`

```gizlang
const REMOTE = "remote"
```

The `of` of an inode whose content is in another range.

### `PRUNE_BATCH`

```gizlang
const PRUNE_BATCH = 64
```

The most journal entries one prune removes.

### `QUOTA_ATTRIBUTE`

```gizlang
const QUOTA_ATTRIBUTE = "user.gizfs.quota"
```

The xattr that gives a directory a quota (changeXattr): the limit in bytes, in decimal.

### `MAX_QUOTAS`

```gizlang
const MAX_QUOTAS = 65536
```

The quota records a range keeps at most: one for each Drive.

### `STORED_WRITE_BYTES`

```gizlang
const STORED_WRITE_BYTES = 65536
```

The largest write whose bytes ride in its own command. Each voter writes them once, as an immutable blob, before
the log entry that names them by identity (Volume.logged); the blob is synced before that entry (Raft ordered).

### `MAX_STORE_PIECES`

```gizlang
const MAX_STORE_PIECES = 1024
```

The most pieces of one stored file.

### `MAX_BATCH_OPS`

```gizlang
const MAX_BATCH_OPS = 64
```

Most ops of one batch: its log entry stays far under MAX_COMMAND_BYTES.

### `INLINE_STORE_BYTES`

```gizlang
const INLINE_STORE_BYTES = 65536
```

A stored write of fewer bytes stays in its log entry; a larger one goes to its blob and the entry names it
(Volume.logged).

