summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib9p/CMakeLists.txt1
-rw-r--r--lib9p/core.c197
-rw-r--r--lib9p/core_include/lib9p/core.h38
-rw-r--r--lib9p/core_tables.c190
4 files changed, 203 insertions, 223 deletions
diff --git a/lib9p/CMakeLists.txt b/lib9p/CMakeLists.txt
index 0a5ea3e..cff07ad 100644
--- a/lib9p/CMakeLists.txt
+++ b/lib9p/CMakeLists.txt
@@ -8,7 +8,6 @@ target_include_directories(lib9p_core PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DI
target_sources(lib9p_core INTERFACE
core.c
core_generated.c
- core_tables.c
)
target_link_libraries(lib9p_core INTERFACE
libfmt
diff --git a/lib9p/core.c b/lib9p/core.c
index cb8ddee..adf7ecf 100644
--- a/lib9p/core.c
+++ b/lib9p/core.c
@@ -4,14 +4,18 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <inttypes.h> /* for PRIu{n} */
-#include <stdarg.h> /* for va_* */
-#include <string.h> /* for strncpy() */
+#include <stdarg.h> /* for va_* */
+#include <string.h> /* for strlen(), strnlen(), strncpy(), memcmp(), memset() */
-#include <libfmt/fmt.h> /* for fmt_vsnprintf() */
+#include <libfmt/fmt.h> /* for fmt_vsnprintf() */
+#include <libmisc/assert.h> /* for assert() */
+#include <libmisc/endian.h> /* for uint32le_decode() */
+#include <libmisc/log.h> /* for const_byte_str() */
#include <lib9p/core.h>
+#include "core_tables.h"
+
/* strings ********************************************************************/
struct lib9p_s lib9p_str(char *s) {
@@ -58,10 +62,7 @@ bool lib9p_ctx_has_error(struct lib9p_ctx *ctx) {
return ctx->err_msg[0];
}
-#undef lib9p_error
-#undef lib9p_errorf
-
-int lib9p_error(struct lib9p_ctx *ctx,
+int _lib9p_error(struct lib9p_ctx *ctx,
#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L
lib9p_errno_t linux_errno,
#endif
@@ -78,7 +79,7 @@ int lib9p_error(struct lib9p_ctx *ctx,
return -1;
}
-int lib9p_errorf(struct lib9p_ctx *ctx,
+int _lib9p_errorf(struct lib9p_ctx *ctx,
#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L
lib9p_errno_t linux_errno,
#endif
@@ -100,3 +101,181 @@ int lib9p_errorf(struct lib9p_ctx *ctx,
return -1;
}
+
+/* bounds checks **************************************************************/
+
+static inline void assert_ver(enum lib9p_version ver) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
+ assert(0 <= ver && ver < LIB9P_VER_NUM);
+#pragma GCC diagnostic pop
+}
+
+static inline void assert_typ(enum lib9p_msg_type typ) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wtype-limits"
+ assert(0 <= typ && typ < 0xFF);
+#pragma GCC diagnostic pop
+}
+
+/* simple lookups *************************************************************/
+
+const char *lib9p_version_str(enum lib9p_version ver) {
+ assert_ver(ver);
+ return _lib9p_table_ver[ver].name;
+}
+
+uint32_t lib9p_version_min_msg_size(enum lib9p_version ver) {
+ assert_ver(ver);
+ return _lib9p_table_ver[ver].min_msg_size;
+}
+
+const char *lib9p_msgtype_str(enum lib9p_version ver, enum lib9p_msg_type typ) {
+ assert_ver(ver);
+ assert_typ(typ);
+ return _lib9p_table_msg[ver][typ].name ?: const_byte_str(typ);
+}
+
+lo_interface fmt_formatter lo_box_lib9p_msg_as_fmt_formatter(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body) {
+ assert(ctx);
+ assert_ver(ctx->version);
+ assert_typ(typ);
+ assert(_lib9p_table_msg[ctx->version][typ].box_as_fmt_formatter);
+ return _lib9p_table_msg[ctx->version][typ].box_as_fmt_formatter(body);
+}
+
+/* main message functions *****************************************************/
+
+static
+ssize_t _lib9p_validate(uint8_t xxx_low_typ_bit,
+ const char *xxx_errmsg,
+ const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0x80],
+ struct lib9p_ctx *ctx, uint8_t *net_bytes) {
+ assert_ver(ctx->version);
+ /* Inspect the first 5 bytes ourselves. */
+ uint32_t net_size = uint32le_decode(net_bytes);
+ if (net_size < 5)
+ return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message is impossibly short");
+ uint8_t typ = net_bytes[4];
+ if (typ % 2 != xxx_low_typ_bit)
+ return lib9p_errorf(ctx, LIB9P_ERRNO_L_EOPNOTSUPP, "%s: message_type=%s", xxx_errmsg,
+ lib9p_msgtype_str(ctx->version, typ));
+ struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
+ if (!tentry.validate)
+ return lib9p_errorf(ctx, LIB9P_ERRNO_L_EOPNOTSUPP, "unknown message type: %s (protocol_version=%s)",
+ lib9p_msgtype_str(ctx->version, typ), lib9p_version_str(ctx->version));
+
+ /* Now use the message-type-specific tentry to process the whole thing. */
+ return tentry.validate(ctx, net_size, net_bytes);
+}
+
+ssize_t lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
+ return _lib9p_validate(0, "expected a T-message but got an R-message", _lib9p_table_Tmsg_recv,
+ ctx, net_bytes);
+}
+
+ssize_t lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
+ return _lib9p_validate(1, "expected an R-message but got a T-message", _lib9p_table_Rmsg_recv,
+ ctx, net_bytes);
+}
+
+static
+void _lib9p_unmarshal(const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0x80],
+ struct lib9p_ctx *ctx, uint8_t *net_bytes,
+ enum lib9p_msg_type *ret_typ, void *ret_body) {
+ assert_ver(ctx->version);
+ enum lib9p_msg_type typ = net_bytes[4];
+ *ret_typ = typ;
+ struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
+ assert(tentry.unmarshal);
+
+ tentry.unmarshal(ctx, net_bytes, ret_body);
+}
+
+void lib9p_Tmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
+ enum lib9p_msg_type *ret_typ, void *ret_body) {
+ _lib9p_unmarshal(_lib9p_table_Tmsg_recv,
+ ctx, net_bytes, ret_typ, ret_body);
+}
+
+void lib9p_Rmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
+ enum lib9p_msg_type *ret_typ, void *ret_body) {
+ _lib9p_unmarshal(_lib9p_table_Rmsg_recv,
+ ctx, net_bytes, ret_typ, ret_body);
+}
+
+static
+bool _lib9p_marshal(const struct _lib9p_send_tentry xxx_table[LIB9P_VER_NUM][0x80],
+ struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
+ size_t *ret_iov_cnt, struct iovec *ret_iov, uint8_t *ret_copied) {
+ assert_ver(ctx->version);
+ assert_typ(typ);
+ struct _marshal_ret ret = {
+ .net_iov_cnt = 1,
+ .net_iov = ret_iov,
+ .net_copied_size = 0,
+ .net_copied = ret_copied,
+ };
+ struct _lib9p_send_tentry tentry = xxx_table[ctx->version][typ/2];
+ assert(tentry.marshal);
+
+ bool ret_erred = tentry.marshal(ctx, body, &ret);
+ if (ret_iov[ret.net_iov_cnt-1].iov_len == 0)
+ ret.net_iov_cnt--;
+ *ret_iov_cnt = ret.net_iov_cnt;
+ return ret_erred;
+}
+
+bool lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
+ struct lib9p_Tmsg_send_buf *ret) {
+ assert(typ % 2 == 0);
+ memset(ret, 0, sizeof(*ret));
+ return _lib9p_marshal(_lib9p_table_Tmsg_send,
+ ctx, typ, body,
+ &ret->iov_cnt, ret->iov, ret->copied);
+}
+
+bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
+ struct lib9p_Rmsg_send_buf *ret) {
+ assert(typ % 2 == 1);
+ memset(ret, 0, sizeof(*ret));
+ return _lib9p_marshal(_lib9p_table_Rmsg_send,
+ ctx, typ, body,
+ &ret->iov_cnt, ret->iov, ret->copied);
+}
+
+/* `struct lib9p_stat` helpers ************************************************/
+
+#if _LIB9P_ENABLE_stat
+bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes,
+ uint32_t *ret_net_size, size_t *ret_host_size) {
+ ssize_t host_size = _lib9p_stat_validate(ctx, net_size, net_bytes, ret_net_size);
+ if (host_size < 0)
+ return true;
+ if (ret_host_size)
+ *ret_host_size = (size_t)host_size;
+ return false;
+}
+
+void lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
+ struct lib9p_stat *ret) {
+ _lib9p_stat_unmarshal(ctx, net_bytes, ret);
+}
+
+uint32_t lib9p_stat_marshal(struct lib9p_ctx *ctx, uint32_t max_net_size, struct lib9p_stat *obj,
+ uint8_t *ret_bytes) {
+ struct lib9p_ctx _ctx = *ctx;
+ _ctx.max_msg_size = max_net_size;
+
+ struct iovec iov = {0};
+ struct _marshal_ret ret = {
+ .net_iov_cnt = 1,
+ .net_iov = &iov,
+ .net_copied_size = 0,
+ .net_copied = ret_bytes,
+ };
+ if (_lib9p_stat_marshal(&_ctx, obj, &ret))
+ return 0;
+ return ret.net_iov[0].iov_len;
+}
+#endif
diff --git a/lib9p/core_include/lib9p/core.h b/lib9p/core_include/lib9p/core.h
index 38f3934..2dfda27 100644
--- a/lib9p/core_include/lib9p/core.h
+++ b/lib9p/core_include/lib9p/core.h
@@ -56,31 +56,23 @@ void lib9p_ctx_clear_error(struct lib9p_ctx *ctx);
bool lib9p_ctx_has_error(struct lib9p_ctx *ctx);
-/** Write an static error into ctx, return -1. */
-int lib9p_error(struct lib9p_ctx *ctx,
+/* NB: This __VA_ARGS__ definition of lib9p_errorf() is handy because it
+ * will produce an error if .../__VA_ARGS__ is empty; which means that
+ * it should be lib9p_error() instead! */
#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L
- lib9p_errno_t linux_errno,
-#endif
- char const *msg);
-/** Write a printf-style error into ctx, return -1. */
-int lib9p_errorf(struct lib9p_ctx *ctx,
-#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L
- lib9p_errno_t linux_errno,
-#endif
- char const *fmt, ...)
-#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L
- [[gnu::format(printf, 3, 4)]]
-#else
- [[gnu::format(printf, 2, 3)]]
-#endif
- ;
-
-#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L
-/* Detect things that should be just lib9p_error() */
-#define lib9p_errorf(ctx, errnum, fmt, ...) lib9p_errorf(ctx, errnum, fmt, __VA_ARGS__)
+ int _lib9p_error(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *msg);
+ int _lib9p_errorf(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *fmt, ...) [[gnu::format(printf, 3, 4)]];
+ /** Write an static error into ctx, return -1. */
+ #define lib9p_error(ctx, errnum, errmsg) _lib9p_error(ctx, errnum, errmsg)
+ /** Write a printf-style error into ctx, return -1. */
+ #define lib9p_errorf(ctx, errnum, fmt, ...) _lib9p_errorf(ctx, errnum, fmt, __VA_ARGS__)
#else
-#define lib9p_errorf(ctx, errnum, fmt, ...) lib9p_errorf(ctx, fmt, __VA_ARGS__)
-#define lib9p_error(ctx, errnum, errmsg) lib9p_error(ctx, errmsg)
+ int _lib9p_error(struct lib9p_ctx *ctx, char const *msg);
+ int _lib9p_errorf(struct lib9p_ctx *ctx, char const *fmt, ...) [[gnu::format(printf, 2, 3)]];
+ /** Write an static error into ctx, return -1. */
+ #define lib9p_error(ctx, errnum, errmsg) _lib9p_error(ctx, errmsg)
+ /** Write a printf-style error into ctx, return -1. */
+ #define lib9p_errorf(ctx, errnum, fmt, ...) _lib9p_errorf(ctx, fmt, __VA_ARGS__)
#endif
/* misc utilities *************************************************************/
diff --git a/lib9p/core_tables.c b/lib9p/core_tables.c
deleted file mode 100644
index bc452c7..0000000
--- a/lib9p/core_tables.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/* lib9p/core_tables.c - Access tables of version and message information
- *
- * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#include <string.h>
-
-#include <libmisc/endian.h>
-#include <libmisc/log.h> /* for const_byte_str() */
-
-#include "core_tables.h"
-
-/* bounds checks **************************************************************/
-
-static inline void assert_ver(enum lib9p_version ver) {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wtype-limits"
- assert(0 <= ver && ver < LIB9P_VER_NUM);
-#pragma GCC diagnostic pop
-}
-
-static inline void assert_typ(enum lib9p_msg_type typ) {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wtype-limits"
- assert(0 <= typ && typ < 0xFF);
-#pragma GCC diagnostic pop
-}
-
-/* simple lookups *************************************************************/
-
-const char *lib9p_version_str(enum lib9p_version ver) {
- assert_ver(ver);
- return _lib9p_table_ver[ver].name;
-}
-
-uint32_t lib9p_version_min_msg_size(enum lib9p_version ver) {
- assert_ver(ver);
- return _lib9p_table_ver[ver].min_msg_size;
-}
-
-const char *lib9p_msgtype_str(enum lib9p_version ver, enum lib9p_msg_type typ) {
- assert_ver(ver);
- assert_typ(typ);
- return _lib9p_table_msg[ver][typ].name ?: const_byte_str(typ);
-}
-
-lo_interface fmt_formatter lo_box_lib9p_msg_as_fmt_formatter(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body) {
- assert(ctx);
- assert_ver(ctx->version);
- assert_typ(typ);
- assert(_lib9p_table_msg[ctx->version][typ].box_as_fmt_formatter);
- return _lib9p_table_msg[ctx->version][typ].box_as_fmt_formatter(body);
-}
-
-/* main message functions *****************************************************/
-
-static
-ssize_t _lib9p_validate(uint8_t xxx_low_typ_bit,
- const char *xxx_errmsg,
- const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0x80],
- struct lib9p_ctx *ctx, uint8_t *net_bytes) {
- assert_ver(ctx->version);
- /* Inspect the first 5 bytes ourselves. */
- uint32_t net_size = uint32le_decode(net_bytes);
- if (net_size < 5)
- return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message is impossibly short");
- uint8_t typ = net_bytes[4];
- if (typ % 2 != xxx_low_typ_bit)
- return lib9p_errorf(ctx, LIB9P_ERRNO_L_EOPNOTSUPP, "%s: message_type=%s", xxx_errmsg,
- lib9p_msgtype_str(ctx->version, typ));
- struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
- if (!tentry.validate)
- return lib9p_errorf(ctx, LIB9P_ERRNO_L_EOPNOTSUPP, "unknown message type: %s (protocol_version=%s)",
- lib9p_msgtype_str(ctx->version, typ), lib9p_version_str(ctx->version));
-
- /* Now use the message-type-specific tentry to process the whole thing. */
- return tentry.validate(ctx, net_size, net_bytes);
-}
-
-ssize_t lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
- return _lib9p_validate(0, "expected a T-message but got an R-message", _lib9p_table_Tmsg_recv,
- ctx, net_bytes);
-}
-
-ssize_t lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) {
- return _lib9p_validate(1, "expected an R-message but got a T-message", _lib9p_table_Rmsg_recv,
- ctx, net_bytes);
-}
-
-static
-void _lib9p_unmarshal(const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0x80],
- struct lib9p_ctx *ctx, uint8_t *net_bytes,
- enum lib9p_msg_type *ret_typ, void *ret_body) {
- assert_ver(ctx->version);
- enum lib9p_msg_type typ = net_bytes[4];
- *ret_typ = typ;
- struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
- assert(tentry.unmarshal);
-
- tentry.unmarshal(ctx, net_bytes, ret_body);
-}
-
-void lib9p_Tmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
- enum lib9p_msg_type *ret_typ, void *ret_body) {
- _lib9p_unmarshal(_lib9p_table_Tmsg_recv,
- ctx, net_bytes, ret_typ, ret_body);
-}
-
-void lib9p_Rmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
- enum lib9p_msg_type *ret_typ, void *ret_body) {
- _lib9p_unmarshal(_lib9p_table_Rmsg_recv,
- ctx, net_bytes, ret_typ, ret_body);
-}
-
-static
-bool _lib9p_marshal(const struct _lib9p_send_tentry xxx_table[LIB9P_VER_NUM][0x80],
- struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
- size_t *ret_iov_cnt, struct iovec *ret_iov, uint8_t *ret_copied) {
- assert_ver(ctx->version);
- assert_typ(typ);
- struct _marshal_ret ret = {
- .net_iov_cnt = 1,
- .net_iov = ret_iov,
- .net_copied_size = 0,
- .net_copied = ret_copied,
- };
- struct _lib9p_send_tentry tentry = xxx_table[ctx->version][typ/2];
- assert(tentry.marshal);
-
- bool ret_erred = tentry.marshal(ctx, body, &ret);
- if (ret_iov[ret.net_iov_cnt-1].iov_len == 0)
- ret.net_iov_cnt--;
- *ret_iov_cnt = ret.net_iov_cnt;
- return ret_erred;
-}
-
-bool lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
- struct lib9p_Tmsg_send_buf *ret) {
- assert(typ % 2 == 0);
- memset(ret, 0, sizeof(*ret));
- return _lib9p_marshal(_lib9p_table_Tmsg_send,
- ctx, typ, body,
- &ret->iov_cnt, ret->iov, ret->copied);
-}
-
-bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body,
- struct lib9p_Rmsg_send_buf *ret) {
- assert(typ % 2 == 1);
- memset(ret, 0, sizeof(*ret));
- return _lib9p_marshal(_lib9p_table_Rmsg_send,
- ctx, typ, body,
- &ret->iov_cnt, ret->iov, ret->copied);
-}
-
-/* `struct lib9p_stat` helpers ************************************************/
-
-#if _LIB9P_ENABLE_stat
-bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes,
- uint32_t *ret_net_size, size_t *ret_host_size) {
- ssize_t host_size = _lib9p_stat_validate(ctx, net_size, net_bytes, ret_net_size);
- if (host_size < 0)
- return true;
- if (ret_host_size)
- *ret_host_size = (size_t)host_size;
- return false;
-}
-
-void lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes,
- struct lib9p_stat *ret) {
- _lib9p_stat_unmarshal(ctx, net_bytes, ret);
-}
-
-uint32_t lib9p_stat_marshal(struct lib9p_ctx *ctx, uint32_t max_net_size, struct lib9p_stat *obj,
- uint8_t *ret_bytes) {
- struct lib9p_ctx _ctx = *ctx;
- _ctx.max_msg_size = max_net_size;
-
- struct iovec iov = {0};
- struct _marshal_ret ret = {
- .net_iov_cnt = 1,
- .net_iov = &iov,
- .net_copied_size = 0,
- .net_copied = ret_bytes,
- };
- if (_lib9p_stat_marshal(&_ctx, obj, &ret))
- return 0;
- return ret.net_iov[0].iov_len;
-}
-#endif