summaryrefslogtreecommitdiff
path: root/9p
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-26 19:36:54 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-26 19:36:54 -0600
commit71e1a86a033c380f85dd300d788af63bfef25bab (patch)
tree07aa53d5a933ba51535a78972edbfe0cd95a31c5 /9p
parentf5da707e77ee954b12f3c961012e4f40fa4e1bd3 (diff)
wip reorg
Diffstat (limited to '9p')
-rw-r--r--9p/.editorconfig3
-rw-r--r--9p/.gitignore2
-rw-r--r--9p/9P2000.L.txt56
-rw-r--r--9p/9P2000.e.txt16
-rw-r--r--9p/9P2000.txt82
-rw-r--r--9p/9P2000.u.txt20
-rw-r--r--9p/9p.h15
-rw-r--r--9p/defs.c89
-rwxr-xr-x9p/defs.gen456
-rw-r--r--9p/defs.h74
-rw-r--r--9p/internal.h139
-rwxr-xr-x9p/linux-errno.h.gen34
-rw-r--r--9p/misc.txt24
-rw-r--r--9p/srv.c194
-rw-r--r--9p/srv.h16
15 files changed, 0 insertions, 1220 deletions
diff --git a/9p/.editorconfig b/9p/.editorconfig
deleted file mode 100644
index 3f04564..0000000
--- a/9p/.editorconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-[{defs.gen,linux-errno.h.gen}]
-indent_style = space
-indent_size = 4
diff --git a/9p/.gitignore b/9p/.gitignore
deleted file mode 100644
index 667e81c..0000000
--- a/9p/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/defs-*
-/linux-errno.h
diff --git a/9p/9P2000.L.txt b/9p/9P2000.L.txt
deleted file mode 100644
index 71ab171..0000000
--- a/9p/9P2000.L.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-# 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 9P2000.txt import *
-from 9P2000.u.txt import Tauth, Tattach
-
-#6/Tlerror = "illegal" # analogous to 106/Terror
-7/Rlerror = "ecode[4]" # analogous to 107/Rerror
-8/Tstatfs = "TODO"
-9/Rstatfs = "TODO"
-12/Tlopen = "TODO" # analogous to 112/Topen
-13/Rlopen = "TODO" # analogous to 113/Ropen
-14/Tlcreate = "TODO" # analogous to 114/Tcreate
-15/Rlcreate = "TODO" # analogous to 115/Rcreate
-16/Tsymlink = "TODO"
-17/Rsymlink = "TODO"
-18/Tmknod = "TODO"
-19/Rmknod = "TODO"
-20/Trename = "TODO"
-21/Rrename = "TODO"
-22/Treadlink = "TODO"
-23/Rreadlink = "TODO"
-24/Tgetattr = "TODO"
-25/Rgetattr = "TODO"
-26/Tsetattr = "TODO"
-27/Rsetattr = "TODO"
-#...
-30/Txattrwalk = "TODO"
-31/Rxattrwalk = "TODO"
-32/Txattrcreate = "TODO"
-33/Rxattrcreate = "TODO"
-#...
-40/Treaddir = "TODO"
-41/Rreaddir = "TODO"
-#...
-50/Tfsync = "TODO"
-51/Rfsync = "TODO"
-52/Tlock = "TODO"
-53/Rlock = "TODO"
-54/Tgetlock = "TODO"
-55/Rgetlock = "TODO"
-# ...
-70/Tlink = "TODO"
-71/Rlink = "TODO"
-72/Tmkdir = "TODO"
-73/Tmkdir = "TODO"
-74/Trenameat = "TODO"
-75/Rrenameat = "TODO"
-76/Tunlinkat = "TODO"
-77/Runlinkat = "TODO"
diff --git a/9p/9P2000.e.txt b/9p/9P2000.e.txt
deleted file mode 100644
index 22f056e..0000000
--- a/9p/9P2000.e.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-# 9P2000e.e.txt - 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"
-
-150/Tsession = "key[8]"
-151/Rsession = ""
-152/Tsread = "fid[4] nwname[2] nwname*(wname[s])"
-153/Rsread = "data[d]"
-154/Tswrite = "Tswrite tag[2] fid[4] nwname[2] nwname*(wname[s]) data[d]"
-155/Rswrite = "count[4]"
diff --git a/9p/9P2000.txt b/9p/9P2000.txt
deleted file mode 100644
index 5f93cdf..0000000
--- a/9p/9P2000.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-# 9P2000.txt - Definitions of 9P2000 messages
-#
-# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
-# SPDX-Licence-Identifier: AGPL-3.0-or-later
-
-# The format of each message (excluding the "size[4] msg_type[1]
-# tag[2]" header) is written here as a sequence of
-# "member_name[member_type]" struct members.
-#
-# The primitive member types types are the following single-character
-# mnemonics:
-#
-# - 1 = u8
-# - 2 = u16le
-# - 4 = u32le
-# - 8 = u16le
-
-# "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 a better
-# references.
-version "9P2000"
-
-# data (u32le `n`, then `n` bytes of data)
-d = "len[4] len*(dat[1])"
-
-# string (u16le `n`, then `n` bytes of UTF-8)
-s = "len[2] len*(utf8[1])"
-
-# qid (TODO)
-qid = "type[1] vers[4] path[8]"
-
-# stat (TODO)
-stat = "stat_size[2]"
- "kern_type[2]"
- "kern_dev[4]"
- "file_qid[qid]"
- "file_mode[4]"
- "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]"
-
-# 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 (I do not know what the Plan 9 designers intended "T" and
-# "R" to stand for). The type of a message is represented by a u8 ID.
-100/Tversion = "max_msg_size[4] version[s]"
-101/Rversion = "max_msg_size[4] version[s]"
-102/Tauth = "afid[4] uname[s] aname[s]"
-103/Rauth = "aqid[qid]"
-104/Tattach = "fid[4] afid[4] uname[s] aname[s]"
-105/Rattach = "qid[qid]"
-#106/Terror = "illegal"
-107/Rerror = "ename[s]"
-108/Tflush = "oldtag[2]"
-109/Rflush = ""
-110/Twalk = "fid[4] newfid[4] nwname[2] nwname*(wname[s])"
-111/Rwalk = "nwqid[2] nwqid*(wqid[qid])"
-112/Topen = "fid[4] mode[1]"
-113/Ropen = "qid[qid] iounit[4]"
-114/Tcreate = "fid[4] name[s] perm[4] mode[1]"
-115/Rcreate = "qid[qid] iounit[4]"
-116/Tread = "fid[4] offset[8] count[4]"
-117/Rread = "data[d]" # for directories data is the sequence "cnt*(entries[stat])"
-118/Twrite = "fid[4] offset[8] data[d]"
-119/Rwrite = "count[4]"
-120/Tclunk = "fid[4]"
-121/Rclunk = ""
-122/Tremove = "fid[4]"
-123/Rremove = ""
-124/Tstat = "fid[4]"
-125/Rstat = "stat[stat]"
-126/Twstat = "fid[4] stat[stat]"
-127/Rwstat = ""
diff --git a/9p/9P2000.u.txt b/9p/9P2000.u.txt
deleted file mode 100644
index 60d2b11..0000000
--- a/9p/9P2000.u.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-# 9P2000.u.txt - 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 9P2000.txt import *
-
-stat += "file_extension[s]"
- "file_owner_n_uid[4]"
- "file_owner_n_gid[4]"
- "file_last_modified_n_uid[4]"
-
-Tauth += "n_uname[4]"
-
-Rerror += "errno[4]"
diff --git a/9p/9p.h b/9p/9p.h
deleted file mode 100644
index 63fbd04..0000000
--- a/9p/9p.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* 9p/9p.h - TODO
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-Licence-Identifier: AGPL-3.0-or-later
- */
-
-#include "9p/linux-errno.h"
-#include "9p/defs.h"
-#include "9p/defs-9P2000.h"
-/*#include "9p/defs-9P2000.u.h"*/
-
-#define P9_TYPECODE_FOR_CTYPE(msg) _Generic((in_msg) \
- _P9_TYPECODE_FOR_CTYPE_9P2000(msg) \
- /* _P9_TYPECODE_FOR_CTYPE_9P2000u(msg) */ \
- )
diff --git a/9p/defs.c b/9p/defs.c
deleted file mode 100644
index 886a0c1..0000000
--- a/9p/defs.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/* 9p/defs.c - TODO
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-Licence-Identifier: AGPL-3.0-or-later
- */
-
-#include <inttypes.h> /* for PRIu{n} */
-#include <stdarg.h> /* for va_* */
-#include <stdio.h> /* for vsnprintf() */
-#include <string.h> /* for strncpy() */
-
-#include "9p/defs.h"
-#include "9p/linux-errno.h"
-#include "9p/internal.h"
-
-static struct version *versions[_P9_VER_CNT] = {
- [P9_VER_9P2000] = &version_9P2000,
- /* [P9_VER_9P2000u] = &version_9P2000u, */
-};
-
-int p9_error(struct p9_ctx *ctx, uint32_t linux_errno, char const *msg) {
- strncpy(ctx->err_msg, msg, sizeof(ctx->err_msg));
- ctx->err_msg[sizeof(ctx->err_msg)-1] = '\0';
- ctx->err_num = linux_errno;
- return -1;
-}
-
-int p9_errorf(struct p9_ctx *ctx, uint32_t linux_errno, char const *fmt, ...) {
- int n;
- va_list args;
-
- va_start(args, fmt);
- n = vsnprintf(ctx->err_msg, sizeof(ctx->err_msg), fmt, args);
- va_end(args);
- if ((size_t)(n+1) < sizeof(ctx->err_msg))
- memset(&ctx->err_msg[n+1], 0, sizeof(ctx->err_msg)-(n+1));
-
- ctx->err_num = linux_errno;
-
- return -1;
-}
-
-size_t p9_unmarshal_size(struct p9_ctx *ctx, uint8_t *net_bytes) {
- /* Header */
- uint32_t net_len = decode_u32le(net_bytes);
- if (net_len < 7)
- return p9_error(ctx, LINUX_EBADMSG, "message is too short");
- uint8_t typ = net_bytes[4];
- uint32_t net_offset = 7;
-
- /* Body */
- if (!versions[ctx->version]->msgs[typ].unmarshal_extrasize)
- return p9_errorf(ctx, LINUX_EOPNOTSUPP, "unknown message type %"PRIu8, typ);
- size_t host_size = versions[ctx->version]->msgs[typ].unmarshal_basesize;
- if (versions[ctx->version]->msgs[typ].unmarshal_extrasize(net_len, net_bytes, &net_offset, &host_size))
- return p9_error(ctx, LINUX_EBADMSG, "message is too short for content");
-
- return host_size;
-}
-
-uint8_t p9_unmarshal(struct p9_ctx *ctx, uint8_t *net_bytes, uint16_t *out_tag, void *out_body) {
- /* Header */
- uint8_t typ = net_bytes[4];
- *out_tag = decode_u16le(&net_bytes[5]);
- uint32_t net_offset = 7;
-
- /* Body */
- void *host_extra = out_body + versions[ctx->version]->msgs[typ].unmarshal_basesize;
- if (versions[ctx->version]->msgs[typ].unmarshal(net_bytes, &net_offset, &host_extra, out_body))
- return p9_error(ctx, LINUX_EBADMSG, "message contains invalid UTF-8");
-
- return typ;
-}
-
-uint32_t _p9_marshal(struct p9_ctx *ctx, uint8_t typ, uint16_t msgid, void *body, uint8_t *out_bytes) {
- /* Header */
- out_bytes[4] = typ;
- encode_u16le(msgid, &out_bytes[5]);
- uint32_t net_offset = 7;
-
- /* Body */
- if (versions[ctx->version]->msgs[typ].marshal(ctx, body, out_bytes, &net_offset))
- return 0;
-
- /* Header, again */
- encode_u32le(net_offset, out_bytes);
-
- return net_offset;
-}
diff --git a/9p/defs.gen b/9p/defs.gen
deleted file mode 100755
index 1a8dc69..0000000
--- a/9p/defs.gen
+++ /dev/null
@@ -1,456 +0,0 @@
-#!/usr/bin/env python
-# 9p/defs.gen - Generate C marshalers/unmarshalers for a .txt file
-# defining a 9P protocol variant.
-#
-# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
-# SPDX-Licence-Identifier: AGPL-3.0-or-later
-
-import enum
-import os.path
-import re
-
-PROGRAM = "./9p/defs.gen"
-
-# Parse the *.txt ##############################################################
-
-
-class Atom(enum.Enum):
- u8 = 1
- u16 = 2
- u32 = 4
- u64 = 8
-
- @property
- def name(self) -> str:
- return str(self.value)
-
- @property
- def static_size(self) -> int:
- return self.value
-
-
-# `msgid/structname = "member1 member2..."`
-# `structname = "member1 member2..."`
-# `structname += "member1 member2..."`
-class Struct:
- msgid: int | None = None
- name: str
- members: list["Member"]
-
- @property
- def static_size(self) -> int | None:
- size = 0
- for member in self.members:
- msize = member.static_size
- if msize is None:
- return None
- size += msize
- return size
-
-
-# `cnt*(name[typ])`
-# the `cnt*(...)` wrapper is optional
-class Member:
- cnt: str | None = None
- name: str
- typ: Atom | Struct
-
- @property
- def static_size(self) -> int | None:
- if self.cnt:
- return None
- return self.typ.static_size
-
-
-re_membername = "(?:[a-zA-Z_][a-zA-Z_0-9]*)"
-re_memberspec = (
- f"(?:(?P<cnt>{re_membername})\\*\\()?(?P<name>{re_membername})\\[(?P<typ>.*)\\]\\)?"
-)
-
-
-def parse_members(
- env: dict[str, Atom | Struct], existing: list[Member], specs: str
-) -> list[Member]:
- ret = existing
- for spec in specs.split():
- m = re.fullmatch(re_memberspec, spec)
- if not m:
- raise SyntaxError(f"invalid member spec {repr(spec)}")
-
- member = Member()
-
- member.name = m.group("name")
- if any(x.name == member.name for x in ret):
- raise ValueError(f"duplicate member name {repr(member.name)}")
-
- if m.group("typ") not in env:
- raise NameError(f"Unknown type {repr(m.group(2))}")
- member.typ = env[m.group("typ")]
-
- if cnt := m.group("cnt"):
- if len(ret) == 0 or ret[-1].name != cnt:
- raise ValueError(f"list count must be previous item: {repr(cnt)}")
- if not isinstance(ret[-1].typ, Atom):
- raise ValueError(f"list count must be an integer type: {repr(cnt)}")
- member.cnt = cnt
-
- ret += [member]
- return ret
-
-
-re_version = r'version\s+"(?P<version>[^"]+)"'
-re_structspec = (
- r'(?:(?P<msgid>[0-9]+)/)?(?P<name>\S+)\s*(?P<op>\+?=)\s*"(?P<members>[^"]*)"'
-)
-re_structspec_cont = r'"(?P<members>[^"]*)"'
-
-
-def parse_file(filename: str) -> tuple[str, list[Struct]]:
- version: str | None = None
- env: dict[str, Atom | Struct] = {
- "1": Atom.u8,
- "2": Atom.u16,
- "4": Atom.u32,
- "8": Atom.u64,
- }
- with open(filename, "r") as fh:
- prev: Struct | None = None
- for line in fh:
- line = line.split("#", 1)[0].strip()
- if not line:
- continue
- if m := re.fullmatch(re_version, line):
- if version:
- raise SyntaxError("must have exactly 1 version line")
- version = m.group("version")
- elif m := re.fullmatch(re_structspec, line):
- if m.group("op") == "+=" and m.group("msgid"):
- raise SyntaxError("cannot += to a message that is not yet defined")
- match m.group("op"):
- case "=":
- struct = Struct()
- if m.group("msgid"):
- struct.msgid = int(m.group("msgid"))
- struct.name = m.group("name")
- struct.members = parse_members(env, [], m.group("members"))
- env[struct.name] = struct
- prev = struct
- case "+=":
- if m.group("name") not in env:
- raise NameError(f"Unknown type {repr(m.group('name'))}")
- _struct = env[m.group("name")]
- if not isinstance(_struct, Struct):
- raise NameError(
- f"Type {repr(m.group('name'))} is not a struct"
- )
- struct = _struct
- struct.members = parse_members(
- env, struct.members, m.group("members")
- )
- prev = struct
- elif m := re.fullmatch(re_structspec_cont, line):
- if not prev:
- raise SyntaxError("continuation line must come after a struct line")
- prev.members = parse_members(env, prev.members, m.group("members"))
- else:
- raise SyntaxError(f"invalid line {repr(line)}")
- if not version:
- raise SyntaxError("must have exactly 1 version line")
- structs = [x for x in env.values() if isinstance(x, Struct)]
- return version, structs
-
-
-# Generate C ###################################################################
-
-
-def c_typename(idprefix: str, typ: Atom | Struct) -> str:
- match typ:
- case Atom():
- return f"uint{typ.value*8}_t"
- case Struct():
- if typ.msgid is not None:
- return f"struct {idprefix}msg_{typ.name}"
- return f"struct {idprefix}{typ.name}"
- case _:
- raise ValueError(f"not a type: {typ.__class__.__name__}")
-
-
-def gen_h(txtname: str, idprefix: str, structs: list[Struct]) -> str:
- guard = (
- f"_{txtname.replace('.txt', '.h').upper().replace('/', '_').replace('.', '_')}_"
- )
- ret = f"""/* Generated by `{PROGRAM} {txtname}`. DO NOT EDIT! */
-
-#ifndef {guard}
-#define {guard}
-
-#define {idprefix.upper()}MIN_MSGLEN 7
-"""
- ret += """
-/* non-message structs ********************************************************/
-
-"""
- for struct in structs:
- if struct.msgid is not None:
- continue
- ret += c_typename(idprefix, struct) + " {\n"
- typewidth = max(
- len(c_typename(idprefix, member.typ)) for member in struct.members
- )
- for member in struct.members:
- ret += f"\t{c_typename(idprefix, member.typ).ljust(typewidth)} {'*' if member.cnt else ' '}{member.name};\n"
- ret += "};\n"
-
- ret += """
-/* message types **************************************************************/
-
-"""
- ret += f"enum {idprefix}msg_type {{ /* uint8_t */\n"
- namewidth = max(len(msg.name) for msg in structs if msg.msgid is not None)
- for msg in structs:
- if msg.msgid is None:
- continue
- ret += f"\t{idprefix.upper()}TYP_{msg.name.ljust(namewidth)} = {msg.msgid},\n"
- ret += "};\n"
-
- ret += """
-/* message structs ************************************************************/
-
-"""
- for msg in structs:
- if msg.msgid is None:
- continue
- if not msg.members:
- ret += c_typename(idprefix, msg) + " {};\n"
- continue
- ret += c_typename(idprefix, msg) + " {\n"
- typewidth = max(len(c_typename(idprefix, member.typ)) for member in msg.members)
- for member in msg.members:
- ret += f"\t{c_typename(idprefix, member.typ).ljust(typewidth)} {'*' if member.cnt else ' '}{member.name};\n"
- ret += "};\n"
-
- ret += f"""
-/* tables *********************************************************************/
-
-#define _P9_TYPECODE_FOR_CTYPE(msg) """
- for msg in structs:
- if msg.msgid is None:
- continue
- ret += f", \\\n\t\t{c_typename(idprefix, msg)}: {idprefix.upper()}TYP_{msg.name}"
- ret += "\n"
-
- ret += "\n"
- ret += f"#endif /* {guard} */\n"
- return ret
-
-
-def gen_c(txtname: str, idprefix: str, structs: list[Struct]) -> str:
- txtdir, txtbase = os.path.split(txtname)
- header = os.path.join(txtdir, "defs-" + txtbase.replace(".txt", ".h"))
- ret = f"""/* Generated by `{PROGRAM} {txtname}`. DO NOT EDIT! */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h> /* for malloc() */
-
-#include "{header}"
-#include "9p/internal.h"
-"""
-
- def used(arg: str) -> str:
- return arg
-
- def unused(arg: str) -> str:
- return f"UNUSED({arg})"
-
- # checksize_* ##############################################################
- ret += """
-/* checksize_* ****************************************************************/
-
-static inline bool _checksize_list(size_t cnt, _checksize_fn_t fn, size_t host_size,
- uint32_t net_len, uint8_t *net_bytes, uint32_t *mut_net_offset, size_t *mut_host_extra) {
- for (size_t i = 0; i < cnt; i++)
- if (__builtin_add_overflow(*mut_host_extra, host_size, mut_host_extra)
- || fn(net_len, net_bytes, mut_net_offset, mut_host_extra))
- return true;
- return false;
-}
-
-static inline bool checksize_1(uint32_t net_len, uint8_t *UNUSED(net_bytes), uint32_t *mut_net_offset, size_t *UNUSED(mut_host_extra)) {
- return __builtin_add_overflow(*mut_net_offset, 1, mut_net_offset) || net_len < *mut_net_offset;
-}
-static inline bool checksize_2(uint32_t net_len, uint8_t *UNUSED(net_bytes), uint32_t *mut_net_offset, size_t *UNUSED(mut_host_extra)) {
- return __builtin_add_overflow(*mut_net_offset, 2, mut_net_offset) || net_len < *mut_net_offset;
-}
-static inline bool checksize_4(uint32_t net_len, uint8_t *UNUSED(net_bytes), uint32_t *mut_net_offset, size_t *UNUSED(mut_host_extra)) {
- return __builtin_add_overflow(*mut_net_offset, 4, mut_net_offset) || net_len < *mut_net_offset;
-}
-static inline bool checksize_8(uint32_t net_len, uint8_t *UNUSED(net_bytes), uint32_t *mut_net_offset, size_t *UNUSED(mut_host_extra)) {
- return __builtin_add_overflow(*mut_net_offset, 8, mut_net_offset) || net_len < *mut_net_offset;
-}
-
-"""
- for struct in structs:
- inline = ' inline' if struct.msgid is None else ''
- argfn = used if struct.members else unused
- ret += f"static{inline} bool checksize_{struct.name}(uint32_t {argfn('net_len')}, uint8_t *{argfn('net_bytes')}, uint32_t *{argfn('mut_net_offset')}, size_t *{argfn('mut_host_extra')}) {{"
- if len(struct.members) == 0:
- ret += "\n\treturn false;\n"
- ret += "}\n"
- continue
- prefix0 = "\treturn "
- prefix1 = "\t || "
- prefix2 = "\t "
- prefix = prefix0
- prev_size: int | None = None
- for member in struct.members:
- if member.cnt is not None:
- assert prev_size
- ret += f"\n{prefix }_checksize_list(decode_u{prev_size*8}le(&net_bytes[(*mut_net_offset)-{prev_size}]), checksize_{member.typ.name}, sizeof({c_typename(idprefix, member.typ)}),"
- ret += f"\n{prefix2} net_len, net_bytes, mut_net_offset, mut_host_extra)"
- else:
- ret += f"\n{prefix}checksize_{member.typ.name}(net_len, net_bytes, mut_net_offset, mut_host_extra)"
- prefix = prefix1
- prev_size = member.static_size
- if struct.name == "s":
- ret += (
- f"\n{prefix}__builtin_add_overflow(*mut_host_extra, 1, mut_host_extra)"
- )
- ret += ";\n}\n"
-
- # unmarshal_* ##############################################################
- ret += """
-/* unmarshal_* ****************************************************************/
-/* checksize_XXX() should be called before unmarshal_XXX(). */
-
-static inline bool unmarshal_1(uint8_t *net_bytes, uint32_t *mut_net_offset, void **UNUSED(mut_host_extra), uint8_t *out) {
- *out = decode_u8le(&net_bytes[*mut_net_offset]);
- *mut_net_offset += 1;
- return false;
-}
-static inline bool unmarshal_2(uint8_t *net_bytes, uint32_t *mut_net_offset, void **UNUSED(mut_host_extra), uint16_t *out) {
- *out = decode_u16le(&net_bytes[*mut_net_offset]);
- *mut_net_offset += 2;
- return false;
-}
-static inline bool unmarshal_4(uint8_t *net_bytes, uint32_t *mut_net_offset, void **UNUSED(mut_host_extra), uint32_t *out) {
- *out = decode_u32le(&net_bytes[*mut_net_offset]);
- *mut_net_offset += 4;
- return false;
-}
-static inline bool unmarshal_8(uint8_t *net_bytes, uint32_t *mut_net_offset, void **UNUSED(mut_host_extra), uint64_t *out) {
- *out = decode_u64le(&net_bytes[*mut_net_offset]);
- *mut_net_offset += 8;
- return false;
-}
-
-"""
- for struct in structs:
- argfn = used if struct.members else unused
- ret += f"static inline bool unmarshal_{struct.name}(uint8_t *{argfn('net_bytes')}, uint32_t *{argfn('mut_net_offset')}, void **{argfn('mut_host_extra')}, {c_typename(idprefix, struct)} *{argfn('out')}) {{\n"
- for member in struct.members:
- if member.cnt:
- ret += f"\tout->{member.name} = *mut_host_extra;\n"
- ret += f"\t*mut_host_extra += sizeof(*out->{member.name}) * out->{member.cnt};\n"
- ret += f"\tfor (typeof(out->{member.cnt}) i = 0; i < out->{member.cnt}; i++)\n"
- ret += f"\t\tif (unmarshal_{member.typ.name}(net_bytes, mut_net_offset, mut_host_extra, &(out->{member.name}[i])))\n"
- ret += f"\t\t\treturn true;\n"
- if struct.name == "s":
- ret += f"\tif (!is_valid_utf8_without_nul(out->{member.name}, out->{member.cnt}))\n"
- ret += f"\t\treturn true;\n"
- ret += f"\tout->{member.name}[out->{member.cnt}] = '\\0';\n"
- else:
- ret += f"\tif (unmarshal_{member.typ.name}(net_bytes, mut_net_offset, mut_host_extra, &(out->{member.name})))\n"
- ret += f"\t\treturn true;\n"
- ret += "\treturn false;\n"
- ret += "}\n"
-
- # marshal_* ################################################################
- ret += """
-/* marshal_* ******************************************************************/
-
-static inline bool marshal_1(struct p9_ctx *ctx, uint8_t val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) {
- if (*mut_net_offset + 1 > ctx->max_msg_size)
- return true;
- out_net_bytes[*mut_net_offset] = val;
- *mut_net_offset += 1;
- return false;
-}
-static inline bool marshal_2(struct p9_ctx *ctx, uint16_t val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) {
- if (*mut_net_offset + 2 > ctx->max_msg_size)
- return true;
- encode_u16le(val, &out_net_bytes[*mut_net_offset]);
- *mut_net_offset += 2;
- return false;
-}
-static inline bool marshal_4(struct p9_ctx *ctx, uint32_t val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) {
- if (*mut_net_offset + 4 > ctx->max_msg_size)
- return true;
- encode_u32le(val, &out_net_bytes[*mut_net_offset]);
- *mut_net_offset += 4;
- return false;
-}
-static inline bool marshal_8(struct p9_ctx *ctx, uint64_t val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) {
- if (*mut_net_offset + 8 > ctx->max_msg_size)
- return true;
- encode_u64le(val, &out_net_bytes[*mut_net_offset]);
- *mut_net_offset += 8;
- return false;
-}
-"""
- for struct in structs:
- argfn = used if struct.members else unused
- ret += f"static inline bool marshal_{struct.name}(struct p9_ctx *{argfn('ctx')}, {c_typename(idprefix, struct)} {argfn('val')}, uint8_t *{argfn('out_net_bytes')}, uint32_t *{argfn('mut_net_offset')}) {{\n"
- for member in struct.members:
- if member.cnt:
- ret += f"\tfor (typeof(val.{member.cnt}) i = 0; i < val.{member.cnt}; i++)\n"
- ret += f"\t\tif (marshal_{member.typ.name}(ctx, val.{member.name}[i], out_net_bytes, mut_net_offset))\n"
- ret += f"\t\t\treturn true;\n"
- else:
- ret += f"\tif (marshal_{member.typ.name}(ctx, val.{member.name}, out_net_bytes, mut_net_offset))\n"
- ret += f"\t\treturn true;\n"
- ret += "\treturn false;\n"
- ret += "}\n"
-
- # tables ###################################################################
- ret += """
-/* tables *********************************************************************/
-
-"""
- for msg in structs:
- if msg.msgid is None:
- continue
- ret += f"static bool _unmarshal_{msg.name}(uint8_t *net_bytes, uint32_t *mut_net_offset, void **mut_host_extra, void *out) {{ return unmarshal_{msg.name}(net_bytes, mut_net_offset, mut_host_extra, ({c_typename(idprefix, msg)} *)out); }}\n"
- for msg in structs:
- if msg.msgid is None:
- continue
- ret += f"static bool _marshal_{msg.name}(struct p9_ctx *ctx, void *val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) {{ return marshal_{msg.name}(ctx, *(({c_typename(idprefix, msg)} *)val), out_net_bytes, mut_net_offset); }}\n"
- ret += "struct version version_9P2000 = {\n"
- ret += "\t.msgs = {\n"
- for msg in structs:
- if msg.msgid is None:
- continue
- ret += f"\t\t[{idprefix.upper()}TYP_{msg.name}] = {{ .unmarshal_basesize=sizeof({c_typename(idprefix, msg)}), .unmarshal_extrasize=checksize_{msg.name}, .unmarshal=_unmarshal_{msg.name}, .marshal=_marshal_{msg.name} }},\n"
- ret += "\t},\n"
- ret += "};\n"
-
- ############################################################################
- return ret
-
-
-################################################################################
-
-if __name__ == "__main__":
- import sys
-
- for txtname in sys.argv[1:]:
- txtdir, txtbase = os.path.split(txtname)
- version, structs = parse_file(txtname)
- with open(
- os.path.join(txtdir, "defs-" + txtbase.replace(".txt", ".h")), "w"
- ) as fh:
- fh.write(gen_h(txtname, "p9_", structs))
- with open(
- os.path.join(txtdir, "defs-" + txtbase.replace(".txt", ".c")), "w"
- ) as fh:
- fh.write(gen_c(txtname, "p9_", structs))
diff --git a/9p/defs.h b/9p/defs.h
deleted file mode 100644
index 907cdde..0000000
--- a/9p/defs.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* 9p/defs.h - TODO
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-Licence-Identifier: AGPL-3.0-or-later
- */
-
-#ifndef _9P_DEFS_H_
-#define _9P_DEFS_H_
-
-#include <stdint.h>
-
-#define P9_NOTAG ((uint16_t)~0U)
-#define P9_NOFID ((uint32_t)~0U)
-
-enum p9_version {
- P9_VER_UNINITIALIZED,
- /* P9_VER_9P1, */
- P9_VER_9P2000,
- /*P9_VER_9P2000_u,*/
- /*P9_VER_9P2000_L,*/
- /*P9_VER_9P2000_e,*/
- _P9_VER_CNT,
-};
-
-struct p9_ctx;
-
-enum p9_version p9_ctx_version(p9_ctx *);
-
-/** Write an static error into ctx, return -1. */
-int p9_error(struct p9_ctx *ctx, uint32_t linux_errno, char const *msg);
-/** Write a printf-style error into ctx, return -1. */
-int p9_errorf(struct p9_ctx *ctx, uint32_t linux_errno, char const *fmt, ...);
-
-/**
- * Return how much space the message at net_bytes will take when
- * unmarshaled. This number may be larger than net_bytes due to (1)
- * struct padding, (2) nul-terminator byes for strings.
- *
- * Emits an error (return -1, set ctx->err_num and ctx->err_msg) if
- * either the message type is unknown or if net_bytes is too short for
- * that message type.
- *
- * @param net_bytes : the complete request, starting with the "size[4]"
- * @return required size, or -1 on error
- */
-size_t p9_unmarshal_size(struct p9_ctx *ctx, uint8_t *net_bytes);
-
-/**
- * Unmarshal the 9P message `net_bytes` into the C struct `out_body`.
- *
- * Emits an error (return 0, set ctx->err_num and ctx->err_msg) if a
- * string contains invalid UTF-8 or a nul-byte.
- *
- * @param net_bytes : the complete message, starting with the "size[4]"
- * @param out_tag : the message-ID tag
- * @param out_body : the message body, must be at least p9_unmarshal_size() bytes
- * @return the message type, or -1 on error
- */
-uint8_t p9_unmarshal(struct p9_ctx *ctx, uint8_t *net_bytes, uint16_t *out_tag, void *out_body);
-
-/**
- * Marshal a `struct p9_msg_{type}` structure into a byte-array.
- *
- * @param struct p9_ctx *ctx : a request context
- * @param uint16_t msgid : the message-ID tag
- * @param struct p9_msg_{type} msg : the message to encode
- *
- * @param uint8_t *out_bytes : the buffer to encode to, must be at be at least ctx->max_msg_size bytes
- * @return uint32_t : the encoded length, or -1 on error
- */
-#define p9_marshal(ctx, msgid, msg, out_bytes) _p9_marshal(ctx, P9_TYPECODE_FOR_CTYPE(msg), msgid, &(msg), out_bytes)
-uint32_t _p9_marshal(struct p9_ctx *ctx, uint8_t typ, uint16_t msgid, void *body, uint8_t *out_bytes);
-
-#endif /* _9P_DEFS_H_ */
diff --git a/9p/internal.h b/9p/internal.h
deleted file mode 100644
index 61977d4..0000000
--- a/9p/internal.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* 9p/internal.h - TODO
- *
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-Licence-Identifier: AGPL-3.0-or-later
- */
-
-#ifndef _9P_INTERNAL_H_
-#define _9P_INTERNAL_H_
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#include "9p/defs.h"
-
-#define USE_CONFIG_9P
-#include "config.h"
-static_assert(CONFIG_9P_MAX_ERR_SIZE <= UINT16_MAX);
-
-/* C language *****************************************************************/
-
-#define UNUSED(name) /* name __attribute__ ((unused)) */
-
-/* types **********************************************************************/
-
-struct p9_ctx {
- enum p9_version version;
- uint32_t max_msg_size;
- uint32_t Rerror_overhead;
-
- uint32_t err_num;
- char err_msg[CONFIG_9P_MAX_ERR_SIZE];
-};
-
-static inline enum p9_version p9_ctx_version(p9_ctx *ctx) {
- assert(ctx);
- return ctx->version;
-}
-
-/* vtables ********************************************************************/
-
-typedef bool (*_checksize_fn_t)(uint32_t net_len, uint8_t *net_bytes, uint32_t *mut_net_offset, size_t *mut_host_extra);
-typedef bool (*_unmarshal_fn_t)(uint8_t *net_bytes, uint32_t *mut_net_offset, void **mut_host_extra, void *out);
-typedef bool (*_marshal_fn_t)(struct p9_ctx *ctx, void *val, uint8_t *out_net_bytes, uint32_t *mut_net_offset);
-
-struct msg_vtable {
- size_t unmarshal_basesize;
- _checksize_fn_t unmarshal_extrasize;
- _unmarshal_fn_t unmarshal;
- _marshal_fn_t marshal;
-};
-
-struct version {
- struct msg_vtable msgs[0xFF];
-};
-
-extern struct version version_9P2000;
-/*extern struct version version_9P2000u; */
-
-/* unmarshal utilities ********************************************************/
-
-static inline uint8_t decode_u8le(uint8_t *in) {
- return in[0];
-}
-static inline uint16_t decode_u16le(uint8_t *in) {
- return (((uint16_t)(in[0])) << 0)
- | (((uint16_t)(in[1])) << 8)
- ;
-}
-static inline uint32_t decode_u32le(uint8_t *in) {
- return (((uint32_t)(in[0])) << 0)
- | (((uint32_t)(in[1])) << 8)
- | (((uint32_t)(in[2])) << 16)
- | (((uint32_t)(in[3])) << 24)
- ;
-}
-static inline uint64_t decode_u64le(uint8_t *in) {
- return (((uint64_t)(in[0])) << 0)
- | (((uint64_t)(in[1])) << 8)
- | (((uint64_t)(in[2])) << 16)
- | (((uint64_t)(in[3])) << 24)
- | (((uint64_t)(in[4])) << 32)
- | (((uint64_t)(in[5])) << 40)
- | (((uint64_t)(in[6])) << 48)
- | (((uint64_t)(in[7])) << 56)
- ;
-}
-
-static inline bool _is_valid_utf8(uint8_t *str, size_t len, bool forbid_nul) {
- uint32_t ch;
- uint8_t chlen;
- assert(str);
- for (size_t pos = 0; pos < len;) {
- if ((str[pos] & 0b10000000) == 0b00000000) { ch = str[pos] & 0b01111111; chlen = 1; }
- else if ((str[pos] & 0b11100000) == 0b11000000) { ch = str[pos] & 0b00011111; chlen = 2; }
- else if ((str[pos] & 0b11110000) == 0b11100000) { ch = str[pos] & 0b00001111; chlen = 3; }
- else if ((str[pos] & 0b11111000) == 0b11110000) { ch = str[pos] & 0b00000111; chlen = 4; }
- else return false;
- if ((ch == 0 && (chlen != 1 || forbid_nul)) || pos + chlen > len) return false;
- for (uint8_t i = 1; i < chlen; i++) {
- if ((str[pos+i] & 0b11000000) != 0b10000000) return false;
- ch = (ch << 6) | (str[pos+i] & 0b00111111);
- }
- if (ch > 0x10FFFF) return false;
- pos += chlen;
- }
- return true;
-}
-
-#define is_valid_utf8(str, len) _is_valid_utf8(str, len, false)
-#define is_valid_utf8_without_nul(str, len) _is_valid_utf8(str, len, true)
-
-/* marshal utilities **********************************************************/
-
-static inline void encode_u8le(uint8_t in, uint8_t *out) {
- out[0] = in;
-}
-static inline void encode_u16le(uint16_t in, uint8_t *out) {
- out[0] = (uint8_t)((in >> 0) & 0xFF);
- out[1] = (uint8_t)((in >> 8) & 0xFF);
-}
-static inline void encode_u32le(uint32_t in, uint8_t *out) {
- out[0] = (uint8_t)((in >> 0) & 0xFF);
- out[1] = (uint8_t)((in >> 8) & 0xFF);
- out[2] = (uint8_t)((in >> 16) & 0xFF);
- out[3] = (uint8_t)((in >> 24) & 0xFF);
-}
-static inline void encode_u64le(uint64_t in, uint8_t *out) {
- out[0] = (uint8_t)((in >> 0) & 0xFF);
- out[1] = (uint8_t)((in >> 8) & 0xFF);
- out[2] = (uint8_t)((in >> 16) & 0xFF);
- out[3] = (uint8_t)((in >> 24) & 0xFF);
- out[4] = (uint8_t)((in >> 32) & 0xFF);
- out[5] = (uint8_t)((in >> 40) & 0xFF);
- out[6] = (uint8_t)((in >> 48) & 0xFF);
- out[7] = (uint8_t)((in >> 56) & 0xFF);
-}
-
-#endif /* _9P_INTERNAL_H_ */
diff --git a/9p/linux-errno.h.gen b/9p/linux-errno.h.gen
deleted file mode 100755
index b896384..0000000
--- a/9p/linux-errno.h.gen
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env python
-
-
-def print_errnos(txtlists: list[str]) -> None:
- print(
- f"/* 9p/linux-errno.h - Generated by `./9p/linux-errno.h.gen {' '.join(txtlists)}`. DO NOT EDIT! */"
- )
- errnos: dict[str, tuple[int, str]] = {}
- for txtlist in sys.argv[1:]:
- with open(txtlist, "r") as fh:
- for line in fh:
- if line.startswith("#"):
- print(f"/* {line[1:].strip()} */")
- continue
- _num, name, desc = line.split(maxsplit=2)
- num = int(_num)
- desc = desc.strip()
- errnos[name] = (num, desc)
- print()
- print("#ifndef _9P_LINUX_ERRNO_H_")
- print("#define _9P_LINUX_ERRNO_H_")
- print()
- namelen = max(len(name) for name in errnos.keys())
- numlen = max(len(str(num)) for (num, desc) in errnos.values())
- for name in errnos:
- print(f"#define LINUX_{name.ljust(namelen)} {str(errnos[name][0]).rjust(numlen)} /* {errnos[name][1]} */")
- print()
- print("#endif /* _9P_LINUX_ERRNO_H_ */")
-
-
-if __name__ == "__main__":
- import sys
-
- print_errnos(sys.argv[1:])
diff --git a/9p/misc.txt b/9p/misc.txt
deleted file mode 100644
index 93aa304..0000000
--- a/9p/misc.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-# qid.types
-QTDIR = 1<<7
-QTAPPEND = 1<<6
-QTEXCL = 1<<5
-QTMOUNT = 1<<4 # been around forever, but undocumented?
-QTAUTH = 1<<3
-QTTMP = 1<<2 # added to Plan 9 2003-12
-QTSYMLINK = 1<<1 # .u
-QTFILE = 1<<0
-
-DMDIR = 1<<31
-DMAPPEND = 1<<30
-DMEXCL = 1<<29
-DMMOUNT = 1<<28
-DMAUTH = 1<<27
-DMTMP = 1<<26
-# = 1<<25
-# = 1<<24
-DMDEVICE = 1<<23 # .u
-# = 1<<22
-DMNAMEDPIPE = 1<<21 # .u
-DMSOCKET = 1<<20 # .u
-DMSETUID = 1<<19 # .u
-DMSETGID = 1<<18 # .u
diff --git a/9p/srv.c b/9p/srv.c
deleted file mode 100644
index 59326c9..0000000
--- a/9p/srv.c
+++ /dev/null
@@ -1,194 +0,0 @@
-#include <assert.h>
-
-#include "coroutine.h"
-#include "netio.h"
-#include "9p/9p.h"
-
-#include "9p/internal.h"
-
-struct p9_srvconn {
- /* immutable */
- p9_srv *srv;
- cid_t reader;
- int fd;
- /* mutable */
- uint32_t max_msg_size;
- enum p9_version version;
- unsigned int refcount;
-};
-
-struct p9_srvreq {
- p9_srvconn *conn;
- uint8_t *msg;
-};
-
-COROUTINE p9_srv_read_cr(void *_srv) {
- uint8_t buf[CONFIG_9P_MAX_MSG_SIZE];
-
- p9_srv *srv = _srv;
- assert(srv);
- cr_begin();
-
- for (;;) {
- struct p9_srvconn conn = {
- .srv = srv,
- .reader = cr_getcid();
-
- .max_msg_size = CONFIG_9P_MAX_MSG_SIZE;
- .version = P9_VER_UNINITIALIZED;
- .refcount = 1,
- };
- conn.fd = netio_accept(srv->sockfd);
- if (conn.fd < 0) {
- fprintf(stderr, "error: accept: %m", -conn.fd);
- continue;
- }
-
- for (;;) {
- /* Read the message size. */
- size_t goal = 4, done = 0;
- while (done < goal) {
- ssize_t r = netio_read(conn.fd, &buf[done], sizeof(buf)-done);
- if (r < 0) {
- fprintf(stderr, "error: read: %m", -r);
- goto close;
- } else if (r == 0) {
- if (done != 0)
- fprintf(stderr, "error: read: unexpected EOF");
- goto close;
- }
- done += r;
- }
- goal = decode_u32le(buf);
- if (goal < 7) {
- /* We can't respond with an Rerror becuase we wouldn't know what tag to use! */
- fprintf(stderr, "error: T-message is impossibly small");
- goto close;
- }
- if (goal > conn.max_msg_size) {
- struct p9_ctx ctx = {
- .version = conn.version,
- .max_msg_size = conn.max_msg_size,
- };
- if (initialized)
- p9_errorf(&ctx, LINUX_EMSGSIZE, "T-message larger than negotiated limit (%zu > %zu)", goal, conn.max_msg_size);
- else
- p9_errorf(&ctx, LINUX_EMSGSIZE, "T-message larger than server limit (%zu > %zu)", goal, conn.max_msg_size);
- marshal_error(&ctx, buf);
- netio_write(conn.fd, buf, decode_u32le(buf));
- continue;
- }
- /* Read the rest of the message. */
- while (done < goal) {
- ssize_t r = netio_read(conn.fd, &buf[done], sizeof(buf)-done);
- if (r < 0) {
- fprintf(stderr, "error: read: %m", -r);
- goto close;
- } else if (r == 0) {
- fprintf(stderr, "error: read: unexpected EOF");
- goto close;
- }
- done += r;
- }
-
- /* Handle the message... */
- if (conn.version == P9_VER_UNINITIALIZED) {
- /* ...synchronously if we haven't negotiated the protocol yet, ... */
- handle_message(&conn, buf);
- } else {
- /* ...asynchronously if we have. */
- cr_chan_send(&srv->reqch, buf);
- cr_pause_and_yield();
- }
- }
- close:
- netio_close(conn.fd, true, (--conn.refcount) == 0);
- if (conn.refcount) {
- cr_pause_and_yield();
- assert(conn.refcount == 0);
- netio_close(conn.fd, false, true);
- }
- }
-
- cr_end();
-}
-
-COROUTINE p9_srv_write_cr(void *_srv) {
- uint8_t net[CONFIG_9P_MAX_MSG_SIZE];
-
- p9_srv *srv = _srv;
- assert(srv);
- cr_begin();
-
- for (;;) {
- struct p9_srvreq req;
- cr_chan_recv(&srv->reqch, &req);
- memcpy(net, req.msg, decode_u32le(req.msg));
- req.conn->refcount++;
- cr_unpause(req.conn->reader);
-
- handle_message(&req.conn, net);
-
- if ((--req.conn->refcount) == 0)
- cr_unpause(req.conn->reader);
- }
-
- cr_end();
-}
-
-void handle_message(p9_srvconn *conn, uint8_t *net) {
- uint8_t host[CONFIG_9P_MAX_MSG_SIZE];
-
- struct p9_ctx ctx = {
- .version = req.conn->version,
- .max_msg_size = req.conn->max_msg_size,
- };
-
- size_t host_size = p9_unmarshal_size(&ctx, net);
- if (host_size == (size_t)-1)
- goto write;
- if (host_size > sizeof(host)) {
- p9_errorf(&ctx, LINUX_EMSGSIZE, "unmarshalled payload larger than server limit (%zu > %zu)", host_size, sizeof(host));
- goto write;
- }
-
- uint16_t tag;
- uint8_t typ = p9_unmarshal(&ctx, net, &tag, host);
- if (typ == (uint8_t)-1)
- goto write;
- if (typ % 2 != 0) {
- p9_errorf(&ctx, LINUX_EOPNOTSUPP, "expected a T-message but got an R-message");
- goto write;
- }
-
- TODO;
-
- write:
- if (ctx.err_num || ctx.err_msg[0])
- marshal_error(&ctx, net);
- else
- TODO;
- netio_write(req.conn->fd, net, decode_u32le(net));
-}
-
-static inline uint16_t min_u16(uint16_t a, b) {
- return (a < b) ? a : b;
-}
-
-/* We have special code for marshaling Rerror because we don't ever
- * want to produce an error because the err_msg is too long for the
- * `ctx->max_msg_size`! */
-void marshal_error(struct p9_ctx *ctx, uint16_t tag, uint8_t *net) {
- struct p9_msg_Rerror host = {
- .ename = {
- .len = strnlen(ctx->err_msg, CONFIG_9P_MAX_ERR_SIZE),
- .utf8 = ctx->err_msg,
- },
- };
- if (host.ename.len + ctx->Rerror_overhead > ctx->max_msg_size)
- host.ename.len = ctx->max_msg_size - overhead;
- p9_marshal(ctx, tag, host, net);
-}
-
-ERANGE for reply too large
-EPROTONOSUPPORT for version errors
diff --git a/9p/srv.h b/9p/srv.h
deleted file mode 100644
index e3623ed..0000000
--- a/9p/srv.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _NET9P_H_
-#define _NET9P_H_
-
-#include "coroutine.h"
-
-struct p9_srvreq;
-
-struct p9_srv {
- int sockfd;
- cr_chan_t(p9_srvreq *) reqch;
-};
-
-COROUTINE p9_srv_read_cr(void *_srv);
-COROUTINE p9_srv_write_cr(void *_srv);
-
-#endif /* _NET9P_H_ */