From 66f2e492c348677ab3050f5e378b9eb4c04c98ce Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Sun, 20 Sep 2026 01:47:28 -0300 Subject: 9proc core becomes a backend of cloud9.fs; engine gains optional features 9proc's own fid table, walk loop and dir-read engine are replaced by cloud9.fs.Server; the tree (static, vars, providers) is served through the engine's Req/Reply contract with node ids that keep the old qid scheme. Providers may answer later by returning error.Again (parked in the engine, retried each step, Tflush -> EINTR); no new files are exposed. Engine (backward compatible, all opt-in via Backend.features / Options): create, remove, wstat, reference accounting for backends that count handles, a salted fid index, name_capacity 0 (names from getattr), Reply.ename for backend-chosen error text, Attr.path/version/atime. Engine-level error strings and the 217-byte msize floor now apply to 9proc; tests updated accordingly. Co-Authored-By: Claude Fable 5.1 --- 9proc/test/adv_9proc_hostile.py | 125 +++++++++++++++++-------------- 9proc/test/adv_core_hostile.py | 158 +++++++++++++++++++++------------------- 2 files changed, 152 insertions(+), 131 deletions(-) (limited to '9proc/test') diff --git a/9proc/test/adv_9proc_hostile.py b/9proc/test/adv_9proc_hostile.py index 934e757..dfa0d20 100755 --- a/9proc/test/adv_9proc_hostile.py +++ b/9proc/test/adv_9proc_hostile.py @@ -21,6 +21,22 @@ import time NOTAG = 0xFFFF NOFID = 0xFFFFFFFF + +# The Rerror strings of the conditions cloud9.fs (the file-server engine the +# core is a backend of) decides itself; the tree's own refusals keep the +# Plan 9 strings ("file does not exist", "bad command", ...). +MSIZE_MIN = 217 # one full Rwalk must fit +E_UNKNOWN_FID = "fid unknown or out of range" +E_FID_IN_USE = "fid already in use" +E_TOO_MANY_FIDS = "Too many open files in system" +E_BAD_USE = "bad use of fid" # I/O on an unopened fid; a walk or clone from an open one +E_ALREADY_OPEN = "file already open for I/O" # open or create on an open fid +E_BAD_OFFSET = "bad offset in directory read" +E_PERM = "permission denied" # the engine's own refusals: dirs for write, OEXEC, static trees +E_WSTAT = "wstat prohibited" # engine-owned stat fields, or a length on a directory +E_ILLEGAL_NAME = "illegal name" # names of creates and renames +E_INVAL = "Invalid argument" # a reply that cannot fit msize; a dir read count below one record +E_INTERRUPTED = "Interrupted system call" Tversion, Rversion, Tauth, Rauth, Tattach, Rattach, Rerror = 100, 101, 102, 103, 104, 105, 107 Tflush, Rflush, Twalk, Rwalk, Topen, Ropen, Tcreate, Rcreate = 108, 109, 110, 111, 112, 113, 114, 115 Tread, Rread, Twrite, Rwrite, Tclunk, Rclunk, Tremove, Rremove = 116, 117, 118, 119, 120, 121, 122, 123 @@ -303,37 +319,31 @@ def attack_framing(path): c.raw(frame(Tversion, 5, struct.pack("0 ok("walk to file", c.walk_ok(0, 1, [b"build", b"target"]) == 2) ok("walk from file fails 'not a directory'", c.err(Twalk, struct.pack(" 0) - ok("read dir at bad offset", c.err(Tread, struct.pack(" 12 else ''} is a partial walk (1)", n == 1, n) - ok(" and newfid stays unbound", c.err(Tclunk, struct.pack("