From e5e15c04bc58c34906e6d7cfcbad68d1a5617563 Mon Sep 17 00:00:00 2001
From: "Luke T. Shumaker" <lukeshu@lukeshu.com>
Date: Fri, 27 Sep 2024 17:25:36 -0600
Subject: wip

---
 lib9p/include/lib9p/9p.h              |  72 +++++++++
 lib9p/include/lib9p/_types.h          | 285 ++++++++++++++++++++++++++++++++++
 lib9p/include/lib9p/linux-errno.h.gen |  34 ++++
 lib9p/include/lib9p/srv.h             |  16 ++
 4 files changed, 407 insertions(+)
 create mode 100644 lib9p/include/lib9p/9p.h
 create mode 100644 lib9p/include/lib9p/_types.h
 create mode 100755 lib9p/include/lib9p/linux-errno.h.gen
 create mode 100644 lib9p/include/lib9p/srv.h

(limited to 'lib9p/include')

diff --git a/lib9p/include/lib9p/9p.h b/lib9p/include/lib9p/9p.h
new file mode 100644
index 0000000..a55f08f
--- /dev/null
+++ b/lib9p/include/lib9p/9p.h
@@ -0,0 +1,72 @@
+/* lib9p/9p.h - Base 9P protocol definitions for both clients and servers
+ *
+ * Copyright (C) 2024  Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-Licence-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _LIB9P_9P_H_
+#define _LIB9P_9P_H_
+
+#include <lib9p/linux-errno.h>
+#include <lib9p/_types.h>
+
+#define LIB9P_NOTAG ((uint16_t)~0U)
+#define LIB9P_NOFID ((uint32_t)~0U)
+
+struct lib9p_ctx;
+enum lib9p_version      lib9p_ctx_version(lib9p_ctx *);
+uint32_t                lib9p_ctx_max_msg_size(lib9p_ctx *);
+
+/** Write an static error into ctx, return -1.  */
+int lib9p_error(struct lib9p_ctx *ctx, uint32_t linux_errno, char const *msg);
+/** Write a printf-style error into ctx, return -1.  */
+int lib9p_errorf(struct lib9p_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, or if an invalid string (invalid UTF-8,
+ * contains a nul-byte) is encountered.
+ *
+ * @param net_bytes : the complete request, starting with the "size[4]"
+ *
+ * @return required size, or -1 on error
+ */
+ssize_t lib9p_unmarshal_size(struct lib9p_ctx *ctx, uint8_t *net_bytes);
+
+/**
+ * Unmarshal the 9P message `net_bytes` into the C struct `ret_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 ctx : negotiated protocol parameters, where to record errors
+ * @param net_bytes : the complete message, starting with the "size[4]"
+ *
+ * @return ret_typ : the mesage type
+ * @return ret_tag : the message-ID tag
+ * @return ret_body : the message body, must be at least lib9p_unmarshal_size() bytes
+ * @return the message type, or -1 on error
+ */
+bool lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
+                     enum lib9p_msg_typ *ret_typ, uint16_t *ret_tag, void *ret_body);
+
+/**
+ * Marshal a `struct lib9p_msg_{typ}` structure into a byte-array.  
+ *
+ * @param ctx : negotiated protocol parameters, where to record errors
+ * @param typ : the message type
+ * @param tag : the message-ID tag
+ * @param msg : the message to encode
+ *
+ * @return ret_bytes : the buffer to encode to, must be at be at least lib9p_ctx_max_msg_size(ctx) bytes
+ * @return whether there was an error (false=success, true=error)
+ */
+bool lib9p_marshal(struct lib9p_ctx *ctx, uint8_t typ, uint16_t tag, void *body,
+                   uint8_t *ret_bytes);
+
+#endif _LIB9P_9P_H_
diff --git a/lib9p/include/lib9p/_types.h b/lib9p/include/lib9p/_types.h
new file mode 100644
index 0000000..348945d
--- /dev/null
+++ b/lib9p/include/lib9p/_types.h
@@ -0,0 +1,285 @@
+/* Generated by `./types.gen 9P2000.txt 9P2000.u.txt 9P2000.e.txt`.  DO NOT EDIT!  */
+
+#ifndef _LIB9P__TYPES_H_
+#define _LIB9P__TYPES_H_
+
+#include <stdint.h>
+
+/* versions *******************************************************************/
+
+enum lib9p_version {
+	LIB9P_VER_UNINITIALIZED = 0,
+	LIB9P_VER_9P2000,   /* "9P2000" */
+	LIB9P_VER_9P2000_e, /* "9P2000.e" */
+	LIB9P_VER_9P2000_u, /* "9P2000.u" */
+	LIB9P_VER_NUM,
+};
+
+/* non-message structs ********************************************************/
+
+struct lib9p_d {
+	uint32_t   len;
+	uint8_t   *dat;
+};
+
+struct lib9p_s {
+	uint16_t   len;
+	uint8_t   *utf8;
+};
+
+struct lib9p_qid {
+	uint8_t    type;
+	uint32_t   vers;
+	uint64_t   path;
+};
+
+struct lib9p_stat {
+	uint16_t           stat_size;
+	uint16_t           kern_type;
+	uint32_t           kern_dev;
+	struct lib9p_qid   file_qid;
+	uint32_t           file_mode;
+	uint32_t           file_atime;
+	uint32_t           file_mtime;
+	uint64_t           file_size;
+	struct lib9p_s     file_name;
+	struct lib9p_s     file_owner_uid;
+	struct lib9p_s     file_owner_gid;
+	struct lib9p_s     file_last_modified_uid;
+	struct lib9p_s     file_extension;           /* 9P2000.u */
+	uint32_t           file_owner_n_uid;         /* 9P2000.u */
+	uint32_t           file_owner_n_gid;         /* 9P2000.u */
+	uint32_t           file_last_modified_n_uid; /* 9P2000.u */
+};
+
+/* messages *******************************************************************/
+
+enum lib9p_msg_type { /* uint8_t */
+	LIB9P_TYP_Tversion = 100,
+	LIB9P_TYP_Rversion = 101,
+	LIB9P_TYP_Tauth    = 102,
+	LIB9P_TYP_Rauth    = 103,
+	LIB9P_TYP_Tattach  = 104,
+	LIB9P_TYP_Rattach  = 105,
+	LIB9P_TYP_Rerror   = 107,
+	LIB9P_TYP_Tflush   = 108,
+	LIB9P_TYP_Rflush   = 109,
+	LIB9P_TYP_Twalk    = 110,
+	LIB9P_TYP_Rwalk    = 111,
+	LIB9P_TYP_Topen    = 112,
+	LIB9P_TYP_Ropen    = 113,
+	LIB9P_TYP_Tcreate  = 114,
+	LIB9P_TYP_Rcreate  = 115,
+	LIB9P_TYP_Tread    = 116,
+	LIB9P_TYP_Rread    = 117,
+	LIB9P_TYP_Twrite   = 118,
+	LIB9P_TYP_Rwrite   = 119,
+	LIB9P_TYP_Tclunk   = 120,
+	LIB9P_TYP_Rclunk   = 121,
+	LIB9P_TYP_Tremove  = 122,
+	LIB9P_TYP_Rremove  = 123,
+	LIB9P_TYP_Tstat    = 124,
+	LIB9P_TYP_Rstat    = 125,
+	LIB9P_TYP_Twstat   = 126,
+	LIB9P_TYP_Rwstat   = 127,
+	LIB9P_TYP_Tsession = 150, /* 9P2000.e */
+	LIB9P_TYP_Rsession = 151, /* 9P2000.e */
+	LIB9P_TYP_Tsread   = 152, /* 9P2000.e */
+	LIB9P_TYP_Rsread   = 153, /* 9P2000.e */
+	LIB9P_TYP_Tswrite  = 154, /* 9P2000.e */
+	LIB9P_TYP_Rswrite  = 155, /* 9P2000.e */
+};
+
+#define LIB9P_TYPECODE_FOR_CTYPE(msg) _Generic((msg), \
+		struct lib9p_msg_Tversion: LIB9P_TYP_Tversion, \
+		struct lib9p_msg_Rversion: LIB9P_TYP_Rversion, \
+		struct lib9p_msg_Tauth: LIB9P_TYP_Tauth, \
+		struct lib9p_msg_Rauth: LIB9P_TYP_Rauth, \
+		struct lib9p_msg_Tattach: LIB9P_TYP_Tattach, \
+		struct lib9p_msg_Rattach: LIB9P_TYP_Rattach, \
+		struct lib9p_msg_Rerror: LIB9P_TYP_Rerror, \
+		struct lib9p_msg_Tflush: LIB9P_TYP_Tflush, \
+		struct lib9p_msg_Rflush: LIB9P_TYP_Rflush, \
+		struct lib9p_msg_Twalk: LIB9P_TYP_Twalk, \
+		struct lib9p_msg_Rwalk: LIB9P_TYP_Rwalk, \
+		struct lib9p_msg_Topen: LIB9P_TYP_Topen, \
+		struct lib9p_msg_Ropen: LIB9P_TYP_Ropen, \
+		struct lib9p_msg_Tcreate: LIB9P_TYP_Tcreate, \
+		struct lib9p_msg_Rcreate: LIB9P_TYP_Rcreate, \
+		struct lib9p_msg_Tread: LIB9P_TYP_Tread, \
+		struct lib9p_msg_Rread: LIB9P_TYP_Rread, \
+		struct lib9p_msg_Twrite: LIB9P_TYP_Twrite, \
+		struct lib9p_msg_Rwrite: LIB9P_TYP_Rwrite, \
+		struct lib9p_msg_Tclunk: LIB9P_TYP_Tclunk, \
+		struct lib9p_msg_Rclunk: LIB9P_TYP_Rclunk, \
+		struct lib9p_msg_Tremove: LIB9P_TYP_Tremove, \
+		struct lib9p_msg_Rremove: LIB9P_TYP_Rremove, \
+		struct lib9p_msg_Tstat: LIB9P_TYP_Tstat, \
+		struct lib9p_msg_Rstat: LIB9P_TYP_Rstat, \
+		struct lib9p_msg_Twstat: LIB9P_TYP_Twstat, \
+		struct lib9p_msg_Rwstat: LIB9P_TYP_Rwstat, \
+		struct lib9p_msg_Tsession: LIB9P_TYP_Tsession, \
+		struct lib9p_msg_Rsession: LIB9P_TYP_Rsession, \
+		struct lib9p_msg_Tsread: LIB9P_TYP_Tsread, \
+		struct lib9p_msg_Rsread: LIB9P_TYP_Rsread, \
+		struct lib9p_msg_Tswrite: LIB9P_TYP_Tswrite, \
+		struct lib9p_msg_Rswrite: LIB9P_TYP_Rswrite)
+
+struct lib9p_msg_Tversion {
+	uint32_t         max_msg_size;
+	struct lib9p_s   version;
+};
+
+struct lib9p_msg_Rversion {
+	uint32_t         max_msg_size;
+	struct lib9p_s   version;
+};
+
+struct lib9p_msg_Tauth {
+	uint32_t         afid;
+	struct lib9p_s   uname;
+	struct lib9p_s   aname;
+	uint32_t         n_uname; /* 9P2000.u */
+};
+
+struct lib9p_msg_Rauth {
+	struct lib9p_qid   aqid;
+};
+
+struct lib9p_msg_Tattach {
+	uint32_t         fid;
+	uint32_t         afid;
+	struct lib9p_s   uname;
+	struct lib9p_s   aname;
+};
+
+struct lib9p_msg_Rattach {
+	struct lib9p_qid   qid;
+};
+
+struct lib9p_msg_Rerror {
+	struct lib9p_s   ename;
+	uint32_t         errno; /* 9P2000.u */
+};
+
+struct lib9p_msg_Tflush {
+	uint16_t   oldtag;
+};
+
+struct lib9p_msg_Rflush {};
+
+struct lib9p_msg_Twalk {
+	uint32_t         fid;
+	uint32_t         newfid;
+	uint16_t         nwname;
+	struct lib9p_s  *wname;
+};
+
+struct lib9p_msg_Rwalk {
+	uint16_t           nwqid;
+	struct lib9p_qid  *wqid;
+};
+
+struct lib9p_msg_Topen {
+	uint32_t   fid;
+	uint8_t    mode;
+};
+
+struct lib9p_msg_Ropen {
+	struct lib9p_qid   qid;
+	uint32_t           iounit;
+};
+
+struct lib9p_msg_Tcreate {
+	uint32_t         fid;
+	struct lib9p_s   name;
+	uint32_t         perm;
+	uint8_t          mode;
+};
+
+struct lib9p_msg_Rcreate {
+	struct lib9p_qid   qid;
+	uint32_t           iounit;
+};
+
+struct lib9p_msg_Tread {
+	uint32_t   fid;
+	uint64_t   offset;
+	uint32_t   count;
+};
+
+struct lib9p_msg_Rread {
+	struct lib9p_d   data;
+};
+
+struct lib9p_msg_Twrite {
+	uint32_t         fid;
+	uint64_t         offset;
+	struct lib9p_d   data;
+};
+
+struct lib9p_msg_Rwrite {
+	uint32_t   count;
+};
+
+struct lib9p_msg_Tclunk {
+	uint32_t   fid;
+};
+
+struct lib9p_msg_Rclunk {};
+
+struct lib9p_msg_Tremove {
+	uint32_t   fid;
+};
+
+struct lib9p_msg_Rremove {};
+
+struct lib9p_msg_Tstat {
+	uint32_t   fid;
+};
+
+struct lib9p_msg_Rstat {
+	struct lib9p_stat   stat;
+};
+
+struct lib9p_msg_Twstat {
+	uint32_t            fid;
+	struct lib9p_stat   stat;
+};
+
+struct lib9p_msg_Rwstat {};
+
+/* 9P2000.e */
+struct lib9p_msg_Tsession {
+	uint64_t   key;
+};
+
+/* 9P2000.e */
+struct lib9p_msg_Rsession {};
+
+/* 9P2000.e */
+struct lib9p_msg_Tsread {
+	uint32_t         fid;
+	uint16_t         nwname;
+	struct lib9p_s  *wname;
+};
+
+/* 9P2000.e */
+struct lib9p_msg_Rsread {
+	struct lib9p_d   data;
+};
+
+/* 9P2000.e */
+struct lib9p_msg_Tswrite {
+	uint32_t         fid;
+	uint16_t         nwname;
+	struct lib9p_s  *wname;
+	struct lib9p_d   data;
+};
+
+/* 9P2000.e */
+struct lib9p_msg_Rswrite {
+	uint32_t   count;
+};
+
+#endif /* _LIB9P__TYPES_H_ */
diff --git a/lib9p/include/lib9p/linux-errno.h.gen b/lib9p/include/lib9p/linux-errno.h.gen
new file mode 100755
index 0000000..b896384
--- /dev/null
+++ b/lib9p/include/lib9p/linux-errno.h.gen
@@ -0,0 +1,34 @@
+#!/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/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h
new file mode 100644
index 0000000..3b8b21e
--- /dev/null
+++ b/lib9p/include/lib9p/srv.h
@@ -0,0 +1,16 @@
+#ifndef _LIB9P_SRV_H_
+#define _LIB9P_SRV_H_
+
+#include <libcr/coroutine.h>
+
+struct lib9p_srvreq;
+
+struct lib9p_srv {
+	int                     sockfd;
+	cr_chan_t(lib9p_srvreq *)  reqch;
+};
+
+COROUTINE lib9p_srv_read_cr(void *_srv);
+COROUTINE lib9p_srv_write_cr(void *_srv);
+
+#endif /* _LIB9P_SRV_H_ */
-- 
cgit v1.2.3-2-g168b