summaryrefslogtreecommitdiff
path: root/lib9p/include
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/include')
-rw-r--r--lib9p/include/lib9p/9p.h72
-rw-r--r--lib9p/include/lib9p/_types.h285
-rwxr-xr-xlib9p/include/lib9p/linux-errno.h.gen34
-rw-r--r--lib9p/include/lib9p/srv.h16
4 files changed, 407 insertions, 0 deletions
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_ */