summaryrefslogtreecommitdiff
path: root/lib9p/idl
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/idl')
-rw-r--r--lib9p/idl/1992-9P0.9p.wip2
-rw-r--r--lib9p/idl/1996-Styx.9p.wip2
-rw-r--r--lib9p/idl/2002-9P2000.9p2
-rw-r--r--lib9p/idl/2003-9P2000.p9p.9p2
-rw-r--r--lib9p/idl/2005-9P2000.u.9p2
-rw-r--r--lib9p/idl/2010-9P2000.L.9p165
-rwxr-xr-xlib9p/idl/2010-9P2000.L.9p.gen282
-rw-r--r--lib9p/idl/__init__.py20
8 files changed, 459 insertions, 18 deletions
diff --git a/lib9p/idl/1992-9P0.9p.wip b/lib9p/idl/1992-9P0.9p.wip
index a434ba2..c9432c9 100644
--- a/lib9p/idl/1992-9P0.9p.wip
+++ b/lib9p/idl/1992-9P0.9p.wip
@@ -107,7 +107,7 @@ msg Rnop = "typ[1,val=51] tag[tag,val=0xFFFF]"
msg Tsession = "typ[1,val=52] tag[tag,val=0xFFFF]"
msg Rsession = "typ[1,val=53] tag[tag,val=0xFFFF]"
#msg Terror = "typ[1,val=54] illegal"
-msg Rerror = "typ[1,val=55] tag[tag] ename[errstr]"
+msg Rerror = "typ[1,val=55] tag[tag] errstr[errstr]"
msg Tflush = "typ[1,val=56] tag[tag] oldtag[tag]"
msg Rflush = "typ[1,val=57] tag[tag]"
msg Tattach = "typ[1,val=58] tag[tag] fid[fid] uid[name] aname[name] auth[auth_ticket] 13*(pad[1])" # Pad to allow auth_tickets up to 28 bytes.
diff --git a/lib9p/idl/1996-Styx.9p.wip b/lib9p/idl/1996-Styx.9p.wip
index 3cb3774..143be83 100644
--- a/lib9p/idl/1996-Styx.9p.wip
+++ b/lib9p/idl/1996-Styx.9p.wip
@@ -28,7 +28,7 @@ from ./1992-9P1.9p import tag, fid, qid, name, errstr, o, ch, stat
msg Tnop = "typ[1,val=0] tag[tag,val=0xFFFF]"
msg Rnop = "typ[1,val=1] tag[tag,val=0xFFFF]"
#msg Terror = "typ[1,val=2] illegal"
-msg Rerror = "typ[1,val=3] tag[tag] ename[errstr]"
+msg Rerror = "typ[1,val=3] tag[tag] errstr[errstr]"
msg Tflush = "typ[1,val=4] tag[tag] oldtag[tag]"
msg Rflush = "typ[1,val=5] tag[tag]"
msg Tclone = "typ[1,val=6] tag[tag] fid[fid] newfid[fid]"
diff --git a/lib9p/idl/2002-9P2000.9p b/lib9p/idl/2002-9P2000.9p
index 2b51612..13393c6 100644
--- a/lib9p/idl/2002-9P2000.9p
+++ b/lib9p/idl/2002-9P2000.9p
@@ -137,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])"
diff --git a/lib9p/idl/2003-9P2000.p9p.9p b/lib9p/idl/2003-9P2000.p9p.9p
index 3f6a524..1d1c307 100644
--- a/lib9p/idl/2003-9P2000.p9p.9p
+++ b/lib9p/idl/2003-9P2000.p9p.9p
@@ -27,7 +27,7 @@ from ./2002-9P2000.9p import *
# e.g. you replace syscall:`open()` with lib9pclient:`fsopen()`).
#
# "Unfortunately", programs in plan9port must deal both with 9P files
-# and native "Unix" files; and need to turn an 9P FID into a native
+# and native "Unix" files; and need to turn a 9P FID into a native
# file descriptor. To do this, the `9pserve` program and lib9pclient
# add an extension call to 9P2000: Topenfd/Ropenfd/fsopenfd().
#
diff --git a/lib9p/idl/2005-9P2000.u.9p b/lib9p/idl/2005-9P2000.u.9p
index 6c2f2dc..1d630f9 100644
--- a/lib9p/idl/2005-9P2000.u.9p
+++ b/lib9p/idl/2005-9P2000.u.9p
@@ -25,7 +25,7 @@ struct stat += "file_extension[s]"
msg Tauth += "n_uid[nuid]"
msg Tattach += "n_uid[nuid]"
-msg Rerror += "errno[errno]"
+msg Rerror += "errnum[errno]"
bitfield dm += "bit 23=DEVICE"
"bit 21=PIPE"
diff --git a/lib9p/idl/2010-9P2000.L.9p b/lib9p/idl/2010-9P2000.L.9p
index d81a15b..5eb7d5c 100644
--- a/lib9p/idl/2010-9P2000.L.9p
+++ b/lib9p/idl/2010-9P2000.L.9p
@@ -1,3 +1,6 @@
+# lib9p/idl/2010-9P2000.L.9p - Generated by `lib9p/idl/2010-9P2000.L.9p.gen 3rd-party/linux-errno.txt`. DO NOT EDIT!
+# 3rd-party/linux-errno.txt - Generated from lib9p/linux-errno.txt.gen and linux.git v6.14. DO NOT EDIT!
+
# lib9p/idl/2010-9P2000.L.9p - Definitions of 9P2000.L messages
#
# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
@@ -8,12 +11,149 @@
# https://github.com/chaos/diod/blob/master/src/libnpfs/protocol.h
version "9P2000.L"
+# low-level types ##############################################################
+
from ./2002-9P2000.9p import tag, fid, s, qt, qid
-from ./2002-9P2000.9p import Rerror
-from ./2002-9P2000.9p import Tversion, Rversion, Tflush, Rflush, Twalk, Rwalk, Tread, Rread, Twrite, Rwrite, Tclunk, Rclunk, Tremove, Rremove
-from ./2005-9P2000.u.9p import nuid, errno, Tauth, Rauth, Tattach, Rattach
+from ./2005-9P2000.u.9p import nuid, errno
-#num errno += # TODO
+# BUG: The definitions of errno are not defined in the 9P2000.L
+# protocol spec, and Linux kernel errno values vary by architecture.
+# Most architectures share a "generic" list, but a handful (as of
+# Linux v6.14, Alpha, MIPS, PA-RISC, PowerPC, and SPARC) have their
+# own numbers. This IDL file lists the generic numbers.
+#
+# https://github.com/chaos/diod/issues/35
+num errno += "L_EPERM = 1" # Operation not permitted
+ "L_ENOENT = 2" # No such file or directory
+ "L_ESRCH = 3" # No such process
+ "L_EINTR = 4" # Interrupted system call
+ "L_EIO = 5" # I/O error
+ "L_ENXIO = 6" # No such device or address
+ "L_E2BIG = 7" # Argument list too long
+ "L_ENOEXEC = 8" # Exec format error
+ "L_EBADF = 9" # Bad file number
+ "L_ECHILD = 10" # No child processes
+ "L_EAGAIN = 11" # Try again
+ "L_ENOMEM = 12" # Out of memory
+ "L_EACCES = 13" # Permission denied
+ "L_EFAULT = 14" # Bad address
+ "L_ENOTBLK = 15" # Block device required
+ "L_EBUSY = 16" # Device or resource busy
+ "L_EEXIST = 17" # File exists
+ "L_EXDEV = 18" # Cross-device link
+ "L_ENODEV = 19" # No such device
+ "L_ENOTDIR = 20" # Not a directory
+ "L_EISDIR = 21" # Is a directory
+ "L_EINVAL = 22" # Invalid argument
+ "L_ENFILE = 23" # File table overflow
+ "L_EMFILE = 24" # Too many open files
+ "L_ENOTTY = 25" # Not a typewriter
+ "L_ETXTBSY = 26" # Text file busy
+ "L_EFBIG = 27" # File too large
+ "L_ENOSPC = 28" # No space left on device
+ "L_ESPIPE = 29" # Illegal seek
+ "L_EROFS = 30" # Read-only file system
+ "L_EMLINK = 31" # Too many links
+ "L_EPIPE = 32" # Broken pipe
+ "L_EDOM = 33" # Math argument out of domain of func
+ "L_ERANGE = 34" # Math result not representable
+ "L_EDEADLK = 35" # Resource deadlock would occur
+ "L_ENAMETOOLONG = 36" # File name too long
+ "L_ENOLCK = 37" # No record locks available
+ "L_ENOSYS = 38" # Invalid system call number
+ "L_ENOTEMPTY = 39" # Directory not empty
+ "L_ELOOP = 40" # Too many symbolic links encountered
+ "L_ENOMSG = 42" # No message of desired type
+ "L_EIDRM = 43" # Identifier removed
+ "L_ECHRNG = 44" # Channel number out of range
+ "L_EL2NSYNC = 45" # Level 2 not synchronized
+ "L_EL3HLT = 46" # Level 3 halted
+ "L_EL3RST = 47" # Level 3 reset
+ "L_ELNRNG = 48" # Link number out of range
+ "L_EUNATCH = 49" # Protocol driver not attached
+ "L_ENOCSI = 50" # No CSI structure available
+ "L_EL2HLT = 51" # Level 2 halted
+ "L_EBADE = 52" # Invalid exchange
+ "L_EBADR = 53" # Invalid request descriptor
+ "L_EXFULL = 54" # Exchange full
+ "L_ENOANO = 55" # No anode
+ "L_EBADRQC = 56" # Invalid request code
+ "L_EBADSLT = 57" # Invalid slot
+ "L_EBFONT = 59" # Bad font file format
+ "L_ENOSTR = 60" # Device not a stream
+ "L_ENODATA = 61" # No data available
+ "L_ETIME = 62" # Timer expired
+ "L_ENOSR = 63" # Out of streams resources
+ "L_ENONET = 64" # Machine is not on the network
+ "L_ENOPKG = 65" # Package not installed
+ "L_EREMOTE = 66" # Object is remote
+ "L_ENOLINK = 67" # Link has been severed
+ "L_EADV = 68" # Advertise error
+ "L_ESRMNT = 69" # Srmount error
+ "L_ECOMM = 70" # Communication error on send
+ "L_EPROTO = 71" # Protocol error
+ "L_EMULTIHOP = 72" # Multihop attempted
+ "L_EDOTDOT = 73" # RFS specific error
+ "L_EBADMSG = 74" # Not a data message
+ "L_EOVERFLOW = 75" # Value too large for defined data type
+ "L_ENOTUNIQ = 76" # Name not unique on network
+ "L_EBADFD = 77" # File descriptor in bad state
+ "L_EREMCHG = 78" # Remote address changed
+ "L_ELIBACC = 79" # Can not access a needed shared library
+ "L_ELIBBAD = 80" # Accessing a corrupted shared library
+ "L_ELIBSCN = 81" # .lib section in a.out corrupted
+ "L_ELIBMAX = 82" # Attempting to link in too many shared libraries
+ "L_ELIBEXEC = 83" # Cannot exec a shared library directly
+ "L_EILSEQ = 84" # Illegal byte sequence
+ "L_ERESTART = 85" # Interrupted system call should be restarted
+ "L_ESTRPIPE = 86" # Streams pipe error
+ "L_EUSERS = 87" # Too many users
+ "L_ENOTSOCK = 88" # Socket operation on non-socket
+ "L_EDESTADDRREQ = 89" # Destination address required
+ "L_EMSGSIZE = 90" # Message too long
+ "L_EPROTOTYPE = 91" # Protocol wrong type for socket
+ "L_ENOPROTOOPT = 92" # Protocol not available
+ "L_EPROTONOSUPPORT = 93" # Protocol not supported
+ "L_ESOCKTNOSUPPORT = 94" # Socket type not supported
+ "L_EOPNOTSUPP = 95" # Operation not supported on transport endpoint
+ "L_EPFNOSUPPORT = 96" # Protocol family not supported
+ "L_EAFNOSUPPORT = 97" # Address family not supported by protocol
+ "L_EADDRINUSE = 98" # Address already in use
+ "L_EADDRNOTAVAIL = 99" # Cannot assign requested address
+ "L_ENETDOWN = 100" # Network is down
+ "L_ENETUNREACH = 101" # Network is unreachable
+ "L_ENETRESET = 102" # Network dropped connection because of reset
+ "L_ECONNABORTED = 103" # Software caused connection abort
+ "L_ECONNRESET = 104" # Connection reset by peer
+ "L_ENOBUFS = 105" # No buffer space available
+ "L_EISCONN = 106" # Transport endpoint is already connected
+ "L_ENOTCONN = 107" # Transport endpoint is not connected
+ "L_ESHUTDOWN = 108" # Cannot send after transport endpoint shutdown
+ "L_ETOOMANYREFS = 109" # Too many references: cannot splice
+ "L_ETIMEDOUT = 110" # Connection timed out
+ "L_ECONNREFUSED = 111" # Connection refused
+ "L_EHOSTDOWN = 112" # Host is down
+ "L_EHOSTUNREACH = 113" # No route to host
+ "L_EALREADY = 114" # Operation already in progress
+ "L_EINPROGRESS = 115" # Operation now in progress
+ "L_ESTALE = 116" # Stale file handle
+ "L_EUCLEAN = 117" # Structure needs cleaning
+ "L_ENOTNAM = 118" # Not a XENIX named type file
+ "L_ENAVAIL = 119" # No XENIX semaphores available
+ "L_EISNAM = 120" # Is a named type file
+ "L_EREMOTEIO = 121" # Remote I/O error
+ "L_EDQUOT = 122" # Quota exceeded
+ "L_ENOMEDIUM = 123" # No medium found
+ "L_EMEDIUMTYPE = 124" # Wrong medium type
+ "L_ECANCELED = 125" # Operation Canceled
+ "L_ENOKEY = 126" # Required key not available
+ "L_EKEYEXPIRED = 127" # Key has expired
+ "L_EKEYREVOKED = 128" # Key has been revoked
+ "L_EKEYREJECTED = 129" # Key was rejected by service
+ "L_EOWNERDEAD = 130" # Owner died
+ "L_ENOTRECOVERABLE = 131" # State not recoverable
+ "L_ERFKILL = 132" # Operation not possible due to RF-kill
+ "L_EHWPOISON = 133" # Memory page has hardware error
num super_magic = 4
# See <linux/magic.h> (linux.git include/uapi/linux/magic.h).
@@ -168,8 +308,23 @@ num lock_status = 1
"ERROR=2"
"GRACE=3"
+# 9P2000 Operations (.L subset) ################################################
+
+from ./2002-9P2000.9p import Tversion, Rversion
+from ./2002-9P2000.9p import Tflush, Rflush
+from ./2002-9P2000.9p import Twalk, Rwalk
+from ./2002-9P2000.9p import Tread, Rread, Twrite, Rwrite
+from ./2002-9P2000.9p import Tclunk, Rclunk
+from ./2002-9P2000.9p import Tremove, Rremove
+
+# 9P2000.u Operations (.L subset) ##############################################
+
+from ./2005-9P2000.u.9p import Tattach, Rattach, Tauth, Rauth
+
+# 9P2000.L Operations ##########################################################
+
#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[errno]" # analogous to 107/Rerror
+msg Rlerror = "size[4,val=end-&size] typ[1,val=7] tag[tag] errnum[errno]" # analogous to 107/Rerror
msg Tstatfs = "size[4,val=end-&size] typ[1,val=8] tag[tag] fid[fid]"
msg Rstatfs = "size[4,val=end-&size] typ[1,val=9] tag[tag]" # Description | statfs | statvfs
"type[super_magic]" # Type of filesystem | f_type | -
diff --git a/lib9p/idl/2010-9P2000.L.9p.gen b/lib9p/idl/2010-9P2000.L.9p.gen
new file mode 100755
index 0000000..cb32585
--- /dev/null
+++ b/lib9p/idl/2010-9P2000.L.9p.gen
@@ -0,0 +1,282 @@
+#!/usr/bin/env python
+# lib9p/idl/2010-9P2000.L.9p.gen - Generate definitions of 9P2000.L messages
+import sys
+
+print(
+ f"# lib9p/idl/2010-9P2000.L.9p - Generated by `{' '.join(sys.argv)}`. DO NOT EDIT!"
+)
+errnos: dict[str, tuple[int, str]] = {}
+with open(sys.argv[1], "r", encoding="utf-8") as fh:
+ for line in fh:
+ if line.startswith("#"):
+ print(line)
+ continue
+ _num, _name, _desc = line.split(maxsplit=2)
+ errnos[_name] = (int(_num), _desc.strip())
+print(
+ """
+# lib9p/idl/2010-9P2000.L.9p - Definitions of 9P2000.L messages
+#
+# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+# "9P2000.L" Linux extension
+# https://github.com/chaos/diod/blob/master/protocol.md
+# https://github.com/chaos/diod/blob/master/src/libnpfs/protocol.h
+version "9P2000.L"
+
+# low-level types ##############################################################
+
+from ./2002-9P2000.9p import tag, fid, s, qt, qid
+from ./2005-9P2000.u.9p import nuid, errno
+
+# BUG: The definitions of errno are not defined in the 9P2000.L
+# protocol spec, and Linux kernel errno values vary by architecture.
+# Most architectures share a "generic" list, but a handful (as of
+# Linux v6.14, Alpha, MIPS, PA-RISC, PowerPC, and SPARC) have their
+# own numbers. This IDL file lists the generic numbers.
+#
+# https://github.com/chaos/diod/issues/35
+""".strip()
+)
+
+prefix = "num errno += "
+namelen = max(len(name) for name in errnos)
+numlen = max(len(str(num)) for (num, desc) in errnos.values())
+for name, (num, desc) in errnos.items():
+ print(f'{prefix}"L_{name:<{namelen}} = {num:>{numlen}}" # {desc}')
+ prefix = " " * len(prefix)
+print()
+
+print(
+ """
+num super_magic = 4
+ # See <linux/magic.h> (linux.git include/uapi/linux/magic.h).
+ #
+ # To quote `util-linux.git:include/statfs_magic.h`:
+ # "Unfortunately, Linux kernel header file <linux/magic.h> is
+ # incomplete mess and kernel returns by statfs f_type many numbers
+ # that are nowhere specified (in API)."
+ #
+ # util-linux <statfs_magic.h> is also incomplete. As is the
+ # statfs(2) man-page.
+ #
+ # I'm working on a patchset to the kernel to get <linux/magic.h>
+ # to be complete, but in the mean-time I'm just not going to
+ # bother with putting a list here.
+ #
+ # TODO
+ "V9FS_MAGIC=0x01021997"
+
+# "L"inux "O"pen flags (flags to pass to Tlopen and Tlcreate)
+#
+# The values are not specified in in protocol.md, but are specified in
+# protocol.h (and are different than the Linux kernel's values, which
+# vary by architecture).
+bitfield lo = 4
+ "bit 0=num(MODE)" # low bit of the 2-bit RDONLY/WRONLY/RDWR/NOACCESS enum
+ "bit 1=num(MODE)" # high bit of the 2-bit RDONLY/WRONLY/RDWR/NOACCESS enum
+ #"bit 2=unused"
+ #"bit 3=unused"
+ #"bit 4=unused"
+ #"bit 5=unused"
+ "bit 6=CREATE"
+ "bit 7=EXCL"
+ "bit 8=NOCTTY"
+ "bit 9=TRUNC"
+ "bit 10=APPEND"
+ "bit 11=NONBLOCK"
+ "bit 12=DSYNC"
+ "bit 13=BSD_FASYNC"
+ "bit 14=DIRECT"
+ "bit 15=LARGEFILE"
+ "bit 16=DIRECTORY"
+ "bit 17=NOFOLLOW"
+ "bit 18=NOATIME"
+ "bit 19=CLOEXEC"
+ "bit 20=SYNC"
+
+ "num(MODE) RDONLY = 0"
+ "num(MODE) WRONLY = 1"
+ "num(MODE) RDWR = 2"
+ "num(MODE) NOACCESS = 3"
+
+ "mask FLAG = 0b111111111111111000000"
+
+# "D"irentry "T"ype
+#
+# These match the Linux kernel's values.
+num dt = 1
+ "UNKNOWN = 0"
+ "PIPE = 1"
+ "CHAR_DEV = 2"
+ "DIRECTORY = 4"
+ "BLOCK_DEV = 6" # proof it's not a bitfield
+ "REGULAR = 8"
+ "SYMLINK = 10" # proof it's not a bitfield
+ "SOCKET = 12" # proof it's not a bitfield
+ "_WHITEOUT = 14" # proof it's not a bitfield
+
+# Mode
+#
+# These match the Linux kernel's values. Why is this 32-bits wide
+# instead of just 16? Who knows?
+bitfield mode = 4
+ #...
+ "bit 15=num(FMT)" # bit of the 4-bit FMT_ enum
+ "bit 14=num(FMT)" # bit of the 4-bit FMT_ enum
+ "bit 13=num(FMT)" # bit of the 4-bit FMT_ enum
+ "bit 12=num(FMT)" # bit of the 4-bit FMT_ enum
+ #...
+ "bit 11=PERM_SETGROUP"
+ "bit 10=PERM_SETUSER"
+ "bit 9=PERM_STICKY"
+ "bit 8=PERM_OWNER_R"
+ "bit 7=PERM_OWNER_W"
+ "bit 6=PERM_OWNER_X"
+ "bit 5=PERM_GROUP_R"
+ "bit 4=PERM_GROUP_W"
+ "bit 3=PERM_GROUP_X"
+ "bit 2=PERM_OTHER_R"
+ "bit 1=PERM_OTHER_W"
+ "bit 0=PERM_OTHER_X"
+
+ "num(FMT) PIPE = dt.PIPE<<12"
+ "num(FMT) CHAR_DEV = dt.CHAR_DEV<<12"
+ "num(FMT) DIRECTORY = dt.DIRECTORY<<12"
+ "num(FMT) BLOCK_DEV = dt.BLOCK_DEV<<12"
+ "num(FMT) REGULAR = dt.REGULAR<<12"
+ "num(FMT) SYMLINK = dt.SYMLINK<<12"
+ "num(FMT) SOCKET = dt.SOCKET<<12"
+
+ "mask PERM = 07777" # PERM_*
+
+# A boolean value that is for some reason 4 bytes wide.
+num b4 = 4
+ "FALSE=0"
+ "TRUE=1"
+ # all other values are true also
+
+bitfield getattr = 8
+ "bit 0=MODE"
+ "bit 1=NLINK"
+ "bit 2=UID"
+ "bit 3=GID"
+ "bit 4=RDEV"
+ "bit 5=ATIME"
+ "bit 6=MTIME"
+ "bit 7=CTIME"
+ "bit 8=INO"
+ "bit 9=SIZE"
+ "bit 10=BLOCKS"
+
+ "bit 11=BTIME"
+ "bit 12=GEN"
+ "bit 13=DATA_VERSION"
+
+ "alias BASIC=0x000007ff" # Mask for fields up to BLOCKS
+ "alias ALL =0x00003fff" # Mask for All fields above
+
+bitfield setattr = 4
+ "bit 0=MODE"
+ "bit 1=UID"
+ "bit 2=GID"
+ "bit 3=SIZE"
+ "bit 4=ATIME"
+ "bit 5=MTIME"
+ "bit 6=CTIME"
+ "bit 7=ATIME_SET"
+ "bit 8=MTIME_SET"
+
+num lock_type = 1
+ "RDLCK=0"
+ "WRLCK=1"
+ "UNLCK=2"
+
+bitfield lock_flags = 4
+ "bit 0=BLOCK"
+ "bit 1=RECLAIM"
+
+num lock_status = 1
+ "SUCCESS=0"
+ "BLOCKED=1"
+ "ERROR=2"
+ "GRACE=3"
+
+# 9P2000 Operations (.L subset) ################################################
+
+from ./2002-9P2000.9p import Tversion, Rversion
+from ./2002-9P2000.9p import Tflush, Rflush
+from ./2002-9P2000.9p import Twalk, Rwalk
+from ./2002-9P2000.9p import Tread, Rread, Twrite, Rwrite
+from ./2002-9P2000.9p import Tclunk, Rclunk
+from ./2002-9P2000.9p import Tremove, Rremove
+
+# 9P2000.u Operations (.L subset) ##############################################
+
+from ./2005-9P2000.u.9p import Tattach, Rattach, Tauth, Rauth
+
+# 9P2000.L Operations ##########################################################
+
+#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] errnum[errno]" # analogous to 107/Rerror
+msg Tstatfs = "size[4,val=end-&size] typ[1,val=8] tag[tag] fid[fid]"
+msg Rstatfs = "size[4,val=end-&size] typ[1,val=9] tag[tag]" # Description | statfs | statvfs
+ "type[super_magic]" # Type of filesystem | f_type | -
+ "bsize[4]" # Block size in bytes | f_bsize | f_bsize
+ # - # Fragment size in bytes | f_frsize (since Linux 2.6) | f_frsize
+ "blocks[8]" # Size of FS in f_frsize units | f_blocks | f_blocks
+ "bfree[8]" # Number of free blocks | f_bfree | f_bfree
+ "bavail[8]" # Number of free blocks for unprivileged users | f_bavail | b_avail
+ "files[8]" # Number of inodes | f_files | f_files
+ "ffree[8]" # Number of free inodes | f_ffree | f_ffree
+ # - # Number of free inodes for unprivileged users | - | f_favail
+ "fsid[8]" # Filesystem instance ID | f_fsid | f_fsid
+ # - # Mount flags | f_flags (since Linux 2.6.36) | f_flag
+ "namelen[4]" # Maximum filename length | f_namemax | f_namemax
+msg Tlopen = "size[4,val=end-&size] typ[1,val=12] tag[tag] fid[fid] flags[lo]" # analogous to 112/Topen
+msg Rlopen = "size[4,val=end-&size] typ[1,val=13] tag[tag] qid[qid] iounit[4]" # analogous to 113/Ropen
+msg Tlcreate = "size[4,val=end-&size] typ[1,val=14] tag[tag] fid[fid] name[s] flags[lo] mode[mode] gid[nuid]" # analogous to 114/Tcreate
+msg Rlcreate = "size[4,val=end-&size] typ[1,val=15] tag[tag] qid[qid] iounit[4]" # analogous to 115/Rcreate
+msg Tsymlink = "size[4,val=end-&size] typ[1,val=16] tag[tag] fid[fid] name[s] symtgt[s] gid[nuid]"
+msg Rsymlink = "size[4,val=end-&size] typ[1,val=17] tag[tag] qid[qid]"
+msg Tmknod = "size[4,val=end-&size] typ[1,val=18] tag[tag] dfid[fid] name[s] mode[mode] major[4] minor[4] gid[nuid]"
+msg Rmknod = "size[4,val=end-&size] typ[1,val=19] tag[tag] qid[qid]"
+msg Trename = "size[4,val=end-&size] typ[1,val=20] tag[tag] fid[fid] dfid[fid] name[s]"
+msg Rrename = "size[4,val=end-&size] typ[1,val=21] tag[tag]"
+msg Treadlink = "size[4,val=end-&size] typ[1,val=22] tag[tag] fid[fid]"
+msg Rreadlink = "size[4,val=end-&size] typ[1,val=23] tag[tag] target[s]"
+msg Tgetattr = "size[4,val=end-&size] typ[1,val=24] tag[tag] fid[fid] request_mask[getattr]"
+msg Rgetattr = "size[4,val=end-&size] typ[1,val=25] tag[tag] valid[getattr] qid[qid] mode[mode] uid[nuid] gid[nuid] nlink[8]"
+ "rdev[8] filesize[8] blksize[8] blocks[8]"
+ "atime_sec[8] atime_nsec[8] mtime_sec[8] mtime_nsec[8]"
+ "ctime_sec[8] ctime_nsec[8] btime_sec[8] btime_nsec[8]"
+ "gen[8] data_version[8]"
+msg Tsetattr = "size[4,val=end-&size] typ[1,val=26] tag[tag] fid[fid] valid[setattr] mode[mode] uid[nuid] gid[nuid] filesize[8] atime_sec[8] atime_nsec[8] mtime_sec[8] mtime_nsec[8]"
+msg Rsetattr = "size[4,val=end-&size] typ[1,val=27] tag[tag]"
+#...
+msg Txattrwalk = "size[4,val=end-&size] typ[1,val=30] tag[tag] fid[fid] newfid[fid] name[s]"
+msg Rxattrwalk = "size[4,val=end-&size] typ[1,val=31] tag[tag] attr_size[8]"
+msg Txattrcreate = "size[4,val=end-&size] typ[1,val=32] tag[tag] fid[fid] name[s] attr_size[8] flags[4]"
+msg Rxattrcreate = "size[4,val=end-&size] typ[1,val=33] tag[tag]"
+#...
+msg Treaddir = "size[4,val=end-&size] typ[1,val=40] tag[tag] fid[fid] offset[8] count[4]"
+msg Rreaddir = "size[4,val=end-&size] typ[1,val=41] tag[tag] count[4] count*(data[1])" # data is "qid[qid] offset[8] type[dt] name[s]"
+#...
+msg Tfsync = "size[4,val=end-&size] typ[1,val=50] tag[tag] fid[fid] datasync[b4]"
+msg Rfsync = "size[4,val=end-&size] typ[1,val=51] tag[tag]"
+msg Tlock = "size[4,val=end-&size] typ[1,val=52] tag[tag] fid[fid] type[lock_type] flags[lock_flags] start[8] length[8] proc_id[4] client_id[s]"
+msg Rlock = "size[4,val=end-&size] typ[1,val=53] tag[tag] status[lock_status]"
+msg Tgetlock = "size[4,val=end-&size] typ[1,val=54] tag[tag] fid[fid] type[lock_type] start[8] length[8] proc_id[4] client_id[s]"
+msg Rgetlock = "size[4,val=end-&size] typ[1,val=55] tag[tag] type[lock_type] start[8] length[8] proc_id[4] client_id[s]"
+# ...
+msg Tlink = "size[4,val=end-&size] typ[1,val=70] tag[tag] dfid[fid] fid[fid] name[s]"
+msg Rlink = "size[4,val=end-&size] typ[1,val=71] tag[tag]"
+msg Tmkdir = "size[4,val=end-&size] typ[1,val=72] tag[tag] dfid[fid] name[s] mode[mode] gid[nuid]"
+msg Rmkdir = "size[4,val=end-&size] typ[1,val=73] tag[tag] qid[qid]"
+msg Trenameat = "size[4,val=end-&size] typ[1,val=74] tag[tag] olddirfid[fid] oldname[s] newdirfid[fid] newname[s]"
+msg Rrenameat = "size[4,val=end-&size] typ[1,val=75] tag[tag]"
+msg Tunlinkat = "size[4,val=end-&size] typ[1,val=76] tag[tag] dirfd[fid] name[s] flags[4]"
+msg Runlinkat = "size[4,val=end-&size] typ[1,val=77] tag[tag]"
+""".strip()
+)
diff --git a/lib9p/idl/__init__.py b/lib9p/idl/__init__.py
index 2d09217..3133cc4 100644
--- a/lib9p/idl/__init__.py
+++ b/lib9p/idl/__init__.py
@@ -647,17 +647,16 @@ def re_string(grpname: str) -> str:
re_line_version = f"version\\s+{re_string('version')}"
re_line_import = f"from\\s+(?P<file>\\S+)\\s+import\\s+(?P<syms>{re_impname}(?:\\s*,\\s*{re_impname})*)"
re_line_num = f"num\\s+(?P<name>{re_symname})\\s*=\\s*(?P<prim>{re_priname})"
+re_line_num_ = f"num\\s+(?P<name>{re_symname})\\s*\\+=\\s*{re_string('spec')}"
re_line_bitfield = f"bitfield\\s+(?P<name>{re_symname})\\s*=\\s*(?P<prim>{re_priname})"
-re_line_bitfield_ = (
- f"bitfield\\s+(?P<name>{re_symname})\\s*\\+=\\s*{re_string('member')}"
-)
+re_line_bitfield_ = f"bitfield\\s+(?P<name>{re_symname})\\s*\\+=\\s*{re_string('spec')}"
re_line_struct = (
f"struct\\s+(?P<name>{re_symname})\\s*(?P<op>\\+?=)\\s*{re_string('members')}"
)
re_line_msg = (
f"msg\\s+(?P<name>{re_msgname})\\s*(?P<op>\\+?=)\\s*{re_string('members')}"
)
-re_line_cont = f"\\s+{re_string('specs')}" # could be bitfield/struct/msg
+re_line_cont = f"\\s+{re_string('spec')}" # could be bitfield/struct/msg
def parse_file(
@@ -741,6 +740,11 @@ def parse_file(
raise ValueError(f"duplicate type name {num.typname!r}")
env[num.typname] = num
prev = num
+ elif m := re.fullmatch(re_line_num_, line):
+ num = get_type(env, m.group("name"), Number)
+ parse_numspec(env, version, num, m.group("spec"))
+
+ prev = num
elif m := re.fullmatch(re_line_bitfield, line):
prim = env[m.group("prim")]
assert isinstance(prim, Primitive)
@@ -754,7 +758,7 @@ def parse_file(
prev = bf
elif m := re.fullmatch(re_line_bitfield_, line):
bf = get_type(env, m.group("name"), Bitfield)
- parse_bitspec(env, version, bf, m.group("member"))
+ parse_bitspec(env, version, bf, m.group("spec"))
prev = bf
elif m := re.fullmatch(re_line_struct, line):
@@ -798,11 +802,11 @@ def parse_file(
elif m := re.fullmatch(re_line_cont, line):
match prev:
case Bitfield():
- parse_bitspec(env, version, prev, m.group("specs"))
+ parse_bitspec(env, version, prev, m.group("spec"))
case Number():
- parse_numspec(env, version, prev, m.group("specs"))
+ parse_numspec(env, version, prev, m.group("spec"))
case Struct(): # and Message()
- parse_members(version, env, prev, m.group("specs"))
+ parse_members(version, env, prev, m.group("spec"))
case _:
raise SyntaxError(
"continuation line must come after a bitfield, struct, or msg line"