summaryrefslogtreecommitdiff
path: root/lib9p/idl
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-10-09 00:00:32 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-10-09 00:00:32 -0600
commitbed78039f9bf086d35a3ae5efc8e6701c50ed006 (patch)
tree38fd0e196f08673f43f984b4228a4b6b5c647431 /lib9p/idl
parent5dfff05adef9b1e09cff350c2dc551fdac6d227a (diff)
wip idl rewrite
Diffstat (limited to 'lib9p/idl')
-rw-r--r--lib9p/idl/00-README.md48
-rw-r--r--lib9p/idl/01-9P2000.9p147
-rw-r--r--lib9p/idl/02-9P2000.e.9p18
-rw-r--r--lib9p/idl/02-9P2000.u.9p29
-rw-r--r--lib9p/idl/03-9P2000.L.9p.wip56
5 files changed, 298 insertions, 0 deletions
diff --git a/lib9p/idl/00-README.md b/lib9p/idl/00-README.md
new file mode 100644
index 0000000..f53acf9
--- /dev/null
+++ b/lib9p/idl/00-README.md
@@ -0,0 +1,48 @@
+# 9P protocol definitions
+<!--
+ Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ SPDX-Licence-Identifier: AGPL-3.0-or-later
+ -->
+
+This directory contains several `*.9p` files, each of which describes
+a 9P protocol variant.
+
+In the 9P protocol, each message has a type, and message types come
+in pairs (except "Rerror"); "T" and "R"; T-messages are
+client->server requests, and R-messages are server->client responses
+(the client "Transmits" T-messages and "Receives" R-messages). The
+type of a message is represented by a u8 ID; T-messages are even and
+R-messages are odd.
+
+Messages are made up of the primitives; unsigned little-endian
+integers, identified with the following single-character mnemonics:
+
+ - 1 = u8
+ - 2 = u16le
+ - 4 = u32le
+ - 8 = u16le
+
+Out of these primitives, we can make other numeric types,
+
+ num NUMNAME = PRIMITIVE_TYPE
+
+bitfields,
+
+ bitfield BFNAME = PRIMITIVE_TYPE "NBIT=NAME... ALIAS=VAL..."
+
+structures,
+
+ struct STRUCTNAME = "FILENAME[FIELDTYPE]..."
+
+and messages (which are a special-case of structures).
+
+ msg Tname = "size[4,val=end-&size] typ[1,val=TYP] tag[tag] REST..."
+
+Struct fields that have numeric types (either primitives or `num`
+types) can add to their type `,val=` and/or `,max=` to specify what
+the exact value must be and/or what the maximum (inclusive) value is.
+
+`,val=` and `,max` take a string of `+`/`-` tokens and values; a value
+can either be a decimal numeric constant (eg: `107`), the `&fieldname`
+to refer to the offset of a field name in that struct, or the special
+value `end` to refer to the offset of the end of the struct.
diff --git a/lib9p/idl/01-9P2000.9p b/lib9p/idl/01-9P2000.9p
new file mode 100644
index 0000000..680d243
--- /dev/null
+++ b/lib9p/idl/01-9P2000.9p
@@ -0,0 +1,147 @@
+# 01-9P2000.9p - Definitions of 9P2000 messages
+#
+# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-Licence-Identifier: AGPL-3.0-or-later
+
+# "9P2000" base protocol
+# https://ericvh.github.io/9p-rfc/rfc9p2000.html
+# https://github.com/ericvh/9p-rfc/blob/master/9p2000.xml
+#
+# But due to incompleteness of the draft RFC, the Plan 9 manual
+# section-5 and the Plan 9 headers (particularly fcall.h) are often
+# better references.
+#
+# https://github.com/plan9foundation/plan9/tree/main/sys/man/5
+# https://man.cat-v.org/plan_9/5/
+# https://github.com/plan9foundation/plan9/blob/main/sys/include/fcall.h
+version "9P2000"
+
+# tag - identify a request/response pair
+num tag = 2
+
+# file identifier
+num fid = 4
+
+# data - u32le `n`, then `n` bytes of data
+struct d = "len[4] len*(dat[1])"
+
+# string - u16le `n`, then `n` bytes of UTF-8, without any nul-bytes
+struct s = "len[2] len*(utf8[1])"
+
+# "d"? mode - file permissions and attributes
+bitfield dm = 4
+ "31=DIR"
+ "30=APPEND"
+ "29=EXCL"
+ # DMMOUNT has been around in Plan 9 forever, but is
+ # undocumented, and is explicitly excluded from the 9P2000
+ # draft RFC. As I understand it, DMMOUNT indicates that the
+ # file is mounted by the kernel as a 9P transport; that the
+ # kernel has a lock on doing I/O on it, so userspace can't do
+ # I/O on it.
+ "28=_PLAN9_MOUNT"
+ "27=AUTH"
+ "26=TMP"
+ #...
+ "8=OWNER_R"
+ "7=OWNER_W"
+ "6=OWNER_X"
+ "5=GROUP_R"
+ "4=GROUP_W"
+ "3=GROUP_X"
+ "2=OTHER_R"
+ "1=OTHER_W"
+ "0=OTHER_X"
+
+ "PERM=0777" # {OWNER,GROUP,OTHER}_{R,W,X}
+
+# QID Type - see `struct qid` below
+bitfield qt = 1
+ "7=DIR"
+ "6=APPEND"
+ "5=EXCL"
+ "4=_PLAN9_MOUNT" # see "MOUNT" in "dm" above
+ "3=AUTH"
+ # Fun historical fact: QTTMP was a relatively late addition to
+ # Plan 9, in 2003-12.
+ "2=TMP"
+ #"1=unused"
+
+ # "The name QTFILE, defined to be zero, identifies the value
+ # of the type for a plain file."
+ "FILE=0"
+
+# uni"Q"ue "ID"entification - "two files on the same server hierarchy
+# are the same if and only if their qids are the same"
+#
+# - "path" is a unique uint64_t that does most of the work in the
+# above statement about files being the same if their QIDs are the
+# same; " If a file is deleted and recreated with the same name in
+# the same directory, the old and new path components of the qids
+# should be different"
+#
+# - "vers" "is a version number for a file; typically, it is
+# incremented every time the file is modified.
+#
+# - "type" indicates "whether the file is a directory, append-only
+# file, etc."; is an instance of the qid_type bitfield.
+struct qid = "type[qt] vers[4] path[8]"
+
+# stat - file status
+struct stat = "stat_size[2,val=end-&kern_type]"
+ "kern_type[2]"
+ "kern_dev[4]"
+ "file_qid[qid]"
+ "file_mode[dm]"
+ "file_atime[4]"
+ "file_mtime[4]"
+ "file_size[8]"
+ "file_name[s]"
+ "file_owner_uid[s]"
+ "file_owner_gid[s]"
+ "file_last_modified_uid[s]"
+
+# "O"pen flags (flags to pass to Topen and Tcreate)
+bitfield o = 1
+ "0=rwx_0" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum
+ "1=rwx_1" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum"
+ #"2=unused"
+ #"3=unused"
+ "4=TRUNC"
+ #"5=unused"
+ "6=RCLOSE" # remove-on-close
+ #"7=unused"
+
+ "READ = 0" # make available for this FID: Tread()
+ "WRITE = 1" # make available for this FID: Twrite()
+ "RDWR = 2" # make available for this FID: Tread() and Twrite()
+ "EXEC = 3" # make available for this FID: Tread()
+
+msg Tversion = "size[4,val=end-&size] typ[1,val=100] tag[tag] max_msg_size[4] version[s]"
+msg Rversion = "size[4,val=end-&size] typ[1,val=101] tag[tag] max_msg_size[4] version[s]"
+msg Tauth = "size[4,val=end-&size] typ[1,val=102] tag[tag] afid[fid] uname[s] aname[s]"
+msg Rauth = "size[4,val=end-&size] typ[1,val=103] tag[tag] aqid[qid]"
+msg Tattach = "size[4,val=end-&size] typ[1,val=104] tag[tag] fid[fid] afid[fid] uname[s] aname[s]"
+msg Rattach = "size[4,val=end-&size] typ[1,val=105] tag[tag] qid[qid]"
+#msg Terror = "size[4,val=end-&size] typ[1,val=106] tag[tag] illegal"
+msg Rerror = "size[4,val=end-&size] typ[1,val=107] tag[tag] ename[s]"
+msg Tflush = "size[4,val=end-&size] typ[1,val=108] tag[tag] oldtag[2]"
+msg Rflush = "size[4,val=end-&size] typ[1,val=109] tag[tag]"
+msg Twalk = "size[4,val=end-&size] typ[1,val=110] tag[tag] fid[fid] newfid[fid] nwname[2,max=16] nwname*(wname[s])"
+msg Rwalk = "size[4,val=end-&size] typ[1,val=111] tag[tag] nwqid[2,max=16] nwqid*(wqid[qid])"
+msg Topen = "size[4,val=end-&size] typ[1,val=112] tag[tag] fid[fid] mode[o]"
+msg Ropen = "size[4,val=end-&size] typ[1,val=113] tag[tag] qid[qid] iounit[4]"
+msg Tcreate = "size[4,val=end-&size] typ[1,val=114] tag[tag] fid[fid] name[s] perm[dm] mode[o]"
+msg Rcreate = "size[4,val=end-&size] typ[1,val=115] tag[tag] qid[qid] iounit[4]"
+msg Tread = "size[4,val=end-&size] typ[1,val=116] tag[tag] fid[fid] offset[8] count[4]"
+msg Rread = "size[4,val=end-&size] typ[1,val=117] tag[tag] data[d]" # for directories, `data` is the sequence "cnt*(entries[stat])"
+msg Twrite = "size[4,val=end-&size] typ[1,val=118] tag[tag] fid[fid] offset[8] data[d]"
+msg Rwrite = "size[4,val=end-&size] typ[1,val=119] tag[tag] count[4]"
+msg Tclunk = "size[4,val=end-&size] typ[1,val=120] tag[tag] fid[fid]"
+msg Rclunk = "size[4,val=end-&size] typ[1,val=121] tag[tag]"
+msg Tremove = "size[4,val=end-&size] typ[1,val=122] tag[tag] fid[fid]"
+msg Rremove = "size[4,val=end-&size] typ[1,val=123] tag[tag]"
+msg Tstat = "size[4,val=end-&size] typ[1,val=124] tag[tag] fid[fid]"
+msg Rstat = "size[4,val=end-&size] typ[1,val=125] tag[tag] nstat[2,val=end-&stat] stat[stat]" # See the "BUG" note in the RFC for the nstat field
+msg Twstat = "size[4,val=end-&size] typ[1,val=126] tag[tag] fid[fid] nstat[2,val=end-&stat] stat[stat]" # See the "BUG" note in the RFC for the nstat field
+msg Rwstat = "size[4,val=end-&size] typ[1,val=127] tag[tag]"
diff --git a/lib9p/idl/02-9P2000.e.9p b/lib9p/idl/02-9P2000.e.9p
new file mode 100644
index 0000000..b91b2c5
--- /dev/null
+++ b/lib9p/idl/02-9P2000.e.9p
@@ -0,0 +1,18 @@
+# 02-9P2000e.e.9p - Definitions of 9P2000.e messages
+#
+# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-Licence-Identifier: AGPL-3.0-or-later
+
+# "9P2000.e" Erlang extension
+# https://erlangonxen.org/more/9p2000e
+# https://github.com/cloudozer/ling/blob/master/doc/9p2000e.md
+version "9P2000.e"
+
+from ./01-9P2000.9p import *
+
+msg Tsession = "size[4,val=end-&size] typ[1,val=150] tag[tag] key[8]"
+msg Rsession = "size[4,val=end-&size] typ[1,val=151] tag[tag]"
+msg Tsread = "size[4,val=end-&size] typ[1,val=152] tag[tag] fid[4] nwname[2] nwname*(wname[s])"
+msg Rsread = "size[4,val=end-&size] typ[1,val=153] tag[tag] data[d]"
+msg Tswrite = "size[4,val=end-&size] typ[1,val=154] tag[tag] fid[4] nwname[2] nwname*(wname[s]) data[d]"
+msg Rswrite = "size[4,val=end-&size] typ[1,val=155] tag[tag] count[4]"
diff --git a/lib9p/idl/02-9P2000.u.9p b/lib9p/idl/02-9P2000.u.9p
new file mode 100644
index 0000000..d3ca6f0
--- /dev/null
+++ b/lib9p/idl/02-9P2000.u.9p
@@ -0,0 +1,29 @@
+# 02-9P2000.u.9p - Definitions of 9P2000.u messages
+#
+# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-Licence-Identifier: AGPL-3.0-or-later
+
+# "9P2000.u" Unix extension
+# https://ericvh.github.io/9p-rfc/rfc9p2000.u.html
+# https://github.com/ericvh/9p-rfc/blob/master/9p2000.u.xml
+version "9P2000.u"
+
+from ./01-9P2000.9p import *
+
+struct stat += "file_extension[s]"
+ "file_owner_n_uid[4]"
+ "file_owner_n_gid[4]"
+ "file_last_modified_n_uid[4]"
+
+msg Tauth += "n_uname[4]"
+msg Tattach += "n_uname[4]"
+
+msg Rerror += "errno[4]"
+
+bitfield dm += "23=DEVICE"
+ "21=NAMEDPIPE"
+ "20=SOCKET"
+ "19=SETUID"
+ "18=SETGID"
+
+bitfield qt += "1=SYMLINK"
diff --git a/lib9p/idl/03-9P2000.L.9p.wip b/lib9p/idl/03-9P2000.L.9p.wip
new file mode 100644
index 0000000..62186f9
--- /dev/null
+++ b/lib9p/idl/03-9P2000.L.9p.wip
@@ -0,0 +1,56 @@
+# 9P2000.L.txt - Definitions of 9P2000.L messages
+#
+# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-Licence-Identifier: AGPL-3.0-or-later
+
+# "9P2000.L" Linux extension
+# https://github.com/chaos/diod/blob/master/protocol.md
+version "9P2000.L"
+
+from ./01-9P2000.9p import *
+from ./02-9P2000.u.9p import Tauth, Tattach
+
+#msg Tlerror = "size[4,val=end-&size] typ[1,val=6] tag[tag] illegal" # analogous to 106/Terror
+msg Rlerror = "size[4,val=end-&size] typ[1,val=7] tag[tag] ecode[4]" # analogous to 107/Rerror
+msg Tstatfs = "size[4,val=end-&size] typ[1,val=8] tag[tag] TODO"
+msg Rstatfs = "size[4,val=end-&size] typ[1,val=9] tag[tag] TODO"
+msg Tlopen = "size[4,val=end-&size] typ[1,val=12] tag[tag] TODO" # analogous to 112/Topen
+msg Rlopen = "size[4,val=end-&size] typ[1,val=13] tag[tag] TODO" # analogous to 113/Ropen
+msg Tlcreate = "size[4,val=end-&size] typ[1,val=14] tag[tag] TODO" # analogous to 114/Tcreate
+msg Rlcreate = "size[4,val=end-&size] typ[1,val=15] tag[tag] TODO" # analogous to 115/Rcreate
+msg Tsymlink = "size[4,val=end-&size] typ[1,val=16] tag[tag] TODO"
+msg Rsymlink = "size[4,val=end-&size] typ[1,val=17] tag[tag] TODO"
+msg Tmknod = "size[4,val=end-&size] typ[1,val=18] tag[tag] TODO"
+msg Rmknod = "size[4,val=end-&size] typ[1,val=19] tag[tag] TODO"
+msg Trename = "size[4,val=end-&size] typ[1,val=20] tag[tag] TODO"
+msg Rrename = "size[4,val=end-&size] typ[1,val=21] tag[tag] TODO"
+msg Treadlink = "size[4,val=end-&size] typ[1,val=22] tag[tag] TODO"
+msg Rreadlink = "size[4,val=end-&size] typ[1,val=23] tag[tag] TODO"
+msg Tgetattr = "size[4,val=end-&size] typ[1,val=24] tag[tag] TODO"
+msg Rgetattr = "size[4,val=end-&size] typ[1,val=25] tag[tag] TODO"
+msg Tsetattr = "size[4,val=end-&size] typ[1,val=26] tag[tag] TODO"
+msg Rsetattr = "size[4,val=end-&size] typ[1,val=27] tag[tag] TODO"
+#...
+msg Txattrwalk = "size[4,val=end-&size] typ[1,val=30] tag[tag] TODO"
+msg Rxattrwalk = "size[4,val=end-&size] typ[1,val=31] tag[tag] TODO"
+msg Txattrcreate = "size[4,val=end-&size] typ[1,val=32] tag[tag] TODO"
+msg Rxattrcreate = "size[4,val=end-&size] typ[1,val=33] tag[tag] TODO"
+#...
+msg Treaddir = "size[4,val=end-&size] typ[1,val=40] tag[tag] TODO"
+msg Rreaddir = "size[4,val=end-&size] typ[1,val=41] tag[tag] TODO"
+#...
+msg Tfsync = "size[4,val=end-&size] typ[1,val=50] tag[tag] TODO"
+msg Rfsync = "size[4,val=end-&size] typ[1,val=51] tag[tag] TODO"
+msg Tlock = "size[4,val=end-&size] typ[1,val=52] tag[tag] TODO"
+msg Rlock = "size[4,val=end-&size] typ[1,val=53] tag[tag] TODO"
+msg Tgetlock = "size[4,val=end-&size] typ[1,val=54] tag[tag] TODO"
+msg Rgetlock = "size[4,val=end-&size] typ[1,val=55] tag[tag] TODO"
+# ...
+msg Tlink = "size[4,val=end-&size] typ[1,val=70] tag[tag] TODO"
+msg Rlink = "size[4,val=end-&size] typ[1,val=71] tag[tag] TODO"
+msg Tmkdir = "size[4,val=end-&size] typ[1,val=72] tag[tag] TODO"
+msg Tmkdir = "size[4,val=end-&size] typ[1,val=73] tag[tag] TODO"
+msg Trenameat = "size[4,val=end-&size] typ[1,val=74] tag[tag] TODO"
+msg Rrenameat = "size[4,val=end-&size] typ[1,val=75] tag[tag] TODO"
+msg Tunlinkat = "size[4,val=end-&size] typ[1,val=76] tag[tag] TODO"
+msg Runlinkat = "size[4,val=end-&size] typ[1,val=77] tag[tag] TODO"