diff options
Diffstat (limited to 'lib9p/idl/2002-9P2000.9p')
-rw-r--r-- | lib9p/idl/2002-9P2000.9p | 124 |
1 files changed, 67 insertions, 57 deletions
diff --git a/lib9p/idl/2002-9P2000.9p b/lib9p/idl/2002-9P2000.9p index 03f00c2..13393c6 100644 --- a/lib9p/idl/2002-9P2000.9p +++ b/lib9p/idl/2002-9P2000.9p @@ -1,6 +1,6 @@ -# 2002-9P2000.9p - Definitions of 9P2000 messages +# lib9p/idl/2002-9P2000.9p - Definitions of 9P2000 messages # -# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> +# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later # "9P2000" base protocol @@ -9,74 +9,77 @@ # # 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. +# better references. The s{32,64}_max limitations are not documented +# in the draft RFC or the manual pages, but have been enforced by +# lib9p/srv.c in every release of Plan 9 4e. # # 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 +# https://github.com/plan9foundation/plan9/blob/main/sys/include/libc.h +# https://github.com/plan9foundation/plan9/blob/main/sys/src/lib9p/srv.c version "9P2000" # tag - identify a request/response pair num tag = 2 + "NOTAG = u16_max" # file identifier - like a UNIX file-descriptor num fid = 4 - -# data - u32le `n`, then `n` bytes of data -struct d = "len[4] len*(dat[1])" + "NOFID = u32_max" # 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 +# "D"ir-entry "M"ode - 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" + "bit 31=DIR" + "bit 30=APPEND" + "bit 29=EXCL" + # DMMOUNT has been around in Plan 9 since 2e (CHMOUNT in <4e), + # 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. + "bit 28=_PLAN9_MOUNT" + "bit 27=AUTH" + "bit 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" + "bit 8=OWNER_R" + "bit 7=OWNER_W" + "bit 6=OWNER_X" + "bit 5=GROUP_R" + "bit 4=GROUP_W" + "bit 3=GROUP_X" + "bit 2=OTHER_R" + "bit 1=OTHER_W" + "bit 0=OTHER_X" - "PERM_MASK=0777" # {OWNER,GROUP,OTHER}_{R,W,X} + "mask 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" + "bit 7=DIR" + "bit 6=APPEND" + "bit 5=EXCL" + "bit 4=_PLAN9_MOUNT" # See "_PLAN9_MOUNT" in "dm" above. + "bit 3=AUTH" # Fun historical fact: QTTMP was a relatively late addition to # Plan 9, in 2003-12. - "2=TMP" - #"1=unused" + "bit 2=TMP" + #"bit 1=unused" # "The name QTFILE, defined to be zero, identifies the value # of the type for a plain file." - "FILE=0" + "alias 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 +# 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" # @@ -102,23 +105,30 @@ struct stat = "stat_size[2,val=end-&kern_type]" "file_last_modified_uid[s]" # "O"pen flags (flags to pass to Topen and Tcreate) +# Unused bits *must* be 0. bitfield o = 1 - "0=mode_0" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum - "1=mode_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" + "bit 0=num(MODE)" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum + "bit 1=num(MODE)" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum + #"bit 2=unused" + #"bit 3=unused" + "bit 4=TRUNC" + "bit 5=reserved(CEXEC)" # close-on-exec + "bit 6=RCLOSE" # remove-on-close + #"bit 7=unused" + + "num(MODE) READ = 0" # make available for this FID: Tread() + "num(MODE) WRITE = 1" # make available for this FID: Twrite() + "num(MODE) RDWR = 2" # make available for this FID: Tread() and Twrite() + "num(MODE) EXEC = 3" # make available for this FID: Tread() - "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() + "mask FLAG = 0b11111100" - "MODE_MASK = 0b00000011" - "FLAG_MASK = 0b11111100" +# A 9P2000 session goes: +# +# version() +# [auth_fid=auth] +# attach([auth_fid]) +# ... 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]" @@ -127,7 +137,7 @@ 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 Rerror = "size[4,val=end-&size] typ[1,val=107] tag[tag] errstr[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])" @@ -136,10 +146,10 @@ 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 Tread = "size[4,val=end-&size] typ[1,val=116] tag[tag] fid[fid] offset[8,max=s64_max] count[4,max=s32_max]" # See 4e `sys/src/lib9p/srv.c:sread()` for `offset:max` and `count:max`. +msg Rread = "size[4,val=end-&size] typ[1,val=117] tag[tag] count[4,max=s32_max] count*(data[1])" # `max` is inherited from Tread, 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,max=s64_max] count[4,max=s32_max] count*(data[1])" # See 4e `sys/src/lib9p/srv.c:swrite()` for `offset:max` and `count:max`. +msg Rwrite = "size[4,val=end-&size] typ[1,val=119] tag[tag] count[4,max=s32_max]" # `max` is inherited from Twrite. 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]" |