diff options
Diffstat (limited to 'lib9p')
63 files changed, 15672 insertions, 9102 deletions
diff --git a/lib9p/9p.c b/lib9p/9p.c deleted file mode 100644 index c11bcd6..0000000 --- a/lib9p/9p.c +++ /dev/null @@ -1,244 +0,0 @@ -/* lib9p/9p.c - Base 9P protocol utilities for both clients and servers - * - * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-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() */ - -#define LOG_NAME 9P -#include <libmisc/log.h> /* for const_byte_str() */ - -#include <lib9p/9p.h> - -#include "internal.h" - -/* strings ********************************************************************/ - -const char *lib9p_version_str(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 - return _lib9p_table_ver_name[ver]; -} - -const char *lib9p_msgtype_str(enum lib9p_version ver, enum lib9p_msg_type typ) { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" - assert(0 <= ver && ver < LIB9P_VER_NUM); - assert(0 <= typ && typ <= 0xFF); -#pragma GCC diagnostic pop - return _lib9p_table_msg_name[ver][typ] ?: const_byte_str(typ); -} - -struct lib9p_s lib9p_str(char *s) { - if (!s) - return (struct lib9p_s){0}; - return (struct lib9p_s){ - .len = strlen(s), - .utf8 = s, - }; -} -struct lib9p_s lib9p_strn(char *s, size_t maxlen) { - if (maxlen == 0 || !s) - return (struct lib9p_s){0}; - return (struct lib9p_s){ - .len = strnlen(s, maxlen), - .utf8 = s, - }; -} -struct lib9p_s lib9p_str_slice(struct lib9p_s s, uint16_t beg, uint16_t end) { - assert(s.len == 0 || s.utf8); - assert(beg <= end && end <= s.len); - return (struct lib9p_s){ - .len = end - beg, - .utf8 = &s.utf8[beg], - }; -} -bool lib9p_str_eq(struct lib9p_s a, struct lib9p_s b) { - return a.len == b.len && - (a.len == 0 || memcmp(a.utf8, b.utf8, a.len) == 0); -} - -/* ctx ************************************************************************/ - -void lib9p_ctx_clear_error(struct lib9p_ctx *ctx) { - assert(ctx); -#if CONFIG_9P_ENABLE_9P2000_u - ctx->err_num = 0; -#endif - ctx->err_msg[0] = '\0'; -} - -bool lib9p_ctx_has_error(struct lib9p_ctx *ctx) { - assert(ctx); - return ctx->err_msg[0]; -} - -int lib9p_error(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *msg) { - if (lib9p_ctx_has_error(ctx)) - return -1; - strncpy(ctx->err_msg, msg, sizeof(ctx->err_msg)); - ctx->err_msg[sizeof(ctx->err_msg)-1] = '\0'; - -#if CONFIG_9P_ENABLE_9P2000_u - ctx->err_num = linux_errno; -#else - (void)(linux_errno); -#endif - - return -1; -} - -int lib9p_errorf(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *fmt, ...) { - int n; - va_list args; - - if (lib9p_ctx_has_error(ctx)) - return -1; - 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)); - -#if CONFIG_9P_ENABLE_9P2000_u - ctx->err_num = linux_errno; -#else - (void)(linux_errno); -#endif - - return -1; -} - -/* 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) { - /* Inspect the first 5 bytes ourselves. */ - uint32_t net_size = uint32le_decode(net_bytes); - if (net_size < 5) - return lib9p_error(ctx, LINUX_EBADMSG, "message is impossibly short"); - uint8_t typ = net_bytes[4]; - if (typ % 2 != xxx_low_typ_bit) - return lib9p_errorf(ctx, LINUX_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, LINUX_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) { - enum lib9p_msg_type typ = net_bytes[4]; - *ret_typ = typ; - struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2]; - - 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) { - 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]; - 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 ************************************************/ - -bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, - uint32_t *ret_net_size, ssize_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 = 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; -} diff --git a/lib9p/9p.generated.c b/lib9p/9p.generated.c deleted file mode 100644 index 6726084..0000000 --- a/lib9p/9p.generated.c +++ /dev/null @@ -1,5238 +0,0 @@ -/* Generated by `lib9p/proto.gen lib9p/idl/2002-9P2000.9p lib9p/idl/2003-9P2000.p9p.9p lib9p/idl/2005-9P2000.u.9p lib9p/idl/2010-9P2000.L.9p lib9p/idl/2012-9P2000.e.9p`. DO NOT EDIT! */ - -#include <stdbool.h> -#include <stddef.h> /* for size_t */ -#include <inttypes.h> /* for PRI* macros */ -#include <string.h> /* for memset() */ - -#include <libmisc/assert.h> - -#include <lib9p/9p.h> - -#include "internal.h" - -/* utilities ******************************************************************/ -#if CONFIG_9P_ENABLE_9P2000 - #define _is_ver_9P2000(v) (v == LIB9P_VER_9P2000) -#else - #define _is_ver_9P2000(v) false -#endif -#if CONFIG_9P_ENABLE_9P2000_L - #define _is_ver_9P2000_L(v) (v == LIB9P_VER_9P2000_L) -#else - #define _is_ver_9P2000_L(v) false -#endif -#if CONFIG_9P_ENABLE_9P2000_e - #define _is_ver_9P2000_e(v) (v == LIB9P_VER_9P2000_e) -#else - #define _is_ver_9P2000_e(v) false -#endif -#if CONFIG_9P_ENABLE_9P2000_p9p - #define _is_ver_9P2000_p9p(v) (v == LIB9P_VER_9P2000_p9p) -#else - #define _is_ver_9P2000_p9p(v) false -#endif -#if CONFIG_9P_ENABLE_9P2000_u - #define _is_ver_9P2000_u(v) (v == LIB9P_VER_9P2000_u) -#else - #define _is_ver_9P2000_u(v) false -#endif - -/** - * is_ver(ctx, ver) is essentially `(ctx->version == LIB9P_VER_##ver)`, but - * compiles correctly (to `false`) even if `LIB9P_VER_##ver` isn't defined - * (because `!CONFIG_9P_ENABLE_##ver`). This is useful when `||`ing - * several version checks together. - */ -#define is_ver(ctx, ver) _is_ver_##ver((ctx)->version) - -/* strings ********************************************************************/ - -const char *const _lib9p_table_ver_name[LIB9P_VER_NUM] = { - [LIB9P_VER_unknown] = "unknown", -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = "9P2000", -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = "9P2000.L", -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = "9P2000.e", -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = "9P2000.p9p", -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = "9P2000.u", -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -#define _MSG_NAME(typ) [LIB9P_TYP_##typ] = #typ -const char *const _lib9p_table_msg_name[LIB9P_VER_NUM][0x100] = { - [LIB9P_VER_unknown] = { - _MSG_NAME(Tversion), - _MSG_NAME(Rversion), - _MSG_NAME(Rerror), - }, -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = { - _MSG_NAME(Tversion), - _MSG_NAME(Rversion), - _MSG_NAME(Tauth), - _MSG_NAME(Rauth), - _MSG_NAME(Tattach), - _MSG_NAME(Rattach), - _MSG_NAME(Rerror), - _MSG_NAME(Tflush), - _MSG_NAME(Rflush), - _MSG_NAME(Twalk), - _MSG_NAME(Rwalk), - _MSG_NAME(Topen), - _MSG_NAME(Ropen), - _MSG_NAME(Tcreate), - _MSG_NAME(Rcreate), - _MSG_NAME(Tread), - _MSG_NAME(Rread), - _MSG_NAME(Twrite), - _MSG_NAME(Rwrite), - _MSG_NAME(Tclunk), - _MSG_NAME(Rclunk), - _MSG_NAME(Tremove), - _MSG_NAME(Rremove), - _MSG_NAME(Tstat), - _MSG_NAME(Rstat), - _MSG_NAME(Twstat), - _MSG_NAME(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = { - _MSG_NAME(Rlerror), - _MSG_NAME(Tstatfs), - _MSG_NAME(Rstatfs), - _MSG_NAME(Tlopen), - _MSG_NAME(Rlopen), - _MSG_NAME(Tlcreate), - _MSG_NAME(Rlcreate), - _MSG_NAME(Tsymlink), - _MSG_NAME(Rsymlink), - _MSG_NAME(Tmknod), - _MSG_NAME(Rmknod), - _MSG_NAME(Trename), - _MSG_NAME(Rrename), - _MSG_NAME(Treadlink), - _MSG_NAME(Rreadlink), - _MSG_NAME(Tgetattr), - _MSG_NAME(Rgetattr), - _MSG_NAME(Tsetattr), - _MSG_NAME(Rsetattr), - _MSG_NAME(Txattrwalk), - _MSG_NAME(Rxattrwalk), - _MSG_NAME(Txattrcreate), - _MSG_NAME(Rxattrcreate), - _MSG_NAME(Treaddir), - _MSG_NAME(Rreaddir), - _MSG_NAME(Tfsync), - _MSG_NAME(Rfsync), - _MSG_NAME(Tlock), - _MSG_NAME(Rlock), - _MSG_NAME(Tgetlock), - _MSG_NAME(Rgetlock), - _MSG_NAME(Tlink), - _MSG_NAME(Rlink), - _MSG_NAME(Tmkdir), - _MSG_NAME(Rmkdir), - _MSG_NAME(Trenameat), - _MSG_NAME(Rrenameat), - _MSG_NAME(Tunlinkat), - _MSG_NAME(Runlinkat), - _MSG_NAME(Tversion), - _MSG_NAME(Rversion), - _MSG_NAME(Tauth), - _MSG_NAME(Rauth), - _MSG_NAME(Tattach), - _MSG_NAME(Rattach), - _MSG_NAME(Rerror), - _MSG_NAME(Tflush), - _MSG_NAME(Rflush), - _MSG_NAME(Twalk), - _MSG_NAME(Rwalk), - _MSG_NAME(Tread), - _MSG_NAME(Rread), - _MSG_NAME(Twrite), - _MSG_NAME(Rwrite), - _MSG_NAME(Tclunk), - _MSG_NAME(Rclunk), - _MSG_NAME(Tremove), - _MSG_NAME(Rremove), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = { - _MSG_NAME(Tversion), - _MSG_NAME(Rversion), - _MSG_NAME(Tauth), - _MSG_NAME(Rauth), - _MSG_NAME(Tattach), - _MSG_NAME(Rattach), - _MSG_NAME(Rerror), - _MSG_NAME(Tflush), - _MSG_NAME(Rflush), - _MSG_NAME(Twalk), - _MSG_NAME(Rwalk), - _MSG_NAME(Topen), - _MSG_NAME(Ropen), - _MSG_NAME(Tcreate), - _MSG_NAME(Rcreate), - _MSG_NAME(Tread), - _MSG_NAME(Rread), - _MSG_NAME(Twrite), - _MSG_NAME(Rwrite), - _MSG_NAME(Tclunk), - _MSG_NAME(Rclunk), - _MSG_NAME(Tremove), - _MSG_NAME(Rremove), - _MSG_NAME(Tstat), - _MSG_NAME(Rstat), - _MSG_NAME(Twstat), - _MSG_NAME(Rwstat), - _MSG_NAME(Tsession), - _MSG_NAME(Rsession), - _MSG_NAME(Tsread), - _MSG_NAME(Rsread), - _MSG_NAME(Tswrite), - _MSG_NAME(Rswrite), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = { - _MSG_NAME(Topenfd), - _MSG_NAME(Ropenfd), - _MSG_NAME(Tversion), - _MSG_NAME(Rversion), - _MSG_NAME(Tauth), - _MSG_NAME(Rauth), - _MSG_NAME(Tattach), - _MSG_NAME(Rattach), - _MSG_NAME(Rerror), - _MSG_NAME(Tflush), - _MSG_NAME(Rflush), - _MSG_NAME(Twalk), - _MSG_NAME(Rwalk), - _MSG_NAME(Topen), - _MSG_NAME(Ropen), - _MSG_NAME(Tcreate), - _MSG_NAME(Rcreate), - _MSG_NAME(Tread), - _MSG_NAME(Rread), - _MSG_NAME(Twrite), - _MSG_NAME(Rwrite), - _MSG_NAME(Tclunk), - _MSG_NAME(Rclunk), - _MSG_NAME(Tremove), - _MSG_NAME(Rremove), - _MSG_NAME(Tstat), - _MSG_NAME(Rstat), - _MSG_NAME(Twstat), - _MSG_NAME(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = { - _MSG_NAME(Tversion), - _MSG_NAME(Rversion), - _MSG_NAME(Tauth), - _MSG_NAME(Rauth), - _MSG_NAME(Tattach), - _MSG_NAME(Rattach), - _MSG_NAME(Rerror), - _MSG_NAME(Tflush), - _MSG_NAME(Rflush), - _MSG_NAME(Twalk), - _MSG_NAME(Rwalk), - _MSG_NAME(Topen), - _MSG_NAME(Ropen), - _MSG_NAME(Tcreate), - _MSG_NAME(Rcreate), - _MSG_NAME(Tread), - _MSG_NAME(Rread), - _MSG_NAME(Twrite), - _MSG_NAME(Rwrite), - _MSG_NAME(Tclunk), - _MSG_NAME(Rclunk), - _MSG_NAME(Tremove), - _MSG_NAME(Rremove), - _MSG_NAME(Tstat), - _MSG_NAME(Rstat), - _MSG_NAME(Twstat), - _MSG_NAME(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -/* bitmasks *******************************************************************/ - -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static const lib9p_dm_t dm_masks[LIB9P_VER_NUM] = { -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 0b11101100000000000000000111111111, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 0b11101100000000000000000111111111, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 0b11101100000000000000000111111111, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 0b11101100101111000000000111111111, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static const lib9p_qt_t qt_masks[LIB9P_VER_NUM] = { -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 0b11101100, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = 0b11101100, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 0b11101100, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 0b11101100, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 0b11101110, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static const lib9p_o_t o_masks[LIB9P_VER_NUM] = { -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 0b01010011, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = 0b00000000, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 0b01010011, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 0b01010011, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 0b01010011, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L -static const lib9p_lo_t lo_masks[LIB9P_VER_NUM] = { -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000 */ - [LIB9P_VER_9P2000_L] = 0b00000000000111111111111111000011, -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -static const lib9p_mode_t mode_masks[LIB9P_VER_NUM] = { -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000 */ - [LIB9P_VER_9P2000_L] = 0b00000000000000001111111111111111, -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -static const lib9p_getattr_t getattr_masks[LIB9P_VER_NUM] = { -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 0b0000000000000000000000000000000000000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000 */ - [LIB9P_VER_9P2000_L] = 0b0000000000000000000000000000000000000000000000000011111111111111, -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 0b0000000000000000000000000000000000000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 0b0000000000000000000000000000000000000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 0b0000000000000000000000000000000000000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -static const lib9p_setattr_t setattr_masks[LIB9P_VER_NUM] = { -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000 */ - [LIB9P_VER_9P2000_L] = 0b00000000000000000000000111111111, -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -static const lib9p_lock_flags_t lock_flags_masks[LIB9P_VER_NUM] = { -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000 */ - [LIB9P_VER_9P2000_L] = 0b00000000000000000000000000000011, -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 0b00000000000000000000000000000000, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; -#endif /* CONFIG_9P_ENABLE_9P2000_L */ - -/* validate_* *****************************************************************/ - -#define VALIDATE_NET_BYTES(n) \ - if (__builtin_add_overflow(net_offset, n, &net_offset)) \ - /* If needed-net-size overflowed uint32_t, then \ - * there's no way that actual-net-size will live up to \ - * that. */ \ - return lib9p_error(ctx, LINUX_EBADMSG, "message is too short for content"); \ - if (net_offset > net_size) \ - return lib9p_errorf(ctx, LINUX_EBADMSG, "message is too short for content (%"PRIu32" > %"PRIu32") @ %d", net_offset, net_size, __LINE__); -#define VALIDATE_NET_UTF8(n) \ - { \ - size_t len = n; \ - VALIDATE_NET_BYTES(len); \ - if (!is_valid_utf8_without_nul(&net_bytes[net_offset-len], len)) \ - return lib9p_error(ctx, LINUX_EBADMSG, "message contains invalid UTF-8"); \ - } -#define RESERVE_HOST_BYTES(n) \ - if (__builtin_add_overflow(host_size, n, &host_size)) \ - /* If needed-host-size overflowed ssize_t, then there's \ - * no way that actual-net-size will live up to \ - * that. */ \ - return lib9p_error(ctx, LINUX_EBADMSG, "message is too short for content"); -#define GET_U8LE(off) (net_bytes[off]) -#define GET_U16LE(off) uint16le_decode(&net_bytes[off]) -#define GET_U32LE(off) uint32le_decode(&net_bytes[off]) -#define GET_U64LE(off) uint64le_decode(&net_bytes[off]) -#define LAST_U8LE() GET_U8LE(net_offset-1) -#define LAST_U16LE() GET_U16LE(net_offset-2) -#define LAST_U32LE() GET_U32LE(net_offset-4) -#define LAST_U64LE() GET_U64LE(net_offset-8) - -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_stat); - uint32_t offsetof_stat_size = net_offset + 0; - uint32_t offsetof_kern_type = net_offset + 2; - uint32_t offsetof_file_qid_type = net_offset + 8; - VALIDATE_NET_BYTES(21); - if (GET_U8LE(offsetof_file_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_file_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_file_mode = net_offset + 0; - VALIDATE_NET_BYTES(22); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(12); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_stat_size) != (uint32_t)(offsetof_end - offsetof_kern_type)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "stat->stat_size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_stat_size), (uint32_t)(offsetof_end - offsetof_kern_type)); - if (GET_U32LE(offsetof_file_mode) & ~dm_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in dm bitfield: %#08"PRIx32, - GET_U32LE(offsetof_file_mode) & ~dm_masks[ctx->version]); - if (ret_net_size) - *ret_net_size = net_offset; - return (ssize_t)host_size; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Tversion(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tversion); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tversion->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(100)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tversion->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(100)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rversion(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rversion); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rversion->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(101)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rversion->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(101)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tauth(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tauth); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { - VALIDATE_NET_BYTES(4); - } -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tauth->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(102)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tauth->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(102)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rauth(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rauth); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_aqid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_aqid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_aqid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rauth->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(103)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rauth->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(103)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tattach(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tattach); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(17); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { - VALIDATE_NET_BYTES(4); - } -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tattach->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(104)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tattach->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(104)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rattach(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rattach); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rattach->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(105)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rattach->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(105)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rerror(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rerror); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(9); - VALIDATE_NET_UTF8(LAST_U16LE()); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - VALIDATE_NET_BYTES(4); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rerror->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(107)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rerror->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(107)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tflush(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tflush); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 9; - VALIDATE_NET_BYTES(9); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tflush->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(108)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tflush->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(108)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rflush(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rflush); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rflush->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(109)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rflush->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(109)); - return (ssize_t)host_size; -} - -static ssize_t validate_Twalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Twalk); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_nwname = net_offset + 15; - VALIDATE_NET_BYTES(17); - for (uint16_t i = 0, cnt = LAST_U16LE(); i < cnt; i++) { - RESERVE_HOST_BYTES(sizeof(struct lib9p_s)); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - } - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twalk->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(110)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twalk->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(110)); - if ((uint16_t)GET_U16LE(offsetof_nwname) > (uint16_t)(16)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twalk->nwname value is too large: %"PRIu16" > %"PRIu16, - (uint16_t)GET_U16LE(offsetof_nwname), (uint16_t)(16)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rwalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rwalk); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_nwqid = net_offset + 7; - VALIDATE_NET_BYTES(9); - for (uint16_t i = 0, cnt = LAST_U16LE(); i < cnt; i++) { - RESERVE_HOST_BYTES(sizeof(struct lib9p_qid)); - uint32_t offsetof_wqid_type = net_offset + 0; - VALIDATE_NET_BYTES(13); - if (GET_U8LE(offsetof_wqid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_wqid_type) & ~qt_masks[ctx->version]); - } - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rwalk->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(111)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rwalk->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(111)); - if ((uint16_t)GET_U16LE(offsetof_nwqid) > (uint16_t)(16)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rwalk->nwqid value is too large: %"PRIu16" > %"PRIu16, - (uint16_t)GET_U16LE(offsetof_nwqid), (uint16_t)(16)); - return (ssize_t)host_size; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Topen(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Topen); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_mode = net_offset + 11; - uint32_t offsetof_end = net_offset + 12; - VALIDATE_NET_BYTES(12); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Topen->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(112)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Topen->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(112)); - if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in o bitfield: %#02"PRIx8, - GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Ropen(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Ropen); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 4; - VALIDATE_NET_BYTES(4); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Ropen->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(113)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Ropen->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(113)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tcreate); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_perm = net_offset + 0; - uint32_t offsetof_mode = net_offset + 4; - uint32_t offsetof_end = net_offset + 5; - VALIDATE_NET_BYTES(5); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tcreate->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(114)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tcreate->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(114)); - if (GET_U32LE(offsetof_perm) & ~dm_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in dm bitfield: %#08"PRIx32, - GET_U32LE(offsetof_perm) & ~dm_masks[ctx->version]); - if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in o bitfield: %#02"PRIx8, - GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Rcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rcreate); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 4; - VALIDATE_NET_BYTES(4); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rcreate->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(115)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rcreate->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(115)); - return (ssize_t)host_size; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Tread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tread); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_offset = net_offset + 11; - uint32_t offsetof_count = net_offset + 19; - uint32_t offsetof_end = net_offset + 23; - VALIDATE_NET_BYTES(23); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tread->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(116)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tread->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(116)); - if ((uint64_t)GET_U64LE(offsetof_offset) > (uint64_t)(INT64_MAX)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tread->offset value is too large: %"PRIu64" > %"PRIu64, - (uint64_t)GET_U64LE(offsetof_offset), (uint64_t)(INT64_MAX)); - if ((uint32_t)GET_U32LE(offsetof_count) > (uint32_t)(INT32_MAX)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tread->count value is too large: %"PRIu32" > %"PRIu32, - (uint32_t)GET_U32LE(offsetof_count), (uint32_t)(INT32_MAX)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rread); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_count = net_offset + 7; - VALIDATE_NET_BYTES(11); - VALIDATE_NET_BYTES(LAST_U32LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rread->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(117)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rread->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(117)); - if ((uint32_t)GET_U32LE(offsetof_count) > (uint32_t)(INT32_MAX)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rread->count value is too large: %"PRIu32" > %"PRIu32, - (uint32_t)GET_U32LE(offsetof_count), (uint32_t)(INT32_MAX)); - return (ssize_t)host_size; -} - -static ssize_t validate_Twrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Twrite); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_offset = net_offset + 11; - uint32_t offsetof_count = net_offset + 19; - VALIDATE_NET_BYTES(23); - VALIDATE_NET_BYTES(LAST_U32LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twrite->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(118)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twrite->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(118)); - if ((uint64_t)GET_U64LE(offsetof_offset) > (uint64_t)(INT64_MAX)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twrite->offset value is too large: %"PRIu64" > %"PRIu64, - (uint64_t)GET_U64LE(offsetof_offset), (uint64_t)(INT64_MAX)); - if ((uint32_t)GET_U32LE(offsetof_count) > (uint32_t)(INT32_MAX)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twrite->count value is too large: %"PRIu32" > %"PRIu32, - (uint32_t)GET_U32LE(offsetof_count), (uint32_t)(INT32_MAX)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rwrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rwrite); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_count = net_offset + 7; - uint32_t offsetof_end = net_offset + 11; - VALIDATE_NET_BYTES(11); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rwrite->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(119)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rwrite->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(119)); - if ((uint32_t)GET_U32LE(offsetof_count) > (uint32_t)(INT32_MAX)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rwrite->count value is too large: %"PRIu32" > %"PRIu32, - (uint32_t)GET_U32LE(offsetof_count), (uint32_t)(INT32_MAX)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tclunk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tclunk); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 11; - VALIDATE_NET_BYTES(11); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tclunk->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(120)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tclunk->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(120)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rclunk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rclunk); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rclunk->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(121)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rclunk->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(121)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tremove(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tremove); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 11; - VALIDATE_NET_BYTES(11); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tremove->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(122)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tremove->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(122)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rremove(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rremove); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rremove->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(123)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rremove->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(123)); - return (ssize_t)host_size; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Tstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tstat); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 11; - VALIDATE_NET_BYTES(11); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tstat->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(124)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tstat->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(124)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rstat); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_nstat = net_offset + 7; - uint32_t offsetof_stat = net_offset + 9; - uint32_t offsetof_stat_stat_size = net_offset + 9; - uint32_t offsetof_stat_kern_type = net_offset + 11; - uint32_t offsetof_stat_file_qid_type = net_offset + 17; - VALIDATE_NET_BYTES(30); - if (GET_U8LE(offsetof_stat_file_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_stat_file_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_stat_file_mode = net_offset + 0; - VALIDATE_NET_BYTES(22); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(12); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - uint32_t offsetof_stat_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_stat_stat_size) != (uint32_t)(offsetof_stat_end - offsetof_stat_kern_type)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rstat->stat.stat_size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_stat_stat_size), (uint32_t)(offsetof_stat_end - offsetof_stat_kern_type)); - if (GET_U32LE(offsetof_stat_file_mode) & ~dm_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in dm bitfield: %#08"PRIx32, - GET_U32LE(offsetof_stat_file_mode) & ~dm_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rstat->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(125)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rstat->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(125)); - if ((uint32_t)GET_U32LE(offsetof_nstat) != (uint32_t)(offsetof_end - offsetof_stat)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rstat->nstat value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_nstat), (uint32_t)(offsetof_end - offsetof_stat)); - return (ssize_t)host_size; -} - -static ssize_t validate_Twstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Twstat); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_nstat = net_offset + 11; - uint32_t offsetof_stat = net_offset + 13; - uint32_t offsetof_stat_stat_size = net_offset + 13; - uint32_t offsetof_stat_kern_type = net_offset + 15; - uint32_t offsetof_stat_file_qid_type = net_offset + 21; - VALIDATE_NET_BYTES(34); - if (GET_U8LE(offsetof_stat_file_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_stat_file_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_stat_file_mode = net_offset + 0; - VALIDATE_NET_BYTES(22); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(12); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - uint32_t offsetof_stat_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_stat_stat_size) != (uint32_t)(offsetof_stat_end - offsetof_stat_kern_type)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twstat->stat.stat_size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_stat_stat_size), (uint32_t)(offsetof_stat_end - offsetof_stat_kern_type)); - if (GET_U32LE(offsetof_stat_file_mode) & ~dm_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in dm bitfield: %#08"PRIx32, - GET_U32LE(offsetof_stat_file_mode) & ~dm_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twstat->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(126)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twstat->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(126)); - if ((uint32_t)GET_U32LE(offsetof_nstat) != (uint32_t)(offsetof_end - offsetof_stat)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Twstat->nstat value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_nstat), (uint32_t)(offsetof_end - offsetof_stat)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rwstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rwstat); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rwstat->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(127)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rwstat->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(127)); - return (ssize_t)host_size; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_p9p -static ssize_t validate_Topenfd(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Topenfd); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_mode = net_offset + 11; - uint32_t offsetof_end = net_offset + 12; - VALIDATE_NET_BYTES(12); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Topenfd->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(98)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Topenfd->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(98)); - if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in o bitfield: %#02"PRIx8, - GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Ropenfd(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Ropenfd); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 8; - VALIDATE_NET_BYTES(8); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Ropenfd->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(99)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Ropenfd->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(99)); - return (ssize_t)host_size; -} - -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_L -static ssize_t validate_Rlerror(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlerror); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 11; - VALIDATE_NET_BYTES(11); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlerror->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(7)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlerror->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(7)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tstatfs(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tstatfs); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 11; - VALIDATE_NET_BYTES(11); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tstatfs->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(8)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tstatfs->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(8)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rstatfs(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rstatfs); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 67; - VALIDATE_NET_BYTES(67); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rstatfs->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(9)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rstatfs->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(9)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tlopen(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tlopen); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_flags = net_offset + 11; - uint32_t offsetof_end = net_offset + 15; - VALIDATE_NET_BYTES(15); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tlopen->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(12)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tlopen->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(12)); - if (GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in lo bitfield: %#08"PRIx32, - GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Rlopen(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlopen); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 4; - VALIDATE_NET_BYTES(4); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlopen->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(13)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlopen->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(13)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tlcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tlcreate); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_flags = net_offset + 0; - uint32_t offsetof_mode = net_offset + 4; - uint32_t offsetof_end = net_offset + 12; - VALIDATE_NET_BYTES(12); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tlcreate->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(14)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tlcreate->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(14)); - if (GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in lo bitfield: %#08"PRIx32, - GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]); - if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in mode bitfield: %#08"PRIx32, - GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Rlcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlcreate); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 4; - VALIDATE_NET_BYTES(4); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlcreate->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(15)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlcreate->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(15)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tsymlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tsymlink); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 4; - VALIDATE_NET_BYTES(4); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tsymlink->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(16)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tsymlink->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(16)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rsymlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rsymlink); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rsymlink->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(17)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rsymlink->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(17)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tmknod(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tmknod); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_mode = net_offset + 0; - uint32_t offsetof_end = net_offset + 16; - VALIDATE_NET_BYTES(16); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tmknod->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(18)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tmknod->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(18)); - if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in mode bitfield: %#08"PRIx32, - GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Rmknod(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rmknod); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rmknod->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(19)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rmknod->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(19)); - return (ssize_t)host_size; -} - -static ssize_t validate_Trename(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Trename); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(17); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Trename->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(20)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Trename->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(20)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rrename(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rrename); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rrename->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(21)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rrename->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(21)); - return (ssize_t)host_size; -} - -static ssize_t validate_Treadlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Treadlink); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 11; - VALIDATE_NET_BYTES(11); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Treadlink->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(22)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Treadlink->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(22)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rreadlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rreadlink); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(9); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rreadlink->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(23)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rreadlink->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(23)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tgetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tgetattr); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_request_mask = net_offset + 11; - uint32_t offsetof_end = net_offset + 19; - VALIDATE_NET_BYTES(19); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tgetattr->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(24)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tgetattr->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(24)); - if (GET_U64LE(offsetof_request_mask) & ~getattr_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in getattr bitfield: %#016"PRIx64, - GET_U64LE(offsetof_request_mask) & ~getattr_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Rgetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rgetattr); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_valid = net_offset + 7; - uint32_t offsetof_qid_type = net_offset + 15; - VALIDATE_NET_BYTES(28); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_mode = net_offset + 0; - uint32_t offsetof_end = net_offset + 132; - VALIDATE_NET_BYTES(132); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rgetattr->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(25)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rgetattr->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(25)); - if (GET_U64LE(offsetof_valid) & ~getattr_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in getattr bitfield: %#016"PRIx64, - GET_U64LE(offsetof_valid) & ~getattr_masks[ctx->version]); - if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in mode bitfield: %#08"PRIx32, - GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Tsetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tsetattr); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_valid = net_offset + 11; - uint32_t offsetof_mode = net_offset + 15; - uint32_t offsetof_end = net_offset + 67; - VALIDATE_NET_BYTES(67); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tsetattr->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(26)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tsetattr->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(26)); - if (GET_U32LE(offsetof_valid) & ~setattr_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in setattr bitfield: %#08"PRIx32, - GET_U32LE(offsetof_valid) & ~setattr_masks[ctx->version]); - if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in mode bitfield: %#08"PRIx32, - GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Rsetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rsetattr); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rsetattr->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(27)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rsetattr->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(27)); - return (ssize_t)host_size; -} - -static ssize_t validate_Txattrwalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Txattrwalk); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(17); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Txattrwalk->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(30)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Txattrwalk->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(30)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rxattrwalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rxattrwalk); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 15; - VALIDATE_NET_BYTES(15); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rxattrwalk->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(31)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rxattrwalk->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(31)); - return (ssize_t)host_size; -} - -static ssize_t validate_Txattrcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Txattrcreate); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 12; - VALIDATE_NET_BYTES(12); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Txattrcreate->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(32)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Txattrcreate->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(32)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rxattrcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rxattrcreate); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rxattrcreate->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(33)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rxattrcreate->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(33)); - return (ssize_t)host_size; -} - -static ssize_t validate_Treaddir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Treaddir); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 23; - VALIDATE_NET_BYTES(23); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Treaddir->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(40)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Treaddir->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(40)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rreaddir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rreaddir); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(11); - VALIDATE_NET_BYTES(LAST_U32LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rreaddir->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(41)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rreaddir->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(41)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tfsync(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tfsync); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 15; - VALIDATE_NET_BYTES(15); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tfsync->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(50)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tfsync->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(50)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rfsync(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rfsync); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rfsync->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(51)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rfsync->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(51)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tlock); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_flags = net_offset + 12; - VALIDATE_NET_BYTES(38); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tlock->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(52)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tlock->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(52)); - if (GET_U32LE(offsetof_flags) & ~lock_flags_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in lock_flags bitfield: %#08"PRIx32, - GET_U32LE(offsetof_flags) & ~lock_flags_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Rlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlock); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 8; - VALIDATE_NET_BYTES(8); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlock->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(53)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlock->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(53)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tgetlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tgetlock); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(34); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tgetlock->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(54)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tgetlock->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(54)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rgetlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rgetlock); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(30); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rgetlock->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(55)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rgetlock->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(55)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tlink); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(17); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tlink->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(70)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tlink->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(70)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlink); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlink->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(71)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rlink->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(71)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tmkdir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tmkdir); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_mode = net_offset + 0; - uint32_t offsetof_end = net_offset + 8; - VALIDATE_NET_BYTES(8); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tmkdir->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(72)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tmkdir->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(72)); - if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in mode bitfield: %#08"PRIx32, - GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]); - return (ssize_t)host_size; -} - -static ssize_t validate_Rmkdir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rmkdir); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_qid_type = net_offset + 7; - VALIDATE_NET_BYTES(20); - if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#02"PRIx8, - GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rmkdir->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(73)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rmkdir->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(73)); - return (ssize_t)host_size; -} - -static ssize_t validate_Trenameat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Trenameat); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - VALIDATE_NET_BYTES(6); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Trenameat->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(74)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Trenameat->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(74)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rrenameat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rrenameat); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rrenameat->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(75)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rrenameat->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(75)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tunlinkat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tunlinkat); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - VALIDATE_NET_UTF8(LAST_U16LE()); - uint32_t offsetof_end = net_offset + 4; - VALIDATE_NET_BYTES(4); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tunlinkat->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(76)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tunlinkat->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(76)); - return (ssize_t)host_size; -} - -static ssize_t validate_Runlinkat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Runlinkat); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Runlinkat->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(77)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Runlinkat->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(77)); - return (ssize_t)host_size; -} - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e -static ssize_t validate_Tsession(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tsession); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 15; - VALIDATE_NET_BYTES(15); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tsession->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(150)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tsession->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(150)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rsession(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rsession); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 7; - VALIDATE_NET_BYTES(7); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rsession->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(151)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rsession->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(151)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tsread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tsread); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - for (uint16_t i = 0, cnt = LAST_U16LE(); i < cnt; i++) { - RESERVE_HOST_BYTES(sizeof(struct lib9p_s)); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - } - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tsread->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(152)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tsread->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(152)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rsread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rsread); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(11); - VALIDATE_NET_BYTES(LAST_U32LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rsread->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(153)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rsread->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(153)); - return (ssize_t)host_size; -} - -static ssize_t validate_Tswrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tswrite); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - VALIDATE_NET_BYTES(13); - for (uint16_t i = 0, cnt = LAST_U16LE(); i < cnt; i++) { - RESERVE_HOST_BYTES(sizeof(struct lib9p_s)); - VALIDATE_NET_BYTES(2); - VALIDATE_NET_UTF8(LAST_U16LE()); - } - VALIDATE_NET_BYTES(4); - VALIDATE_NET_BYTES(LAST_U32LE()); - uint32_t offsetof_end = net_offset + 0; - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tswrite->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(154)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Tswrite->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(154)); - return (ssize_t)host_size; -} - -static ssize_t validate_Rswrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { - uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rswrite); - uint32_t offsetof_size = net_offset + 0; - uint32_t offsetof_typ = net_offset + 4; - uint32_t offsetof_end = net_offset + 11; - VALIDATE_NET_BYTES(11); - if ((uint32_t)GET_U32LE(offsetof_size) != (uint32_t)(offsetof_end - offsetof_size)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rswrite->size value is wrong: actual: %"PRIu32" != correct:%"PRIu32, - (uint32_t)GET_U32LE(offsetof_size), (uint32_t)(offsetof_end - offsetof_size)); - if ((uint8_t)GET_U8LE(offsetof_typ) != (uint8_t)(155)) - return lib9p_errorf(ctx, LINUX_EBADMSG, "Rswrite->typ value is wrong: actual: %"PRIu8" != correct:%"PRIu8, - (uint8_t)GET_U8LE(offsetof_typ), (uint8_t)(155)); - return (ssize_t)host_size; -} -#endif /* CONFIG_9P_ENABLE_9P2000_e */ - -/* unmarshal_* ****************************************************************/ - -#define UNMARSHAL_BYTES(ctx, data_lvalue, len) \ - data_lvalue = (char *)&net_bytes[net_offset]; \ - net_offset += len; -#define UNMARSHAL_U8LE(ctx, val_lvalue) \ - val_lvalue = net_bytes[net_offset]; \ - net_offset += 1; -#define UNMARSHAL_U16LE(ctx, val_lvalue) \ - val_lvalue = uint16le_decode(&net_bytes[net_offset]); \ - net_offset += 2; -#define UNMARSHAL_U32LE(ctx, val_lvalue) \ - val_lvalue = uint32le_decode(&net_bytes[net_offset]); \ - net_offset += 4; -#define UNMARSHAL_U64LE(ctx, val_lvalue) \ - val_lvalue = uint64le_decode(&net_bytes[net_offset]); \ - net_offset += 8; - -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static void unmarshal_stat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_stat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 2; - UNMARSHAL_U16LE(ctx, out->kern_type); - UNMARSHAL_U32LE(ctx, out->kern_dev); - UNMARSHAL_U8LE(ctx, out->file_qid.type); - UNMARSHAL_U32LE(ctx, out->file_qid.vers); - UNMARSHAL_U64LE(ctx, out->file_qid.path); - UNMARSHAL_U32LE(ctx, out->file_mode); - UNMARSHAL_U32LE(ctx, out->file_atime); - UNMARSHAL_U32LE(ctx, out->file_mtime); - UNMARSHAL_U64LE(ctx, out->file_size); - UNMARSHAL_U16LE(ctx, out->file_name.len); - UNMARSHAL_BYTES(ctx, out->file_name.utf8, out->file_name.len); - UNMARSHAL_U16LE(ctx, out->file_owner_uid.len); - UNMARSHAL_BYTES(ctx, out->file_owner_uid.utf8, out->file_owner_uid.len); - UNMARSHAL_U16LE(ctx, out->file_owner_gid.len); - UNMARSHAL_BYTES(ctx, out->file_owner_gid.utf8, out->file_owner_gid.len); - UNMARSHAL_U16LE(ctx, out->file_last_modified_uid.len); - UNMARSHAL_BYTES(ctx, out->file_last_modified_uid.utf8, out->file_last_modified_uid.len); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - UNMARSHAL_U16LE(ctx, out->file_extension.len); - UNMARSHAL_BYTES(ctx, out->file_extension.utf8, out->file_extension.len); - UNMARSHAL_U32LE(ctx, out->file_owner_n_uid); - UNMARSHAL_U32LE(ctx, out->file_owner_n_gid); - UNMARSHAL_U32LE(ctx, out->file_last_modified_n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static void unmarshal_Tversion([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tversion *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->max_msg_size); - UNMARSHAL_U16LE(ctx, out->version.len); - UNMARSHAL_BYTES(ctx, out->version.utf8, out->version.len); -} - -static void unmarshal_Rversion([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rversion *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->max_msg_size); - UNMARSHAL_U16LE(ctx, out->version.len); - UNMARSHAL_BYTES(ctx, out->version.utf8, out->version.len); -} - -static void unmarshal_Tauth([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tauth *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->afid); - UNMARSHAL_U16LE(ctx, out->uname.len); - UNMARSHAL_BYTES(ctx, out->uname.utf8, out->uname.len); - UNMARSHAL_U16LE(ctx, out->aname.len); - UNMARSHAL_BYTES(ctx, out->aname.utf8, out->aname.len); -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { - UNMARSHAL_U32LE(ctx, out->n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ -} - -static void unmarshal_Rauth([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rauth *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->aqid.type); - UNMARSHAL_U32LE(ctx, out->aqid.vers); - UNMARSHAL_U64LE(ctx, out->aqid.path); -} - -static void unmarshal_Tattach([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tattach *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U32LE(ctx, out->afid); - UNMARSHAL_U16LE(ctx, out->uname.len); - UNMARSHAL_BYTES(ctx, out->uname.utf8, out->uname.len); - UNMARSHAL_U16LE(ctx, out->aname.len); - UNMARSHAL_BYTES(ctx, out->aname.utf8, out->aname.len); -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { - UNMARSHAL_U32LE(ctx, out->n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ -} - -static void unmarshal_Rattach([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rattach *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); -} - -static void unmarshal_Rerror([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rerror *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U16LE(ctx, out->ename.len); - UNMARSHAL_BYTES(ctx, out->ename.utf8, out->ename.len); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - UNMARSHAL_U32LE(ctx, out->errno); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -} - -static void unmarshal_Tflush([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tflush *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U16LE(ctx, out->oldtag); -} - -static void unmarshal_Rflush([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rflush *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Twalk([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Twalk *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U32LE(ctx, out->newfid); - UNMARSHAL_U16LE(ctx, out->nwname); - out->wname = extra; - extra += sizeof(out->wname[0]) * out->nwname; - for (uint16_t i = 0; i < out->nwname; i++) { - UNMARSHAL_U16LE(ctx, out->wname[i].len); - UNMARSHAL_BYTES(ctx, out->wname[i].utf8, out->wname[i].len); - } -} - -static void unmarshal_Rwalk([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rwalk *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U16LE(ctx, out->nwqid); - out->wqid = extra; - extra += sizeof(out->wqid[0]) * out->nwqid; - for (uint16_t i = 0; i < out->nwqid; i++) { - UNMARSHAL_U8LE(ctx, out->wqid[i].type); - UNMARSHAL_U32LE(ctx, out->wqid[i].vers); - UNMARSHAL_U64LE(ctx, out->wqid[i].path); - } -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static void unmarshal_Topen([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Topen *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U8LE(ctx, out->mode); -} - -static void unmarshal_Ropen([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Ropen *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); - UNMARSHAL_U32LE(ctx, out->iounit); -} - -static void unmarshal_Tcreate([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tcreate *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); - UNMARSHAL_U32LE(ctx, out->perm); - UNMARSHAL_U8LE(ctx, out->mode); -} - -static void unmarshal_Rcreate([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rcreate *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); - UNMARSHAL_U32LE(ctx, out->iounit); -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static void unmarshal_Tread([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tread *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U64LE(ctx, out->offset); - UNMARSHAL_U32LE(ctx, out->count); -} - -static void unmarshal_Rread([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rread *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->count); - UNMARSHAL_BYTES(ctx, out->data, out->count); -} - -static void unmarshal_Twrite([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Twrite *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U64LE(ctx, out->offset); - UNMARSHAL_U32LE(ctx, out->count); - UNMARSHAL_BYTES(ctx, out->data, out->count); -} - -static void unmarshal_Rwrite([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rwrite *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->count); -} - -static void unmarshal_Tclunk([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tclunk *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); -} - -static void unmarshal_Rclunk([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rclunk *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Tremove([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tremove *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); -} - -static void unmarshal_Rremove([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rremove *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static void unmarshal_Tstat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tstat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); -} - -static void unmarshal_Rstat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rstat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - net_offset += 2; - net_offset += 2; - UNMARSHAL_U16LE(ctx, out->stat.kern_type); - UNMARSHAL_U32LE(ctx, out->stat.kern_dev); - UNMARSHAL_U8LE(ctx, out->stat.file_qid.type); - UNMARSHAL_U32LE(ctx, out->stat.file_qid.vers); - UNMARSHAL_U64LE(ctx, out->stat.file_qid.path); - UNMARSHAL_U32LE(ctx, out->stat.file_mode); - UNMARSHAL_U32LE(ctx, out->stat.file_atime); - UNMARSHAL_U32LE(ctx, out->stat.file_mtime); - UNMARSHAL_U64LE(ctx, out->stat.file_size); - UNMARSHAL_U16LE(ctx, out->stat.file_name.len); - UNMARSHAL_BYTES(ctx, out->stat.file_name.utf8, out->stat.file_name.len); - UNMARSHAL_U16LE(ctx, out->stat.file_owner_uid.len); - UNMARSHAL_BYTES(ctx, out->stat.file_owner_uid.utf8, out->stat.file_owner_uid.len); - UNMARSHAL_U16LE(ctx, out->stat.file_owner_gid.len); - UNMARSHAL_BYTES(ctx, out->stat.file_owner_gid.utf8, out->stat.file_owner_gid.len); - UNMARSHAL_U16LE(ctx, out->stat.file_last_modified_uid.len); - UNMARSHAL_BYTES(ctx, out->stat.file_last_modified_uid.utf8, out->stat.file_last_modified_uid.len); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - UNMARSHAL_U16LE(ctx, out->stat.file_extension.len); - UNMARSHAL_BYTES(ctx, out->stat.file_extension.utf8, out->stat.file_extension.len); - UNMARSHAL_U32LE(ctx, out->stat.file_owner_n_uid); - UNMARSHAL_U32LE(ctx, out->stat.file_owner_n_gid); - UNMARSHAL_U32LE(ctx, out->stat.file_last_modified_n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -} - -static void unmarshal_Twstat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Twstat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - net_offset += 2; - net_offset += 2; - UNMARSHAL_U16LE(ctx, out->stat.kern_type); - UNMARSHAL_U32LE(ctx, out->stat.kern_dev); - UNMARSHAL_U8LE(ctx, out->stat.file_qid.type); - UNMARSHAL_U32LE(ctx, out->stat.file_qid.vers); - UNMARSHAL_U64LE(ctx, out->stat.file_qid.path); - UNMARSHAL_U32LE(ctx, out->stat.file_mode); - UNMARSHAL_U32LE(ctx, out->stat.file_atime); - UNMARSHAL_U32LE(ctx, out->stat.file_mtime); - UNMARSHAL_U64LE(ctx, out->stat.file_size); - UNMARSHAL_U16LE(ctx, out->stat.file_name.len); - UNMARSHAL_BYTES(ctx, out->stat.file_name.utf8, out->stat.file_name.len); - UNMARSHAL_U16LE(ctx, out->stat.file_owner_uid.len); - UNMARSHAL_BYTES(ctx, out->stat.file_owner_uid.utf8, out->stat.file_owner_uid.len); - UNMARSHAL_U16LE(ctx, out->stat.file_owner_gid.len); - UNMARSHAL_BYTES(ctx, out->stat.file_owner_gid.utf8, out->stat.file_owner_gid.len); - UNMARSHAL_U16LE(ctx, out->stat.file_last_modified_uid.len); - UNMARSHAL_BYTES(ctx, out->stat.file_last_modified_uid.utf8, out->stat.file_last_modified_uid.len); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - UNMARSHAL_U16LE(ctx, out->stat.file_extension.len); - UNMARSHAL_BYTES(ctx, out->stat.file_extension.utf8, out->stat.file_extension.len); - UNMARSHAL_U32LE(ctx, out->stat.file_owner_n_uid); - UNMARSHAL_U32LE(ctx, out->stat.file_owner_n_gid); - UNMARSHAL_U32LE(ctx, out->stat.file_last_modified_n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -} - -static void unmarshal_Rwstat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rwstat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_p9p -static void unmarshal_Topenfd([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Topenfd *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U8LE(ctx, out->mode); -} - -static void unmarshal_Ropenfd([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Ropenfd *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); - UNMARSHAL_U32LE(ctx, out->iounit); - UNMARSHAL_U32LE(ctx, out->unixfd); -} - -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_L -static void unmarshal_Rlerror([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rlerror *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->ecode); -} - -static void unmarshal_Tstatfs([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tstatfs *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); -} - -static void unmarshal_Rstatfs([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rstatfs *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->type); - UNMARSHAL_U32LE(ctx, out->bsize); - UNMARSHAL_U64LE(ctx, out->blocks); - UNMARSHAL_U64LE(ctx, out->bfree); - UNMARSHAL_U64LE(ctx, out->bavail); - UNMARSHAL_U64LE(ctx, out->files); - UNMARSHAL_U64LE(ctx, out->ffree); - UNMARSHAL_U64LE(ctx, out->fsid); - UNMARSHAL_U32LE(ctx, out->namelen); -} - -static void unmarshal_Tlopen([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tlopen *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U32LE(ctx, out->flags); -} - -static void unmarshal_Rlopen([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rlopen *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); - UNMARSHAL_U32LE(ctx, out->iounit); -} - -static void unmarshal_Tlcreate([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tlcreate *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); - UNMARSHAL_U32LE(ctx, out->flags); - UNMARSHAL_U32LE(ctx, out->mode); - UNMARSHAL_U32LE(ctx, out->gid); -} - -static void unmarshal_Rlcreate([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rlcreate *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); - UNMARSHAL_U32LE(ctx, out->iounit); -} - -static void unmarshal_Tsymlink([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tsymlink *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); - UNMARSHAL_U16LE(ctx, out->symtgt.len); - UNMARSHAL_BYTES(ctx, out->symtgt.utf8, out->symtgt.len); - UNMARSHAL_U32LE(ctx, out->gid); -} - -static void unmarshal_Rsymlink([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rsymlink *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); -} - -static void unmarshal_Tmknod([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tmknod *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->dfid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); - UNMARSHAL_U32LE(ctx, out->mode); - UNMARSHAL_U32LE(ctx, out->major); - UNMARSHAL_U32LE(ctx, out->minor); - UNMARSHAL_U32LE(ctx, out->gid); -} - -static void unmarshal_Rmknod([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rmknod *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); -} - -static void unmarshal_Trename([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Trename *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U32LE(ctx, out->dfid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); -} - -static void unmarshal_Rrename([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rrename *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Treadlink([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Treadlink *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); -} - -static void unmarshal_Rreadlink([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rreadlink *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U16LE(ctx, out->target.len); - UNMARSHAL_BYTES(ctx, out->target.utf8, out->target.len); -} - -static void unmarshal_Tgetattr([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tgetattr *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U64LE(ctx, out->request_mask); -} - -static void unmarshal_Rgetattr([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rgetattr *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U64LE(ctx, out->valid); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); - UNMARSHAL_U32LE(ctx, out->mode); - UNMARSHAL_U32LE(ctx, out->uid); - UNMARSHAL_U32LE(ctx, out->gid); - UNMARSHAL_U64LE(ctx, out->nlink); - UNMARSHAL_U64LE(ctx, out->rdev); - UNMARSHAL_U64LE(ctx, out->filesize); - UNMARSHAL_U64LE(ctx, out->blksize); - UNMARSHAL_U64LE(ctx, out->blocks); - UNMARSHAL_U64LE(ctx, out->atime_sec); - UNMARSHAL_U64LE(ctx, out->atime_nsec); - UNMARSHAL_U64LE(ctx, out->mtime_sec); - UNMARSHAL_U64LE(ctx, out->mtime_nsec); - UNMARSHAL_U64LE(ctx, out->ctime_sec); - UNMARSHAL_U64LE(ctx, out->ctime_nsec); - UNMARSHAL_U64LE(ctx, out->btime_sec); - UNMARSHAL_U64LE(ctx, out->btime_nsec); - UNMARSHAL_U64LE(ctx, out->gen); - UNMARSHAL_U64LE(ctx, out->data_version); -} - -static void unmarshal_Tsetattr([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tsetattr *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U32LE(ctx, out->valid); - UNMARSHAL_U32LE(ctx, out->mode); - UNMARSHAL_U32LE(ctx, out->uid); - UNMARSHAL_U32LE(ctx, out->gid); - UNMARSHAL_U64LE(ctx, out->filesize); - UNMARSHAL_U64LE(ctx, out->atime_sec); - UNMARSHAL_U64LE(ctx, out->atime_nsec); - UNMARSHAL_U64LE(ctx, out->mtime_sec); - UNMARSHAL_U64LE(ctx, out->mtime_nsec); -} - -static void unmarshal_Rsetattr([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rsetattr *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Txattrwalk([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Txattrwalk *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U32LE(ctx, out->newfid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); -} - -static void unmarshal_Rxattrwalk([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rxattrwalk *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U64LE(ctx, out->attr_size); -} - -static void unmarshal_Txattrcreate([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Txattrcreate *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); - UNMARSHAL_U64LE(ctx, out->attr_size); - UNMARSHAL_U32LE(ctx, out->flags); -} - -static void unmarshal_Rxattrcreate([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rxattrcreate *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Treaddir([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Treaddir *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U64LE(ctx, out->offset); - UNMARSHAL_U32LE(ctx, out->count); -} - -static void unmarshal_Rreaddir([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rreaddir *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->count); - UNMARSHAL_BYTES(ctx, out->data, out->count); -} - -static void unmarshal_Tfsync([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tfsync *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U32LE(ctx, out->datasync); -} - -static void unmarshal_Rfsync([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rfsync *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Tlock([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tlock *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U8LE(ctx, out->type); - UNMARSHAL_U32LE(ctx, out->flags); - UNMARSHAL_U64LE(ctx, out->start); - UNMARSHAL_U64LE(ctx, out->length); - UNMARSHAL_U32LE(ctx, out->proc_id); - UNMARSHAL_U16LE(ctx, out->client_id.len); - UNMARSHAL_BYTES(ctx, out->client_id.utf8, out->client_id.len); -} - -static void unmarshal_Rlock([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rlock *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->status); -} - -static void unmarshal_Tgetlock([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tgetlock *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U8LE(ctx, out->type); - UNMARSHAL_U64LE(ctx, out->start); - UNMARSHAL_U64LE(ctx, out->length); - UNMARSHAL_U32LE(ctx, out->proc_id); - UNMARSHAL_U16LE(ctx, out->client_id.len); - UNMARSHAL_BYTES(ctx, out->client_id.utf8, out->client_id.len); -} - -static void unmarshal_Rgetlock([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rgetlock *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->type); - UNMARSHAL_U64LE(ctx, out->start); - UNMARSHAL_U64LE(ctx, out->length); - UNMARSHAL_U32LE(ctx, out->proc_id); - UNMARSHAL_U16LE(ctx, out->client_id.len); - UNMARSHAL_BYTES(ctx, out->client_id.utf8, out->client_id.len); -} - -static void unmarshal_Tlink([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tlink *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->dfid); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); -} - -static void unmarshal_Rlink([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rlink *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Tmkdir([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tmkdir *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->dfid); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); - UNMARSHAL_U32LE(ctx, out->mode); - UNMARSHAL_U32LE(ctx, out->gid); -} - -static void unmarshal_Rmkdir([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rmkdir *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U8LE(ctx, out->qid.type); - UNMARSHAL_U32LE(ctx, out->qid.vers); - UNMARSHAL_U64LE(ctx, out->qid.path); -} - -static void unmarshal_Trenameat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Trenameat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->olddirfid); - UNMARSHAL_U16LE(ctx, out->oldname.len); - UNMARSHAL_BYTES(ctx, out->oldname.utf8, out->oldname.len); - UNMARSHAL_U32LE(ctx, out->newdirfid); - UNMARSHAL_U16LE(ctx, out->newname.len); - UNMARSHAL_BYTES(ctx, out->newname.utf8, out->newname.len); -} - -static void unmarshal_Rrenameat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rrenameat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Tunlinkat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tunlinkat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->dirfd); - UNMARSHAL_U16LE(ctx, out->name.len); - UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); - UNMARSHAL_U32LE(ctx, out->flags); -} - -static void unmarshal_Runlinkat([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Runlinkat *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e -static void unmarshal_Tsession([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tsession *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U64LE(ctx, out->key); -} - -static void unmarshal_Rsession([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rsession *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); -} - -static void unmarshal_Tsread([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tsread *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U16LE(ctx, out->nwname); - out->wname = extra; - extra += sizeof(out->wname[0]) * out->nwname; - for (uint16_t i = 0; i < out->nwname; i++) { - UNMARSHAL_U16LE(ctx, out->wname[i].len); - UNMARSHAL_BYTES(ctx, out->wname[i].utf8, out->wname[i].len); - } -} - -static void unmarshal_Rsread([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rsread *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->count); - UNMARSHAL_BYTES(ctx, out->data, out->count); -} - -static void unmarshal_Tswrite([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Tswrite *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->fid); - UNMARSHAL_U16LE(ctx, out->nwname); - out->wname = extra; - extra += sizeof(out->wname[0]) * out->nwname; - for (uint16_t i = 0; i < out->nwname; i++) { - UNMARSHAL_U16LE(ctx, out->wname[i].len); - UNMARSHAL_BYTES(ctx, out->wname[i].utf8, out->wname[i].len); - } - UNMARSHAL_U32LE(ctx, out->count); - UNMARSHAL_BYTES(ctx, out->data, out->count); -} - -static void unmarshal_Rswrite([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { - struct lib9p_msg_Rswrite *out = out_buf; - [[gnu::unused]] void *extra = &out[1]; - uint32_t net_offset = 0; - net_offset += 4; - net_offset += 1; - UNMARSHAL_U16LE(ctx, out->tag); - UNMARSHAL_U32LE(ctx, out->count); -} -#endif /* CONFIG_9P_ENABLE_9P2000_e */ - -/* marshal_* ******************************************************************/ - -#define MARSHAL_BYTES_ZEROCOPY(ctx, data, len) \ - if (ret->net_iov[ret->net_iov_cnt-1].iov_len) \ - ret->net_iov_cnt++; \ - ret->net_iov[ret->net_iov_cnt-1].iov_base = data; \ - ret->net_iov[ret->net_iov_cnt-1].iov_len = len; \ - ret->net_iov_cnt++; -#define MARSHAL_BYTES(ctx, data, len) \ - if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ - ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ - memcpy(&ret->net_copied[ret->net_copied_size], data, len); \ - ret->net_copied_size += len; \ - ret->net_iov[ret->net_iov_cnt-1].iov_len += len; -#define MARSHAL_U8LE(ctx, val) \ - if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ - ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ - ret->net_copied[ret->net_copied_size] = val; \ - ret->net_copied_size += 1; \ - ret->net_iov[ret->net_iov_cnt-1].iov_len += 1; -#define MARSHAL_U16LE(ctx, val) \ - if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ - ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ - uint16le_encode(&ret->net_copied[ret->net_copied_size], val); \ - ret->net_copied_size += 2; \ - ret->net_iov[ret->net_iov_cnt-1].iov_len += 2; -#define MARSHAL_U32LE(ctx, val) \ - if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ - ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ - uint32le_encode(&ret->net_copied[ret->net_copied_size], val); \ - ret->net_copied_size += 4; \ - ret->net_iov[ret->net_iov_cnt-1].iov_len += 4; -#define MARSHAL_U64LE(ctx, val) \ - if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ - ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ - uint64le_encode(&ret->net_copied[ret->net_copied_size], val); \ - ret->net_copied_size += 8; \ - ret->net_iov[ret->net_iov_cnt-1].iov_len += 8; - -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_stat(struct lib9p_ctx *ctx, struct lib9p_stat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 49 + val->file_name.len + val->file_owner_uid.len + val->file_owner_gid.len + val->file_last_modified_uid.len; -#if CONFIG_9P_ENABLE_9P2000_u - if is_ver(ctx, 9P2000_u) { - needed_size += 14 + val->file_extension.len; - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - if (needed_size > ctx->max_msg_size) { - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_kern_type = 2; - MARSHAL_U16LE(ctx, offsetof_end - offsetof_kern_type); - MARSHAL_U16LE(ctx, val->kern_type); - MARSHAL_U32LE(ctx, val->kern_dev); - MARSHAL_U8LE(ctx, val->file_qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->file_qid.vers); - MARSHAL_U64LE(ctx, val->file_qid.path); - MARSHAL_U32LE(ctx, val->file_mode & dm_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->file_atime); - MARSHAL_U32LE(ctx, val->file_mtime); - MARSHAL_U64LE(ctx, val->file_size); - MARSHAL_U16LE(ctx, val->file_name.len); - MARSHAL_BYTES(ctx, val->file_name.utf8, val->file_name.len); - MARSHAL_U16LE(ctx, val->file_owner_uid.len); - MARSHAL_BYTES(ctx, val->file_owner_uid.utf8, val->file_owner_uid.len); - MARSHAL_U16LE(ctx, val->file_owner_gid.len); - MARSHAL_BYTES(ctx, val->file_owner_gid.utf8, val->file_owner_gid.len); - MARSHAL_U16LE(ctx, val->file_last_modified_uid.len); - MARSHAL_BYTES(ctx, val->file_last_modified_uid.utf8, val->file_last_modified_uid.len); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - MARSHAL_U16LE(ctx, val->file_extension.len); - MARSHAL_BYTES(ctx, val->file_extension.utf8, val->file_extension.len); - MARSHAL_U32LE(ctx, val->file_owner_n_uid); - MARSHAL_U32LE(ctx, val->file_owner_n_gid); - MARSHAL_U32LE(ctx, val->file_last_modified_n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - return false; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Tversion(struct lib9p_ctx *ctx, struct lib9p_msg_Tversion *val, struct _marshal_ret *ret) { - uint32_t needed_size = 13 + val->version.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tversion", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 100); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->max_msg_size); - MARSHAL_U16LE(ctx, val->version.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->version.utf8, val->version.len); - return false; -} - -static bool marshal_Rversion(struct lib9p_ctx *ctx, struct lib9p_msg_Rversion *val, struct _marshal_ret *ret) { - uint32_t needed_size = 13 + val->version.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rversion", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 101); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->max_msg_size); - MARSHAL_U16LE(ctx, val->version.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->version.utf8, val->version.len); - return false; -} - -static bool marshal_Tauth(struct lib9p_ctx *ctx, struct lib9p_msg_Tauth *val, struct _marshal_ret *ret) { - uint32_t needed_size = 15 + val->uname.len + val->aname.len; -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - if ( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) ) { - needed_size += 4; - } -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tauth", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 102); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->afid); - MARSHAL_U16LE(ctx, val->uname.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->uname.utf8, val->uname.len); - MARSHAL_U16LE(ctx, val->aname.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->aname.utf8, val->aname.len); -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { - MARSHAL_U32LE(ctx, val->n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ - return false; -} - -static bool marshal_Rauth(struct lib9p_ctx *ctx, struct lib9p_msg_Rauth *val, struct _marshal_ret *ret) { - uint32_t needed_size = 20; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rauth", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 103); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->aqid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->aqid.vers); - MARSHAL_U64LE(ctx, val->aqid.path); - return false; -} - -static bool marshal_Tattach(struct lib9p_ctx *ctx, struct lib9p_msg_Tattach *val, struct _marshal_ret *ret) { - uint32_t needed_size = 19 + val->uname.len + val->aname.len; -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - if ( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) ) { - needed_size += 4; - } -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tattach", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 104); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U32LE(ctx, val->afid); - MARSHAL_U16LE(ctx, val->uname.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->uname.utf8, val->uname.len); - MARSHAL_U16LE(ctx, val->aname.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->aname.utf8, val->aname.len); -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { - MARSHAL_U32LE(ctx, val->n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ - return false; -} - -static bool marshal_Rattach(struct lib9p_ctx *ctx, struct lib9p_msg_Rattach *val, struct _marshal_ret *ret) { - uint32_t needed_size = 20; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rattach", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 105); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - return false; -} - -static bool marshal_Rerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rerror *val, struct _marshal_ret *ret) { - uint32_t needed_size = 9 + val->ename.len; -#if CONFIG_9P_ENABLE_9P2000_u - if is_ver(ctx, 9P2000_u) { - needed_size += 4; - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rerror", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 107); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U16LE(ctx, val->ename.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->ename.utf8, val->ename.len); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - MARSHAL_U32LE(ctx, val->errno); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - return false; -} - -static bool marshal_Tflush(struct lib9p_ctx *ctx, struct lib9p_msg_Tflush *val, struct _marshal_ret *ret) { - uint32_t needed_size = 9; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tflush", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 108); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U16LE(ctx, val->oldtag); - return false; -} - -static bool marshal_Rflush(struct lib9p_ctx *ctx, struct lib9p_msg_Rflush *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rflush", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 109); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Twalk(struct lib9p_ctx *ctx, struct lib9p_msg_Twalk *val, struct _marshal_ret *ret) { - uint32_t needed_size = 17; - for (uint16_t i = 0; i < val->nwname; i++) { - needed_size += 2 + val->wname[i].len; - } - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Twalk", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 110); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U32LE(ctx, val->newfid); - MARSHAL_U16LE(ctx, val->nwname); - for (uint16_t i = 0; i < val->nwname; i++) { - MARSHAL_U16LE(ctx, val->wname[i].len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->wname[i].utf8, val->wname[i].len); - } - return false; -} - -static bool marshal_Rwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rwalk *val, struct _marshal_ret *ret) { - uint32_t needed_size = 9 + (val->nwqid)*13; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rwalk", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 111); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U16LE(ctx, val->nwqid); - for (uint16_t i = 0; i < val->nwqid; i++) { - MARSHAL_U8LE(ctx, val->wqid[i].type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->wqid[i].vers); - MARSHAL_U64LE(ctx, val->wqid[i].path); - } - return false; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Topen(struct lib9p_ctx *ctx, struct lib9p_msg_Topen *val, struct _marshal_ret *ret) { - uint32_t needed_size = 12; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Topen", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 112); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); - return false; -} - -static bool marshal_Ropen(struct lib9p_ctx *ctx, struct lib9p_msg_Ropen *val, struct _marshal_ret *ret) { - uint32_t needed_size = 24; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Ropen", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 113); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - MARSHAL_U32LE(ctx, val->iounit); - return false; -} - -static bool marshal_Tcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tcreate *val, struct _marshal_ret *ret) { - uint32_t needed_size = 18 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tcreate", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 114); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - MARSHAL_U32LE(ctx, val->perm & dm_masks[ctx->version]); - MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); - return false; -} - -static bool marshal_Rcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rcreate *val, struct _marshal_ret *ret) { - uint32_t needed_size = 24; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rcreate", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 115); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - MARSHAL_U32LE(ctx, val->iounit); - return false; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Tread(struct lib9p_ctx *ctx, struct lib9p_msg_Tread *val, struct _marshal_ret *ret) { - uint32_t needed_size = 23; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tread", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 116); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U64LE(ctx, val->offset); - MARSHAL_U32LE(ctx, val->count); - return false; -} - -static bool marshal_Rread(struct lib9p_ctx *ctx, struct lib9p_msg_Rread *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11 + val->count; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rread", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 117); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->count); - MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; -} - -static bool marshal_Twrite(struct lib9p_ctx *ctx, struct lib9p_msg_Twrite *val, struct _marshal_ret *ret) { - uint32_t needed_size = 23 + val->count; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Twrite", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 118); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U64LE(ctx, val->offset); - MARSHAL_U32LE(ctx, val->count); - MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; -} - -static bool marshal_Rwrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rwrite *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rwrite", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 119); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->count); - return false; -} - -static bool marshal_Tclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Tclunk *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tclunk", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 120); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - return false; -} - -static bool marshal_Rclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Rclunk *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rclunk", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 121); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Tremove(struct lib9p_ctx *ctx, struct lib9p_msg_Tremove *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tremove", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 122); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - return false; -} - -static bool marshal_Rremove(struct lib9p_ctx *ctx, struct lib9p_msg_Rremove *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rremove", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 123); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Tstat(struct lib9p_ctx *ctx, struct lib9p_msg_Tstat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tstat", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 124); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - return false; -} - -static bool marshal_Rstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rstat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 58 + val->stat.file_name.len + val->stat.file_owner_uid.len + val->stat.file_owner_gid.len + val->stat.file_last_modified_uid.len; -#if CONFIG_9P_ENABLE_9P2000_u - if is_ver(ctx, 9P2000_u) { - needed_size += 14 + val->stat.file_extension.len; - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rstat", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - uint32_t offsetof_stat = 9; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 125); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U16LE(ctx, offsetof_end - offsetof_stat); - uint32_t offsetof_stat_end = 49 + val->stat.file_name.len + val->stat.file_owner_uid.len + val->stat.file_owner_gid.len + val->stat.file_last_modified_uid.len; -#if CONFIG_9P_ENABLE_9P2000_u - if is_ver(ctx, 9P2000_u) { - offsetof_stat_end += 14 + val->stat.file_extension.len; - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - uint32_t offsetof_stat_kern_type = 2; - MARSHAL_U16LE(ctx, offsetof_stat_end - offsetof_stat_kern_type); - MARSHAL_U16LE(ctx, val->stat.kern_type); - MARSHAL_U32LE(ctx, val->stat.kern_dev); - MARSHAL_U8LE(ctx, val->stat.file_qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->stat.file_qid.vers); - MARSHAL_U64LE(ctx, val->stat.file_qid.path); - MARSHAL_U32LE(ctx, val->stat.file_mode & dm_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->stat.file_atime); - MARSHAL_U32LE(ctx, val->stat.file_mtime); - MARSHAL_U64LE(ctx, val->stat.file_size); - MARSHAL_U16LE(ctx, val->stat.file_name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_name.utf8, val->stat.file_name.len); - MARSHAL_U16LE(ctx, val->stat.file_owner_uid.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_owner_uid.utf8, val->stat.file_owner_uid.len); - MARSHAL_U16LE(ctx, val->stat.file_owner_gid.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_owner_gid.utf8, val->stat.file_owner_gid.len); - MARSHAL_U16LE(ctx, val->stat.file_last_modified_uid.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_last_modified_uid.utf8, val->stat.file_last_modified_uid.len); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - MARSHAL_U16LE(ctx, val->stat.file_extension.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_extension.utf8, val->stat.file_extension.len); - MARSHAL_U32LE(ctx, val->stat.file_owner_n_uid); - MARSHAL_U32LE(ctx, val->stat.file_owner_n_gid); - MARSHAL_U32LE(ctx, val->stat.file_last_modified_n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - return false; -} - -static bool marshal_Twstat(struct lib9p_ctx *ctx, struct lib9p_msg_Twstat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 62 + val->stat.file_name.len + val->stat.file_owner_uid.len + val->stat.file_owner_gid.len + val->stat.file_last_modified_uid.len; -#if CONFIG_9P_ENABLE_9P2000_u - if is_ver(ctx, 9P2000_u) { - needed_size += 14 + val->stat.file_extension.len; - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Twstat", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - uint32_t offsetof_stat = 13; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 126); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U16LE(ctx, offsetof_end - offsetof_stat); - uint32_t offsetof_stat_end = 49 + val->stat.file_name.len + val->stat.file_owner_uid.len + val->stat.file_owner_gid.len + val->stat.file_last_modified_uid.len; -#if CONFIG_9P_ENABLE_9P2000_u - if is_ver(ctx, 9P2000_u) { - offsetof_stat_end += 14 + val->stat.file_extension.len; - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - uint32_t offsetof_stat_kern_type = 2; - MARSHAL_U16LE(ctx, offsetof_stat_end - offsetof_stat_kern_type); - MARSHAL_U16LE(ctx, val->stat.kern_type); - MARSHAL_U32LE(ctx, val->stat.kern_dev); - MARSHAL_U8LE(ctx, val->stat.file_qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->stat.file_qid.vers); - MARSHAL_U64LE(ctx, val->stat.file_qid.path); - MARSHAL_U32LE(ctx, val->stat.file_mode & dm_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->stat.file_atime); - MARSHAL_U32LE(ctx, val->stat.file_mtime); - MARSHAL_U64LE(ctx, val->stat.file_size); - MARSHAL_U16LE(ctx, val->stat.file_name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_name.utf8, val->stat.file_name.len); - MARSHAL_U16LE(ctx, val->stat.file_owner_uid.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_owner_uid.utf8, val->stat.file_owner_uid.len); - MARSHAL_U16LE(ctx, val->stat.file_owner_gid.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_owner_gid.utf8, val->stat.file_owner_gid.len); - MARSHAL_U16LE(ctx, val->stat.file_last_modified_uid.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_last_modified_uid.utf8, val->stat.file_last_modified_uid.len); -#if CONFIG_9P_ENABLE_9P2000_u - if (is_ver(ctx, 9P2000_u)) { - MARSHAL_U16LE(ctx, val->stat.file_extension.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.file_extension.utf8, val->stat.file_extension.len); - MARSHAL_U32LE(ctx, val->stat.file_owner_n_uid); - MARSHAL_U32LE(ctx, val->stat.file_owner_n_gid); - MARSHAL_U32LE(ctx, val->stat.file_last_modified_n_uid); - } -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - return false; -} - -static bool marshal_Rwstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rwstat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rwstat", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 127); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_p9p -static bool marshal_Topenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Topenfd *val, struct _marshal_ret *ret) { - uint32_t needed_size = 12; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Topenfd", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 98); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); - return false; -} - -static bool marshal_Ropenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Ropenfd *val, struct _marshal_ret *ret) { - uint32_t needed_size = 28; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Ropenfd", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 99); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - MARSHAL_U32LE(ctx, val->iounit); - MARSHAL_U32LE(ctx, val->unixfd); - return false; -} - -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_L -static bool marshal_Rlerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rlerror *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rlerror", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 7); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->ecode); - return false; -} - -static bool marshal_Tstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Tstatfs *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tstatfs", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 8); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - return false; -} - -static bool marshal_Rstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Rstatfs *val, struct _marshal_ret *ret) { - uint32_t needed_size = 67; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rstatfs", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 9); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->type); - MARSHAL_U32LE(ctx, val->bsize); - MARSHAL_U64LE(ctx, val->blocks); - MARSHAL_U64LE(ctx, val->bfree); - MARSHAL_U64LE(ctx, val->bavail); - MARSHAL_U64LE(ctx, val->files); - MARSHAL_U64LE(ctx, val->ffree); - MARSHAL_U64LE(ctx, val->fsid); - MARSHAL_U32LE(ctx, val->namelen); - return false; -} - -static bool marshal_Tlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Tlopen *val, struct _marshal_ret *ret) { - uint32_t needed_size = 15; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tlopen", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 12); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U32LE(ctx, val->flags & lo_masks[ctx->version]); - return false; -} - -static bool marshal_Rlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Rlopen *val, struct _marshal_ret *ret) { - uint32_t needed_size = 24; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rlopen", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 13); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - MARSHAL_U32LE(ctx, val->iounit); - return false; -} - -static bool marshal_Tlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tlcreate *val, struct _marshal_ret *ret) { - uint32_t needed_size = 25 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tlcreate", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 14); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - MARSHAL_U32LE(ctx, val->flags & lo_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->gid); - return false; -} - -static bool marshal_Rlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rlcreate *val, struct _marshal_ret *ret) { - uint32_t needed_size = 24; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rlcreate", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 15); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - MARSHAL_U32LE(ctx, val->iounit); - return false; -} - -static bool marshal_Tsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tsymlink *val, struct _marshal_ret *ret) { - uint32_t needed_size = 19 + val->name.len + val->symtgt.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tsymlink", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 16); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - MARSHAL_U16LE(ctx, val->symtgt.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->symtgt.utf8, val->symtgt.len); - MARSHAL_U32LE(ctx, val->gid); - return false; -} - -static bool marshal_Rsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rsymlink *val, struct _marshal_ret *ret) { - uint32_t needed_size = 20; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rsymlink", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 17); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - return false; -} - -static bool marshal_Tmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Tmknod *val, struct _marshal_ret *ret) { - uint32_t needed_size = 29 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tmknod", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 18); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->dfid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->major); - MARSHAL_U32LE(ctx, val->minor); - MARSHAL_U32LE(ctx, val->gid); - return false; -} - -static bool marshal_Rmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Rmknod *val, struct _marshal_ret *ret) { - uint32_t needed_size = 20; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rmknod", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 19); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - return false; -} - -static bool marshal_Trename(struct lib9p_ctx *ctx, struct lib9p_msg_Trename *val, struct _marshal_ret *ret) { - uint32_t needed_size = 17 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Trename", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 20); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U32LE(ctx, val->dfid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - return false; -} - -static bool marshal_Rrename(struct lib9p_ctx *ctx, struct lib9p_msg_Rrename *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rrename", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 21); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Treadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Treadlink *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Treadlink", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 22); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - return false; -} - -static bool marshal_Rreadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rreadlink *val, struct _marshal_ret *ret) { - uint32_t needed_size = 9 + val->target.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rreadlink", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 23); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U16LE(ctx, val->target.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->target.utf8, val->target.len); - return false; -} - -static bool marshal_Tgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetattr *val, struct _marshal_ret *ret) { - uint32_t needed_size = 19; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tgetattr", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 24); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U64LE(ctx, val->request_mask & getattr_masks[ctx->version]); - return false; -} - -static bool marshal_Rgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetattr *val, struct _marshal_ret *ret) { - uint32_t needed_size = 160; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rgetattr", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 25); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U64LE(ctx, val->valid & getattr_masks[ctx->version]); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->uid); - MARSHAL_U32LE(ctx, val->gid); - MARSHAL_U64LE(ctx, val->nlink); - MARSHAL_U64LE(ctx, val->rdev); - MARSHAL_U64LE(ctx, val->filesize); - MARSHAL_U64LE(ctx, val->blksize); - MARSHAL_U64LE(ctx, val->blocks); - MARSHAL_U64LE(ctx, val->atime_sec); - MARSHAL_U64LE(ctx, val->atime_nsec); - MARSHAL_U64LE(ctx, val->mtime_sec); - MARSHAL_U64LE(ctx, val->mtime_nsec); - MARSHAL_U64LE(ctx, val->ctime_sec); - MARSHAL_U64LE(ctx, val->ctime_nsec); - MARSHAL_U64LE(ctx, val->btime_sec); - MARSHAL_U64LE(ctx, val->btime_nsec); - MARSHAL_U64LE(ctx, val->gen); - MARSHAL_U64LE(ctx, val->data_version); - return false; -} - -static bool marshal_Tsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tsetattr *val, struct _marshal_ret *ret) { - uint32_t needed_size = 67; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tsetattr", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 26); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U32LE(ctx, val->valid & setattr_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->uid); - MARSHAL_U32LE(ctx, val->gid); - MARSHAL_U64LE(ctx, val->filesize); - MARSHAL_U64LE(ctx, val->atime_sec); - MARSHAL_U64LE(ctx, val->atime_nsec); - MARSHAL_U64LE(ctx, val->mtime_sec); - MARSHAL_U64LE(ctx, val->mtime_nsec); - return false; -} - -static bool marshal_Rsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rsetattr *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rsetattr", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 27); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Txattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrwalk *val, struct _marshal_ret *ret) { - uint32_t needed_size = 17 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Txattrwalk", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 30); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U32LE(ctx, val->newfid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - return false; -} - -static bool marshal_Rxattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrwalk *val, struct _marshal_ret *ret) { - uint32_t needed_size = 15; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rxattrwalk", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 31); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U64LE(ctx, val->attr_size); - return false; -} - -static bool marshal_Txattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrcreate *val, struct _marshal_ret *ret) { - uint32_t needed_size = 25 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Txattrcreate", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 32); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - MARSHAL_U64LE(ctx, val->attr_size); - MARSHAL_U32LE(ctx, val->flags); - return false; -} - -static bool marshal_Rxattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrcreate *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rxattrcreate", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 33); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Treaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Treaddir *val, struct _marshal_ret *ret) { - uint32_t needed_size = 23; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Treaddir", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 40); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U64LE(ctx, val->offset); - MARSHAL_U32LE(ctx, val->count); - return false; -} - -static bool marshal_Rreaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Rreaddir *val, struct _marshal_ret *ret) { - uint64_t needed_size = 11 + val->count; - if (needed_size > (uint64_t)(ctx->max_msg_size)) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rreaddir", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = (uint32_t)needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 41); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->count); - MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; -} - -static bool marshal_Tfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Tfsync *val, struct _marshal_ret *ret) { - uint32_t needed_size = 15; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tfsync", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 50); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U32LE(ctx, val->datasync); - return false; -} - -static bool marshal_Rfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Rfsync *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rfsync", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 51); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Tlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tlock *val, struct _marshal_ret *ret) { - uint32_t needed_size = 38 + val->client_id.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tlock", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 52); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U8LE(ctx, val->type); - MARSHAL_U32LE(ctx, val->flags & lock_flags_masks[ctx->version]); - MARSHAL_U64LE(ctx, val->start); - MARSHAL_U64LE(ctx, val->length); - MARSHAL_U32LE(ctx, val->proc_id); - MARSHAL_U16LE(ctx, val->client_id.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); - return false; -} - -static bool marshal_Rlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rlock *val, struct _marshal_ret *ret) { - uint32_t needed_size = 8; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rlock", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 53); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->status); - return false; -} - -static bool marshal_Tgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetlock *val, struct _marshal_ret *ret) { - uint32_t needed_size = 34 + val->client_id.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tgetlock", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 54); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U8LE(ctx, val->type); - MARSHAL_U64LE(ctx, val->start); - MARSHAL_U64LE(ctx, val->length); - MARSHAL_U32LE(ctx, val->proc_id); - MARSHAL_U16LE(ctx, val->client_id.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); - return false; -} - -static bool marshal_Rgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetlock *val, struct _marshal_ret *ret) { - uint32_t needed_size = 30 + val->client_id.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rgetlock", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 55); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->type); - MARSHAL_U64LE(ctx, val->start); - MARSHAL_U64LE(ctx, val->length); - MARSHAL_U32LE(ctx, val->proc_id); - MARSHAL_U16LE(ctx, val->client_id.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); - return false; -} - -static bool marshal_Tlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tlink *val, struct _marshal_ret *ret) { - uint32_t needed_size = 17 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tlink", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 70); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->dfid); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - return false; -} - -static bool marshal_Rlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rlink *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rlink", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 71); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Tmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Tmkdir *val, struct _marshal_ret *ret) { - uint32_t needed_size = 21 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tmkdir", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 72); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->dfid); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->gid); - return false; -} - -static bool marshal_Rmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Rmkdir *val, struct _marshal_ret *ret) { - uint32_t needed_size = 20; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rmkdir", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 73); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); - MARSHAL_U32LE(ctx, val->qid.vers); - MARSHAL_U64LE(ctx, val->qid.path); - return false; -} - -static bool marshal_Trenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Trenameat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 19 + val->oldname.len + val->newname.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Trenameat", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 74); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->olddirfid); - MARSHAL_U16LE(ctx, val->oldname.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->oldname.utf8, val->oldname.len); - MARSHAL_U32LE(ctx, val->newdirfid); - MARSHAL_U16LE(ctx, val->newname.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->newname.utf8, val->newname.len); - return false; -} - -static bool marshal_Rrenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Rrenameat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rrenameat", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 75); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Tunlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Tunlinkat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 17 + val->name.len; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tunlinkat", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 76); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->dirfd); - MARSHAL_U16LE(ctx, val->name.len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - MARSHAL_U32LE(ctx, val->flags); - return false; -} - -static bool marshal_Runlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Runlinkat *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Runlinkat", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 77); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e -static bool marshal_Tsession(struct lib9p_ctx *ctx, struct lib9p_msg_Tsession *val, struct _marshal_ret *ret) { - uint32_t needed_size = 15; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tsession", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 150); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U64LE(ctx, val->key); - return false; -} - -static bool marshal_Rsession(struct lib9p_ctx *ctx, struct lib9p_msg_Rsession *val, struct _marshal_ret *ret) { - uint32_t needed_size = 7; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rsession", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 151); - MARSHAL_U16LE(ctx, val->tag); - return false; -} - -static bool marshal_Tsread(struct lib9p_ctx *ctx, struct lib9p_msg_Tsread *val, struct _marshal_ret *ret) { - uint64_t needed_size = 13; - for (uint16_t i = 0; i < val->nwname; i++) { - needed_size += 2 + val->wname[i].len; - } - if (needed_size > (uint64_t)(ctx->max_msg_size)) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tsread", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = (uint32_t)needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 152); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U16LE(ctx, val->nwname); - for (uint16_t i = 0; i < val->nwname; i++) { - MARSHAL_U16LE(ctx, val->wname[i].len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->wname[i].utf8, val->wname[i].len); - } - return false; -} - -static bool marshal_Rsread(struct lib9p_ctx *ctx, struct lib9p_msg_Rsread *val, struct _marshal_ret *ret) { - uint64_t needed_size = 11 + val->count; - if (needed_size > (uint64_t)(ctx->max_msg_size)) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rsread", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = (uint32_t)needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 153); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->count); - MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; -} - -static bool marshal_Tswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Tswrite *val, struct _marshal_ret *ret) { - uint64_t needed_size = 17 + val->count; - for (uint16_t i = 0; i < val->nwname; i++) { - needed_size += 2 + val->wname[i].len; - } - if (needed_size > (uint64_t)(ctx->max_msg_size)) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Tswrite", - ctx->version ? "negotiated" : "client", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = (uint32_t)needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 154); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->fid); - MARSHAL_U16LE(ctx, val->nwname); - for (uint16_t i = 0; i < val->nwname; i++) { - MARSHAL_U16LE(ctx, val->wname[i].len); - MARSHAL_BYTES_ZEROCOPY(ctx, val->wname[i].utf8, val->wname[i].len); - } - MARSHAL_U32LE(ctx, val->count); - MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; -} - -static bool marshal_Rswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rswrite *val, struct _marshal_ret *ret) { - uint32_t needed_size = 11; - if (needed_size > ctx->max_msg_size) { - lib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")", - "Rswrite", - ctx->version ? "negotiated" : "server", - ctx->max_msg_size); - return true; - } - uint32_t offsetof_end = needed_size; - uint32_t offsetof_size = 0; - MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); - MARSHAL_U8LE(ctx, 155); - MARSHAL_U16LE(ctx, val->tag); - MARSHAL_U32LE(ctx, val->count); - return false; -} -#endif /* CONFIG_9P_ENABLE_9P2000_e */ - -/* function tables ************************************************************/ - -const uint32_t _lib9p_table_msg_min_size[LIB9P_VER_NUM] = { - [LIB9P_VER_unknown] = 9, -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = 9, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = 9, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = 9, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = 9, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = 13, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -#define _MSG_RECV(typ) [LIB9P_TYP_##typ/2] = { \ - .basesize = sizeof(struct lib9p_msg_##typ), \ - .validate = validate_##typ, \ - .unmarshal = (_unmarshal_fn_t)unmarshal_##typ, \ - } -#define _MSG_SEND(typ) [LIB9P_TYP_##typ/2] = { \ - .marshal = (_marshal_fn_t)marshal_##typ, \ - } - -const struct _lib9p_recv_tentry _lib9p_table_Tmsg_recv[LIB9P_VER_NUM][0x80] = { - [LIB9P_VER_unknown] = { - _MSG_RECV(Tversion), - }, -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = { - _MSG_RECV(Tversion), - _MSG_RECV(Tauth), - _MSG_RECV(Tattach), - _MSG_RECV(Tflush), - _MSG_RECV(Twalk), - _MSG_RECV(Topen), - _MSG_RECV(Tcreate), - _MSG_RECV(Tread), - _MSG_RECV(Twrite), - _MSG_RECV(Tclunk), - _MSG_RECV(Tremove), - _MSG_RECV(Tstat), - _MSG_RECV(Twstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = { - _MSG_RECV(Tstatfs), - _MSG_RECV(Tlopen), - _MSG_RECV(Tlcreate), - _MSG_RECV(Tsymlink), - _MSG_RECV(Tmknod), - _MSG_RECV(Trename), - _MSG_RECV(Treadlink), - _MSG_RECV(Tgetattr), - _MSG_RECV(Tsetattr), - _MSG_RECV(Txattrwalk), - _MSG_RECV(Txattrcreate), - _MSG_RECV(Treaddir), - _MSG_RECV(Tfsync), - _MSG_RECV(Tlock), - _MSG_RECV(Tgetlock), - _MSG_RECV(Tlink), - _MSG_RECV(Tmkdir), - _MSG_RECV(Trenameat), - _MSG_RECV(Tunlinkat), - _MSG_RECV(Tversion), - _MSG_RECV(Tauth), - _MSG_RECV(Tattach), - _MSG_RECV(Tflush), - _MSG_RECV(Twalk), - _MSG_RECV(Tread), - _MSG_RECV(Twrite), - _MSG_RECV(Tclunk), - _MSG_RECV(Tremove), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = { - _MSG_RECV(Tversion), - _MSG_RECV(Tauth), - _MSG_RECV(Tattach), - _MSG_RECV(Tflush), - _MSG_RECV(Twalk), - _MSG_RECV(Topen), - _MSG_RECV(Tcreate), - _MSG_RECV(Tread), - _MSG_RECV(Twrite), - _MSG_RECV(Tclunk), - _MSG_RECV(Tremove), - _MSG_RECV(Tstat), - _MSG_RECV(Twstat), - _MSG_RECV(Tsession), - _MSG_RECV(Tsread), - _MSG_RECV(Tswrite), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = { - _MSG_RECV(Topenfd), - _MSG_RECV(Tversion), - _MSG_RECV(Tauth), - _MSG_RECV(Tattach), - _MSG_RECV(Tflush), - _MSG_RECV(Twalk), - _MSG_RECV(Topen), - _MSG_RECV(Tcreate), - _MSG_RECV(Tread), - _MSG_RECV(Twrite), - _MSG_RECV(Tclunk), - _MSG_RECV(Tremove), - _MSG_RECV(Tstat), - _MSG_RECV(Twstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = { - _MSG_RECV(Tversion), - _MSG_RECV(Tauth), - _MSG_RECV(Tattach), - _MSG_RECV(Tflush), - _MSG_RECV(Twalk), - _MSG_RECV(Topen), - _MSG_RECV(Tcreate), - _MSG_RECV(Tread), - _MSG_RECV(Twrite), - _MSG_RECV(Tclunk), - _MSG_RECV(Tremove), - _MSG_RECV(Tstat), - _MSG_RECV(Twstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -const struct _lib9p_recv_tentry _lib9p_table_Rmsg_recv[LIB9P_VER_NUM][0x80] = { - [LIB9P_VER_unknown] = { - _MSG_RECV(Rversion), - _MSG_RECV(Rerror), - }, -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = { - _MSG_RECV(Rversion), - _MSG_RECV(Rauth), - _MSG_RECV(Rattach), - _MSG_RECV(Rerror), - _MSG_RECV(Rflush), - _MSG_RECV(Rwalk), - _MSG_RECV(Ropen), - _MSG_RECV(Rcreate), - _MSG_RECV(Rread), - _MSG_RECV(Rwrite), - _MSG_RECV(Rclunk), - _MSG_RECV(Rremove), - _MSG_RECV(Rstat), - _MSG_RECV(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = { - _MSG_RECV(Rlerror), - _MSG_RECV(Rstatfs), - _MSG_RECV(Rlopen), - _MSG_RECV(Rlcreate), - _MSG_RECV(Rsymlink), - _MSG_RECV(Rmknod), - _MSG_RECV(Rrename), - _MSG_RECV(Rreadlink), - _MSG_RECV(Rgetattr), - _MSG_RECV(Rsetattr), - _MSG_RECV(Rxattrwalk), - _MSG_RECV(Rxattrcreate), - _MSG_RECV(Rreaddir), - _MSG_RECV(Rfsync), - _MSG_RECV(Rlock), - _MSG_RECV(Rgetlock), - _MSG_RECV(Rlink), - _MSG_RECV(Rmkdir), - _MSG_RECV(Rrenameat), - _MSG_RECV(Runlinkat), - _MSG_RECV(Rversion), - _MSG_RECV(Rauth), - _MSG_RECV(Rattach), - _MSG_RECV(Rerror), - _MSG_RECV(Rflush), - _MSG_RECV(Rwalk), - _MSG_RECV(Rread), - _MSG_RECV(Rwrite), - _MSG_RECV(Rclunk), - _MSG_RECV(Rremove), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = { - _MSG_RECV(Rversion), - _MSG_RECV(Rauth), - _MSG_RECV(Rattach), - _MSG_RECV(Rerror), - _MSG_RECV(Rflush), - _MSG_RECV(Rwalk), - _MSG_RECV(Ropen), - _MSG_RECV(Rcreate), - _MSG_RECV(Rread), - _MSG_RECV(Rwrite), - _MSG_RECV(Rclunk), - _MSG_RECV(Rremove), - _MSG_RECV(Rstat), - _MSG_RECV(Rwstat), - _MSG_RECV(Rsession), - _MSG_RECV(Rsread), - _MSG_RECV(Rswrite), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = { - _MSG_RECV(Ropenfd), - _MSG_RECV(Rversion), - _MSG_RECV(Rauth), - _MSG_RECV(Rattach), - _MSG_RECV(Rerror), - _MSG_RECV(Rflush), - _MSG_RECV(Rwalk), - _MSG_RECV(Ropen), - _MSG_RECV(Rcreate), - _MSG_RECV(Rread), - _MSG_RECV(Rwrite), - _MSG_RECV(Rclunk), - _MSG_RECV(Rremove), - _MSG_RECV(Rstat), - _MSG_RECV(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = { - _MSG_RECV(Rversion), - _MSG_RECV(Rauth), - _MSG_RECV(Rattach), - _MSG_RECV(Rerror), - _MSG_RECV(Rflush), - _MSG_RECV(Rwalk), - _MSG_RECV(Ropen), - _MSG_RECV(Rcreate), - _MSG_RECV(Rread), - _MSG_RECV(Rwrite), - _MSG_RECV(Rclunk), - _MSG_RECV(Rremove), - _MSG_RECV(Rstat), - _MSG_RECV(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -const struct _lib9p_send_tentry _lib9p_table_Tmsg_send[LIB9P_VER_NUM][0x80] = { - [LIB9P_VER_unknown] = { - _MSG_SEND(Tversion), - }, -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = { - _MSG_SEND(Tversion), - _MSG_SEND(Tauth), - _MSG_SEND(Tattach), - _MSG_SEND(Tflush), - _MSG_SEND(Twalk), - _MSG_SEND(Topen), - _MSG_SEND(Tcreate), - _MSG_SEND(Tread), - _MSG_SEND(Twrite), - _MSG_SEND(Tclunk), - _MSG_SEND(Tremove), - _MSG_SEND(Tstat), - _MSG_SEND(Twstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = { - _MSG_SEND(Tstatfs), - _MSG_SEND(Tlopen), - _MSG_SEND(Tlcreate), - _MSG_SEND(Tsymlink), - _MSG_SEND(Tmknod), - _MSG_SEND(Trename), - _MSG_SEND(Treadlink), - _MSG_SEND(Tgetattr), - _MSG_SEND(Tsetattr), - _MSG_SEND(Txattrwalk), - _MSG_SEND(Txattrcreate), - _MSG_SEND(Treaddir), - _MSG_SEND(Tfsync), - _MSG_SEND(Tlock), - _MSG_SEND(Tgetlock), - _MSG_SEND(Tlink), - _MSG_SEND(Tmkdir), - _MSG_SEND(Trenameat), - _MSG_SEND(Tunlinkat), - _MSG_SEND(Tversion), - _MSG_SEND(Tauth), - _MSG_SEND(Tattach), - _MSG_SEND(Tflush), - _MSG_SEND(Twalk), - _MSG_SEND(Tread), - _MSG_SEND(Twrite), - _MSG_SEND(Tclunk), - _MSG_SEND(Tremove), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = { - _MSG_SEND(Tversion), - _MSG_SEND(Tauth), - _MSG_SEND(Tattach), - _MSG_SEND(Tflush), - _MSG_SEND(Twalk), - _MSG_SEND(Topen), - _MSG_SEND(Tcreate), - _MSG_SEND(Tread), - _MSG_SEND(Twrite), - _MSG_SEND(Tclunk), - _MSG_SEND(Tremove), - _MSG_SEND(Tstat), - _MSG_SEND(Twstat), - _MSG_SEND(Tsession), - _MSG_SEND(Tsread), - _MSG_SEND(Tswrite), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = { - _MSG_SEND(Topenfd), - _MSG_SEND(Tversion), - _MSG_SEND(Tauth), - _MSG_SEND(Tattach), - _MSG_SEND(Tflush), - _MSG_SEND(Twalk), - _MSG_SEND(Topen), - _MSG_SEND(Tcreate), - _MSG_SEND(Tread), - _MSG_SEND(Twrite), - _MSG_SEND(Tclunk), - _MSG_SEND(Tremove), - _MSG_SEND(Tstat), - _MSG_SEND(Twstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = { - _MSG_SEND(Tversion), - _MSG_SEND(Tauth), - _MSG_SEND(Tattach), - _MSG_SEND(Tflush), - _MSG_SEND(Twalk), - _MSG_SEND(Topen), - _MSG_SEND(Tcreate), - _MSG_SEND(Tread), - _MSG_SEND(Twrite), - _MSG_SEND(Tclunk), - _MSG_SEND(Tremove), - _MSG_SEND(Tstat), - _MSG_SEND(Twstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -const struct _lib9p_send_tentry _lib9p_table_Rmsg_send[LIB9P_VER_NUM][0x80] = { - [LIB9P_VER_unknown] = { - _MSG_SEND(Rversion), - _MSG_SEND(Rerror), - }, -#if CONFIG_9P_ENABLE_9P2000 - [LIB9P_VER_9P2000] = { - _MSG_SEND(Rversion), - _MSG_SEND(Rauth), - _MSG_SEND(Rattach), - _MSG_SEND(Rerror), - _MSG_SEND(Rflush), - _MSG_SEND(Rwalk), - _MSG_SEND(Ropen), - _MSG_SEND(Rcreate), - _MSG_SEND(Rread), - _MSG_SEND(Rwrite), - _MSG_SEND(Rclunk), - _MSG_SEND(Rremove), - _MSG_SEND(Rstat), - _MSG_SEND(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - [LIB9P_VER_9P2000_L] = { - _MSG_SEND(Rlerror), - _MSG_SEND(Rstatfs), - _MSG_SEND(Rlopen), - _MSG_SEND(Rlcreate), - _MSG_SEND(Rsymlink), - _MSG_SEND(Rmknod), - _MSG_SEND(Rrename), - _MSG_SEND(Rreadlink), - _MSG_SEND(Rgetattr), - _MSG_SEND(Rsetattr), - _MSG_SEND(Rxattrwalk), - _MSG_SEND(Rxattrcreate), - _MSG_SEND(Rreaddir), - _MSG_SEND(Rfsync), - _MSG_SEND(Rlock), - _MSG_SEND(Rgetlock), - _MSG_SEND(Rlink), - _MSG_SEND(Rmkdir), - _MSG_SEND(Rrenameat), - _MSG_SEND(Runlinkat), - _MSG_SEND(Rversion), - _MSG_SEND(Rauth), - _MSG_SEND(Rattach), - _MSG_SEND(Rerror), - _MSG_SEND(Rflush), - _MSG_SEND(Rwalk), - _MSG_SEND(Rread), - _MSG_SEND(Rwrite), - _MSG_SEND(Rclunk), - _MSG_SEND(Rremove), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_VER_9P2000_e] = { - _MSG_SEND(Rversion), - _MSG_SEND(Rauth), - _MSG_SEND(Rattach), - _MSG_SEND(Rerror), - _MSG_SEND(Rflush), - _MSG_SEND(Rwalk), - _MSG_SEND(Ropen), - _MSG_SEND(Rcreate), - _MSG_SEND(Rread), - _MSG_SEND(Rwrite), - _MSG_SEND(Rclunk), - _MSG_SEND(Rremove), - _MSG_SEND(Rstat), - _MSG_SEND(Rwstat), - _MSG_SEND(Rsession), - _MSG_SEND(Rsread), - _MSG_SEND(Rswrite), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - [LIB9P_VER_9P2000_p9p] = { - _MSG_SEND(Ropenfd), - _MSG_SEND(Rversion), - _MSG_SEND(Rauth), - _MSG_SEND(Rattach), - _MSG_SEND(Rerror), - _MSG_SEND(Rflush), - _MSG_SEND(Rwalk), - _MSG_SEND(Ropen), - _MSG_SEND(Rcreate), - _MSG_SEND(Rread), - _MSG_SEND(Rwrite), - _MSG_SEND(Rclunk), - _MSG_SEND(Rremove), - _MSG_SEND(Rstat), - _MSG_SEND(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - [LIB9P_VER_9P2000_u] = { - _MSG_SEND(Rversion), - _MSG_SEND(Rauth), - _MSG_SEND(Rattach), - _MSG_SEND(Rerror), - _MSG_SEND(Rflush), - _MSG_SEND(Rwalk), - _MSG_SEND(Ropen), - _MSG_SEND(Rcreate), - _MSG_SEND(Rread), - _MSG_SEND(Rwrite), - _MSG_SEND(Rclunk), - _MSG_SEND(Rremove), - _MSG_SEND(Rstat), - _MSG_SEND(Rwstat), - }, -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -LM_FLATTEN ssize_t _lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) { - return validate_stat(ctx, net_size, net_bytes, ret_net_size); -} -LM_FLATTEN void _lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out) { - unmarshal_stat(ctx, net_bytes, out); -} -LM_FLATTEN bool _lib9p_stat_marshal(struct lib9p_ctx *ctx, struct lib9p_stat *val, struct _marshal_ret *ret) { - return marshal_stat(ctx, val, ret); -} diff --git a/lib9p/CMakeLists.txt b/lib9p/CMakeLists.txt index 707308e..e81e7b9 100644 --- a/lib9p/CMakeLists.txt +++ b/lib9p/CMakeLists.txt @@ -3,25 +3,69 @@ # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later -add_library(lib9p INTERFACE) -target_include_directories(lib9p SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_sources(lib9p INTERFACE - 9p.generated.c - 9p.c +add_library(lib9p_core INTERFACE) +target_include_directories(lib9p_core PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/core_include) +target_sources(lib9p_core INTERFACE + core.c + core_generated.c +) +target_link_libraries(lib9p_core INTERFACE + libhw_generic + libmisc +) + +add_library(lib9p_srv INTERFACE) +target_include_directories(lib9p_srv PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/srv_include) +target_sources(lib9p_srv INTERFACE srv.c + srv_generated.c ) -target_link_libraries(lib9p INTERFACE +target_link_libraries(lib9p_srv INTERFACE + lib9p_core libcr_ipc - libmisc - libhw_generic ) if (ENABLE_TESTS) add_subdirectory(tests/test_server) - add_test( - NAME "lib9p/runtest" - COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/runtest" + + function(add_lib9p_executable arg_testname) + add_executable("${arg_testname}" "tests/${arg_testname}.c") + target_link_libraries("${arg_testname}" lib9p_core) + target_include_directories("${arg_testname}" PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/tests + ${CMAKE_CURRENT_SOURCE_DIR}/tests/client_config + ) + endfunction() + function(add_lib9p_test arg_testscript) + get_filename_component(tmp_basename "${arg_testscript}" "NAME") + add_test( + NAME "lib9p/${tmp_basename}" + COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/runtest" "${arg_testscript}" "${CMAKE_CURRENT_SOURCE_DIR}/tests/${tmp_basename}.explog" + ) + endfunction() + + add_lib9p_test("${CMAKE_CURRENT_SOURCE_DIR}/tests/testclient-p9p") + + add_lib9p_executable("testclient-sess") + add_lib9p_test("./testclient-sess") + + add_lib9p_executable("testclient-hangup") + add_lib9p_test("./testclient-hangup") + + set(cfg_matrix + "CONFIG_9P_SRV_DEBUG;[0;1]" + "CONFIG_9P_ENABLE_9P2000;[0;1]" + "CONFIG_9P_ENABLE_9P2000_u;[0;1]" + "CONFIG_9P_ENABLE_9P2000_e;[0;1]" + "CONFIG_9P_ENABLE_9P2000_L;[0;1]" + "CONFIG_9P_ENABLE_9P2000_p9p;[0;1]" ) - add_lib_test(lib9p test_compile) - target_include_directories(test_compile PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_compile_config) + function(add_compile_test n defs) + add_executable("test_compile${n}" "tests/test_compile.c") + target_link_libraries("test_compile${n}" lib9p_srv) + target_include_directories("test_compile${n}" PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_compile_config) + target_compile_definitions("test_compile${n}" PUBLIC "${defs}") + # Don't bother running it (don't bother calling add_test()) + endfunction() + apply_matrix(add_compile_test "${cfg_matrix}") endif() diff --git a/lib9p/core.c b/lib9p/core.c new file mode 100644 index 0000000..58fe538 --- /dev/null +++ b/lib9p/core.c @@ -0,0 +1,213 @@ +/* lib9p/core.c - Base 9P protocol utilities for both clients and servers + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <string.h> /* for strlen(), strnlen(), strncpy(), memcmp(), memset() */ + +#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) { + if (!s) + return (struct lib9p_s){}; + return (struct lib9p_s){ + .len = strlen(s), + .utf8 = s, + }; +} +struct lib9p_s lib9p_strn(char *s, size_t maxlen) { + if (maxlen == 0 || !s) + return (struct lib9p_s){}; + return (struct lib9p_s){ + .len = strnlen(s, maxlen), + .utf8 = s, + }; +} +struct lib9p_s lib9p_str_slice(struct lib9p_s s, uint16_t beg, uint16_t end) { + assert(s.len == 0 || s.utf8); + assert(beg <= end && end <= s.len); + return (struct lib9p_s){ + .len = end - beg, + .utf8 = &s.utf8[beg], + }; +} +bool lib9p_str_eq(struct lib9p_s a, struct lib9p_s b) { + return a.len == b.len && + (a.len == 0 || memcmp(a.utf8, b.utf8, a.len) == 0); +} + +/* 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_Rerror_size(enum lib9p_version ver) { + assert_ver(ver); + return _lib9p_table_ver[ver].min_Rerror_size; +} + +uint32_t lib9p_version_min_Rread_size(enum lib9p_version ver) { + assert_ver(ver); + return _lib9p_table_ver[ver].min_Rread_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); +} + +/* main message functions *****************************************************/ + +void fmt_print_lib9p_msg(lo_interface fmt_dest w, 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].print); + _lib9p_table_msg[ctx->version][typ].print(w, ctx, body); +} + +#define _lib9p_validate(LOW_TYP_BIT, ERRMSG, TABLE) do { \ + assert_ver(ctx->version); \ + /* Inspect the first 5 bytes ourselves. */ \ + uint32_t net_size = uint32le_decode(net_bytes); \ + if (net_size < 5) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is impossibly short")); \ + uint8_t typ = net_bytes[4]; \ + if (typ % 2 != LOW_TYP_BIT) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EOPNOTSUPP, ERRMSG ": message_type=", \ + lib9p_msgtype_str(ctx->version, typ))); \ + struct _lib9p_recv_tentry tentry = TABLE[ctx->version][typ/2]; \ + if (!tentry.validate) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EOPNOTSUPP, "unknown message type: ", \ + lib9p_msgtype_str(ctx->version, typ), \ + " (protocol_version=", 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); \ +} while (0) + +size_t_or_error lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) { + _lib9p_validate(0, "expected a T-message but got an R-message", _lib9p_table_Tmsg_recv); +} + +size_t_or_error lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) { + _lib9p_validate(1, "expected an R-message but got a T-message", _lib9p_table_Rmsg_recv); +} + +#define _lib9p_unmarshal(TABLE) do { \ + assert_ver(ctx->version); \ + enum lib9p_msg_type typ = net_bytes[4]; \ + *ret_typ = typ; \ + struct _lib9p_recv_tentry tentry = TABLE[ctx->version][typ/2]; \ + assert(tentry.unmarshal); \ + \ + tentry.unmarshal(ctx, net_bytes, ret_body); \ +} while (0) + +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); +} + +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); +} + +#define _lib9p_marshal(LOW_TYP_BIT, TABLE) do { \ + assert_ver(ctx->version); \ + assert(typ % 2 == LOW_TYP_BIT); \ + assert_typ(typ); \ + \ + memset(ret, 0, sizeof(*ret)); \ + \ + 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 = TABLE[ctx->version][typ/2]; \ + assert(tentry.marshal); \ + \ + error ret_err = tentry.marshal(ctx, body, &_ret); \ + if (_ret.net_iov[_ret.net_iov_cnt-1].iov_len == 0) \ + _ret.net_iov_cnt--; \ + \ + ret->iov_cnt = _ret.net_iov_cnt; \ + return ret_err; \ +} while (0) + +error lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, + struct lib9p_Tmsg_send_buf *ret) { + _lib9p_marshal(0, _lib9p_table_Tmsg_send); +} + +error lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, + struct lib9p_Rmsg_send_buf *ret) { + _lib9p_marshal(1, _lib9p_table_Rmsg_send); +} + +/* `struct lib9p_stat` helpers ************************************************/ + +#if _LIB9P_ENABLE_stat +error 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) { + size_t_or_error host_size = _lib9p_stat_validate(ctx, net_size, net_bytes, ret_net_size); + if (host_size.is_err) + return host_size.err; + if (ret_host_size) + *ret_host_size = host_size.size_t; + return ERROR_NULL; +} + +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 = {}; + 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/proto.gen b/lib9p/core.gen index 60f1347..24f66de 100755 --- a/lib9p/proto.gen +++ b/lib9p/core.gen @@ -1,6 +1,6 @@ -#!/usr/bin/env python -# lib9p/proto.gen - Generate C marshalers/unmarshalers for .9p files -# defining 9P protocol variants. +#!/usr/bin/env python3 +# lib9p/core.gen - Generate C marshalers/unmarshalers for .9p files +# defining 9P protocol variants. # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later @@ -9,7 +9,7 @@ import os.path import sys sys.path.insert(0, os.path.normpath(os.path.join(__file__, ".."))) -import protogen # pylint: disable=wrong-import-position +import core_gen # pylint: disable=wrong-import-position if __name__ == "__main__": - protogen.main() + core_gen.main() diff --git a/lib9p/protogen/__init__.py b/lib9p/core_gen/__init__.py index c2c6173..b0da237 100644 --- a/lib9p/protogen/__init__.py +++ b/lib9p/core_gen/__init__.py @@ -1,4 +1,4 @@ -# lib9p/protogen/__init__.py - Generate C marshalers/unmarshalers for +# lib9p/core_gen/__init__.py - Generate C marshalers/unmarshalers for # .9p files defining 9P protocol variants # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> @@ -50,8 +50,10 @@ def main() -> None: versions, typs = parser.all() outdir = os.path.normpath(os.path.join(sys.argv[0], "..")) with open( - os.path.join(outdir, "include/lib9p/9p.generated.h"), "w", encoding="utf-8" + os.path.join(outdir, "core_include/lib9p/_core_generated.h"), + "w", + encoding="utf-8", ) as fh: fh.write(h.gen_h(versions, typs)) - with open(os.path.join(outdir, "9p.generated.c"), "w", encoding="utf-8") as fh: + with open(os.path.join(outdir, "core_generated.c"), "w", encoding="utf-8") as fh: fh.write(c.gen_c(versions, typs)) diff --git a/lib9p/protogen/c.py b/lib9p/core_gen/c.py index 5e67939..ab34387 100644 --- a/lib9p/protogen/c.py +++ b/lib9p/core_gen/c.py @@ -1,4 +1,4 @@ -# lib9p/protogen/c.py - Generate 9p.generated.c +# lib9p/core_gen/c.py - Generate core_generated.c # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later @@ -7,7 +7,7 @@ import sys import idl -from . import c9util, c_marshal, c_unmarshal, c_validate, cutil +from . import c9util, c_fmt_print, c_marshal, c_unmarshal, c_validate, cutil # This strives to be "general-purpose" in that it just acts on the # *.9p inputs; but (unfortunately?) there are a few special-cases in @@ -23,18 +23,17 @@ def gen_c(versions: set[str], typs: list[idl.UserType]) -> str: ret = f"""/* Generated by `{' '.join(sys.argv)}`. DO NOT EDIT! */ -#include <stdbool.h> -#include <stddef.h> /* for size_t */ -#include <inttypes.h> /* for PRI* macros */ -#include <string.h> /* for memset() */ +#include <stddef.h> /* for size_t */ +#include <string.h> /* for memset() */ #include <libmisc/assert.h> +#include <libmisc/endian.h> +#include <libmisc/utf8.h> -#include <lib9p/9p.h> +#include <lib9p/core.h> -#include "internal.h" +#include "core_tables.h" """ - # utilities ################################################################ ret += """ /* utilities ******************************************************************/ @@ -44,28 +43,6 @@ def gen_c(versions: set[str], typs: list[idl.UserType]) -> str: for msg in [msg for msg in typs if isinstance(msg, idl.Message)]: id2typ[msg.msgid] = msg - def msg_table(grp: str, meth: str, tentry: str, rng: tuple[int, int, int]) -> str: - ret = f"const {tentry} {c9util.ident(f'_table_{grp}_{meth}')}[{c9util.ver_enum('NUM')}][{hex(len(range(*rng)))}] = {{\n" - for ver in ["unknown", *sorted(versions)]: - if ver != "unknown": - ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) - ret += f"\t[{c9util.ver_enum(ver)}] = {{\n" - for n in range(*rng): - xmsg: idl.Message | None = id2typ.get(n, None) - if xmsg: - if ver == "unknown": # SPECIAL (initialization) - if xmsg.typname not in ["Tversion", "Rversion", "Rerror"]: - xmsg = None - else: - if ver not in xmsg.in_versions: - xmsg = None - if xmsg: - ret += f"\t\t_MSG_{meth.upper()}({xmsg.typname}),\n" - ret += "\t},\n" - ret += cutil.ifdef_pop(0) - ret += "};\n" - return ret - for v in sorted(versions): ret += f"#if CONFIG_9P_ENABLE_{v.replace('.', '_')}\n" ret += ( @@ -83,23 +60,6 @@ def gen_c(versions: set[str], typs: list[idl.UserType]) -> str: ret += " */\n" ret += "#define is_ver(ctx, ver) _is_ver_##ver((ctx)->version)\n" - # strings ################################################################## - ret += f""" -/* strings ********************************************************************/ - -const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] = {{ -""" - for ver in ["unknown", *sorted(versions)]: - if ver in versions: - ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) - ret += f'\t[{c9util.ver_enum(ver)}] = "{ver}",\n' - ret += cutil.ifdef_pop(0) - ret += "};\n" - - ret += "\n" - ret += f"#define _MSG_NAME(typ) [{c9util.Ident('TYP_')}##typ] = #typ\n" - ret += msg_table("msg", "name", "char *const", (0, 0x100, 1)) - # bitmasks ################################################################# ret += """ /* bitmasks *******************************************************************/ @@ -108,7 +68,9 @@ const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] = if not isinstance(typ, idl.Bitfield): continue ret += "\n" - ret += cutil.ifdef_push(1, c9util.ver_ifdef(typ.in_versions)) + ret += cutil.ifdef_push( # SPECIAL (initialization) + 1, c9util.ver_ifdef(typ.in_versions - {"uninitialized"}) + ) ret += f"static const {c9util.typename(typ)} {typ.typname}_masks[{c9util.ver_enum('NUM')}] = {{\n" verwidth = max(len(ver) for ver in versions) for ver in sorted(versions): @@ -118,7 +80,7 @@ const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] = + "".join( ( "1" - if bit.cat in (idl.BitCat.USED, idl.BitCat.SUBFIELD) + if (bit.cat == "USED" or isinstance(bit.cat, idl.BitNum)) and ver in bit.in_versions else "0" ) @@ -139,25 +101,60 @@ const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] = # marshal_* ################################################################ ret += c_marshal.gen_c_marshal(versions, typs) - # function tables ########################################################## + # fmt_print_* ############################################################## + ret += c_fmt_print.gen_c_fmt_print(versions, typs) + + # tables.h ################################################################# ret += """ -/* function tables ************************************************************/ +/* tables.h *******************************************************************/ """ ret += "\n" - ret += f"const uint32_t {c9util.ident('_table_msg_min_size')}[{c9util.ver_enum('NUM')}] = {{\n" + ret += f"const struct {c9util.ident('_ver_tentry')} {c9util.ident('_table_ver')}[{c9util.ver_enum('NUM')}] = {{\n" rerror = next(typ for typ in typs if typ.typname == "Rerror") - ret += f"\t[{c9util.ver_enum('unknown')}] = {rerror.min_size('9P2000')},\n" # SPECIAL (initialization) + rlerror = next(typ for typ in typs if typ.typname == "Rlerror") + rread = next(typ for typ in typs if typ.typname == "Rread") for ver in sorted(versions): ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) - ret += f"\t[{c9util.ver_enum(ver)}] = {rerror.min_size(ver)},\n" + min_rerror_size = rerror.min_size(ver) + if ver == "9P2000.L": # SPECIAL (9P2000.L) + min_rerror_size = rlerror.min_size(ver) + min_rread_size = rread.min_size(ver) + ret += f'\t[{c9util.ver_enum(ver)}] = {{.name="{ver}", .min_Rerror_size={min_rerror_size}, .min_Rread_size={min_rread_size}}},\n' ret += cutil.ifdef_pop(0) ret += "};\n" + def msg_table( + cstruct: str, cname: str, each: str, _range: tuple[int, int, int] + ) -> str: + ret = f"const struct {c9util.ident(cstruct)} {c9util.ident(cname)}[{c9util.ver_enum('NUM')}][{hex(len(range(*_range)))}] = {{\n" + for ver in sorted(versions): + ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) + ret += f"\t[{c9util.ver_enum(ver)}] = {{\n" + for n in range(*_range): + xmsg: idl.Message | None = id2typ.get(n, None) + if xmsg: + if ver not in xmsg.in_versions: + xmsg = None + if xmsg: + ret += f"\t\t{each}({xmsg.typname}),\n" + ret += "\t},\n" + ret += cutil.ifdef_pop(0) + ret += "};\n" + return ret + + ret += "\n" + ret += cutil.macro( + f"#define _MSG(typ) [{c9util.Ident('TYP_')}##typ] = {{\n" + f"\t\t.name = #typ,\n" + f"\t\t.print = (_print_fn_t)fmt_print_##typ,\n" + f"\t}}\n" + ) + ret += msg_table("_msg_tentry", "_table_msg", "_MSG", (0, 0x100, 1)) + ret += "\n" ret += cutil.macro( f"#define _MSG_RECV(typ) [{c9util.Ident('TYP_')}##typ/2] = {{\n" - f"\t\t.basesize = sizeof(struct {c9util.ident('msg_')}##typ),\n" f"\t\t.validate = validate_##typ,\n" f"\t\t.unmarshal = (_unmarshal_fn_t)unmarshal_##typ,\n" f"\t}}\n" @@ -168,24 +165,17 @@ const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] = f"\t}}\n" ) ret += "\n" - ret += msg_table( - "Tmsg", "recv", f"struct {c9util.ident('_recv_tentry')}", (0, 0x100, 2) - ) + ret += msg_table("_recv_tentry", "_table_Tmsg_recv", "_MSG_RECV", (0, 0x100, 2)) ret += "\n" - ret += msg_table( - "Rmsg", "recv", f"struct {c9util.ident('_recv_tentry')}", (1, 0x100, 2) - ) + ret += msg_table("_recv_tentry", "_table_Rmsg_recv", "_MSG_RECV", (1, 0x100, 2)) ret += "\n" - ret += msg_table( - "Tmsg", "send", f"struct {c9util.ident('_send_tentry')}", (0, 0x100, 2) - ) + ret += msg_table("_send_tentry", "_table_Tmsg_send", "_MSG_SEND", (0, 0x100, 2)) ret += "\n" - ret += msg_table( - "Rmsg", "send", f"struct {c9util.ident('_send_tentry')}", (1, 0x100, 2) - ) + ret += msg_table("_send_tentry", "_table_Rmsg_send", "_MSG_SEND", (1, 0x100, 2)) ret += f""" -LM_FLATTEN ssize_t {c9util.ident('_stat_validate')}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{ +{cutil.ifdef_push(1, c9util.ver_ifdef(next(typ for typ in typs if typ.typname == 'stat').in_versions)).rstrip()} +LM_FLATTEN size_t_or_error {c9util.ident('_stat_validate')}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{ \treturn validate_stat(ctx, net_size, net_bytes, ret_net_size); }} LM_FLATTEN void {c9util.ident('_stat_unmarshal')}(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out) {{ @@ -194,7 +184,7 @@ LM_FLATTEN void {c9util.ident('_stat_unmarshal')}(struct lib9p_ctx *ctx, uint8_t LM_FLATTEN bool {c9util.ident('_stat_marshal')}(struct lib9p_ctx *ctx, struct {c9util.ident('stat')} *val, struct _marshal_ret *ret) {{ \treturn marshal_stat(ctx, val, ret); }} -""" +{cutil.ifdef_pop(0)}""" ############################################################################ return ret diff --git a/lib9p/protogen/c9util.py b/lib9p/core_gen/c9util.py index e7ad999..a304ff4 100644 --- a/lib9p/protogen/c9util.py +++ b/lib9p/core_gen/c9util.py @@ -1,8 +1,9 @@ -# lib9p/protogen/c9util.py - Utilities for generating lib9p-specific C +# lib9p/core_gen/c9util.py - Utilities for generating lib9p-specific C # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later +import re import typing import idl @@ -72,38 +73,64 @@ def ver_cond(versions: typing.Collection[str]) -> str: # misc ######################################################################### +def basename(typ: idl.UserType) -> str: + match typ: + case idl.Number(): + return ident(typ.typname) + case idl.Bitfield(): + return ident(typ.typname) + case idl.Message(): + return ident(f"msg_{typ.typname}") + case idl.Struct(): + return ident(typ.typname) + case _: + raise ValueError(f"not a defined type: {typ.__class__.__name__}") + + def typename(typ: idl.Type, parent: idl.StructMember | None = None) -> str: match typ: case idl.Primitive(): if typ.value == 1 and parent and parent.cnt: # SPECIAL (string) + if parent.membname == "data": # SPECIAL (iovec) + return f"struct {ident('_iovec')}" return "[[gnu::nonstring]] char" return f"uint{typ.value*8}_t" case idl.Number(): - return ident(f"{typ.typname}_t") + return f"{basename(typ)}_t" case idl.Bitfield(): - return ident(f"{typ.typname}_t") + return f"{basename(typ)}_t" case idl.Message(): - return f"struct {ident(f'msg_{typ.typname}')}" + return f"struct {basename(typ)}" case idl.Struct(): - return f"struct {ident(typ.typname)}" + return f"struct {basename(typ)}" case _: raise ValueError(f"not a type: {typ.__class__.__name__}") -def idl_expr(expr: idl.Expr, lookup_sym: typing.Callable[[str], str]) -> str: +def idl_expr( + expr: idl.Expr, lookup_sym: typing.Callable[[str], str], bitwidth: int = 0 +) -> str: ret: list[str] = [] for tok in expr.tokens: match tok: case idl.ExprOp(): ret.append(tok.op) case idl.ExprLit(): - ret.append(str(tok.val)) - case idl.ExprSym(symname="s32_max"): - ret.append("INT32_MAX") - case idl.ExprSym(symname="s64_max"): - ret.append("INT64_MAX") + if bitwidth: + ret.append(f"{tok.val:#0{bitwidth}b}") + else: + ret.append(str(tok.val)) case idl.ExprSym(): - ret.append(lookup_sym(tok.symname)) + if m := re.fullmatch(r"^u(8|16|32|64)_max$", tok.symname): + ret.append(f"UINT{m.group(1)}_MAX") + elif m := re.fullmatch(r"^s(8|16|32|64)_max$", tok.symname): + ret.append(f"INT{m.group(1)}_MAX") + else: + ret.append(lookup_sym(tok.symname)) + case idl.ExprOff(): + ret.append(lookup_sym("&" + tok.membname)) + case idl.ExprNum(): + ret.append(Ident(add_prefix(f"{tok.numname}_".upper(), tok.valname))) case _: assert False return " ".join(ret) diff --git a/lib9p/core_gen/c_fmt_print.py b/lib9p/core_gen/c_fmt_print.py new file mode 100644 index 0000000..7a0a9d3 --- /dev/null +++ b/lib9p/core_gen/c_fmt_print.py @@ -0,0 +1,146 @@ +# lib9p/core_gen/c_fmt_print.py - Generate C pretty-print functions +# +# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + + +import idl + +from . import c9util, cutil, idlutil + +# This strives to be "general-purpose" in that it just acts on the +# *.9p inputs; but (unfortunately?) there are a few special-cases in +# this script, marked with "SPECIAL". + +# pylint: disable=unused-variable +__all__ = ["gen_c_fmt_print"] + + +def bf_numname(typ: idl.Bitfield, num: idl.BitNum, base: str) -> str: + prefix = f"{typ.typname}_{num.numname}_".upper() + return c9util.Ident(c9util.add_prefix(prefix, base)) + + +def gen_c_fmt_print(versions: set[str], typs: list[idl.UserType]) -> str: + ret = """ +/* fmt_print_* ****************************************************************/ +""" + for typ in idlutil.topo_sorted(typs): + ret += "\n" + ret += cutil.ifdef_push(1, c9util.ver_ifdef(typ.in_versions)) + storage = "" if typ.typname == "stat" else "static " # SPECIAL (stat is public) + ret += f"[[maybe_unused]] {storage}void fmt_print_{typ.typname}(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, {c9util.typename(typ)} *self) {{\n" + match typ: + case idl.Number(): + if typ.vals: + ret += "\tswitch (*self) {\n" + for name in typ.vals: + ret += f"\tcase {c9util.Ident(c9util.add_prefix(f'{typ.typname}_'.upper(), name))}:\n" + ret += f'\t\tfmt_print_str(w, "{name}");\n' + ret += "\t\tbreak;\n" + ret += "\tdefault:\n" + ret += "\t\tfmt_print_base10(w, *self);\n" + ret += "\t}\n" + else: + ret += "\t\tfmt_print_base10(w, *self);\n" + case idl.Bitfield(): + val = "*self" + if typ.typname == "dm": # SPECIAL (pretty file permissions) + val = f"(*self & ~(({c9util.typename(typ)})0777))" + ret += "\tbool empty = true;\n" + ret += "\tfmt_print_byte(w, '(');\n" + nums: set[str] = set() + + for bit in reversed(typ.bits): + match bit.cat: + case "UNUSED" | "USED" | "RESERVED": + if bit.cat == "UNUSED": + bitname = f"1<<{bit.num}" + else: + bitname = bit.bitname + ret += f"\tif ({val} & (UINT{typ.static_size*8}_C(1)<<{bit.num})) {{\n" + ret += "\t\tif (!empty)\n" + ret += "\t\t\tfmt_print_byte(w, '|');\n" + ret += f'\t\tfmt_print_str(w, "{bitname}");\n' + ret += "\t\tempty = false;\n" + ret += "\t}\n" + case idl.BitNum(): + if bit.cat.numname in nums: + continue + ret += f"\tswitch ({val} & {bf_numname(typ, bit.cat, 'MASK')}) {{\n" + for name in bit.cat.vals: + ret += f"\tcase {bf_numname(typ, bit.cat, name)}:\n" + bitname = c9util.add_prefix( + f"{bit.cat.numname}_".upper(), name + ) + ret += "\t\tif (!empty)\n" + ret += "\t\t\tfmt_print_byte(w, '|');\n" + ret += f'\t\tfmt_print_str(w, "{bitname}");\n' + ret += "\t\tempty = false;\n" + ret += "\t\tbreak;\n" + ret += "\tdefault:\n" + ret += "\t\tif (!empty)\n" + ret += "\t\t\tfmt_print_byte(w, '|');\n" + ret += f"\t\tfmt_print_base10(w, {val} & {bf_numname(typ, bit.cat, 'MASK')});\n" + ret += "\t\tempty = false;\n" + ret += "\t}\n" + nums.add(bit.cat.numname) + if typ.typname == "dm": # SPECIAL (pretty file permissions) + ret += "\tif (!empty)\n" + ret += "\t\tfmt_print_byte(w, '|');\n" + ret += "\tfmt_print(w, (rjust, 4, '0', (base8, *self & 0777)));\n" + else: + ret += "\tif (empty)\n" + ret += "\t\tfmt_print_byte(w, '0');\n" + ret += "\tfmt_print_byte(w, ')');\n" + case idl.Struct(typname="s"): # SPECIAL (string) + ret += "\tfmt_print_qmem(w, self->utf8, self->len);\n" + case idl.Struct(): # and idl.Message(): + if isinstance(typ, idl.Message): + ret += f'\tfmt_print_str(w, "{typ.typname} {{");\n' + else: + ret += "\tfmt_print_byte(w, '{');\n" + for member in typ.members: + if member.val: + continue + ret += cutil.ifdef_push(2, c9util.ver_ifdef(member.in_versions)) + if member.cnt: + if isinstance(member.cnt, int): + cnt_str = str(member.cnt) + cnt_typ = "size_t" + else: + cnt_str = f"self->{member.cnt.membname}" + cnt_typ = c9util.typename(member.cnt.typ) + if member.typ.static_size == 1: # SPECIAL (data) + ret += f"\tif (utf8_is_valid_without_nul((uint8_t *)self->{member.membname}, (size_t){cnt_str})) {{\n" + ret += f'\t\tfmt_print_str(w, " {member.membname}=");\n' + ret += f"\t\tfmt_print_qmem(w, self->{member.membname}, {cnt_str} < 50 ? {cnt_str} : 50);\n" + ret += f"\t\tif ({cnt_str} > 50)\n" + ret += '\t\t\tfmt_print_str(w, "...");\n' + ret += "\t} else {\n" + ret += f'\t\tfmt_print_str(w, " {member.membname}=<bytedata>");\n' + ret += "\t}\n" + continue + ret += f'\tfmt_print_str(w, " {member.membname}=[");\n' + ret += f"\tfor ({cnt_typ} i = 0; i < {cnt_str}; i++) {{\n" + ret += "\t\tif (i)\n" + ret += "\t\t\tfmt_print_byte(w, ',');\n" + ret += "\t\tfmt_print_byte(w, ' ');\n" + if isinstance(member.typ, idl.Primitive): + ret += f"\t\tfmt_print_base10(w, self->{member.membname}[i]);\n" + else: + ret += f"\t\tfmt_print_{member.typ.typname}(w, ctx, &self->{member.membname}[i]);\n" + ret += "\t}\n" + ret += '\tfmt_print_str(w, " ]");\n' + else: + ret += f'\tfmt_print_str(w, " {member.membname}=");\n' + if isinstance(member.typ, idl.Primitive): + ret += f"\tfmt_print_base10(w, self->{member.membname});\n" + else: + ret += f"\tfmt_print_{member.typ.typname}(w, ctx, &self->{member.membname});\n" + ret += cutil.ifdef_pop(1) + ret += '\tfmt_print_str(w, " }");\n' + ret += "}\n" + ret += cutil.ifdef_pop(0) + + return ret diff --git a/lib9p/protogen/c_marshal.py b/lib9p/core_gen/c_marshal.py index 74b64f5..af8d582 100644 --- a/lib9p/protogen/c_marshal.py +++ b/lib9p/core_gen/c_marshal.py @@ -1,4 +1,4 @@ -# lib9p/protogen/c_marshal.py - Generate C marshal functions +# lib9p/core_gen/c_marshal.py - Generate C marshal functions # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later @@ -23,7 +23,7 @@ __all__ = ["gen_c_marshal"] class OffsetExpr: static: int cond: dict[frozenset[str], "OffsetExpr"] - rep: list[tuple[idlutil.Path, "OffsetExpr"]] + rep: list[tuple[idlutil.Path | int, "OffsetExpr"]] def __init__(self) -> None: self.static = 0 @@ -52,14 +52,20 @@ class OffsetExpr: if self.static: oneline.append(str(self.static)) for cnt, sub in self.rep: + if isinstance(cnt, int): + cnt_str = str(cnt) + cnt_typ = "size_t" + else: + cnt_str = cnt.c_str(root) + cnt_typ = c9util.typename(cnt.elems[-1].typ) if not sub.cond and not sub.rep: if sub.static == 1: - oneline.append(cnt.c_str(root)) + oneline.append(cnt_str) else: - oneline.append(f"({cnt.c_str(root)})*{sub.static}") + oneline.append(f"({cnt_str})*{sub.static}") continue loopvar = chr(ord("i") + loop_depth) - multiline += f"{'\t'*indent_depth}for ({c9util.typename(cnt.elems[-1].typ)} {loopvar} = 0; {loopvar} < {cnt.c_str(root)}; {loopvar}++) {{\n" + multiline += f"{'\t'*indent_depth}for ({cnt_typ} {loopvar} = 0; {loopvar} < {cnt_str}; {loopvar}++) {{\n" multiline += sub.gen_c("", dstvar, root, indent_depth + 1, loop_depth + 1) multiline += f"{'\t'*indent_depth}}}\n" for vers, sub in self.cond.items(): @@ -113,8 +119,12 @@ def get_offset_expr(typ: idl.UserType, recurse: OffsetExprRecursion) -> OffsetEx member_path = expr_stack[-1].path member = member_path.elems[-1] assert member.cnt - cnt_path = member_path.parent().add(member.cnt) - expr_stack[-2].expr.rep.append((cnt_path, expr_stack[-1].expr)) + cnt: idlutil.Path | int + if isinstance(member.cnt, int): + cnt = member.cnt + else: + cnt = member_path.parent().add(member.cnt) + expr_stack[-2].expr.rep.append((cnt, expr_stack[-1].expr)) expr_stack = expr_stack[:-1] def handle( @@ -268,11 +278,13 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str: if not member.val: continue for tok in member.val.tokens: - if not isinstance(tok, idl.ExprSym): - continue - if tok.symname == "end" or tok.symname.startswith("&"): - if tok.symname not in offsets: - offsets.append(tok.symname) + match tok: + case idl.ExprSym(symname="end"): + if tok.symname not in offsets: + offsets.append(tok.symname) + case idl.ExprOff(): + if f"&{tok.membname}" not in offsets: + offsets.append(f"&{tok.membname}") for name in offsets: name_prefix = f"offsetof{''.join('_'+m.membname for m in path.elems)}_" if name == "end": @@ -313,15 +325,23 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str: ) indent_stack.append(IndentLevel(ifdef=True)) if child.cnt: - cnt_path = path.parent().add(child.cnt) + if isinstance(child.cnt, int): + cnt_str = str(child.cnt) + cnt_typ = "size_t" + else: + cnt_str = path.parent().add(child.cnt).c_str("val->") + cnt_typ = c9util.typename(child.cnt.typ) if child.typ.static_size == 1: # SPECIAL (zerocopy) if path.root.typname == "stat": # SPECIAL (stat) - ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES(ctx, {path.c_str('val->')[:-3]}, {cnt_path.c_str('val->')});\n" + ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES(ctx, {path.c_str('val->')[:-3]}, {cnt_str});\n" + elif c9util.typename(child.typ, child) == f"struct {c9util.ident("_iovec")}": # SPECIAL (iovec) + ret += f"{'\t'*indent_lvl()}for (int iov_i = 0; iov_i < {path.c_str('val->')[:-3]}->iovcnt; iov_i++)\n" + ret += f"{'\t'*(indent_lvl()+1)}MARSHAL_BYTES_ZEROCOPY(ctx, {path.c_str('val->')[:-3]}->iov[iov_i].iov_base, {path.c_str('val->')[:-3]}->iov[iov_i].iov_len);\n" else: - ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES_ZEROCOPY(ctx, {path.c_str('val->')[:-3]}, {cnt_path.c_str('val->')});\n" + ret += f"{'\t'*indent_lvl()}MARSHAL_BYTES_ZEROCOPY(ctx, {path.c_str('val->')[:-3]}, {cnt_str});\n" return idlutil.WalkCmd.KEEP_GOING, pop loopvar = chr(ord("i") + loopdepth - 1) - ret += f"{'\t'*indent_lvl()}for ({c9util.typename(child.cnt.typ)} {loopvar} = 0; {loopvar} < {cnt_path.c_str('val->')}; {loopvar}++) {{\n" + ret += f"{'\t'*indent_lvl()}for ({cnt_typ} {loopvar} = 0; {loopvar} < {cnt_str}; {loopvar}++) {{\n" indent_stack.append(IndentLevel(ifdef=False)) if not isinstance(child.typ, idl.Struct): if child.val: @@ -348,27 +368,30 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str: assert isinstance(typ, idl.Struct) ret += "\n" ret += cutil.ifdef_push(1, c9util.ver_ifdef(typ.in_versions)) - ret += f"static bool marshal_{typ.typname}(struct lib9p_ctx *ctx, {c9util.typename(typ)} *val, struct _marshal_ret *ret) {{\n" + if not isinstance(typ, idl.Message): # SPECIAL (bool for stat) + ret += f"static bool marshal_{typ.typname}(struct lib9p_ctx *ctx, {c9util.typename(typ)} *val, struct _marshal_ret *ret) {{\n" + else: + ret += f"static error marshal_{typ.typname}(struct lib9p_ctx *ctx, {c9util.typename(typ)} *val, struct _marshal_ret *ret) {{\n" # Pass 1 - check size max_size = max(typ.max_size(v) for v in typ.in_versions) + szbits = 32 if max_size > cutil.UINT32_MAX: # SPECIAL (9P2000.e) - ret += get_offset_expr(typ, go_to_end).gen_c( - "uint64_t", "needed_size", "val->", 1, 0 - ) + szbits = 64 + ret += get_offset_expr(typ, go_to_end).gen_c( + f"uint{szbits}_t", "needed_size", "val->", 1, 0 + ) + if szbits > 32: # SPECIAL (9P2000.e) ret += "\tif (needed_size > (uint64_t)(ctx->max_msg_size)) {\n" else: - ret += get_offset_expr(typ, go_to_end).gen_c( - "uint32_t", "needed_size", "val->", 1, 0 - ) ret += "\tif (needed_size > ctx->max_msg_size) {\n" - if isinstance(typ, idl.Message): # SPECIAL (disable for stat) - ret += '\t\tlib9p_errorf(ctx, LINUX_ERANGE, "%s message too large to marshal into %s limit (limit=%"PRIu32")",\n' - ret += f'\t\t\t"{typ.typname}",\n' - ret += f'\t\t\tctx->version ? "negotiated" : "{'client' if typ.msgid % 2 == 0 else 'server'}",\n' - ret += "\t\t\tctx->max_msg_size);\n" - ret += "\t\treturn true;\n" + if not isinstance(typ, idl.Message): # SPECIAL (bool for stat) + ret += "\t\treturn true;\n" + else: + ret += f'\t\treturn error_new(E_POSIX_ERANGE, "{typ.typname} message too large to marshal into ",\n' + ret += f'\t\t\tctx->version ? "negotiated" : "{'client' if typ.msgid % 2 == 0 else 'server'}", " limit",\n' + ret += '\t\t\t" (", needed_size, " > ", ctx->max_msg_size, ")");\n' ret += "\t}\n" # Pass 2 - write data @@ -380,7 +403,10 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str: ret += cutil.ifdef_pop(ifdef_lvl()) # Return - ret += "\treturn false;\n" + if not isinstance(typ, idl.Message): # SPECIAL (bool for stat) + ret += "\treturn false;\n" + else: + ret += "\treturn ERROR_NULL;\n" ret += "}\n" ret += cutil.ifdef_pop(0) return ret diff --git a/lib9p/protogen/c_unmarshal.py b/lib9p/core_gen/c_unmarshal.py index 018d750..c510e44 100644 --- a/lib9p/protogen/c_unmarshal.py +++ b/lib9p/core_gen/c_unmarshal.py @@ -1,4 +1,4 @@ -# lib9p/protogen/c_unmarshal.py - Generate C unmarshal functions +# lib9p/core_gen/c_unmarshal.py - Generate C unmarshal functions # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later @@ -93,15 +93,27 @@ def gen_c_unmarshal(versions: set[str], typs: list[idl.UserType]) -> str: ) indent_stack.append(IndentLevel(ifdef=True)) if child.cnt: - cnt_path = path.parent().add(child.cnt) + if isinstance(child.cnt, int): + cnt_str = str(child.cnt) + cnt_typ = "size_t" + else: + cnt_str = path.parent().add(child.cnt).c_str("out->") + cnt_typ = c9util.typename(child.cnt.typ) if child.typ.static_size == 1: # SPECIAL (zerocopy) - ret += f"{'\t'*indent_lvl()}UNMARSHAL_BYTES(ctx, {path.c_str('out->')[:-3]}, {cnt_path.c_str('out->')});\n" + if c9util.typename(child.typ, child) == f"struct {c9util.ident('_iovec')}": # SPECIAL (iovec) + ret += f"{'\t'*indent_lvl()}out->{child.membname}.iov = ctx->extra;\n" + ret += f"{'\t'*indent_lvl()}ctx->extra += sizeof(out->{child.membname}.iov[0]);\n" + ret += f"{'\t'*indent_lvl()}out->{child.membname}.iov->iov_base = &ctx->net_bytes[ctx->net_offset];\n" + ret += f"{'\t'*indent_lvl()}out->{child.membname}.iov->iov_len = out->{child.cnt.membname};\n" + ret += f"{'\t'*indent_lvl()}out->{child.membname}.iovcnt = 1;\n" + else: + ret += f"{'\t'*indent_lvl()}UNMARSHAL_BYTES(ctx, {path.c_str('out->')[:-3]}, {cnt_str});\n" return idlutil.WalkCmd.KEEP_GOING, pop ret += f"{'\t'*indent_lvl()}{path.c_str('out->')[:-3]} = extra;\n" - ret += f"{'\t'*indent_lvl()}extra += sizeof({path.c_str('out->')[:-3]}[0]) * {cnt_path.c_str('out->')};\n" + ret += f"{'\t'*indent_lvl()}extra += sizeof({path.c_str('out->')[:-3]}[0]) * {cnt_str};\n" loopdepth = sum(1 for elem in path.elems if elem.cnt) loopvar = chr(ord("i") + loopdepth - 1) - ret += f"{'\t'*indent_lvl()}for ({c9util.typename(child.cnt.typ)} {loopvar} = 0; {loopvar} < {cnt_path.c_str('out->')}; {loopvar}++) {{\n" + ret += f"{'\t'*indent_lvl()}for ({cnt_typ} {loopvar} = 0; {loopvar} < {cnt_str}; {loopvar}++) {{\n" indent_stack.append(IndentLevel(ifdef=False)) if not isinstance(child.typ, idl.Struct): if child.val: @@ -118,9 +130,9 @@ def gen_c_unmarshal(versions: set[str], typs: list[idl.UserType]) -> str: assert isinstance(typ, idl.Struct) ret += "\n" ret += cutil.ifdef_push(1, c9util.ver_ifdef(typ.in_versions)) - ret += f"static void unmarshal_{typ.typname}([[gnu::unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) {{\n" + ret += f"static void unmarshal_{typ.typname}([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) {{\n" ret += f"\t{c9util.typename(typ)} *out = out_buf;\n" - ret += "\t[[gnu::unused]] void *extra = &out[1];\n" + ret += "\t[[maybe_unused]] void *extra = &out[1];\n" ret += "\tuint32_t net_offset = 0;\n" indent_stack = [IndentLevel(ifdef=True)] diff --git a/lib9p/protogen/c_validate.py b/lib9p/core_gen/c_validate.py index e315b60..1bfe329 100644 --- a/lib9p/protogen/c_validate.py +++ b/lib9p/core_gen/c_validate.py @@ -1,4 +1,4 @@ -# lib9p/protogen/c_validate.py - Generate C validation functions +# lib9p/core_gen/c_validate.py - Generate C validation functions # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later @@ -24,11 +24,11 @@ def should_save_offset(parent: idl.Struct, child: idl.StructMember) -> bool: for sibling in parent.members: if sibling.val: for tok in sibling.val.tokens: - if isinstance(tok, idl.ExprSym) and tok.symname == f"&{child.membname}": + if isinstance(tok, idl.ExprOff) and tok.membname == child.membname: return True if sibling.max: for tok in sibling.max.tokens: - if isinstance(tok, idl.ExprSym) and tok.symname == f"&{child.membname}": + if isinstance(tok, idl.ExprOff) and tok.membname == child.membname: return True return False @@ -57,26 +57,26 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: "\t\t/* If needed-net-size overflowed uint32_t, then\n" "\t\t * there's no way that actual-net-size will live up to\n" "\t\t * that. */\n" - '\t\treturn lib9p_error(ctx, LINUX_EBADMSG, "message is too short for content");\n' + '\t\treturn ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content"));\n' "\tif (net_offset > net_size)\n" - '\t\treturn lib9p_errorf(ctx, LINUX_EBADMSG, "message is too short for content (%"PRIu32" > %"PRIu32") @ %d", net_offset, net_size, __LINE__);\n' + '\t\treturn ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content (", net_offset, " > ", net_size, ")"));\n' ) ret += cutil.macro( "#define VALIDATE_NET_UTF8(n)\n" "\t{\n" "\t\tsize_t len = n;\n" "\t\tVALIDATE_NET_BYTES(len);\n" - "\t\tif (!is_valid_utf8_without_nul(&net_bytes[net_offset-len], len))\n" - '\t\t\treturn lib9p_error(ctx, LINUX_EBADMSG, "message contains invalid UTF-8");\n' + "\t\tif (!utf8_is_valid_without_nul(&net_bytes[net_offset-len], len))\n" + '\t\t\treturn ERROR_NEW_ERR(size_t, error_new(E_POSIX_EILSEQ, "message contains invalid UTF-8"));\n' "\t}\n" ) ret += cutil.macro( "#define RESERVE_HOST_BYTES(n)\n" "\tif (__builtin_add_overflow(host_size, n, &host_size))\n" - "\t\t/* If needed-host-size overflowed ssize_t, then there's\n" + "\t\t/* If needed-host-size overflowed size_t, then there's\n" "\t\t * no way that actual-net-size will live up to\n" "\t\t * that. */\n" - '\t\treturn lib9p_error(ctx, LINUX_EBADMSG, "message is too short for content");\n' + '\t\treturn ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content"));\n' ) ret += "#define GET_U8LE(off) (net_bytes[off])\n" @@ -132,21 +132,33 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: if should_save_offset(parent, child): ret += f"{'\t'*indent_lvl()}uint32_t offsetof{''.join('_'+m.membname for m in path.elems)} = net_offset + {incr_buf};\n" if child.cnt: - assert child.cnt.typ.static_size - cnt_path = path.parent().add(child.cnt) - incr_flush() + if isinstance(child.cnt, int): + cnt_str = str(child.cnt) + cnt_typ = "size_t" + else: + assert child.cnt.typ.static_size + incr_flush() + cnt_str = f"LAST_U{child.cnt.typ.static_size*8}LE()" + cnt_typ = c9util.typename(child.cnt.typ) if child.membname == "utf8": # SPECIAL (string) + assert child.typ.static_size == 1 # Yes, this is content-validation and "belongs" in # gen_validate_content(), not here. But it's just # easier this way. - ret += f"{'\t'*indent_lvl()}VALIDATE_NET_UTF8(LAST_U{child.cnt.typ.static_size*8}LE());\n" + incr_flush() + ret += f"{'\t'*indent_lvl()}VALIDATE_NET_UTF8({cnt_str});\n" return if child.typ.static_size == 1: # SPECIAL (zerocopy) - ret += f"{'\t'*indent_lvl()}VALIDATE_NET_BYTES(LAST_U{child.cnt.typ.static_size*8}LE());\n" + if isinstance(child.cnt, int): + incr_buf += child.cnt + return + incr_flush() + ret += f"{'\t'*indent_lvl()}VALIDATE_NET_BYTES({cnt_str});\n" return loopdepth = sum(1 for elem in path.elems if elem.cnt) loopvar = chr(ord("i") + loopdepth - 1) - ret += f"{'\t'*indent_lvl()}for ({c9util.typename(child.cnt.typ)} {loopvar} = 0, cnt = LAST_U{child.cnt.typ.static_size*8}LE(); {loopvar} < cnt; {loopvar}++) {{\n" + incr_flush() + ret += f"{'\t'*indent_lvl()}for ({cnt_typ} {loopvar} = 0, cnt = {cnt_str}; {loopvar} < cnt; {loopvar}++) {{\n" indent_stack.append(IndentLevel(ifdef=False)) ret += f"{'\t'*indent_lvl()}RESERVE_HOST_BYTES(sizeof({c9util.typename(child.typ)}));\n" if not isinstance(child.typ, idl.Struct): @@ -178,11 +190,10 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: for tok in child.val.tokens ): nbits = 32 - act = f"(uint{nbits}_t)GET_U{nbits}LE({lookup_sym(f'&{child.membname}')})" - exp = f"(uint{nbits}_t)({c9util.idl_expr(child.val, lookup_sym)})" + act = f"GET_U{nbits}LE({lookup_sym(f'&{child.membname}')})" + exp = f"{c9util.idl_expr(child.val, lookup_sym)}" ret += f"{'\t'*indent_lvl()}if ({act} != {exp})\n" - ret += f'{"\t"*(indent_lvl()+1)}return lib9p_errorf(ctx, LINUX_EBADMSG, "{path} value is wrong: actual: %"PRIu{nbits}" != correct:%"PRIu{nbits},\n' - ret += f"{'\t'*(indent_lvl()+2)}{act}, {exp});\n" + ret += f'{"\t"*(indent_lvl()+1)}return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "{path} value is wrong: actual:", (base10, {act}), " != correct:", (base10, {exp})));\n' if child.max: incr_flush() assert child.typ.static_size @@ -193,19 +204,18 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: for tok in child.max.tokens ): nbits = 32 - act = f"(uint{nbits}_t)GET_U{nbits}LE({lookup_sym(f'&{child.membname}')})" - exp = f"(uint{nbits}_t)({c9util.idl_expr(child.max, lookup_sym)})" + act = f"GET_U{nbits}LE({lookup_sym(f'&{child.membname}')})" + exp = f"{c9util.idl_expr(child.max, lookup_sym)}" ret += f"{'\t'*indent_lvl()}if ({act} > {exp})\n" - ret += f'{"\t"*(indent_lvl()+1)}return lib9p_errorf(ctx, LINUX_EBADMSG, "{path} value is too large: %"PRIu{nbits}" > %"PRIu{nbits},\n' - ret += f"{'\t'*(indent_lvl()+2)}{act}, {exp});\n" + ret += f'{"\t"*(indent_lvl()+1)}return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "{path} value is too large: ", (base10, {act}), " > ", (base10, {exp})));\n' if isinstance(child.typ, idl.Bitfield): incr_flush() nbytes = child.typ.static_size nbits = nbytes * 8 act = f"GET_U{nbits}LE({lookup_sym(f'&{child.membname}')})" ret += f"{'\t'*indent_lvl()}if ({act} & ~{child.typ.typname}_masks[ctx->version])\n" - ret += f'{"\t"*(indent_lvl()+1)}return lib9p_errorf(ctx, LINUX_EBADMSG, "unknown bits in {child.typ.typname} bitfield: %#0{nbytes*2}"PRIx{nbits},\n' - ret += f"{'\t'*(indent_lvl()+2)}{act} & ~{child.typ.typname}_masks[ctx->version]);\n" + ret += f'{"\t"*(indent_lvl()+1)}return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in {child.typ.typname} bitfield: ",\n' + ret += f"{'\t'*(indent_lvl()+2)}(base16_u{nbits}_, {act} & ~{child.typ.typname}_masks[ctx->version])));\n" def handle( path: idlutil.Path, @@ -261,12 +271,12 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: ret += "\n" ret += cutil.ifdef_push(1, c9util.ver_ifdef(typ.in_versions)) if typ.typname == "stat": # SPECIAL (stat) - ret += f"static ssize_t validate_{typ.typname}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{\n" + ret += f"static size_t_or_error validate_{typ.typname}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{\n" else: - ret += f"static ssize_t validate_{typ.typname}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) {{\n" + ret += f"static size_t_or_error validate_{typ.typname}([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) {{\n" ret += "\tuint32_t net_offset = 0;\n" - ret += f"\tssize_t host_size = sizeof({c9util.typename(typ)});\n" + ret += f"\tsize_t host_size = sizeof({c9util.typename(typ)});\n" incr_buf = 0 indent_stack = [IndentLevel(ifdef=True)] @@ -281,7 +291,7 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: if typ.typname == "stat": # SPECIAL (stat) ret += "\tif (ret_net_size)\n" ret += "\t\t*ret_net_size = net_offset;\n" - ret += "\treturn (ssize_t)host_size;\n" + ret += "\treturn ERROR_NEW_VAL(size_t, host_size);\n" ret += "}\n" ret += cutil.ifdef_pop(0) return ret diff --git a/lib9p/protogen/cutil.py b/lib9p/core_gen/cutil.py index 8df6db9..9183cc4 100644 --- a/lib9p/protogen/cutil.py +++ b/lib9p/core_gen/cutil.py @@ -1,4 +1,4 @@ -# lib9p/protogen/cutil.py - Utilities for generating C code +# lib9p/core_gen/cutil.py - Utilities for generating C code # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib9p/protogen/h.py b/lib9p/core_gen/h.py index 7785ca1..6ead5ba 100644 --- a/lib9p/protogen/h.py +++ b/lib9p/core_gen/h.py @@ -1,4 +1,4 @@ -# lib9p/protogen/h.py - Generate 9p.generated.h +# lib9p/core_gen/h.py - Generate _core_generated.h # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later @@ -159,23 +159,21 @@ def gen_h(versions: set[str], typs: list[idl.UserType]) -> str: ret = f"""/* Generated by `{' '.join(sys.argv)}`. DO NOT EDIT! */ -#ifndef _LIB9P_9P_H_ -\t#error Do not include <lib9p/9p.generated.h> directly; include <lib9p/9p.h> instead +#ifndef _LIB9P_CORE_H_ +\t#error Do not include <lib9p/_core_generated.h> directly; include <lib9p/core.h> instead #endif -#include <stdint.h> /* for uint{{n}}_t types */ - -#include <libhw/generic/net.h> /* for struct iovec */ +struct {c9util.ident('_iovec_list')} {{ +\tstruct iovec *iov; +\tint iovcnt; +}}; """ - id2typ: dict[int, idl.Message] = {} for msg in [msg for msg in typs if isinstance(msg, idl.Message)]: id2typ[msg.msgid] = msg ret += """ /* config *********************************************************************/ - -#include "config.h" """ for ver in sorted(versions): ret += "\n" @@ -191,14 +189,21 @@ def gen_h(versions: set[str], typs: list[idl.UserType]) -> str: ret += "\t#endif\n" ret += "#endif\n" + # SPECIAL (convenience) + ret += "\n" + ret += f"#define _LIB9P_ENABLE_stat {c9util.ver_ifdef(next(typ for typ in typs if typ.typname == 'stat').in_versions)}\n" + ret += f""" /* enum version ***************************************************************/ enum {c9util.ident('version')} {{ """ - fullversions = ["unknown = 0", *sorted(versions)] - verwidth = max(len(v) for v in fullversions) - for ver in fullversions: + xversions = [ # SPECIAL (initialization) + "uninitialized = 0", + *sorted(v for v in versions if v != "uninitialized"), + ] + verwidth = max(len(v) for v in xversions) + for ver in xversions: if ver in versions: ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) ret += f"\t{c9util.ver_enum(ver)}," @@ -268,99 +273,11 @@ enum {c9util.ident('version')} {{ match typ: case idl.Number(): - ret += f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n" - prefix = f"{c9util.IDENT(typ.typname)}_" - namewidth = max(len(name) for name in typ.vals) - for name, val in typ.vals.items(): - ret += f"#define {prefix}{name:<{namewidth}} (({c9util.typename(typ)})UINT{typ.static_size*8}_C({val}))\n" + ret += gen_number(typ) case idl.Bitfield(): - ret += f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n" - - def bitname(val: idl.Bit | idl.BitAlias) -> str: - s = val.bitname - match val: - case idl.Bit(cat=idl.BitCat.RESERVED): - s = "_RESERVED_" + s - case idl.Bit(cat=idl.BitCat.SUBFIELD): - assert isinstance(typ, idl.Bitfield) - n = sum( - 1 - for b in typ.bits[: val.num] - if b.cat == idl.BitCat.SUBFIELD - and b.bitname == val.bitname - ) - s = f"_{s}_{n}" - case idl.Bit(cat=idl.BitCat.UNUSED): - return "" - return c9util.Ident(c9util.add_prefix(typ.typname.upper() + "_", s)) - - namewidth = max( - len(bitname(val)) for val in [*typ.bits, *typ.names.values()] - ) - - ret += "\n" - for bit in reversed(typ.bits): - vers = bit.in_versions - if bit.cat == idl.BitCat.UNUSED: - vers = typ.in_versions - ret += cutil.ifdef_push(2, c9util.ver_ifdef(vers)) - - # It is important all of the `beg` strings have - # the same length. - end = "" - match bit.cat: - case ( - idl.BitCat.USED | idl.BitCat.RESERVED | idl.BitCat.SUBFIELD - ): - if cutil.ifdef_leaf_is_noop(): - beg = "#define " - else: - beg = "# define" - case idl.BitCat.UNUSED: - beg = "/* unused" - end = " */" - - c_name = bitname(bit) - c_val = f"1<<{bit.num}" - ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" - if aliases := [ - alias - for alias in typ.names.values() - if isinstance(alias, idl.BitAlias) - ]: - ret += "\n" - - for alias in aliases: - ret += cutil.ifdef_push(2, c9util.ver_ifdef(alias.in_versions)) - - end = "" - if cutil.ifdef_leaf_is_noop(): - beg = "#define " - else: - beg = "# define" - - c_name = bitname(alias) - c_val = alias.val - ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" - ret += cutil.ifdef_pop(1) - del bitname + ret += gen_bitfield(typ) case idl.Struct(): # and idl.Message(): - ret += c9util.typename(typ) + " {" - if not typ.members: - ret += "};\n" - continue - ret += "\n" - - typewidth = max(len(c9util.typename(m.typ, m)) for m in typ.members) - - for member in typ.members: - if member.val: - continue - ret += cutil.ifdef_push(2, c9util.ver_ifdef(member.in_versions)) - ret += f"\t{c9util.typename(member.typ, member):<{typewidth}} {'*' if member.cnt else ' '}{member.membname};\n" - ret += cutil.ifdef_pop(1) - ret += "};\n" - del typ + ret += gen_struct(typ) ret += cutil.ifdef_pop(0) ret += """ @@ -445,3 +362,179 @@ enum {c9util.ident('version')} {{ ret += "};\n" return ret + + +def gen_number(typ: idl.Number) -> str: + ret = f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n" + + def lookup_sym(sym: str) -> str: + assert False + + def cname(base: str) -> str: + prefix = f"{typ.typname}_".upper() + return c9util.Ident(c9util.add_prefix(prefix, base)) + + namewidth = max(len(cname(name)) for name in typ.vals) + for name, val in typ.vals.items(): + c_name = cname(name) + c_val = c9util.idl_expr(val, lookup_sym) + ret += f"#define {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val}))\n" + return ret + + +def gen_bitfield(typ: idl.Bitfield) -> str: + ret = f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n" + + def lookup_sym(sym: str) -> str: + assert False + + # There are 4 parts here: bits, aliases, masks, and numbers. + + # 1. bits + + def bitname(bit: idl.Bit) -> str: + prefix = f"{typ.typname}_".upper() + base = bit.bitname + match bit: + case idl.Bit(cat="RESERVED"): + base = "_RESERVED_" + base + case idl.Bit(cat=idl.BitNum()): + base += "_*" + case idl.Bit(cat="UNUSED"): + base = f"_UNUSED_{bit.num}" + return c9util.Ident(c9util.add_prefix(prefix, base)) + + namewidth = max(len(bitname(bit)) for bit in typ.bits) + + ret += "/* bits */\n" + for bit in reversed(typ.bits): + vers = bit.in_versions + if bit.cat == "UNUSED": + vers = typ.in_versions + ret += cutil.ifdef_push(2, c9util.ver_ifdef(vers)) + + # It is important all of the `beg` strings have + # the same length. + end = "" + match bit.cat: + case "USED" | "RESERVED" | "UNUSED": + if cutil.ifdef_leaf_is_noop(): + beg = "#define " + else: + beg = "# define" + case idl.BitNum(): + beg = "/* number" + end = " */" + + c_name = bitname(bit) + c_val = f"UINT{typ.static_size*8}_C(1)<<{bit.num}" + ret += ( + f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" + ) + ret += cutil.ifdef_pop(1) + + # 2. aliases + if typ.aliases: + + def aliasname(alias: idl.BitAlias) -> str: + prefix = f"{typ.typname}_".upper() + base = alias.bitname + return c9util.Ident(c9util.add_prefix(prefix, base)) + + ret += "/* aliases */\n" + for alias in typ.aliases.values(): + ret += cutil.ifdef_push(2, c9util.ver_ifdef(alias.in_versions)) + + end = "" + if cutil.ifdef_leaf_is_noop(): + beg = "#define " + else: + beg = "# define" + + c_name = aliasname(alias) + c_val = c9util.idl_expr(alias.val, lookup_sym) + ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" + + ret += cutil.ifdef_pop(1) + + # 3. masks + if typ.masks: + + def maskname(mask: idl.BitAlias) -> str: + prefix = f"{typ.typname}_".upper() + base = mask.bitname + return c9util.Ident(c9util.add_prefix(prefix, base) + "_MASK") + + ret += "/* masks */\n" + for mask in typ.masks.values(): + ret += cutil.ifdef_push(2, c9util.ver_ifdef(mask.in_versions)) + + end = "" + if cutil.ifdef_leaf_is_noop(): + beg = "#define " + else: + beg = "# define" + + c_name = maskname(mask) + c_val = c9util.idl_expr(mask.val, lookup_sym, bitwidth=typ.static_size * 8) + ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" + + ret += cutil.ifdef_pop(1) + + # 4. numbers + def numname(num: idl.BitNum, base: str) -> str: + prefix = f"{typ.typname}_{num.numname}_".upper() + return c9util.Ident(c9util.add_prefix(prefix, base)) + + for num in typ.nums.values(): + namewidth = max( + len(numname(num, base)) + for base in [ + *[alias.bitname for alias in num.vals.values()], + "MASK", + ] + ) + ret += f"/* number: {num.numname} */\n" + for alias in num.vals.values(): + ret += cutil.ifdef_push(2, c9util.ver_ifdef(alias.in_versions)) + + end = "" + if cutil.ifdef_leaf_is_noop(): + beg = "#define " + else: + beg = "# define" + + c_name = numname(num, alias.bitname) + c_val = c9util.idl_expr(alias.val, lookup_sym) + ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" + ret += cutil.ifdef_pop(1) + c_name = numname(num, "MASK") + c_val = f"{num.mask:#0{typ.static_size*8}b}" + ret += ( + f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n" + ) + + return ret + + +def gen_struct(typ: idl.Struct) -> str: # and idl.Message + ret = c9util.typename(typ) + " {" + if typ.members: + ret += "\n" + + typewidth = max(len(c9util.typename(m.typ, m)) for m in typ.members) + + for member in typ.members: + if member.val: + continue + ret += cutil.ifdef_push(2, c9util.ver_ifdef(member.in_versions)) + ptr = bool(member.cnt) + if ( + c9util.typename(member.typ, member) + == f"struct {c9util.ident('_iovec')}" + ): # SPECIAL (zerocopy) + ptr = False + ret += f"\t{c9util.typename(member.typ, member):<{typewidth}} {'*' if ptr else ' '}{member.membname};\n" + ret += cutil.ifdef_pop(1) + ret += "};\n" + return ret diff --git a/lib9p/protogen/idlutil.py b/lib9p/core_gen/idlutil.py index dc4d012..e92839a 100644 --- a/lib9p/protogen/idlutil.py +++ b/lib9p/core_gen/idlutil.py @@ -1,10 +1,9 @@ -# lib9p/protogen/idlutil.py - Utilities for working with the 9P idl package +# lib9p/core_gen/idlutil.py - Utilities for working with the 9P idl package # # Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later import enum -import graphlib import typing import idl @@ -22,21 +21,40 @@ __all__ = [ def topo_sorted(typs: list[idl.UserType]) -> typing.Iterable[idl.UserType]: - ts: graphlib.TopologicalSorter[idl.UserType] = graphlib.TopologicalSorter() + ret: list[idl.UserType] = [] + struct_ord: dict[str, int] = {} + + def get_struct_ord(typ: idl.Struct) -> int: + nonlocal struct_ord + if typ.typname not in struct_ord: + deps = [ + get_struct_ord(member.typ) + for member in typ.members + if isinstance(member.typ, idl.Struct) + ] + if len(deps) == 0: + struct_ord[typ.typname] = 0 + else: + struct_ord[typ.typname] = 1 + max(deps) + return struct_ord[typ.typname] + for typ in typs: match typ: case idl.Number(): - ts.add(typ) + ret.append(typ) case idl.Bitfield(): - ts.add(typ) + ret.append(typ) case idl.Struct(): # and idl.Message(): - deps = [ - member.typ - for member in typ.members - if not isinstance(member.typ, idl.Primitive) - ] - ts.add(typ, *deps) - return ts.static_order() + _ = get_struct_ord(typ) + for _ord in sorted(set(struct_ord.values())): + for typ in typs: + if not isinstance(typ, idl.Struct): + continue + if struct_ord[typ.typname] != _ord: + continue + ret.append(typ) + assert len(ret) == len(typs) + return ret # walk() ####################################################################### diff --git a/lib9p/core_generated.c b/lib9p/core_generated.c new file mode 100644 index 0000000..49cb8d9 --- /dev/null +++ b/lib9p/core_generated.c @@ -0,0 +1,8140 @@ +/* Generated by `lib9p/core.gen lib9p/idl/0000-uninitialized.9p lib9p/idl/2002-9P2000.9p lib9p/idl/2003-9P2000.p9p.9p lib9p/idl/2005-9P2000.u.9p lib9p/idl/2010-9P2000.L.9p lib9p/idl/2012-9P2000.e.9p`. DO NOT EDIT! */ + +#include <stddef.h> /* for size_t */ +#include <string.h> /* for memset() */ + +#include <libmisc/assert.h> +#include <libmisc/endian.h> +#include <libmisc/utf8.h> + +#include <lib9p/core.h> + +#include "core_tables.h" + +/* utilities ******************************************************************/ +#if CONFIG_9P_ENABLE_9P2000 + #define _is_ver_9P2000(v) (v == LIB9P_VER_9P2000) +#else + #define _is_ver_9P2000(v) false +#endif +#if CONFIG_9P_ENABLE_9P2000_L + #define _is_ver_9P2000_L(v) (v == LIB9P_VER_9P2000_L) +#else + #define _is_ver_9P2000_L(v) false +#endif +#if CONFIG_9P_ENABLE_9P2000_e + #define _is_ver_9P2000_e(v) (v == LIB9P_VER_9P2000_e) +#else + #define _is_ver_9P2000_e(v) false +#endif +#if CONFIG_9P_ENABLE_9P2000_p9p + #define _is_ver_9P2000_p9p(v) (v == LIB9P_VER_9P2000_p9p) +#else + #define _is_ver_9P2000_p9p(v) false +#endif +#if CONFIG_9P_ENABLE_9P2000_u + #define _is_ver_9P2000_u(v) (v == LIB9P_VER_9P2000_u) +#else + #define _is_ver_9P2000_u(v) false +#endif +#if CONFIG_9P_ENABLE_uninitialized + #define _is_ver_uninitialized(v) (v == LIB9P_VER_uninitialized) +#else + #define _is_ver_uninitialized(v) false +#endif + +/** + * is_ver(ctx, ver) is essentially `(ctx->version == LIB9P_VER_##ver)`, but + * compiles correctly (to `false`) even if `LIB9P_VER_##ver` isn't defined + * (because `!CONFIG_9P_ENABLE_##ver`). This is useful when `||`ing + * several version checks together. + */ +#define is_ver(ctx, ver) _is_ver_##ver((ctx)->version) + +/* bitmasks *******************************************************************/ + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static const lib9p_dm_t dm_masks[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = 0b11111100000000000000000111111111, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = 0b11111100000000000000000111111111, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = 0b11111100000000000000000111111111, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = 0b11111100101111000000000111111111, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = 0b11111100000000000000000111111111, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static const lib9p_qt_t qt_masks[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = 0b11111100, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = 0b11111100, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = 0b11111100, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = 0b11111100, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = 0b11111110, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = 0b11111100, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static const lib9p_o_t o_masks[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = 0b01010011, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = 0b00000000, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = 0b01010011, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = 0b01010011, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = 0b01010011, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = 0b00000000, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_L +static const lib9p_lo_t lo_masks[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000 */ + [LIB9P_VER_9P2000_L] = 0b00000000000111111111111111000011, +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +static const lib9p_mode_t mode_masks[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000 */ + [LIB9P_VER_9P2000_L] = 0b00000000000000001111111111111111, +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +static const lib9p_getattr_t getattr_masks[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = 0b0000000000000000000000000000000000000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000 */ + [LIB9P_VER_9P2000_L] = 0b0000000000000000000000000000000000000000000000000011111111111111, +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = 0b0000000000000000000000000000000000000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = 0b0000000000000000000000000000000000000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = 0b0000000000000000000000000000000000000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = 0b0000000000000000000000000000000000000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +static const lib9p_setattr_t setattr_masks[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000 */ + [LIB9P_VER_9P2000_L] = 0b00000000000000000000000111111111, +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +static const lib9p_lock_flags_t lock_flags_masks[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000 */ + [LIB9P_VER_9P2000_L] = 0b00000000000000000000000000000011, +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = 0b00000000000000000000000000000000, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; +#endif /* CONFIG_9P_ENABLE_9P2000_L */ + +/* validate_* *****************************************************************/ + +#define VALIDATE_NET_BYTES(n) \ + if (__builtin_add_overflow(net_offset, n, &net_offset)) \ + /* If needed-net-size overflowed uint32_t, then \ + * there's no way that actual-net-size will live up to \ + * that. */ \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content")); \ + if (net_offset > net_size) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content (", net_offset, " > ", net_size, ")")); +#define VALIDATE_NET_UTF8(n) \ + { \ + size_t len = n; \ + VALIDATE_NET_BYTES(len); \ + if (!utf8_is_valid_without_nul(&net_bytes[net_offset-len], len)) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EILSEQ, "message contains invalid UTF-8")); \ + } +#define RESERVE_HOST_BYTES(n) \ + if (__builtin_add_overflow(host_size, n, &host_size)) \ + /* If needed-host-size overflowed size_t, then there's \ + * no way that actual-net-size will live up to \ + * that. */ \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content")); +#define GET_U8LE(off) (net_bytes[off]) +#define GET_U16LE(off) uint16le_decode(&net_bytes[off]) +#define GET_U32LE(off) uint32le_decode(&net_bytes[off]) +#define GET_U64LE(off) uint64le_decode(&net_bytes[off]) +#define LAST_U8LE() GET_U8LE(net_offset-1) +#define LAST_U16LE() GET_U16LE(net_offset-2) +#define LAST_U32LE() GET_U32LE(net_offset-4) +#define LAST_U64LE() GET_U64LE(net_offset-8) + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static size_t_or_error validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_stat); + uint32_t offsetof__stat_size = net_offset + 0; + uint32_t offsetof_fstype = net_offset + 2; + uint32_t offsetof_qid_type = net_offset + 8; + VALIDATE_NET_BYTES(21); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_mode = net_offset + 0; + VALIDATE_NET_BYTES(22); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(12); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof__stat_size) != offsetof_end - offsetof_fstype) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "stat->_stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof__stat_size)), " != correct:", (base10, offsetof_end - offsetof_fstype))); + if (GET_U32LE(offsetof_mode) & ~dm_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in dm bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~dm_masks[ctx->version]))); + if (ret_net_size) + *ret_net_size = net_offset; + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +static size_t_or_error validate_Tversion([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tversion); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tversion->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 100) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tversion->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 100))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rversion([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rversion); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rversion->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 101) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rversion->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 101))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static size_t_or_error validate_Tauth([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tauth); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { + VALIDATE_NET_BYTES(4); + } +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tauth->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 102) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tauth->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 102))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rauth([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rauth); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_aqid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_aqid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_aqid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rauth->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 103) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rauth->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 103))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tattach([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tattach); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(17); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { + VALIDATE_NET_BYTES(4); + } +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tattach->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 104) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tattach->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 104))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rattach([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rattach); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rattach->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 105) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rattach->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 105))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +static size_t_or_error validate_Rerror([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rerror); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(9); + VALIDATE_NET_UTF8(LAST_U16LE()); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + VALIDATE_NET_BYTES(4); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rerror->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 107) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rerror->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 107))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static size_t_or_error validate_Tflush([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tflush); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 9; + VALIDATE_NET_BYTES(9); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tflush->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 108) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tflush->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 108))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rflush([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rflush); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rflush->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 109) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rflush->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 109))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Twalk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Twalk); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_nwname = net_offset + 15; + VALIDATE_NET_BYTES(17); + for (uint16_t i = 0, cnt = LAST_U16LE(); i < cnt; i++) { + RESERVE_HOST_BYTES(sizeof(struct lib9p_s)); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + } + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 110) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 110))); + if (GET_U16LE(offsetof_nwname) > 16) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twalk->nwname value is too large: ", (base10, GET_U16LE(offsetof_nwname)), " > ", (base10, 16))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rwalk); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_nwqid = net_offset + 7; + VALIDATE_NET_BYTES(9); + for (uint16_t i = 0, cnt = LAST_U16LE(); i < cnt; i++) { + RESERVE_HOST_BYTES(sizeof(struct lib9p_qid)); + uint32_t offsetof_wqid_type = net_offset + 0; + VALIDATE_NET_BYTES(13); + if (GET_U8LE(offsetof_wqid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_wqid_type) & ~qt_masks[ctx->version]))); + } + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 111) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 111))); + if (GET_U16LE(offsetof_nwqid) > 16) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwalk->nwqid value is too large: ", (base10, GET_U16LE(offsetof_nwqid)), " > ", (base10, 16))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static size_t_or_error validate_Topen([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Topen); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_mode = net_offset + 11; + uint32_t offsetof_end = net_offset + 12; + VALIDATE_NET_BYTES(12); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Topen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 112) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Topen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 112))); + if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in o bitfield: ", + (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Ropen([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Ropen); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 4; + VALIDATE_NET_BYTES(4); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Ropen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 113) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Ropen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 113))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tcreate); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_perm = net_offset + 0; + uint32_t offsetof_mode = net_offset + 4; + uint32_t offsetof_end = net_offset + 5; + VALIDATE_NET_BYTES(5); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 114) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 114))); + if (GET_U32LE(offsetof_perm) & ~dm_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in dm bitfield: ", + (base16_u32_, GET_U32LE(offsetof_perm) & ~dm_masks[ctx->version]))); + if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in o bitfield: ", + (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rcreate); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 4; + VALIDATE_NET_BYTES(4); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 115) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 115))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static size_t_or_error validate_Tread([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tread); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_offset = net_offset + 11; + uint32_t offsetof_count = net_offset + 19; + uint32_t offsetof_end = net_offset + 23; + VALIDATE_NET_BYTES(23); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 116) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 116))); + if (GET_U64LE(offsetof_offset) > INT64_MAX) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tread->offset value is too large: ", (base10, GET_U64LE(offsetof_offset)), " > ", (base10, INT64_MAX))); + if (GET_U32LE(offsetof_count) > INT32_MAX) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tread->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rread([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rread); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_count = net_offset + 7; + VALIDATE_NET_BYTES(11); + VALIDATE_NET_BYTES(LAST_U32LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 117) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 117))); + if (GET_U32LE(offsetof_count) > INT32_MAX) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rread->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Twrite([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Twrite); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_offset = net_offset + 11; + uint32_t offsetof_count = net_offset + 19; + VALIDATE_NET_BYTES(23); + VALIDATE_NET_BYTES(LAST_U32LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 118) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 118))); + if (GET_U64LE(offsetof_offset) > INT64_MAX) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twrite->offset value is too large: ", (base10, GET_U64LE(offsetof_offset)), " > ", (base10, INT64_MAX))); + if (GET_U32LE(offsetof_count) > INT32_MAX) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twrite->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rwrite([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rwrite); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_count = net_offset + 7; + uint32_t offsetof_end = net_offset + 11; + VALIDATE_NET_BYTES(11); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 119) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 119))); + if (GET_U32LE(offsetof_count) > INT32_MAX) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwrite->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tclunk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tclunk); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 11; + VALIDATE_NET_BYTES(11); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tclunk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 120) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tclunk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 120))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rclunk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rclunk); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rclunk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 121) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rclunk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 121))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tremove([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tremove); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 11; + VALIDATE_NET_BYTES(11); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tremove->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 122) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tremove->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 122))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rremove([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rremove); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rremove->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 123) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rremove->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 123))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static size_t_or_error validate_Tstat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tstat); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 11; + VALIDATE_NET_BYTES(11); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 124) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 124))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rstat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rstat); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_nstat = net_offset + 7; + uint32_t offsetof_stat = net_offset + 9; + uint32_t offsetof_stat__stat_size = net_offset + 9; + uint32_t offsetof_stat_fstype = net_offset + 11; + uint32_t offsetof_stat_qid_type = net_offset + 17; + VALIDATE_NET_BYTES(30); + if (GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_stat_mode = net_offset + 0; + VALIDATE_NET_BYTES(22); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(12); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + uint32_t offsetof_stat_end = net_offset + 0; + if (GET_U32LE(offsetof_stat__stat_size) != offsetof_stat_end - offsetof_stat_fstype) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstat->stat._stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof_stat__stat_size)), " != correct:", (base10, offsetof_stat_end - offsetof_stat_fstype))); + if (GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in dm bitfield: ", + (base16_u32_, GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 125) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 125))); + if (GET_U32LE(offsetof_nstat) != offsetof_end - offsetof_stat) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstat->nstat value is wrong: actual:", (base10, GET_U32LE(offsetof_nstat)), " != correct:", (base10, offsetof_end - offsetof_stat))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Twstat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Twstat); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_nstat = net_offset + 11; + uint32_t offsetof_stat = net_offset + 13; + uint32_t offsetof_stat__stat_size = net_offset + 13; + uint32_t offsetof_stat_fstype = net_offset + 15; + uint32_t offsetof_stat_qid_type = net_offset + 21; + VALIDATE_NET_BYTES(34); + if (GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_stat_mode = net_offset + 0; + VALIDATE_NET_BYTES(22); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(12); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + uint32_t offsetof_stat_end = net_offset + 0; + if (GET_U32LE(offsetof_stat__stat_size) != offsetof_stat_end - offsetof_stat_fstype) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twstat->stat._stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof_stat__stat_size)), " != correct:", (base10, offsetof_stat_end - offsetof_stat_fstype))); + if (GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in dm bitfield: ", + (base16_u32_, GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 126) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 126))); + if (GET_U32LE(offsetof_nstat) != offsetof_end - offsetof_stat) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twstat->nstat value is wrong: actual:", (base10, GET_U32LE(offsetof_nstat)), " != correct:", (base10, offsetof_end - offsetof_stat))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rwstat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rwstat); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 127) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 127))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_p9p +static size_t_or_error validate_Topenfd([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Topenfd); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_mode = net_offset + 11; + uint32_t offsetof_end = net_offset + 12; + VALIDATE_NET_BYTES(12); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Topenfd->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 98) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Topenfd->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 98))); + if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in o bitfield: ", + (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Ropenfd([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Ropenfd); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 8; + VALIDATE_NET_BYTES(8); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Ropenfd->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 99) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Ropenfd->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 99))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_L +static size_t_or_error validate_Rlerror([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rlerror); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 11; + VALIDATE_NET_BYTES(11); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlerror->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 7) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlerror->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 7))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tstatfs([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tstatfs); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 11; + VALIDATE_NET_BYTES(11); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tstatfs->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 8) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tstatfs->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 8))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rstatfs([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rstatfs); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 67; + VALIDATE_NET_BYTES(67); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstatfs->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 9) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstatfs->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 9))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tlopen([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tlopen); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_flags = net_offset + 11; + uint32_t offsetof_end = net_offset + 15; + VALIDATE_NET_BYTES(15); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlopen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 12) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlopen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 12))); + if (GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in lo bitfield: ", + (base16_u32_, GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rlopen([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rlopen); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 4; + VALIDATE_NET_BYTES(4); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlopen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 13) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlopen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 13))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tlcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tlcreate); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_flags = net_offset + 0; + uint32_t offsetof_mode = net_offset + 4; + uint32_t offsetof_end = net_offset + 12; + VALIDATE_NET_BYTES(12); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 14) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 14))); + if (GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in lo bitfield: ", + (base16_u32_, GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]))); + if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rlcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rlcreate); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 4; + VALIDATE_NET_BYTES(4); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 15) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 15))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tsymlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tsymlink); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 4; + VALIDATE_NET_BYTES(4); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsymlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 16) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsymlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 16))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rsymlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rsymlink); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsymlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 17) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsymlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 17))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tmknod([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tmknod); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_mode = net_offset + 0; + uint32_t offsetof_end = net_offset + 16; + VALIDATE_NET_BYTES(16); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tmknod->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 18) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tmknod->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 18))); + if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rmknod([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rmknod); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rmknod->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 19) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rmknod->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 19))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Trename([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Trename); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(17); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Trename->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 20) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Trename->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 20))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rrename([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rrename); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rrename->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 21) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rrename->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 21))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Treadlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Treadlink); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 11; + VALIDATE_NET_BYTES(11); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Treadlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 22) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Treadlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 22))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rreadlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rreadlink); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(9); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rreadlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 23) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rreadlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 23))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tgetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tgetattr); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_request_mask = net_offset + 11; + uint32_t offsetof_end = net_offset + 19; + VALIDATE_NET_BYTES(19); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tgetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 24) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tgetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 24))); + if (GET_U64LE(offsetof_request_mask) & ~getattr_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in getattr bitfield: ", + (base16_u64_, GET_U64LE(offsetof_request_mask) & ~getattr_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rgetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rgetattr); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_valid = net_offset + 7; + uint32_t offsetof_qid_type = net_offset + 15; + VALIDATE_NET_BYTES(28); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_mode = net_offset + 0; + uint32_t offsetof_end = net_offset + 132; + VALIDATE_NET_BYTES(132); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rgetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 25) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rgetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 25))); + if (GET_U64LE(offsetof_valid) & ~getattr_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in getattr bitfield: ", + (base16_u64_, GET_U64LE(offsetof_valid) & ~getattr_masks[ctx->version]))); + if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tsetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tsetattr); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_valid = net_offset + 11; + uint32_t offsetof_mode = net_offset + 15; + uint32_t offsetof_end = net_offset + 67; + VALIDATE_NET_BYTES(67); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 26) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 26))); + if (GET_U32LE(offsetof_valid) & ~setattr_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in setattr bitfield: ", + (base16_u32_, GET_U32LE(offsetof_valid) & ~setattr_masks[ctx->version]))); + if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rsetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rsetattr); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 27) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 27))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Txattrwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Txattrwalk); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(17); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Txattrwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 30) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Txattrwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 30))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rxattrwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rxattrwalk); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 15; + VALIDATE_NET_BYTES(15); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rxattrwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 31) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rxattrwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 31))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Txattrcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Txattrcreate); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 12; + VALIDATE_NET_BYTES(12); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Txattrcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 32) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Txattrcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 32))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rxattrcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rxattrcreate); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rxattrcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 33) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rxattrcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 33))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Treaddir([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Treaddir); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 23; + VALIDATE_NET_BYTES(23); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Treaddir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 40) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Treaddir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 40))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rreaddir([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rreaddir); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(11); + VALIDATE_NET_BYTES(LAST_U32LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rreaddir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 41) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rreaddir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 41))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tfsync([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tfsync); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 15; + VALIDATE_NET_BYTES(15); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tfsync->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 50) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tfsync->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 50))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rfsync([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rfsync); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rfsync->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 51) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rfsync->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 51))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tlock([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tlock); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_flags = net_offset + 12; + VALIDATE_NET_BYTES(38); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 52) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 52))); + if (GET_U32LE(offsetof_flags) & ~lock_flags_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in lock_flags bitfield: ", + (base16_u32_, GET_U32LE(offsetof_flags) & ~lock_flags_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rlock([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rlock); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 8; + VALIDATE_NET_BYTES(8); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 53) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 53))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tgetlock([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tgetlock); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(34); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tgetlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 54) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tgetlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 54))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rgetlock([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rgetlock); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(30); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rgetlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 55) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rgetlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 55))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tlink); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(17); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 70) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 70))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rlink); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 71) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 71))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tmkdir([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tmkdir); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_mode = net_offset + 0; + uint32_t offsetof_end = net_offset + 8; + VALIDATE_NET_BYTES(8); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tmkdir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 72) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tmkdir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 72))); + if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rmkdir([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rmkdir); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_qid_type = net_offset + 7; + VALIDATE_NET_BYTES(20); + if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rmkdir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 73) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rmkdir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 73))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Trenameat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Trenameat); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + VALIDATE_NET_BYTES(6); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Trenameat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 74) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Trenameat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 74))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rrenameat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rrenameat); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rrenameat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 75) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rrenameat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 75))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tunlinkat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tunlinkat); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + VALIDATE_NET_UTF8(LAST_U16LE()); + uint32_t offsetof_end = net_offset + 4; + VALIDATE_NET_BYTES(4); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tunlinkat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 76) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tunlinkat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 76))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Runlinkat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Runlinkat); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Runlinkat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 77) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Runlinkat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 77))); + return ERROR_NEW_VAL(size_t, host_size); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e +static size_t_or_error validate_Tsession([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tsession); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 15; + VALIDATE_NET_BYTES(15); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsession->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 150) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsession->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 150))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rsession([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rsession); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 7; + VALIDATE_NET_BYTES(7); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsession->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 151) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsession->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 151))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tsread([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tsread); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + for (uint16_t i = 0, cnt = LAST_U16LE(); i < cnt; i++) { + RESERVE_HOST_BYTES(sizeof(struct lib9p_s)); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + } + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 152) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 152))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rsread([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rsread); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(11); + VALIDATE_NET_BYTES(LAST_U32LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 153) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 153))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Tswrite([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Tswrite); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + VALIDATE_NET_BYTES(13); + for (uint16_t i = 0, cnt = LAST_U16LE(); i < cnt; i++) { + RESERVE_HOST_BYTES(sizeof(struct lib9p_s)); + VALIDATE_NET_BYTES(2); + VALIDATE_NET_UTF8(LAST_U16LE()); + } + VALIDATE_NET_BYTES(4); + VALIDATE_NET_BYTES(LAST_U32LE()); + uint32_t offsetof_end = net_offset + 0; + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tswrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 154) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tswrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 154))); + return ERROR_NEW_VAL(size_t, host_size); +} + +static size_t_or_error validate_Rswrite([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { + uint32_t net_offset = 0; + size_t host_size = sizeof(struct lib9p_msg_Rswrite); + uint32_t offsetof_size = net_offset + 0; + uint32_t offsetof_typ = net_offset + 4; + uint32_t offsetof_end = net_offset + 11; + VALIDATE_NET_BYTES(11); + if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rswrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); + if (GET_U8LE(offsetof_typ) != 155) + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rswrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 155))); + return ERROR_NEW_VAL(size_t, host_size); +} +#endif /* CONFIG_9P_ENABLE_9P2000_e */ + +/* unmarshal_* ****************************************************************/ + +#define UNMARSHAL_BYTES(ctx, data_lvalue, len) \ + data_lvalue = (char *)&net_bytes[net_offset]; \ + net_offset += len; +#define UNMARSHAL_U8LE(ctx, val_lvalue) \ + val_lvalue = net_bytes[net_offset]; \ + net_offset += 1; +#define UNMARSHAL_U16LE(ctx, val_lvalue) \ + val_lvalue = uint16le_decode(&net_bytes[net_offset]); \ + net_offset += 2; +#define UNMARSHAL_U32LE(ctx, val_lvalue) \ + val_lvalue = uint32le_decode(&net_bytes[net_offset]); \ + net_offset += 4; +#define UNMARSHAL_U64LE(ctx, val_lvalue) \ + val_lvalue = uint64le_decode(&net_bytes[net_offset]); \ + net_offset += 8; + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static void unmarshal_stat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_stat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 2; + UNMARSHAL_U16LE(ctx, out->fstype); + UNMARSHAL_U32LE(ctx, out->fsdev); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); + UNMARSHAL_U32LE(ctx, out->mode); + UNMARSHAL_U32LE(ctx, out->atime); + UNMARSHAL_U32LE(ctx, out->mtime); + UNMARSHAL_U64LE(ctx, out->length); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); + UNMARSHAL_U16LE(ctx, out->owner_uname.len); + UNMARSHAL_BYTES(ctx, out->owner_uname.utf8, out->owner_uname.len); + UNMARSHAL_U16LE(ctx, out->owner_gname.len); + UNMARSHAL_BYTES(ctx, out->owner_gname.utf8, out->owner_gname.len); + UNMARSHAL_U16LE(ctx, out->last_modifier_uname.len); + UNMARSHAL_BYTES(ctx, out->last_modifier_uname.utf8, out->last_modifier_uname.len); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + UNMARSHAL_U16LE(ctx, out->extension.len); + UNMARSHAL_BYTES(ctx, out->extension.utf8, out->extension.len); + UNMARSHAL_U32LE(ctx, out->owner_unum); + UNMARSHAL_U32LE(ctx, out->owner_gnum); + UNMARSHAL_U32LE(ctx, out->last_modifier_unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +static void unmarshal_Tversion([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tversion *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->max_msg_size); + UNMARSHAL_U16LE(ctx, out->version.len); + UNMARSHAL_BYTES(ctx, out->version.utf8, out->version.len); +} + +static void unmarshal_Rversion([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rversion *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->max_msg_size); + UNMARSHAL_U16LE(ctx, out->version.len); + UNMARSHAL_BYTES(ctx, out->version.utf8, out->version.len); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static void unmarshal_Tauth([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tauth *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->afid); + UNMARSHAL_U16LE(ctx, out->uname.len); + UNMARSHAL_BYTES(ctx, out->uname.utf8, out->uname.len); + UNMARSHAL_U16LE(ctx, out->aname.len); + UNMARSHAL_BYTES(ctx, out->aname.utf8, out->aname.len); +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { + UNMARSHAL_U32LE(ctx, out->unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ +} + +static void unmarshal_Rauth([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rauth *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->aqid.type); + UNMARSHAL_U32LE(ctx, out->aqid.vers); + UNMARSHAL_U64LE(ctx, out->aqid.path); +} + +static void unmarshal_Tattach([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tattach *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U32LE(ctx, out->afid); + UNMARSHAL_U16LE(ctx, out->uname.len); + UNMARSHAL_BYTES(ctx, out->uname.utf8, out->uname.len); + UNMARSHAL_U16LE(ctx, out->aname.len); + UNMARSHAL_BYTES(ctx, out->aname.utf8, out->aname.len); +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { + UNMARSHAL_U32LE(ctx, out->unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ +} + +static void unmarshal_Rattach([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rattach *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +static void unmarshal_Rerror([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rerror *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U16LE(ctx, out->errstr.len); + UNMARSHAL_BYTES(ctx, out->errstr.utf8, out->errstr.len); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + UNMARSHAL_U32LE(ctx, out->errnum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static void unmarshal_Tflush([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tflush *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U16LE(ctx, out->oldtag); +} + +static void unmarshal_Rflush([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rflush *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Twalk([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Twalk *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U32LE(ctx, out->newfid); + UNMARSHAL_U16LE(ctx, out->nwname); + out->wname = extra; + extra += sizeof(out->wname[0]) * out->nwname; + for (uint16_t i = 0; i < out->nwname; i++) { + UNMARSHAL_U16LE(ctx, out->wname[i].len); + UNMARSHAL_BYTES(ctx, out->wname[i].utf8, out->wname[i].len); + } +} + +static void unmarshal_Rwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rwalk *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U16LE(ctx, out->nwqid); + out->wqid = extra; + extra += sizeof(out->wqid[0]) * out->nwqid; + for (uint16_t i = 0; i < out->nwqid; i++) { + UNMARSHAL_U8LE(ctx, out->wqid[i].type); + UNMARSHAL_U32LE(ctx, out->wqid[i].vers); + UNMARSHAL_U64LE(ctx, out->wqid[i].path); + } +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static void unmarshal_Topen([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Topen *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U8LE(ctx, out->mode); +} + +static void unmarshal_Ropen([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Ropen *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); + UNMARSHAL_U32LE(ctx, out->iounit); +} + +static void unmarshal_Tcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tcreate *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); + UNMARSHAL_U32LE(ctx, out->perm); + UNMARSHAL_U8LE(ctx, out->mode); +} + +static void unmarshal_Rcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rcreate *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); + UNMARSHAL_U32LE(ctx, out->iounit); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static void unmarshal_Tread([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tread *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U64LE(ctx, out->offset); + UNMARSHAL_U32LE(ctx, out->count); +} + +static void unmarshal_Rread([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rread *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->count); + out->data.iov = ctx->extra; + ctx->extra += sizeof(out->data.iov[0]); + out->data.iov->iov_base = &ctx->net_bytes[ctx->net_offset]; + out->data.iov->iov_len = out->count; + out->data.iovcnt = 1; +} + +static void unmarshal_Twrite([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Twrite *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U64LE(ctx, out->offset); + UNMARSHAL_U32LE(ctx, out->count); + out->data.iov = ctx->extra; + ctx->extra += sizeof(out->data.iov[0]); + out->data.iov->iov_base = &ctx->net_bytes[ctx->net_offset]; + out->data.iov->iov_len = out->count; + out->data.iovcnt = 1; +} + +static void unmarshal_Rwrite([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rwrite *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->count); +} + +static void unmarshal_Tclunk([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tclunk *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); +} + +static void unmarshal_Rclunk([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rclunk *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Tremove([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tremove *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); +} + +static void unmarshal_Rremove([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rremove *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static void unmarshal_Tstat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tstat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); +} + +static void unmarshal_Rstat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rstat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + net_offset += 2; + net_offset += 2; + UNMARSHAL_U16LE(ctx, out->stat.fstype); + UNMARSHAL_U32LE(ctx, out->stat.fsdev); + UNMARSHAL_U8LE(ctx, out->stat.qid.type); + UNMARSHAL_U32LE(ctx, out->stat.qid.vers); + UNMARSHAL_U64LE(ctx, out->stat.qid.path); + UNMARSHAL_U32LE(ctx, out->stat.mode); + UNMARSHAL_U32LE(ctx, out->stat.atime); + UNMARSHAL_U32LE(ctx, out->stat.mtime); + UNMARSHAL_U64LE(ctx, out->stat.length); + UNMARSHAL_U16LE(ctx, out->stat.name.len); + UNMARSHAL_BYTES(ctx, out->stat.name.utf8, out->stat.name.len); + UNMARSHAL_U16LE(ctx, out->stat.owner_uname.len); + UNMARSHAL_BYTES(ctx, out->stat.owner_uname.utf8, out->stat.owner_uname.len); + UNMARSHAL_U16LE(ctx, out->stat.owner_gname.len); + UNMARSHAL_BYTES(ctx, out->stat.owner_gname.utf8, out->stat.owner_gname.len); + UNMARSHAL_U16LE(ctx, out->stat.last_modifier_uname.len); + UNMARSHAL_BYTES(ctx, out->stat.last_modifier_uname.utf8, out->stat.last_modifier_uname.len); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + UNMARSHAL_U16LE(ctx, out->stat.extension.len); + UNMARSHAL_BYTES(ctx, out->stat.extension.utf8, out->stat.extension.len); + UNMARSHAL_U32LE(ctx, out->stat.owner_unum); + UNMARSHAL_U32LE(ctx, out->stat.owner_gnum); + UNMARSHAL_U32LE(ctx, out->stat.last_modifier_unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +} + +static void unmarshal_Twstat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Twstat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + net_offset += 2; + net_offset += 2; + UNMARSHAL_U16LE(ctx, out->stat.fstype); + UNMARSHAL_U32LE(ctx, out->stat.fsdev); + UNMARSHAL_U8LE(ctx, out->stat.qid.type); + UNMARSHAL_U32LE(ctx, out->stat.qid.vers); + UNMARSHAL_U64LE(ctx, out->stat.qid.path); + UNMARSHAL_U32LE(ctx, out->stat.mode); + UNMARSHAL_U32LE(ctx, out->stat.atime); + UNMARSHAL_U32LE(ctx, out->stat.mtime); + UNMARSHAL_U64LE(ctx, out->stat.length); + UNMARSHAL_U16LE(ctx, out->stat.name.len); + UNMARSHAL_BYTES(ctx, out->stat.name.utf8, out->stat.name.len); + UNMARSHAL_U16LE(ctx, out->stat.owner_uname.len); + UNMARSHAL_BYTES(ctx, out->stat.owner_uname.utf8, out->stat.owner_uname.len); + UNMARSHAL_U16LE(ctx, out->stat.owner_gname.len); + UNMARSHAL_BYTES(ctx, out->stat.owner_gname.utf8, out->stat.owner_gname.len); + UNMARSHAL_U16LE(ctx, out->stat.last_modifier_uname.len); + UNMARSHAL_BYTES(ctx, out->stat.last_modifier_uname.utf8, out->stat.last_modifier_uname.len); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + UNMARSHAL_U16LE(ctx, out->stat.extension.len); + UNMARSHAL_BYTES(ctx, out->stat.extension.utf8, out->stat.extension.len); + UNMARSHAL_U32LE(ctx, out->stat.owner_unum); + UNMARSHAL_U32LE(ctx, out->stat.owner_gnum); + UNMARSHAL_U32LE(ctx, out->stat.last_modifier_unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +} + +static void unmarshal_Rwstat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rwstat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_p9p +static void unmarshal_Topenfd([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Topenfd *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U8LE(ctx, out->mode); +} + +static void unmarshal_Ropenfd([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Ropenfd *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); + UNMARSHAL_U32LE(ctx, out->iounit); + UNMARSHAL_U32LE(ctx, out->unixfd); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_L +static void unmarshal_Rlerror([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rlerror *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->errnum); +} + +static void unmarshal_Tstatfs([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tstatfs *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); +} + +static void unmarshal_Rstatfs([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rstatfs *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->type); + UNMARSHAL_U32LE(ctx, out->bsize); + UNMARSHAL_U64LE(ctx, out->blocks); + UNMARSHAL_U64LE(ctx, out->bfree); + UNMARSHAL_U64LE(ctx, out->bavail); + UNMARSHAL_U64LE(ctx, out->files); + UNMARSHAL_U64LE(ctx, out->ffree); + UNMARSHAL_U64LE(ctx, out->fsid); + UNMARSHAL_U32LE(ctx, out->namelen); +} + +static void unmarshal_Tlopen([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tlopen *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U32LE(ctx, out->flags); +} + +static void unmarshal_Rlopen([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rlopen *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); + UNMARSHAL_U32LE(ctx, out->iounit); +} + +static void unmarshal_Tlcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tlcreate *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); + UNMARSHAL_U32LE(ctx, out->flags); + UNMARSHAL_U32LE(ctx, out->mode); + UNMARSHAL_U32LE(ctx, out->gid); +} + +static void unmarshal_Rlcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rlcreate *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); + UNMARSHAL_U32LE(ctx, out->iounit); +} + +static void unmarshal_Tsymlink([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tsymlink *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); + UNMARSHAL_U16LE(ctx, out->symtgt.len); + UNMARSHAL_BYTES(ctx, out->symtgt.utf8, out->symtgt.len); + UNMARSHAL_U32LE(ctx, out->gid); +} + +static void unmarshal_Rsymlink([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rsymlink *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); +} + +static void unmarshal_Tmknod([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tmknod *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->dfid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); + UNMARSHAL_U32LE(ctx, out->mode); + UNMARSHAL_U32LE(ctx, out->major); + UNMARSHAL_U32LE(ctx, out->minor); + UNMARSHAL_U32LE(ctx, out->gid); +} + +static void unmarshal_Rmknod([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rmknod *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); +} + +static void unmarshal_Trename([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Trename *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U32LE(ctx, out->dfid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); +} + +static void unmarshal_Rrename([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rrename *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Treadlink([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Treadlink *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); +} + +static void unmarshal_Rreadlink([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rreadlink *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U16LE(ctx, out->target.len); + UNMARSHAL_BYTES(ctx, out->target.utf8, out->target.len); +} + +static void unmarshal_Tgetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tgetattr *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U64LE(ctx, out->request_mask); +} + +static void unmarshal_Rgetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rgetattr *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U64LE(ctx, out->valid); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); + UNMARSHAL_U32LE(ctx, out->mode); + UNMARSHAL_U32LE(ctx, out->uid); + UNMARSHAL_U32LE(ctx, out->gid); + UNMARSHAL_U64LE(ctx, out->nlink); + UNMARSHAL_U64LE(ctx, out->rdev); + UNMARSHAL_U64LE(ctx, out->filesize); + UNMARSHAL_U64LE(ctx, out->blksize); + UNMARSHAL_U64LE(ctx, out->blocks); + UNMARSHAL_U64LE(ctx, out->atime_sec); + UNMARSHAL_U64LE(ctx, out->atime_nsec); + UNMARSHAL_U64LE(ctx, out->mtime_sec); + UNMARSHAL_U64LE(ctx, out->mtime_nsec); + UNMARSHAL_U64LE(ctx, out->ctime_sec); + UNMARSHAL_U64LE(ctx, out->ctime_nsec); + UNMARSHAL_U64LE(ctx, out->btime_sec); + UNMARSHAL_U64LE(ctx, out->btime_nsec); + UNMARSHAL_U64LE(ctx, out->gen); + UNMARSHAL_U64LE(ctx, out->data_version); +} + +static void unmarshal_Tsetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tsetattr *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U32LE(ctx, out->valid); + UNMARSHAL_U32LE(ctx, out->mode); + UNMARSHAL_U32LE(ctx, out->uid); + UNMARSHAL_U32LE(ctx, out->gid); + UNMARSHAL_U64LE(ctx, out->filesize); + UNMARSHAL_U64LE(ctx, out->atime_sec); + UNMARSHAL_U64LE(ctx, out->atime_nsec); + UNMARSHAL_U64LE(ctx, out->mtime_sec); + UNMARSHAL_U64LE(ctx, out->mtime_nsec); +} + +static void unmarshal_Rsetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rsetattr *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Txattrwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Txattrwalk *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U32LE(ctx, out->newfid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); +} + +static void unmarshal_Rxattrwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rxattrwalk *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U64LE(ctx, out->attr_size); +} + +static void unmarshal_Txattrcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Txattrcreate *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); + UNMARSHAL_U64LE(ctx, out->attr_size); + UNMARSHAL_U32LE(ctx, out->flags); +} + +static void unmarshal_Rxattrcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rxattrcreate *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Treaddir([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Treaddir *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U64LE(ctx, out->offset); + UNMARSHAL_U32LE(ctx, out->count); +} + +static void unmarshal_Rreaddir([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rreaddir *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->count); + out->data.iov = ctx->extra; + ctx->extra += sizeof(out->data.iov[0]); + out->data.iov->iov_base = &ctx->net_bytes[ctx->net_offset]; + out->data.iov->iov_len = out->count; + out->data.iovcnt = 1; +} + +static void unmarshal_Tfsync([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tfsync *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U32LE(ctx, out->datasync); +} + +static void unmarshal_Rfsync([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rfsync *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Tlock([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tlock *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U8LE(ctx, out->type); + UNMARSHAL_U32LE(ctx, out->flags); + UNMARSHAL_U64LE(ctx, out->start); + UNMARSHAL_U64LE(ctx, out->length); + UNMARSHAL_U32LE(ctx, out->proc_id); + UNMARSHAL_U16LE(ctx, out->client_id.len); + UNMARSHAL_BYTES(ctx, out->client_id.utf8, out->client_id.len); +} + +static void unmarshal_Rlock([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rlock *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->status); +} + +static void unmarshal_Tgetlock([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tgetlock *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U8LE(ctx, out->type); + UNMARSHAL_U64LE(ctx, out->start); + UNMARSHAL_U64LE(ctx, out->length); + UNMARSHAL_U32LE(ctx, out->proc_id); + UNMARSHAL_U16LE(ctx, out->client_id.len); + UNMARSHAL_BYTES(ctx, out->client_id.utf8, out->client_id.len); +} + +static void unmarshal_Rgetlock([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rgetlock *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->type); + UNMARSHAL_U64LE(ctx, out->start); + UNMARSHAL_U64LE(ctx, out->length); + UNMARSHAL_U32LE(ctx, out->proc_id); + UNMARSHAL_U16LE(ctx, out->client_id.len); + UNMARSHAL_BYTES(ctx, out->client_id.utf8, out->client_id.len); +} + +static void unmarshal_Tlink([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tlink *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->dfid); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); +} + +static void unmarshal_Rlink([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rlink *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Tmkdir([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tmkdir *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->dfid); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); + UNMARSHAL_U32LE(ctx, out->mode); + UNMARSHAL_U32LE(ctx, out->gid); +} + +static void unmarshal_Rmkdir([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rmkdir *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U8LE(ctx, out->qid.type); + UNMARSHAL_U32LE(ctx, out->qid.vers); + UNMARSHAL_U64LE(ctx, out->qid.path); +} + +static void unmarshal_Trenameat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Trenameat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->olddirfid); + UNMARSHAL_U16LE(ctx, out->oldname.len); + UNMARSHAL_BYTES(ctx, out->oldname.utf8, out->oldname.len); + UNMARSHAL_U32LE(ctx, out->newdirfid); + UNMARSHAL_U16LE(ctx, out->newname.len); + UNMARSHAL_BYTES(ctx, out->newname.utf8, out->newname.len); +} + +static void unmarshal_Rrenameat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rrenameat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Tunlinkat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tunlinkat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->dirfd); + UNMARSHAL_U16LE(ctx, out->name.len); + UNMARSHAL_BYTES(ctx, out->name.utf8, out->name.len); + UNMARSHAL_U32LE(ctx, out->flags); +} + +static void unmarshal_Runlinkat([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Runlinkat *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e +static void unmarshal_Tsession([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tsession *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U64LE(ctx, out->key); +} + +static void unmarshal_Rsession([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rsession *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); +} + +static void unmarshal_Tsread([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tsread *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U16LE(ctx, out->nwname); + out->wname = extra; + extra += sizeof(out->wname[0]) * out->nwname; + for (uint16_t i = 0; i < out->nwname; i++) { + UNMARSHAL_U16LE(ctx, out->wname[i].len); + UNMARSHAL_BYTES(ctx, out->wname[i].utf8, out->wname[i].len); + } +} + +static void unmarshal_Rsread([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rsread *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->count); + out->data.iov = ctx->extra; + ctx->extra += sizeof(out->data.iov[0]); + out->data.iov->iov_base = &ctx->net_bytes[ctx->net_offset]; + out->data.iov->iov_len = out->count; + out->data.iovcnt = 1; +} + +static void unmarshal_Tswrite([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Tswrite *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->fid); + UNMARSHAL_U16LE(ctx, out->nwname); + out->wname = extra; + extra += sizeof(out->wname[0]) * out->nwname; + for (uint16_t i = 0; i < out->nwname; i++) { + UNMARSHAL_U16LE(ctx, out->wname[i].len); + UNMARSHAL_BYTES(ctx, out->wname[i].utf8, out->wname[i].len); + } + UNMARSHAL_U32LE(ctx, out->count); + out->data.iov = ctx->extra; + ctx->extra += sizeof(out->data.iov[0]); + out->data.iov->iov_base = &ctx->net_bytes[ctx->net_offset]; + out->data.iov->iov_len = out->count; + out->data.iovcnt = 1; +} + +static void unmarshal_Rswrite([[maybe_unused]] struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out_buf) { + struct lib9p_msg_Rswrite *out = out_buf; + [[maybe_unused]] void *extra = &out[1]; + uint32_t net_offset = 0; + net_offset += 4; + net_offset += 1; + UNMARSHAL_U16LE(ctx, out->tag); + UNMARSHAL_U32LE(ctx, out->count); +} +#endif /* CONFIG_9P_ENABLE_9P2000_e */ + +/* marshal_* ******************************************************************/ + +#define MARSHAL_BYTES_ZEROCOPY(ctx, data, len) \ + if (ret->net_iov[ret->net_iov_cnt-1].iov_len) \ + ret->net_iov_cnt++; \ + ret->net_iov[ret->net_iov_cnt-1].iov_base = data; \ + ret->net_iov[ret->net_iov_cnt-1].iov_len = len; \ + ret->net_iov_cnt++; +#define MARSHAL_BYTES(ctx, data, len) \ + if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ + ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ + memcpy(&ret->net_copied[ret->net_copied_size], data, len); \ + ret->net_copied_size += len; \ + ret->net_iov[ret->net_iov_cnt-1].iov_len += len; +#define MARSHAL_U8LE(ctx, val) \ + if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ + ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ + ret->net_copied[ret->net_copied_size] = val; \ + ret->net_copied_size += 1; \ + ret->net_iov[ret->net_iov_cnt-1].iov_len += 1; +#define MARSHAL_U16LE(ctx, val) \ + if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ + ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ + uint16le_encode(&ret->net_copied[ret->net_copied_size], val); \ + ret->net_copied_size += 2; \ + ret->net_iov[ret->net_iov_cnt-1].iov_len += 2; +#define MARSHAL_U32LE(ctx, val) \ + if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ + ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ + uint32le_encode(&ret->net_copied[ret->net_copied_size], val); \ + ret->net_copied_size += 4; \ + ret->net_iov[ret->net_iov_cnt-1].iov_len += 4; +#define MARSHAL_U64LE(ctx, val) \ + if (!ret->net_iov[ret->net_iov_cnt-1].iov_base) \ + ret->net_iov[ret->net_iov_cnt-1].iov_base = &ret->net_copied[ret->net_copied_size]; \ + uint64le_encode(&ret->net_copied[ret->net_copied_size], val); \ + ret->net_copied_size += 8; \ + ret->net_iov[ret->net_iov_cnt-1].iov_len += 8; + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static bool marshal_stat(struct lib9p_ctx *ctx, struct lib9p_stat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 49 + val->name.len + val->owner_uname.len + val->owner_gname.len + val->last_modifier_uname.len; +#if CONFIG_9P_ENABLE_9P2000_u + if is_ver(ctx, 9P2000_u) { + needed_size += 14 + val->extension.len; + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + if (needed_size > ctx->max_msg_size) { + return true; + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_fstype = 2; + MARSHAL_U16LE(ctx, offsetof_end - offsetof_fstype); + MARSHAL_U16LE(ctx, val->fstype); + MARSHAL_U32LE(ctx, val->fsdev); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + MARSHAL_U32LE(ctx, val->mode & dm_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->atime); + MARSHAL_U32LE(ctx, val->mtime); + MARSHAL_U64LE(ctx, val->length); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES(ctx, val->name.utf8, val->name.len); + MARSHAL_U16LE(ctx, val->owner_uname.len); + MARSHAL_BYTES(ctx, val->owner_uname.utf8, val->owner_uname.len); + MARSHAL_U16LE(ctx, val->owner_gname.len); + MARSHAL_BYTES(ctx, val->owner_gname.utf8, val->owner_gname.len); + MARSHAL_U16LE(ctx, val->last_modifier_uname.len); + MARSHAL_BYTES(ctx, val->last_modifier_uname.utf8, val->last_modifier_uname.len); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + MARSHAL_U16LE(ctx, val->extension.len); + MARSHAL_BYTES(ctx, val->extension.utf8, val->extension.len); + MARSHAL_U32LE(ctx, val->owner_unum); + MARSHAL_U32LE(ctx, val->owner_gnum); + MARSHAL_U32LE(ctx, val->last_modifier_unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + return false; +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +static error marshal_Tversion(struct lib9p_ctx *ctx, struct lib9p_msg_Tversion *val, struct _marshal_ret *ret) { + uint32_t needed_size = 13 + val->version.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tversion message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 100); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->max_msg_size); + MARSHAL_U16LE(ctx, val->version.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->version.utf8, val->version.len); + return ERROR_NULL; +} + +static error marshal_Rversion(struct lib9p_ctx *ctx, struct lib9p_msg_Rversion *val, struct _marshal_ret *ret) { + uint32_t needed_size = 13 + val->version.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rversion message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 101); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->max_msg_size); + MARSHAL_U16LE(ctx, val->version.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->version.utf8, val->version.len); + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static error marshal_Tauth(struct lib9p_ctx *ctx, struct lib9p_msg_Tauth *val, struct _marshal_ret *ret) { + uint32_t needed_size = 15 + val->uname.len + val->aname.len; +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + if ( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) ) { + needed_size += 4; + } +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tauth message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 102); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->afid); + MARSHAL_U16LE(ctx, val->uname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->uname.utf8, val->uname.len); + MARSHAL_U16LE(ctx, val->aname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->aname.utf8, val->aname.len); +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { + MARSHAL_U32LE(ctx, val->unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ + return ERROR_NULL; +} + +static error marshal_Rauth(struct lib9p_ctx *ctx, struct lib9p_msg_Rauth *val, struct _marshal_ret *ret) { + uint32_t needed_size = 20; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rauth message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 103); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->aqid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->aqid.vers); + MARSHAL_U64LE(ctx, val->aqid.path); + return ERROR_NULL; +} + +static error marshal_Tattach(struct lib9p_ctx *ctx, struct lib9p_msg_Tattach *val, struct _marshal_ret *ret) { + uint32_t needed_size = 19 + val->uname.len + val->aname.len; +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + if ( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) ) { + needed_size += 4; + } +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tattach message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 104); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U32LE(ctx, val->afid); + MARSHAL_U16LE(ctx, val->uname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->uname.utf8, val->uname.len); + MARSHAL_U16LE(ctx, val->aname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->aname.utf8, val->aname.len); +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + if (( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) )) { + MARSHAL_U32LE(ctx, val->unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ + return ERROR_NULL; +} + +static error marshal_Rattach(struct lib9p_ctx *ctx, struct lib9p_msg_Rattach *val, struct _marshal_ret *ret) { + uint32_t needed_size = 20; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rattach message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 105); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +static error marshal_Rerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rerror *val, struct _marshal_ret *ret) { + uint32_t needed_size = 9 + val->errstr.len; +#if CONFIG_9P_ENABLE_9P2000_u + if is_ver(ctx, 9P2000_u) { + needed_size += 4; + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rerror message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 107); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U16LE(ctx, val->errstr.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->errstr.utf8, val->errstr.len); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + MARSHAL_U32LE(ctx, val->errnum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static error marshal_Tflush(struct lib9p_ctx *ctx, struct lib9p_msg_Tflush *val, struct _marshal_ret *ret) { + uint32_t needed_size = 9; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tflush message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 108); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U16LE(ctx, val->oldtag); + return ERROR_NULL; +} + +static error marshal_Rflush(struct lib9p_ctx *ctx, struct lib9p_msg_Rflush *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rflush message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 109); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Twalk(struct lib9p_ctx *ctx, struct lib9p_msg_Twalk *val, struct _marshal_ret *ret) { + uint32_t needed_size = 17; + for (uint16_t i = 0; i < val->nwname; i++) { + needed_size += 2 + val->wname[i].len; + } + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Twalk message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 110); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U32LE(ctx, val->newfid); + MARSHAL_U16LE(ctx, val->nwname); + for (uint16_t i = 0; i < val->nwname; i++) { + MARSHAL_U16LE(ctx, val->wname[i].len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->wname[i].utf8, val->wname[i].len); + } + return ERROR_NULL; +} + +static error marshal_Rwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rwalk *val, struct _marshal_ret *ret) { + uint32_t needed_size = 9 + (val->nwqid)*13; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rwalk message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 111); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U16LE(ctx, val->nwqid); + for (uint16_t i = 0; i < val->nwqid; i++) { + MARSHAL_U8LE(ctx, val->wqid[i].type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->wqid[i].vers); + MARSHAL_U64LE(ctx, val->wqid[i].path); + } + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static error marshal_Topen(struct lib9p_ctx *ctx, struct lib9p_msg_Topen *val, struct _marshal_ret *ret) { + uint32_t needed_size = 12; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Topen message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 112); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); + return ERROR_NULL; +} + +static error marshal_Ropen(struct lib9p_ctx *ctx, struct lib9p_msg_Ropen *val, struct _marshal_ret *ret) { + uint32_t needed_size = 24; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Ropen message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 113); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + MARSHAL_U32LE(ctx, val->iounit); + return ERROR_NULL; +} + +static error marshal_Tcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tcreate *val, struct _marshal_ret *ret) { + uint32_t needed_size = 18 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tcreate message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 114); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + MARSHAL_U32LE(ctx, val->perm & dm_masks[ctx->version]); + MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); + return ERROR_NULL; +} + +static error marshal_Rcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rcreate *val, struct _marshal_ret *ret) { + uint32_t needed_size = 24; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rcreate message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 115); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + MARSHAL_U32LE(ctx, val->iounit); + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static error marshal_Tread(struct lib9p_ctx *ctx, struct lib9p_msg_Tread *val, struct _marshal_ret *ret) { + uint32_t needed_size = 23; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tread message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 116); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U64LE(ctx, val->offset); + MARSHAL_U32LE(ctx, val->count); + return ERROR_NULL; +} + +static error marshal_Rread(struct lib9p_ctx *ctx, struct lib9p_msg_Rread *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11 + val->count; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rread message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 117); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->count); + for (int iov_i = 0; iov_i < val->data->iovcnt; iov_i++) + MARSHAL_BYTES_ZEROCOPY(ctx, val->data->iov[iov_i].iov_base, val->data->iov[iov_i].iov_len); + return ERROR_NULL; +} + +static error marshal_Twrite(struct lib9p_ctx *ctx, struct lib9p_msg_Twrite *val, struct _marshal_ret *ret) { + uint32_t needed_size = 23 + val->count; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Twrite message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 118); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U64LE(ctx, val->offset); + MARSHAL_U32LE(ctx, val->count); + for (int iov_i = 0; iov_i < val->data->iovcnt; iov_i++) + MARSHAL_BYTES_ZEROCOPY(ctx, val->data->iov[iov_i].iov_base, val->data->iov[iov_i].iov_len); + return ERROR_NULL; +} + +static error marshal_Rwrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rwrite *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rwrite message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 119); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->count); + return ERROR_NULL; +} + +static error marshal_Tclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Tclunk *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tclunk message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 120); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + return ERROR_NULL; +} + +static error marshal_Rclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Rclunk *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rclunk message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 121); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Tremove(struct lib9p_ctx *ctx, struct lib9p_msg_Tremove *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tremove message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 122); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + return ERROR_NULL; +} + +static error marshal_Rremove(struct lib9p_ctx *ctx, struct lib9p_msg_Rremove *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rremove message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 123); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +static error marshal_Tstat(struct lib9p_ctx *ctx, struct lib9p_msg_Tstat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tstat message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 124); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + return ERROR_NULL; +} + +static error marshal_Rstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rstat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 58 + val->stat.name.len + val->stat.owner_uname.len + val->stat.owner_gname.len + val->stat.last_modifier_uname.len; +#if CONFIG_9P_ENABLE_9P2000_u + if is_ver(ctx, 9P2000_u) { + needed_size += 14 + val->stat.extension.len; + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rstat message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + uint32_t offsetof_stat = 9; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 125); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U16LE(ctx, offsetof_end - offsetof_stat); + uint32_t offsetof_stat_end = 49 + val->stat.name.len + val->stat.owner_uname.len + val->stat.owner_gname.len + val->stat.last_modifier_uname.len; +#if CONFIG_9P_ENABLE_9P2000_u + if is_ver(ctx, 9P2000_u) { + offsetof_stat_end += 14 + val->stat.extension.len; + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + uint32_t offsetof_stat_fstype = 2; + MARSHAL_U16LE(ctx, offsetof_stat_end - offsetof_stat_fstype); + MARSHAL_U16LE(ctx, val->stat.fstype); + MARSHAL_U32LE(ctx, val->stat.fsdev); + MARSHAL_U8LE(ctx, val->stat.qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->stat.qid.vers); + MARSHAL_U64LE(ctx, val->stat.qid.path); + MARSHAL_U32LE(ctx, val->stat.mode & dm_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->stat.atime); + MARSHAL_U32LE(ctx, val->stat.mtime); + MARSHAL_U64LE(ctx, val->stat.length); + MARSHAL_U16LE(ctx, val->stat.name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.name.utf8, val->stat.name.len); + MARSHAL_U16LE(ctx, val->stat.owner_uname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.owner_uname.utf8, val->stat.owner_uname.len); + MARSHAL_U16LE(ctx, val->stat.owner_gname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.owner_gname.utf8, val->stat.owner_gname.len); + MARSHAL_U16LE(ctx, val->stat.last_modifier_uname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.last_modifier_uname.utf8, val->stat.last_modifier_uname.len); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + MARSHAL_U16LE(ctx, val->stat.extension.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.extension.utf8, val->stat.extension.len); + MARSHAL_U32LE(ctx, val->stat.owner_unum); + MARSHAL_U32LE(ctx, val->stat.owner_gnum); + MARSHAL_U32LE(ctx, val->stat.last_modifier_unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + return ERROR_NULL; +} + +static error marshal_Twstat(struct lib9p_ctx *ctx, struct lib9p_msg_Twstat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 62 + val->stat.name.len + val->stat.owner_uname.len + val->stat.owner_gname.len + val->stat.last_modifier_uname.len; +#if CONFIG_9P_ENABLE_9P2000_u + if is_ver(ctx, 9P2000_u) { + needed_size += 14 + val->stat.extension.len; + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Twstat message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + uint32_t offsetof_stat = 13; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 126); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U16LE(ctx, offsetof_end - offsetof_stat); + uint32_t offsetof_stat_end = 49 + val->stat.name.len + val->stat.owner_uname.len + val->stat.owner_gname.len + val->stat.last_modifier_uname.len; +#if CONFIG_9P_ENABLE_9P2000_u + if is_ver(ctx, 9P2000_u) { + offsetof_stat_end += 14 + val->stat.extension.len; + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + uint32_t offsetof_stat_fstype = 2; + MARSHAL_U16LE(ctx, offsetof_stat_end - offsetof_stat_fstype); + MARSHAL_U16LE(ctx, val->stat.fstype); + MARSHAL_U32LE(ctx, val->stat.fsdev); + MARSHAL_U8LE(ctx, val->stat.qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->stat.qid.vers); + MARSHAL_U64LE(ctx, val->stat.qid.path); + MARSHAL_U32LE(ctx, val->stat.mode & dm_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->stat.atime); + MARSHAL_U32LE(ctx, val->stat.mtime); + MARSHAL_U64LE(ctx, val->stat.length); + MARSHAL_U16LE(ctx, val->stat.name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.name.utf8, val->stat.name.len); + MARSHAL_U16LE(ctx, val->stat.owner_uname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.owner_uname.utf8, val->stat.owner_uname.len); + MARSHAL_U16LE(ctx, val->stat.owner_gname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.owner_gname.utf8, val->stat.owner_gname.len); + MARSHAL_U16LE(ctx, val->stat.last_modifier_uname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.last_modifier_uname.utf8, val->stat.last_modifier_uname.len); +#if CONFIG_9P_ENABLE_9P2000_u + if (is_ver(ctx, 9P2000_u)) { + MARSHAL_U16LE(ctx, val->stat.extension.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->stat.extension.utf8, val->stat.extension.len); + MARSHAL_U32LE(ctx, val->stat.owner_unum); + MARSHAL_U32LE(ctx, val->stat.owner_gnum); + MARSHAL_U32LE(ctx, val->stat.last_modifier_unum); + } +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + return ERROR_NULL; +} + +static error marshal_Rwstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rwstat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rwstat message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 127); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_p9p +static error marshal_Topenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Topenfd *val, struct _marshal_ret *ret) { + uint32_t needed_size = 12; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Topenfd message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 98); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); + return ERROR_NULL; +} + +static error marshal_Ropenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Ropenfd *val, struct _marshal_ret *ret) { + uint32_t needed_size = 28; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Ropenfd message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 99); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + MARSHAL_U32LE(ctx, val->iounit); + MARSHAL_U32LE(ctx, val->unixfd); + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_L +static error marshal_Rlerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rlerror *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rlerror message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 7); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->errnum); + return ERROR_NULL; +} + +static error marshal_Tstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Tstatfs *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tstatfs message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 8); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + return ERROR_NULL; +} + +static error marshal_Rstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Rstatfs *val, struct _marshal_ret *ret) { + uint32_t needed_size = 67; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rstatfs message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 9); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->type); + MARSHAL_U32LE(ctx, val->bsize); + MARSHAL_U64LE(ctx, val->blocks); + MARSHAL_U64LE(ctx, val->bfree); + MARSHAL_U64LE(ctx, val->bavail); + MARSHAL_U64LE(ctx, val->files); + MARSHAL_U64LE(ctx, val->ffree); + MARSHAL_U64LE(ctx, val->fsid); + MARSHAL_U32LE(ctx, val->namelen); + return ERROR_NULL; +} + +static error marshal_Tlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Tlopen *val, struct _marshal_ret *ret) { + uint32_t needed_size = 15; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tlopen message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 12); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U32LE(ctx, val->flags & lo_masks[ctx->version]); + return ERROR_NULL; +} + +static error marshal_Rlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Rlopen *val, struct _marshal_ret *ret) { + uint32_t needed_size = 24; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rlopen message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 13); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + MARSHAL_U32LE(ctx, val->iounit); + return ERROR_NULL; +} + +static error marshal_Tlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tlcreate *val, struct _marshal_ret *ret) { + uint32_t needed_size = 25 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tlcreate message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 14); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + MARSHAL_U32LE(ctx, val->flags & lo_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->gid); + return ERROR_NULL; +} + +static error marshal_Rlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rlcreate *val, struct _marshal_ret *ret) { + uint32_t needed_size = 24; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rlcreate message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 15); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + MARSHAL_U32LE(ctx, val->iounit); + return ERROR_NULL; +} + +static error marshal_Tsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tsymlink *val, struct _marshal_ret *ret) { + uint32_t needed_size = 19 + val->name.len + val->symtgt.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tsymlink message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 16); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + MARSHAL_U16LE(ctx, val->symtgt.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->symtgt.utf8, val->symtgt.len); + MARSHAL_U32LE(ctx, val->gid); + return ERROR_NULL; +} + +static error marshal_Rsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rsymlink *val, struct _marshal_ret *ret) { + uint32_t needed_size = 20; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rsymlink message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 17); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + return ERROR_NULL; +} + +static error marshal_Tmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Tmknod *val, struct _marshal_ret *ret) { + uint32_t needed_size = 29 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tmknod message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 18); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->dfid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->major); + MARSHAL_U32LE(ctx, val->minor); + MARSHAL_U32LE(ctx, val->gid); + return ERROR_NULL; +} + +static error marshal_Rmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Rmknod *val, struct _marshal_ret *ret) { + uint32_t needed_size = 20; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rmknod message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 19); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + return ERROR_NULL; +} + +static error marshal_Trename(struct lib9p_ctx *ctx, struct lib9p_msg_Trename *val, struct _marshal_ret *ret) { + uint32_t needed_size = 17 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Trename message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 20); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U32LE(ctx, val->dfid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + return ERROR_NULL; +} + +static error marshal_Rrename(struct lib9p_ctx *ctx, struct lib9p_msg_Rrename *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rrename message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 21); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Treadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Treadlink *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Treadlink message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 22); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + return ERROR_NULL; +} + +static error marshal_Rreadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rreadlink *val, struct _marshal_ret *ret) { + uint32_t needed_size = 9 + val->target.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rreadlink message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 23); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U16LE(ctx, val->target.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->target.utf8, val->target.len); + return ERROR_NULL; +} + +static error marshal_Tgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetattr *val, struct _marshal_ret *ret) { + uint32_t needed_size = 19; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tgetattr message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 24); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U64LE(ctx, val->request_mask & getattr_masks[ctx->version]); + return ERROR_NULL; +} + +static error marshal_Rgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetattr *val, struct _marshal_ret *ret) { + uint32_t needed_size = 160; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rgetattr message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 25); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U64LE(ctx, val->valid & getattr_masks[ctx->version]); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->uid); + MARSHAL_U32LE(ctx, val->gid); + MARSHAL_U64LE(ctx, val->nlink); + MARSHAL_U64LE(ctx, val->rdev); + MARSHAL_U64LE(ctx, val->filesize); + MARSHAL_U64LE(ctx, val->blksize); + MARSHAL_U64LE(ctx, val->blocks); + MARSHAL_U64LE(ctx, val->atime_sec); + MARSHAL_U64LE(ctx, val->atime_nsec); + MARSHAL_U64LE(ctx, val->mtime_sec); + MARSHAL_U64LE(ctx, val->mtime_nsec); + MARSHAL_U64LE(ctx, val->ctime_sec); + MARSHAL_U64LE(ctx, val->ctime_nsec); + MARSHAL_U64LE(ctx, val->btime_sec); + MARSHAL_U64LE(ctx, val->btime_nsec); + MARSHAL_U64LE(ctx, val->gen); + MARSHAL_U64LE(ctx, val->data_version); + return ERROR_NULL; +} + +static error marshal_Tsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tsetattr *val, struct _marshal_ret *ret) { + uint32_t needed_size = 67; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tsetattr message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 26); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U32LE(ctx, val->valid & setattr_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->uid); + MARSHAL_U32LE(ctx, val->gid); + MARSHAL_U64LE(ctx, val->filesize); + MARSHAL_U64LE(ctx, val->atime_sec); + MARSHAL_U64LE(ctx, val->atime_nsec); + MARSHAL_U64LE(ctx, val->mtime_sec); + MARSHAL_U64LE(ctx, val->mtime_nsec); + return ERROR_NULL; +} + +static error marshal_Rsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rsetattr *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rsetattr message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 27); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Txattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrwalk *val, struct _marshal_ret *ret) { + uint32_t needed_size = 17 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Txattrwalk message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 30); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U32LE(ctx, val->newfid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + return ERROR_NULL; +} + +static error marshal_Rxattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrwalk *val, struct _marshal_ret *ret) { + uint32_t needed_size = 15; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rxattrwalk message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 31); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U64LE(ctx, val->attr_size); + return ERROR_NULL; +} + +static error marshal_Txattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrcreate *val, struct _marshal_ret *ret) { + uint32_t needed_size = 25 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Txattrcreate message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 32); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + MARSHAL_U64LE(ctx, val->attr_size); + MARSHAL_U32LE(ctx, val->flags); + return ERROR_NULL; +} + +static error marshal_Rxattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrcreate *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rxattrcreate message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 33); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Treaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Treaddir *val, struct _marshal_ret *ret) { + uint32_t needed_size = 23; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Treaddir message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 40); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U64LE(ctx, val->offset); + MARSHAL_U32LE(ctx, val->count); + return ERROR_NULL; +} + +static error marshal_Rreaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Rreaddir *val, struct _marshal_ret *ret) { + uint64_t needed_size = 11 + val->count; + if (needed_size > (uint64_t)(ctx->max_msg_size)) { + return error_new(E_POSIX_ERANGE, "Rreaddir message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = (uint32_t)needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 41); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->count); + for (int iov_i = 0; iov_i < val->data->iovcnt; iov_i++) + MARSHAL_BYTES_ZEROCOPY(ctx, val->data->iov[iov_i].iov_base, val->data->iov[iov_i].iov_len); + return ERROR_NULL; +} + +static error marshal_Tfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Tfsync *val, struct _marshal_ret *ret) { + uint32_t needed_size = 15; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tfsync message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 50); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U32LE(ctx, val->datasync); + return ERROR_NULL; +} + +static error marshal_Rfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Rfsync *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rfsync message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 51); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Tlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tlock *val, struct _marshal_ret *ret) { + uint32_t needed_size = 38 + val->client_id.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tlock message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 52); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U8LE(ctx, val->type); + MARSHAL_U32LE(ctx, val->flags & lock_flags_masks[ctx->version]); + MARSHAL_U64LE(ctx, val->start); + MARSHAL_U64LE(ctx, val->length); + MARSHAL_U32LE(ctx, val->proc_id); + MARSHAL_U16LE(ctx, val->client_id.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); + return ERROR_NULL; +} + +static error marshal_Rlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rlock *val, struct _marshal_ret *ret) { + uint32_t needed_size = 8; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rlock message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 53); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->status); + return ERROR_NULL; +} + +static error marshal_Tgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetlock *val, struct _marshal_ret *ret) { + uint32_t needed_size = 34 + val->client_id.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tgetlock message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 54); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U8LE(ctx, val->type); + MARSHAL_U64LE(ctx, val->start); + MARSHAL_U64LE(ctx, val->length); + MARSHAL_U32LE(ctx, val->proc_id); + MARSHAL_U16LE(ctx, val->client_id.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); + return ERROR_NULL; +} + +static error marshal_Rgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetlock *val, struct _marshal_ret *ret) { + uint32_t needed_size = 30 + val->client_id.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rgetlock message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 55); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->type); + MARSHAL_U64LE(ctx, val->start); + MARSHAL_U64LE(ctx, val->length); + MARSHAL_U32LE(ctx, val->proc_id); + MARSHAL_U16LE(ctx, val->client_id.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); + return ERROR_NULL; +} + +static error marshal_Tlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tlink *val, struct _marshal_ret *ret) { + uint32_t needed_size = 17 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tlink message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 70); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->dfid); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + return ERROR_NULL; +} + +static error marshal_Rlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rlink *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rlink message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 71); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Tmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Tmkdir *val, struct _marshal_ret *ret) { + uint32_t needed_size = 21 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tmkdir message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 72); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->dfid); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->gid); + return ERROR_NULL; +} + +static error marshal_Rmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Rmkdir *val, struct _marshal_ret *ret) { + uint32_t needed_size = 20; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rmkdir message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 73); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); + MARSHAL_U32LE(ctx, val->qid.vers); + MARSHAL_U64LE(ctx, val->qid.path); + return ERROR_NULL; +} + +static error marshal_Trenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Trenameat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 19 + val->oldname.len + val->newname.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Trenameat message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 74); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->olddirfid); + MARSHAL_U16LE(ctx, val->oldname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->oldname.utf8, val->oldname.len); + MARSHAL_U32LE(ctx, val->newdirfid); + MARSHAL_U16LE(ctx, val->newname.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->newname.utf8, val->newname.len); + return ERROR_NULL; +} + +static error marshal_Rrenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Rrenameat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rrenameat message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 75); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Tunlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Tunlinkat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 17 + val->name.len; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tunlinkat message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 76); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->dirfd); + MARSHAL_U16LE(ctx, val->name.len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); + MARSHAL_U32LE(ctx, val->flags); + return ERROR_NULL; +} + +static error marshal_Runlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Runlinkat *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Runlinkat message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 77); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e +static error marshal_Tsession(struct lib9p_ctx *ctx, struct lib9p_msg_Tsession *val, struct _marshal_ret *ret) { + uint32_t needed_size = 15; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Tsession message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 150); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U64LE(ctx, val->key); + return ERROR_NULL; +} + +static error marshal_Rsession(struct lib9p_ctx *ctx, struct lib9p_msg_Rsession *val, struct _marshal_ret *ret) { + uint32_t needed_size = 7; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rsession message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 151); + MARSHAL_U16LE(ctx, val->tag); + return ERROR_NULL; +} + +static error marshal_Tsread(struct lib9p_ctx *ctx, struct lib9p_msg_Tsread *val, struct _marshal_ret *ret) { + uint64_t needed_size = 13; + for (uint16_t i = 0; i < val->nwname; i++) { + needed_size += 2 + val->wname[i].len; + } + if (needed_size > (uint64_t)(ctx->max_msg_size)) { + return error_new(E_POSIX_ERANGE, "Tsread message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = (uint32_t)needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 152); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U16LE(ctx, val->nwname); + for (uint16_t i = 0; i < val->nwname; i++) { + MARSHAL_U16LE(ctx, val->wname[i].len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->wname[i].utf8, val->wname[i].len); + } + return ERROR_NULL; +} + +static error marshal_Rsread(struct lib9p_ctx *ctx, struct lib9p_msg_Rsread *val, struct _marshal_ret *ret) { + uint64_t needed_size = 11 + val->count; + if (needed_size > (uint64_t)(ctx->max_msg_size)) { + return error_new(E_POSIX_ERANGE, "Rsread message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = (uint32_t)needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 153); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->count); + for (int iov_i = 0; iov_i < val->data->iovcnt; iov_i++) + MARSHAL_BYTES_ZEROCOPY(ctx, val->data->iov[iov_i].iov_base, val->data->iov[iov_i].iov_len); + return ERROR_NULL; +} + +static error marshal_Tswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Tswrite *val, struct _marshal_ret *ret) { + uint64_t needed_size = 17 + val->count; + for (uint16_t i = 0; i < val->nwname; i++) { + needed_size += 2 + val->wname[i].len; + } + if (needed_size > (uint64_t)(ctx->max_msg_size)) { + return error_new(E_POSIX_ERANGE, "Tswrite message too large to marshal into ", + ctx->version ? "negotiated" : "client", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = (uint32_t)needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 154); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->fid); + MARSHAL_U16LE(ctx, val->nwname); + for (uint16_t i = 0; i < val->nwname; i++) { + MARSHAL_U16LE(ctx, val->wname[i].len); + MARSHAL_BYTES_ZEROCOPY(ctx, val->wname[i].utf8, val->wname[i].len); + } + MARSHAL_U32LE(ctx, val->count); + for (int iov_i = 0; iov_i < val->data->iovcnt; iov_i++) + MARSHAL_BYTES_ZEROCOPY(ctx, val->data->iov[iov_i].iov_base, val->data->iov[iov_i].iov_len); + return ERROR_NULL; +} + +static error marshal_Rswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rswrite *val, struct _marshal_ret *ret) { + uint32_t needed_size = 11; + if (needed_size > ctx->max_msg_size) { + return error_new(E_POSIX_ERANGE, "Rswrite message too large to marshal into ", + ctx->version ? "negotiated" : "server", " limit", + " (", needed_size, " > ", ctx->max_msg_size, ")"); + } + uint32_t offsetof_end = needed_size; + uint32_t offsetof_size = 0; + MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); + MARSHAL_U8LE(ctx, 155); + MARSHAL_U16LE(ctx, val->tag); + MARSHAL_U32LE(ctx, val->count); + return ERROR_NULL; +} +#endif /* CONFIG_9P_ENABLE_9P2000_e */ + +/* fmt_print_* ****************************************************************/ + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +[[maybe_unused]] static void fmt_print_tag(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_tag_t *self) { + switch (*self) { + case LIB9P_TAG_NOTAG: + fmt_print_str(w, "NOTAG"); + break; + default: + fmt_print_base10(w, *self); + } +} + +[[maybe_unused]] static void fmt_print_fid(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_fid_t *self) { + switch (*self) { + case LIB9P_FID_NOFID: + fmt_print_str(w, "NOFID"); + break; + default: + fmt_print_base10(w, *self); + } +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +[[maybe_unused]] static void fmt_print_dm(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_dm_t *self) { + bool empty = true; + fmt_print_byte(w, '('); + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<31)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "DIR"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<30)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "APPEND"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<29)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "EXCL"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<28)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "_PLAN9_MOUNT"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<27)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "AUTH"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<26)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "TMP"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<25)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<25"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<24)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<24"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<23)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "DEVICE"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<22)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<22"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<21)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PIPE"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<20)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "SOCKET"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<19)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "SETUID"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<18)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "SETGID"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<17)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<17"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<16)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<16"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<15)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<15"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<14)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<14"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<13)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<13"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<12)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<12"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<11)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<11"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<10)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<10"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<9)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<9"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<8)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "OWNER_R"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<7)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "OWNER_W"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<6)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "OWNER_X"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<5)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "GROUP_R"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<4)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "GROUP_W"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<3)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "GROUP_X"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<2)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "OTHER_R"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<1)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "OTHER_W"); + empty = false; + } + if ((*self & ~((lib9p_dm_t)0777)) & (UINT32_C(1)<<0)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "OTHER_X"); + empty = false; + } + if (!empty) + fmt_print_byte(w, '|'); + fmt_print(w, (rjust, 4, '0', (base8, *self & 0777))); + fmt_print_byte(w, ')'); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +[[maybe_unused]] static void fmt_print_qt(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_qt_t *self) { + bool empty = true; + fmt_print_byte(w, '('); + if (*self & (UINT8_C(1)<<7)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "DIR"); + empty = false; + } + if (*self & (UINT8_C(1)<<6)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "APPEND"); + empty = false; + } + if (*self & (UINT8_C(1)<<5)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "EXCL"); + empty = false; + } + if (*self & (UINT8_C(1)<<4)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "_PLAN9_MOUNT"); + empty = false; + } + if (*self & (UINT8_C(1)<<3)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "AUTH"); + empty = false; + } + if (*self & (UINT8_C(1)<<2)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "TMP"); + empty = false; + } + if (*self & (UINT8_C(1)<<1)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "SYMLINK"); + empty = false; + } + if (*self & (UINT8_C(1)<<0)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<0"); + empty = false; + } + if (empty) + fmt_print_byte(w, '0'); + fmt_print_byte(w, ')'); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_o(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_o_t *self) { + bool empty = true; + fmt_print_byte(w, '('); + if (*self & (UINT8_C(1)<<7)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<7"); + empty = false; + } + if (*self & (UINT8_C(1)<<6)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "RCLOSE"); + empty = false; + } + if (*self & (UINT8_C(1)<<5)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "CEXEC"); + empty = false; + } + if (*self & (UINT8_C(1)<<4)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "TRUNC"); + empty = false; + } + if (*self & (UINT8_C(1)<<3)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<3"); + empty = false; + } + if (*self & (UINT8_C(1)<<2)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<2"); + empty = false; + } + switch (*self & LIB9P_O_MODE_MASK) { + case LIB9P_O_MODE_READ: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE_READ"); + empty = false; + break; + case LIB9P_O_MODE_WRITE: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE_WRITE"); + empty = false; + break; + case LIB9P_O_MODE_RDWR: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE_RDWR"); + empty = false; + break; + case LIB9P_O_MODE_EXEC: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE_EXEC"); + empty = false; + break; + default: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_base10(w, *self & LIB9P_O_MODE_MASK); + empty = false; + } + if (empty) + fmt_print_byte(w, '0'); + fmt_print_byte(w, ')'); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_nuid(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_nuid_t *self) { + switch (*self) { + case LIB9P_NUID_NONUID: + fmt_print_str(w, "NONUID"); + break; + default: + fmt_print_base10(w, *self); + } +} + +[[maybe_unused]] static void fmt_print_errno(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_errno_t *self) { + switch (*self) { + case LIB9P_ERRNO_NOERROR: + fmt_print_str(w, "NOERROR"); + break; + case LIB9P_ERRNO_L_EPERM: + fmt_print_str(w, "L_EPERM"); + break; + case LIB9P_ERRNO_L_ENOENT: + fmt_print_str(w, "L_ENOENT"); + break; + case LIB9P_ERRNO_L_ESRCH: + fmt_print_str(w, "L_ESRCH"); + break; + case LIB9P_ERRNO_L_EINTR: + fmt_print_str(w, "L_EINTR"); + break; + case LIB9P_ERRNO_L_EIO: + fmt_print_str(w, "L_EIO"); + break; + case LIB9P_ERRNO_L_ENXIO: + fmt_print_str(w, "L_ENXIO"); + break; + case LIB9P_ERRNO_L_E2BIG: + fmt_print_str(w, "L_E2BIG"); + break; + case LIB9P_ERRNO_L_ENOEXEC: + fmt_print_str(w, "L_ENOEXEC"); + break; + case LIB9P_ERRNO_L_EBADF: + fmt_print_str(w, "L_EBADF"); + break; + case LIB9P_ERRNO_L_ECHILD: + fmt_print_str(w, "L_ECHILD"); + break; + case LIB9P_ERRNO_L_EAGAIN: + fmt_print_str(w, "L_EAGAIN"); + break; + case LIB9P_ERRNO_L_ENOMEM: + fmt_print_str(w, "L_ENOMEM"); + break; + case LIB9P_ERRNO_L_EACCES: + fmt_print_str(w, "L_EACCES"); + break; + case LIB9P_ERRNO_L_EFAULT: + fmt_print_str(w, "L_EFAULT"); + break; + case LIB9P_ERRNO_L_ENOTBLK: + fmt_print_str(w, "L_ENOTBLK"); + break; + case LIB9P_ERRNO_L_EBUSY: + fmt_print_str(w, "L_EBUSY"); + break; + case LIB9P_ERRNO_L_EEXIST: + fmt_print_str(w, "L_EEXIST"); + break; + case LIB9P_ERRNO_L_EXDEV: + fmt_print_str(w, "L_EXDEV"); + break; + case LIB9P_ERRNO_L_ENODEV: + fmt_print_str(w, "L_ENODEV"); + break; + case LIB9P_ERRNO_L_ENOTDIR: + fmt_print_str(w, "L_ENOTDIR"); + break; + case LIB9P_ERRNO_L_EISDIR: + fmt_print_str(w, "L_EISDIR"); + break; + case LIB9P_ERRNO_L_EINVAL: + fmt_print_str(w, "L_EINVAL"); + break; + case LIB9P_ERRNO_L_ENFILE: + fmt_print_str(w, "L_ENFILE"); + break; + case LIB9P_ERRNO_L_EMFILE: + fmt_print_str(w, "L_EMFILE"); + break; + case LIB9P_ERRNO_L_ENOTTY: + fmt_print_str(w, "L_ENOTTY"); + break; + case LIB9P_ERRNO_L_ETXTBSY: + fmt_print_str(w, "L_ETXTBSY"); + break; + case LIB9P_ERRNO_L_EFBIG: + fmt_print_str(w, "L_EFBIG"); + break; + case LIB9P_ERRNO_L_ENOSPC: + fmt_print_str(w, "L_ENOSPC"); + break; + case LIB9P_ERRNO_L_ESPIPE: + fmt_print_str(w, "L_ESPIPE"); + break; + case LIB9P_ERRNO_L_EROFS: + fmt_print_str(w, "L_EROFS"); + break; + case LIB9P_ERRNO_L_EMLINK: + fmt_print_str(w, "L_EMLINK"); + break; + case LIB9P_ERRNO_L_EPIPE: + fmt_print_str(w, "L_EPIPE"); + break; + case LIB9P_ERRNO_L_EDOM: + fmt_print_str(w, "L_EDOM"); + break; + case LIB9P_ERRNO_L_ERANGE: + fmt_print_str(w, "L_ERANGE"); + break; + case LIB9P_ERRNO_L_EDEADLK: + fmt_print_str(w, "L_EDEADLK"); + break; + case LIB9P_ERRNO_L_ENAMETOOLONG: + fmt_print_str(w, "L_ENAMETOOLONG"); + break; + case LIB9P_ERRNO_L_ENOLCK: + fmt_print_str(w, "L_ENOLCK"); + break; + case LIB9P_ERRNO_L_ENOSYS: + fmt_print_str(w, "L_ENOSYS"); + break; + case LIB9P_ERRNO_L_ENOTEMPTY: + fmt_print_str(w, "L_ENOTEMPTY"); + break; + case LIB9P_ERRNO_L_ELOOP: + fmt_print_str(w, "L_ELOOP"); + break; + case LIB9P_ERRNO_L_ENOMSG: + fmt_print_str(w, "L_ENOMSG"); + break; + case LIB9P_ERRNO_L_EIDRM: + fmt_print_str(w, "L_EIDRM"); + break; + case LIB9P_ERRNO_L_ECHRNG: + fmt_print_str(w, "L_ECHRNG"); + break; + case LIB9P_ERRNO_L_EL2NSYNC: + fmt_print_str(w, "L_EL2NSYNC"); + break; + case LIB9P_ERRNO_L_EL3HLT: + fmt_print_str(w, "L_EL3HLT"); + break; + case LIB9P_ERRNO_L_EL3RST: + fmt_print_str(w, "L_EL3RST"); + break; + case LIB9P_ERRNO_L_ELNRNG: + fmt_print_str(w, "L_ELNRNG"); + break; + case LIB9P_ERRNO_L_EUNATCH: + fmt_print_str(w, "L_EUNATCH"); + break; + case LIB9P_ERRNO_L_ENOCSI: + fmt_print_str(w, "L_ENOCSI"); + break; + case LIB9P_ERRNO_L_EL2HLT: + fmt_print_str(w, "L_EL2HLT"); + break; + case LIB9P_ERRNO_L_EBADE: + fmt_print_str(w, "L_EBADE"); + break; + case LIB9P_ERRNO_L_EBADR: + fmt_print_str(w, "L_EBADR"); + break; + case LIB9P_ERRNO_L_EXFULL: + fmt_print_str(w, "L_EXFULL"); + break; + case LIB9P_ERRNO_L_ENOANO: + fmt_print_str(w, "L_ENOANO"); + break; + case LIB9P_ERRNO_L_EBADRQC: + fmt_print_str(w, "L_EBADRQC"); + break; + case LIB9P_ERRNO_L_EBADSLT: + fmt_print_str(w, "L_EBADSLT"); + break; + case LIB9P_ERRNO_L_EBFONT: + fmt_print_str(w, "L_EBFONT"); + break; + case LIB9P_ERRNO_L_ENOSTR: + fmt_print_str(w, "L_ENOSTR"); + break; + case LIB9P_ERRNO_L_ENODATA: + fmt_print_str(w, "L_ENODATA"); + break; + case LIB9P_ERRNO_L_ETIME: + fmt_print_str(w, "L_ETIME"); + break; + case LIB9P_ERRNO_L_ENOSR: + fmt_print_str(w, "L_ENOSR"); + break; + case LIB9P_ERRNO_L_ENONET: + fmt_print_str(w, "L_ENONET"); + break; + case LIB9P_ERRNO_L_ENOPKG: + fmt_print_str(w, "L_ENOPKG"); + break; + case LIB9P_ERRNO_L_EREMOTE: + fmt_print_str(w, "L_EREMOTE"); + break; + case LIB9P_ERRNO_L_ENOLINK: + fmt_print_str(w, "L_ENOLINK"); + break; + case LIB9P_ERRNO_L_EADV: + fmt_print_str(w, "L_EADV"); + break; + case LIB9P_ERRNO_L_ESRMNT: + fmt_print_str(w, "L_ESRMNT"); + break; + case LIB9P_ERRNO_L_ECOMM: + fmt_print_str(w, "L_ECOMM"); + break; + case LIB9P_ERRNO_L_EPROTO: + fmt_print_str(w, "L_EPROTO"); + break; + case LIB9P_ERRNO_L_EMULTIHOP: + fmt_print_str(w, "L_EMULTIHOP"); + break; + case LIB9P_ERRNO_L_EDOTDOT: + fmt_print_str(w, "L_EDOTDOT"); + break; + case LIB9P_ERRNO_L_EBADMSG: + fmt_print_str(w, "L_EBADMSG"); + break; + case LIB9P_ERRNO_L_EOVERFLOW: + fmt_print_str(w, "L_EOVERFLOW"); + break; + case LIB9P_ERRNO_L_ENOTUNIQ: + fmt_print_str(w, "L_ENOTUNIQ"); + break; + case LIB9P_ERRNO_L_EBADFD: + fmt_print_str(w, "L_EBADFD"); + break; + case LIB9P_ERRNO_L_EREMCHG: + fmt_print_str(w, "L_EREMCHG"); + break; + case LIB9P_ERRNO_L_ELIBACC: + fmt_print_str(w, "L_ELIBACC"); + break; + case LIB9P_ERRNO_L_ELIBBAD: + fmt_print_str(w, "L_ELIBBAD"); + break; + case LIB9P_ERRNO_L_ELIBSCN: + fmt_print_str(w, "L_ELIBSCN"); + break; + case LIB9P_ERRNO_L_ELIBMAX: + fmt_print_str(w, "L_ELIBMAX"); + break; + case LIB9P_ERRNO_L_ELIBEXEC: + fmt_print_str(w, "L_ELIBEXEC"); + break; + case LIB9P_ERRNO_L_EILSEQ: + fmt_print_str(w, "L_EILSEQ"); + break; + case LIB9P_ERRNO_L_ERESTART: + fmt_print_str(w, "L_ERESTART"); + break; + case LIB9P_ERRNO_L_ESTRPIPE: + fmt_print_str(w, "L_ESTRPIPE"); + break; + case LIB9P_ERRNO_L_EUSERS: + fmt_print_str(w, "L_EUSERS"); + break; + case LIB9P_ERRNO_L_ENOTSOCK: + fmt_print_str(w, "L_ENOTSOCK"); + break; + case LIB9P_ERRNO_L_EDESTADDRREQ: + fmt_print_str(w, "L_EDESTADDRREQ"); + break; + case LIB9P_ERRNO_L_EMSGSIZE: + fmt_print_str(w, "L_EMSGSIZE"); + break; + case LIB9P_ERRNO_L_EPROTOTYPE: + fmt_print_str(w, "L_EPROTOTYPE"); + break; + case LIB9P_ERRNO_L_ENOPROTOOPT: + fmt_print_str(w, "L_ENOPROTOOPT"); + break; + case LIB9P_ERRNO_L_EPROTONOSUPPORT: + fmt_print_str(w, "L_EPROTONOSUPPORT"); + break; + case LIB9P_ERRNO_L_ESOCKTNOSUPPORT: + fmt_print_str(w, "L_ESOCKTNOSUPPORT"); + break; + case LIB9P_ERRNO_L_EOPNOTSUPP: + fmt_print_str(w, "L_EOPNOTSUPP"); + break; + case LIB9P_ERRNO_L_EPFNOSUPPORT: + fmt_print_str(w, "L_EPFNOSUPPORT"); + break; + case LIB9P_ERRNO_L_EAFNOSUPPORT: + fmt_print_str(w, "L_EAFNOSUPPORT"); + break; + case LIB9P_ERRNO_L_EADDRINUSE: + fmt_print_str(w, "L_EADDRINUSE"); + break; + case LIB9P_ERRNO_L_EADDRNOTAVAIL: + fmt_print_str(w, "L_EADDRNOTAVAIL"); + break; + case LIB9P_ERRNO_L_ENETDOWN: + fmt_print_str(w, "L_ENETDOWN"); + break; + case LIB9P_ERRNO_L_ENETUNREACH: + fmt_print_str(w, "L_ENETUNREACH"); + break; + case LIB9P_ERRNO_L_ENETRESET: + fmt_print_str(w, "L_ENETRESET"); + break; + case LIB9P_ERRNO_L_ECONNABORTED: + fmt_print_str(w, "L_ECONNABORTED"); + break; + case LIB9P_ERRNO_L_ECONNRESET: + fmt_print_str(w, "L_ECONNRESET"); + break; + case LIB9P_ERRNO_L_ENOBUFS: + fmt_print_str(w, "L_ENOBUFS"); + break; + case LIB9P_ERRNO_L_EISCONN: + fmt_print_str(w, "L_EISCONN"); + break; + case LIB9P_ERRNO_L_ENOTCONN: + fmt_print_str(w, "L_ENOTCONN"); + break; + case LIB9P_ERRNO_L_ESHUTDOWN: + fmt_print_str(w, "L_ESHUTDOWN"); + break; + case LIB9P_ERRNO_L_ETOOMANYREFS: + fmt_print_str(w, "L_ETOOMANYREFS"); + break; + case LIB9P_ERRNO_L_ETIMEDOUT: + fmt_print_str(w, "L_ETIMEDOUT"); + break; + case LIB9P_ERRNO_L_ECONNREFUSED: + fmt_print_str(w, "L_ECONNREFUSED"); + break; + case LIB9P_ERRNO_L_EHOSTDOWN: + fmt_print_str(w, "L_EHOSTDOWN"); + break; + case LIB9P_ERRNO_L_EHOSTUNREACH: + fmt_print_str(w, "L_EHOSTUNREACH"); + break; + case LIB9P_ERRNO_L_EALREADY: + fmt_print_str(w, "L_EALREADY"); + break; + case LIB9P_ERRNO_L_EINPROGRESS: + fmt_print_str(w, "L_EINPROGRESS"); + break; + case LIB9P_ERRNO_L_ESTALE: + fmt_print_str(w, "L_ESTALE"); + break; + case LIB9P_ERRNO_L_EUCLEAN: + fmt_print_str(w, "L_EUCLEAN"); + break; + case LIB9P_ERRNO_L_ENOTNAM: + fmt_print_str(w, "L_ENOTNAM"); + break; + case LIB9P_ERRNO_L_ENAVAIL: + fmt_print_str(w, "L_ENAVAIL"); + break; + case LIB9P_ERRNO_L_EISNAM: + fmt_print_str(w, "L_EISNAM"); + break; + case LIB9P_ERRNO_L_EREMOTEIO: + fmt_print_str(w, "L_EREMOTEIO"); + break; + case LIB9P_ERRNO_L_EDQUOT: + fmt_print_str(w, "L_EDQUOT"); + break; + case LIB9P_ERRNO_L_ENOMEDIUM: + fmt_print_str(w, "L_ENOMEDIUM"); + break; + case LIB9P_ERRNO_L_EMEDIUMTYPE: + fmt_print_str(w, "L_EMEDIUMTYPE"); + break; + case LIB9P_ERRNO_L_ECANCELED: + fmt_print_str(w, "L_ECANCELED"); + break; + case LIB9P_ERRNO_L_ENOKEY: + fmt_print_str(w, "L_ENOKEY"); + break; + case LIB9P_ERRNO_L_EKEYEXPIRED: + fmt_print_str(w, "L_EKEYEXPIRED"); + break; + case LIB9P_ERRNO_L_EKEYREVOKED: + fmt_print_str(w, "L_EKEYREVOKED"); + break; + case LIB9P_ERRNO_L_EKEYREJECTED: + fmt_print_str(w, "L_EKEYREJECTED"); + break; + case LIB9P_ERRNO_L_EOWNERDEAD: + fmt_print_str(w, "L_EOWNERDEAD"); + break; + case LIB9P_ERRNO_L_ENOTRECOVERABLE: + fmt_print_str(w, "L_ENOTRECOVERABLE"); + break; + case LIB9P_ERRNO_L_ERFKILL: + fmt_print_str(w, "L_ERFKILL"); + break; + case LIB9P_ERRNO_L_EHWPOISON: + fmt_print_str(w, "L_EHWPOISON"); + break; + default: + fmt_print_base10(w, *self); + } +} + +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_L +[[maybe_unused]] static void fmt_print_super_magic(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_super_magic_t *self) { + switch (*self) { + case LIB9P_SUPER_MAGIC_V9FS_MAGIC: + fmt_print_str(w, "V9FS_MAGIC"); + break; + default: + fmt_print_base10(w, *self); + } +} + +[[maybe_unused]] static void fmt_print_lo(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_lo_t *self) { + bool empty = true; + fmt_print_byte(w, '('); + if (*self & (UINT32_C(1)<<31)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<31"); + empty = false; + } + if (*self & (UINT32_C(1)<<30)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<30"); + empty = false; + } + if (*self & (UINT32_C(1)<<29)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<29"); + empty = false; + } + if (*self & (UINT32_C(1)<<28)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<28"); + empty = false; + } + if (*self & (UINT32_C(1)<<27)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<27"); + empty = false; + } + if (*self & (UINT32_C(1)<<26)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<26"); + empty = false; + } + if (*self & (UINT32_C(1)<<25)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<25"); + empty = false; + } + if (*self & (UINT32_C(1)<<24)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<24"); + empty = false; + } + if (*self & (UINT32_C(1)<<23)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<23"); + empty = false; + } + if (*self & (UINT32_C(1)<<22)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<22"); + empty = false; + } + if (*self & (UINT32_C(1)<<21)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<21"); + empty = false; + } + if (*self & (UINT32_C(1)<<20)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "SYNC"); + empty = false; + } + if (*self & (UINT32_C(1)<<19)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "CLOEXEC"); + empty = false; + } + if (*self & (UINT32_C(1)<<18)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "NOATIME"); + empty = false; + } + if (*self & (UINT32_C(1)<<17)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "NOFOLLOW"); + empty = false; + } + if (*self & (UINT32_C(1)<<16)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "DIRECTORY"); + empty = false; + } + if (*self & (UINT32_C(1)<<15)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "LARGEFILE"); + empty = false; + } + if (*self & (UINT32_C(1)<<14)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "DIRECT"); + empty = false; + } + if (*self & (UINT32_C(1)<<13)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "BSD_FASYNC"); + empty = false; + } + if (*self & (UINT32_C(1)<<12)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "DSYNC"); + empty = false; + } + if (*self & (UINT32_C(1)<<11)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "NONBLOCK"); + empty = false; + } + if (*self & (UINT32_C(1)<<10)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "APPEND"); + empty = false; + } + if (*self & (UINT32_C(1)<<9)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "TRUNC"); + empty = false; + } + if (*self & (UINT32_C(1)<<8)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "NOCTTY"); + empty = false; + } + if (*self & (UINT32_C(1)<<7)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "EXCL"); + empty = false; + } + if (*self & (UINT32_C(1)<<6)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "CREATE"); + empty = false; + } + if (*self & (UINT32_C(1)<<5)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<5"); + empty = false; + } + if (*self & (UINT32_C(1)<<4)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<4"); + empty = false; + } + if (*self & (UINT32_C(1)<<3)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<3"); + empty = false; + } + if (*self & (UINT32_C(1)<<2)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<2"); + empty = false; + } + switch (*self & LIB9P_LO_MODE_MASK) { + case LIB9P_LO_MODE_RDONLY: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE_RDONLY"); + empty = false; + break; + case LIB9P_LO_MODE_WRONLY: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE_WRONLY"); + empty = false; + break; + case LIB9P_LO_MODE_RDWR: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE_RDWR"); + empty = false; + break; + case LIB9P_LO_MODE_NOACCESS: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE_NOACCESS"); + empty = false; + break; + default: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_base10(w, *self & LIB9P_LO_MODE_MASK); + empty = false; + } + if (empty) + fmt_print_byte(w, '0'); + fmt_print_byte(w, ')'); +} + +[[maybe_unused]] static void fmt_print_dt(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_dt_t *self) { + switch (*self) { + case LIB9P_DT_UNKNOWN: + fmt_print_str(w, "UNKNOWN"); + break; + case LIB9P_DT_PIPE: + fmt_print_str(w, "PIPE"); + break; + case LIB9P_DT_CHAR_DEV: + fmt_print_str(w, "CHAR_DEV"); + break; + case LIB9P_DT_DIRECTORY: + fmt_print_str(w, "DIRECTORY"); + break; + case LIB9P_DT_BLOCK_DEV: + fmt_print_str(w, "BLOCK_DEV"); + break; + case LIB9P_DT_REGULAR: + fmt_print_str(w, "REGULAR"); + break; + case LIB9P_DT_SYMLINK: + fmt_print_str(w, "SYMLINK"); + break; + case LIB9P_DT_SOCKET: + fmt_print_str(w, "SOCKET"); + break; + case _LIB9P_DT_WHITEOUT: + fmt_print_str(w, "_WHITEOUT"); + break; + default: + fmt_print_base10(w, *self); + } +} + +[[maybe_unused]] static void fmt_print_mode(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_mode_t *self) { + bool empty = true; + fmt_print_byte(w, '('); + if (*self & (UINT32_C(1)<<31)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<31"); + empty = false; + } + if (*self & (UINT32_C(1)<<30)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<30"); + empty = false; + } + if (*self & (UINT32_C(1)<<29)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<29"); + empty = false; + } + if (*self & (UINT32_C(1)<<28)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<28"); + empty = false; + } + if (*self & (UINT32_C(1)<<27)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<27"); + empty = false; + } + if (*self & (UINT32_C(1)<<26)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<26"); + empty = false; + } + if (*self & (UINT32_C(1)<<25)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<25"); + empty = false; + } + if (*self & (UINT32_C(1)<<24)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<24"); + empty = false; + } + if (*self & (UINT32_C(1)<<23)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<23"); + empty = false; + } + if (*self & (UINT32_C(1)<<22)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<22"); + empty = false; + } + if (*self & (UINT32_C(1)<<21)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<21"); + empty = false; + } + if (*self & (UINT32_C(1)<<20)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<20"); + empty = false; + } + if (*self & (UINT32_C(1)<<19)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<19"); + empty = false; + } + if (*self & (UINT32_C(1)<<18)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<18"); + empty = false; + } + if (*self & (UINT32_C(1)<<17)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<17"); + empty = false; + } + if (*self & (UINT32_C(1)<<16)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<16"); + empty = false; + } + switch (*self & LIB9P_MODE_FMT_MASK) { + case LIB9P_MODE_FMT_PIPE: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "FMT_PIPE"); + empty = false; + break; + case LIB9P_MODE_FMT_CHAR_DEV: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "FMT_CHAR_DEV"); + empty = false; + break; + case LIB9P_MODE_FMT_DIRECTORY: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "FMT_DIRECTORY"); + empty = false; + break; + case LIB9P_MODE_FMT_BLOCK_DEV: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "FMT_BLOCK_DEV"); + empty = false; + break; + case LIB9P_MODE_FMT_REGULAR: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "FMT_REGULAR"); + empty = false; + break; + case LIB9P_MODE_FMT_SYMLINK: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "FMT_SYMLINK"); + empty = false; + break; + case LIB9P_MODE_FMT_SOCKET: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "FMT_SOCKET"); + empty = false; + break; + default: + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_base10(w, *self & LIB9P_MODE_FMT_MASK); + empty = false; + } + if (*self & (UINT32_C(1)<<11)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_SETGROUP"); + empty = false; + } + if (*self & (UINT32_C(1)<<10)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_SETUSER"); + empty = false; + } + if (*self & (UINT32_C(1)<<9)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_STICKY"); + empty = false; + } + if (*self & (UINT32_C(1)<<8)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_OWNER_R"); + empty = false; + } + if (*self & (UINT32_C(1)<<7)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_OWNER_W"); + empty = false; + } + if (*self & (UINT32_C(1)<<6)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_OWNER_X"); + empty = false; + } + if (*self & (UINT32_C(1)<<5)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_GROUP_R"); + empty = false; + } + if (*self & (UINT32_C(1)<<4)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_GROUP_W"); + empty = false; + } + if (*self & (UINT32_C(1)<<3)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_GROUP_X"); + empty = false; + } + if (*self & (UINT32_C(1)<<2)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_OTHER_R"); + empty = false; + } + if (*self & (UINT32_C(1)<<1)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_OTHER_W"); + empty = false; + } + if (*self & (UINT32_C(1)<<0)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "PERM_OTHER_X"); + empty = false; + } + if (empty) + fmt_print_byte(w, '0'); + fmt_print_byte(w, ')'); +} + +[[maybe_unused]] static void fmt_print_b4(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_b4_t *self) { + switch (*self) { + case LIB9P_B4_FALSE: + fmt_print_str(w, "FALSE"); + break; + case LIB9P_B4_TRUE: + fmt_print_str(w, "TRUE"); + break; + default: + fmt_print_base10(w, *self); + } +} + +[[maybe_unused]] static void fmt_print_getattr(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_getattr_t *self) { + bool empty = true; + fmt_print_byte(w, '('); + if (*self & (UINT64_C(1)<<63)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<63"); + empty = false; + } + if (*self & (UINT64_C(1)<<62)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<62"); + empty = false; + } + if (*self & (UINT64_C(1)<<61)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<61"); + empty = false; + } + if (*self & (UINT64_C(1)<<60)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<60"); + empty = false; + } + if (*self & (UINT64_C(1)<<59)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<59"); + empty = false; + } + if (*self & (UINT64_C(1)<<58)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<58"); + empty = false; + } + if (*self & (UINT64_C(1)<<57)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<57"); + empty = false; + } + if (*self & (UINT64_C(1)<<56)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<56"); + empty = false; + } + if (*self & (UINT64_C(1)<<55)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<55"); + empty = false; + } + if (*self & (UINT64_C(1)<<54)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<54"); + empty = false; + } + if (*self & (UINT64_C(1)<<53)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<53"); + empty = false; + } + if (*self & (UINT64_C(1)<<52)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<52"); + empty = false; + } + if (*self & (UINT64_C(1)<<51)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<51"); + empty = false; + } + if (*self & (UINT64_C(1)<<50)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<50"); + empty = false; + } + if (*self & (UINT64_C(1)<<49)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<49"); + empty = false; + } + if (*self & (UINT64_C(1)<<48)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<48"); + empty = false; + } + if (*self & (UINT64_C(1)<<47)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<47"); + empty = false; + } + if (*self & (UINT64_C(1)<<46)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<46"); + empty = false; + } + if (*self & (UINT64_C(1)<<45)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<45"); + empty = false; + } + if (*self & (UINT64_C(1)<<44)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<44"); + empty = false; + } + if (*self & (UINT64_C(1)<<43)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<43"); + empty = false; + } + if (*self & (UINT64_C(1)<<42)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<42"); + empty = false; + } + if (*self & (UINT64_C(1)<<41)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<41"); + empty = false; + } + if (*self & (UINT64_C(1)<<40)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<40"); + empty = false; + } + if (*self & (UINT64_C(1)<<39)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<39"); + empty = false; + } + if (*self & (UINT64_C(1)<<38)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<38"); + empty = false; + } + if (*self & (UINT64_C(1)<<37)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<37"); + empty = false; + } + if (*self & (UINT64_C(1)<<36)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<36"); + empty = false; + } + if (*self & (UINT64_C(1)<<35)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<35"); + empty = false; + } + if (*self & (UINT64_C(1)<<34)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<34"); + empty = false; + } + if (*self & (UINT64_C(1)<<33)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<33"); + empty = false; + } + if (*self & (UINT64_C(1)<<32)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<32"); + empty = false; + } + if (*self & (UINT64_C(1)<<31)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<31"); + empty = false; + } + if (*self & (UINT64_C(1)<<30)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<30"); + empty = false; + } + if (*self & (UINT64_C(1)<<29)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<29"); + empty = false; + } + if (*self & (UINT64_C(1)<<28)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<28"); + empty = false; + } + if (*self & (UINT64_C(1)<<27)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<27"); + empty = false; + } + if (*self & (UINT64_C(1)<<26)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<26"); + empty = false; + } + if (*self & (UINT64_C(1)<<25)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<25"); + empty = false; + } + if (*self & (UINT64_C(1)<<24)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<24"); + empty = false; + } + if (*self & (UINT64_C(1)<<23)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<23"); + empty = false; + } + if (*self & (UINT64_C(1)<<22)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<22"); + empty = false; + } + if (*self & (UINT64_C(1)<<21)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<21"); + empty = false; + } + if (*self & (UINT64_C(1)<<20)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<20"); + empty = false; + } + if (*self & (UINT64_C(1)<<19)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<19"); + empty = false; + } + if (*self & (UINT64_C(1)<<18)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<18"); + empty = false; + } + if (*self & (UINT64_C(1)<<17)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<17"); + empty = false; + } + if (*self & (UINT64_C(1)<<16)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<16"); + empty = false; + } + if (*self & (UINT64_C(1)<<15)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<15"); + empty = false; + } + if (*self & (UINT64_C(1)<<14)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<14"); + empty = false; + } + if (*self & (UINT64_C(1)<<13)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "DATA_VERSION"); + empty = false; + } + if (*self & (UINT64_C(1)<<12)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "GEN"); + empty = false; + } + if (*self & (UINT64_C(1)<<11)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "BTIME"); + empty = false; + } + if (*self & (UINT64_C(1)<<10)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "BLOCKS"); + empty = false; + } + if (*self & (UINT64_C(1)<<9)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "SIZE"); + empty = false; + } + if (*self & (UINT64_C(1)<<8)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "INO"); + empty = false; + } + if (*self & (UINT64_C(1)<<7)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "CTIME"); + empty = false; + } + if (*self & (UINT64_C(1)<<6)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MTIME"); + empty = false; + } + if (*self & (UINT64_C(1)<<5)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "ATIME"); + empty = false; + } + if (*self & (UINT64_C(1)<<4)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "RDEV"); + empty = false; + } + if (*self & (UINT64_C(1)<<3)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "GID"); + empty = false; + } + if (*self & (UINT64_C(1)<<2)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "UID"); + empty = false; + } + if (*self & (UINT64_C(1)<<1)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "NLINK"); + empty = false; + } + if (*self & (UINT64_C(1)<<0)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE"); + empty = false; + } + if (empty) + fmt_print_byte(w, '0'); + fmt_print_byte(w, ')'); +} + +[[maybe_unused]] static void fmt_print_setattr(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_setattr_t *self) { + bool empty = true; + fmt_print_byte(w, '('); + if (*self & (UINT32_C(1)<<31)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<31"); + empty = false; + } + if (*self & (UINT32_C(1)<<30)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<30"); + empty = false; + } + if (*self & (UINT32_C(1)<<29)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<29"); + empty = false; + } + if (*self & (UINT32_C(1)<<28)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<28"); + empty = false; + } + if (*self & (UINT32_C(1)<<27)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<27"); + empty = false; + } + if (*self & (UINT32_C(1)<<26)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<26"); + empty = false; + } + if (*self & (UINT32_C(1)<<25)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<25"); + empty = false; + } + if (*self & (UINT32_C(1)<<24)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<24"); + empty = false; + } + if (*self & (UINT32_C(1)<<23)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<23"); + empty = false; + } + if (*self & (UINT32_C(1)<<22)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<22"); + empty = false; + } + if (*self & (UINT32_C(1)<<21)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<21"); + empty = false; + } + if (*self & (UINT32_C(1)<<20)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<20"); + empty = false; + } + if (*self & (UINT32_C(1)<<19)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<19"); + empty = false; + } + if (*self & (UINT32_C(1)<<18)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<18"); + empty = false; + } + if (*self & (UINT32_C(1)<<17)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<17"); + empty = false; + } + if (*self & (UINT32_C(1)<<16)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<16"); + empty = false; + } + if (*self & (UINT32_C(1)<<15)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<15"); + empty = false; + } + if (*self & (UINT32_C(1)<<14)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<14"); + empty = false; + } + if (*self & (UINT32_C(1)<<13)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<13"); + empty = false; + } + if (*self & (UINT32_C(1)<<12)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<12"); + empty = false; + } + if (*self & (UINT32_C(1)<<11)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<11"); + empty = false; + } + if (*self & (UINT32_C(1)<<10)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<10"); + empty = false; + } + if (*self & (UINT32_C(1)<<9)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<9"); + empty = false; + } + if (*self & (UINT32_C(1)<<8)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MTIME_SET"); + empty = false; + } + if (*self & (UINT32_C(1)<<7)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "ATIME_SET"); + empty = false; + } + if (*self & (UINT32_C(1)<<6)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "CTIME"); + empty = false; + } + if (*self & (UINT32_C(1)<<5)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MTIME"); + empty = false; + } + if (*self & (UINT32_C(1)<<4)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "ATIME"); + empty = false; + } + if (*self & (UINT32_C(1)<<3)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "SIZE"); + empty = false; + } + if (*self & (UINT32_C(1)<<2)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "GID"); + empty = false; + } + if (*self & (UINT32_C(1)<<1)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "UID"); + empty = false; + } + if (*self & (UINT32_C(1)<<0)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "MODE"); + empty = false; + } + if (empty) + fmt_print_byte(w, '0'); + fmt_print_byte(w, ')'); +} + +[[maybe_unused]] static void fmt_print_lock_type(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_lock_type_t *self) { + switch (*self) { + case LIB9P_LOCK_TYPE_RDLCK: + fmt_print_str(w, "RDLCK"); + break; + case LIB9P_LOCK_TYPE_WRLCK: + fmt_print_str(w, "WRLCK"); + break; + case LIB9P_LOCK_TYPE_UNLCK: + fmt_print_str(w, "UNLCK"); + break; + default: + fmt_print_base10(w, *self); + } +} + +[[maybe_unused]] static void fmt_print_lock_flags(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_lock_flags_t *self) { + bool empty = true; + fmt_print_byte(w, '('); + if (*self & (UINT32_C(1)<<31)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<31"); + empty = false; + } + if (*self & (UINT32_C(1)<<30)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<30"); + empty = false; + } + if (*self & (UINT32_C(1)<<29)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<29"); + empty = false; + } + if (*self & (UINT32_C(1)<<28)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<28"); + empty = false; + } + if (*self & (UINT32_C(1)<<27)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<27"); + empty = false; + } + if (*self & (UINT32_C(1)<<26)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<26"); + empty = false; + } + if (*self & (UINT32_C(1)<<25)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<25"); + empty = false; + } + if (*self & (UINT32_C(1)<<24)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<24"); + empty = false; + } + if (*self & (UINT32_C(1)<<23)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<23"); + empty = false; + } + if (*self & (UINT32_C(1)<<22)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<22"); + empty = false; + } + if (*self & (UINT32_C(1)<<21)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<21"); + empty = false; + } + if (*self & (UINT32_C(1)<<20)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<20"); + empty = false; + } + if (*self & (UINT32_C(1)<<19)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<19"); + empty = false; + } + if (*self & (UINT32_C(1)<<18)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<18"); + empty = false; + } + if (*self & (UINT32_C(1)<<17)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<17"); + empty = false; + } + if (*self & (UINT32_C(1)<<16)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<16"); + empty = false; + } + if (*self & (UINT32_C(1)<<15)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<15"); + empty = false; + } + if (*self & (UINT32_C(1)<<14)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<14"); + empty = false; + } + if (*self & (UINT32_C(1)<<13)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<13"); + empty = false; + } + if (*self & (UINT32_C(1)<<12)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<12"); + empty = false; + } + if (*self & (UINT32_C(1)<<11)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<11"); + empty = false; + } + if (*self & (UINT32_C(1)<<10)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<10"); + empty = false; + } + if (*self & (UINT32_C(1)<<9)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<9"); + empty = false; + } + if (*self & (UINT32_C(1)<<8)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<8"); + empty = false; + } + if (*self & (UINT32_C(1)<<7)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<7"); + empty = false; + } + if (*self & (UINT32_C(1)<<6)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<6"); + empty = false; + } + if (*self & (UINT32_C(1)<<5)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<5"); + empty = false; + } + if (*self & (UINT32_C(1)<<4)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<4"); + empty = false; + } + if (*self & (UINT32_C(1)<<3)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<3"); + empty = false; + } + if (*self & (UINT32_C(1)<<2)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "1<<2"); + empty = false; + } + if (*self & (UINT32_C(1)<<1)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "RECLAIM"); + empty = false; + } + if (*self & (UINT32_C(1)<<0)) { + if (!empty) + fmt_print_byte(w, '|'); + fmt_print_str(w, "BLOCK"); + empty = false; + } + if (empty) + fmt_print_byte(w, '0'); + fmt_print_byte(w, ')'); +} + +[[maybe_unused]] static void fmt_print_lock_status(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, lib9p_lock_status_t *self) { + switch (*self) { + case LIB9P_LOCK_STATUS_SUCCESS: + fmt_print_str(w, "SUCCESS"); + break; + case LIB9P_LOCK_STATUS_BLOCKED: + fmt_print_str(w, "BLOCKED"); + break; + case LIB9P_LOCK_STATUS_ERROR: + fmt_print_str(w, "ERROR"); + break; + case LIB9P_LOCK_STATUS_GRACE: + fmt_print_str(w, "GRACE"); + break; + default: + fmt_print_base10(w, *self); + } +} + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +[[maybe_unused]] static void fmt_print_s(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_s *self) { + fmt_print_qmem(w, self->utf8, self->len); +} + +[[maybe_unused]] static void fmt_print_qid(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_qid *self) { + fmt_print_byte(w, '{'); + fmt_print_str(w, " type="); + fmt_print_qt(w, ctx, &self->type); + fmt_print_str(w, " vers="); + fmt_print_base10(w, self->vers); + fmt_print_str(w, " path="); + fmt_print_base10(w, self->path); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_Tflush(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tflush *self) { + fmt_print_str(w, "Tflush {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " oldtag="); + fmt_print_base10(w, self->oldtag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rflush(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rflush *self) { + fmt_print_str(w, "Rflush {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_Topen(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Topen *self) { + fmt_print_str(w, "Topen {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " mode="); + fmt_print_o(w, ctx, &self->mode); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_Tread(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tread *self) { + fmt_print_str(w, "Tread {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " offset="); + fmt_print_base10(w, self->offset); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rread(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rread *self) { + fmt_print_str(w, "Rread {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + if (utf8_is_valid_without_nul((uint8_t *)self->data, (size_t)self->count)) { + fmt_print_str(w, " data="); + fmt_print_qmem(w, self->data, self->count < 50 ? self->count : 50); + if (self->count > 50) + fmt_print_str(w, "..."); + } else { + fmt_print_str(w, " data=<bytedata>"); + } + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Twrite(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Twrite *self) { + fmt_print_str(w, "Twrite {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " offset="); + fmt_print_base10(w, self->offset); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + if (utf8_is_valid_without_nul((uint8_t *)self->data, (size_t)self->count)) { + fmt_print_str(w, " data="); + fmt_print_qmem(w, self->data, self->count < 50 ? self->count : 50); + if (self->count > 50) + fmt_print_str(w, "..."); + } else { + fmt_print_str(w, " data=<bytedata>"); + } + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rwrite(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rwrite *self) { + fmt_print_str(w, "Rwrite {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tclunk(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tclunk *self) { + fmt_print_str(w, "Tclunk {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rclunk(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rclunk *self) { + fmt_print_str(w, "Rclunk {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tremove(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tremove *self) { + fmt_print_str(w, "Tremove {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rremove(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rremove *self) { + fmt_print_str(w, "Rremove {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_Tstat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tstat *self) { + fmt_print_str(w, "Tstat {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rwstat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rwstat *self) { + fmt_print_str(w, "Rwstat {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_p9p +[[maybe_unused]] static void fmt_print_Topenfd(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Topenfd *self) { + fmt_print_str(w, "Topenfd {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " mode="); + fmt_print_o(w, ctx, &self->mode); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_L +[[maybe_unused]] static void fmt_print_Rlerror(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rlerror *self) { + fmt_print_str(w, "Rlerror {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " errnum="); + fmt_print_errno(w, ctx, &self->errnum); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tstatfs(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tstatfs *self) { + fmt_print_str(w, "Tstatfs {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rstatfs(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rstatfs *self) { + fmt_print_str(w, "Rstatfs {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " type="); + fmt_print_super_magic(w, ctx, &self->type); + fmt_print_str(w, " bsize="); + fmt_print_base10(w, self->bsize); + fmt_print_str(w, " blocks="); + fmt_print_base10(w, self->blocks); + fmt_print_str(w, " bfree="); + fmt_print_base10(w, self->bfree); + fmt_print_str(w, " bavail="); + fmt_print_base10(w, self->bavail); + fmt_print_str(w, " files="); + fmt_print_base10(w, self->files); + fmt_print_str(w, " ffree="); + fmt_print_base10(w, self->ffree); + fmt_print_str(w, " fsid="); + fmt_print_base10(w, self->fsid); + fmt_print_str(w, " namelen="); + fmt_print_base10(w, self->namelen); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tlopen(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tlopen *self) { + fmt_print_str(w, "Tlopen {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " flags="); + fmt_print_lo(w, ctx, &self->flags); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rrename(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rrename *self) { + fmt_print_str(w, "Rrename {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Treadlink(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Treadlink *self) { + fmt_print_str(w, "Treadlink {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tgetattr(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tgetattr *self) { + fmt_print_str(w, "Tgetattr {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " request_mask="); + fmt_print_getattr(w, ctx, &self->request_mask); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tsetattr(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tsetattr *self) { + fmt_print_str(w, "Tsetattr {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " valid="); + fmt_print_setattr(w, ctx, &self->valid); + fmt_print_str(w, " mode="); + fmt_print_mode(w, ctx, &self->mode); + fmt_print_str(w, " uid="); + fmt_print_nuid(w, ctx, &self->uid); + fmt_print_str(w, " gid="); + fmt_print_nuid(w, ctx, &self->gid); + fmt_print_str(w, " filesize="); + fmt_print_base10(w, self->filesize); + fmt_print_str(w, " atime_sec="); + fmt_print_base10(w, self->atime_sec); + fmt_print_str(w, " atime_nsec="); + fmt_print_base10(w, self->atime_nsec); + fmt_print_str(w, " mtime_sec="); + fmt_print_base10(w, self->mtime_sec); + fmt_print_str(w, " mtime_nsec="); + fmt_print_base10(w, self->mtime_nsec); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rsetattr(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rsetattr *self) { + fmt_print_str(w, "Rsetattr {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rxattrwalk(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrwalk *self) { + fmt_print_str(w, "Rxattrwalk {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " attr_size="); + fmt_print_base10(w, self->attr_size); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rxattrcreate(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrcreate *self) { + fmt_print_str(w, "Rxattrcreate {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Treaddir(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Treaddir *self) { + fmt_print_str(w, "Treaddir {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " offset="); + fmt_print_base10(w, self->offset); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rreaddir(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rreaddir *self) { + fmt_print_str(w, "Rreaddir {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + if (utf8_is_valid_without_nul((uint8_t *)self->data, (size_t)self->count)) { + fmt_print_str(w, " data="); + fmt_print_qmem(w, self->data, self->count < 50 ? self->count : 50); + if (self->count > 50) + fmt_print_str(w, "..."); + } else { + fmt_print_str(w, " data=<bytedata>"); + } + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tfsync(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tfsync *self) { + fmt_print_str(w, "Tfsync {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " datasync="); + fmt_print_b4(w, ctx, &self->datasync); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rfsync(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rfsync *self) { + fmt_print_str(w, "Rfsync {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rlock(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rlock *self) { + fmt_print_str(w, "Rlock {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " status="); + fmt_print_lock_status(w, ctx, &self->status); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rlink(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rlink *self) { + fmt_print_str(w, "Rlink {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rrenameat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rrenameat *self) { + fmt_print_str(w, "Rrenameat {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Runlinkat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Runlinkat *self) { + fmt_print_str(w, "Runlinkat {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e +[[maybe_unused]] static void fmt_print_Tsession(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tsession *self) { + fmt_print_str(w, "Tsession {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " key="); + fmt_print_base10(w, self->key); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rsession(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rsession *self) { + fmt_print_str(w, "Rsession {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rsread(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rsread *self) { + fmt_print_str(w, "Rsread {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + if (utf8_is_valid_without_nul((uint8_t *)self->data, (size_t)self->count)) { + fmt_print_str(w, " data="); + fmt_print_qmem(w, self->data, self->count < 50 ? self->count : 50); + if (self->count > 50) + fmt_print_str(w, "..."); + } else { + fmt_print_str(w, " data=<bytedata>"); + } + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rswrite(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rswrite *self) { + fmt_print_str(w, "Rswrite {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] void fmt_print_stat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_stat *self) { + fmt_print_byte(w, '{'); + fmt_print_str(w, " fstype="); + fmt_print_base10(w, self->fstype); + fmt_print_str(w, " fsdev="); + fmt_print_base10(w, self->fsdev); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " mode="); + fmt_print_dm(w, ctx, &self->mode); + fmt_print_str(w, " atime="); + fmt_print_base10(w, self->atime); + fmt_print_str(w, " mtime="); + fmt_print_base10(w, self->mtime); + fmt_print_str(w, " length="); + fmt_print_base10(w, self->length); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " owner_uname="); + fmt_print_s(w, ctx, &self->owner_uname); + fmt_print_str(w, " owner_gname="); + fmt_print_s(w, ctx, &self->owner_gname); + fmt_print_str(w, " last_modifier_uname="); + fmt_print_s(w, ctx, &self->last_modifier_uname); +#if CONFIG_9P_ENABLE_9P2000_u + fmt_print_str(w, " extension="); + fmt_print_s(w, ctx, &self->extension); + fmt_print_str(w, " owner_unum="); + fmt_print_nuid(w, ctx, &self->owner_unum); + fmt_print_str(w, " owner_gnum="); + fmt_print_nuid(w, ctx, &self->owner_gnum); + fmt_print_str(w, " last_modifier_unum="); + fmt_print_nuid(w, ctx, &self->last_modifier_unum); +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +[[maybe_unused]] static void fmt_print_Tversion(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tversion *self) { + fmt_print_str(w, "Tversion {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " max_msg_size="); + fmt_print_base10(w, self->max_msg_size); + fmt_print_str(w, " version="); + fmt_print_s(w, ctx, &self->version); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rversion(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rversion *self) { + fmt_print_str(w, "Rversion {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " max_msg_size="); + fmt_print_base10(w, self->max_msg_size); + fmt_print_str(w, " version="); + fmt_print_s(w, ctx, &self->version); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_Tauth(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tauth *self) { + fmt_print_str(w, "Tauth {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " afid="); + fmt_print_fid(w, ctx, &self->afid); + fmt_print_str(w, " uname="); + fmt_print_s(w, ctx, &self->uname); + fmt_print_str(w, " aname="); + fmt_print_s(w, ctx, &self->aname); +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + fmt_print_str(w, " unum="); + fmt_print_nuid(w, ctx, &self->unum); +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rauth(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rauth *self) { + fmt_print_str(w, "Rauth {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " aqid="); + fmt_print_qid(w, ctx, &self->aqid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tattach(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tattach *self) { + fmt_print_str(w, "Tattach {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " afid="); + fmt_print_fid(w, ctx, &self->afid); + fmt_print_str(w, " uname="); + fmt_print_s(w, ctx, &self->uname); + fmt_print_str(w, " aname="); + fmt_print_s(w, ctx, &self->aname); +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + fmt_print_str(w, " unum="); + fmt_print_nuid(w, ctx, &self->unum); +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rattach(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rattach *self) { + fmt_print_str(w, "Rattach {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +[[maybe_unused]] static void fmt_print_Rerror(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rerror *self) { + fmt_print_str(w, "Rerror {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " errstr="); + fmt_print_s(w, ctx, &self->errstr); +#if CONFIG_9P_ENABLE_9P2000_u + fmt_print_str(w, " errnum="); + fmt_print_errno(w, ctx, &self->errnum); +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_Twalk(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Twalk *self) { + fmt_print_str(w, "Twalk {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " newfid="); + fmt_print_fid(w, ctx, &self->newfid); + fmt_print_str(w, " nwname="); + fmt_print_base10(w, self->nwname); + fmt_print_str(w, " wname=["); + for (uint16_t i = 0; i < self->nwname; i++) { + if (i) + fmt_print_byte(w, ','); + fmt_print_byte(w, ' '); + fmt_print_s(w, ctx, &self->wname[i]); + } + fmt_print_str(w, " ]"); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rwalk(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rwalk *self) { + fmt_print_str(w, "Rwalk {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " nwqid="); + fmt_print_base10(w, self->nwqid); + fmt_print_str(w, " wqid=["); + for (uint16_t i = 0; i < self->nwqid; i++) { + if (i) + fmt_print_byte(w, ','); + fmt_print_byte(w, ' '); + fmt_print_qid(w, ctx, &self->wqid[i]); + } + fmt_print_str(w, " ]"); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_Ropen(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Ropen *self) { + fmt_print_str(w, "Ropen {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " iounit="); + fmt_print_base10(w, self->iounit); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tcreate(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tcreate *self) { + fmt_print_str(w, "Tcreate {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " perm="); + fmt_print_dm(w, ctx, &self->perm); + fmt_print_str(w, " mode="); + fmt_print_o(w, ctx, &self->mode); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rcreate(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rcreate *self) { + fmt_print_str(w, "Rcreate {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " iounit="); + fmt_print_base10(w, self->iounit); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_p9p +[[maybe_unused]] static void fmt_print_Ropenfd(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Ropenfd *self) { + fmt_print_str(w, "Ropenfd {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " iounit="); + fmt_print_base10(w, self->iounit); + fmt_print_str(w, " unixfd="); + fmt_print_base10(w, self->unixfd); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_L +[[maybe_unused]] static void fmt_print_Rlopen(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rlopen *self) { + fmt_print_str(w, "Rlopen {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " iounit="); + fmt_print_base10(w, self->iounit); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tlcreate(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tlcreate *self) { + fmt_print_str(w, "Tlcreate {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " flags="); + fmt_print_lo(w, ctx, &self->flags); + fmt_print_str(w, " mode="); + fmt_print_mode(w, ctx, &self->mode); + fmt_print_str(w, " gid="); + fmt_print_nuid(w, ctx, &self->gid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rlcreate(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rlcreate *self) { + fmt_print_str(w, "Rlcreate {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " iounit="); + fmt_print_base10(w, self->iounit); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tsymlink(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tsymlink *self) { + fmt_print_str(w, "Tsymlink {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " symtgt="); + fmt_print_s(w, ctx, &self->symtgt); + fmt_print_str(w, " gid="); + fmt_print_nuid(w, ctx, &self->gid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rsymlink(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rsymlink *self) { + fmt_print_str(w, "Rsymlink {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tmknod(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tmknod *self) { + fmt_print_str(w, "Tmknod {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " dfid="); + fmt_print_fid(w, ctx, &self->dfid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " mode="); + fmt_print_mode(w, ctx, &self->mode); + fmt_print_str(w, " major="); + fmt_print_base10(w, self->major); + fmt_print_str(w, " minor="); + fmt_print_base10(w, self->minor); + fmt_print_str(w, " gid="); + fmt_print_nuid(w, ctx, &self->gid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rmknod(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rmknod *self) { + fmt_print_str(w, "Rmknod {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Trename(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Trename *self) { + fmt_print_str(w, "Trename {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " dfid="); + fmt_print_fid(w, ctx, &self->dfid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rreadlink(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rreadlink *self) { + fmt_print_str(w, "Rreadlink {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " target="); + fmt_print_s(w, ctx, &self->target); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rgetattr(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rgetattr *self) { + fmt_print_str(w, "Rgetattr {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " valid="); + fmt_print_getattr(w, ctx, &self->valid); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " mode="); + fmt_print_mode(w, ctx, &self->mode); + fmt_print_str(w, " uid="); + fmt_print_nuid(w, ctx, &self->uid); + fmt_print_str(w, " gid="); + fmt_print_nuid(w, ctx, &self->gid); + fmt_print_str(w, " nlink="); + fmt_print_base10(w, self->nlink); + fmt_print_str(w, " rdev="); + fmt_print_base10(w, self->rdev); + fmt_print_str(w, " filesize="); + fmt_print_base10(w, self->filesize); + fmt_print_str(w, " blksize="); + fmt_print_base10(w, self->blksize); + fmt_print_str(w, " blocks="); + fmt_print_base10(w, self->blocks); + fmt_print_str(w, " atime_sec="); + fmt_print_base10(w, self->atime_sec); + fmt_print_str(w, " atime_nsec="); + fmt_print_base10(w, self->atime_nsec); + fmt_print_str(w, " mtime_sec="); + fmt_print_base10(w, self->mtime_sec); + fmt_print_str(w, " mtime_nsec="); + fmt_print_base10(w, self->mtime_nsec); + fmt_print_str(w, " ctime_sec="); + fmt_print_base10(w, self->ctime_sec); + fmt_print_str(w, " ctime_nsec="); + fmt_print_base10(w, self->ctime_nsec); + fmt_print_str(w, " btime_sec="); + fmt_print_base10(w, self->btime_sec); + fmt_print_str(w, " btime_nsec="); + fmt_print_base10(w, self->btime_nsec); + fmt_print_str(w, " gen="); + fmt_print_base10(w, self->gen); + fmt_print_str(w, " data_version="); + fmt_print_base10(w, self->data_version); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Txattrwalk(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Txattrwalk *self) { + fmt_print_str(w, "Txattrwalk {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " newfid="); + fmt_print_fid(w, ctx, &self->newfid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Txattrcreate(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Txattrcreate *self) { + fmt_print_str(w, "Txattrcreate {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " attr_size="); + fmt_print_base10(w, self->attr_size); + fmt_print_str(w, " flags="); + fmt_print_base10(w, self->flags); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tlock(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tlock *self) { + fmt_print_str(w, "Tlock {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " type="); + fmt_print_lock_type(w, ctx, &self->type); + fmt_print_str(w, " flags="); + fmt_print_lock_flags(w, ctx, &self->flags); + fmt_print_str(w, " start="); + fmt_print_base10(w, self->start); + fmt_print_str(w, " length="); + fmt_print_base10(w, self->length); + fmt_print_str(w, " proc_id="); + fmt_print_base10(w, self->proc_id); + fmt_print_str(w, " client_id="); + fmt_print_s(w, ctx, &self->client_id); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tgetlock(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tgetlock *self) { + fmt_print_str(w, "Tgetlock {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " type="); + fmt_print_lock_type(w, ctx, &self->type); + fmt_print_str(w, " start="); + fmt_print_base10(w, self->start); + fmt_print_str(w, " length="); + fmt_print_base10(w, self->length); + fmt_print_str(w, " proc_id="); + fmt_print_base10(w, self->proc_id); + fmt_print_str(w, " client_id="); + fmt_print_s(w, ctx, &self->client_id); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rgetlock(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rgetlock *self) { + fmt_print_str(w, "Rgetlock {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " type="); + fmt_print_lock_type(w, ctx, &self->type); + fmt_print_str(w, " start="); + fmt_print_base10(w, self->start); + fmt_print_str(w, " length="); + fmt_print_base10(w, self->length); + fmt_print_str(w, " proc_id="); + fmt_print_base10(w, self->proc_id); + fmt_print_str(w, " client_id="); + fmt_print_s(w, ctx, &self->client_id); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tlink(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tlink *self) { + fmt_print_str(w, "Tlink {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " dfid="); + fmt_print_fid(w, ctx, &self->dfid); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tmkdir(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tmkdir *self) { + fmt_print_str(w, "Tmkdir {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " dfid="); + fmt_print_fid(w, ctx, &self->dfid); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " mode="); + fmt_print_mode(w, ctx, &self->mode); + fmt_print_str(w, " gid="); + fmt_print_nuid(w, ctx, &self->gid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Rmkdir(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rmkdir *self) { + fmt_print_str(w, "Rmkdir {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " qid="); + fmt_print_qid(w, ctx, &self->qid); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Trenameat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Trenameat *self) { + fmt_print_str(w, "Trenameat {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " olddirfid="); + fmt_print_fid(w, ctx, &self->olddirfid); + fmt_print_str(w, " oldname="); + fmt_print_s(w, ctx, &self->oldname); + fmt_print_str(w, " newdirfid="); + fmt_print_fid(w, ctx, &self->newdirfid); + fmt_print_str(w, " newname="); + fmt_print_s(w, ctx, &self->newname); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tunlinkat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tunlinkat *self) { + fmt_print_str(w, "Tunlinkat {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " dirfd="); + fmt_print_fid(w, ctx, &self->dirfd); + fmt_print_str(w, " name="); + fmt_print_s(w, ctx, &self->name); + fmt_print_str(w, " flags="); + fmt_print_base10(w, self->flags); + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e +[[maybe_unused]] static void fmt_print_Tsread(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tsread *self) { + fmt_print_str(w, "Tsread {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_base10(w, self->fid); + fmt_print_str(w, " nwname="); + fmt_print_base10(w, self->nwname); + fmt_print_str(w, " wname=["); + for (uint16_t i = 0; i < self->nwname; i++) { + if (i) + fmt_print_byte(w, ','); + fmt_print_byte(w, ' '); + fmt_print_s(w, ctx, &self->wname[i]); + } + fmt_print_str(w, " ]"); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Tswrite(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Tswrite *self) { + fmt_print_str(w, "Tswrite {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_base10(w, self->fid); + fmt_print_str(w, " nwname="); + fmt_print_base10(w, self->nwname); + fmt_print_str(w, " wname=["); + for (uint16_t i = 0; i < self->nwname; i++) { + if (i) + fmt_print_byte(w, ','); + fmt_print_byte(w, ' '); + fmt_print_s(w, ctx, &self->wname[i]); + } + fmt_print_str(w, " ]"); + fmt_print_str(w, " count="); + fmt_print_base10(w, self->count); + if (utf8_is_valid_without_nul((uint8_t *)self->data, (size_t)self->count)) { + fmt_print_str(w, " data="); + fmt_print_qmem(w, self->data, self->count < 50 ? self->count : 50); + if (self->count > 50) + fmt_print_str(w, "..."); + } else { + fmt_print_str(w, " data=<bytedata>"); + } + fmt_print_str(w, " }"); +} + +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +[[maybe_unused]] static void fmt_print_Rstat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Rstat *self) { + fmt_print_str(w, "Rstat {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " stat="); + fmt_print_stat(w, ctx, &self->stat); + fmt_print_str(w, " }"); +} + +[[maybe_unused]] static void fmt_print_Twstat(lo_interface fmt_dest w, [[maybe_unused]] struct lib9p_ctx *ctx, struct lib9p_msg_Twstat *self) { + fmt_print_str(w, "Twstat {"); + fmt_print_str(w, " tag="); + fmt_print_tag(w, ctx, &self->tag); + fmt_print_str(w, " fid="); + fmt_print_fid(w, ctx, &self->fid); + fmt_print_str(w, " stat="); + fmt_print_stat(w, ctx, &self->stat); + fmt_print_str(w, " }"); +} +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ + +/* tables.h *******************************************************************/ + +const struct _lib9p_ver_tentry _lib9p_table_ver[LIB9P_VER_NUM] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = {.name="9P2000", .min_Rerror_size=9, .min_Rread_size=11}, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = {.name="9P2000.L", .min_Rerror_size=11, .min_Rread_size=11}, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = {.name="9P2000.e", .min_Rerror_size=9, .min_Rread_size=11}, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = {.name="9P2000.p9p", .min_Rerror_size=9, .min_Rread_size=11}, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = {.name="9P2000.u", .min_Rerror_size=13, .min_Rread_size=11}, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = {.name="uninitialized", .min_Rerror_size=9, .min_Rread_size=0}, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +#define _MSG(typ) [LIB9P_TYP_##typ] = { \ + .name = #typ, \ + .print = (_print_fn_t)fmt_print_##typ, \ + } +const struct _lib9p_msg_tentry _lib9p_table_msg[LIB9P_VER_NUM][0x100] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = { + _MSG(Tversion), + _MSG(Rversion), + _MSG(Tauth), + _MSG(Rauth), + _MSG(Tattach), + _MSG(Rattach), + _MSG(Rerror), + _MSG(Tflush), + _MSG(Rflush), + _MSG(Twalk), + _MSG(Rwalk), + _MSG(Topen), + _MSG(Ropen), + _MSG(Tcreate), + _MSG(Rcreate), + _MSG(Tread), + _MSG(Rread), + _MSG(Twrite), + _MSG(Rwrite), + _MSG(Tclunk), + _MSG(Rclunk), + _MSG(Tremove), + _MSG(Rremove), + _MSG(Tstat), + _MSG(Rstat), + _MSG(Twstat), + _MSG(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = { + _MSG(Rlerror), + _MSG(Tstatfs), + _MSG(Rstatfs), + _MSG(Tlopen), + _MSG(Rlopen), + _MSG(Tlcreate), + _MSG(Rlcreate), + _MSG(Tsymlink), + _MSG(Rsymlink), + _MSG(Tmknod), + _MSG(Rmknod), + _MSG(Trename), + _MSG(Rrename), + _MSG(Treadlink), + _MSG(Rreadlink), + _MSG(Tgetattr), + _MSG(Rgetattr), + _MSG(Tsetattr), + _MSG(Rsetattr), + _MSG(Txattrwalk), + _MSG(Rxattrwalk), + _MSG(Txattrcreate), + _MSG(Rxattrcreate), + _MSG(Treaddir), + _MSG(Rreaddir), + _MSG(Tfsync), + _MSG(Rfsync), + _MSG(Tlock), + _MSG(Rlock), + _MSG(Tgetlock), + _MSG(Rgetlock), + _MSG(Tlink), + _MSG(Rlink), + _MSG(Tmkdir), + _MSG(Rmkdir), + _MSG(Trenameat), + _MSG(Rrenameat), + _MSG(Tunlinkat), + _MSG(Runlinkat), + _MSG(Tversion), + _MSG(Rversion), + _MSG(Tauth), + _MSG(Rauth), + _MSG(Tattach), + _MSG(Rattach), + _MSG(Tflush), + _MSG(Rflush), + _MSG(Twalk), + _MSG(Rwalk), + _MSG(Tread), + _MSG(Rread), + _MSG(Twrite), + _MSG(Rwrite), + _MSG(Tclunk), + _MSG(Rclunk), + _MSG(Tremove), + _MSG(Rremove), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = { + _MSG(Tversion), + _MSG(Rversion), + _MSG(Tauth), + _MSG(Rauth), + _MSG(Tattach), + _MSG(Rattach), + _MSG(Rerror), + _MSG(Tflush), + _MSG(Rflush), + _MSG(Twalk), + _MSG(Rwalk), + _MSG(Topen), + _MSG(Ropen), + _MSG(Tcreate), + _MSG(Rcreate), + _MSG(Tread), + _MSG(Rread), + _MSG(Twrite), + _MSG(Rwrite), + _MSG(Tclunk), + _MSG(Rclunk), + _MSG(Tremove), + _MSG(Rremove), + _MSG(Tstat), + _MSG(Rstat), + _MSG(Twstat), + _MSG(Rwstat), + _MSG(Tsession), + _MSG(Rsession), + _MSG(Tsread), + _MSG(Rsread), + _MSG(Tswrite), + _MSG(Rswrite), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = { + _MSG(Topenfd), + _MSG(Ropenfd), + _MSG(Tversion), + _MSG(Rversion), + _MSG(Tauth), + _MSG(Rauth), + _MSG(Tattach), + _MSG(Rattach), + _MSG(Rerror), + _MSG(Tflush), + _MSG(Rflush), + _MSG(Twalk), + _MSG(Rwalk), + _MSG(Topen), + _MSG(Ropen), + _MSG(Tcreate), + _MSG(Rcreate), + _MSG(Tread), + _MSG(Rread), + _MSG(Twrite), + _MSG(Rwrite), + _MSG(Tclunk), + _MSG(Rclunk), + _MSG(Tremove), + _MSG(Rremove), + _MSG(Tstat), + _MSG(Rstat), + _MSG(Twstat), + _MSG(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = { + _MSG(Tversion), + _MSG(Rversion), + _MSG(Tauth), + _MSG(Rauth), + _MSG(Tattach), + _MSG(Rattach), + _MSG(Rerror), + _MSG(Tflush), + _MSG(Rflush), + _MSG(Twalk), + _MSG(Rwalk), + _MSG(Topen), + _MSG(Ropen), + _MSG(Tcreate), + _MSG(Rcreate), + _MSG(Tread), + _MSG(Rread), + _MSG(Twrite), + _MSG(Rwrite), + _MSG(Tclunk), + _MSG(Rclunk), + _MSG(Tremove), + _MSG(Rremove), + _MSG(Tstat), + _MSG(Rstat), + _MSG(Twstat), + _MSG(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = { + _MSG(Tversion), + _MSG(Rversion), + _MSG(Rerror), + }, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +#define _MSG_RECV(typ) [LIB9P_TYP_##typ/2] = { \ + .validate = validate_##typ, \ + .unmarshal = (_unmarshal_fn_t)unmarshal_##typ, \ + } +#define _MSG_SEND(typ) [LIB9P_TYP_##typ/2] = { \ + .marshal = (_marshal_fn_t)marshal_##typ, \ + } + +const struct _lib9p_recv_tentry _lib9p_table_Tmsg_recv[LIB9P_VER_NUM][0x80] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = { + _MSG_RECV(Tversion), + _MSG_RECV(Tauth), + _MSG_RECV(Tattach), + _MSG_RECV(Tflush), + _MSG_RECV(Twalk), + _MSG_RECV(Topen), + _MSG_RECV(Tcreate), + _MSG_RECV(Tread), + _MSG_RECV(Twrite), + _MSG_RECV(Tclunk), + _MSG_RECV(Tremove), + _MSG_RECV(Tstat), + _MSG_RECV(Twstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = { + _MSG_RECV(Tstatfs), + _MSG_RECV(Tlopen), + _MSG_RECV(Tlcreate), + _MSG_RECV(Tsymlink), + _MSG_RECV(Tmknod), + _MSG_RECV(Trename), + _MSG_RECV(Treadlink), + _MSG_RECV(Tgetattr), + _MSG_RECV(Tsetattr), + _MSG_RECV(Txattrwalk), + _MSG_RECV(Txattrcreate), + _MSG_RECV(Treaddir), + _MSG_RECV(Tfsync), + _MSG_RECV(Tlock), + _MSG_RECV(Tgetlock), + _MSG_RECV(Tlink), + _MSG_RECV(Tmkdir), + _MSG_RECV(Trenameat), + _MSG_RECV(Tunlinkat), + _MSG_RECV(Tversion), + _MSG_RECV(Tauth), + _MSG_RECV(Tattach), + _MSG_RECV(Tflush), + _MSG_RECV(Twalk), + _MSG_RECV(Tread), + _MSG_RECV(Twrite), + _MSG_RECV(Tclunk), + _MSG_RECV(Tremove), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = { + _MSG_RECV(Tversion), + _MSG_RECV(Tauth), + _MSG_RECV(Tattach), + _MSG_RECV(Tflush), + _MSG_RECV(Twalk), + _MSG_RECV(Topen), + _MSG_RECV(Tcreate), + _MSG_RECV(Tread), + _MSG_RECV(Twrite), + _MSG_RECV(Tclunk), + _MSG_RECV(Tremove), + _MSG_RECV(Tstat), + _MSG_RECV(Twstat), + _MSG_RECV(Tsession), + _MSG_RECV(Tsread), + _MSG_RECV(Tswrite), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = { + _MSG_RECV(Topenfd), + _MSG_RECV(Tversion), + _MSG_RECV(Tauth), + _MSG_RECV(Tattach), + _MSG_RECV(Tflush), + _MSG_RECV(Twalk), + _MSG_RECV(Topen), + _MSG_RECV(Tcreate), + _MSG_RECV(Tread), + _MSG_RECV(Twrite), + _MSG_RECV(Tclunk), + _MSG_RECV(Tremove), + _MSG_RECV(Tstat), + _MSG_RECV(Twstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = { + _MSG_RECV(Tversion), + _MSG_RECV(Tauth), + _MSG_RECV(Tattach), + _MSG_RECV(Tflush), + _MSG_RECV(Twalk), + _MSG_RECV(Topen), + _MSG_RECV(Tcreate), + _MSG_RECV(Tread), + _MSG_RECV(Twrite), + _MSG_RECV(Tclunk), + _MSG_RECV(Tremove), + _MSG_RECV(Tstat), + _MSG_RECV(Twstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = { + _MSG_RECV(Tversion), + }, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +const struct _lib9p_recv_tentry _lib9p_table_Rmsg_recv[LIB9P_VER_NUM][0x80] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = { + _MSG_RECV(Rversion), + _MSG_RECV(Rauth), + _MSG_RECV(Rattach), + _MSG_RECV(Rerror), + _MSG_RECV(Rflush), + _MSG_RECV(Rwalk), + _MSG_RECV(Ropen), + _MSG_RECV(Rcreate), + _MSG_RECV(Rread), + _MSG_RECV(Rwrite), + _MSG_RECV(Rclunk), + _MSG_RECV(Rremove), + _MSG_RECV(Rstat), + _MSG_RECV(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = { + _MSG_RECV(Rlerror), + _MSG_RECV(Rstatfs), + _MSG_RECV(Rlopen), + _MSG_RECV(Rlcreate), + _MSG_RECV(Rsymlink), + _MSG_RECV(Rmknod), + _MSG_RECV(Rrename), + _MSG_RECV(Rreadlink), + _MSG_RECV(Rgetattr), + _MSG_RECV(Rsetattr), + _MSG_RECV(Rxattrwalk), + _MSG_RECV(Rxattrcreate), + _MSG_RECV(Rreaddir), + _MSG_RECV(Rfsync), + _MSG_RECV(Rlock), + _MSG_RECV(Rgetlock), + _MSG_RECV(Rlink), + _MSG_RECV(Rmkdir), + _MSG_RECV(Rrenameat), + _MSG_RECV(Runlinkat), + _MSG_RECV(Rversion), + _MSG_RECV(Rauth), + _MSG_RECV(Rattach), + _MSG_RECV(Rflush), + _MSG_RECV(Rwalk), + _MSG_RECV(Rread), + _MSG_RECV(Rwrite), + _MSG_RECV(Rclunk), + _MSG_RECV(Rremove), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = { + _MSG_RECV(Rversion), + _MSG_RECV(Rauth), + _MSG_RECV(Rattach), + _MSG_RECV(Rerror), + _MSG_RECV(Rflush), + _MSG_RECV(Rwalk), + _MSG_RECV(Ropen), + _MSG_RECV(Rcreate), + _MSG_RECV(Rread), + _MSG_RECV(Rwrite), + _MSG_RECV(Rclunk), + _MSG_RECV(Rremove), + _MSG_RECV(Rstat), + _MSG_RECV(Rwstat), + _MSG_RECV(Rsession), + _MSG_RECV(Rsread), + _MSG_RECV(Rswrite), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = { + _MSG_RECV(Ropenfd), + _MSG_RECV(Rversion), + _MSG_RECV(Rauth), + _MSG_RECV(Rattach), + _MSG_RECV(Rerror), + _MSG_RECV(Rflush), + _MSG_RECV(Rwalk), + _MSG_RECV(Ropen), + _MSG_RECV(Rcreate), + _MSG_RECV(Rread), + _MSG_RECV(Rwrite), + _MSG_RECV(Rclunk), + _MSG_RECV(Rremove), + _MSG_RECV(Rstat), + _MSG_RECV(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = { + _MSG_RECV(Rversion), + _MSG_RECV(Rauth), + _MSG_RECV(Rattach), + _MSG_RECV(Rerror), + _MSG_RECV(Rflush), + _MSG_RECV(Rwalk), + _MSG_RECV(Ropen), + _MSG_RECV(Rcreate), + _MSG_RECV(Rread), + _MSG_RECV(Rwrite), + _MSG_RECV(Rclunk), + _MSG_RECV(Rremove), + _MSG_RECV(Rstat), + _MSG_RECV(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = { + _MSG_RECV(Rversion), + _MSG_RECV(Rerror), + }, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +const struct _lib9p_send_tentry _lib9p_table_Tmsg_send[LIB9P_VER_NUM][0x80] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = { + _MSG_SEND(Tversion), + _MSG_SEND(Tauth), + _MSG_SEND(Tattach), + _MSG_SEND(Tflush), + _MSG_SEND(Twalk), + _MSG_SEND(Topen), + _MSG_SEND(Tcreate), + _MSG_SEND(Tread), + _MSG_SEND(Twrite), + _MSG_SEND(Tclunk), + _MSG_SEND(Tremove), + _MSG_SEND(Tstat), + _MSG_SEND(Twstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = { + _MSG_SEND(Tstatfs), + _MSG_SEND(Tlopen), + _MSG_SEND(Tlcreate), + _MSG_SEND(Tsymlink), + _MSG_SEND(Tmknod), + _MSG_SEND(Trename), + _MSG_SEND(Treadlink), + _MSG_SEND(Tgetattr), + _MSG_SEND(Tsetattr), + _MSG_SEND(Txattrwalk), + _MSG_SEND(Txattrcreate), + _MSG_SEND(Treaddir), + _MSG_SEND(Tfsync), + _MSG_SEND(Tlock), + _MSG_SEND(Tgetlock), + _MSG_SEND(Tlink), + _MSG_SEND(Tmkdir), + _MSG_SEND(Trenameat), + _MSG_SEND(Tunlinkat), + _MSG_SEND(Tversion), + _MSG_SEND(Tauth), + _MSG_SEND(Tattach), + _MSG_SEND(Tflush), + _MSG_SEND(Twalk), + _MSG_SEND(Tread), + _MSG_SEND(Twrite), + _MSG_SEND(Tclunk), + _MSG_SEND(Tremove), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = { + _MSG_SEND(Tversion), + _MSG_SEND(Tauth), + _MSG_SEND(Tattach), + _MSG_SEND(Tflush), + _MSG_SEND(Twalk), + _MSG_SEND(Topen), + _MSG_SEND(Tcreate), + _MSG_SEND(Tread), + _MSG_SEND(Twrite), + _MSG_SEND(Tclunk), + _MSG_SEND(Tremove), + _MSG_SEND(Tstat), + _MSG_SEND(Twstat), + _MSG_SEND(Tsession), + _MSG_SEND(Tsread), + _MSG_SEND(Tswrite), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = { + _MSG_SEND(Topenfd), + _MSG_SEND(Tversion), + _MSG_SEND(Tauth), + _MSG_SEND(Tattach), + _MSG_SEND(Tflush), + _MSG_SEND(Twalk), + _MSG_SEND(Topen), + _MSG_SEND(Tcreate), + _MSG_SEND(Tread), + _MSG_SEND(Twrite), + _MSG_SEND(Tclunk), + _MSG_SEND(Tremove), + _MSG_SEND(Tstat), + _MSG_SEND(Twstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = { + _MSG_SEND(Tversion), + _MSG_SEND(Tauth), + _MSG_SEND(Tattach), + _MSG_SEND(Tflush), + _MSG_SEND(Twalk), + _MSG_SEND(Topen), + _MSG_SEND(Tcreate), + _MSG_SEND(Tread), + _MSG_SEND(Twrite), + _MSG_SEND(Tclunk), + _MSG_SEND(Tremove), + _MSG_SEND(Tstat), + _MSG_SEND(Twstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = { + _MSG_SEND(Tversion), + }, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +const struct _lib9p_send_tentry _lib9p_table_Rmsg_send[LIB9P_VER_NUM][0x80] = { +#if CONFIG_9P_ENABLE_9P2000 + [LIB9P_VER_9P2000] = { + _MSG_SEND(Rversion), + _MSG_SEND(Rauth), + _MSG_SEND(Rattach), + _MSG_SEND(Rerror), + _MSG_SEND(Rflush), + _MSG_SEND(Rwalk), + _MSG_SEND(Ropen), + _MSG_SEND(Rcreate), + _MSG_SEND(Rread), + _MSG_SEND(Rwrite), + _MSG_SEND(Rclunk), + _MSG_SEND(Rremove), + _MSG_SEND(Rstat), + _MSG_SEND(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + [LIB9P_VER_9P2000_L] = { + _MSG_SEND(Rlerror), + _MSG_SEND(Rstatfs), + _MSG_SEND(Rlopen), + _MSG_SEND(Rlcreate), + _MSG_SEND(Rsymlink), + _MSG_SEND(Rmknod), + _MSG_SEND(Rrename), + _MSG_SEND(Rreadlink), + _MSG_SEND(Rgetattr), + _MSG_SEND(Rsetattr), + _MSG_SEND(Rxattrwalk), + _MSG_SEND(Rxattrcreate), + _MSG_SEND(Rreaddir), + _MSG_SEND(Rfsync), + _MSG_SEND(Rlock), + _MSG_SEND(Rgetlock), + _MSG_SEND(Rlink), + _MSG_SEND(Rmkdir), + _MSG_SEND(Rrenameat), + _MSG_SEND(Runlinkat), + _MSG_SEND(Rversion), + _MSG_SEND(Rauth), + _MSG_SEND(Rattach), + _MSG_SEND(Rflush), + _MSG_SEND(Rwalk), + _MSG_SEND(Rread), + _MSG_SEND(Rwrite), + _MSG_SEND(Rclunk), + _MSG_SEND(Rremove), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + [LIB9P_VER_9P2000_e] = { + _MSG_SEND(Rversion), + _MSG_SEND(Rauth), + _MSG_SEND(Rattach), + _MSG_SEND(Rerror), + _MSG_SEND(Rflush), + _MSG_SEND(Rwalk), + _MSG_SEND(Ropen), + _MSG_SEND(Rcreate), + _MSG_SEND(Rread), + _MSG_SEND(Rwrite), + _MSG_SEND(Rclunk), + _MSG_SEND(Rremove), + _MSG_SEND(Rstat), + _MSG_SEND(Rwstat), + _MSG_SEND(Rsession), + _MSG_SEND(Rsread), + _MSG_SEND(Rswrite), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + [LIB9P_VER_9P2000_p9p] = { + _MSG_SEND(Ropenfd), + _MSG_SEND(Rversion), + _MSG_SEND(Rauth), + _MSG_SEND(Rattach), + _MSG_SEND(Rerror), + _MSG_SEND(Rflush), + _MSG_SEND(Rwalk), + _MSG_SEND(Ropen), + _MSG_SEND(Rcreate), + _MSG_SEND(Rread), + _MSG_SEND(Rwrite), + _MSG_SEND(Rclunk), + _MSG_SEND(Rremove), + _MSG_SEND(Rstat), + _MSG_SEND(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + [LIB9P_VER_9P2000_u] = { + _MSG_SEND(Rversion), + _MSG_SEND(Rauth), + _MSG_SEND(Rattach), + _MSG_SEND(Rerror), + _MSG_SEND(Rflush), + _MSG_SEND(Rwalk), + _MSG_SEND(Ropen), + _MSG_SEND(Rcreate), + _MSG_SEND(Rread), + _MSG_SEND(Rwrite), + _MSG_SEND(Rclunk), + _MSG_SEND(Rremove), + _MSG_SEND(Rstat), + _MSG_SEND(Rwstat), + }, +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_uninitialized + [LIB9P_VER_uninitialized] = { + _MSG_SEND(Rversion), + _MSG_SEND(Rerror), + }, +#endif /* CONFIG_9P_ENABLE_uninitialized */ +}; + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +LM_FLATTEN size_t_or_error _lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) { + return validate_stat(ctx, net_size, net_bytes, ret_net_size); +} +LM_FLATTEN void _lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out) { + unmarshal_stat(ctx, net_bytes, out); +} +LM_FLATTEN bool _lib9p_stat_marshal(struct lib9p_ctx *ctx, struct lib9p_stat *val, struct _marshal_ret *ret) { + return marshal_stat(ctx, val, ret); +} +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ diff --git a/lib9p/core_include/lib9p/_core_generated.h b/lib9p/core_include/lib9p/_core_generated.h new file mode 100644 index 0000000..905f1f0 --- /dev/null +++ b/lib9p/core_include/lib9p/_core_generated.h @@ -0,0 +1,1389 @@ +/* Generated by `lib9p/core.gen lib9p/idl/0000-uninitialized.9p lib9p/idl/2002-9P2000.9p lib9p/idl/2003-9P2000.p9p.9p lib9p/idl/2005-9P2000.u.9p lib9p/idl/2010-9P2000.L.9p lib9p/idl/2012-9P2000.e.9p`. DO NOT EDIT! */ + +#ifndef _LIB9P_CORE_H_ + #error Do not include <lib9p/_core_generated.h> directly; include <lib9p/core.h> instead +#endif + +struct _lib9p_iovec_list { + struct iovec *iov; + int iovcnt; +}; + +/* config *********************************************************************/ + +#ifndef CONFIG_9P_ENABLE_9P2000 + #error config.h must define CONFIG_9P_ENABLE_9P2000 +#endif + +#ifndef CONFIG_9P_ENABLE_9P2000_L + #error config.h must define CONFIG_9P_ENABLE_9P2000_L +#endif + +#ifndef CONFIG_9P_ENABLE_9P2000_e + #error config.h must define CONFIG_9P_ENABLE_9P2000_e +#else + #if CONFIG_9P_ENABLE_9P2000_e + #ifndef CONFIG_9P_MAX_9P2000_e_WELEM + #error if CONFIG_9P_ENABLE_9P2000_e then config.h must define CONFIG_9P_MAX_9P2000_e_WELEM + #endif + static_assert(CONFIG_9P_MAX_9P2000_e_WELEM > 0); + #endif +#endif + +#ifndef CONFIG_9P_ENABLE_9P2000_p9p + #error config.h must define CONFIG_9P_ENABLE_9P2000_p9p +#endif + +#ifndef CONFIG_9P_ENABLE_9P2000_u + #error config.h must define CONFIG_9P_ENABLE_9P2000_u +#endif + +#ifndef CONFIG_9P_ENABLE_uninitialized + #error config.h must define CONFIG_9P_ENABLE_uninitialized +#endif + +#define _LIB9P_ENABLE_stat CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u + +/* enum version ***************************************************************/ + +enum lib9p_version { + LIB9P_VER_uninitialized = 0, /* "uninitialized" */ +#if CONFIG_9P_ENABLE_9P2000 + LIB9P_VER_9P2000, /* "9P2000" */ +#endif /* CONFIG_9P_ENABLE_9P2000 */ +#if CONFIG_9P_ENABLE_9P2000_L + LIB9P_VER_9P2000_L, /* "9P2000.L" */ +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e + LIB9P_VER_9P2000_e, /* "9P2000.e" */ +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000_p9p + LIB9P_VER_9P2000_p9p, /* "9P2000.p9p" */ +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_u + LIB9P_VER_9P2000_u, /* "9P2000.u" */ +#endif /* CONFIG_9P_ENABLE_9P2000_u */ + LIB9P_VER_NUM, +}; + +/* enum msg_type **************************************************************/ + +enum lib9p_msg_type { /* uint8_t */ +#if CONFIG_9P_ENABLE_9P2000_L + LIB9P_TYP_Rlerror = 7, + LIB9P_TYP_Tstatfs = 8, + LIB9P_TYP_Rstatfs = 9, + LIB9P_TYP_Tlopen = 12, + LIB9P_TYP_Rlopen = 13, + LIB9P_TYP_Tlcreate = 14, + LIB9P_TYP_Rlcreate = 15, + LIB9P_TYP_Tsymlink = 16, + LIB9P_TYP_Rsymlink = 17, + LIB9P_TYP_Tmknod = 18, + LIB9P_TYP_Rmknod = 19, + LIB9P_TYP_Trename = 20, + LIB9P_TYP_Rrename = 21, + LIB9P_TYP_Treadlink = 22, + LIB9P_TYP_Rreadlink = 23, + LIB9P_TYP_Tgetattr = 24, + LIB9P_TYP_Rgetattr = 25, + LIB9P_TYP_Tsetattr = 26, + LIB9P_TYP_Rsetattr = 27, + LIB9P_TYP_Txattrwalk = 30, + LIB9P_TYP_Rxattrwalk = 31, + LIB9P_TYP_Txattrcreate = 32, + LIB9P_TYP_Rxattrcreate = 33, + LIB9P_TYP_Treaddir = 40, + LIB9P_TYP_Rreaddir = 41, + LIB9P_TYP_Tfsync = 50, + LIB9P_TYP_Rfsync = 51, + LIB9P_TYP_Tlock = 52, + LIB9P_TYP_Rlock = 53, + LIB9P_TYP_Tgetlock = 54, + LIB9P_TYP_Rgetlock = 55, + LIB9P_TYP_Tlink = 70, + LIB9P_TYP_Rlink = 71, + LIB9P_TYP_Tmkdir = 72, + LIB9P_TYP_Rmkdir = 73, + LIB9P_TYP_Trenameat = 74, + LIB9P_TYP_Rrenameat = 75, + LIB9P_TYP_Tunlinkat = 76, + LIB9P_TYP_Runlinkat = 77, +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_p9p + LIB9P_TYP_Topenfd = 98, + LIB9P_TYP_Ropenfd = 99, +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized + LIB9P_TYP_Tversion = 100, + LIB9P_TYP_Rversion = 101, +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u + LIB9P_TYP_Tauth = 102, + LIB9P_TYP_Rauth = 103, + LIB9P_TYP_Tattach = 104, + LIB9P_TYP_Rattach = 105, +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized + LIB9P_TYP_Rerror = 107, +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u + LIB9P_TYP_Tflush = 108, + LIB9P_TYP_Rflush = 109, + LIB9P_TYP_Twalk = 110, + LIB9P_TYP_Rwalk = 111, +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u + LIB9P_TYP_Topen = 112, + LIB9P_TYP_Ropen = 113, + LIB9P_TYP_Tcreate = 114, + LIB9P_TYP_Rcreate = 115, +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u + 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, +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u + LIB9P_TYP_Tstat = 124, + LIB9P_TYP_Rstat = 125, + LIB9P_TYP_Twstat = 126, + LIB9P_TYP_Rwstat = 127, +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_e + LIB9P_TYP_Tsession = 150, + LIB9P_TYP_Rsession = 151, + LIB9P_TYP_Tsread = 152, + LIB9P_TYP_Rsread = 153, + LIB9P_TYP_Tswrite = 154, + LIB9P_TYP_Rswrite = 155, +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +}; + +/* payload types **************************************************************/ + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +/* size = 2 ; max_iov = 1 ; max_copy = 2 */ +typedef uint16_t lib9p_tag_t; +#define LIB9P_TAG_NOTAG ((lib9p_tag_t)(UINT16_MAX)) + +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_fid_t; +#define LIB9P_FID_NOFID ((lib9p_fid_t)(UINT32_MAX)) + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_dm_t; +/* bits */ +#define LIB9P_DM_DIR ((lib9p_dm_t)(UINT32_C(1)<<31)) +#define LIB9P_DM_APPEND ((lib9p_dm_t)(UINT32_C(1)<<30)) +#define LIB9P_DM_EXCL ((lib9p_dm_t)(UINT32_C(1)<<29)) +#define _LIB9P_DM_PLAN9_MOUNT ((lib9p_dm_t)(UINT32_C(1)<<28)) +#define LIB9P_DM_AUTH ((lib9p_dm_t)(UINT32_C(1)<<27)) +#define LIB9P_DM_TMP ((lib9p_dm_t)(UINT32_C(1)<<26)) +#define _LIB9P_DM_UNUSED_25 ((lib9p_dm_t)(UINT32_C(1)<<25)) +#define _LIB9P_DM_UNUSED_24 ((lib9p_dm_t)(UINT32_C(1)<<24)) +#if CONFIG_9P_ENABLE_9P2000_u +# define LIB9P_DM_DEVICE ((lib9p_dm_t)(UINT32_C(1)<<23)) +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#define _LIB9P_DM_UNUSED_22 ((lib9p_dm_t)(UINT32_C(1)<<22)) +#if CONFIG_9P_ENABLE_9P2000_u +# define LIB9P_DM_PIPE ((lib9p_dm_t)(UINT32_C(1)<<21)) +# define LIB9P_DM_SOCKET ((lib9p_dm_t)(UINT32_C(1)<<20)) +# define LIB9P_DM_SETUID ((lib9p_dm_t)(UINT32_C(1)<<19)) +# define LIB9P_DM_SETGID ((lib9p_dm_t)(UINT32_C(1)<<18)) +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#define _LIB9P_DM_UNUSED_17 ((lib9p_dm_t)(UINT32_C(1)<<17)) +#define _LIB9P_DM_UNUSED_16 ((lib9p_dm_t)(UINT32_C(1)<<16)) +#define _LIB9P_DM_UNUSED_15 ((lib9p_dm_t)(UINT32_C(1)<<15)) +#define _LIB9P_DM_UNUSED_14 ((lib9p_dm_t)(UINT32_C(1)<<14)) +#define _LIB9P_DM_UNUSED_13 ((lib9p_dm_t)(UINT32_C(1)<<13)) +#define _LIB9P_DM_UNUSED_12 ((lib9p_dm_t)(UINT32_C(1)<<12)) +#define _LIB9P_DM_UNUSED_11 ((lib9p_dm_t)(UINT32_C(1)<<11)) +#define _LIB9P_DM_UNUSED_10 ((lib9p_dm_t)(UINT32_C(1)<<10)) +#define _LIB9P_DM_UNUSED_9 ((lib9p_dm_t)(UINT32_C(1)<<9)) +#define LIB9P_DM_OWNER_R ((lib9p_dm_t)(UINT32_C(1)<<8)) +#define LIB9P_DM_OWNER_W ((lib9p_dm_t)(UINT32_C(1)<<7)) +#define LIB9P_DM_OWNER_X ((lib9p_dm_t)(UINT32_C(1)<<6)) +#define LIB9P_DM_GROUP_R ((lib9p_dm_t)(UINT32_C(1)<<5)) +#define LIB9P_DM_GROUP_W ((lib9p_dm_t)(UINT32_C(1)<<4)) +#define LIB9P_DM_GROUP_X ((lib9p_dm_t)(UINT32_C(1)<<3)) +#define LIB9P_DM_OTHER_R ((lib9p_dm_t)(UINT32_C(1)<<2)) +#define LIB9P_DM_OTHER_W ((lib9p_dm_t)(UINT32_C(1)<<1)) +#define LIB9P_DM_OTHER_X ((lib9p_dm_t)(UINT32_C(1)<<0)) +/* masks */ +#define LIB9P_DM_PERM_MASK ((lib9p_dm_t)(0b000000000000000000000111111111)) + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +/* size = 1 ; max_iov = 1 ; max_copy = 1 */ +typedef uint8_t lib9p_qt_t; +/* bits */ +#define LIB9P_QT_DIR ((lib9p_qt_t)(UINT8_C(1)<<7)) +#define LIB9P_QT_APPEND ((lib9p_qt_t)(UINT8_C(1)<<6)) +#define LIB9P_QT_EXCL ((lib9p_qt_t)(UINT8_C(1)<<5)) +#define _LIB9P_QT_PLAN9_MOUNT ((lib9p_qt_t)(UINT8_C(1)<<4)) +#define LIB9P_QT_AUTH ((lib9p_qt_t)(UINT8_C(1)<<3)) +#define LIB9P_QT_TMP ((lib9p_qt_t)(UINT8_C(1)<<2)) +#if CONFIG_9P_ENABLE_9P2000_u +# define LIB9P_QT_SYMLINK ((lib9p_qt_t)(UINT8_C(1)<<1)) +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +#define _LIB9P_QT_UNUSED_0 ((lib9p_qt_t)(UINT8_C(1)<<0)) +/* aliases */ +#define LIB9P_QT_FILE ((lib9p_qt_t)(0)) + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* size = 1 ; max_iov = 1 ; max_copy = 1 */ +typedef uint8_t lib9p_o_t; +/* bits */ +#define _LIB9P_O_UNUSED_7 ((lib9p_o_t)(UINT8_C(1)<<7)) +#define LIB9P_O_RCLOSE ((lib9p_o_t)(UINT8_C(1)<<6)) +#define _LIB9P_O_RESERVED_CEXEC ((lib9p_o_t)(UINT8_C(1)<<5)) +#define LIB9P_O_TRUNC ((lib9p_o_t)(UINT8_C(1)<<4)) +#define _LIB9P_O_UNUSED_3 ((lib9p_o_t)(UINT8_C(1)<<3)) +#define _LIB9P_O_UNUSED_2 ((lib9p_o_t)(UINT8_C(1)<<2)) +/* number LIB9P_O_MODE_* ((lib9p_o_t)(UINT8_C(1)<<1)) */ +/* number LIB9P_O_MODE_* ((lib9p_o_t)(UINT8_C(1)<<0)) */ +/* masks */ +#define LIB9P_O_FLAG_MASK ((lib9p_o_t)(0b11111100)) +/* number: MODE */ +#define LIB9P_O_MODE_READ ((lib9p_o_t)(0)) +#define LIB9P_O_MODE_WRITE ((lib9p_o_t)(1)) +#define LIB9P_O_MODE_RDWR ((lib9p_o_t)(2)) +#define LIB9P_O_MODE_EXEC ((lib9p_o_t)(3)) +#define LIB9P_O_MODE_MASK ((lib9p_o_t)(0b000011)) + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_nuid_t; +#define LIB9P_NUID_NONUID ((lib9p_nuid_t)(UINT32_MAX)) + +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_errno_t; +#define LIB9P_ERRNO_NOERROR ((lib9p_errno_t)(0)) +#define LIB9P_ERRNO_L_EPERM ((lib9p_errno_t)(1)) +#define LIB9P_ERRNO_L_ENOENT ((lib9p_errno_t)(2)) +#define LIB9P_ERRNO_L_ESRCH ((lib9p_errno_t)(3)) +#define LIB9P_ERRNO_L_EINTR ((lib9p_errno_t)(4)) +#define LIB9P_ERRNO_L_EIO ((lib9p_errno_t)(5)) +#define LIB9P_ERRNO_L_ENXIO ((lib9p_errno_t)(6)) +#define LIB9P_ERRNO_L_E2BIG ((lib9p_errno_t)(7)) +#define LIB9P_ERRNO_L_ENOEXEC ((lib9p_errno_t)(8)) +#define LIB9P_ERRNO_L_EBADF ((lib9p_errno_t)(9)) +#define LIB9P_ERRNO_L_ECHILD ((lib9p_errno_t)(10)) +#define LIB9P_ERRNO_L_EAGAIN ((lib9p_errno_t)(11)) +#define LIB9P_ERRNO_L_ENOMEM ((lib9p_errno_t)(12)) +#define LIB9P_ERRNO_L_EACCES ((lib9p_errno_t)(13)) +#define LIB9P_ERRNO_L_EFAULT ((lib9p_errno_t)(14)) +#define LIB9P_ERRNO_L_ENOTBLK ((lib9p_errno_t)(15)) +#define LIB9P_ERRNO_L_EBUSY ((lib9p_errno_t)(16)) +#define LIB9P_ERRNO_L_EEXIST ((lib9p_errno_t)(17)) +#define LIB9P_ERRNO_L_EXDEV ((lib9p_errno_t)(18)) +#define LIB9P_ERRNO_L_ENODEV ((lib9p_errno_t)(19)) +#define LIB9P_ERRNO_L_ENOTDIR ((lib9p_errno_t)(20)) +#define LIB9P_ERRNO_L_EISDIR ((lib9p_errno_t)(21)) +#define LIB9P_ERRNO_L_EINVAL ((lib9p_errno_t)(22)) +#define LIB9P_ERRNO_L_ENFILE ((lib9p_errno_t)(23)) +#define LIB9P_ERRNO_L_EMFILE ((lib9p_errno_t)(24)) +#define LIB9P_ERRNO_L_ENOTTY ((lib9p_errno_t)(25)) +#define LIB9P_ERRNO_L_ETXTBSY ((lib9p_errno_t)(26)) +#define LIB9P_ERRNO_L_EFBIG ((lib9p_errno_t)(27)) +#define LIB9P_ERRNO_L_ENOSPC ((lib9p_errno_t)(28)) +#define LIB9P_ERRNO_L_ESPIPE ((lib9p_errno_t)(29)) +#define LIB9P_ERRNO_L_EROFS ((lib9p_errno_t)(30)) +#define LIB9P_ERRNO_L_EMLINK ((lib9p_errno_t)(31)) +#define LIB9P_ERRNO_L_EPIPE ((lib9p_errno_t)(32)) +#define LIB9P_ERRNO_L_EDOM ((lib9p_errno_t)(33)) +#define LIB9P_ERRNO_L_ERANGE ((lib9p_errno_t)(34)) +#define LIB9P_ERRNO_L_EDEADLK ((lib9p_errno_t)(35)) +#define LIB9P_ERRNO_L_ENAMETOOLONG ((lib9p_errno_t)(36)) +#define LIB9P_ERRNO_L_ENOLCK ((lib9p_errno_t)(37)) +#define LIB9P_ERRNO_L_ENOSYS ((lib9p_errno_t)(38)) +#define LIB9P_ERRNO_L_ENOTEMPTY ((lib9p_errno_t)(39)) +#define LIB9P_ERRNO_L_ELOOP ((lib9p_errno_t)(40)) +#define LIB9P_ERRNO_L_ENOMSG ((lib9p_errno_t)(42)) +#define LIB9P_ERRNO_L_EIDRM ((lib9p_errno_t)(43)) +#define LIB9P_ERRNO_L_ECHRNG ((lib9p_errno_t)(44)) +#define LIB9P_ERRNO_L_EL2NSYNC ((lib9p_errno_t)(45)) +#define LIB9P_ERRNO_L_EL3HLT ((lib9p_errno_t)(46)) +#define LIB9P_ERRNO_L_EL3RST ((lib9p_errno_t)(47)) +#define LIB9P_ERRNO_L_ELNRNG ((lib9p_errno_t)(48)) +#define LIB9P_ERRNO_L_EUNATCH ((lib9p_errno_t)(49)) +#define LIB9P_ERRNO_L_ENOCSI ((lib9p_errno_t)(50)) +#define LIB9P_ERRNO_L_EL2HLT ((lib9p_errno_t)(51)) +#define LIB9P_ERRNO_L_EBADE ((lib9p_errno_t)(52)) +#define LIB9P_ERRNO_L_EBADR ((lib9p_errno_t)(53)) +#define LIB9P_ERRNO_L_EXFULL ((lib9p_errno_t)(54)) +#define LIB9P_ERRNO_L_ENOANO ((lib9p_errno_t)(55)) +#define LIB9P_ERRNO_L_EBADRQC ((lib9p_errno_t)(56)) +#define LIB9P_ERRNO_L_EBADSLT ((lib9p_errno_t)(57)) +#define LIB9P_ERRNO_L_EBFONT ((lib9p_errno_t)(59)) +#define LIB9P_ERRNO_L_ENOSTR ((lib9p_errno_t)(60)) +#define LIB9P_ERRNO_L_ENODATA ((lib9p_errno_t)(61)) +#define LIB9P_ERRNO_L_ETIME ((lib9p_errno_t)(62)) +#define LIB9P_ERRNO_L_ENOSR ((lib9p_errno_t)(63)) +#define LIB9P_ERRNO_L_ENONET ((lib9p_errno_t)(64)) +#define LIB9P_ERRNO_L_ENOPKG ((lib9p_errno_t)(65)) +#define LIB9P_ERRNO_L_EREMOTE ((lib9p_errno_t)(66)) +#define LIB9P_ERRNO_L_ENOLINK ((lib9p_errno_t)(67)) +#define LIB9P_ERRNO_L_EADV ((lib9p_errno_t)(68)) +#define LIB9P_ERRNO_L_ESRMNT ((lib9p_errno_t)(69)) +#define LIB9P_ERRNO_L_ECOMM ((lib9p_errno_t)(70)) +#define LIB9P_ERRNO_L_EPROTO ((lib9p_errno_t)(71)) +#define LIB9P_ERRNO_L_EMULTIHOP ((lib9p_errno_t)(72)) +#define LIB9P_ERRNO_L_EDOTDOT ((lib9p_errno_t)(73)) +#define LIB9P_ERRNO_L_EBADMSG ((lib9p_errno_t)(74)) +#define LIB9P_ERRNO_L_EOVERFLOW ((lib9p_errno_t)(75)) +#define LIB9P_ERRNO_L_ENOTUNIQ ((lib9p_errno_t)(76)) +#define LIB9P_ERRNO_L_EBADFD ((lib9p_errno_t)(77)) +#define LIB9P_ERRNO_L_EREMCHG ((lib9p_errno_t)(78)) +#define LIB9P_ERRNO_L_ELIBACC ((lib9p_errno_t)(79)) +#define LIB9P_ERRNO_L_ELIBBAD ((lib9p_errno_t)(80)) +#define LIB9P_ERRNO_L_ELIBSCN ((lib9p_errno_t)(81)) +#define LIB9P_ERRNO_L_ELIBMAX ((lib9p_errno_t)(82)) +#define LIB9P_ERRNO_L_ELIBEXEC ((lib9p_errno_t)(83)) +#define LIB9P_ERRNO_L_EILSEQ ((lib9p_errno_t)(84)) +#define LIB9P_ERRNO_L_ERESTART ((lib9p_errno_t)(85)) +#define LIB9P_ERRNO_L_ESTRPIPE ((lib9p_errno_t)(86)) +#define LIB9P_ERRNO_L_EUSERS ((lib9p_errno_t)(87)) +#define LIB9P_ERRNO_L_ENOTSOCK ((lib9p_errno_t)(88)) +#define LIB9P_ERRNO_L_EDESTADDRREQ ((lib9p_errno_t)(89)) +#define LIB9P_ERRNO_L_EMSGSIZE ((lib9p_errno_t)(90)) +#define LIB9P_ERRNO_L_EPROTOTYPE ((lib9p_errno_t)(91)) +#define LIB9P_ERRNO_L_ENOPROTOOPT ((lib9p_errno_t)(92)) +#define LIB9P_ERRNO_L_EPROTONOSUPPORT ((lib9p_errno_t)(93)) +#define LIB9P_ERRNO_L_ESOCKTNOSUPPORT ((lib9p_errno_t)(94)) +#define LIB9P_ERRNO_L_EOPNOTSUPP ((lib9p_errno_t)(95)) +#define LIB9P_ERRNO_L_EPFNOSUPPORT ((lib9p_errno_t)(96)) +#define LIB9P_ERRNO_L_EAFNOSUPPORT ((lib9p_errno_t)(97)) +#define LIB9P_ERRNO_L_EADDRINUSE ((lib9p_errno_t)(98)) +#define LIB9P_ERRNO_L_EADDRNOTAVAIL ((lib9p_errno_t)(99)) +#define LIB9P_ERRNO_L_ENETDOWN ((lib9p_errno_t)(100)) +#define LIB9P_ERRNO_L_ENETUNREACH ((lib9p_errno_t)(101)) +#define LIB9P_ERRNO_L_ENETRESET ((lib9p_errno_t)(102)) +#define LIB9P_ERRNO_L_ECONNABORTED ((lib9p_errno_t)(103)) +#define LIB9P_ERRNO_L_ECONNRESET ((lib9p_errno_t)(104)) +#define LIB9P_ERRNO_L_ENOBUFS ((lib9p_errno_t)(105)) +#define LIB9P_ERRNO_L_EISCONN ((lib9p_errno_t)(106)) +#define LIB9P_ERRNO_L_ENOTCONN ((lib9p_errno_t)(107)) +#define LIB9P_ERRNO_L_ESHUTDOWN ((lib9p_errno_t)(108)) +#define LIB9P_ERRNO_L_ETOOMANYREFS ((lib9p_errno_t)(109)) +#define LIB9P_ERRNO_L_ETIMEDOUT ((lib9p_errno_t)(110)) +#define LIB9P_ERRNO_L_ECONNREFUSED ((lib9p_errno_t)(111)) +#define LIB9P_ERRNO_L_EHOSTDOWN ((lib9p_errno_t)(112)) +#define LIB9P_ERRNO_L_EHOSTUNREACH ((lib9p_errno_t)(113)) +#define LIB9P_ERRNO_L_EALREADY ((lib9p_errno_t)(114)) +#define LIB9P_ERRNO_L_EINPROGRESS ((lib9p_errno_t)(115)) +#define LIB9P_ERRNO_L_ESTALE ((lib9p_errno_t)(116)) +#define LIB9P_ERRNO_L_EUCLEAN ((lib9p_errno_t)(117)) +#define LIB9P_ERRNO_L_ENOTNAM ((lib9p_errno_t)(118)) +#define LIB9P_ERRNO_L_ENAVAIL ((lib9p_errno_t)(119)) +#define LIB9P_ERRNO_L_EISNAM ((lib9p_errno_t)(120)) +#define LIB9P_ERRNO_L_EREMOTEIO ((lib9p_errno_t)(121)) +#define LIB9P_ERRNO_L_EDQUOT ((lib9p_errno_t)(122)) +#define LIB9P_ERRNO_L_ENOMEDIUM ((lib9p_errno_t)(123)) +#define LIB9P_ERRNO_L_EMEDIUMTYPE ((lib9p_errno_t)(124)) +#define LIB9P_ERRNO_L_ECANCELED ((lib9p_errno_t)(125)) +#define LIB9P_ERRNO_L_ENOKEY ((lib9p_errno_t)(126)) +#define LIB9P_ERRNO_L_EKEYEXPIRED ((lib9p_errno_t)(127)) +#define LIB9P_ERRNO_L_EKEYREVOKED ((lib9p_errno_t)(128)) +#define LIB9P_ERRNO_L_EKEYREJECTED ((lib9p_errno_t)(129)) +#define LIB9P_ERRNO_L_EOWNERDEAD ((lib9p_errno_t)(130)) +#define LIB9P_ERRNO_L_ENOTRECOVERABLE ((lib9p_errno_t)(131)) +#define LIB9P_ERRNO_L_ERFKILL ((lib9p_errno_t)(132)) +#define LIB9P_ERRNO_L_EHWPOISON ((lib9p_errno_t)(133)) + +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_L +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_super_magic_t; +#define LIB9P_SUPER_MAGIC_V9FS_MAGIC ((lib9p_super_magic_t)(16914839)) + +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_lo_t; +/* bits */ +#define _LIB9P_LO_UNUSED_31 ((lib9p_lo_t)(UINT32_C(1)<<31)) +#define _LIB9P_LO_UNUSED_30 ((lib9p_lo_t)(UINT32_C(1)<<30)) +#define _LIB9P_LO_UNUSED_29 ((lib9p_lo_t)(UINT32_C(1)<<29)) +#define _LIB9P_LO_UNUSED_28 ((lib9p_lo_t)(UINT32_C(1)<<28)) +#define _LIB9P_LO_UNUSED_27 ((lib9p_lo_t)(UINT32_C(1)<<27)) +#define _LIB9P_LO_UNUSED_26 ((lib9p_lo_t)(UINT32_C(1)<<26)) +#define _LIB9P_LO_UNUSED_25 ((lib9p_lo_t)(UINT32_C(1)<<25)) +#define _LIB9P_LO_UNUSED_24 ((lib9p_lo_t)(UINT32_C(1)<<24)) +#define _LIB9P_LO_UNUSED_23 ((lib9p_lo_t)(UINT32_C(1)<<23)) +#define _LIB9P_LO_UNUSED_22 ((lib9p_lo_t)(UINT32_C(1)<<22)) +#define _LIB9P_LO_UNUSED_21 ((lib9p_lo_t)(UINT32_C(1)<<21)) +#define LIB9P_LO_SYNC ((lib9p_lo_t)(UINT32_C(1)<<20)) +#define LIB9P_LO_CLOEXEC ((lib9p_lo_t)(UINT32_C(1)<<19)) +#define LIB9P_LO_NOATIME ((lib9p_lo_t)(UINT32_C(1)<<18)) +#define LIB9P_LO_NOFOLLOW ((lib9p_lo_t)(UINT32_C(1)<<17)) +#define LIB9P_LO_DIRECTORY ((lib9p_lo_t)(UINT32_C(1)<<16)) +#define LIB9P_LO_LARGEFILE ((lib9p_lo_t)(UINT32_C(1)<<15)) +#define LIB9P_LO_DIRECT ((lib9p_lo_t)(UINT32_C(1)<<14)) +#define LIB9P_LO_BSD_FASYNC ((lib9p_lo_t)(UINT32_C(1)<<13)) +#define LIB9P_LO_DSYNC ((lib9p_lo_t)(UINT32_C(1)<<12)) +#define LIB9P_LO_NONBLOCK ((lib9p_lo_t)(UINT32_C(1)<<11)) +#define LIB9P_LO_APPEND ((lib9p_lo_t)(UINT32_C(1)<<10)) +#define LIB9P_LO_TRUNC ((lib9p_lo_t)(UINT32_C(1)<<9)) +#define LIB9P_LO_NOCTTY ((lib9p_lo_t)(UINT32_C(1)<<8)) +#define LIB9P_LO_EXCL ((lib9p_lo_t)(UINT32_C(1)<<7)) +#define LIB9P_LO_CREATE ((lib9p_lo_t)(UINT32_C(1)<<6)) +#define _LIB9P_LO_UNUSED_5 ((lib9p_lo_t)(UINT32_C(1)<<5)) +#define _LIB9P_LO_UNUSED_4 ((lib9p_lo_t)(UINT32_C(1)<<4)) +#define _LIB9P_LO_UNUSED_3 ((lib9p_lo_t)(UINT32_C(1)<<3)) +#define _LIB9P_LO_UNUSED_2 ((lib9p_lo_t)(UINT32_C(1)<<2)) +/* number LIB9P_LO_MODE_* ((lib9p_lo_t)(UINT32_C(1)<<1)) */ +/* number LIB9P_LO_MODE_* ((lib9p_lo_t)(UINT32_C(1)<<0)) */ +/* masks */ +#define LIB9P_LO_FLAG_MASK ((lib9p_lo_t)(0b000000000111111111111111000000)) +/* number: MODE */ +#define LIB9P_LO_MODE_RDONLY ((lib9p_lo_t)(0)) +#define LIB9P_LO_MODE_WRONLY ((lib9p_lo_t)(1)) +#define LIB9P_LO_MODE_RDWR ((lib9p_lo_t)(2)) +#define LIB9P_LO_MODE_NOACCESS ((lib9p_lo_t)(3)) +#define LIB9P_LO_MODE_MASK ((lib9p_lo_t)(0b000000000000000000000000000011)) + +/* size = 1 ; max_iov = 1 ; max_copy = 1 */ +typedef uint8_t lib9p_dt_t; +#define LIB9P_DT_UNKNOWN ((lib9p_dt_t)(0)) +#define LIB9P_DT_PIPE ((lib9p_dt_t)(1)) +#define LIB9P_DT_CHAR_DEV ((lib9p_dt_t)(2)) +#define LIB9P_DT_DIRECTORY ((lib9p_dt_t)(4)) +#define LIB9P_DT_BLOCK_DEV ((lib9p_dt_t)(6)) +#define LIB9P_DT_REGULAR ((lib9p_dt_t)(8)) +#define LIB9P_DT_SYMLINK ((lib9p_dt_t)(10)) +#define LIB9P_DT_SOCKET ((lib9p_dt_t)(12)) +#define _LIB9P_DT_WHITEOUT ((lib9p_dt_t)(14)) + +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_mode_t; +/* bits */ +#define _LIB9P_MODE_UNUSED_31 ((lib9p_mode_t)(UINT32_C(1)<<31)) +#define _LIB9P_MODE_UNUSED_30 ((lib9p_mode_t)(UINT32_C(1)<<30)) +#define _LIB9P_MODE_UNUSED_29 ((lib9p_mode_t)(UINT32_C(1)<<29)) +#define _LIB9P_MODE_UNUSED_28 ((lib9p_mode_t)(UINT32_C(1)<<28)) +#define _LIB9P_MODE_UNUSED_27 ((lib9p_mode_t)(UINT32_C(1)<<27)) +#define _LIB9P_MODE_UNUSED_26 ((lib9p_mode_t)(UINT32_C(1)<<26)) +#define _LIB9P_MODE_UNUSED_25 ((lib9p_mode_t)(UINT32_C(1)<<25)) +#define _LIB9P_MODE_UNUSED_24 ((lib9p_mode_t)(UINT32_C(1)<<24)) +#define _LIB9P_MODE_UNUSED_23 ((lib9p_mode_t)(UINT32_C(1)<<23)) +#define _LIB9P_MODE_UNUSED_22 ((lib9p_mode_t)(UINT32_C(1)<<22)) +#define _LIB9P_MODE_UNUSED_21 ((lib9p_mode_t)(UINT32_C(1)<<21)) +#define _LIB9P_MODE_UNUSED_20 ((lib9p_mode_t)(UINT32_C(1)<<20)) +#define _LIB9P_MODE_UNUSED_19 ((lib9p_mode_t)(UINT32_C(1)<<19)) +#define _LIB9P_MODE_UNUSED_18 ((lib9p_mode_t)(UINT32_C(1)<<18)) +#define _LIB9P_MODE_UNUSED_17 ((lib9p_mode_t)(UINT32_C(1)<<17)) +#define _LIB9P_MODE_UNUSED_16 ((lib9p_mode_t)(UINT32_C(1)<<16)) +/* number LIB9P_MODE_FMT_* ((lib9p_mode_t)(UINT32_C(1)<<15)) */ +/* number LIB9P_MODE_FMT_* ((lib9p_mode_t)(UINT32_C(1)<<14)) */ +/* number LIB9P_MODE_FMT_* ((lib9p_mode_t)(UINT32_C(1)<<13)) */ +/* number LIB9P_MODE_FMT_* ((lib9p_mode_t)(UINT32_C(1)<<12)) */ +#define LIB9P_MODE_PERM_SETGROUP ((lib9p_mode_t)(UINT32_C(1)<<11)) +#define LIB9P_MODE_PERM_SETUSER ((lib9p_mode_t)(UINT32_C(1)<<10)) +#define LIB9P_MODE_PERM_STICKY ((lib9p_mode_t)(UINT32_C(1)<<9)) +#define LIB9P_MODE_PERM_OWNER_R ((lib9p_mode_t)(UINT32_C(1)<<8)) +#define LIB9P_MODE_PERM_OWNER_W ((lib9p_mode_t)(UINT32_C(1)<<7)) +#define LIB9P_MODE_PERM_OWNER_X ((lib9p_mode_t)(UINT32_C(1)<<6)) +#define LIB9P_MODE_PERM_GROUP_R ((lib9p_mode_t)(UINT32_C(1)<<5)) +#define LIB9P_MODE_PERM_GROUP_W ((lib9p_mode_t)(UINT32_C(1)<<4)) +#define LIB9P_MODE_PERM_GROUP_X ((lib9p_mode_t)(UINT32_C(1)<<3)) +#define LIB9P_MODE_PERM_OTHER_R ((lib9p_mode_t)(UINT32_C(1)<<2)) +#define LIB9P_MODE_PERM_OTHER_W ((lib9p_mode_t)(UINT32_C(1)<<1)) +#define LIB9P_MODE_PERM_OTHER_X ((lib9p_mode_t)(UINT32_C(1)<<0)) +/* masks */ +#define LIB9P_MODE_PERM_MASK ((lib9p_mode_t)(0b000000000000000000111111111111)) +/* number: FMT */ +#define LIB9P_MODE_FMT_PIPE ((lib9p_mode_t)(LIB9P_DT_PIPE << 12)) +#define LIB9P_MODE_FMT_CHAR_DEV ((lib9p_mode_t)(LIB9P_DT_CHAR_DEV << 12)) +#define LIB9P_MODE_FMT_DIRECTORY ((lib9p_mode_t)(LIB9P_DT_DIRECTORY << 12)) +#define LIB9P_MODE_FMT_BLOCK_DEV ((lib9p_mode_t)(LIB9P_DT_BLOCK_DEV << 12)) +#define LIB9P_MODE_FMT_REGULAR ((lib9p_mode_t)(LIB9P_DT_REGULAR << 12)) +#define LIB9P_MODE_FMT_SYMLINK ((lib9p_mode_t)(LIB9P_DT_SYMLINK << 12)) +#define LIB9P_MODE_FMT_SOCKET ((lib9p_mode_t)(LIB9P_DT_SOCKET << 12)) +#define LIB9P_MODE_FMT_MASK ((lib9p_mode_t)(0b000000000000001111000000000000)) + +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_b4_t; +#define LIB9P_B4_FALSE ((lib9p_b4_t)(0)) +#define LIB9P_B4_TRUE ((lib9p_b4_t)(1)) + +/* size = 8 ; max_iov = 1 ; max_copy = 8 */ +typedef uint64_t lib9p_getattr_t; +/* bits */ +#define _LIB9P_GETATTR_UNUSED_63 ((lib9p_getattr_t)(UINT64_C(1)<<63)) +#define _LIB9P_GETATTR_UNUSED_62 ((lib9p_getattr_t)(UINT64_C(1)<<62)) +#define _LIB9P_GETATTR_UNUSED_61 ((lib9p_getattr_t)(UINT64_C(1)<<61)) +#define _LIB9P_GETATTR_UNUSED_60 ((lib9p_getattr_t)(UINT64_C(1)<<60)) +#define _LIB9P_GETATTR_UNUSED_59 ((lib9p_getattr_t)(UINT64_C(1)<<59)) +#define _LIB9P_GETATTR_UNUSED_58 ((lib9p_getattr_t)(UINT64_C(1)<<58)) +#define _LIB9P_GETATTR_UNUSED_57 ((lib9p_getattr_t)(UINT64_C(1)<<57)) +#define _LIB9P_GETATTR_UNUSED_56 ((lib9p_getattr_t)(UINT64_C(1)<<56)) +#define _LIB9P_GETATTR_UNUSED_55 ((lib9p_getattr_t)(UINT64_C(1)<<55)) +#define _LIB9P_GETATTR_UNUSED_54 ((lib9p_getattr_t)(UINT64_C(1)<<54)) +#define _LIB9P_GETATTR_UNUSED_53 ((lib9p_getattr_t)(UINT64_C(1)<<53)) +#define _LIB9P_GETATTR_UNUSED_52 ((lib9p_getattr_t)(UINT64_C(1)<<52)) +#define _LIB9P_GETATTR_UNUSED_51 ((lib9p_getattr_t)(UINT64_C(1)<<51)) +#define _LIB9P_GETATTR_UNUSED_50 ((lib9p_getattr_t)(UINT64_C(1)<<50)) +#define _LIB9P_GETATTR_UNUSED_49 ((lib9p_getattr_t)(UINT64_C(1)<<49)) +#define _LIB9P_GETATTR_UNUSED_48 ((lib9p_getattr_t)(UINT64_C(1)<<48)) +#define _LIB9P_GETATTR_UNUSED_47 ((lib9p_getattr_t)(UINT64_C(1)<<47)) +#define _LIB9P_GETATTR_UNUSED_46 ((lib9p_getattr_t)(UINT64_C(1)<<46)) +#define _LIB9P_GETATTR_UNUSED_45 ((lib9p_getattr_t)(UINT64_C(1)<<45)) +#define _LIB9P_GETATTR_UNUSED_44 ((lib9p_getattr_t)(UINT64_C(1)<<44)) +#define _LIB9P_GETATTR_UNUSED_43 ((lib9p_getattr_t)(UINT64_C(1)<<43)) +#define _LIB9P_GETATTR_UNUSED_42 ((lib9p_getattr_t)(UINT64_C(1)<<42)) +#define _LIB9P_GETATTR_UNUSED_41 ((lib9p_getattr_t)(UINT64_C(1)<<41)) +#define _LIB9P_GETATTR_UNUSED_40 ((lib9p_getattr_t)(UINT64_C(1)<<40)) +#define _LIB9P_GETATTR_UNUSED_39 ((lib9p_getattr_t)(UINT64_C(1)<<39)) +#define _LIB9P_GETATTR_UNUSED_38 ((lib9p_getattr_t)(UINT64_C(1)<<38)) +#define _LIB9P_GETATTR_UNUSED_37 ((lib9p_getattr_t)(UINT64_C(1)<<37)) +#define _LIB9P_GETATTR_UNUSED_36 ((lib9p_getattr_t)(UINT64_C(1)<<36)) +#define _LIB9P_GETATTR_UNUSED_35 ((lib9p_getattr_t)(UINT64_C(1)<<35)) +#define _LIB9P_GETATTR_UNUSED_34 ((lib9p_getattr_t)(UINT64_C(1)<<34)) +#define _LIB9P_GETATTR_UNUSED_33 ((lib9p_getattr_t)(UINT64_C(1)<<33)) +#define _LIB9P_GETATTR_UNUSED_32 ((lib9p_getattr_t)(UINT64_C(1)<<32)) +#define _LIB9P_GETATTR_UNUSED_31 ((lib9p_getattr_t)(UINT64_C(1)<<31)) +#define _LIB9P_GETATTR_UNUSED_30 ((lib9p_getattr_t)(UINT64_C(1)<<30)) +#define _LIB9P_GETATTR_UNUSED_29 ((lib9p_getattr_t)(UINT64_C(1)<<29)) +#define _LIB9P_GETATTR_UNUSED_28 ((lib9p_getattr_t)(UINT64_C(1)<<28)) +#define _LIB9P_GETATTR_UNUSED_27 ((lib9p_getattr_t)(UINT64_C(1)<<27)) +#define _LIB9P_GETATTR_UNUSED_26 ((lib9p_getattr_t)(UINT64_C(1)<<26)) +#define _LIB9P_GETATTR_UNUSED_25 ((lib9p_getattr_t)(UINT64_C(1)<<25)) +#define _LIB9P_GETATTR_UNUSED_24 ((lib9p_getattr_t)(UINT64_C(1)<<24)) +#define _LIB9P_GETATTR_UNUSED_23 ((lib9p_getattr_t)(UINT64_C(1)<<23)) +#define _LIB9P_GETATTR_UNUSED_22 ((lib9p_getattr_t)(UINT64_C(1)<<22)) +#define _LIB9P_GETATTR_UNUSED_21 ((lib9p_getattr_t)(UINT64_C(1)<<21)) +#define _LIB9P_GETATTR_UNUSED_20 ((lib9p_getattr_t)(UINT64_C(1)<<20)) +#define _LIB9P_GETATTR_UNUSED_19 ((lib9p_getattr_t)(UINT64_C(1)<<19)) +#define _LIB9P_GETATTR_UNUSED_18 ((lib9p_getattr_t)(UINT64_C(1)<<18)) +#define _LIB9P_GETATTR_UNUSED_17 ((lib9p_getattr_t)(UINT64_C(1)<<17)) +#define _LIB9P_GETATTR_UNUSED_16 ((lib9p_getattr_t)(UINT64_C(1)<<16)) +#define _LIB9P_GETATTR_UNUSED_15 ((lib9p_getattr_t)(UINT64_C(1)<<15)) +#define _LIB9P_GETATTR_UNUSED_14 ((lib9p_getattr_t)(UINT64_C(1)<<14)) +#define LIB9P_GETATTR_DATA_VERSION ((lib9p_getattr_t)(UINT64_C(1)<<13)) +#define LIB9P_GETATTR_GEN ((lib9p_getattr_t)(UINT64_C(1)<<12)) +#define LIB9P_GETATTR_BTIME ((lib9p_getattr_t)(UINT64_C(1)<<11)) +#define LIB9P_GETATTR_BLOCKS ((lib9p_getattr_t)(UINT64_C(1)<<10)) +#define LIB9P_GETATTR_SIZE ((lib9p_getattr_t)(UINT64_C(1)<<9)) +#define LIB9P_GETATTR_INO ((lib9p_getattr_t)(UINT64_C(1)<<8)) +#define LIB9P_GETATTR_CTIME ((lib9p_getattr_t)(UINT64_C(1)<<7)) +#define LIB9P_GETATTR_MTIME ((lib9p_getattr_t)(UINT64_C(1)<<6)) +#define LIB9P_GETATTR_ATIME ((lib9p_getattr_t)(UINT64_C(1)<<5)) +#define LIB9P_GETATTR_RDEV ((lib9p_getattr_t)(UINT64_C(1)<<4)) +#define LIB9P_GETATTR_GID ((lib9p_getattr_t)(UINT64_C(1)<<3)) +#define LIB9P_GETATTR_UID ((lib9p_getattr_t)(UINT64_C(1)<<2)) +#define LIB9P_GETATTR_NLINK ((lib9p_getattr_t)(UINT64_C(1)<<1)) +#define LIB9P_GETATTR_MODE ((lib9p_getattr_t)(UINT64_C(1)<<0)) +/* aliases */ +#define LIB9P_GETATTR_BASIC ((lib9p_getattr_t)(2047)) +#define LIB9P_GETATTR_ALL ((lib9p_getattr_t)(16383)) + +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_setattr_t; +/* bits */ +#define _LIB9P_SETATTR_UNUSED_31 ((lib9p_setattr_t)(UINT32_C(1)<<31)) +#define _LIB9P_SETATTR_UNUSED_30 ((lib9p_setattr_t)(UINT32_C(1)<<30)) +#define _LIB9P_SETATTR_UNUSED_29 ((lib9p_setattr_t)(UINT32_C(1)<<29)) +#define _LIB9P_SETATTR_UNUSED_28 ((lib9p_setattr_t)(UINT32_C(1)<<28)) +#define _LIB9P_SETATTR_UNUSED_27 ((lib9p_setattr_t)(UINT32_C(1)<<27)) +#define _LIB9P_SETATTR_UNUSED_26 ((lib9p_setattr_t)(UINT32_C(1)<<26)) +#define _LIB9P_SETATTR_UNUSED_25 ((lib9p_setattr_t)(UINT32_C(1)<<25)) +#define _LIB9P_SETATTR_UNUSED_24 ((lib9p_setattr_t)(UINT32_C(1)<<24)) +#define _LIB9P_SETATTR_UNUSED_23 ((lib9p_setattr_t)(UINT32_C(1)<<23)) +#define _LIB9P_SETATTR_UNUSED_22 ((lib9p_setattr_t)(UINT32_C(1)<<22)) +#define _LIB9P_SETATTR_UNUSED_21 ((lib9p_setattr_t)(UINT32_C(1)<<21)) +#define _LIB9P_SETATTR_UNUSED_20 ((lib9p_setattr_t)(UINT32_C(1)<<20)) +#define _LIB9P_SETATTR_UNUSED_19 ((lib9p_setattr_t)(UINT32_C(1)<<19)) +#define _LIB9P_SETATTR_UNUSED_18 ((lib9p_setattr_t)(UINT32_C(1)<<18)) +#define _LIB9P_SETATTR_UNUSED_17 ((lib9p_setattr_t)(UINT32_C(1)<<17)) +#define _LIB9P_SETATTR_UNUSED_16 ((lib9p_setattr_t)(UINT32_C(1)<<16)) +#define _LIB9P_SETATTR_UNUSED_15 ((lib9p_setattr_t)(UINT32_C(1)<<15)) +#define _LIB9P_SETATTR_UNUSED_14 ((lib9p_setattr_t)(UINT32_C(1)<<14)) +#define _LIB9P_SETATTR_UNUSED_13 ((lib9p_setattr_t)(UINT32_C(1)<<13)) +#define _LIB9P_SETATTR_UNUSED_12 ((lib9p_setattr_t)(UINT32_C(1)<<12)) +#define _LIB9P_SETATTR_UNUSED_11 ((lib9p_setattr_t)(UINT32_C(1)<<11)) +#define _LIB9P_SETATTR_UNUSED_10 ((lib9p_setattr_t)(UINT32_C(1)<<10)) +#define _LIB9P_SETATTR_UNUSED_9 ((lib9p_setattr_t)(UINT32_C(1)<<9)) +#define LIB9P_SETATTR_MTIME_SET ((lib9p_setattr_t)(UINT32_C(1)<<8)) +#define LIB9P_SETATTR_ATIME_SET ((lib9p_setattr_t)(UINT32_C(1)<<7)) +#define LIB9P_SETATTR_CTIME ((lib9p_setattr_t)(UINT32_C(1)<<6)) +#define LIB9P_SETATTR_MTIME ((lib9p_setattr_t)(UINT32_C(1)<<5)) +#define LIB9P_SETATTR_ATIME ((lib9p_setattr_t)(UINT32_C(1)<<4)) +#define LIB9P_SETATTR_SIZE ((lib9p_setattr_t)(UINT32_C(1)<<3)) +#define LIB9P_SETATTR_GID ((lib9p_setattr_t)(UINT32_C(1)<<2)) +#define LIB9P_SETATTR_UID ((lib9p_setattr_t)(UINT32_C(1)<<1)) +#define LIB9P_SETATTR_MODE ((lib9p_setattr_t)(UINT32_C(1)<<0)) + +/* size = 1 ; max_iov = 1 ; max_copy = 1 */ +typedef uint8_t lib9p_lock_type_t; +#define LIB9P_LOCK_TYPE_RDLCK ((lib9p_lock_type_t)(0)) +#define LIB9P_LOCK_TYPE_WRLCK ((lib9p_lock_type_t)(1)) +#define LIB9P_LOCK_TYPE_UNLCK ((lib9p_lock_type_t)(2)) + +/* size = 4 ; max_iov = 1 ; max_copy = 4 */ +typedef uint32_t lib9p_lock_flags_t; +/* bits */ +#define _LIB9P_LOCK_FLAGS_UNUSED_31 ((lib9p_lock_flags_t)(UINT32_C(1)<<31)) +#define _LIB9P_LOCK_FLAGS_UNUSED_30 ((lib9p_lock_flags_t)(UINT32_C(1)<<30)) +#define _LIB9P_LOCK_FLAGS_UNUSED_29 ((lib9p_lock_flags_t)(UINT32_C(1)<<29)) +#define _LIB9P_LOCK_FLAGS_UNUSED_28 ((lib9p_lock_flags_t)(UINT32_C(1)<<28)) +#define _LIB9P_LOCK_FLAGS_UNUSED_27 ((lib9p_lock_flags_t)(UINT32_C(1)<<27)) +#define _LIB9P_LOCK_FLAGS_UNUSED_26 ((lib9p_lock_flags_t)(UINT32_C(1)<<26)) +#define _LIB9P_LOCK_FLAGS_UNUSED_25 ((lib9p_lock_flags_t)(UINT32_C(1)<<25)) +#define _LIB9P_LOCK_FLAGS_UNUSED_24 ((lib9p_lock_flags_t)(UINT32_C(1)<<24)) +#define _LIB9P_LOCK_FLAGS_UNUSED_23 ((lib9p_lock_flags_t)(UINT32_C(1)<<23)) +#define _LIB9P_LOCK_FLAGS_UNUSED_22 ((lib9p_lock_flags_t)(UINT32_C(1)<<22)) +#define _LIB9P_LOCK_FLAGS_UNUSED_21 ((lib9p_lock_flags_t)(UINT32_C(1)<<21)) +#define _LIB9P_LOCK_FLAGS_UNUSED_20 ((lib9p_lock_flags_t)(UINT32_C(1)<<20)) +#define _LIB9P_LOCK_FLAGS_UNUSED_19 ((lib9p_lock_flags_t)(UINT32_C(1)<<19)) +#define _LIB9P_LOCK_FLAGS_UNUSED_18 ((lib9p_lock_flags_t)(UINT32_C(1)<<18)) +#define _LIB9P_LOCK_FLAGS_UNUSED_17 ((lib9p_lock_flags_t)(UINT32_C(1)<<17)) +#define _LIB9P_LOCK_FLAGS_UNUSED_16 ((lib9p_lock_flags_t)(UINT32_C(1)<<16)) +#define _LIB9P_LOCK_FLAGS_UNUSED_15 ((lib9p_lock_flags_t)(UINT32_C(1)<<15)) +#define _LIB9P_LOCK_FLAGS_UNUSED_14 ((lib9p_lock_flags_t)(UINT32_C(1)<<14)) +#define _LIB9P_LOCK_FLAGS_UNUSED_13 ((lib9p_lock_flags_t)(UINT32_C(1)<<13)) +#define _LIB9P_LOCK_FLAGS_UNUSED_12 ((lib9p_lock_flags_t)(UINT32_C(1)<<12)) +#define _LIB9P_LOCK_FLAGS_UNUSED_11 ((lib9p_lock_flags_t)(UINT32_C(1)<<11)) +#define _LIB9P_LOCK_FLAGS_UNUSED_10 ((lib9p_lock_flags_t)(UINT32_C(1)<<10)) +#define _LIB9P_LOCK_FLAGS_UNUSED_9 ((lib9p_lock_flags_t)(UINT32_C(1)<<9)) +#define _LIB9P_LOCK_FLAGS_UNUSED_8 ((lib9p_lock_flags_t)(UINT32_C(1)<<8)) +#define _LIB9P_LOCK_FLAGS_UNUSED_7 ((lib9p_lock_flags_t)(UINT32_C(1)<<7)) +#define _LIB9P_LOCK_FLAGS_UNUSED_6 ((lib9p_lock_flags_t)(UINT32_C(1)<<6)) +#define _LIB9P_LOCK_FLAGS_UNUSED_5 ((lib9p_lock_flags_t)(UINT32_C(1)<<5)) +#define _LIB9P_LOCK_FLAGS_UNUSED_4 ((lib9p_lock_flags_t)(UINT32_C(1)<<4)) +#define _LIB9P_LOCK_FLAGS_UNUSED_3 ((lib9p_lock_flags_t)(UINT32_C(1)<<3)) +#define _LIB9P_LOCK_FLAGS_UNUSED_2 ((lib9p_lock_flags_t)(UINT32_C(1)<<2)) +#define LIB9P_LOCK_FLAGS_RECLAIM ((lib9p_lock_flags_t)(UINT32_C(1)<<1)) +#define LIB9P_LOCK_FLAGS_BLOCK ((lib9p_lock_flags_t)(UINT32_C(1)<<0)) + +/* size = 1 ; max_iov = 1 ; max_copy = 1 */ +typedef uint8_t lib9p_lock_status_t; +#define LIB9P_LOCK_STATUS_SUCCESS ((lib9p_lock_status_t)(0)) +#define LIB9P_LOCK_STATUS_BLOCKED ((lib9p_lock_status_t)(1)) +#define LIB9P_LOCK_STATUS_ERROR ((lib9p_lock_status_t)(2)) +#define LIB9P_LOCK_STATUS_GRACE ((lib9p_lock_status_t)(3)) + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +/* min_size = 2 ; exp_size = 29 ; max_size = 65,537 ; max_iov = 2 ; max_copy = 2 */ +struct lib9p_s { + uint16_t len; + [[gnu::nonstring]] char *utf8; +}; + +/* size = 13 ; max_iov = 1 ; max_copy = 13 */ +struct lib9p_qid { + lib9p_qt_t type; + uint32_t vers; + uint64_t path; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* size = 9 ; max_iov = 1 ; max_copy = 9 */ +struct lib9p_msg_Tflush { + lib9p_tag_t tag; + uint16_t oldtag; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rflush { + lib9p_tag_t tag; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* size = 12 ; max_iov = 1 ; max_copy = 12 */ +struct lib9p_msg_Topen { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_o_t mode; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* size = 23 ; max_iov = 1 ; max_copy = 23 */ +struct lib9p_msg_Tread { + lib9p_tag_t tag; + lib9p_fid_t fid; + uint64_t offset; + uint32_t count; +}; + +/* min_size = 11 ; exp_size = 8,203 ; max_size = 2,147,483,658 ; max_iov = 2 ; max_copy = 11 */ +struct lib9p_msg_Rread { + lib9p_tag_t tag; + uint32_t count; + struct _lib9p_iovec data; +}; + +/* min_size = 23 ; exp_size = 8,215 ; max_size = 2,147,483,670 ; max_iov = 2 ; max_copy = 23 */ +struct lib9p_msg_Twrite { + lib9p_tag_t tag; + lib9p_fid_t fid; + uint64_t offset; + uint32_t count; + struct _lib9p_iovec data; +}; + +/* size = 11 ; max_iov = 1 ; max_copy = 11 */ +struct lib9p_msg_Rwrite { + lib9p_tag_t tag; + uint32_t count; +}; + +/* size = 11 ; max_iov = 1 ; max_copy = 11 */ +struct lib9p_msg_Tclunk { + lib9p_tag_t tag; + lib9p_fid_t fid; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rclunk { + lib9p_tag_t tag; +}; + +/* size = 11 ; max_iov = 1 ; max_copy = 11 */ +struct lib9p_msg_Tremove { + lib9p_tag_t tag; + lib9p_fid_t fid; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rremove { + lib9p_tag_t tag; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* size = 11 ; max_iov = 1 ; max_copy = 11 */ +struct lib9p_msg_Tstat { + lib9p_tag_t tag; + lib9p_fid_t fid; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rwstat { + lib9p_tag_t tag; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_p9p +/* size = 12 ; max_iov = 1 ; max_copy = 12 */ +struct lib9p_msg_Topenfd { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_o_t mode; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_L +/* size = 11 ; max_iov = 1 ; max_copy = 11 */ +struct lib9p_msg_Rlerror { + lib9p_tag_t tag; + lib9p_errno_t errnum; +}; + +/* size = 11 ; max_iov = 1 ; max_copy = 11 */ +struct lib9p_msg_Tstatfs { + lib9p_tag_t tag; + lib9p_fid_t fid; +}; + +/* size = 67 ; max_iov = 1 ; max_copy = 67 */ +struct lib9p_msg_Rstatfs { + lib9p_tag_t tag; + lib9p_super_magic_t type; + uint32_t bsize; + uint64_t blocks; + uint64_t bfree; + uint64_t bavail; + uint64_t files; + uint64_t ffree; + uint64_t fsid; + uint32_t namelen; +}; + +/* size = 15 ; max_iov = 1 ; max_copy = 15 */ +struct lib9p_msg_Tlopen { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_lo_t flags; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rrename { + lib9p_tag_t tag; +}; + +/* size = 11 ; max_iov = 1 ; max_copy = 11 */ +struct lib9p_msg_Treadlink { + lib9p_tag_t tag; + lib9p_fid_t fid; +}; + +/* size = 19 ; max_iov = 1 ; max_copy = 19 */ +struct lib9p_msg_Tgetattr { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_getattr_t request_mask; +}; + +/* size = 67 ; max_iov = 1 ; max_copy = 67 */ +struct lib9p_msg_Tsetattr { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_setattr_t valid; + lib9p_mode_t mode; + lib9p_nuid_t uid; + lib9p_nuid_t gid; + uint64_t filesize; + uint64_t atime_sec; + uint64_t atime_nsec; + uint64_t mtime_sec; + uint64_t mtime_nsec; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rsetattr { + lib9p_tag_t tag; +}; + +/* size = 15 ; max_iov = 1 ; max_copy = 15 */ +struct lib9p_msg_Rxattrwalk { + lib9p_tag_t tag; + uint64_t attr_size; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rxattrcreate { + lib9p_tag_t tag; +}; + +/* size = 23 ; max_iov = 1 ; max_copy = 23 */ +struct lib9p_msg_Treaddir { + lib9p_tag_t tag; + lib9p_fid_t fid; + uint64_t offset; + uint32_t count; +}; + +/* min_size = 11 ; exp_size = 8,203 ; max_size = 4,294,967,306 (warning: >UINT32_MAX) ; max_iov = 2 ; max_copy = 11 */ +struct lib9p_msg_Rreaddir { + lib9p_tag_t tag; + uint32_t count; + struct _lib9p_iovec data; +}; + +/* size = 15 ; max_iov = 1 ; max_copy = 15 */ +struct lib9p_msg_Tfsync { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_b4_t datasync; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rfsync { + lib9p_tag_t tag; +}; + +/* size = 8 ; max_iov = 1 ; max_copy = 8 */ +struct lib9p_msg_Rlock { + lib9p_tag_t tag; + lib9p_lock_status_t status; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rlink { + lib9p_tag_t tag; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rrenameat { + lib9p_tag_t tag; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Runlinkat { + lib9p_tag_t tag; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e +/* size = 15 ; max_iov = 1 ; max_copy = 15 */ +struct lib9p_msg_Tsession { + lib9p_tag_t tag; + uint64_t key; +}; + +/* size = 7 ; max_iov = 1 ; max_copy = 7 */ +struct lib9p_msg_Rsession { + lib9p_tag_t tag; +}; + +/* min_size = 11 ; exp_size = 8,203 ; max_size = 4,294,967,306 (warning: >UINT32_MAX) ; max_iov = 2 ; max_copy = 11 */ +struct lib9p_msg_Rsread { + lib9p_tag_t tag; + uint32_t count; + struct _lib9p_iovec data; +}; + +/* size = 11 ; max_iov = 1 ; max_copy = 11 */ +struct lib9p_msg_Rswrite { + lib9p_tag_t tag; + uint32_t count; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* LIB9P_VER_9P2000 : min_size = 49 ; exp_size = 157 ; max_size = 262,189 ; max_iov = 8 ; max_copy = 49 */ +/* LIB9P_VER_9P2000_e : min_size = 49 ; exp_size = 157 ; max_size = 262,189 ; max_iov = 8 ; max_copy = 49 */ +/* LIB9P_VER_9P2000_p9p: min_size = 49 ; exp_size = 157 ; max_size = 262,189 ; max_iov = 8 ; max_copy = 49 */ +/* LIB9P_VER_9P2000_u : min_size = 63 ; exp_size = 198 ; max_size = 327,738 ; max_iov = 11 ; max_copy = 63 */ +struct lib9p_stat { + uint16_t fstype; + uint32_t fsdev; + struct lib9p_qid qid; + lib9p_dm_t mode; + uint32_t atime; + uint32_t mtime; + uint64_t length; + struct lib9p_s name; + struct lib9p_s owner_uname; + struct lib9p_s owner_gname; + struct lib9p_s last_modifier_uname; +#if CONFIG_9P_ENABLE_9P2000_u + struct lib9p_s extension; + lib9p_nuid_t owner_unum; + lib9p_nuid_t owner_gnum; + lib9p_nuid_t last_modifier_unum; +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +/* min_size = 13 ; exp_size = 40 ; max_size = 65,548 ; max_iov = 2 ; max_copy = 13 */ +struct lib9p_msg_Tversion { + lib9p_tag_t tag; + uint32_t max_msg_size; + struct lib9p_s version; +}; + +/* min_size = 13 ; exp_size = 40 ; max_size = 65,548 ; max_iov = 2 ; max_copy = 13 */ +struct lib9p_msg_Rversion { + lib9p_tag_t tag; + uint32_t max_msg_size; + struct lib9p_s version; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* LIB9P_VER_9P2000 : min_size = 15 ; exp_size = 69 ; max_size = 131,085 ; max_iov = 4 ; max_copy = 15 */ +/* LIB9P_VER_9P2000_L : min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 5 ; max_copy = 19 */ +/* LIB9P_VER_9P2000_e : min_size = 15 ; exp_size = 69 ; max_size = 131,085 ; max_iov = 4 ; max_copy = 15 */ +/* LIB9P_VER_9P2000_p9p: min_size = 15 ; exp_size = 69 ; max_size = 131,085 ; max_iov = 4 ; max_copy = 15 */ +/* LIB9P_VER_9P2000_u : min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 5 ; max_copy = 19 */ +struct lib9p_msg_Tauth { + lib9p_tag_t tag; + lib9p_fid_t afid; + struct lib9p_s uname; + struct lib9p_s aname; +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + lib9p_nuid_t unum; +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ +}; + +/* size = 20 ; max_iov = 1 ; max_copy = 20 */ +struct lib9p_msg_Rauth { + lib9p_tag_t tag; + struct lib9p_qid aqid; +}; + +/* LIB9P_VER_9P2000 : min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 4 ; max_copy = 19 */ +/* LIB9P_VER_9P2000_L : min_size = 23 ; exp_size = 77 ; max_size = 131,093 ; max_iov = 5 ; max_copy = 23 */ +/* LIB9P_VER_9P2000_e : min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 4 ; max_copy = 19 */ +/* LIB9P_VER_9P2000_p9p: min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 4 ; max_copy = 19 */ +/* LIB9P_VER_9P2000_u : min_size = 23 ; exp_size = 77 ; max_size = 131,093 ; max_iov = 5 ; max_copy = 23 */ +struct lib9p_msg_Tattach { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_fid_t afid; + struct lib9p_s uname; + struct lib9p_s aname; +#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u + lib9p_nuid_t unum; +#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ +}; + +/* size = 20 ; max_iov = 1 ; max_copy = 20 */ +struct lib9p_msg_Rattach { + lib9p_tag_t tag; + struct lib9p_qid qid; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized +/* LIB9P_VER_9P2000 : min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ +/* LIB9P_VER_9P2000_e : min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ +/* LIB9P_VER_9P2000_p9p : min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ +/* LIB9P_VER_9P2000_u : min_size = 13 ; exp_size = 40 ; max_size = 65,548 ; max_iov = 3 ; max_copy = 13 */ +/* LIB9P_VER_uninitialized: min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ +struct lib9p_msg_Rerror { + lib9p_tag_t tag; + struct lib9p_s errstr; +#if CONFIG_9P_ENABLE_9P2000_u + lib9p_errno_t errnum; +#endif /* CONFIG_9P_ENABLE_9P2000_u */ +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* min_size = 17 ; exp_size = 481 ; max_size = 1,048,609 ; max_iov = 32 ; max_copy = 49 */ +struct lib9p_msg_Twalk { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_fid_t newfid; + uint16_t nwname; + struct lib9p_s *wname; +}; + +/* min_size = 9 ; exp_size = 217 ; max_size = 217 ; max_iov = 1 ; max_copy = 217 */ +struct lib9p_msg_Rwalk { + lib9p_tag_t tag; + uint16_t nwqid; + struct lib9p_qid *wqid; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* size = 24 ; max_iov = 1 ; max_copy = 24 */ +struct lib9p_msg_Ropen { + lib9p_tag_t tag; + struct lib9p_qid qid; + uint32_t iounit; +}; + +/* min_size = 18 ; exp_size = 45 ; max_size = 65,553 ; max_iov = 3 ; max_copy = 18 */ +struct lib9p_msg_Tcreate { + lib9p_tag_t tag; + lib9p_fid_t fid; + struct lib9p_s name; + lib9p_dm_t perm; + lib9p_o_t mode; +}; + +/* size = 24 ; max_iov = 1 ; max_copy = 24 */ +struct lib9p_msg_Rcreate { + lib9p_tag_t tag; + struct lib9p_qid qid; + uint32_t iounit; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ +#if CONFIG_9P_ENABLE_9P2000_p9p +/* size = 28 ; max_iov = 1 ; max_copy = 28 */ +struct lib9p_msg_Ropenfd { + lib9p_tag_t tag; + struct lib9p_qid qid; + uint32_t iounit; + uint32_t unixfd; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ +#if CONFIG_9P_ENABLE_9P2000_L +/* size = 24 ; max_iov = 1 ; max_copy = 24 */ +struct lib9p_msg_Rlopen { + lib9p_tag_t tag; + struct lib9p_qid qid; + uint32_t iounit; +}; + +/* min_size = 25 ; exp_size = 52 ; max_size = 65,560 ; max_iov = 3 ; max_copy = 25 */ +struct lib9p_msg_Tlcreate { + lib9p_tag_t tag; + lib9p_fid_t fid; + struct lib9p_s name; + lib9p_lo_t flags; + lib9p_mode_t mode; + lib9p_nuid_t gid; +}; + +/* size = 24 ; max_iov = 1 ; max_copy = 24 */ +struct lib9p_msg_Rlcreate { + lib9p_tag_t tag; + struct lib9p_qid qid; + uint32_t iounit; +}; + +/* min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 5 ; max_copy = 19 */ +struct lib9p_msg_Tsymlink { + lib9p_tag_t tag; + lib9p_fid_t fid; + struct lib9p_s name; + struct lib9p_s symtgt; + lib9p_nuid_t gid; +}; + +/* size = 20 ; max_iov = 1 ; max_copy = 20 */ +struct lib9p_msg_Rsymlink { + lib9p_tag_t tag; + struct lib9p_qid qid; +}; + +/* min_size = 29 ; exp_size = 56 ; max_size = 65,564 ; max_iov = 3 ; max_copy = 29 */ +struct lib9p_msg_Tmknod { + lib9p_tag_t tag; + lib9p_fid_t dfid; + struct lib9p_s name; + lib9p_mode_t mode; + uint32_t major; + uint32_t minor; + lib9p_nuid_t gid; +}; + +/* size = 20 ; max_iov = 1 ; max_copy = 20 */ +struct lib9p_msg_Rmknod { + lib9p_tag_t tag; + struct lib9p_qid qid; +}; + +/* min_size = 17 ; exp_size = 44 ; max_size = 65,552 ; max_iov = 2 ; max_copy = 17 */ +struct lib9p_msg_Trename { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_fid_t dfid; + struct lib9p_s name; +}; + +/* min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ +struct lib9p_msg_Rreadlink { + lib9p_tag_t tag; + struct lib9p_s target; +}; + +/* size = 160 ; max_iov = 1 ; max_copy = 160 */ +struct lib9p_msg_Rgetattr { + lib9p_tag_t tag; + lib9p_getattr_t valid; + struct lib9p_qid qid; + lib9p_mode_t mode; + lib9p_nuid_t uid; + lib9p_nuid_t gid; + uint64_t nlink; + uint64_t rdev; + uint64_t filesize; + uint64_t blksize; + uint64_t blocks; + uint64_t atime_sec; + uint64_t atime_nsec; + uint64_t mtime_sec; + uint64_t mtime_nsec; + uint64_t ctime_sec; + uint64_t ctime_nsec; + uint64_t btime_sec; + uint64_t btime_nsec; + uint64_t gen; + uint64_t data_version; +}; + +/* min_size = 17 ; exp_size = 44 ; max_size = 65,552 ; max_iov = 2 ; max_copy = 17 */ +struct lib9p_msg_Txattrwalk { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_fid_t newfid; + struct lib9p_s name; +}; + +/* min_size = 25 ; exp_size = 52 ; max_size = 65,560 ; max_iov = 3 ; max_copy = 25 */ +struct lib9p_msg_Txattrcreate { + lib9p_tag_t tag; + lib9p_fid_t fid; + struct lib9p_s name; + uint64_t attr_size; + uint32_t flags; +}; + +/* min_size = 38 ; exp_size = 65 ; max_size = 65,573 ; max_iov = 2 ; max_copy = 38 */ +struct lib9p_msg_Tlock { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_lock_type_t type; + lib9p_lock_flags_t flags; + uint64_t start; + uint64_t length; + uint32_t proc_id; + struct lib9p_s client_id; +}; + +/* min_size = 34 ; exp_size = 61 ; max_size = 65,569 ; max_iov = 2 ; max_copy = 34 */ +struct lib9p_msg_Tgetlock { + lib9p_tag_t tag; + lib9p_fid_t fid; + lib9p_lock_type_t type; + uint64_t start; + uint64_t length; + uint32_t proc_id; + struct lib9p_s client_id; +}; + +/* min_size = 30 ; exp_size = 57 ; max_size = 65,565 ; max_iov = 2 ; max_copy = 30 */ +struct lib9p_msg_Rgetlock { + lib9p_tag_t tag; + lib9p_lock_type_t type; + uint64_t start; + uint64_t length; + uint32_t proc_id; + struct lib9p_s client_id; +}; + +/* min_size = 17 ; exp_size = 44 ; max_size = 65,552 ; max_iov = 2 ; max_copy = 17 */ +struct lib9p_msg_Tlink { + lib9p_tag_t tag; + lib9p_fid_t dfid; + lib9p_fid_t fid; + struct lib9p_s name; +}; + +/* min_size = 21 ; exp_size = 48 ; max_size = 65,556 ; max_iov = 3 ; max_copy = 21 */ +struct lib9p_msg_Tmkdir { + lib9p_tag_t tag; + lib9p_fid_t dfid; + struct lib9p_s name; + lib9p_mode_t mode; + lib9p_nuid_t gid; +}; + +/* size = 20 ; max_iov = 1 ; max_copy = 20 */ +struct lib9p_msg_Rmkdir { + lib9p_tag_t tag; + struct lib9p_qid qid; +}; + +/* min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 4 ; max_copy = 19 */ +struct lib9p_msg_Trenameat { + lib9p_tag_t tag; + lib9p_fid_t olddirfid; + struct lib9p_s oldname; + lib9p_fid_t newdirfid; + struct lib9p_s newname; +}; + +/* min_size = 17 ; exp_size = 44 ; max_size = 65,552 ; max_iov = 3 ; max_copy = 17 */ +struct lib9p_msg_Tunlinkat { + lib9p_tag_t tag; + lib9p_fid_t dirfd; + struct lib9p_s name; + uint32_t flags; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000_L */ +#if CONFIG_9P_ENABLE_9P2000_e +/* min_size = 13 ; exp_size = 477 ; max_size = 4,294,967,308 (warning: >UINT32_MAX) ; max_iov = 0 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2) ; max_copy = 13 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2) */ +struct lib9p_msg_Tsread { + lib9p_tag_t tag; + uint32_t fid; + uint16_t nwname; + struct lib9p_s *wname; +}; + +/* min_size = 17 ; exp_size = 8,673 ; max_size = 8,589,934,607 (warning: >UINT32_MAX) ; max_iov = 2 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2) ; max_copy = 17 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2) */ +struct lib9p_msg_Tswrite { + lib9p_tag_t tag; + uint32_t fid; + uint16_t nwname; + struct lib9p_s *wname; + uint32_t count; + struct _lib9p_iovec data; +}; + +#endif /* CONFIG_9P_ENABLE_9P2000_e */ +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u +/* LIB9P_VER_9P2000 : min_size = 58 ; exp_size = 166 ; max_size = 262,198 ; max_iov = 8 ; max_copy = 58 */ +/* LIB9P_VER_9P2000_e : min_size = 58 ; exp_size = 166 ; max_size = 262,198 ; max_iov = 8 ; max_copy = 58 */ +/* LIB9P_VER_9P2000_p9p: min_size = 58 ; exp_size = 166 ; max_size = 262,198 ; max_iov = 8 ; max_copy = 58 */ +/* LIB9P_VER_9P2000_u : min_size = 72 ; exp_size = 207 ; max_size = 327,747 ; max_iov = 11 ; max_copy = 72 */ +struct lib9p_msg_Rstat { + lib9p_tag_t tag; + struct lib9p_stat stat; +}; + +/* LIB9P_VER_9P2000 : min_size = 62 ; exp_size = 170 ; max_size = 262,202 ; max_iov = 8 ; max_copy = 62 */ +/* LIB9P_VER_9P2000_e : min_size = 62 ; exp_size = 170 ; max_size = 262,202 ; max_iov = 8 ; max_copy = 62 */ +/* LIB9P_VER_9P2000_p9p: min_size = 62 ; exp_size = 170 ; max_size = 262,202 ; max_iov = 8 ; max_copy = 62 */ +/* LIB9P_VER_9P2000_u : min_size = 76 ; exp_size = 211 ; max_size = 327,751 ; max_iov = 11 ; max_copy = 76 */ +struct lib9p_msg_Twstat { + lib9p_tag_t tag; + lib9p_fid_t fid; + struct lib9p_stat stat; +}; +#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ + +/* containers *****************************************************************/ + +#define _LIB9P_MAX(a, b) ((a) > (b)) ? (a) : (b) + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u + #if CONFIG_9P_ENABLE_9P2000_e + #define LIB9P_TMSG_MAX_IOV _LIB9P_MAX(32, 2 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2)) + #else + #define LIB9P_TMSG_MAX_IOV 32 + #endif +#elif CONFIG_9P_ENABLE_uninitialized + #define LIB9P_TMSG_MAX_IOV 2 +#endif + +#if CONFIG_9P_ENABLE_9P2000_u + #if CONFIG_9P_ENABLE_9P2000_e + #define LIB9P_TMSG_MAX_COPY _LIB9P_MAX(76, 17 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2)) + #else + #define LIB9P_TMSG_MAX_COPY 76 + #endif +#elif CONFIG_9P_ENABLE_9P2000_L + #if CONFIG_9P_ENABLE_9P2000_e + #define LIB9P_TMSG_MAX_COPY _LIB9P_MAX(67, 17 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2)) + #else + #define LIB9P_TMSG_MAX_COPY 67 + #endif +#elif CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p + #if CONFIG_9P_ENABLE_9P2000_e + #define LIB9P_TMSG_MAX_COPY _LIB9P_MAX(62, 17 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2)) + #else + #define LIB9P_TMSG_MAX_COPY 62 + #endif +#elif CONFIG_9P_ENABLE_uninitialized + #define LIB9P_TMSG_MAX_COPY 13 +#endif + +#if CONFIG_9P_ENABLE_9P2000_u + #define LIB9P_RMSG_MAX_IOV 11 +#elif CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p + #define LIB9P_RMSG_MAX_IOV 8 +#elif CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_uninitialized + #define LIB9P_RMSG_MAX_IOV 2 +#endif + +#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u + #define LIB9P_RMSG_MAX_COPY 217 +#elif CONFIG_9P_ENABLE_uninitialized + #define LIB9P_RMSG_MAX_COPY 13 +#endif + +struct lib9p_Tmsg_send_buf { + size_t iov_cnt; + struct iovec iov[LIB9P_TMSG_MAX_IOV]; + uint8_t copied[LIB9P_TMSG_MAX_COPY]; +}; + +struct lib9p_Rmsg_send_buf { + size_t iov_cnt; + struct iovec iov[LIB9P_RMSG_MAX_IOV]; + uint8_t copied[LIB9P_RMSG_MAX_COPY]; +}; diff --git a/lib9p/include/lib9p/9p.h b/lib9p/core_include/lib9p/core.h index ffac453..9d92312 100644 --- a/lib9p/include/lib9p/9p.h +++ b/lib9p/core_include/lib9p/core.h @@ -1,23 +1,24 @@ -/* lib9p/9p.h - Base 9P protocol definitions for both clients and servers +/* lib9p/core.h - Base 9P protocol definitions for both clients and servers * * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ -#ifndef _LIB9P_9P_H_ -#define _LIB9P_9P_H_ +#ifndef _LIB9P_CORE_H_ +#define _LIB9P_CORE_H_ -#include <stdbool.h> +#include <stdint.h> /* for uint{n}_t */ +#include <string.h> /* for memset() */ #include <sys/types.h> /* for ssize_t */ +#include <libhw/generic/io.h> /* for struct iovec */ #include <libmisc/assert.h> +#include <libmisc/fmt.h> -#include <lib9p/linux-errno.h> -#include <lib9p/9p.generated.h> +#define CONFIG_9P_ENABLE_uninitialized 1 +#include "config.h" -#ifndef CONFIG_9P_MAX_ERR_SIZE - #error config.h must define CONFIG_9P_MAX_ERR_SIZE -#endif +#include <lib9p/_core_generated.h> /* _after_ other includes, including config.h */ /* constants ******************************************************************/ @@ -43,22 +44,14 @@ struct lib9p_ctx { /* negotiated */ enum lib9p_version version; uint32_t max_msg_size; - - /* state */ -#ifdef CONFIG_9P_ENABLE_9P2000_u - lib9p_errno_t err_num; -#endif - [[gnu::nonstring]] char err_msg[CONFIG_9P_MAX_ERR_SIZE]; }; -void lib9p_ctx_clear_error(struct lib9p_ctx *ctx); +/* misc utilities *************************************************************/ -bool lib9p_ctx_has_error(struct lib9p_ctx *ctx); +uint32_t lib9p_version_min_Rerror_size(enum lib9p_version); +uint32_t lib9p_version_min_Rread_size(enum lib9p_version); -/** Write an static error into ctx, return -1. */ -int lib9p_error(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *msg); -/** Write a printf-style error into ctx, return -1. */ -int lib9p_errorf(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *fmt, ...) [[gnu::format(printf, 3, 4)]]; +void fmt_print_lib9p_msg(lo_interface fmt_dest w, struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body); /* main T-message functions ***************************************************/ @@ -70,23 +63,19 @@ int lib9p_errorf(struct lib9p_ctx *ctx, lib9p_errno_t linux_errno, char const *f * number may be larger than net_bytes due to (1) struct padding, (2) * array pointers. * - * 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 ctx : negotiated protocol parameters * @param net_bytes : the complete request, starting with the "size[4]" * - * @return required size, or -1 on error + * @return required size, or an error * - * @errno LINUX_EOPNOTSUPP: message is an R-message - * @errno LINUX_EOPNOTSUPP: message has unknown type - * @errno LINUX_EBADMSG: message is wrong size for content - * @errno LINUX_EBADMSG: message contains invalid UTF-8 - * @errno LINUX_EBADMSG: message contains a bitfield with unknown bits - * @errno LINUX_EMSGSIZE: would-be return value overflows SSIZE_MAX + * @errno E_POSIX_EOPNOTSUPP: message is an R-message + * @errno E_POSIX_EOPNOTSUPP: message has unknown type + * @errno E_POSIX_EBADMSG: message is wrong size for content + * @errno E_POSIX_EILSEQ: message contains invalid UTF-8, or the UTF-8 contains a nul-byte + * @errno E_POSIX_EBADMSG: message contains a bitfield with unknown bits + * @errno E_POSIX_EMSGSIZE: would-be return value overflows SSIZE_MAX */ -ssize_t lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); +size_t_or_error lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); /** * Unmarshal the 9P message `net_bytes` into the C struct `ret_body`. @@ -112,54 +101,48 @@ void lib9p_Tmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, * marshal bitfield bits that aren't in ctx->version; it applies a * version-specific mask to bitfields. * - * @param ctx : negotiated protocol parameters, where to record errors + * @param ctx : negotiated protocol parameters * @param typ : the message type - * @param msg : the message to encode + * @param msg : the message to encode (`struct lib9p_msg_XXXX` according to `typ`) * - * @return ret_bytes : the buffer to encode to, must be at be at least ctx->max_msg_size bytes - * @return whether there was an error (false=success, true=error) + * @return ret : the buffer to encode to + * @return error * - * @errno LINUX_ERANGE: reply does not fit in ctx->max_msg_size + * @errno E_POSIX_ERANGE: reply does not fit in ctx->max_msg_size */ -bool lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, - struct lib9p_Tmsg_send_buf *ret); +error lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, + struct lib9p_Tmsg_send_buf *ret); /* main R-message functions ***************************************************/ /** Same as above, but for R-messages instead of T-messages. */ -ssize_t lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); +size_t_or_error lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); void lib9p_Rmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, enum lib9p_msg_type *ret_typ, void *ret_body); -bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, - struct lib9p_Rmsg_send_buf *ret); +error lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, + struct lib9p_Rmsg_send_buf *ret); /* `struct lib9p_stat` helpers ************************************************/ -/** Assert that a `struct lib9p_stat` object looks valid. */ -static inline void lib9p_stat_assert(struct lib9p_stat stat) { - assert( ((bool)(stat.file_mode & LIB9P_DM_DIR )) == ((bool)(stat.file_qid.type & LIB9P_QT_DIR )) ); - assert( ((bool)(stat.file_mode & LIB9P_DM_APPEND)) == ((bool)(stat.file_qid.type & LIB9P_QT_APPEND)) ); - assert( ((bool)(stat.file_mode & LIB9P_DM_EXCL )) == ((bool)(stat.file_qid.type & LIB9P_QT_EXCL )) ); - assert( ((bool)(stat.file_mode & LIB9P_DM_AUTH )) == ((bool)(stat.file_qid.type & LIB9P_QT_AUTH )) ); - assert( ((bool)(stat.file_mode & LIB9P_DM_TMP )) == ((bool)(stat.file_qid.type & LIB9P_QT_TMP )) ); - assert( (stat.file_size == 0) || !(stat.file_mode & LIB9P_DM_DIR) ); -} +#if _LIB9P_ENABLE_stat + +void fmt_print_lib9p_stat(lo_interface fmt_dest w, struct lib9p_ctx *ctx, struct lib9p_stat *stat); /** * Validate a message's `stat` structure. * - * @param ctx : negotiated protocol parameters, where to record errors + * @param ctx : negotiated protocol parameters * @param net_bytes : network-encoded stat structure * @param net_size : the number of net_bytes that may be read * * @return ret_net_size : number of bytes consumed; <=net_size * @return ret_host_size : number of bytes that lib9p_stat_unmarshal would take - * @return whether there was an error + * @return error */ -bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, - uint32_t *ret_net_size, ssize_t *ret_host_size); +error 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); /** * Unmarshal the 9P `net_bytes` into the C struct `ret_obj`. @@ -184,16 +167,15 @@ void lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, * marshal bitfield bits that aren't in ctx->version; it applies a * version-specific mask to bitfields. * - * @param ctx : negotiated protocol parameters, where to record errors + * @param ctx : negotiated protocol parameters * @param max_net_size : the maximum network-encoded size to allow * @param obj : the message to encode * * @return ret_bytes: the buffer to encode into * @return the number of bytes written, or 0 if the stat object does not fit in max_net_size - * - * @errno LINUX_ERANGE: reply does not fit in max_net_size */ uint32_t lib9p_stat_marshal(struct lib9p_ctx *ctx, uint32_t max_net_size, struct lib9p_stat *obj, uint8_t *ret_bytes); +#endif -#endif /* _LIB9P_9P_H_ */ +#endif /* _LIB9P_CORE_H_ */ diff --git a/lib9p/core_tables.h b/lib9p/core_tables.h new file mode 100644 index 0000000..8f8c8d6 --- /dev/null +++ b/lib9p/core_tables.h @@ -0,0 +1,62 @@ +/* lib9p/core_tables.h - Declare tables of version and message information + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_CORE_TABLES_H_ +#define _LIB9P_CORE_TABLES_H_ + +#include <lib9p/core.h> + +/* version ********************************************************************/ + +struct _lib9p_ver_tentry { + const char *name; + uint32_t min_Rerror_size; + uint32_t min_Rread_size; +}; + +extern const struct _lib9p_ver_tentry _lib9p_table_ver[LIB9P_VER_NUM]; + +/* message ********************************************************************/ + +typedef void (*_print_fn_t)(lo_interface fmt_dest, struct lib9p_ctx *, void *); +struct _lib9p_msg_tentry { + const char *name; + _print_fn_t print; +}; + +typedef size_t_or_error (*_validate_fn_t)(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes); +typedef void (*_unmarshal_fn_t)(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out); +struct _lib9p_recv_tentry { + _validate_fn_t validate; + _unmarshal_fn_t unmarshal; +}; + +struct _marshal_ret { + size_t net_iov_cnt; + struct iovec *net_iov; + size_t net_copied_size; + uint8_t *net_copied; +}; +typedef error (*_marshal_fn_t)(struct lib9p_ctx *ctx, void *host_val, struct _marshal_ret *ret); +struct _lib9p_send_tentry { + _marshal_fn_t marshal; +}; + +extern const struct _lib9p_msg_tentry _lib9p_table_msg[LIB9P_VER_NUM][0x100]; +extern const struct _lib9p_recv_tentry _lib9p_table_Tmsg_recv[LIB9P_VER_NUM][0x80]; +extern const struct _lib9p_recv_tentry _lib9p_table_Rmsg_recv[LIB9P_VER_NUM][0x80]; +extern const struct _lib9p_send_tentry _lib9p_table_Tmsg_send[LIB9P_VER_NUM][0x80]; +extern const struct _lib9p_send_tentry _lib9p_table_Rmsg_send[LIB9P_VER_NUM][0x80]; + +/* stat ***********************************************************************/ + +#if _LIB9P_ENABLE_stat +size_t_or_error _lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size); +void _lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out); +bool _lib9p_stat_marshal(struct lib9p_ctx *ctx, struct lib9p_stat *val, struct _marshal_ret *ret); +#endif + +#endif /* _LIB9P_CORE_TABLES_H_ */ diff --git a/lib9p/idl/0000-README.md b/lib9p/idl/0000-README.md index e19a1e8..84cf865 100644 --- a/lib9p/idl/0000-README.md +++ b/lib9p/idl/0000-README.md @@ -17,35 +17,62 @@ client->server requests, and R-messages are server->client responses type of a message is represented by a u8 ID; T-messages are even and R-messages are odd. -Messages are made up of the primitives; unsigned little-endian -integers, identified with the following single-character mnemonics: +9P messages are exchanged over a reliable bidirectional in-order octet +stream. Messages are made up of the primitives; unsigned +little-endian integers, identified with the following single-character +mnemonics: - 1 = u8 - 2 = u16le - 4 = u32le - 8 = u16le -Out of these primitives, we can make other numeric types, +Out of these primitives, we can make more complex types: + +## User-defined types + +### Numeric types num NUMNAME = PRIMITIVE_TYPE + "NAME=VAL"... + +Besides just being an alias for a primitive type, a numeric type may +define 0 or more named constants of that type, each wrapped in +"quotes". + +### Bitfields -bitfields, + bitfield BFNAME = PRIMITIVE_TYPE + "bit NBIT=NAME"... + "bit NBIT=reserved(NAME)"... + "bit NBIT=num(NUMNAME)"... + "alias NAME=VAL"... + "mask NAME=VAL"... + "num(NUMNAME) NAME=VAL"... - bitfield BFNAME = PRIMITIVE_TYPE "NBIT=NAME... ALIAS=VAL..." +The same NBIT may not be defined multiple times. The same NAME may +not be defined multiple times. -structures, + - A `reserved(...)` bit indicates that the bit is named but is not + allowed to be used. + - `num(...)` bits embed a numeric/enumerated field within a set of + bits. Once several bits have been allocated to a numeric field + with `bit NBIT=num(NUMNAME)`, constant values for that field may be + declared with `num(NUMNAME) NAME=VAL`. For each numeric field, a + `mask NUMNAME=BITMASK` is automatically declared. + - A `mask` defines a bitmask that selects several bits. + - An `alias` defines a convenience alias for a bit or set of bits. + +### Structures struct STRUCTNAME = "FIELDNAME[FIELDTYPE]..." -and messages (which are a special-case of structures). +Or a special-case for structs that are messages; `msg` has the same +syntax as `struct`, but has restrictions on the STRUCTNAME and the +first 3 fields must all be declared in the same way: msg Tname = "size[4,val=end-&size] typ[1,val=TYP] tag[tag] REST..." -Bitfield bit names may be wrapped in `reserved(...)` or -`subfield(...)`; reserved indicates that the bit is named but is not -allowed to be used, and subfield indicates that the bit is part of a -num/enum that is handled by an alias. - Struct fields that have numeric types (either primitives or `num` types) can add to their type `,val=` and/or `,max=` to specify what the exact value must be and/or what the maximum (inclusive) value is. @@ -59,11 +86,13 @@ can be - `&fieldname` to refer to the offset of a field name in that struct, - the special value `end` to refer to the offset of the end of the struct, - - the special value `s32_max` to refer to the constant value - `(1<<31)-1`, or - - the special value `s64_max` to refer to the constant value - `(1<<63)-1` + - the special value `u{8,16,32,64}_max` to refer to the constant + value `(1<<{n})-1`, or + - the special value `s{8,16,32,64}_max` to refer to the constant value + `(1<<({n}-1))-1`. + +## Parser A parser for this syntax is given in `__init__.py`. However, `__init__.py` places the somewhat arbitrary undocumented restrictions -on fields referenced as the count for a repeated field. +on fields referenced as the count of a repeated field. diff --git a/lib9p/idl/0000-TODO.md b/lib9p/idl/0000-TODO.md index 81cafe5..e52902f 100644 --- a/lib9p/idl/0000-TODO.md +++ b/lib9p/idl/0000-TODO.md @@ -9,5 +9,3 @@ - Decide how to handle duplicate type names from different versions - Decide how to handle duplicate `enum lib9p_msg_type` names and values -- Clean up the iterate-over-all-msgids-in-a-version code -- Allow for const `.cnt` instead of only having previous-member `.cnt` diff --git a/lib9p/idl/0000-uninitialized.9p b/lib9p/idl/0000-uninitialized.9p new file mode 100644 index 0000000..193cb19 --- /dev/null +++ b/lib9p/idl/0000-uninitialized.9p @@ -0,0 +1,13 @@ +# lib9p/idl/0000-uninitialized.9p - Defs for bootstrapping +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +version "uninitialized" + +# For the actual protocol. +from ./2002-9P2000.9p import s, tag +from ./2002-9P2000.9p import Tversion, Rversion, Rerror + +# For srv.h +from ./2002-9P2000.9p import dm, qt, qid, fid diff --git a/lib9p/idl/1992-9P0.9p.wip b/lib9p/idl/1992-9P0.9p.wip index 086e8e4..c9432c9 100644 --- a/lib9p/idl/1992-9P0.9p.wip +++ b/lib9p/idl/1992-9P0.9p.wip @@ -37,40 +37,40 @@ struct errstr = "64*(txt[1])" # "O"pen flags (flags to pass to Topen and Tcreate) # Unused bits are *ignored*. bitfield o = 1 - "0=mode_0" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum - "1=mode_1" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum - #"2=unused" - #"3=unused" - "4=TRUNC" - #"5=_reserved_CEXEC" # close-on-exec - "6=RCLOSE" # remove-on-close - #"7=unused" + "bit 0=num(MODE)" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum + "bit 1=num(MODE)" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum + #"bit 2=unused" + #"bit 3=unused" + "bit 4=TRUNC" + "bit 5=reserved(CEXEC)" # close-on-exec + "bit 6=RCLOSE" # remove-on-close + #"bit 7=unused" - "READ = 0" # make available for this FID: Tread() - "WRITE = 1" # make available for this FID: Twrite() - "RDWR = 2" # make available for this FID: Tread() and Twrite() - "EXEC = 3" # make available for this FID: Tread() + "num(MODE) READ = 0" # make available for this FID: Tread() + "num(MODE) WRITE = 1" # make available for this FID: Twrite() + "num(MODE) RDWR = 2" # make available for this FID: Tread() and Twrite() + "num(MODE) EXEC = 3" # make available for this FID: Tread() - "MODE_MASK = 0b00000011" - "FLAG_MASK = 0b11111100" + "mask FLAG = 0b11111100" -# "C"??? "H"??? - file permissions and attributes +# "CH"annel flags - file permissions and attributes (a "channel" is +# what a file handle is called inside of the Plan 9 kernel). bitfield ch = 4 - "31=DIR" - "30=APPEND" - "29=EXCL" + "bit 31=DIR" + "bit 30=APPEND" + "bit 29=EXCL" #... - "8=OWNER_R" - "7=OWNER_W" - "6=OWNER_X" - "5=GROUP_R" - "4=GROUP_W" - "3=GROUP_X" - "2=OTHER_R" - "1=OTHER_W" - "0=OTHER_X" + "bit 8=OWNER_R" + "bit 7=OWNER_W" + "bit 6=OWNER_X" + "bit 5=GROUP_R" + "bit 4=GROUP_W" + "bit 3=GROUP_X" + "bit 2=OTHER_R" + "bit 1=OTHER_W" + "bit 0=OTHER_X" - "PERM_MASK=0777" # {OWNER,GROUP,OTHER}_{R,W,X} + "mask PERM=0777" # {OWNER,GROUP,OTHER}_{R,W,X} struct stat = "file_name[name]" "file_owner[name]" @@ -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/1995-9P1.9p.wip b/lib9p/idl/1995-9P1.9p.wip index 2caf39d..660e24a 100644 --- a/lib9p/idl/1995-9P1.9p.wip +++ b/lib9p/idl/1995-9P1.9p.wip @@ -43,7 +43,7 @@ from ./1992-9P0.9p import tag, fid, qid, name, errstr, o, ch, stat # draft RFC). As I understand it, CHMOUNT indicates that the file is # mounted by the kernel as a 9P transport; that the kernel has a lock # on doing I/O on it, so userspace can't do I/O on it. -bitfield ch += "28=MOUNT" +bitfield ch += "bit 28=_PLAN9_MOUNT" # Authentication uses DES encryption. The client obtains a ticket and # a nonce-key from a separate auth-server; how it does this is beyond diff --git a/lib9p/idl/1996-Styx.9p.wip b/lib9p/idl/1996-Styx.9p.wip index 6ba4509..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]" @@ -40,7 +40,7 @@ msg Ropen = "typ[1,val=11] tag[tag] fid[fid] qid[qid]" msg Tcreate = "typ[1,val=12] tag[tag] fid[fid] name[name] perm[ch] mode[o]" msg Rcreate = "typ[1,val=13] tag[tag] fid[fid] qid[qid]" # For `offset:max`, see `fs.c` `f_read()` and `f_write()`. -# For `count:max`, see `styx.h:MAXFDATA'. +# For `count:max`, see `styx.h:MAXFDATA`. msg Tread = "typ[1,val=14] tag[tag] fid[fid] offset[8,max=s64_max] count[2,max=8192]" msg Rread = "typ[1,val=15] tag[tag] fid[fid] count[2,max=8192] pad[1] count*(data[1])" msg Twrite = "typ[1,val=16] tag[tag] fid[fid] offset[8,max=s64_max] count[2,max=8192] pad[1] count*(data[1])" diff --git a/lib9p/idl/2002-9P2000.9p b/lib9p/idl/2002-9P2000.9p index 2a4f7ed..712ffea 100644 --- a/lib9p/idl/2002-9P2000.9p +++ b/lib9p/idl/2002-9P2000.9p @@ -22,64 +22,64 @@ version "9P2000" # tag - identify a request/response pair num tag = 2 - "NOTAG = ~0" + "NOTAG = u16_max" # file identifier - like a UNIX file-descriptor num fid = 4 - "NOFID = ~0" + "NOFID = u32_max" # string - u16le `n`, then `n` bytes of UTF-8, without any nul-bytes struct s = "len[2] len*(utf8[1])" # "D"ir-entry "M"ode - file permissions and attributes bitfield dm = 4 - "31=DIR" - "30=APPEND" - "29=EXCL" - # DMMOUNT has been around in Plan 9 forever (CHMOUNT in <4e), + "bit 31=DIR" + "bit 30=APPEND" + "bit 29=EXCL" + # DMMOUNT has been around in Plan 9 since 2e (CHMOUNT in <4e), # but is undocumented, and is explicitly excluded from the # 9P2000 draft RFC. As I understand it, DMMOUNT indicates # that the file is mounted by the kernel as a 9P transport; # that the kernel has a lock on doing I/O on it, so userspace # can't do I/O on it. - "28=reserved(PLAN9_MOUNT)" - "27=AUTH" - "26=TMP" + "bit 28=_PLAN9_MOUNT" + "bit 27=AUTH" + "bit 26=TMP" #... - "8=OWNER_R" - "7=OWNER_W" - "6=OWNER_X" - "5=GROUP_R" - "4=GROUP_W" - "3=GROUP_X" - "2=OTHER_R" - "1=OTHER_W" - "0=OTHER_X" + "bit 8=OWNER_R" + "bit 7=OWNER_W" + "bit 6=OWNER_X" + "bit 5=GROUP_R" + "bit 4=GROUP_W" + "bit 3=GROUP_X" + "bit 2=OTHER_R" + "bit 1=OTHER_W" + "bit 0=OTHER_X" - "PERM_MASK=0777" # {OWNER,GROUP,OTHER}_{R,W,X} + "mask PERM=0777" # {OWNER,GROUP,OTHER}_{R,W,X} # QID Type - see `struct qid` below bitfield qt = 1 - "7=DIR" - "6=APPEND" - "5=EXCL" - "4=reserved(PLAN9_MOUNT)" # See "PLAN9_MOUNT" in "dm" above. - "3=AUTH" + "bit 7=DIR" + "bit 6=APPEND" + "bit 5=EXCL" + "bit 4=_PLAN9_MOUNT" # See "_PLAN9_MOUNT" in "dm" above. + "bit 3=AUTH" # Fun historical fact: QTTMP was a relatively late addition to # Plan 9, in 2003-12. - "2=TMP" - #"1=unused" + "bit 2=TMP" + #"bit 1=unused" # "The name QTFILE, defined to be zero, identifies the value # of the type for a plain file." - "FILE=0" + "alias FILE=0" # uni"Q"ue "ID"entification - "two files on the same server hierarchy # are the same if and only if their qids are the same" # # - "path" is a unique uint64_t that does most of the work in the # above statement about files being the same if their QIDs are the -# same; " If a file is deleted and recreated with the same name in +# same; "If a file is deleted and recreated with the same name in # the same directory, the old and new path components of the qids # should be different" # @@ -91,38 +91,45 @@ bitfield qt = 1 struct qid = "type[qt] vers[4] path[8]" # stat - file status -struct stat = "stat_size[2,val=end-&kern_type]" - "kern_type[2]" - "kern_dev[4]" - "file_qid[qid]" - "file_mode[dm]" - "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]" +struct stat = "_stat_size[2,val=end-&fstype]" + # fstype and fsdev are documented simply as "for kernel + # use". The are ignored by Plan 9's in-kernel 9P + # client; mntdirfix() overwrites them with fstype='M' + # and fsdev=nonce. Processes may observe values other + # than fstype='M', as 'M' is used for actual 9P servers, + # while other values are used for in-kernel device + # servers (such as '|' for pipes, or 'I' for the IP + # stack). + "fstype[2]" # filesystem type + "fsdev[4]" # filesystem instance/subtype + "qid[qid]" + "mode[dm]" + "atime[4]" + "mtime[4]" + "length[8]" # 0 for directories + "name[s]" + "owner_uname[s]" + "owner_gname[s]" + "last_modifier_uname[s]" # "O"pen flags (flags to pass to Topen and Tcreate) # Unused bits *must* be 0. bitfield o = 1 - "0=subfield(mode)" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum - "1=subfield(mode)" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum - #"2=unused" - #"3=unused" - "4=TRUNC" - "5=reserved(CEXEC)" # close-on-exec - "6=RCLOSE" # remove-on-close - #"7=unused" + "bit 0=num(MODE)" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum + "bit 1=num(MODE)" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum + #"bit 2=unused" + #"bit 3=unused" + "bit 4=TRUNC" + "bit 5=reserved(CEXEC)" # close-on-exec + "bit 6=RCLOSE" # remove-on-close + #"bit 7=unused" - "READ = 0" # make available for this FID: Tread() - "WRITE = 1" # make available for this FID: Twrite() - "RDWR = 2" # make available for this FID: Tread() and Twrite() - "EXEC = 3" # make available for this FID: Tread() + "num(MODE) READ = 0" # make available for this FID: Tread() + "num(MODE) WRITE = 1" # make available for this FID: Twrite() + "num(MODE) RDWR = 2" # make available for this FID: Tread() and Twrite() + "num(MODE) EXEC = 3" # make available for this FID: Tread() - "MODE_MASK = 0b00000011" - "FLAG_MASK = 0b11111100" + "mask FLAG = 0b11111100" # A 9P2000 session goes: # @@ -138,7 +145,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 fefe3e9..446385c 100644 --- a/lib9p/idl/2005-9P2000.u.9p +++ b/lib9p/idl/2005-9P2000.u.9p @@ -12,25 +12,25 @@ from ./2002-9P2000.9p import * # numeric user ID num nuid = 4 - "NONUID = ~0" + "NONUID = u32_max" num errno = 4 "NOERROR = 0" -struct stat += "file_extension[s]" - "file_owner_n_uid[nuid]" - "file_owner_n_gid[nuid]" - "file_last_modified_n_uid[nuid]" +struct stat += "extension[s]" + "owner_unum[nuid]" + "owner_gnum[nuid]" + "last_modifier_unum[nuid]" -msg Tauth += "n_uid[nuid]" -msg Tattach += "n_uid[nuid]" +msg Tauth += "unum[nuid]" +msg Tattach += "unum[nuid]" -msg Rerror += "errno[errno]" +msg Rerror += "errnum[errno]" -bitfield dm += "23=DEVICE" - "21=NAMEDPIPE" - "20=SOCKET" - "19=SETUID" - "18=SETGID" +bitfield dm += "bit 23=DEVICE" + "bit 21=PIPE" + "bit 20=SOCKET" + "bit 19=SETUID" + "bit 18=SETGID" -bitfield qt += "1=SYMLINK" +bitfield qt += "bit 1=SYMLINK" diff --git a/lib9p/idl/2010-9P2000.L.9p b/lib9p/idl/2010-9P2000.L.9p index 7ac86a6..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). @@ -39,49 +179,48 @@ num super_magic = 4 # protocol.h (and are different than the Linux kernel's values, which # vary by architecture). bitfield lo = 4 - "0=subfield(mode)" # low bit of the 2-bit RDONLY/WRONLY/RDWR/NOACCESS enum - "1=subfield(mode)" # high bit of the 2-bit RDONLY/WRONLY/RDWR/NOACCESS enum - #"2=unused" - #"3=unused" - #"4=unused" - #"5=unused" - "6=CREATE" - "7=EXCL" - "8=NOCTTY" - "9=TRUNC" - "10=APPEND" - "11=NONBLOCK" - "12=DSYNC" - "13=BSD_FASYNC" - "14=DIRECT" - "15=LARGEFILE" - "16=DIRECTORY" - "17=NOFOLLOW" - "18=NOATIME" - "19=CLOEXEC" - "20=SYNC" - - "RDONLY = 0" - "WRONLY = 1" - "RDWR = 2" - "NOACCESS = 3" - - "MODE_MASK = 0b000000000000000000011" - "FLAG_MASK = 0b111111111111111000000" + "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" - "NAMED_PIPE = 1" - "CHAR_DEV = 2" - "DIRECTORY = 4" - "BLOCK_DEV = 6" - "REGULAR = 8" - "SYMLINK = 10" - "SOCKET = 12" - "WHITEOUT = 14" + "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 # @@ -89,34 +228,33 @@ num dt = 1 # instead of just 16? Who knows? bitfield mode = 4 #... - "15=subfield(fmt)" # bit of the 4-bit FMT_ enum - "14=subfield(fmt)" # bit of the 4-bit FMT_ enum - "13=subfield(fmt)" # bit of the 4-bit FMT_ enum - "12=subfield(fmt)" # bit of the 4-bit FMT_ enum + "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 #... - "11=PERM_SETGROUP" - "10=PERM_SETUSER" - "9=PERM_STICKY" - "8=PERM_OWNER_R" - "7=PERM_OWNER_W" - "6=PERM_OWNER_X" - "5=PERM_GROUP_R" - "4=PERM_GROUP_W" - "3=PERM_GROUP_X" - "2=PERM_OTHER_R" - "1=PERM_OTHER_W" - "0=PERM_OTHER_X" - - "FMT_NAMED_PIPE = LIB9P_DT_NAMED_PIPE<<12" - "FMT_CHAR_DEV = LIB9P_DT_CHAR_DEV<<12" - "FMT_DIRECTORY = LIB9P_DT_DIRECTORY<<12" - "FMT_BLOCK_DEV = LIB9P_DT_BLOCK_DEV<<12" - "FMT_REGULAR = LIB9P_DT_REGULAR<<12" - "FMT_SYMLINK = LIB9P_DT_SYMLINK<<12" - "FMT_SOCKET = LIB9P_DT_SOCKET<<12" - - "PERM_MASK = 0000777" # PERM_* - "FMT_MASK = 0170000" # _fmt_* + "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 @@ -125,35 +263,35 @@ num b4 = 4 # all other values are true also bitfield getattr = 8 - "0=MODE" - "1=NLINK" - "2=UID" - "3=GID" - "4=RDEV" - "5=ATIME" - "6=MTIME" - "7=CTIME" - "8=INO" - "9=SIZE" - "10=BLOCKS" - - "11=BTIME" - "12=GEN" - "13=DATA_VERSION" - - "BASIC=0x000007ff" # Mask for fields up to BLOCKS - "ALL =0x00003fff" # Mask for All fields above + "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 - "0=MODE" - "1=UID" - "2=GID" - "3=SIZE" - "4=ATIME" - "5=MTIME" - "6=CTIME" - "7=ATIME_SET" - "8=MTIME_SET" + "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" @@ -161,8 +299,8 @@ num lock_type = 1 "UNLCK=2" bitfield lock_flags = 4 - "0=BLOCK" - "1=RECLAIM" + "bit 0=BLOCK" + "bit 1=RECLAIM" num lock_status = 1 "SUCCESS=0" @@ -170,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..f0bdb6b --- /dev/null +++ b/lib9p/idl/2010-9P2000.L.9p.gen @@ -0,0 +1,282 @@ +#!/usr/bin/env python3 +# 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 e7b3670..3133cc4 100644 --- a/lib9p/idl/__init__.py +++ b/lib9p/idl/__init__.py @@ -15,14 +15,27 @@ __all__ = [ # types "Type", "Primitive", + *["Expr", "ExprTok", "ExprOp", "ExprLit", "ExprSym", "ExprOff", "ExprNum"], "Number", - *["Bitfield", "Bit", "BitCat", "BitAlias"], - *["Struct", "StructMember", "Expr", "ExprOp", "ExprSym", "ExprLit"], + *["Bitfield", "Bit", "BitCat", "BitNum", "BitAlias"], + *["Struct", "StructMember"], "Message", ] # The syntax that this parses is described in `./0000-README.md`. +# Utilities #################################################################### + + +def get_type(env: dict[str, "Type"], name: str, tc: type["T"]) -> "T": + if name not in env: + raise NameError(f"Unknown type {name!r}") + ret = env[name] + if (not isinstance(ret, tc)) or (ret.__class__.__name__ != tc.__name__): + raise NameError(f"Type {ret.typname!r} is not a {tc.__name__}") + return ret + + # Types ######################################################################## @@ -51,13 +64,129 @@ class Primitive(enum.Enum): return self.value +class ExprOp: + op: typing.Literal["-", "+", "<<"] + + def __init__(self, op: typing.Literal["-", "+", "<<"]) -> None: + self.op = op + + +class ExprLit: + val: int + + def __init__(self, val: int) -> None: + self.val = val + + +class ExprSym: + symname: str + + def __init__(self, name: str) -> None: + self.symname = name + + +class ExprOff: + membname: str + + def __init__(self, name: str) -> None: + self.membname = name + + +class ExprNum: + numname: str + valname: str + + def __init__(self, numname: str, valname: str) -> None: + self.numname = numname + self.valname = valname + + +type ExprTok = ExprOp | ExprLit | ExprSym | ExprOff | ExprNum + + +class Expr: + tokens: typing.Sequence[ExprTok] + const: int | None + + def __init__( + self, env: dict[str, "Type"], tokens: typing.Sequence[ExprTok] = () + ) -> None: + self.tokens = tokens + self.const = self._const(env, tokens) + + def _const( + self, env: dict[str, "Type"], toks: typing.Sequence[ExprTok] + ) -> int | None: + if not toks: + return None + + def read_val() -> int | None: + nonlocal toks + assert toks + neg = False + match toks[0]: + case ExprOp(op="-"): + neg = True + toks = toks[1:] + assert not isinstance(toks[0], ExprOp) + val: int + match toks[0]: + case ExprLit(): + val = toks[0].val + case ExprSym(): + if m := re.fullmatch(r"^u(8|16|32|64)_max$", toks[0].symname): + n = int(m.group(1)) + val = (1 << n) - 1 + elif m := re.fullmatch(r"^s(8|16|32|64)_max$", toks[0].symname): + n = int(m.group(1)) + val = (1 << (n - 1)) - 1 + else: + return None + case ExprOff(): + return None + case ExprNum(): + num = get_type(env, toks[0].numname, Number) + if toks[0].valname not in num.vals: + raise NameError( + f"Type {toks[0].numname!r} does not have a value {toks[0].valname!r}" + ) + _val = num.vals[toks[0].valname].const + if _val is None: + return None + val = _val + toks = toks[1:] + return -val if neg else val + + ret = read_val() + if ret is None: + return None + while toks: + assert isinstance(toks[0], ExprOp) + op = toks[0].op + toks = toks[1:] + operand = read_val() + if operand is None: + return None + match op: + case "+": + ret = ret + operand + case "-": + ret = ret - operand + case "<<": + ret = ret << operand + return ret + + def __bool__(self) -> bool: + return len(self.tokens) > 0 + + class Number: typname: str in_versions: set[str] prim: Primitive - vals: dict[str, str] + vals: dict[str, Expr] def __init__(self) -> None: self.in_versions = set() @@ -74,11 +203,31 @@ class Number: return self.static_size -class BitCat(enum.Enum): - UNUSED = 1 - USED = 2 - RESERVED = 3 - SUBFIELD = 4 +class BitAlias: + bitname: str + in_versions: set[str] + val: Expr + + def __init__(self, name: str, val: Expr) -> None: + if val.const is None: + raise ValueError(f"{name!r} value is not constant") + self.bitname = name + self.in_versions = set() + self.val = val + + +class BitNum: + numname: str + mask: int + vals: dict[str, BitAlias] + + def __init__(self, name: str) -> None: + self.numname = name + self.mask = 0 + self.vals = {} + + +type BitCat = typing.Literal["UNUSED", "USED", "RESERVED"] | BitNum class Bit: @@ -91,33 +240,32 @@ class Bit: self.bitname = "" self.in_versions = set() self.num = num - self.cat = BitCat.UNUSED - - -class BitAlias: - bitname: str - in_versions: set[str] - val: str # FIXME: Don't have bitfield aliases be raw C expressions - - def __init__(self, name: str, val: str) -> None: - self.bitname = name - self.in_versions = set() - self.val = val + self.cat = "UNUSED" class Bitfield: typname: str in_versions: set[str] prim: Primitive + bits: list[Bit] - names: dict[str, Bit | BitAlias] + nums: dict[str, BitNum] + masks: dict[str, BitAlias] + aliases: dict[str, BitAlias] + + names: set[str] def __init__(self, name: str, prim: Primitive) -> None: self.typname = name self.in_versions = set() self.prim = prim + self.bits = [Bit(i) for i in range(prim.static_size * 8)] - self.names = {} + self.nums = {} + self.masks = {} + self.aliases = {} + + self.names = set() @property def static_size(self) -> int: @@ -130,40 +278,9 @@ class Bitfield: return self.static_size -class ExprLit: - val: int - - def __init__(self, val: int) -> None: - self.val = val - - -class ExprSym: - symname: str - - def __init__(self, name: str) -> None: - self.symname = name - - -class ExprOp: - op: typing.Literal["-", "+"] - - def __init__(self, op: typing.Literal["-", "+"]) -> None: - self.op = op - - -class Expr: - tokens: list[ExprLit | ExprSym | ExprOp] - - def __init__(self) -> None: - self.tokens = [] - - def __bool__(self) -> bool: - return len(self.tokens) > 0 - - class StructMember: # from left-to-right when parsing - cnt: "StructMember | None" = None + cnt: "StructMember| int | None" = None membname: str typ: "Type" max: Expr @@ -174,6 +291,8 @@ class StructMember: @property def min_cnt(self) -> int: assert self.cnt + if isinstance(self.cnt, int): + return self.cnt if not isinstance(self.cnt.typ, Primitive): raise ValueError( f"list count must be an integer type: {self.cnt.membname!r}" @@ -185,6 +304,8 @@ class StructMember: @property def max_cnt(self) -> int: assert self.cnt + if isinstance(self.cnt, int): + return self.cnt if not isinstance(self.cnt.typ, Primitive): raise ValueError( f"list count must be an integer type: {self.cnt.membname!r}" @@ -193,21 +314,12 @@ class StructMember: raise ValueError(f"list count may not have ,val=: {self.cnt.membname!r}") if self.cnt.max: # TODO: be more flexible? - if len(self.cnt.max.tokens) != 1: + val = self.cnt.max.const + if val is None: raise ValueError( - f"list count ,max= may only have 1 token: {self.cnt.membname!r}" + f"list count ,max= must be a constant value: {self.cnt.membname!r}" ) - match tok := self.cnt.max.tokens[0]: - case ExprLit(): - return tok.val - case ExprSym(symname="s32_max"): - return (1 << 31) - 1 - case ExprSym(symname="s64_max"): - return (1 << 63) - 1 - case _: - raise ValueError( - f'list count ,max= only allows literal, "s32_max", and "s64_max" tokens: {self.cnt.membname!r}' - ) + return val return (1 << (self.cnt.typ.value * 8)) - 1 @property @@ -279,6 +391,8 @@ T = typing.TypeVar("T", Number, Bitfield, Struct, Message) # Parse ######################################################################## +# common elements ###################### + re_priname = "(?:1|2|4|8)" # primitive names re_symname = "(?:[a-zA-Z_][a-zA-Z_0-9]*)" # "symbol" names; most *.9p-defined names re_symname_u = "(?:[A-Z_][A-Z_0-9]*)" # upper-case "symbol" names; bit names @@ -288,99 +402,186 @@ re_msgname = r"(?:[TR][a-zA-Z_0-9]*)" # names a message can be re_memtype = f"(?:{re_symname}|{re_priname})" # typenames that a struct member can be -re_expr = f"(?:(?:-|\\+|[0-9]+|&?{re_symname})+)" +valid_syms = [ + "end", + "u8_max", + "u16_max", + "u32_max", + "u64_max", + "s8_max", + "s16_max", + "s32_max", + "s64_max", +] -re_numspec = f"(?P<name>{re_symname})\\s*=\\s*(?P<val>\\S+)" +_re_expr_op = r"(?:-|\+|<<)" -re_bitspec_bit = ( - "(?P<bitnum>[0-9]+)\\s*=\\s*(?:" +_res_expr_val = { + "lit_2": r"0b[01]+", + "lit_8": r"0[0-7]+", + "lit_10": r"0(?![0-9bxX])|[1-9][0-9]*", + "lit_16": r"0[xX][0-9a-fA-F]+", + "sym": "|".join(valid_syms), # pre-defined symbols + "off": f"&{re_symname}", # offset of a field this struct + "num": f"{re_symname}\\.{re_symname}", # `num` values +} + +re_expr_tok = ( + "(?:" + "|".join( [ - f"(?P<name_used>{re_symname_u})", - f"reserved\\((?P<name_reserved>{re_symname_u})\\)", - f"subfield\\((?P<name_subfield>{re_symname_l})\\)", + f"(?P<op>{_re_expr_op})", + *[f"(?P<{k}>{v})" for k, v in _res_expr_val.items()], ] ) + ")" ) -re_bitspec_alias = f"(?P<name>{re_symname_u})\\s*=\\s*(?P<val>\\S+)" -re_memberspec = f"(?:(?P<cnt>{re_symname})\\*\\()?(?P<name>{re_symname})\\[(?P<typ>{re_memtype})(?:,max=(?P<max>{re_expr})|,val=(?P<val>{re_expr}))*\\]\\)?" +_re_expr_val = "(?:" + "|".join(_res_expr_val.values()) + ")" + +re_expr = f"(?:\\s*(?:-\\s*)?{_re_expr_val}\\s*(?:{_re_expr_op}\\s*(?:-\\s*)?{_re_expr_val}\\s*)*)" + +def parse_expr(env: dict[str, Type], expr: str) -> Expr: + assert re.fullmatch(re_expr, expr) + tokens: list[ExprTok] = [] + for m in re.finditer(re_expr_tok, expr): + if tok := m.group("op"): + tokens.append(ExprOp(typing.cast(typing.Literal["-", "+", "<<"], tok))) + elif tok := m.group("lit_2"): + tokens.append(ExprLit(int(tok[2:], 2))) + elif tok := m.group("lit_8"): + tokens.append(ExprLit(int(tok[1:], 8))) + elif tok := m.group("lit_10"): + tokens.append(ExprLit(int(tok, 10))) + elif tok := m.group("lit_16"): + tokens.append(ExprLit(int(tok[2:], 16))) + elif tok := m.group("sym"): + tokens.append(ExprSym(tok)) + elif tok := m.group("off"): + tokens.append(ExprOff(tok[1:])) + elif tok := m.group("num"): + [numname, valname] = tok.split(".", 1) + tokens.append(ExprNum(numname, valname)) + else: + assert False + return Expr(env, tokens) + + +# numspec ############################## + +re_numspec = f"(?P<name>{re_symname})\\s*=\\s*(?P<val>{re_expr})" -def parse_numspec(ver: str, n: Number, spec: str) -> None: + +def parse_numspec(env: dict[str, Type], ver: str, n: Number, spec: str) -> None: spec = spec.strip() if m := re.fullmatch(re_numspec, spec): name = m.group("name") - val = m.group("val") if name in n.vals: raise ValueError(f"{n.typname}: name {name!r} already assigned") + val = parse_expr(env, m.group("val")) + if val is None: + raise ValueError( + f"{n.typname}: {name!r} value is not constant: {m.group('val')!r}" + ) n.vals[name] = val else: raise SyntaxError(f"invalid num spec {spec!r}") -def parse_bitspec(ver: str, bf: Bitfield, spec: str) -> None: +# bitspec ############################## + +re_bitspec_bit = ( + "bit\\s+(?P<bitnum>[0-9]+)\\s*=\\s*(?:" + + "|".join( + [ + f"(?P<name_used>{re_symname_u})", + f"reserved\\((?P<name_reserved>{re_symname_u})\\)", + f"num\\((?P<name_num>{re_symname_u})\\)", + ] + ) + + ")" +) +re_bitspec_mask = f"mask\\s+(?P<name>{re_symname_u})\\s*=\\s*(?P<val>{re_expr})" +re_bitspec_alias = f"alias\\s+(?P<name>{re_symname_u})\\s*=\\s*(?P<val>{re_expr})" +re_bitspec_num = f"num\\((?P<num>{re_symname_u})\\)\\s+(?P<name>{re_symname_u})\\s*=\\s*(?P<val>{re_expr})" + + +def parse_bitspec(env: dict[str, Type], ver: str, bf: Bitfield, spec: str) -> None: spec = spec.strip() + def check_name(name: str, is_num: bool = False) -> None: + if name == "MASK": + raise ValueError(f"{bf.typname}: bit name may not be {'MASK'!r}: {name!r}") + if name.endswith("_MASK"): + raise ValueError( + f"{bf.typname}: bit name may not end with {'_MASK'!r}: {name!r}" + ) + if name in bf.names and not (is_num and name in bf.nums): + raise ValueError(f"{bf.typname}: bit name already assigned: {name!r}") + if m := re.fullmatch(re_bitspec_bit, spec): bitnum = int(m.group("bitnum")) if bitnum < 0 or bitnum >= len(bf.bits): raise ValueError(f"{bf.typname}: bit num {bitnum} out-of-bounds") bit = bf.bits[bitnum] - if bit.cat != BitCat.UNUSED: + if bit.cat != "UNUSED": raise ValueError(f"{bf.typname}: bit num {bitnum} already assigned") if name := m.group("name_used"): bit.bitname = name - bit.cat = BitCat.USED + bit.cat = "USED" bit.in_versions.add(ver) elif name := m.group("name_reserved"): bit.bitname = name - bit.cat = BitCat.RESERVED + bit.cat = "RESERVED" bit.in_versions.add(ver) - elif name := m.group("name_subfield"): + elif name := m.group("name_num"): bit.bitname = name - bit.cat = BitCat.SUBFIELD + if name not in bf.nums: + bf.nums[name] = BitNum(name) + bf.nums[name].mask |= 1 << bit.num + bit.cat = bf.nums[name] bit.in_versions.add(ver) if bit.bitname: - if bit.bitname in bf.names: - other = bf.names[bit.bitname] - if ( - isinstance(other, Bit) - and other.cat == bit.cat - and bit.cat == BitCat.SUBFIELD - ): - return - raise ValueError( - f"{bf.typname}: bit name {bit.bitname!r} already assigned" - ) - bf.names[bit.bitname] = bit + check_name(name, isinstance(bit.cat, BitNum)) + bf.names.add(bit.bitname) + elif m := re.fullmatch(re_bitspec_mask, spec): + mask = BitAlias(m.group("name"), parse_expr(env, m.group("val"))) + mask.in_versions.add(ver) + check_name(mask.bitname) + bf.masks[mask.bitname] = mask + bf.names.add(mask.bitname) elif m := re.fullmatch(re_bitspec_alias, spec): - alias = BitAlias(m.group("name"), m.group("val")) + alias = BitAlias(m.group("name"), parse_expr(env, m.group("val"))) + alias.in_versions.add(ver) + check_name(alias.bitname) + bf.aliases[alias.bitname] = alias + bf.names.add(alias.bitname) + elif m := re.fullmatch(re_bitspec_num, spec): + numname = m.group("num") + alias = BitAlias(m.group("name"), parse_expr(env, m.group("val"))) alias.in_versions.add(ver) - if alias.bitname in bf.names: + check_name(alias.bitname) + if numname not in bf.nums: + raise NameError( + f"{bf.typname}: nested num not allocated any bits: {numname!r}" + ) + assert alias.val.const is not None + if alias.val.const & ~bf.nums[numname].mask: raise ValueError( - f"{bf.typname}: bit name {alias.bitname!r} already assigned" + f"{bf.typname}: {alias.bitname!r} does not fit within bitmask: val={alias.val.const:b} mask={bf.nums[numname].mask}" ) - bf.names[alias.bitname] = alias + bf.nums[numname].vals[alias.bitname] = alias + bf.names.add(alias.bitname) else: raise SyntaxError(f"invalid bitfield spec {spec!r}") -def parse_expr(expr: str) -> Expr: - assert re.fullmatch(re_expr, expr) - ret = Expr() - for tok in re.split("([-+])", expr): - if tok in ("-", "+"): - # I, for the life of me, do not understand why I need this - # typing.cast() to keep mypy happy. - ret.tokens += [ExprOp(typing.cast(typing.Literal["-", "+"], tok))] - elif re.fullmatch("[0-9]+", tok): - ret.tokens += [ExprLit(int(tok))] - else: - ret.tokens += [ExprSym(tok)] - return ret +# struct members ####################### + + +re_memberspec = f"(?:(?P<cnt>{re_symname}|[1-9][0-9]*)\\*\\()?(?P<name>{re_symname})\\[(?P<typ>{re_memtype})(?:,max=(?P<max>{re_expr})|,val=(?P<val>{re_expr}))*\\]\\)?" def parse_members(ver: str, env: dict[str, Type], struct: Struct, specs: str) -> None: @@ -401,29 +602,44 @@ def parse_members(ver: str, env: dict[str, Type], struct: Struct, specs: str) -> member.typ = env[m.group("typ")] if cnt := m.group("cnt"): - if len(struct.members) == 0 or struct.members[-1].membname != cnt: - raise ValueError(f"list count must be previous item: {cnt!r}") - cnt_mem = struct.members[-1] - member.cnt = cnt_mem - _ = member.max_cnt # force validation + if cnt.isnumeric(): + member.cnt = int(cnt) + else: + if len(struct.members) == 0 or struct.members[-1].membname != cnt: + raise ValueError(f"list count must be previous item: {cnt!r}") + member.cnt = struct.members[-1] + _ = member.max_cnt # force validation if maxstr := m.group("max"): - if (not isinstance(member.typ, Primitive)) or member.cnt: - raise ValueError("',max=' may only be specified on a non-repeated atom") - member.max = parse_expr(maxstr) + if ( + not isinstance(member.typ, Primitive) + and not isinstance(member.typ, Number) + ) or member.cnt: + raise ValueError( + "',max=' may only be specified on a non-repeated numeric type" + ) + member.max = parse_expr(env, maxstr) else: - member.max = Expr() + member.max = Expr(env) if valstr := m.group("val"): - if (not isinstance(member.typ, Primitive)) or member.cnt: - raise ValueError("',val=' may only be specified on a non-repeated atom") - member.val = parse_expr(valstr) + if ( + not isinstance(member.typ, Primitive) + and not isinstance(member.typ, Number) + ) or member.cnt: + raise ValueError( + "',val=' may only be specified on a non-repeated numeric type" + ) + member.val = parse_expr(env, valstr) else: - member.val = Expr() + member.val = Expr(env) struct.members += [member] +# main parser ########################## + + def re_string(grpname: str) -> str: return f'"(?P<{grpname}>[^"]*)"' @@ -431,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( @@ -455,15 +670,6 @@ def parse_file( "8": Primitive.u64, } - def get_type(name: str, tc: type[T]) -> T: - nonlocal env - if name not in env: - raise NameError(f"Unknown type {name!r}") - ret = env[name] - if (not isinstance(ret, tc)) or (ret.__class__.__name__ != tc.__name__): - raise NameError(f"Type {ret.typname!r} is not a {tc.__name__}") - return ret - with open(filename, "r", encoding="utf-8") as fh: prev: Type | None = None for lineno, line in enumerate(fh): @@ -494,12 +700,19 @@ def parse_file( typ.in_versions.add(version) case Bitfield(): typ.in_versions.add(version) - for bit in typ.bits: - if other_version in bit.in_versions: - bit.in_versions.add(version) - for val in typ.names.values(): - if other_version in val.in_versions: - val.in_versions.add(version) + for bf_bit in typ.bits: + if other_version in bf_bit.in_versions: + bf_bit.in_versions.add(version) + for bf_num in typ.nums.values(): + for bf_val in bf_num.vals.values(): + if other_version in bf_val.in_versions: + bf_val.in_versions.add(version) + for bf_mask in typ.masks.values(): + if other_version in bf_mask.in_versions: + bf_mask.in_versions.add(version) + for bf_alias in typ.aliases.values(): + if other_version in bf_alias.in_versions: + bf_alias.in_versions.add(version) case Struct(): # and Message() typ.in_versions.add(version) for member in typ.members: @@ -527,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) @@ -539,8 +757,8 @@ def parse_file( env[bf.typname] = bf prev = bf elif m := re.fullmatch(re_line_bitfield_, line): - bf = get_type(m.group("name"), Bitfield) - parse_bitspec(version, bf, m.group("member")) + bf = get_type(env, m.group("name"), Bitfield) + parse_bitspec(env, version, bf, m.group("spec")) prev = bf elif m := re.fullmatch(re_line_struct, line): @@ -559,7 +777,7 @@ def parse_file( env[struct.typname] = struct prev = struct case "+=": - struct = get_type(m.group("name"), Struct) + struct = get_type(env, m.group("name"), Struct) parse_members(version, env, struct, m.group("members")) prev = struct @@ -577,18 +795,18 @@ def parse_file( env[msg.typname] = msg prev = msg case "+=": - msg = get_type(m.group("name"), Message) + msg = get_type(env, m.group("name"), Message) parse_members(version, env, msg, m.group("members")) prev = msg elif m := re.fullmatch(re_line_cont, line): match prev: case Bitfield(): - parse_bitspec(version, prev, m.group("specs")) + parse_bitspec(env, version, prev, m.group("spec")) case Number(): - parse_numspec(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" @@ -607,12 +825,6 @@ def parse_file( typs: list[UserType] = [x for x in env.values() if not isinstance(x, Primitive)] for typ in [typ for typ in typs if isinstance(typ, Struct)]: - valid_syms = [ - "end", - "s32_max", - "s64_max", - *["&" + m.membname for m in typ.members], - ] for member in typ.members: if ( not isinstance(member.typ, Primitive) @@ -622,9 +834,11 @@ def parse_file( f"{typ.typname}.{member.membname}: type {member.typ.typname} does not exist in {member.in_versions.difference(member.typ.in_versions)}" ) for tok in [*member.max.tokens, *member.val.tokens]: - if isinstance(tok, ExprSym) and tok.symname not in valid_syms: - raise ValueError( - f"{typ.typname}.{member.membname}: invalid sym: {tok.symname}" + if isinstance(tok, ExprOff) and not any( + m.membname == tok.membname for m in typ.members + ): + raise NameError( + f"{typ.typname}.{member.membname}: invalid offset: &{tok.membname}" ) return version, typs diff --git a/lib9p/include/lib9p/9p.generated.h b/lib9p/include/lib9p/9p.generated.h deleted file mode 100644 index 7a50537..0000000 --- a/lib9p/include/lib9p/9p.generated.h +++ /dev/null @@ -1,1248 +0,0 @@ -/* Generated by `lib9p/proto.gen lib9p/idl/2002-9P2000.9p lib9p/idl/2003-9P2000.p9p.9p lib9p/idl/2005-9P2000.u.9p lib9p/idl/2010-9P2000.L.9p lib9p/idl/2012-9P2000.e.9p`. DO NOT EDIT! */ - -#ifndef _LIB9P_9P_H_ - #error Do not include <lib9p/9p.generated.h> directly; include <lib9p/9p.h> instead -#endif - -#include <stdint.h> /* for uint{n}_t types */ - -#include <libhw/generic/net.h> /* for struct iovec */ - -/* config *********************************************************************/ - -#include "config.h" - -#ifndef CONFIG_9P_ENABLE_9P2000 - #error config.h must define CONFIG_9P_ENABLE_9P2000 -#endif - -#ifndef CONFIG_9P_ENABLE_9P2000_L - #error config.h must define CONFIG_9P_ENABLE_9P2000_L -#endif - -#ifndef CONFIG_9P_ENABLE_9P2000_e - #error config.h must define CONFIG_9P_ENABLE_9P2000_e -#else - #if CONFIG_9P_ENABLE_9P2000_e - #ifndef CONFIG_9P_MAX_9P2000_e_WELEM - #error if CONFIG_9P_ENABLE_9P2000_e then config.h must define CONFIG_9P_MAX_9P2000_e_WELEM - #endif - static_assert(CONFIG_9P_MAX_9P2000_e_WELEM > 0); - #endif -#endif - -#ifndef CONFIG_9P_ENABLE_9P2000_p9p - #error config.h must define CONFIG_9P_ENABLE_9P2000_p9p -#endif - -#ifndef CONFIG_9P_ENABLE_9P2000_u - #error config.h must define CONFIG_9P_ENABLE_9P2000_u -#endif - -/* enum version ***************************************************************/ - -enum lib9p_version { - LIB9P_VER_unknown = 0, /* "unknown" */ -#if CONFIG_9P_ENABLE_9P2000 - LIB9P_VER_9P2000, /* "9P2000" */ -#endif /* CONFIG_9P_ENABLE_9P2000 */ -#if CONFIG_9P_ENABLE_9P2000_L - LIB9P_VER_9P2000_L, /* "9P2000.L" */ -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e - LIB9P_VER_9P2000_e, /* "9P2000.e" */ -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000_p9p - LIB9P_VER_9P2000_p9p, /* "9P2000.p9p" */ -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_u - LIB9P_VER_9P2000_u, /* "9P2000.u" */ -#endif /* CONFIG_9P_ENABLE_9P2000_u */ - LIB9P_VER_NUM, -}; - -/* enum msg_type **************************************************************/ - -enum lib9p_msg_type { /* uint8_t */ -#if CONFIG_9P_ENABLE_9P2000_L - LIB9P_TYP_Rlerror = 7, - LIB9P_TYP_Tstatfs = 8, - LIB9P_TYP_Rstatfs = 9, - LIB9P_TYP_Tlopen = 12, - LIB9P_TYP_Rlopen = 13, - LIB9P_TYP_Tlcreate = 14, - LIB9P_TYP_Rlcreate = 15, - LIB9P_TYP_Tsymlink = 16, - LIB9P_TYP_Rsymlink = 17, - LIB9P_TYP_Tmknod = 18, - LIB9P_TYP_Rmknod = 19, - LIB9P_TYP_Trename = 20, - LIB9P_TYP_Rrename = 21, - LIB9P_TYP_Treadlink = 22, - LIB9P_TYP_Rreadlink = 23, - LIB9P_TYP_Tgetattr = 24, - LIB9P_TYP_Rgetattr = 25, - LIB9P_TYP_Tsetattr = 26, - LIB9P_TYP_Rsetattr = 27, - LIB9P_TYP_Txattrwalk = 30, - LIB9P_TYP_Rxattrwalk = 31, - LIB9P_TYP_Txattrcreate = 32, - LIB9P_TYP_Rxattrcreate = 33, - LIB9P_TYP_Treaddir = 40, - LIB9P_TYP_Rreaddir = 41, - LIB9P_TYP_Tfsync = 50, - LIB9P_TYP_Rfsync = 51, - LIB9P_TYP_Tlock = 52, - LIB9P_TYP_Rlock = 53, - LIB9P_TYP_Tgetlock = 54, - LIB9P_TYP_Rgetlock = 55, - LIB9P_TYP_Tlink = 70, - LIB9P_TYP_Rlink = 71, - LIB9P_TYP_Tmkdir = 72, - LIB9P_TYP_Rmkdir = 73, - LIB9P_TYP_Trenameat = 74, - LIB9P_TYP_Rrenameat = 75, - LIB9P_TYP_Tunlinkat = 76, - LIB9P_TYP_Runlinkat = 77, -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_p9p - LIB9P_TYP_Topenfd = 98, - LIB9P_TYP_Ropenfd = 99, -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u - 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, -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u - LIB9P_TYP_Topen = 112, - LIB9P_TYP_Ropen = 113, - LIB9P_TYP_Tcreate = 114, - LIB9P_TYP_Rcreate = 115, -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u - 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, -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u - LIB9P_TYP_Tstat = 124, - LIB9P_TYP_Rstat = 125, - LIB9P_TYP_Twstat = 126, - LIB9P_TYP_Rwstat = 127, -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_e - LIB9P_TYP_Tsession = 150, - LIB9P_TYP_Rsession = 151, - LIB9P_TYP_Tsread = 152, - LIB9P_TYP_Rsread = 153, - LIB9P_TYP_Tswrite = 154, - LIB9P_TYP_Rswrite = 155, -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -}; - -/* payload types **************************************************************/ - -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 2 ; max_iov = 1 ; max_copy = 2 */ -typedef uint16_t lib9p_tag_t; -#define LIB9P_TAG_NOTAG ((lib9p_tag_t)UINT16_C(~0)) - -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_fid_t; -#define LIB9P_FID_NOFID ((lib9p_fid_t)UINT32_C(~0)) - -/* min_size = 2 ; exp_size = 29 ; max_size = 65,537 ; max_iov = 2 ; max_copy = 2 */ -struct lib9p_s { - uint16_t len; - [[gnu::nonstring]] char *utf8; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_dm_t; - -#define LIB9P_DM_DIR ((lib9p_dm_t)(1<<31)) -#define LIB9P_DM_APPEND ((lib9p_dm_t)(1<<30)) -#define LIB9P_DM_EXCL ((lib9p_dm_t)(1<<29)) -#define _LIB9P_DM_RESERVED_PLAN9_MOUNT ((lib9p_dm_t)(1<<28)) -#define LIB9P_DM_AUTH ((lib9p_dm_t)(1<<27)) -#define LIB9P_DM_TMP ((lib9p_dm_t)(1<<26)) -/* unused ((lib9p_dm_t)(1<<25)) */ -/* unused ((lib9p_dm_t)(1<<24)) */ -#if CONFIG_9P_ENABLE_9P2000_u -# define LIB9P_DM_DEVICE ((lib9p_dm_t)(1<<23)) -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -/* unused ((lib9p_dm_t)(1<<22)) */ -#if CONFIG_9P_ENABLE_9P2000_u -# define LIB9P_DM_NAMEDPIPE ((lib9p_dm_t)(1<<21)) -# define LIB9P_DM_SOCKET ((lib9p_dm_t)(1<<20)) -# define LIB9P_DM_SETUID ((lib9p_dm_t)(1<<19)) -# define LIB9P_DM_SETGID ((lib9p_dm_t)(1<<18)) -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -/* unused ((lib9p_dm_t)(1<<17)) */ -/* unused ((lib9p_dm_t)(1<<16)) */ -/* unused ((lib9p_dm_t)(1<<15)) */ -/* unused ((lib9p_dm_t)(1<<14)) */ -/* unused ((lib9p_dm_t)(1<<13)) */ -/* unused ((lib9p_dm_t)(1<<12)) */ -/* unused ((lib9p_dm_t)(1<<11)) */ -/* unused ((lib9p_dm_t)(1<<10)) */ -/* unused ((lib9p_dm_t)(1<<9)) */ -#define LIB9P_DM_OWNER_R ((lib9p_dm_t)(1<<8)) -#define LIB9P_DM_OWNER_W ((lib9p_dm_t)(1<<7)) -#define LIB9P_DM_OWNER_X ((lib9p_dm_t)(1<<6)) -#define LIB9P_DM_GROUP_R ((lib9p_dm_t)(1<<5)) -#define LIB9P_DM_GROUP_W ((lib9p_dm_t)(1<<4)) -#define LIB9P_DM_GROUP_X ((lib9p_dm_t)(1<<3)) -#define LIB9P_DM_OTHER_R ((lib9p_dm_t)(1<<2)) -#define LIB9P_DM_OTHER_W ((lib9p_dm_t)(1<<1)) -#define LIB9P_DM_OTHER_X ((lib9p_dm_t)(1<<0)) - -#define LIB9P_DM_PERM_MASK ((lib9p_dm_t)(0777)) - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 1 ; max_iov = 1 ; max_copy = 1 */ -typedef uint8_t lib9p_qt_t; - -#define LIB9P_QT_DIR ((lib9p_qt_t)(1<<7)) -#define LIB9P_QT_APPEND ((lib9p_qt_t)(1<<6)) -#define LIB9P_QT_EXCL ((lib9p_qt_t)(1<<5)) -#define _LIB9P_QT_RESERVED_PLAN9_MOUNT ((lib9p_qt_t)(1<<4)) -#define LIB9P_QT_AUTH ((lib9p_qt_t)(1<<3)) -#define LIB9P_QT_TMP ((lib9p_qt_t)(1<<2)) -#if CONFIG_9P_ENABLE_9P2000_u -# define LIB9P_QT_SYMLINK ((lib9p_qt_t)(1<<1)) -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -/* unused ((lib9p_qt_t)(1<<0)) */ - -#define LIB9P_QT_FILE ((lib9p_qt_t)(0)) - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_nuid_t; -#define LIB9P_NUID_NONUID ((lib9p_nuid_t)UINT32_C(~0)) - -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 1 ; max_iov = 1 ; max_copy = 1 */ -typedef uint8_t lib9p_o_t; - -/* unused ((lib9p_o_t)(1<<7)) */ -#define LIB9P_O_RCLOSE ((lib9p_o_t)(1<<6)) -#define _LIB9P_O_RESERVED_CEXEC ((lib9p_o_t)(1<<5)) -#define LIB9P_O_TRUNC ((lib9p_o_t)(1<<4)) -/* unused ((lib9p_o_t)(1<<3)) */ -/* unused ((lib9p_o_t)(1<<2)) */ -#define _LIB9P_O_mode_1 ((lib9p_o_t)(1<<1)) -#define _LIB9P_O_mode_0 ((lib9p_o_t)(1<<0)) - -#define LIB9P_O_READ ((lib9p_o_t)(0)) -#define LIB9P_O_WRITE ((lib9p_o_t)(1)) -#define LIB9P_O_RDWR ((lib9p_o_t)(2)) -#define LIB9P_O_EXEC ((lib9p_o_t)(3)) -#define LIB9P_O_MODE_MASK ((lib9p_o_t)(0b00000011)) -#define LIB9P_O_FLAG_MASK ((lib9p_o_t)(0b11111100)) - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_errno_t; -#define LIB9P_ERRNO_NOERROR ((lib9p_errno_t)UINT32_C(0)) - -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_super_magic_t; -#define LIB9P_SUPER_MAGIC_V9FS_MAGIC ((lib9p_super_magic_t)UINT32_C(0x01021997)) - -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_lo_t; - -/* unused ((lib9p_lo_t)(1<<31)) */ -/* unused ((lib9p_lo_t)(1<<30)) */ -/* unused ((lib9p_lo_t)(1<<29)) */ -/* unused ((lib9p_lo_t)(1<<28)) */ -/* unused ((lib9p_lo_t)(1<<27)) */ -/* unused ((lib9p_lo_t)(1<<26)) */ -/* unused ((lib9p_lo_t)(1<<25)) */ -/* unused ((lib9p_lo_t)(1<<24)) */ -/* unused ((lib9p_lo_t)(1<<23)) */ -/* unused ((lib9p_lo_t)(1<<22)) */ -/* unused ((lib9p_lo_t)(1<<21)) */ -#define LIB9P_LO_SYNC ((lib9p_lo_t)(1<<20)) -#define LIB9P_LO_CLOEXEC ((lib9p_lo_t)(1<<19)) -#define LIB9P_LO_NOATIME ((lib9p_lo_t)(1<<18)) -#define LIB9P_LO_NOFOLLOW ((lib9p_lo_t)(1<<17)) -#define LIB9P_LO_DIRECTORY ((lib9p_lo_t)(1<<16)) -#define LIB9P_LO_LARGEFILE ((lib9p_lo_t)(1<<15)) -#define LIB9P_LO_DIRECT ((lib9p_lo_t)(1<<14)) -#define LIB9P_LO_BSD_FASYNC ((lib9p_lo_t)(1<<13)) -#define LIB9P_LO_DSYNC ((lib9p_lo_t)(1<<12)) -#define LIB9P_LO_NONBLOCK ((lib9p_lo_t)(1<<11)) -#define LIB9P_LO_APPEND ((lib9p_lo_t)(1<<10)) -#define LIB9P_LO_TRUNC ((lib9p_lo_t)(1<<9)) -#define LIB9P_LO_NOCTTY ((lib9p_lo_t)(1<<8)) -#define LIB9P_LO_EXCL ((lib9p_lo_t)(1<<7)) -#define LIB9P_LO_CREATE ((lib9p_lo_t)(1<<6)) -/* unused ((lib9p_lo_t)(1<<5)) */ -/* unused ((lib9p_lo_t)(1<<4)) */ -/* unused ((lib9p_lo_t)(1<<3)) */ -/* unused ((lib9p_lo_t)(1<<2)) */ -#define _LIB9P_LO_mode_1 ((lib9p_lo_t)(1<<1)) -#define _LIB9P_LO_mode_0 ((lib9p_lo_t)(1<<0)) - -#define LIB9P_LO_RDONLY ((lib9p_lo_t)(0)) -#define LIB9P_LO_WRONLY ((lib9p_lo_t)(1)) -#define LIB9P_LO_RDWR ((lib9p_lo_t)(2)) -#define LIB9P_LO_NOACCESS ((lib9p_lo_t)(3)) -#define LIB9P_LO_MODE_MASK ((lib9p_lo_t)(0b000000000000000000011)) -#define LIB9P_LO_FLAG_MASK ((lib9p_lo_t)(0b111111111111111000000)) - -/* size = 1 ; max_iov = 1 ; max_copy = 1 */ -typedef uint8_t lib9p_dt_t; -#define LIB9P_DT_UNKNOWN ((lib9p_dt_t)UINT8_C(0)) -#define LIB9P_DT_NAMED_PIPE ((lib9p_dt_t)UINT8_C(1)) -#define LIB9P_DT_CHAR_DEV ((lib9p_dt_t)UINT8_C(2)) -#define LIB9P_DT_DIRECTORY ((lib9p_dt_t)UINT8_C(4)) -#define LIB9P_DT_BLOCK_DEV ((lib9p_dt_t)UINT8_C(6)) -#define LIB9P_DT_REGULAR ((lib9p_dt_t)UINT8_C(8)) -#define LIB9P_DT_SYMLINK ((lib9p_dt_t)UINT8_C(10)) -#define LIB9P_DT_SOCKET ((lib9p_dt_t)UINT8_C(12)) -#define LIB9P_DT_WHITEOUT ((lib9p_dt_t)UINT8_C(14)) - -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_mode_t; - -/* unused ((lib9p_mode_t)(1<<31)) */ -/* unused ((lib9p_mode_t)(1<<30)) */ -/* unused ((lib9p_mode_t)(1<<29)) */ -/* unused ((lib9p_mode_t)(1<<28)) */ -/* unused ((lib9p_mode_t)(1<<27)) */ -/* unused ((lib9p_mode_t)(1<<26)) */ -/* unused ((lib9p_mode_t)(1<<25)) */ -/* unused ((lib9p_mode_t)(1<<24)) */ -/* unused ((lib9p_mode_t)(1<<23)) */ -/* unused ((lib9p_mode_t)(1<<22)) */ -/* unused ((lib9p_mode_t)(1<<21)) */ -/* unused ((lib9p_mode_t)(1<<20)) */ -/* unused ((lib9p_mode_t)(1<<19)) */ -/* unused ((lib9p_mode_t)(1<<18)) */ -/* unused ((lib9p_mode_t)(1<<17)) */ -/* unused ((lib9p_mode_t)(1<<16)) */ -#define _LIB9P_MODE_fmt_3 ((lib9p_mode_t)(1<<15)) -#define _LIB9P_MODE_fmt_2 ((lib9p_mode_t)(1<<14)) -#define _LIB9P_MODE_fmt_1 ((lib9p_mode_t)(1<<13)) -#define _LIB9P_MODE_fmt_0 ((lib9p_mode_t)(1<<12)) -#define LIB9P_MODE_PERM_SETGROUP ((lib9p_mode_t)(1<<11)) -#define LIB9P_MODE_PERM_SETUSER ((lib9p_mode_t)(1<<10)) -#define LIB9P_MODE_PERM_STICKY ((lib9p_mode_t)(1<<9)) -#define LIB9P_MODE_PERM_OWNER_R ((lib9p_mode_t)(1<<8)) -#define LIB9P_MODE_PERM_OWNER_W ((lib9p_mode_t)(1<<7)) -#define LIB9P_MODE_PERM_OWNER_X ((lib9p_mode_t)(1<<6)) -#define LIB9P_MODE_PERM_GROUP_R ((lib9p_mode_t)(1<<5)) -#define LIB9P_MODE_PERM_GROUP_W ((lib9p_mode_t)(1<<4)) -#define LIB9P_MODE_PERM_GROUP_X ((lib9p_mode_t)(1<<3)) -#define LIB9P_MODE_PERM_OTHER_R ((lib9p_mode_t)(1<<2)) -#define LIB9P_MODE_PERM_OTHER_W ((lib9p_mode_t)(1<<1)) -#define LIB9P_MODE_PERM_OTHER_X ((lib9p_mode_t)(1<<0)) - -#define LIB9P_MODE_FMT_NAMED_PIPE ((lib9p_mode_t)(LIB9P_DT_NAMED_PIPE<<12)) -#define LIB9P_MODE_FMT_CHAR_DEV ((lib9p_mode_t)(LIB9P_DT_CHAR_DEV<<12)) -#define LIB9P_MODE_FMT_DIRECTORY ((lib9p_mode_t)(LIB9P_DT_DIRECTORY<<12)) -#define LIB9P_MODE_FMT_BLOCK_DEV ((lib9p_mode_t)(LIB9P_DT_BLOCK_DEV<<12)) -#define LIB9P_MODE_FMT_REGULAR ((lib9p_mode_t)(LIB9P_DT_REGULAR<<12)) -#define LIB9P_MODE_FMT_SYMLINK ((lib9p_mode_t)(LIB9P_DT_SYMLINK<<12)) -#define LIB9P_MODE_FMT_SOCKET ((lib9p_mode_t)(LIB9P_DT_SOCKET<<12)) -#define LIB9P_MODE_PERM_MASK ((lib9p_mode_t)(0000777)) -#define LIB9P_MODE_FMT_MASK ((lib9p_mode_t)(0170000)) - -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_b4_t; -#define LIB9P_B4_FALSE ((lib9p_b4_t)UINT32_C(0)) -#define LIB9P_B4_TRUE ((lib9p_b4_t)UINT32_C(1)) - -/* size = 8 ; max_iov = 1 ; max_copy = 8 */ -typedef uint64_t lib9p_getattr_t; - -/* unused ((lib9p_getattr_t)(1<<63)) */ -/* unused ((lib9p_getattr_t)(1<<62)) */ -/* unused ((lib9p_getattr_t)(1<<61)) */ -/* unused ((lib9p_getattr_t)(1<<60)) */ -/* unused ((lib9p_getattr_t)(1<<59)) */ -/* unused ((lib9p_getattr_t)(1<<58)) */ -/* unused ((lib9p_getattr_t)(1<<57)) */ -/* unused ((lib9p_getattr_t)(1<<56)) */ -/* unused ((lib9p_getattr_t)(1<<55)) */ -/* unused ((lib9p_getattr_t)(1<<54)) */ -/* unused ((lib9p_getattr_t)(1<<53)) */ -/* unused ((lib9p_getattr_t)(1<<52)) */ -/* unused ((lib9p_getattr_t)(1<<51)) */ -/* unused ((lib9p_getattr_t)(1<<50)) */ -/* unused ((lib9p_getattr_t)(1<<49)) */ -/* unused ((lib9p_getattr_t)(1<<48)) */ -/* unused ((lib9p_getattr_t)(1<<47)) */ -/* unused ((lib9p_getattr_t)(1<<46)) */ -/* unused ((lib9p_getattr_t)(1<<45)) */ -/* unused ((lib9p_getattr_t)(1<<44)) */ -/* unused ((lib9p_getattr_t)(1<<43)) */ -/* unused ((lib9p_getattr_t)(1<<42)) */ -/* unused ((lib9p_getattr_t)(1<<41)) */ -/* unused ((lib9p_getattr_t)(1<<40)) */ -/* unused ((lib9p_getattr_t)(1<<39)) */ -/* unused ((lib9p_getattr_t)(1<<38)) */ -/* unused ((lib9p_getattr_t)(1<<37)) */ -/* unused ((lib9p_getattr_t)(1<<36)) */ -/* unused ((lib9p_getattr_t)(1<<35)) */ -/* unused ((lib9p_getattr_t)(1<<34)) */ -/* unused ((lib9p_getattr_t)(1<<33)) */ -/* unused ((lib9p_getattr_t)(1<<32)) */ -/* unused ((lib9p_getattr_t)(1<<31)) */ -/* unused ((lib9p_getattr_t)(1<<30)) */ -/* unused ((lib9p_getattr_t)(1<<29)) */ -/* unused ((lib9p_getattr_t)(1<<28)) */ -/* unused ((lib9p_getattr_t)(1<<27)) */ -/* unused ((lib9p_getattr_t)(1<<26)) */ -/* unused ((lib9p_getattr_t)(1<<25)) */ -/* unused ((lib9p_getattr_t)(1<<24)) */ -/* unused ((lib9p_getattr_t)(1<<23)) */ -/* unused ((lib9p_getattr_t)(1<<22)) */ -/* unused ((lib9p_getattr_t)(1<<21)) */ -/* unused ((lib9p_getattr_t)(1<<20)) */ -/* unused ((lib9p_getattr_t)(1<<19)) */ -/* unused ((lib9p_getattr_t)(1<<18)) */ -/* unused ((lib9p_getattr_t)(1<<17)) */ -/* unused ((lib9p_getattr_t)(1<<16)) */ -/* unused ((lib9p_getattr_t)(1<<15)) */ -/* unused ((lib9p_getattr_t)(1<<14)) */ -#define LIB9P_GETATTR_DATA_VERSION ((lib9p_getattr_t)(1<<13)) -#define LIB9P_GETATTR_GEN ((lib9p_getattr_t)(1<<12)) -#define LIB9P_GETATTR_BTIME ((lib9p_getattr_t)(1<<11)) -#define LIB9P_GETATTR_BLOCKS ((lib9p_getattr_t)(1<<10)) -#define LIB9P_GETATTR_SIZE ((lib9p_getattr_t)(1<<9)) -#define LIB9P_GETATTR_INO ((lib9p_getattr_t)(1<<8)) -#define LIB9P_GETATTR_CTIME ((lib9p_getattr_t)(1<<7)) -#define LIB9P_GETATTR_MTIME ((lib9p_getattr_t)(1<<6)) -#define LIB9P_GETATTR_ATIME ((lib9p_getattr_t)(1<<5)) -#define LIB9P_GETATTR_RDEV ((lib9p_getattr_t)(1<<4)) -#define LIB9P_GETATTR_GID ((lib9p_getattr_t)(1<<3)) -#define LIB9P_GETATTR_UID ((lib9p_getattr_t)(1<<2)) -#define LIB9P_GETATTR_NLINK ((lib9p_getattr_t)(1<<1)) -#define LIB9P_GETATTR_MODE ((lib9p_getattr_t)(1<<0)) - -#define LIB9P_GETATTR_BASIC ((lib9p_getattr_t)(0x000007ff)) -#define LIB9P_GETATTR_ALL ((lib9p_getattr_t)(0x00003fff)) - -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_setattr_t; - -/* unused ((lib9p_setattr_t)(1<<31)) */ -/* unused ((lib9p_setattr_t)(1<<30)) */ -/* unused ((lib9p_setattr_t)(1<<29)) */ -/* unused ((lib9p_setattr_t)(1<<28)) */ -/* unused ((lib9p_setattr_t)(1<<27)) */ -/* unused ((lib9p_setattr_t)(1<<26)) */ -/* unused ((lib9p_setattr_t)(1<<25)) */ -/* unused ((lib9p_setattr_t)(1<<24)) */ -/* unused ((lib9p_setattr_t)(1<<23)) */ -/* unused ((lib9p_setattr_t)(1<<22)) */ -/* unused ((lib9p_setattr_t)(1<<21)) */ -/* unused ((lib9p_setattr_t)(1<<20)) */ -/* unused ((lib9p_setattr_t)(1<<19)) */ -/* unused ((lib9p_setattr_t)(1<<18)) */ -/* unused ((lib9p_setattr_t)(1<<17)) */ -/* unused ((lib9p_setattr_t)(1<<16)) */ -/* unused ((lib9p_setattr_t)(1<<15)) */ -/* unused ((lib9p_setattr_t)(1<<14)) */ -/* unused ((lib9p_setattr_t)(1<<13)) */ -/* unused ((lib9p_setattr_t)(1<<12)) */ -/* unused ((lib9p_setattr_t)(1<<11)) */ -/* unused ((lib9p_setattr_t)(1<<10)) */ -/* unused ((lib9p_setattr_t)(1<<9)) */ -#define LIB9P_SETATTR_MTIME_SET ((lib9p_setattr_t)(1<<8)) -#define LIB9P_SETATTR_ATIME_SET ((lib9p_setattr_t)(1<<7)) -#define LIB9P_SETATTR_CTIME ((lib9p_setattr_t)(1<<6)) -#define LIB9P_SETATTR_MTIME ((lib9p_setattr_t)(1<<5)) -#define LIB9P_SETATTR_ATIME ((lib9p_setattr_t)(1<<4)) -#define LIB9P_SETATTR_SIZE ((lib9p_setattr_t)(1<<3)) -#define LIB9P_SETATTR_GID ((lib9p_setattr_t)(1<<2)) -#define LIB9P_SETATTR_UID ((lib9p_setattr_t)(1<<1)) -#define LIB9P_SETATTR_MODE ((lib9p_setattr_t)(1<<0)) - -/* size = 1 ; max_iov = 1 ; max_copy = 1 */ -typedef uint8_t lib9p_lock_type_t; -#define LIB9P_LOCK_TYPE_RDLCK ((lib9p_lock_type_t)UINT8_C(0)) -#define LIB9P_LOCK_TYPE_WRLCK ((lib9p_lock_type_t)UINT8_C(1)) -#define LIB9P_LOCK_TYPE_UNLCK ((lib9p_lock_type_t)UINT8_C(2)) - -/* size = 4 ; max_iov = 1 ; max_copy = 4 */ -typedef uint32_t lib9p_lock_flags_t; - -/* unused ((lib9p_lock_flags_t)(1<<31)) */ -/* unused ((lib9p_lock_flags_t)(1<<30)) */ -/* unused ((lib9p_lock_flags_t)(1<<29)) */ -/* unused ((lib9p_lock_flags_t)(1<<28)) */ -/* unused ((lib9p_lock_flags_t)(1<<27)) */ -/* unused ((lib9p_lock_flags_t)(1<<26)) */ -/* unused ((lib9p_lock_flags_t)(1<<25)) */ -/* unused ((lib9p_lock_flags_t)(1<<24)) */ -/* unused ((lib9p_lock_flags_t)(1<<23)) */ -/* unused ((lib9p_lock_flags_t)(1<<22)) */ -/* unused ((lib9p_lock_flags_t)(1<<21)) */ -/* unused ((lib9p_lock_flags_t)(1<<20)) */ -/* unused ((lib9p_lock_flags_t)(1<<19)) */ -/* unused ((lib9p_lock_flags_t)(1<<18)) */ -/* unused ((lib9p_lock_flags_t)(1<<17)) */ -/* unused ((lib9p_lock_flags_t)(1<<16)) */ -/* unused ((lib9p_lock_flags_t)(1<<15)) */ -/* unused ((lib9p_lock_flags_t)(1<<14)) */ -/* unused ((lib9p_lock_flags_t)(1<<13)) */ -/* unused ((lib9p_lock_flags_t)(1<<12)) */ -/* unused ((lib9p_lock_flags_t)(1<<11)) */ -/* unused ((lib9p_lock_flags_t)(1<<10)) */ -/* unused ((lib9p_lock_flags_t)(1<<9)) */ -/* unused ((lib9p_lock_flags_t)(1<<8)) */ -/* unused ((lib9p_lock_flags_t)(1<<7)) */ -/* unused ((lib9p_lock_flags_t)(1<<6)) */ -/* unused ((lib9p_lock_flags_t)(1<<5)) */ -/* unused ((lib9p_lock_flags_t)(1<<4)) */ -/* unused ((lib9p_lock_flags_t)(1<<3)) */ -/* unused ((lib9p_lock_flags_t)(1<<2)) */ -#define LIB9P_LOCK_FLAGS_RECLAIM ((lib9p_lock_flags_t)(1<<1)) -#define LIB9P_LOCK_FLAGS_BLOCK ((lib9p_lock_flags_t)(1<<0)) - -/* size = 1 ; max_iov = 1 ; max_copy = 1 */ -typedef uint8_t lib9p_lock_status_t; -#define LIB9P_LOCK_STATUS_SUCCESS ((lib9p_lock_status_t)UINT8_C(0)) -#define LIB9P_LOCK_STATUS_BLOCKED ((lib9p_lock_status_t)UINT8_C(1)) -#define LIB9P_LOCK_STATUS_ERROR ((lib9p_lock_status_t)UINT8_C(2)) -#define LIB9P_LOCK_STATUS_GRACE ((lib9p_lock_status_t)UINT8_C(3)) - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 9 ; max_iov = 1 ; max_copy = 9 */ -struct lib9p_msg_Tflush { - lib9p_tag_t tag; - uint16_t oldtag; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rflush { - lib9p_tag_t tag; -}; - -/* min_size = 11 ; exp_size = 8,203 ; max_size = 2,147,483,658 ; max_iov = 2 ; max_copy = 11 */ -struct lib9p_msg_Rread { - lib9p_tag_t tag; - uint32_t count; - [[gnu::nonstring]] char *data; -}; - -/* size = 11 ; max_iov = 1 ; max_copy = 11 */ -struct lib9p_msg_Rwrite { - lib9p_tag_t tag; - uint32_t count; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rclunk { - lib9p_tag_t tag; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rremove { - lib9p_tag_t tag; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rwstat { - lib9p_tag_t tag; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rrename { - lib9p_tag_t tag; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rsetattr { - lib9p_tag_t tag; -}; - -/* size = 15 ; max_iov = 1 ; max_copy = 15 */ -struct lib9p_msg_Rxattrwalk { - lib9p_tag_t tag; - uint64_t attr_size; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rxattrcreate { - lib9p_tag_t tag; -}; - -/* min_size = 11 ; exp_size = 8,203 ; max_size = 4,294,967,306 (warning: >UINT32_MAX) ; max_iov = 2 ; max_copy = 11 */ -struct lib9p_msg_Rreaddir { - lib9p_tag_t tag; - uint32_t count; - [[gnu::nonstring]] char *data; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rfsync { - lib9p_tag_t tag; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rlink { - lib9p_tag_t tag; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rrenameat { - lib9p_tag_t tag; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Runlinkat { - lib9p_tag_t tag; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e -/* size = 15 ; max_iov = 1 ; max_copy = 15 */ -struct lib9p_msg_Tsession { - lib9p_tag_t tag; - uint64_t key; -}; - -/* size = 7 ; max_iov = 1 ; max_copy = 7 */ -struct lib9p_msg_Rsession { - lib9p_tag_t tag; -}; - -/* min_size = 11 ; exp_size = 8,203 ; max_size = 4,294,967,306 (warning: >UINT32_MAX) ; max_iov = 2 ; max_copy = 11 */ -struct lib9p_msg_Rsread { - lib9p_tag_t tag; - uint32_t count; - [[gnu::nonstring]] char *data; -}; - -/* size = 11 ; max_iov = 1 ; max_copy = 11 */ -struct lib9p_msg_Rswrite { - lib9p_tag_t tag; - uint32_t count; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 23 ; max_iov = 1 ; max_copy = 23 */ -struct lib9p_msg_Tread { - lib9p_tag_t tag; - lib9p_fid_t fid; - uint64_t offset; - uint32_t count; -}; - -/* min_size = 23 ; exp_size = 8,215 ; max_size = 2,147,483,670 ; max_iov = 2 ; max_copy = 23 */ -struct lib9p_msg_Twrite { - lib9p_tag_t tag; - lib9p_fid_t fid; - uint64_t offset; - uint32_t count; - [[gnu::nonstring]] char *data; -}; - -/* size = 11 ; max_iov = 1 ; max_copy = 11 */ -struct lib9p_msg_Tclunk { - lib9p_tag_t tag; - lib9p_fid_t fid; -}; - -/* size = 11 ; max_iov = 1 ; max_copy = 11 */ -struct lib9p_msg_Tremove { - lib9p_tag_t tag; - lib9p_fid_t fid; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 11 ; max_iov = 1 ; max_copy = 11 */ -struct lib9p_msg_Tstat { - lib9p_tag_t tag; - lib9p_fid_t fid; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L -/* size = 11 ; max_iov = 1 ; max_copy = 11 */ -struct lib9p_msg_Tstatfs { - lib9p_tag_t tag; - lib9p_fid_t fid; -}; - -/* size = 11 ; max_iov = 1 ; max_copy = 11 */ -struct lib9p_msg_Treadlink { - lib9p_tag_t tag; - lib9p_fid_t fid; -}; - -/* size = 23 ; max_iov = 1 ; max_copy = 23 */ -struct lib9p_msg_Treaddir { - lib9p_tag_t tag; - lib9p_fid_t fid; - uint64_t offset; - uint32_t count; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* min_size = 13 ; exp_size = 40 ; max_size = 65,548 ; max_iov = 2 ; max_copy = 13 */ -struct lib9p_msg_Tversion { - lib9p_tag_t tag; - uint32_t max_msg_size; - struct lib9p_s version; -}; - -/* min_size = 13 ; exp_size = 40 ; max_size = 65,548 ; max_iov = 2 ; max_copy = 13 */ -struct lib9p_msg_Rversion { - lib9p_tag_t tag; - uint32_t max_msg_size; - struct lib9p_s version; -}; - -/* min_size = 17 ; exp_size = 481 ; max_size = 1,048,609 ; max_iov = 32 ; max_copy = 49 */ -struct lib9p_msg_Twalk { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_fid_t newfid; - uint16_t nwname; - struct lib9p_s *wname; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L -/* min_size = 17 ; exp_size = 44 ; max_size = 65,552 ; max_iov = 2 ; max_copy = 17 */ -struct lib9p_msg_Trename { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_fid_t dfid; - struct lib9p_s name; -}; - -/* min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ -struct lib9p_msg_Rreadlink { - lib9p_tag_t tag; - struct lib9p_s target; -}; - -/* min_size = 17 ; exp_size = 44 ; max_size = 65,552 ; max_iov = 2 ; max_copy = 17 */ -struct lib9p_msg_Txattrwalk { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_fid_t newfid; - struct lib9p_s name; -}; - -/* min_size = 25 ; exp_size = 52 ; max_size = 65,560 ; max_iov = 3 ; max_copy = 25 */ -struct lib9p_msg_Txattrcreate { - lib9p_tag_t tag; - lib9p_fid_t fid; - struct lib9p_s name; - uint64_t attr_size; - uint32_t flags; -}; - -/* min_size = 17 ; exp_size = 44 ; max_size = 65,552 ; max_iov = 2 ; max_copy = 17 */ -struct lib9p_msg_Tlink { - lib9p_tag_t tag; - lib9p_fid_t dfid; - lib9p_fid_t fid; - struct lib9p_s name; -}; - -/* min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 4 ; max_copy = 19 */ -struct lib9p_msg_Trenameat { - lib9p_tag_t tag; - lib9p_fid_t olddirfid; - struct lib9p_s oldname; - lib9p_fid_t newdirfid; - struct lib9p_s newname; -}; - -/* min_size = 17 ; exp_size = 44 ; max_size = 65,552 ; max_iov = 3 ; max_copy = 17 */ -struct lib9p_msg_Tunlinkat { - lib9p_tag_t tag; - lib9p_fid_t dirfd; - struct lib9p_s name; - uint32_t flags; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000_e -/* min_size = 13 ; exp_size = 477 ; max_size = 4,294,967,308 (warning: >UINT32_MAX) ; max_iov = 0 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2) ; max_copy = 13 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2) */ -struct lib9p_msg_Tsread { - lib9p_tag_t tag; - uint32_t fid; - uint16_t nwname; - struct lib9p_s *wname; -}; - -/* min_size = 17 ; exp_size = 8,673 ; max_size = 8,589,934,607 (warning: >UINT32_MAX) ; max_iov = 2 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2) ; max_copy = 17 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2) */ -struct lib9p_msg_Tswrite { - lib9p_tag_t tag; - uint32_t fid; - uint16_t nwname; - struct lib9p_s *wname; - uint32_t count; - [[gnu::nonstring]] char *data; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_e */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 13 ; max_iov = 1 ; max_copy = 13 */ -struct lib9p_qid { - lib9p_qt_t type; - uint32_t vers; - uint64_t path; -}; - -/* LIB9P_VER_9P2000 : min_size = 15 ; exp_size = 69 ; max_size = 131,085 ; max_iov = 4 ; max_copy = 15 */ -/* LIB9P_VER_9P2000_L : min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 5 ; max_copy = 19 */ -/* LIB9P_VER_9P2000_e : min_size = 15 ; exp_size = 69 ; max_size = 131,085 ; max_iov = 4 ; max_copy = 15 */ -/* LIB9P_VER_9P2000_p9p: min_size = 15 ; exp_size = 69 ; max_size = 131,085 ; max_iov = 4 ; max_copy = 15 */ -/* LIB9P_VER_9P2000_u : min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 5 ; max_copy = 19 */ -struct lib9p_msg_Tauth { - lib9p_tag_t tag; - lib9p_fid_t afid; - struct lib9p_s uname; - struct lib9p_s aname; -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - lib9p_nuid_t n_uid; -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ -}; - -/* LIB9P_VER_9P2000 : min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 4 ; max_copy = 19 */ -/* LIB9P_VER_9P2000_L : min_size = 23 ; exp_size = 77 ; max_size = 131,093 ; max_iov = 5 ; max_copy = 23 */ -/* LIB9P_VER_9P2000_e : min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 4 ; max_copy = 19 */ -/* LIB9P_VER_9P2000_p9p: min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 4 ; max_copy = 19 */ -/* LIB9P_VER_9P2000_u : min_size = 23 ; exp_size = 77 ; max_size = 131,093 ; max_iov = 5 ; max_copy = 23 */ -struct lib9p_msg_Tattach { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_fid_t afid; - struct lib9p_s uname; - struct lib9p_s aname; -#if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u - lib9p_nuid_t n_uid; -#endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L -/* min_size = 19 ; exp_size = 73 ; max_size = 131,089 ; max_iov = 5 ; max_copy = 19 */ -struct lib9p_msg_Tsymlink { - lib9p_tag_t tag; - lib9p_fid_t fid; - struct lib9p_s name; - struct lib9p_s symtgt; - lib9p_nuid_t gid; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 12 ; max_iov = 1 ; max_copy = 12 */ -struct lib9p_msg_Topen { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_o_t mode; -}; - -/* min_size = 18 ; exp_size = 45 ; max_size = 65,553 ; max_iov = 3 ; max_copy = 18 */ -struct lib9p_msg_Tcreate { - lib9p_tag_t tag; - lib9p_fid_t fid; - struct lib9p_s name; - lib9p_dm_t perm; - lib9p_o_t mode; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_p9p -/* size = 12 ; max_iov = 1 ; max_copy = 12 */ -struct lib9p_msg_Topenfd { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_o_t mode; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* LIB9P_VER_9P2000 : min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ -/* LIB9P_VER_9P2000_L : min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ -/* LIB9P_VER_9P2000_e : min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ -/* LIB9P_VER_9P2000_p9p: min_size = 9 ; exp_size = 36 ; max_size = 65,544 ; max_iov = 2 ; max_copy = 9 */ -/* LIB9P_VER_9P2000_u : min_size = 13 ; exp_size = 40 ; max_size = 65,548 ; max_iov = 3 ; max_copy = 13 */ -struct lib9p_msg_Rerror { - lib9p_tag_t tag; - struct lib9p_s ename; -#if CONFIG_9P_ENABLE_9P2000_u - lib9p_errno_t errno; -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_L -/* size = 11 ; max_iov = 1 ; max_copy = 11 */ -struct lib9p_msg_Rlerror { - lib9p_tag_t tag; - lib9p_errno_t ecode; -}; - -/* size = 67 ; max_iov = 1 ; max_copy = 67 */ -struct lib9p_msg_Rstatfs { - lib9p_tag_t tag; - lib9p_super_magic_t type; - uint32_t bsize; - uint64_t blocks; - uint64_t bfree; - uint64_t bavail; - uint64_t files; - uint64_t ffree; - uint64_t fsid; - uint32_t namelen; -}; - -/* size = 15 ; max_iov = 1 ; max_copy = 15 */ -struct lib9p_msg_Tlopen { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_lo_t flags; -}; - -/* min_size = 25 ; exp_size = 52 ; max_size = 65,560 ; max_iov = 3 ; max_copy = 25 */ -struct lib9p_msg_Tlcreate { - lib9p_tag_t tag; - lib9p_fid_t fid; - struct lib9p_s name; - lib9p_lo_t flags; - lib9p_mode_t mode; - lib9p_nuid_t gid; -}; - -/* min_size = 29 ; exp_size = 56 ; max_size = 65,564 ; max_iov = 3 ; max_copy = 29 */ -struct lib9p_msg_Tmknod { - lib9p_tag_t tag; - lib9p_fid_t dfid; - struct lib9p_s name; - lib9p_mode_t mode; - uint32_t major; - uint32_t minor; - lib9p_nuid_t gid; -}; - -/* min_size = 21 ; exp_size = 48 ; max_size = 65,556 ; max_iov = 3 ; max_copy = 21 */ -struct lib9p_msg_Tmkdir { - lib9p_tag_t tag; - lib9p_fid_t dfid; - struct lib9p_s name; - lib9p_mode_t mode; - lib9p_nuid_t gid; -}; - -/* size = 15 ; max_iov = 1 ; max_copy = 15 */ -struct lib9p_msg_Tfsync { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_b4_t datasync; -}; - -/* size = 19 ; max_iov = 1 ; max_copy = 19 */ -struct lib9p_msg_Tgetattr { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_getattr_t request_mask; -}; - -/* size = 67 ; max_iov = 1 ; max_copy = 67 */ -struct lib9p_msg_Tsetattr { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_setattr_t valid; - lib9p_mode_t mode; - lib9p_nuid_t uid; - lib9p_nuid_t gid; - uint64_t filesize; - uint64_t atime_sec; - uint64_t atime_nsec; - uint64_t mtime_sec; - uint64_t mtime_nsec; -}; - -/* min_size = 34 ; exp_size = 61 ; max_size = 65,569 ; max_iov = 2 ; max_copy = 34 */ -struct lib9p_msg_Tgetlock { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_lock_type_t type; - uint64_t start; - uint64_t length; - uint32_t proc_id; - struct lib9p_s client_id; -}; - -/* min_size = 30 ; exp_size = 57 ; max_size = 65,565 ; max_iov = 2 ; max_copy = 30 */ -struct lib9p_msg_Rgetlock { - lib9p_tag_t tag; - lib9p_lock_type_t type; - uint64_t start; - uint64_t length; - uint32_t proc_id; - struct lib9p_s client_id; -}; - -/* min_size = 38 ; exp_size = 65 ; max_size = 65,573 ; max_iov = 2 ; max_copy = 38 */ -struct lib9p_msg_Tlock { - lib9p_tag_t tag; - lib9p_fid_t fid; - lib9p_lock_type_t type; - lib9p_lock_flags_t flags; - uint64_t start; - uint64_t length; - uint32_t proc_id; - struct lib9p_s client_id; -}; - -/* size = 8 ; max_iov = 1 ; max_copy = 8 */ -struct lib9p_msg_Rlock { - lib9p_tag_t tag; - lib9p_lock_status_t status; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* LIB9P_VER_9P2000 : min_size = 49 ; exp_size = 157 ; max_size = 262,189 ; max_iov = 8 ; max_copy = 49 */ -/* LIB9P_VER_9P2000_e : min_size = 49 ; exp_size = 157 ; max_size = 262,189 ; max_iov = 8 ; max_copy = 49 */ -/* LIB9P_VER_9P2000_p9p: min_size = 49 ; exp_size = 157 ; max_size = 262,189 ; max_iov = 8 ; max_copy = 49 */ -/* LIB9P_VER_9P2000_u : min_size = 63 ; exp_size = 198 ; max_size = 327,738 ; max_iov = 11 ; max_copy = 63 */ -struct lib9p_stat { - uint16_t kern_type; - uint32_t kern_dev; - struct lib9p_qid file_qid; - lib9p_dm_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; -#if CONFIG_9P_ENABLE_9P2000_u - struct lib9p_s file_extension; - lib9p_nuid_t file_owner_n_uid; - lib9p_nuid_t file_owner_n_gid; - lib9p_nuid_t file_last_modified_n_uid; -#endif /* CONFIG_9P_ENABLE_9P2000_u */ -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 20 ; max_iov = 1 ; max_copy = 20 */ -struct lib9p_msg_Rauth { - lib9p_tag_t tag; - struct lib9p_qid aqid; -}; - -/* size = 20 ; max_iov = 1 ; max_copy = 20 */ -struct lib9p_msg_Rattach { - lib9p_tag_t tag; - struct lib9p_qid qid; -}; - -/* min_size = 9 ; exp_size = 217 ; max_size = 217 ; max_iov = 1 ; max_copy = 217 */ -struct lib9p_msg_Rwalk { - lib9p_tag_t tag; - uint16_t nwqid; - struct lib9p_qid *wqid; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* size = 24 ; max_iov = 1 ; max_copy = 24 */ -struct lib9p_msg_Ropen { - lib9p_tag_t tag; - struct lib9p_qid qid; - uint32_t iounit; -}; - -/* size = 24 ; max_iov = 1 ; max_copy = 24 */ -struct lib9p_msg_Rcreate { - lib9p_tag_t tag; - struct lib9p_qid qid; - uint32_t iounit; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ -#if CONFIG_9P_ENABLE_9P2000_p9p -/* size = 28 ; max_iov = 1 ; max_copy = 28 */ -struct lib9p_msg_Ropenfd { - lib9p_tag_t tag; - struct lib9p_qid qid; - uint32_t iounit; - uint32_t unixfd; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_p9p */ -#if CONFIG_9P_ENABLE_9P2000_L -/* size = 24 ; max_iov = 1 ; max_copy = 24 */ -struct lib9p_msg_Rlopen { - lib9p_tag_t tag; - struct lib9p_qid qid; - uint32_t iounit; -}; - -/* size = 24 ; max_iov = 1 ; max_copy = 24 */ -struct lib9p_msg_Rlcreate { - lib9p_tag_t tag; - struct lib9p_qid qid; - uint32_t iounit; -}; - -/* size = 20 ; max_iov = 1 ; max_copy = 20 */ -struct lib9p_msg_Rsymlink { - lib9p_tag_t tag; - struct lib9p_qid qid; -}; - -/* size = 20 ; max_iov = 1 ; max_copy = 20 */ -struct lib9p_msg_Rmknod { - lib9p_tag_t tag; - struct lib9p_qid qid; -}; - -/* size = 160 ; max_iov = 1 ; max_copy = 160 */ -struct lib9p_msg_Rgetattr { - lib9p_tag_t tag; - lib9p_getattr_t valid; - struct lib9p_qid qid; - lib9p_mode_t mode; - lib9p_nuid_t uid; - lib9p_nuid_t gid; - uint64_t nlink; - uint64_t rdev; - uint64_t filesize; - uint64_t blksize; - uint64_t blocks; - uint64_t atime_sec; - uint64_t atime_nsec; - uint64_t mtime_sec; - uint64_t mtime_nsec; - uint64_t ctime_sec; - uint64_t ctime_nsec; - uint64_t btime_sec; - uint64_t btime_nsec; - uint64_t gen; - uint64_t data_version; -}; - -/* size = 20 ; max_iov = 1 ; max_copy = 20 */ -struct lib9p_msg_Rmkdir { - lib9p_tag_t tag; - struct lib9p_qid qid; -}; - -#endif /* CONFIG_9P_ENABLE_9P2000_L */ -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -/* LIB9P_VER_9P2000 : min_size = 58 ; exp_size = 166 ; max_size = 262,198 ; max_iov = 8 ; max_copy = 58 */ -/* LIB9P_VER_9P2000_e : min_size = 58 ; exp_size = 166 ; max_size = 262,198 ; max_iov = 8 ; max_copy = 58 */ -/* LIB9P_VER_9P2000_p9p: min_size = 58 ; exp_size = 166 ; max_size = 262,198 ; max_iov = 8 ; max_copy = 58 */ -/* LIB9P_VER_9P2000_u : min_size = 72 ; exp_size = 207 ; max_size = 327,747 ; max_iov = 11 ; max_copy = 72 */ -struct lib9p_msg_Rstat { - lib9p_tag_t tag; - struct lib9p_stat stat; -}; - -/* LIB9P_VER_9P2000 : min_size = 62 ; exp_size = 170 ; max_size = 262,202 ; max_iov = 8 ; max_copy = 62 */ -/* LIB9P_VER_9P2000_e : min_size = 62 ; exp_size = 170 ; max_size = 262,202 ; max_iov = 8 ; max_copy = 62 */ -/* LIB9P_VER_9P2000_p9p: min_size = 62 ; exp_size = 170 ; max_size = 262,202 ; max_iov = 8 ; max_copy = 62 */ -/* LIB9P_VER_9P2000_u : min_size = 76 ; exp_size = 211 ; max_size = 327,751 ; max_iov = 11 ; max_copy = 76 */ -struct lib9p_msg_Twstat { - lib9p_tag_t tag; - lib9p_fid_t fid; - struct lib9p_stat stat; -}; -#endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ - -/* containers *****************************************************************/ - -#define _LIB9P_MAX(a, b) ((a) > (b)) ? (a) : (b) - -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u - #if CONFIG_9P_ENABLE_9P2000_e - #define LIB9P_TMSG_MAX_IOV _LIB9P_MAX(32, 2 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2)) - #else - #define LIB9P_TMSG_MAX_IOV 32 - #endif -#endif - -#if CONFIG_9P_ENABLE_9P2000_u - #if CONFIG_9P_ENABLE_9P2000_e - #define LIB9P_TMSG_MAX_COPY _LIB9P_MAX(76, 17 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2)) - #else - #define LIB9P_TMSG_MAX_COPY 76 - #endif -#elif CONFIG_9P_ENABLE_9P2000_L - #if CONFIG_9P_ENABLE_9P2000_e - #define LIB9P_TMSG_MAX_COPY _LIB9P_MAX(67, 17 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2)) - #else - #define LIB9P_TMSG_MAX_COPY 67 - #endif -#elif CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p - #if CONFIG_9P_ENABLE_9P2000_e - #define LIB9P_TMSG_MAX_COPY _LIB9P_MAX(62, 17 + (CONFIG_9P_MAX_9P2000_e_WELEM * 2)) - #else - #define LIB9P_TMSG_MAX_COPY 62 - #endif -#endif - -#if CONFIG_9P_ENABLE_9P2000_u - #define LIB9P_RMSG_MAX_IOV 11 -#elif CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p - #define LIB9P_RMSG_MAX_IOV 8 -#elif CONFIG_9P_ENABLE_9P2000_L - #define LIB9P_RMSG_MAX_IOV 2 -#endif - -#if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u - #define LIB9P_RMSG_MAX_COPY 217 -#endif - -struct lib9p_Tmsg_send_buf { - size_t iov_cnt; - struct iovec iov[LIB9P_TMSG_MAX_IOV]; - uint8_t copied[LIB9P_TMSG_MAX_COPY]; -}; - -struct lib9p_Rmsg_send_buf { - size_t iov_cnt; - struct iovec iov[LIB9P_RMSG_MAX_IOV]; - uint8_t copied[LIB9P_RMSG_MAX_COPY]; -}; diff --git a/lib9p/include/lib9p/linux-errno.h b/lib9p/include/lib9p/linux-errno.h deleted file mode 100644 index e7c74f5..0000000 --- a/lib9p/include/lib9p/linux-errno.h +++ /dev/null @@ -1,139 +0,0 @@ -/* lib9p/linux-errno.h - Generated by `lib9p/include/lib9p/linux-errno.h.gen 3rd-party/linux-errno.txt`. DO NOT EDIT! */ -/* 3rd-party/linux-errno.txt - Generated from build-aux/linux-errno.txt.gen and linux.git v6.7. DO NOT EDIT! */ - -#ifndef _LIB9P_LINUX_ERRNO_H_ -#define _LIB9P_LINUX_ERRNO_H_ - -#define LINUX_EPERM 1 /* Operation not permitted */ -#define LINUX_ENOENT 2 /* No such file or directory */ -#define LINUX_ESRCH 3 /* No such process */ -#define LINUX_EINTR 4 /* Interrupted system call */ -#define LINUX_EIO 5 /* I/O error */ -#define LINUX_ENXIO 6 /* No such device or address */ -#define LINUX_E2BIG 7 /* Argument list too long */ -#define LINUX_ENOEXEC 8 /* Exec format error */ -#define LINUX_EBADF 9 /* Bad file number */ -#define LINUX_ECHILD 10 /* No child processes */ -#define LINUX_EAGAIN 11 /* Try again */ -#define LINUX_ENOMEM 12 /* Out of memory */ -#define LINUX_EACCES 13 /* Permission denied */ -#define LINUX_EFAULT 14 /* Bad address */ -#define LINUX_ENOTBLK 15 /* Block device required */ -#define LINUX_EBUSY 16 /* Device or resource busy */ -#define LINUX_EEXIST 17 /* File exists */ -#define LINUX_EXDEV 18 /* Cross-device link */ -#define LINUX_ENODEV 19 /* No such device */ -#define LINUX_ENOTDIR 20 /* Not a directory */ -#define LINUX_EISDIR 21 /* Is a directory */ -#define LINUX_EINVAL 22 /* Invalid argument */ -#define LINUX_ENFILE 23 /* File table overflow */ -#define LINUX_EMFILE 24 /* Too many open files */ -#define LINUX_ENOTTY 25 /* Not a typewriter */ -#define LINUX_ETXTBSY 26 /* Text file busy */ -#define LINUX_EFBIG 27 /* File too large */ -#define LINUX_ENOSPC 28 /* No space left on device */ -#define LINUX_ESPIPE 29 /* Illegal seek */ -#define LINUX_EROFS 30 /* Read-only file system */ -#define LINUX_EMLINK 31 /* Too many links */ -#define LINUX_EPIPE 32 /* Broken pipe */ -#define LINUX_EDOM 33 /* Math argument out of domain of func */ -#define LINUX_ERANGE 34 /* Math result not representable */ -#define LINUX_EDEADLK 35 /* Resource deadlock would occur */ -#define LINUX_ENAMETOOLONG 36 /* File name too long */ -#define LINUX_ENOLCK 37 /* No record locks available */ -#define LINUX_ENOSYS 38 /* Invalid system call number */ -#define LINUX_ENOTEMPTY 39 /* Directory not empty */ -#define LINUX_ELOOP 40 /* Too many symbolic links encountered */ -#define LINUX_ENOMSG 42 /* No message of desired type */ -#define LINUX_EIDRM 43 /* Identifier removed */ -#define LINUX_ECHRNG 44 /* Channel number out of range */ -#define LINUX_EL2NSYNC 45 /* Level 2 not synchronized */ -#define LINUX_EL3HLT 46 /* Level 3 halted */ -#define LINUX_EL3RST 47 /* Level 3 reset */ -#define LINUX_ELNRNG 48 /* Link number out of range */ -#define LINUX_EUNATCH 49 /* Protocol driver not attached */ -#define LINUX_ENOCSI 50 /* No CSI structure available */ -#define LINUX_EL2HLT 51 /* Level 2 halted */ -#define LINUX_EBADE 52 /* Invalid exchange */ -#define LINUX_EBADR 53 /* Invalid request descriptor */ -#define LINUX_EXFULL 54 /* Exchange full */ -#define LINUX_ENOANO 55 /* No anode */ -#define LINUX_EBADRQC 56 /* Invalid request code */ -#define LINUX_EBADSLT 57 /* Invalid slot */ -#define LINUX_EBFONT 59 /* Bad font file format */ -#define LINUX_ENOSTR 60 /* Device not a stream */ -#define LINUX_ENODATA 61 /* No data available */ -#define LINUX_ETIME 62 /* Timer expired */ -#define LINUX_ENOSR 63 /* Out of streams resources */ -#define LINUX_ENONET 64 /* Machine is not on the network */ -#define LINUX_ENOPKG 65 /* Package not installed */ -#define LINUX_EREMOTE 66 /* Object is remote */ -#define LINUX_ENOLINK 67 /* Link has been severed */ -#define LINUX_EADV 68 /* Advertise error */ -#define LINUX_ESRMNT 69 /* Srmount error */ -#define LINUX_ECOMM 70 /* Communication error on send */ -#define LINUX_EPROTO 71 /* Protocol error */ -#define LINUX_EMULTIHOP 72 /* Multihop attempted */ -#define LINUX_EDOTDOT 73 /* RFS specific error */ -#define LINUX_EBADMSG 74 /* Not a data message */ -#define LINUX_EOVERFLOW 75 /* Value too large for defined data type */ -#define LINUX_ENOTUNIQ 76 /* Name not unique on network */ -#define LINUX_EBADFD 77 /* File descriptor in bad state */ -#define LINUX_EREMCHG 78 /* Remote address changed */ -#define LINUX_ELIBACC 79 /* Can not access a needed shared library */ -#define LINUX_ELIBBAD 80 /* Accessing a corrupted shared library */ -#define LINUX_ELIBSCN 81 /* .lib section in a.out corrupted */ -#define LINUX_ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define LINUX_ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define LINUX_EILSEQ 84 /* Illegal byte sequence */ -#define LINUX_ERESTART 85 /* Interrupted system call should be restarted */ -#define LINUX_ESTRPIPE 86 /* Streams pipe error */ -#define LINUX_EUSERS 87 /* Too many users */ -#define LINUX_ENOTSOCK 88 /* Socket operation on non-socket */ -#define LINUX_EDESTADDRREQ 89 /* Destination address required */ -#define LINUX_EMSGSIZE 90 /* Message too long */ -#define LINUX_EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define LINUX_ENOPROTOOPT 92 /* Protocol not available */ -#define LINUX_EPROTONOSUPPORT 93 /* Protocol not supported */ -#define LINUX_ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define LINUX_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define LINUX_EPFNOSUPPORT 96 /* Protocol family not supported */ -#define LINUX_EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define LINUX_EADDRINUSE 98 /* Address already in use */ -#define LINUX_EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define LINUX_ENETDOWN 100 /* Network is down */ -#define LINUX_ENETUNREACH 101 /* Network is unreachable */ -#define LINUX_ENETRESET 102 /* Network dropped connection because of reset */ -#define LINUX_ECONNABORTED 103 /* Software caused connection abort */ -#define LINUX_ECONNRESET 104 /* Connection reset by peer */ -#define LINUX_ENOBUFS 105 /* No buffer space available */ -#define LINUX_EISCONN 106 /* Transport endpoint is already connected */ -#define LINUX_ENOTCONN 107 /* Transport endpoint is not connected */ -#define LINUX_ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define LINUX_ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define LINUX_ETIMEDOUT 110 /* Connection timed out */ -#define LINUX_ECONNREFUSED 111 /* Connection refused */ -#define LINUX_EHOSTDOWN 112 /* Host is down */ -#define LINUX_EHOSTUNREACH 113 /* No route to host */ -#define LINUX_EALREADY 114 /* Operation already in progress */ -#define LINUX_EINPROGRESS 115 /* Operation now in progress */ -#define LINUX_ESTALE 116 /* Stale file handle */ -#define LINUX_EUCLEAN 117 /* Structure needs cleaning */ -#define LINUX_ENOTNAM 118 /* Not a XENIX named type file */ -#define LINUX_ENAVAIL 119 /* No XENIX semaphores available */ -#define LINUX_EISNAM 120 /* Is a named type file */ -#define LINUX_EREMOTEIO 121 /* Remote I/O error */ -#define LINUX_EDQUOT 122 /* Quota exceeded */ -#define LINUX_ENOMEDIUM 123 /* No medium found */ -#define LINUX_EMEDIUMTYPE 124 /* Wrong medium type */ -#define LINUX_ECANCELED 125 /* Operation Canceled */ -#define LINUX_ENOKEY 126 /* Required key not available */ -#define LINUX_EKEYEXPIRED 127 /* Key has expired */ -#define LINUX_EKEYREVOKED 128 /* Key has been revoked */ -#define LINUX_EKEYREJECTED 129 /* Key was rejected by service */ -#define LINUX_EOWNERDEAD 130 /* Owner died */ -#define LINUX_ENOTRECOVERABLE 131 /* State not recoverable */ -#define LINUX_ERFKILL 132 /* Operation not possible due to RF-kill */ -#define LINUX_EHWPOISON 133 /* Memory page has hardware error */ - -#endif /* _LIB9P_LINUX_ERRNO_H_ */ diff --git a/lib9p/include/lib9p/linux-errno.h.gen b/lib9p/include/lib9p/linux-errno.h.gen deleted file mode 100755 index 2c736a2..0000000 --- a/lib9p/include/lib9p/linux-errno.h.gen +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python -# lib9p/linux-errno.h.gen - Generate a C header from a list of errno numbers -# -# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> -# SPDX-License-Identifier: AGPL-3.0-or-later - -import sys - - -def print_errnos() -> None: - print( - f"/* lib9p/linux-errno.h - Generated by `{' '.join(sys.argv)}`. DO NOT EDIT! */" - ) - errnos: dict[str, tuple[int, str]] = {} - for txtlist in sys.argv[1:]: - with open(txtlist, "r", encoding="utf-8") 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 _LIB9P_LINUX_ERRNO_H_") - print("#define _LIB9P_LINUX_ERRNO_H_") - print() - namelen = max(len(name) for name in errnos) - numlen = max(len(str(num)) for (num, desc) in errnos.values()) - for name, [num, msg] in errnos.items(): - print(f"#define LINUX_{name:<{namelen}} {num:>{numlen}} /* {msg} */") - print() - print("#endif /* _LIB9P_LINUX_ERRNO_H_ */") - - -if __name__ == "__main__": - print_errnos() diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h deleted file mode 100644 index ff5ebdc..0000000 --- a/lib9p/include/lib9p/srv.h +++ /dev/null @@ -1,179 +0,0 @@ -/* lib9p/srv.h - 9P server - * - * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#ifndef _LIB9P_SRV_H_ -#define _LIB9P_SRV_H_ - -#include <libcr/coroutine.h> -#include <libcr_ipc/rpc.h> -#include <libcr_ipc/chan.h> -#include <libhw/generic/net.h> -#include <libmisc/assert.h> -#include <libmisc/private.h> -#include <libobj/obj.h> - -#include <lib9p/9p.h> - -/* context ********************************************************************/ - -CR_CHAN_DECLARE(_lib9p_srv_flushch, bool) - -struct lib9p_srv_ctx { - struct lib9p_ctx basectx; - uint32_t uid; - struct lib9p_s uname; - - BEGIN_PRIVATE(LIB9P_SRV_H) - _lib9p_srv_flushch_t _flushch; - END_PRIVATE(LIB9P_SRV_H) -}; - -bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx); - -int lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx); - -/* interface definitions ******************************************************/ - -lo_interface lib9p_srv_fio; -lo_interface lib9p_srv_dio; - -/* FIXME: I don't like that the pointers returned by stat() and - * pread() have to remain live after they return. Perhaps a - * `respond()`-callback? But that just reads as gross in C. - * - * FIXME: It would be nice if pread() could return more than 1 iovec. - */ -#define lib9p_srv_file_LO_IFACE \ - /* resource management **********************************************/ \ - \ - /** \ - * free() is be called when all FIDs associated with the file are \ - * clunked. \ - * \ - * free() MUST NOT error. \ - */ \ - LO_FUNC(void , free ) \ - \ - /** \ - * qid() is called frequently and returns the current QID of the file. \ - * The .path field MUST never change, the .type field may change in \ - * response to wstat() calls (but the QT_DIR bit MUST NOT change), and \ - * the .vers field may change frequently in response to any number of \ - * things (wstat(), write(), or non-9P events). \ - * \ - * qid() MUST NOT error. \ - */ \ - LO_FUNC(struct lib9p_qid , qid ) \ - \ - /* non-"opened" generic I/O *****************************************/ \ - \ - LO_FUNC(struct lib9p_stat , stat , struct lib9p_srv_ctx *) \ - LO_FUNC(void , wstat , struct lib9p_srv_ctx *, \ - struct lib9p_stat new) \ - LO_FUNC(void , remove , struct lib9p_srv_ctx *) \ - \ - /* non-"opened" directory I/O ***************************************/ \ - \ - LO_FUNC(lo_interface lib9p_srv_file, dwalk , struct lib9p_srv_ctx *, \ - struct lib9p_s childname) \ - LO_FUNC(lo_interface lib9p_srv_file, dcreate, struct lib9p_srv_ctx *, \ - struct lib9p_s childname, \ - lib9p_dm_t perm, \ - lib9p_o_t flags) \ - \ - /* open() for I/O ***************************************************/ \ - \ - LO_FUNC(lo_interface lib9p_srv_fio , fopen , struct lib9p_srv_ctx *, \ - bool rd, bool wr, \ - bool trunc) \ - LO_FUNC(lo_interface lib9p_srv_dio , dopen , struct lib9p_srv_ctx *) -LO_INTERFACE(lib9p_srv_file); - -#define lib9p_srv_fio_LO_IFACE \ - LO_FUNC(struct lib9p_qid , qid ) \ - LO_FUNC(void , iofree ) \ - LO_FUNC(uint32_t , iounit ) \ - LO_FUNC(void , pread , struct lib9p_srv_ctx *, \ - uint32_t byte_count, \ - uint64_t byte_offset, \ - struct iovec *ret) \ - LO_FUNC(uint32_t , pwrite , struct lib9p_srv_ctx *, \ - void *buf, \ - uint32_t byte_count, \ - uint64_t byte_offset) -LO_INTERFACE(lib9p_srv_fio); - -/* FIXME: The dio interface just feels clunky. I'm not in a rush to - * change it because util9p_static_dir is already implemented and I - * don't anticipate the sbc-harness needing another dio - * implementation. But if I wanted lib9p to be used outside of - * sbc-harness, this is one of the first things that I'd want to - * change. - */ -#define lib9p_srv_dio_LO_IFACE \ - LO_FUNC(struct lib9p_qid , qid ) \ - LO_FUNC(void , iofree ) \ - LO_FUNC(size_t /* <- obj cnt */ , dread , struct lib9p_srv_ctx *, \ - uint8_t *buf, \ - /* num bytes -> */ uint32_t byte_count, \ - /* starting at this object -> */ size_t obj_offset) -LO_INTERFACE(lib9p_srv_dio); - -#define LIB9P_SRV_NOTDIR(TYP, NAM) \ - static lo_interface lib9p_srv_file NAM##_dwalk (TYP *, struct lib9p_srv_ctx *, struct lib9p_s) { assert_notreached("not a directory"); } \ - static lo_interface lib9p_srv_file NAM##_dcreate(TYP *, struct lib9p_srv_ctx *, struct lib9p_s, lib9p_dm_t, lib9p_o_t) { assert_notreached("not a directory"); } \ - static lo_interface lib9p_srv_dio NAM##_dopen (TYP *, struct lib9p_srv_ctx *) { assert_notreached("not a directory"); } - -#define LIB9P_SRV_NOTFILE(TYP, NAM) \ - static lo_interface lib9p_srv_fio NAM##_fopen (TYP *, struct lib9p_srv_ctx *, bool, bool, bool) { assert_notreached("not a file"); } - -/* main server entrypoints ****************************************************/ - -CR_RPC_DECLARE(_lib9p_srv_reqch, struct _lib9p_srv_req *, bool) - -struct lib9p_srv { - /* Things you provide */ - void /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */ - lo_interface lib9p_srv_file (*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename); - - /* For internal use */ - BEGIN_PRIVATE(LIB9P_SRV_H) - unsigned int readers; - unsigned int writers; - _lib9p_srv_reqch_t _reqch; - END_PRIVATE(LIB9P_SRV_H) -}; - -/** - * In an infinite loop, accept a connection and read messages from it until - * close; dispatching requests to a pool of lib9p_srv_write_cr() coroutines - * with the same `srv`. - * - * Will just close the connection if a T-message has a size[4] <7. - * - * @param srv: The server configuration and state; has an associated pool of - * lib9p_srv_write_cr() coroutines. - * @param listener: The listener object to accept connections from. - * - * @errno LINUX_EMSGSIZE T-message has size[4] bigger than max_msg_size - * @errno LINUX_EDOM Tversion specified an impossibly small max_msg_size - * @errno LINUX_EOPNOTSUPP T-message has an R-message type, or an unrecognized T-message type - * @errno LINUX_EBADMSG T-message has wrong size[4] for its content, or has invalid UTF-8 - * @errno LINUX_ERANGE R-message does not fit into max_msg_size - */ -[[noreturn]] void lib9p_srv_read_cr(struct lib9p_srv *srv, lo_interface net_stream_listener listener); - -/** - * Service requests to the `struct lib9p_srv *srv` argument that have been - * read by lib9p_srv_read_cr(). - * - * @param struct lib9p_srv *srv: The server configuration and state; has an - * associated pool of lib9p_srv_read_cr() - * coroutines. - */ -COROUTINE lib9p_srv_write_cr(void *_srv); - -#endif /* _LIB9P_SRV_H_ */ diff --git a/lib9p/internal.h b/lib9p/internal.h deleted file mode 100644 index 92340a5..0000000 --- a/lib9p/internal.h +++ /dev/null @@ -1,100 +0,0 @@ -/* lib9p/internal.h - Internal machinery shared between parts of lib9p - * - * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#ifndef _LIB9P_INTERNAL_H_ -#define _LIB9P_INTERNAL_H_ - -#include <stddef.h> /* for size_t */ -#include <limits.h> /* for SSIZE_MAX, not set by newlib */ -#ifndef SSIZE_MAX -#define SSIZE_MAX (SIZE_MAX >> 1) -#endif - -#include <libmisc/endian.h> -#include <libmisc/macro.h> - -#include <lib9p/9p.h> - -/* configuration **************************************************************/ - -#include "config.h" - -#ifndef CONFIG_9P_MAX_MSG_SIZE - #error config.h must define CONFIG_9P_MAX_MSG_SIZE -#endif -#ifndef CONFIG_9P_MAX_HOSTMSG_SIZE - #error config.h must define CONFIG_9P_MAX_HOSTMSG_SIZE -#endif -#ifndef CONFIG_9P_MAX_ERR_SIZE - #error config.h must define CONFIG_9P_MAX_ERR_SIZE -#endif - -static_assert(CONFIG_9P_MAX_ERR_SIZE <= UINT16_MAX); -static_assert(CONFIG_9P_MAX_MSG_SIZE <= CONFIG_9P_MAX_HOSTMSG_SIZE); -static_assert(CONFIG_9P_MAX_HOSTMSG_SIZE <= SSIZE_MAX); - -/* tables / exports ***********************************************************/ - -typedef ssize_t (*_validate_fn_t)(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes); -typedef void (*_unmarshal_fn_t)(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out); - -struct _marshal_ret { - size_t net_iov_cnt; - struct iovec *net_iov; - size_t net_copied_size; - uint8_t *net_copied; -}; -typedef bool (*_marshal_fn_t)(struct lib9p_ctx *ctx, void *host_val, struct _marshal_ret *ret); - -struct _lib9p_recv_tentry { - size_t basesize; - _validate_fn_t validate; - _unmarshal_fn_t unmarshal; -}; - -struct _lib9p_send_tentry { - _marshal_fn_t marshal; -}; - -extern const char *const _lib9p_table_ver_name[LIB9P_VER_NUM]; -extern const char *const _lib9p_table_msg_name[LIB9P_VER_NUM][0x100]; -extern const uint32_t _lib9p_table_msg_min_size[LIB9P_VER_NUM]; -extern const struct _lib9p_recv_tentry _lib9p_table_Tmsg_recv[LIB9P_VER_NUM][0x80]; -extern const struct _lib9p_recv_tentry _lib9p_table_Rmsg_recv[LIB9P_VER_NUM][0x80]; -extern const struct _lib9p_send_tentry _lib9p_table_Tmsg_send[LIB9P_VER_NUM][0x80]; -extern const struct _lib9p_send_tentry _lib9p_table_Rmsg_send[LIB9P_VER_NUM][0x80]; - -ssize_t _lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size); -void _lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out); -bool _lib9p_stat_marshal(struct lib9p_ctx *ctx, struct lib9p_stat *val, struct _marshal_ret *ret); - -/* unmarshal utilities ********************************************************/ - -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) - -#endif /* _LIB9P_INTERNAL_H_ */ diff --git a/lib9p/linux-errno.txt.gen b/lib9p/linux-errno.txt.gen new file mode 100755 index 0000000..687e58b --- /dev/null +++ b/lib9p/linux-errno.txt.gen @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# lib9p/linux-errno.txt.gen - Generate a listing of Linux kernel errnos +# +# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +set -e +linux_git=${1:?} +outfile=${2:?} + +( + cd "${linux_git}" + echo "# ${outfile} - Generated from $0 and linux.git $(git describe). DO NOT EDIT!" + git ls-files include/uapi/ | grep errno | + xargs sed -nE 's,#\s*define\s+(E[A-Z0-9]+)\s+([0-9]+)\s+/\* (.*) \*/,\2 \1 \3,p' | + sort --numeric-sort +) >"${outfile}" diff --git a/lib9p/map.h b/lib9p/map.h deleted file mode 100644 index ab9564f..0000000 --- a/lib9p/map.h +++ /dev/null @@ -1,116 +0,0 @@ -/* lib9p/map.h - A really dumb map/dict data structure - * - * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -#include "internal.h" - -/** - * `#define` `NAME`, `KEY_T`, `VAL_T`, and `CAP`; then `#include - * "map.h". - */ - -#ifndef NAME - #error NAME must be defined -#endif -#ifndef KEY_T - #error KEY_T must be defined -#endif -#ifndef VAL_T - #error VAL_T must be defined -#endif -#ifndef CAP - #error CAP must be defined -#endif - -#ifndef MAP_KEY -#define MAP_KV(TNAME) LM_CAT3(_,TNAME,_kv) -#define MAP_METHOD(TNAME, MNAME) LM_CAT3(TNAME,_,MNAME) -#define MAP_FOREACH(m, k, v) \ - for (size_t i = 0; i < LM_ARRAY_LEN((m)->items); i++) \ - if ( ({ k = (m)->items[i].key; v = &(m)->items[i].val; (m)->items[i].set; }) ) -#endif - -/* This implementation is just an array that we brute-force search - * over for a slot. I don't want to use the heap, which means - * statically-sized maps, and I'm probably going to choose a low - * static size, so this is fine. */ - -struct MAP_KV(NAME) { - bool set; - KEY_T key; - VAL_T val; -}; - -struct NAME { - size_t len; - struct MAP_KV(NAME) items[CAP]; -}; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" - -/** - * Load an item from the map; return a pointer to the in-map value, or - * NULL if the item is not in the map. - */ -static VAL_T *MAP_METHOD(NAME,load)(struct NAME *m, KEY_T k) { - if (!m->len) - return NULL; - for (size_t i = 0; i < LM_ARRAY_LEN(m->items); i++) - if (m->items[i].set && m->items[i].key == k) - return &(m->items[i].val); - return NULL; -} - -/** - * Store an item into the map, perhaps replacing an existing value. - * Return a pointer to the in-map value, or NULL if the map is full. - */ -static VAL_T *MAP_METHOD(NAME,store)(struct NAME *m, KEY_T k, VAL_T v) { - VAL_T *old = MAP_METHOD(NAME,load)(m, k); - if (old) { - *old = v; - return old; - } - if (m->len == LM_ARRAY_LEN(m->items)) - return NULL; - for (size_t i = 0; i < LM_ARRAY_LEN(m->items); i++) - if (!m->items[i].set) { - m->len++; - m->items[i].set = true; - m->items[i].key = k; - m->items[i].val = v; - return &(m->items[i].val); - } - assert_notreached("should have returned from inside for() loop"); -} - -/** - * Delete an item from the map. Returns true if an item was deleted, - * false if no such item was in the map. - */ -static bool MAP_METHOD(NAME,del)(struct NAME *m, KEY_T k) { - if (!m->len) - return NULL; - for (size_t i = 0; i < LM_ARRAY_LEN(m->items); i++) - if (m->items[i].set && m->items[i].key == k) { - m->items[i].set = false; - m->len--; - return true; - } - return false; -} - -#pragma GCC diagnostic pop - -#undef NAME -#undef KEY_T -#undef VAL_T -#undef CAP - -/* Keep the linter happy. */ -#ifndef _LIB9P_MAP_H_ -#define _LIB9P_MAP_H_ -#endif /* _LIB9P_MAP_H_ */ diff --git a/lib9p/srv.c b/lib9p/srv.c index 50d0b78..f4b904e 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -4,15 +4,22 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include <alloca.h> -#include <inttypes.h> /* for PRI* */ +#include <limits.h> /* for SSIZE_MAX, not set by newlib */ +#include <stddef.h> /* for size_t */ +#include <stdlib.h> /* for malloc() */ +#include <string.h> /* for memcpy() */ +#ifndef SSIZE_MAX +#define SSIZE_MAX (SIZE_MAX >> 1) +#endif #include <libcr/coroutine.h> #include <libcr_ipc/chan.h> #include <libcr_ipc/mutex.h> -#include <libcr_ipc/select.h> -#include <libmisc/assert.h> #include <libhw/generic/net.h> +#include <libmisc/alloc.h> +#include <libmisc/assert.h> +#include <libmisc/endian.h> +#include <libmisc/map.h> #define LOG_NAME 9P_SRV #include <libmisc/log.h> @@ -20,40 +27,60 @@ #define IMPLEMENTATION_FOR_LIB9P_SRV_H YES #include <lib9p/srv.h> -#include "internal.h" +#include "srv_errno.h" -#ifndef CONFIG_9P_SRV_MAX_FIDS - #error config.h must define CONFIG_9P_SRV_MAX_FIDS -#endif -#ifndef CONFIG_9P_SRV_MAX_REQS - #error config.h must define CONFIG_9P_SRV_MAX_REQS +/* config *********************************************************************/ + +#include "config.h" + +#ifndef CONFIG_9P_SRV_MAX_MSG_SIZE + #error config.h must define CONFIG_9P_SRV_MAX_MSG_SIZE #endif -#ifndef CONFIG_9P_SRV_MAX_DEPTH - /* 1=just the root dir, 2=just files in the root dir, 3=1 subdir, ... */ - #error config.h must define CONFIG_9P_SRV_MAX_DEPTH +#ifndef CONFIG_9P_SRV_MAX_HOSTMSG_SIZE + #error config.h must define CONFIG_9P_SRV_MAX_HOSTMSG_SIZE #endif +static_assert(CONFIG_9P_SRV_MAX_MSG_SIZE <= CONFIG_9P_SRV_MAX_HOSTMSG_SIZE); +static_assert(CONFIG_9P_SRV_MAX_HOSTMSG_SIZE <= SSIZE_MAX); /* context ********************************************************************/ bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx) { assert(ctx); - return _lib9p_srv_flushch_can_send(&ctx->_flushch); + return cr_chan_can_send(&ctx->flush_ch); } -int lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) { - assert(ctx); - assert(_lib9p_srv_flushch_can_send(&ctx->_flushch)); - lib9p_error(&ctx->basectx, LINUX_ECANCELED, "request canceled by flush"); - _lib9p_srv_flushch_send(&ctx->_flushch, true); - return -1; -} +#define req_debug(...) \ + log_debugln( \ + "cid=", cr_getcid(), ": ", \ + lib9p_msgtype_str(ctx->basectx.version, ctx->net_bytes[4]), "(tag=", ctx->tag, "): ", \ + __VA_ARGS__) /* structs ********************************************************************/ +void lib9p_srv_stat_assert(struct lib9p_srv_stat stat) { + assert( ((bool)(stat.mode & LIB9P_DM_DIR )) == ((bool)(stat.qid.type & LIB9P_QT_DIR )) ); + assert( ((bool)(stat.mode & LIB9P_DM_APPEND)) == ((bool)(stat.qid.type & LIB9P_QT_APPEND)) ); + assert( ((bool)(stat.mode & LIB9P_DM_EXCL )) == ((bool)(stat.qid.type & LIB9P_QT_EXCL )) ); + assert( ((bool)(stat.mode & LIB9P_DM_AUTH )) == ((bool)(stat.qid.type & LIB9P_QT_AUTH )) ); + assert( ((bool)(stat.mode & LIB9P_DM_TMP )) == ((bool)(stat.qid.type & LIB9P_QT_TMP )) ); + assert( (stat.size == 0) || !(stat.mode & LIB9P_DM_DIR) ); +} + +enum srv_filetype { + SRV_FILETYPE_FILE, + SRV_FILETYPE_DIR, + SRV_FILETYPE_AUTH, +}; + +/* path *****************************************/ + typedef typeof( ((struct lib9p_qid){}).path ) srv_path_t; struct srv_pathinfo { lo_interface lib9p_srv_file file; + enum srv_filetype type; + /* .parent_dir is used for (1) Twalk(".."), and (2) for checking + * permissions on the parent directory for remove(). */ srv_path_t parent_dir; /* References from other srv_pathinfos (via .parent_dir) or @@ -63,21 +90,19 @@ struct srv_pathinfo { unsigned int io_refcount; }; -#define NAME pathmap -#define KEY_T srv_path_t -#define VAL_T struct srv_pathinfo -/* ( naive ) + ( working space for walk() ) */ -#define CAP ( (CONFIG_9P_SRV_MAX_FIDS*CONFIG_9P_SRV_MAX_DEPTH) + (CONFIG_9P_SRV_MAX_REQS*2) ) -#include "map.h" +/* fid ******************************************/ #define FIDFLAG_OPEN_R (1<<0) #define FIDFLAG_OPEN_W (1<<1) #define FIDFLAG_RCLOSE (1<<2) +#define FIDFLAG_APPEND (1<<3) #define FIDFLAG_OPEN (FIDFLAG_OPEN_R|FIDFLAG_OPEN_W) -struct _srv_fidinfo { +struct srv_fidinfo { srv_path_t path; + struct lib9p_srv_userid *user; uint8_t flags; + enum srv_filetype type; union { struct { lo_interface lib9p_srv_fio io; @@ -86,31 +111,28 @@ struct _srv_fidinfo { lo_interface lib9p_srv_dio io; size_t idx; uint64_t off; + struct lib9p_srv_dirent buffered_dirent; } dir; + struct { + struct lib9p_s aname; + bool completed; + } auth; }; }; +typedef struct srv_fidinfo *srv_fidinfop; +DECLARE_ERROR_OR(srv_fidinfop); -#define NAME fidmap -#define KEY_T lib9p_fid_t -#define VAL_T struct _srv_fidinfo -#define CAP CONFIG_9P_SRV_MAX_FIDS -#include "map.h" - -#define NAME reqmap -#define KEY_T lib9p_tag_t -#define VAL_T struct _lib9p_srv_req * -#define CAP CONFIG_9P_SRV_MAX_REQS -#include "map.h" - -/* The hierarchy of concepts is: +/* contexts ************************************** + * + * The hierarchy of contexts is: * * server -> connection -> session -> request * */ -/* struct _srv_srv {} is defined in <lib9p/srv.h> */ +/* struct lib9p_srv {} is defined in <lib9p/srv.h> */ -struct _srv_conn { +struct srv_conn { /* immutable */ struct lib9p_srv *parent_srv; lo_interface net_stream_conn fd; @@ -119,241 +141,464 @@ struct _srv_conn { cr_mutex_t writelock; }; -struct _srv_sess { +#define srv_sess _lib9p_srv_sess +MAP_DECLARE(srv_pathmap, srv_path_t, struct srv_pathinfo); +MAP_DECLARE(srv_fidmap, lib9p_fid_t, struct srv_fidinfo); +MAP_DECLARE(srv_reqmap, lib9p_tag_t, struct lib9p_srv_ctx *); +struct srv_sess { /* immutable */ - struct _srv_conn *parent_conn; + struct srv_conn *parent_conn; enum lib9p_version version; uint32_t max_msg_size; - uint32_t rerror_overhead; /* mutable */ bool initialized; bool closing; - struct pathmap paths; /* srv_path_t => lib9p_srv_file + metadata */ - struct fidmap fids; /* lib9p_fid_t => lib9p_srv_{fio,dio} + metadata */ - struct reqmap reqs; /* lib9p_tag_t => *_lib9p_srv_req */ + struct srv_pathmap paths; /* srv_path_t => `lib9p_srv_file` + metadata */ + struct srv_fidmap fids; /* lib9p_fid_t => `lib9p_srv_{fio,dio}` + metadata */ + struct srv_reqmap reqs; /* lib9p_tag_t => `struct srv_req *` */ }; -struct _lib9p_srv_req { - /* immutable */ - struct _srv_sess *parent_sess; - uint16_t tag; - uint8_t *net_bytes; - /* mutable */ - struct lib9p_srv_ctx ctx; -}; +#define srv_req lib9p_srv_ctx /* struct lib9p_srv_ctx {} is defined in <lib9p/srv.h> */ + +/* utilities for the above types **********************************************/ + +static inline enum srv_filetype srv_qid_filetype(struct lib9p_qid qid) { + if (qid.type & LIB9P_QT_AUTH) + return SRV_FILETYPE_AUTH; + if (qid.type & LIB9P_QT_DIR) + return SRV_FILETYPE_DIR; + return SRV_FILETYPE_FILE; +} + +static inline bool srv_check_perm(struct srv_req *ctx, struct lib9p_srv_stat *stat, uint8_t action) { + assert(ctx); + assert(stat); + assert(action); + + /* TODO actually check user and group instead of just assuming "other". */ + uint8_t mode = (uint8_t)(stat->mode & 07); + + return mode & action; +} + +[[maybe_unused]] +static struct lib9p_srv_userid *srv_userid_new(struct lib9p_s name +#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L + , lib9p_nuid_t num +#endif + ) { + struct lib9p_srv_userid *ret = malloc(sizeof(struct lib9p_srv_userid) + name.len); + if (!ret) + return NULL; +#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L + ret->num = num; +#endif + ret->name.len = name.len; + ret->name.utf8 = (void *)&ret[1]; + memcpy(ret->name.utf8, name.utf8, name.len); + ret->refcount = 1; + return ret; +} +#if !(CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L) +#define srv_userid_new(name, num) srv_userid_new(name) +#endif + +static struct lib9p_srv_userid *srv_userid_decref(struct lib9p_srv_userid *userid) { + assert(userid); + assert(userid->refcount); + userid->refcount--; + if (!userid->refcount) + free(userid); + return NULL; +} + +static struct lib9p_srv_userid *srv_userid_incref(struct lib9p_srv_userid *userid) { + assert(userid); + userid->refcount++; + return userid; +} + +/** + * Ensures that `file` is saved into the pathmap, and increments the + * gc_refcount by 1 (for presumptive insertion into the fidmap). + * parent_path's gc_refcount is also incremented as appropriate. + * + * Returns a pointer to the stored pathinfo. + */ +static inline struct srv_pathinfo *srv_path_save(struct srv_req *ctx, + lo_interface lib9p_srv_file file, + srv_path_t parent_path) { + assert(ctx); + assert(!LO_IS_NULL(file)); + + struct lib9p_qid qid = LO_CALL(file, qid); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, qid.path); + if (pathinfo) + assert(LO_EQ(pathinfo->file, file)); + else { + pathinfo = map_store(&ctx->parent_sess->paths, qid.path, + (struct srv_pathinfo){ + .file = file, + .type = srv_qid_filetype(qid), + .parent_dir = parent_path, + .gc_refcount = 0, + .io_refcount = 0, + }); + assert(pathinfo); + if (parent_path != qid.path) { + struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, parent_path); + assert(parent); + parent->gc_refcount++; + } + } + pathinfo->gc_refcount++; + return pathinfo; +} + +/** + * Decrement the path's gc_refcount, and trigger garbage collection as + * appropriate. + */ +static inline void srv_path_decref(struct srv_req *ctx, srv_path_t path) { + assert(ctx); + + for (;;) { + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, path); + assert(pathinfo); + pathinfo->gc_refcount--; + if (pathinfo->gc_refcount) + break; + srv_path_t parent_path = pathinfo->parent_dir; + LO_CALL(pathinfo->file, free); + map_del(&ctx->parent_sess->paths, path); + if (parent_path == path) + break; + path = parent_path; + } +} + +static inline error srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, struct srv_fidinfo *fidinfo, bool remove) { + assert(ctx); + assert(!ctx->user); + assert(fidinfo); + + error err = {}; + + if (fidinfo->flags & FIDFLAG_RCLOSE) + remove = true; + ctx->user = srv_userid_incref(fidinfo->user); + + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); + assert(pathinfo); + + if (remove) + err = LO_CALL(pathinfo->file, remove, ctx); + + if (fidinfo->flags & FIDFLAG_OPEN) { + switch (fidinfo->type) { + case SRV_FILETYPE_DIR: + LO_CALL(fidinfo->dir.io, iofree); + break; + case SRV_FILETYPE_FILE: + LO_CALL(fidinfo->file.io, iofree); + break; + case SRV_FILETYPE_AUTH: + assert_notreached("TODO: auth not yet implemented"); + break; + } + pathinfo->io_refcount--; + } + fidinfo->user = srv_userid_decref(fidinfo->user); + srv_path_decref(ctx, fidinfo->path); + map_del(&ctx->parent_sess->fids, fid); + + ctx->user = srv_userid_decref(ctx->user); + + return err; +} + +/** + * Store fid as pointing to pathinfo. Assumes that + * pathinfo->gc_refcount has already been incremented; does *not* + * decrement it on failure. + */ +static inline srv_fidinfop_or_error srv_fid_store(struct srv_req *ctx, lib9p_fid_t fid, struct srv_pathinfo *pathinfo, bool overwrite) { + assert(ctx); + assert(fid != LIB9P_FID_NOFID); + assert(pathinfo); + + struct lib9p_qid qid = LO_CALL(pathinfo->file, qid); + + struct srv_fidinfo *old_fidinfo = map_load(&ctx->parent_sess->fids, fid); + if (old_fidinfo) { + if (overwrite) { + /* This should only happen from Twalk; because + * directories cannot be RCLOSE and Twalk cannot walk on + * FIDs open for I/O, we can skip most of + * srv_fid_del(). */ + assert(old_fidinfo->type == SRV_FILETYPE_DIR); + assert(old_fidinfo->flags == 0); + + old_fidinfo->user = srv_userid_decref(old_fidinfo->user); + srv_path_decref(ctx, old_fidinfo->path); + map_del(&ctx->parent_sess->fids, fid); + } else { + return ERROR_NEW_ERR(srv_fidinfop, error_new(E_POSIX_EBADF, "FID already in use")); + } + } + struct srv_fidinfo *fidinfo = map_store(&ctx->parent_sess->fids, fid, (struct srv_fidinfo){ + .path = qid.path, + .type = srv_qid_filetype(qid), + .user = srv_userid_incref(ctx->user), + }); + assert(fidinfo); + return ERROR_NEW_VAL(srv_fidinfop, fidinfo); +} /* base utilities *************************************************************/ -#define nonrespond_errorf errorf +static void srv_msglog(struct srv_req *req, enum lib9p_msg_type typ, void *hostmsg) { + struct lib9p_srv *srv = req->parent_sess->parent_conn->parent_srv; + if (srv->msglog) { + srv->msglog(req, typ, hostmsg); + return; + } + log_infoln(typ % 2 ? "< " : "> ", (lib9p_msg, &req->basectx, typ, hostmsg)); +} + +#define srv_nonrespond_error log_errorln -static ssize_t write_Rmsg(struct _lib9p_srv_req *req, struct lib9p_Rmsg_send_buf *resp) { - ssize_t r; +static void srv_write_Rmsg(struct srv_req *req, struct lib9p_Rmsg_send_buf *resp) { + size_t_and_error r; cr_mutex_lock(&req->parent_sess->parent_conn->writelock); r = io_writev(req->parent_sess->parent_conn->fd, resp->iov, resp->iov_cnt); cr_mutex_unlock(&req->parent_sess->parent_conn->writelock); - return r; + if (!ERROR_IS_NULL(r.err)) + srv_nonrespond_error("write: (", r.size_t, ", ", (error, r.err), ")"); } -static void respond_error(struct _lib9p_srv_req *req) { -#if CONFIG_9P_ENABLE_9P2000_u - assert(req->ctx.basectx.err_num); -#endif - assert(req->ctx.basectx.err_msg[0]); +static void srv_respond_error(struct srv_req *req, error err) { + assert(!ERROR_IS_NULL(err)); - ssize_t r; struct lib9p_msg_Rerror host = { .tag = req->tag, - .ename = lib9p_strn(req->ctx.basectx.err_msg, - CONFIG_9P_MAX_ERR_SIZE), + .errstr = lib9p_str((char *)error_msg(err)), /* cast to discard `const` */ #if CONFIG_9P_ENABLE_9P2000_u - .errno = req->ctx.basectx.err_num, + .errnum = libmisc_to_linuxgeneric_errno(err.num), #endif }; - struct _srv_sess *sess = req->parent_sess; + struct srv_sess *sess = req->parent_sess; + + uint32_t overhead = lib9p_version_min_Rerror_size(sess->version); /* Truncate the error-string if necessary to avoid needing to - * return LINUX_ERANGE. */ - if (((uint32_t)host.ename.len) + sess->rerror_overhead > sess->max_msg_size) - host.ename.len = sess->max_msg_size - sess->rerror_overhead; + * return E_POSIX_ERANGE. */ + if (((uint32_t)host.errstr.len) + overhead > sess->max_msg_size) + host.errstr.len = sess->max_msg_size - overhead; struct lib9p_Rmsg_send_buf net; - lib9p_Rmsg_marshal(&req->ctx.basectx, + lib9p_Rmsg_marshal(&req->basectx, LIB9P_TYP_Rerror, &host, &net); - r = write_Rmsg(req, &net); - if (r < 0) - nonrespond_errorf("write: %s", net_strerror(-r)); + srv_msglog(req, LIB9P_TYP_Rerror, &host); + srv_write_Rmsg(req, &net); + error_cleanup(&err); } /* read coroutine *************************************************************/ -static bool read_exactly(lo_interface net_stream_conn fd, uint8_t *buf, size_t goal, size_t *done) { +/** Return whether to `break`. */ +static inline bool srv_read_exactly(lo_interface net_stream_conn fd, uint8_t *buf, size_t goal, size_t *done) { assert(buf); assert(goal); assert(done); while (*done < goal) { - ssize_t r = io_read(fd, &buf[*done], goal - *done); - if (r < 0) { - nonrespond_errorf("read: %s", net_strerror(-r)); - return true; - } else if (r == 0) { - if (*done != 0) - nonrespond_errorf("read: unexpected EOF"); + size_t_or_error r = io_read(fd, &buf[*done], goal - *done); + if (r.is_err) { + if (r.err.num == E_EOF) { + if (*done != 0) + srv_nonrespond_error("read: unexpected EOF"); + } else { + srv_nonrespond_error("read: ", (error, r.err)); + } + error_cleanup(&r.err); return true; } - *done += r; + *done += r.size_t; } return false; } -static void handle_message(struct _lib9p_srv_req *ctx); - -[[noreturn]] void lib9p_srv_read_cr(struct lib9p_srv *srv, lo_interface net_stream_listener listener) { +void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stream_listener listener) { assert(srv); assert(srv->rootdir); assert(!LO_IS_NULL(listener)); srv->readers++; - uint32_t initial_rerror_overhead = _lib9p_table_msg_min_size[LIB9P_VER_unknown]; - for (;;) { - struct _srv_conn conn = { - .parent_srv = srv, - .fd = LO_CALL(listener, accept), - .reader = cr_getcid(), - }; - if (LO_IS_NULL(conn.fd)) { - nonrespond_errorf("accept: error"); + net_stream_conn_or_error r = LO_CALL(listener, accept); + if (r.is_err) { + srv_nonrespond_error("accept: ", (error, r.err)); + error_cleanup(&r.err); srv->readers--; if (srv->readers == 0) while (srv->writers > 0) - _lib9p_srv_reqch_send_req(&srv->_reqch, NULL); - cr_exit(); + cr_rpc_send_req(&srv->_reqch, NULL); + return; } + lib9p_srv_read(srv, r.net_stream_conn); + } +} - struct _srv_sess sess = { - .parent_conn = &conn, - .version = LIB9P_VER_unknown, - .max_msg_size = CONFIG_9P_MAX_MSG_SIZE, - .rerror_overhead = initial_rerror_overhead, - .initialized = false, +void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) { + assert(srv); + assert(srv->rootdir); + assert(!LO_IS_NULL(_conn)); + + struct srv_conn conn = { + .parent_srv = srv, + .fd = _conn, + .reader = cr_getcid(), + }; + struct srv_sess sess = { + .parent_conn = &conn, + .version = LIB9P_VER_uninitialized, + .max_msg_size = CONFIG_9P_SRV_MAX_MSG_SIZE, + .initialized = false, + }; + for (;;) { + /* Read the message. */ + size_t done = 0; + uint8_t buf[7]; + if (srv_read_exactly(conn.fd, buf, 4, &done)) + break; + size_t goal = uint32le_decode(buf); + if (goal < 7) { + srv_nonrespond_error("T-message is impossibly small"); + break; + } + if (srv_read_exactly(conn.fd, buf, 7, &done)) + break; + struct srv_req req = { + .basectx = { + .version = sess.version, + .max_msg_size = sess.max_msg_size, + }, + + .parent_sess = &sess, + .tag = uint16le_decode(&buf[5]), + .net_bytes = buf, }; - for (;;) { - nextmsg: - /* Read the message. */ - size_t done = 0; - uint8_t buf[7]; - if (read_exactly(conn.fd, buf, 4, &done)) - goto close; - size_t goal = uint32le_decode(buf); - if (goal < 7) { - nonrespond_errorf("T-message is impossibly small"); - goto close; - } - if (read_exactly(conn.fd, buf, 7, &done)) - goto close; - struct _lib9p_srv_req req = { - .parent_sess = &sess, - .tag = uint16le_decode(&buf[5]), - .net_bytes = buf, - .ctx = { - .basectx = { - .version = sess.version, - .max_msg_size = sess.max_msg_size, - }, - }, - }; - if (goal > sess.max_msg_size) { - lib9p_errorf(&req.ctx.basectx, - LINUX_EMSGSIZE, "T-message larger than %s limit (%zu > %"PRIu32")", - sess.initialized ? "negotiated" : "server", - goal, - sess.max_msg_size); - respond_error(&req); - goto nextmsg; - } - req.net_bytes = malloc(goal); - assert(req.net_bytes); - memcpy(req.net_bytes, buf, done); - if (read_exactly(conn.fd, req.net_bytes, goal, &done)) { - free(req.net_bytes); - goto close; - } + if (goal > sess.max_msg_size) { + srv_respond_error(&req, error_new(E_POSIX_EMSGSIZE, + "T-message larger than ", sess.initialized ? "negotiated" : "server", " limit", + " (", goal, " > ", sess.max_msg_size, ")")); + continue; + } + req.net_bytes = malloc(goal); + assert(req.net_bytes); + memcpy(req.net_bytes, buf, done); + if (srv_read_exactly(conn.fd, req.net_bytes, goal, &done)) { + free(req.net_bytes); + break; + } - /* Handle the message... */ - if (req.net_bytes[4] == LIB9P_TYP_Tversion) - /* ...in this coroutine for Tversion, */ - handle_message(&req); - else - /* ...but usually in another coroutine. */ - _lib9p_srv_reqch_send_req(&srv->_reqch, &req); + /* Handle the message... */ + if (req.net_bytes[4] == LIB9P_TYP_Tversion) + /* ...in this coroutine for Tversion, */ + lib9p_srv_worker(&req); + else + /* ...but usually in another coroutine. */ + cr_rpc_send_req(&srv->_reqch, &req); + } + if (map_len(&sess.reqs) == 0) { + error err = io_close(conn.fd); + if (!ERROR_IS_NULL(err)) { + srv_nonrespond_error("conn close: ", (error, err)); + error_cleanup(&err); + } + } else { + error err = io_close_read(conn.fd); + if (!ERROR_IS_NULL(err)) { + srv_nonrespond_error("conn close: ", (error, err)); + error_cleanup(&err); + } + sess.closing = true; + cr_pause_and_yield(); + assert(map_len(&sess.reqs) == 0); + err = io_close_write(conn.fd); + if (!ERROR_IS_NULL(err)) { + srv_nonrespond_error("conn close: ", (error, err)); + error_cleanup(&err); } - close: - if (sess.reqs.len == 0) - io_close(conn.fd); - else { - io_close_read(conn.fd); - sess.closing = true; - cr_pause_and_yield(); - assert(sess.reqs.len == 0); - io_close_write(conn.fd); + } + + assert(map_len(&sess.reqs) == 0); + map_free(&sess.reqs); + + struct srv_req pseudoreq = { + .basectx = { + .version = sess.version, + .max_msg_size = sess.max_msg_size, + }, + .parent_sess = &sess, + }; + MAP_FOREACH(&sess.fids, fid, fidinfo) { + error err = srv_fid_del(&pseudoreq, fid, fidinfo, false); + if (!ERROR_IS_NULL(err)) { + srv_nonrespond_error("clunk: ", (error, err)); + error_cleanup(&err); } } + map_free(&sess.fids); + + assert(map_len(&sess.paths) == 0); + map_free(&sess.paths); } /* write coroutine ************************************************************/ -COROUTINE lib9p_srv_write_cr(void *_srv) { - struct _lib9p_srv_req req; +void lib9p_srv_worker_loop(struct lib9p_srv *srv) { + struct srv_req req; _lib9p_srv_reqch_req_t rpc_handle; - struct lib9p_srv *srv = _srv; assert(srv); assert(srv->rootdir); - cr_begin(); srv->writers++; for (;;) { /* Receive the request from the reader coroutine. ************/ - rpc_handle = _lib9p_srv_reqch_recv_req(&srv->_reqch); + rpc_handle = cr_rpc_recv_req(&srv->_reqch); if (!rpc_handle.req) { srv->writers--; - _lib9p_srv_reqch_send_resp(rpc_handle, 0); - cr_exit(); + cr_rpc_send_resp(rpc_handle, 0); + return; } /* Copy the request from the reader coroutine's * stack to our stack. */ req = *rpc_handle.req; /* Record that we have it. */ - reqmap_store(&req.parent_sess->reqs, req.tag, &req); + struct srv_req **reqpp = map_store(&req.parent_sess->reqs, req.tag, &req); + assert(reqpp && *reqpp == &req); /* Notify the reader coroutine that we're done with * its data. */ - _lib9p_srv_reqch_send_resp(rpc_handle, 0); + cr_rpc_send_resp(rpc_handle, 0); /* Process the request. **************************************/ - handle_message(&req); - - /* Release resources. ****************************************/ - while (_lib9p_srv_flushch_can_send(&req.ctx._flushch)) - _lib9p_srv_flushch_send(&req.ctx._flushch, false); - reqmap_del(&req.parent_sess->reqs, req.tag); - if (req.parent_sess->closing && !req.parent_sess->reqs.len) - cr_unpause(req.parent_sess->parent_conn->reader); + lib9p_srv_worker(&req); } - - cr_end(); } #define _HANDLER_PROTO(typ) \ - static void handle_T##typ(struct _lib9p_srv_req *, \ - struct lib9p_msg_T##typ *, \ - struct lib9p_msg_R##typ *) + static void handle_T##typ(struct srv_req *, \ + struct lib9p_msg_T##typ *) _HANDLER_PROTO(version); +#if _LIB9P_ENABLE_stat _HANDLER_PROTO(auth); _HANDLER_PROTO(attach); _HANDLER_PROTO(flush); @@ -366,193 +611,122 @@ _HANDLER_PROTO(clunk); _HANDLER_PROTO(remove); _HANDLER_PROTO(stat); _HANDLER_PROTO(wstat); +#endif +#if CONFIG_9P_ENABLE_9P2000_p9p +_HANDLER_PROTO(openfd); +#endif #if CONFIG_9P_ENABLE_9P2000_e _HANDLER_PROTO(session); _HANDLER_PROTO(sread); _HANDLER_PROTO(swrite); #endif -typedef void (*tmessage_handler)(struct _lib9p_srv_req *, void *, void *); - -static tmessage_handler tmessage_handlers[0x100] = { - [LIB9P_TYP_Tversion] = (tmessage_handler)handle_Tversion, - [LIB9P_TYP_Tauth] = (tmessage_handler)handle_Tauth, - [LIB9P_TYP_Tattach] = (tmessage_handler)handle_Tattach, - [LIB9P_TYP_Tflush] = (tmessage_handler)handle_Tflush, - [LIB9P_TYP_Twalk] = (tmessage_handler)handle_Twalk, - [LIB9P_TYP_Topen] = (tmessage_handler)handle_Topen, - [LIB9P_TYP_Tcreate] = (tmessage_handler)handle_Tcreate, - [LIB9P_TYP_Tread] = (tmessage_handler)handle_Tread, - [LIB9P_TYP_Twrite] = (tmessage_handler)handle_Twrite, - [LIB9P_TYP_Tclunk] = (tmessage_handler)handle_Tclunk, - [LIB9P_TYP_Tremove] = (tmessage_handler)handle_Tremove, - [LIB9P_TYP_Tstat] = (tmessage_handler)handle_Tstat, - [LIB9P_TYP_Twstat] = (tmessage_handler)handle_Twstat, -#if CONFIG_9P_ENABLE_9P2000_e - [LIB9P_TYP_Tsession] = (tmessage_handler)handle_Tsession, - [LIB9P_TYP_Tsread] = (tmessage_handler)handle_Tsread, - [LIB9P_TYP_Tswrite] = (tmessage_handler)handle_Tswrite, -#endif -}; - -static void handle_message(struct _lib9p_srv_req *ctx) { +void lib9p_srv_worker(struct srv_req *ctx) { uint8_t *host_req = NULL; - uint8_t host_resp[CONFIG_9P_MAX_HOSTMSG_SIZE]; - /* Unmarshal it. */ - ssize_t host_size = lib9p_Tmsg_validate(&ctx->ctx.basectx, ctx->net_bytes); - if (host_size < 0) - goto write; - host_req = malloc(host_size); + /* Unmarshal it. *****************************************************/ + size_t_or_error r = lib9p_Tmsg_validate(&ctx->basectx, ctx->net_bytes); + if (r.is_err) { + srv_respond_error(ctx, r.err); + goto release; + } + size_t host_size = r.size_t; + host_req = calloc(1, host_size); assert(host_req); enum lib9p_msg_type typ; - lib9p_Tmsg_unmarshal(&ctx->ctx.basectx, ctx->net_bytes, - &typ, host_req); - - /* Handle it. */ - tmessage_handlers[typ](ctx, (void *)host_req, (void *)host_resp); - - write: - if (lib9p_ctx_has_error(&ctx->ctx.basectx)) - respond_error(ctx); - else { - struct lib9p_Rmsg_send_buf net_resp; - if (lib9p_Rmsg_marshal(&ctx->ctx.basectx, - typ+1, host_resp, - &net_resp)) - goto write; - write_Rmsg(ctx, &net_resp); + lib9p_Tmsg_unmarshal(&ctx->basectx, ctx->net_bytes, + &typ, host_req); + srv_msglog(ctx, typ, host_req); + + /* Handle it. ********************************************************/ +#define CASE(typ) case LIB9P_TYP_##typ: handle_##typ(ctx, (void *)host_req); break + LM_PARTIAL_SWITCH (typ) { + CASE(Tversion); +#if _LIB9P_ENABLE_stat + CASE(Tauth); + CASE(Tattach); + CASE(Tflush); + CASE(Twalk); + CASE(Topen); + CASE(Tcreate); + CASE(Tread); + CASE(Twrite); + CASE(Tclunk); + CASE(Tremove); + CASE(Tstat); + CASE(Twstat); +#endif +#if CONFIG_9P_ENABLE_9P2000_p9p + CASE(Topenfd); +#endif +#if CONFIG_9P_ENABLE_9P2000_e + CASE(Tsession); + CASE(Tsread); + CASE(Tswrite); +#endif +#undef CASE + default: + assert_notreached("lib9p_Tmsg_validate() should have rejected unknown typ"); } + assert(ctx->responded); + + /* Release resources. ************************************************/ + release: + map_del(&ctx->parent_sess->reqs, ctx->tag); + size_t nwaiters; + while ((nwaiters = cr_chan_num_waiters(&ctx->flush_ch))) { + cr_chan_send(&ctx->flush_ch, (nwaiters == 1) + ? _LIB9P_SRV_FLUSH_RFLUSH + : _LIB9P_SRV_FLUSH_SILENT); + } + if (ctx->parent_sess->closing && !map_len(&ctx->parent_sess->reqs)) + cr_unpause(ctx->parent_sess->parent_conn->reader); if (host_req) free(host_req); free(ctx->net_bytes); } -#define util_handler_common(ctx, req, resp) do { \ - assert(ctx); \ - assert(req); \ - assert(resp); \ - resp->tag = req->tag; \ - } while (0) - -static inline bool srv_util_check_perm(struct _lib9p_srv_req *ctx, struct lib9p_stat *stat, uint8_t action) { - assert(ctx); - assert(stat); - assert(action); - - /* TODO actually check user and group instead of just assuming "other". */ - uint8_t mode = (uint8_t)(stat->file_mode & 07); - - return mode & action; -} - -/** - * Ensures that `file` is saved into the pathmap, and increments the - * gc_refcount by 1 (for presumptive insertion into the fidmap). - * parent_path's gc_refcount is also incremented as appropriate. - * - * Returns a pointer to the stored pathinfo. - */ -static inline struct srv_pathinfo *srv_util_pathsave(struct _lib9p_srv_req *ctx, - lo_interface lib9p_srv_file file, - srv_path_t parent_path) { - assert(ctx); - assert(!LO_IS_NULL(file)); - - struct lib9p_qid qid = LO_CALL(file, qid); - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, qid.path); - if (pathinfo) - assert(LO_EQ(pathinfo->file, file)); - else { - pathinfo = pathmap_store(&ctx->parent_sess->paths, qid.path, - (struct srv_pathinfo){ - .file = file, - .parent_dir = parent_path, - .gc_refcount = 0, - .io_refcount = 0, - }); - assert(pathinfo); - if (parent_path != qid.path) { - struct srv_pathinfo *parent = pathmap_load(&ctx->parent_sess->paths, parent_path); - assert(parent); - parent->gc_refcount++; - } - } - pathinfo->gc_refcount++; - return pathinfo; -} - -/** - * Decrement the path's gc_refcount, and trigger garbage collection as - * appropriate. - */ -static inline void srv_util_pathfree(struct _lib9p_srv_req *ctx, srv_path_t path) { - assert(ctx); - - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, path); - assert(pathinfo); - pathinfo->gc_refcount--; - if (pathinfo->gc_refcount == 0) { - if (pathinfo->parent_dir != path) - srv_util_pathfree(ctx, pathinfo->parent_dir); - LO_CALL(pathinfo->file, free); - pathmap_del(&ctx->parent_sess->paths, path); - } -} - -static inline bool srv_util_pathisdir(struct srv_pathinfo *pathinfo) { - assert(pathinfo); - return LO_CALL(pathinfo->file, qid).type & LIB9P_QT_DIR; -} - -/** - * Store fid as pointing to pathinfo. Assumes that - * pathinfo->gc_refcount has already been incremented; does *not* - * decrement it on failure. - */ -static inline struct _srv_fidinfo *srv_util_fidsave(struct _lib9p_srv_req *ctx, lib9p_fid_t fid, struct srv_pathinfo *pathinfo, bool overwrite) { - assert(ctx); - assert(fid != LIB9P_FID_NOFID); - assert(pathinfo); - - struct lib9p_qid qid = LO_CALL(pathinfo->file, qid); - - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, fid); - if (fidinfo) { - if (overwrite) { - struct srv_pathinfo *old_pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); - assert(old_pathinfo); - if (srv_util_pathisdir(old_pathinfo)) - LO_CALL(fidinfo->dir.io, iofree); - else - LO_CALL(fidinfo->file.io, iofree); - srv_util_pathfree(ctx, fidinfo->path); +static inline void _srv_respond(struct srv_req *ctx, enum lib9p_msg_type resp_typ, void *host_resp, error err) { + assert(!ctx->responded); + if (!ERROR_IS_NULL(err)) { + if (err.num == E_POSIX_ECANCELED && lib9p_srv_flush_requested(ctx)) { + error_cleanup(&err); } else { - lib9p_error(&ctx->ctx.basectx, - LINUX_EBADF, "FID already in use"); - return NULL; + error: + srv_respond_error(ctx, err); } } else { - fidinfo = fidmap_store(&ctx->parent_sess->fids, fid, (struct _srv_fidinfo){}); - if (!fidinfo) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EMFILE, "too many open files"); - return NULL; - } + assert(host_resp); + struct lib9p_Rmsg_send_buf net_resp; + err = lib9p_Rmsg_marshal(&ctx->basectx, + resp_typ, host_resp, + &net_resp); + if (!ERROR_IS_NULL(err)) + goto error; + srv_msglog(ctx, resp_typ, host_resp); + srv_write_Rmsg(ctx, &net_resp); } - *fidinfo = (struct _srv_fidinfo){ - .path = qid.path, - }; - return fidinfo; + ctx->responded = true; } +#define srv_respond(CTX, TYP, HOST_RESP, ERR) do { \ + struct lib9p_msg_R##TYP *_host_resp = HOST_RESP; \ + _srv_respond(CTX, LIB9P_TYP_R##TYP, _host_resp, ERR); \ +} while (0) +/* handle_T* ******************************************************************/ -static void handle_Tversion(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tversion *req, - struct lib9p_msg_Rversion *resp) { - util_handler_common(ctx, req, resp); +#define srv_handler_common(ctx, typ, req) \ + assert(ctx); \ + assert(req); \ + struct lib9p_msg_T##typ *_typecheck_req [[maybe_unused]] = req; \ + struct lib9p_msg_R##typ resp = { .tag = ctx->tag }; \ + error err = {} - enum lib9p_version version = LIB9P_VER_unknown; +static void handle_Tversion(struct srv_req *ctx, + struct lib9p_msg_Tversion *req) { + srv_handler_common(ctx, version, req); + + enum lib9p_version version = LIB9P_VER_uninitialized; if (req->version.len >= 6 && req->version.utf8[0] == '9' && @@ -562,7 +736,14 @@ static void handle_Tversion(struct _lib9p_srv_req *ctx, '0' <= req->version.utf8[4] && req->version.utf8[4] <= '9' && '0' <= req->version.utf8[5] && req->version.utf8[5] <= '9' && (req->version.len == 6 || req->version.utf8[6] == '.')) { +#if CONFIG_9P_ENABLE_9P2000 version = LIB9P_VER_9P2000; +#endif +#if CONFIG_9P_ENABLE_9P2000_p9p + struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv; + if (srv->type_assert_unix && !LO_IS_NULL(srv->type_assert_unix(ctx->parent_sess->parent_conn->fd))) + version = LIB9P_VER_9P2000_p9p; +#endif #if CONFIG_9P_ENABLE_9P2000_u if (lib9p_str_eq(lib9p_str_sliceleft(req->version, 6), lib9p_str(".u"))) version = LIB9P_VER_9P2000_u; @@ -573,340 +754,385 @@ static void handle_Tversion(struct _lib9p_srv_req *ctx, #endif } - uint32_t min_msg_size = _lib9p_table_msg_min_size[version]; + /* XXX: There are good arguments that min_msg_size should be + * something larger than max(rerror.min_size(), + * rread.min_size()+1). */ + uint32_t min_msg_size = _LIB9P_MAX(lib9p_version_min_Rerror_size(ctx->basectx.version), + lib9p_version_min_Rread_size(ctx->basectx.version)+1); if (req->max_msg_size < min_msg_size) { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EDOM, "requested max_msg_size is less than minimum for %s (%"PRIu32" < %"PRIu32")", - lib9p_version_str(version), req->max_msg_size, min_msg_size); - return; + err = error_new(E_POSIX_EDOM, "requested max_msg_size is less than minimum for ", lib9p_version_str(version), + " (", req->max_msg_size, " < ", min_msg_size, ")"); + goto tversion_return; } - resp->version = lib9p_str((char *)lib9p_version_str(version)); /* cast to discard "const" qualifier */ - resp->max_msg_size = (CONFIG_9P_MAX_MSG_SIZE < req->max_msg_size) - ? CONFIG_9P_MAX_MSG_SIZE + resp.version = lib9p_str((char *)lib9p_version_str(version)); /* cast to discard "const" qualifier */ +#if CONFIG_9P_ENABLE_9P2000_p9p + if (version == LIB9P_VER_9P2000_p9p) + resp.version = lib9p_str("9P2000"); +#endif + resp.max_msg_size = (CONFIG_9P_SRV_MAX_MSG_SIZE < req->max_msg_size) + ? CONFIG_9P_SRV_MAX_MSG_SIZE : req->max_msg_size; /* Close the old session. */ - if (ctx->parent_sess->reqs.len) { + if (map_len(&ctx->parent_sess->reqs)) { /* Flush all in-progress requests, and wait for them * to finish. */ - struct cr_select_arg *list = alloca(sizeof(struct cr_select_arg) * ctx->parent_sess->reqs.len); - while (ctx->parent_sess->reqs.len) { - uint16_t tag [[gnu::unused]]; - struct _lib9p_srv_req **reqpp; + struct cr_select_arg *args = stack_alloc(map_len(&ctx->parent_sess->reqs), struct cr_select_arg); + while (map_len(&ctx->parent_sess->reqs)) { size_t i = 0; - bool flushed; MAP_FOREACH(&ctx->parent_sess->reqs, tag, reqpp) { - list[i] = CR_SELECT_RECV(&((*reqpp)->ctx._flushch), &flushed); + enum _lib9p_srv_flush_result flushed; + args[i++] = CR_SELECT_RECV(&((*reqpp)->flush_ch), &flushed); } - cr_select_v(i, list); + assert(i == map_len(&ctx->parent_sess->reqs)); + cr_select_v(i, args); } } - if (ctx->parent_sess->fids.len) { - /* Close all FIDs. */ - uint32_t fid; - struct _srv_fidinfo *fidinfo [[gnu::unused]]; - MAP_FOREACH(&ctx->parent_sess->fids, fid, fidinfo) { - handle_Tclunk(ctx, - &(struct lib9p_msg_Tclunk){.fid = fid}, - &(struct lib9p_msg_Rclunk){}); + /* Close all FIDs. */ + MAP_FOREACH(&ctx->parent_sess->fids, fid, fidinfo) { + error fiderr = srv_fid_del(ctx, fid, fidinfo, false); + if (!ERROR_IS_NULL(fiderr)) { + srv_nonrespond_error("clunk: ", (error, fiderr)); + error_cleanup(&fiderr); } } /* Replace the old session with the new session. */ ctx->parent_sess->version = version; - ctx->parent_sess->max_msg_size = resp->max_msg_size; - ctx->parent_sess->rerror_overhead = min_msg_size; + ctx->parent_sess->max_msg_size = resp.max_msg_size; + + tversion_return: + srv_respond(ctx, version, &resp, err); } -static void handle_Tauth(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tauth *req, - struct lib9p_msg_Rauth *resp) { - util_handler_common(ctx, req, resp); +#if _LIB9P_ENABLE_stat +static void handle_Tauth(struct srv_req *ctx, + struct lib9p_msg_Tauth *req) { + srv_handler_common(ctx, auth, req); - ctx->ctx.uid = req->n_uid; - ctx->ctx.uname = req->uname; struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv; - if (!srv->auth) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EOPNOTSUPP, "authentication not required"); - return; + err = error_new(E_POSIX_EOPNOTSUPP, "authentication not required"); + goto tauth_return; } - srv->auth(&ctx->ctx, req->aname); - lib9p_error(&ctx->ctx.basectx, - LINUX_EOPNOTSUPP, "TODO: auth not implemented"); + ctx->user = srv_userid_new(req->uname, req->unum); + + err = srv->auth(ctx, req->aname); + if (!ERROR_IS_NULL(err)) + goto tauth_return; + + err = error_new(E_POSIX_EOPNOTSUPP, "TODO: auth not implemented"); + + tauth_return: + if (!ERROR_IS_NULL(err) && ctx->user) + ctx->user = srv_userid_decref(ctx->user); + srv_respond(ctx, auth, &resp, err); } -static void handle_Tattach(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tattach *req, - struct lib9p_msg_Rattach *resp) { - util_handler_common(ctx, req, resp); +static void handle_Tattach(struct srv_req *ctx, + struct lib9p_msg_Tattach *req) { + srv_handler_common(ctx, attach, req); - ctx->ctx.uid = req->n_uid; - ctx->ctx.uname = req->uname; - struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv; + if (req->fid == LIB9P_FID_NOFID) { + err = error_new(E_POSIX_EBADF, "cannot assign to NOFID"); + goto tattach_return; + } + struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv; if (srv->auth) { - /* - struct lib9p_srv_filehandle *fh = fidmap_get(req->afid); - if (!fh) - lib9p_error(&ctx->ctx.basectx, - LINUX_EACCES, "FID provided as auth-file is not a valid FID"); - else if (fh->type != FH_AUTH) - lib9p_error(&ctx->ctx.basectx, - LINUX_EACCES, "FID provided as auth-file is not an auth-file"); - else if (!lib9p_str_eq(fh->data.auth.uname, req->uname)) - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EACCES, "FID provided as auth-file is for user=\"%.*s\" and cannot be used for user=\"%.*s\"", - fh->data.auth.uname.len, fh->data.auth.uname.utf8, - req->uname.len, req->uname.utf8); - else if (!lib9p_str_eq(fh->data.auth.aname, req->aname)) - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EACCES, "FID provided as auth-file is for tree=\"%.*s\" and cannot be used for tree=\"%.*s\"", - fh->data.auth.aname.len, fh->data.auth.aname.utf8, - req->aname.len, req->aname.utf8); - else if (!fh->data.auth.authenticated) - lib9p_error(&ctx->ctx.basectx, - LINUX_EACCES, "FID provided as auth-file has not completed authentication"); - fh->refcount--; - if (lib9p_ctx_has_error(&ctx->ctx)) - return; - */ - lib9p_error(&ctx->ctx.basectx, - LINUX_EOPNOTSUPP, "TODO: auth not (yet?) implemented"); - return; + struct srv_fidinfo *afid = map_load(&ctx->parent_sess->fids, req->afid); + if (!afid) + err = error_new(E_POSIX_EACCES, "FID provided as auth-file is not a valid FID"); + else if (afid->type != SRV_FILETYPE_AUTH) + err = error_new(E_POSIX_EACCES, "FID provided as auth-file is not an auth-file"); + else if (!lib9p_str_eq(afid->user->name, req->uname)) + err = error_new(E_POSIX_EACCES, + "FID provided as auth-file is for user=", (qmem, afid->user->name.utf8, afid->user->name.len), + " and cannot be used for user=", (qmem, req->uname.utf8, req->uname.len)); +#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L + else if (afid->user->num != req->unum) + err = error_new(E_POSIX_EACCES, + "FID provided as auth-file is for user=", afid->user->num, + " and cannot be used for user=", req->unum); +#endif + else if (!lib9p_str_eq(afid->auth.aname, req->aname)) + err = error_new(E_POSIX_EACCES, + "FID provided as auth-file is for tree=", (qmem, afid->auth.aname.utf8, afid->auth.aname.len), + " and cannot be used for tree=", (qmem, req->aname.utf8, req->aname.len)); + else if (!afid->auth.completed) + err = error_new(E_POSIX_EACCES, "FID provided as auth-file has not completed authentication"); + if (!ERROR_IS_NULL(err)) + goto tattach_return; + ctx->user = srv_userid_incref(afid->user); } else { if (req->afid != LIB9P_FID_NOFID) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EACCES, "FID provided as auth-file, but no auth-file is required"); - return; + err = error_new(E_POSIX_EACCES, "FID provided as auth-file, but no auth-file is required"); + goto tattach_return; } - } - - if (req->fid == LIB9P_FID_NOFID) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EBADF, "cannot assign to NOFID"); - return; + ctx->user = srv_userid_new(req->uname, req->unum); } /* 1. File object */ - lo_interface lib9p_srv_file root_file = srv->rootdir(&ctx->ctx, req->aname); - assert(LO_IS_NULL(root_file) == lib9p_ctx_has_error(&ctx->ctx.basectx)); - if (lib9p_ctx_has_error(&ctx->ctx.basectx)) - return; + lib9p_srv_file_or_error root_file_r = srv->rootdir(ctx, req->aname); + if (root_file_r.is_err) { + err = root_file_r.err; + goto tattach_return; + } + lo_interface lib9p_srv_file root_file = root_file_r.lib9p_srv_file; struct lib9p_qid root_qid = LO_CALL(root_file, qid); - assert(root_qid.type & LIB9P_QT_DIR); + assert(srv_qid_filetype(root_qid) == SRV_FILETYPE_DIR); /* 2. pathinfo */ - struct srv_pathinfo *root_pathinfo = srv_util_pathsave(ctx, root_file, root_qid.path); + struct srv_pathinfo *root_pathinfo = srv_path_save(ctx, root_file, root_qid.path); /* 3. fidinfo */ - if (!srv_util_fidsave(ctx, req->fid, root_pathinfo, false)) { - srv_util_pathfree(ctx, root_qid.path); - return; + srv_fidinfop_or_error fidinfo = srv_fid_store(ctx, req->fid, root_pathinfo, false); + if (fidinfo.is_err) { + err = fidinfo.err; + srv_path_decref(ctx, root_qid.path); + goto tattach_return; } - resp->qid = root_qid; - return; + resp.qid = root_qid; + tattach_return: + if (ctx->user) + ctx->user = srv_userid_decref(ctx->user); + srv_respond(ctx, attach, &resp, err); } -static void handle_Tflush(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tflush *req, - struct lib9p_msg_Rflush *resp) { - util_handler_common(ctx, req, resp); - - struct _lib9p_srv_req **oldreqp = reqmap_load(&ctx->parent_sess->reqs, req->oldtag); - if (oldreqp) - _lib9p_srv_flushch_recv(&((*oldreqp)->ctx._flushch)); +static void handle_Tflush(struct srv_req *ctx, + struct lib9p_msg_Tflush *req) { + srv_handler_common(ctx, flush, req); + + struct srv_req **oldreqp = map_load(&ctx->parent_sess->reqs, req->oldtag); + if (oldreqp) { + struct srv_req *oldreq = *oldreqp; + enum _lib9p_srv_flush_result res = _LIB9P_SRV_FLUSH_RFLUSH; + switch (cr_select_l(CR_SELECT_RECV(&oldreq->flush_ch, &res), + CR_SELECT_SEND(&ctx->flush_ch, &res))) { + case 0: /* original request returned */ + req_debug("original request (tag=", req->oldtag, ") returned"); + if (res == _LIB9P_SRV_FLUSH_SILENT) { + ctx->responded = true; + return; + } + break; + case 1: /* flush itself got flushed */ + ctx->responded = true; + return; + } + } + srv_respond(ctx, flush, &resp, err); } -static void handle_Twalk(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Twalk *req, - struct lib9p_msg_Rwalk *resp) { - util_handler_common(ctx, req, resp); +static void handle_Twalk(struct srv_req *ctx, + struct lib9p_msg_Twalk *req) { + srv_handler_common(ctx, walk, req); if (req->newfid == LIB9P_FID_NOFID) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EBADF, "cannot assign to NOFID"); - return; + err = error_new(E_POSIX_EBADF, "cannot assign to NOFID"); + goto twalk_return; } - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EBADF, "bad file number %"PRIu32, req->fid); - return; + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); + goto twalk_return; } + if (fidinfo->flags & FIDFLAG_OPEN) { + err = error_new(E_POSIX_EALREADY, "cannot walk on FID open for I/O"); + goto twalk_return; + } + ctx->user = srv_userid_incref(fidinfo->user); - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); pathinfo->gc_refcount++; - resp->wqid = (struct lib9p_qid *)(&resp[1]); - for (resp->nwqid = 0; resp->nwqid < req->nwname; resp->nwqid++) { + struct lib9p_qid _resp_qid[16]; + resp.wqid = _resp_qid; + for (resp.nwqid = 0; resp.nwqid < req->nwname; resp.nwqid++) { + if (pathinfo->type != SRV_FILETYPE_DIR) { + err = error_new(E_POSIX_ENOTDIR, "not a directory"); + break; + } + struct srv_pathinfo *new_pathinfo; - if (lib9p_str_eq(req->wname[resp->nwqid], lib9p_str(".."))) { - new_pathinfo = pathmap_load(&ctx->parent_sess->paths, pathinfo->parent_dir); + if (lib9p_str_eq(req->wname[resp.nwqid], lib9p_str(".."))) { + new_pathinfo = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(new_pathinfo); new_pathinfo->gc_refcount++; } else { - if (!srv_util_pathisdir(pathinfo)) { - lib9p_error(&ctx->ctx.basectx, - LINUX_ENOTDIR, "not a directory"); + lib9p_srv_file_or_error member_file = LO_CALL(pathinfo->file, dwalk, ctx, req->wname[resp.nwqid]); + if (member_file.is_err) { + err = member_file.err; break; } - - lo_interface lib9p_srv_file member_file = LO_CALL(pathinfo->file, dwalk, &ctx->ctx, req->wname[resp->nwqid]); - assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(&ctx->ctx.basectx)); - if (lib9p_ctx_has_error(&ctx->ctx.basectx)) - break; - new_pathinfo = srv_util_pathsave(ctx, member_file, LO_CALL(pathinfo->file, qid).path); + new_pathinfo = srv_path_save(ctx, member_file.lib9p_srv_file, LO_CALL(pathinfo->file, qid).path); + assert(new_pathinfo); } - if (srv_util_pathisdir(new_pathinfo)) { - struct lib9p_stat stat = LO_CALL(new_pathinfo->file, stat, &ctx->ctx); - if (lib9p_ctx_has_error(&ctx->ctx.basectx)) + if (new_pathinfo->type == SRV_FILETYPE_DIR) { + lib9p_srv_stat_or_error stat = LO_CALL(new_pathinfo->file, stat, ctx); + if (stat.is_err) { + err = stat.err; break; - lib9p_stat_assert(stat); - if (!srv_util_check_perm(ctx, &stat, 0b001)) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EACCES, "you do not have execute permission on that directory"); - srv_util_pathfree(ctx, LO_CALL(new_pathinfo->file, qid).path); + } + lib9p_srv_stat_assert(stat.lib9p_srv_stat); + if (!srv_check_perm(ctx, &stat.lib9p_srv_stat, 0b001)) { + err = error_new(E_POSIX_EACCES, "you do not have execute permission on that directory"); + srv_path_decref(ctx, LO_CALL(new_pathinfo->file, qid).path); break; } } - resp->wqid[resp->nwqid] = LO_CALL(new_pathinfo->file, qid); + resp.wqid[resp.nwqid] = LO_CALL(new_pathinfo->file, qid); - srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path); + srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); pathinfo = new_pathinfo; } - if (resp->nwqid == req->nwname) { - if (req->newfid == req->fid) { - if (srv_util_pathisdir(pathinfo)) - LO_CALL(fidinfo->dir.io, iofree); - else - LO_CALL(fidinfo->file.io, iofree); - fidinfo->flags = 0; + if (resp.nwqid == req->nwname) { + srv_fidinfop_or_error fidinfo = srv_fid_store(ctx, req->newfid, pathinfo, req->newfid == req->fid); + if (fidinfo.is_err) { + err = fidinfo.err; + srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); } - if (!srv_util_fidsave(ctx, req->newfid, pathinfo, req->newfid == req->fid)) - srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path); } else { - assert(lib9p_ctx_has_error(&ctx->ctx.basectx)); - srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path); - if (resp->nwqid > 0) - lib9p_ctx_clear_error(&ctx->ctx.basectx); + assert(!ERROR_IS_NULL(err)); + srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); + if (resp.nwqid > 0) + error_cleanup(&err); } + twalk_return: + if (ctx->user) + ctx->user = srv_userid_decref(ctx->user); + srv_respond(ctx, walk, &resp, err); } -static void handle_Topen(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Topen *req, - struct lib9p_msg_Ropen *resp) { - util_handler_common(ctx, req, resp); +static void handle_Topen(struct srv_req *ctx, + struct lib9p_msg_Topen *req) { + srv_handler_common(ctx, open, req); /* Check that the FID is valid for this. */ - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EBADF, "bad file number %"PRIu32, req->fid); - return; + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); + goto topen_return; } if (fidinfo->flags & FIDFLAG_OPEN) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EALREADY, "FID is already open"); - return; + err = error_new(E_POSIX_EALREADY, "FID is already open"); + goto topen_return; } - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); - assert(pathinfo); - if (srv_util_pathisdir(pathinfo)) { - if ( ((req->mode & LIB9P_O_MODE_MASK) != LIB9P_O_READ) || + if (fidinfo->type == SRV_FILETYPE_DIR) { + if ( ((req->mode & LIB9P_O_MODE_MASK) != LIB9P_O_MODE_READ) || (req->mode & LIB9P_O_TRUNC) || (req->mode & LIB9P_O_RCLOSE) ) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EISDIR, "directories cannot be written, executed, truncated, or removed-on-close"); - return; + err = error_new(E_POSIX_EISDIR, "directories cannot be written, executed, truncated, or removed-on-close"); + goto topen_return; } } + ctx->user = srv_userid_incref(fidinfo->user); /* Variables. */ - lib9p_o_t reqmode = req->mode; - uint8_t fidflags = fidinfo->flags; + lib9p_o_t reqmode = req->mode; + uint8_t fidflags = fidinfo->flags; + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); + assert(pathinfo); /* Check permissions. */ if (reqmode & LIB9P_O_RCLOSE) { - struct srv_pathinfo *parent = pathmap_load(&ctx->parent_sess->paths, pathinfo->parent_dir); + struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(parent); - struct lib9p_stat parent_stat = LO_CALL(parent->file, stat, &ctx->ctx); - if (lib9p_ctx_has_error(&ctx->ctx.basectx)) - return; - lib9p_stat_assert(parent_stat); - if (!srv_util_check_perm(ctx, &parent_stat, 0b010)) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EACCES, "permission denied to remove-on-close"); - return; + lib9p_srv_stat_or_error parent_stat = LO_CALL(parent->file, stat, ctx); + if (parent_stat.is_err) { + err = parent_stat.err; + goto topen_return; + } + lib9p_srv_stat_assert(parent_stat.lib9p_srv_stat); + if (!srv_check_perm(ctx, &parent_stat.lib9p_srv_stat, 0b010)) { + err = error_new(E_POSIX_EACCES, "permission denied to remove-on-close"); + goto topen_return; } fidflags |= FIDFLAG_RCLOSE; } - struct lib9p_stat stat = LO_CALL(pathinfo->file, stat, &ctx->ctx); - if (lib9p_ctx_has_error(&ctx->ctx.basectx)) - return; - lib9p_stat_assert(stat); - if ((stat.file_mode & LIB9P_DM_EXCL) && pathinfo->io_refcount) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EEXIST, "exclusive file is already opened"); - return; + lib9p_srv_stat_or_error stat = LO_CALL(pathinfo->file, stat, ctx); + if (stat.is_err) { + err = stat.err; + goto topen_return; + } + lib9p_srv_stat_assert(stat.lib9p_srv_stat); + if ((stat.lib9p_srv_stat.mode & LIB9P_DM_EXCL) && pathinfo->io_refcount) { + err = error_new(E_POSIX_EEXIST, "exclusive file is already opened"); + goto topen_return; } - if (stat.file_mode & LIB9P_DM_APPEND) + if (stat.lib9p_srv_stat.mode & LIB9P_DM_APPEND) { + fidflags |= FIDFLAG_APPEND; reqmode = reqmode & ~LIB9P_O_TRUNC; + } uint8_t perm_bits = 0; bool rd = false, wr = false; switch (reqmode & LIB9P_O_MODE_MASK) { - case LIB9P_O_READ: + case LIB9P_O_MODE_READ: perm_bits = 0b100; rd = true; break; - case LIB9P_O_WRITE: + case LIB9P_O_MODE_WRITE: perm_bits = 0b010; wr = true; break; - case LIB9P_O_RDWR: + case LIB9P_O_MODE_RDWR: perm_bits = 0b110; rd = wr = true; break; - case LIB9P_O_EXEC: + case LIB9P_O_MODE_EXEC: perm_bits = 0b001; rd = true; break; } - if (!srv_util_check_perm(ctx, &stat, perm_bits)) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EACCES, "permission denied"); + if (!srv_check_perm(ctx, &stat.lib9p_srv_stat, perm_bits)) { + err = error_new(E_POSIX_EACCES, "permission denied"); + goto topen_return; } /* Actually make the call. */ uint32_t iounit; struct lib9p_qid qid; - if (srv_util_pathisdir(pathinfo)) { - fidinfo->dir.io = LO_CALL(pathinfo->file, dopen, &ctx->ctx); - assert(LO_IS_NULL(fidinfo->dir.io) == lib9p_ctx_has_error(&ctx->ctx.basectx)); - if (lib9p_ctx_has_error(&ctx->ctx.basectx)) - return; + switch (pathinfo->type) { + case SRV_FILETYPE_DIR: + lib9p_srv_dio_or_error dio_r = + LO_CALL(pathinfo->file, dopen, ctx); + if (dio_r.is_err) { + err = dio_r.err; + goto topen_return; + } + fidinfo->dir.io = dio_r.lib9p_srv_dio; fidinfo->dir.idx = 0; fidinfo->dir.off = 0; qid = LO_CALL(fidinfo->dir.io, qid); iounit = 0; - } else { - fidinfo->file.io = LO_CALL(pathinfo->file, fopen, &ctx->ctx, - rd, wr, - reqmode & LIB9P_O_TRUNC); - assert(LO_IS_NULL(fidinfo->file.io) == lib9p_ctx_has_error(&ctx->ctx.basectx)); - if (lib9p_ctx_has_error(&ctx->ctx.basectx)) - return; + break; + case SRV_FILETYPE_FILE: + lib9p_srv_fio_or_error fio_r = + LO_CALL(pathinfo->file, fopen, ctx, + rd, wr, + reqmode & LIB9P_O_TRUNC); + if (fio_r.is_err) { + err = fio_r.err; + goto topen_return; + } + fidinfo->file.io = fio_r.lib9p_srv_fio; qid = LO_CALL(fidinfo->file.io, qid); iounit = LO_CALL(fidinfo->file.io, iounit); + break; + case SRV_FILETYPE_AUTH: + assert_notreached("TODO: auth not yet implemented"); + break; + default: + assert_notreached("invalid srv_filetype"); + break; } /* Success. */ @@ -916,218 +1142,348 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, fidflags |= FIDFLAG_OPEN_W; pathinfo->io_refcount++; fidinfo->flags = fidflags; - resp->qid = qid; - resp->iounit = iounit; + resp.qid = qid; + resp.iounit = iounit; + topen_return: + if (ctx->user) + ctx->user = srv_userid_decref(ctx->user); + srv_respond(ctx, open, &resp, err); } -static void handle_Tcreate(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tcreate *req, - struct lib9p_msg_Rcreate *resp) { - util_handler_common(ctx, req, resp); +static void handle_Tcreate(struct srv_req *ctx, + struct lib9p_msg_Tcreate *req) { + srv_handler_common(ctx, create, req); - lib9p_error(&ctx->ctx.basectx, - LINUX_EOPNOTSUPP, "create not (yet?) implemented"); + err = error_new(E_POSIX_EOPNOTSUPP, "create not (yet?) implemented"); + + srv_respond(ctx, create, &resp, err); +} + +static inline struct lib9p_stat srv_stat_to_net_stat(struct lib9p_srv_stat in) { + return (struct lib9p_stat){ + .qid = in.qid, + .mode = in.mode, + .atime = in.atime_sec, + .mtime = in.mtime_sec, + .length = in.size, + .name = in.name, + .owner_uname = in.owner_uid.name, + .owner_gname = in.owner_gid.name, + .last_modifier_uname = in.last_modifier_uid.name, +#if CONFIG_9P_ENABLE_9P2000_u + .owner_unum = in.owner_uid.num, + .owner_gnum = in.owner_gid.num, + .last_modifier_unum = in.last_modifier_uid.num, + .extension = in.extension, +#endif + }; } -static void handle_Tread(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tread *req, - struct lib9p_msg_Rread *resp) { - util_handler_common(ctx, req, resp); +static void handle_Tread(struct srv_req *ctx, + struct lib9p_msg_Tread *req) { + srv_handler_common(ctx, read, req); + char *heap = NULL; + + /* TODO: serialize simultaneous reads to the same FID */ + + if (req->count > ctx->basectx.max_msg_size - lib9p_version_min_Rread_size(ctx->basectx.version)) + req->count = ctx->basectx.max_msg_size - lib9p_version_min_Rread_size(ctx->basectx.version); /* Check that the FID is valid for this. */ - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EBADF, "bad file number %"PRIu32, req->fid); - return; + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); + goto tread_return; } if (!(fidinfo->flags & FIDFLAG_OPEN_R)) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EINVAL, "FID not open for reading"); - return; + err = error_new(E_POSIX_EINVAL, "FID not open for reading"); + goto tread_return; } - /* Variables. */ - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); - assert(pathinfo); - /* Do it. */ - if (srv_util_pathisdir(pathinfo)) { - /* Translate byte-offset to object-index. */ - size_t idx; - if (req->offset == 0) - idx = 0; - else if (req->offset == fidinfo->dir.off) - idx = fidinfo->dir.idx; - else { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EINVAL, "invalid offset (must be 0 or %"PRIu64"): %"PRIu64, - fidinfo->dir.off, req->offset); - return; + ctx->user = srv_userid_incref(fidinfo->user); + switch (fidinfo->type) { + case SRV_FILETYPE_DIR: +#if _LIB9P_ENABLE_stat + /* Seek. */ + if (req->offset == 0) { + fidinfo->dir.idx = 0; + fidinfo->dir.off = 0; + fidinfo->dir.buffered_dirent = (struct lib9p_srv_dirent){}; + } else if (req->offset != fidinfo->dir.off) { + err = error_new(E_POSIX_EINVAL, "invalid offset (must be 0 or ", fidinfo->dir.off, "): ", req->offset); + goto tread_return; } - /* Do it. */ - resp->data = (char *)(&resp[1]); - size_t num = LO_CALL(fidinfo->dir.io, dread, &ctx->ctx, (uint8_t *)resp->data, req->count, idx); - /* Translate object-count back to byte-count. */ - uint32_t len = 0; - for (size_t i = 0; i < num; i++) { - uint32_t i_len; - lib9p_stat_validate(&ctx->ctx.basectx, req->count, &((uint8_t *)resp->data)[len], &i_len, NULL); - len += i_len; + /* Read. */ + resp.data = heap = malloc(req->count); + resp.count = 0; + struct srv_pathinfo *dir_pathinfo = NULL; + for (;;) { + lo_interface lib9p_srv_file member_file = {}; + struct lib9p_srv_dirent member_dirent; + if (fidinfo->dir.buffered_dirent.name.len) { + member_dirent = fidinfo->dir.buffered_dirent; + } else { + lib9p_srv_dirent_or_error member_dirent_r; + member_dirent_r = LO_CALL(fidinfo->dir.io, dread, ctx, fidinfo->dir.idx); + if (member_dirent_r.is_err) { + if (!resp.count) { + err = member_dirent_r.err; + goto tread_return; + } + error_cleanup(&member_dirent_r.err); + break; + } + member_dirent = member_dirent_r.lib9p_srv_dirent; + } + if (!member_dirent.name.len) + break; + struct lib9p_srv_stat member_stat; + struct srv_pathinfo *member_pathinfo = map_load(&ctx->parent_sess->paths, member_dirent.qid.path); + if (member_pathinfo) { + lib9p_srv_stat_or_error r = LO_CALL(member_pathinfo->file, stat, ctx); + if (r.is_err) { + err = r.err; + goto member_err; + } + member_stat = r.lib9p_srv_stat; + } else { + if (!dir_pathinfo) + dir_pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); + assert(dir_pathinfo); + lib9p_srv_file_or_error file_r = LO_CALL(dir_pathinfo->file, dwalk, ctx, member_dirent.name); + if (file_r.is_err) { + err = file_r.err; + goto member_err; + } + member_file = file_r.lib9p_srv_file; + lib9p_srv_stat_or_error stat_r = LO_CALL(member_file, stat, ctx); + if (stat_r.is_err) { + err = stat_r.err; + goto member_err; + } + member_stat = stat_r.lib9p_srv_stat; + } + if (false) { + member_err: + if (!LO_IS_NULL(member_file)) + LO_CALL(member_file, free); + if (!resp.count) + goto tread_return; + error_cleanup(&err); + break; + } + lib9p_srv_stat_assert(member_stat); + struct lib9p_stat member_netstat = srv_stat_to_net_stat(member_stat); + uint32_t nbytes = lib9p_stat_marshal(&ctx->basectx, req->count-resp.count, &member_netstat, + (uint8_t *)&resp.data[resp.count]); + if (!LO_IS_NULL(member_file)) + LO_CALL(member_file, free); + if (!nbytes) { + if (!resp.count) { + err = error_new(E_POSIX_ERANGE, "stat object does not fit into negotiated max message size"); + goto tread_return; + } + fidinfo->dir.buffered_dirent = member_dirent; + break; + } + resp.count += nbytes; + fidinfo->dir.idx++; + fidinfo->dir.off += nbytes; + fidinfo->dir.buffered_dirent = (struct lib9p_srv_dirent){}; } - resp->count = len; - /* Remember. */ - fidinfo->dir.idx = idx+num; - fidinfo->dir.off = req->offset + len; - } else { - struct iovec iov; - LO_CALL(fidinfo->file.io, pread, &ctx->ctx, req->count, req->offset, &iov); - if (!lib9p_ctx_has_error(&ctx->ctx.basectx)) { - resp->count = iov.iov_len; - resp->data = iov.iov_base; - if (resp->count > req->count) - resp->count = req->count; +#else + assert_notreached("Tread for directory on protocol version without that"); +#endif + break; + case SRV_FILETYPE_FILE: + iovec_or_error iov = LO_CALL(fidinfo->file.io, pread, ctx, req->count, req->offset); + if (iov.is_err) { + err = iov.err; + } else { + resp.count = 0; + assert(resp.iovcnt >= 0); + if (resp.iovcnt) { + assert(resp.iov); + for (int i = 0; i < resp.iovcnt; i++) { + assert(resp.iov[i].iov_len == 0 || resp.iov[i].iov_base); + bool overflowed = __builtin_add_overflow(resp.count, resp.iov[i].iov_len, &resp.count); + assert(!overflowed); + } + } + assert(resp.count <= req->count); } + break; + case SRV_FILETYPE_AUTH: + assert_notreached("TODO: auth not yet implemented"); + break; } + tread_return: + if (ctx->user) + ctx->user = srv_userid_decref(ctx->user); + srv_respond(ctx, read, &resp, err); + if (heap) + free(heap); } -static void handle_Twrite(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Twrite *req, - struct lib9p_msg_Rwrite *resp) { - util_handler_common(ctx, req, resp); +static void handle_Twrite(struct srv_req *ctx, + struct lib9p_msg_Twrite *req) { + srv_handler_common(ctx, write, req); + + /* TODO: serialize simultaneous writes to the same FID */ /* Check that the FID is valid for this. */ - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EBADF, "bad file number %"PRIu32, req->fid); - return; + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); + goto twrite_return; } if (!(fidinfo->flags & FIDFLAG_OPEN_W)) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EINVAL, "FID not open for writing"); - return; + err = error_new(E_POSIX_EINVAL, "FID not open for writing"); + goto twrite_return; } - - /* Variables. */ - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); - assert(pathinfo); + if (fidinfo->flags & FIDFLAG_APPEND) + req->offset = 0; /* Do it. */ - resp->count = LO_CALL(fidinfo->file.io, pwrite, &ctx->ctx, req->data, req->count, req->offset); + ctx->user = srv_userid_incref(fidinfo->user); + uint32_t_or_error count = LO_CALL(fidinfo->file.io, pwrite, ctx, req->data, req->count, req->offset); + if (count.is_err) + err = count.err; + else + resp.count = count.uint32_t; + twrite_return: + if (ctx->user) + ctx->user = srv_userid_decref(ctx->user); + srv_respond(ctx, write, &resp, err); } -static void clunkremove(struct _lib9p_srv_req *ctx, lib9p_fid_t fid, bool remove) { - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, fid); +static void handle_Tclunk(struct srv_req *ctx, + struct lib9p_msg_Tclunk *req) { + srv_handler_common(ctx, clunk, req); + + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EBADF, "bad file number %"PRIu32, fid); - return; + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); + goto tclunk_return; } - if (fidinfo->flags & FIDFLAG_RCLOSE) - remove = true; - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); - assert(pathinfo); - if (remove) { - if (pathinfo->parent_dir == fidinfo->path) { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EBUSY, "cannot remove root"); - goto clunk; - } - struct srv_pathinfo *parent = pathmap_load(&ctx->parent_sess->paths, pathinfo->parent_dir); - assert(parent); - struct lib9p_stat parent_stat = LO_CALL(parent->file, stat, &ctx->ctx); - if (!srv_util_check_perm(ctx, &parent_stat, 0b010)) { - lib9p_error(&ctx->ctx.basectx, - LINUX_EACCES, "you do not have write permission on the parent directory"); - goto clunk; - } - LO_CALL(pathinfo->file, remove, &ctx->ctx); - } + srv_fid_del(ctx, req->fid, fidinfo, false); - clunk: - if (fidinfo->flags & FIDFLAG_OPEN) { - if (srv_util_pathisdir(pathinfo)) - LO_CALL(fidinfo->dir.io, iofree); - else - LO_CALL(fidinfo->file.io, iofree); - pathinfo->io_refcount--; - } - srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path); - fidmap_del(&ctx->parent_sess->fids, fid); + tclunk_return: + srv_respond(ctx, clunk, &resp, err); } -static void handle_Tclunk(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tclunk *req, - struct lib9p_msg_Rclunk *resp) { - util_handler_common(ctx, req, resp); - - clunkremove(ctx, req->fid, false); -} +static void handle_Tremove(struct srv_req *ctx, + struct lib9p_msg_Tremove *req) { + srv_handler_common(ctx, remove, req); + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); + if (!fidinfo) { + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); + goto tremove_return; + } -static void handle_Tremove(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tremove *req, - struct lib9p_msg_Rremove *resp) { - util_handler_common(ctx, req, resp); + bool remove = true; + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); + assert(pathinfo); + if (pathinfo->parent_dir == fidinfo->path) { + err = error_new(E_POSIX_EBUSY, "cannot remove root"); + remove = false; + goto tremove_main; + } + struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir); + assert(parent); + lib9p_srv_stat_or_error r = LO_CALL(parent->file, stat, ctx); + if (r.is_err) { + err = r.err; + goto tremove_main; + } + struct lib9p_srv_stat parent_stat = r.lib9p_srv_stat; + if (!srv_check_perm(ctx, &parent_stat, 0b010)) { + err = error_new(E_POSIX_EACCES, "you do not have write permission on the parent directory"); + remove = false; + goto tremove_main; + } - clunkremove(ctx, req->fid, true); + tremove_main: + srv_fid_del(ctx, req->fid, fidinfo, remove); + tremove_return: + srv_respond(ctx, remove, &resp, err); } -static void handle_Tstat(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tstat *req, - struct lib9p_msg_Rstat *resp) { - util_handler_common(ctx, req, resp); +static void handle_Tstat(struct srv_req *ctx, + struct lib9p_msg_Tstat *req) { + srv_handler_common(ctx, stat, req); - struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_errorf(&ctx->ctx.basectx, - LINUX_EBADF, "bad file number %"PRIu32, req->fid); - return; + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); + goto tstat_return; } - struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); + struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); - resp->stat = LO_CALL(pathinfo->file, stat, &ctx->ctx); - if (!lib9p_ctx_has_error(&ctx->ctx.basectx)) - lib9p_stat_assert(resp->stat); + ctx->user = srv_userid_incref(fidinfo->user); + lib9p_srv_stat_or_error r = LO_CALL(pathinfo->file, stat, ctx); + if (r.is_err) { + err = r.err; + goto tstat_return; + } + lib9p_srv_stat_assert(r.lib9p_srv_stat); + resp.stat = srv_stat_to_net_stat(r.lib9p_srv_stat); + tstat_return: + if (ctx->user) + ctx->user = srv_userid_decref(ctx->user); + srv_respond(ctx, stat, &resp, err); } -static void handle_Twstat(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Twstat *req, - struct lib9p_msg_Rwstat *resp) { - util_handler_common(ctx, req, resp); +static void handle_Twstat(struct srv_req *ctx, + struct lib9p_msg_Twstat *req) { + srv_handler_common(ctx, wstat, req); + + err = error_new(E_POSIX_EOPNOTSUPP, "wstat not (yet?) implemented"); - lib9p_error(&ctx->ctx.basectx, - LINUX_EOPNOTSUPP, "wstat not (yet?) implemented"); + srv_respond(ctx, wstat, &resp, err); } +#endif + +#if CONFIG_9P_ENABLE_9P2000_p9p +static void handle_Topenfd(struct srv_req *ctx, + struct lib9p_msg_Topenfd *req) { + srv_handler_common(ctx, openfd, req); + + err = error_new(E_POSIX_EOPNOTSUPP, "openfd not (yet?) implemented"); + + srv_respond(ctx, openfd, &resp, err); +} +#endif #if CONFIG_9P_ENABLE_9P2000_e -static void handle_Tsession(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tsession *req, - struct lib9p_msg_Rsession *resp) { - util_handler_common(ctx, req, resp); +static void handle_Tsession(struct srv_req *ctx, + struct lib9p_msg_Tsession *req) { + srv_handler_common(ctx, session, req); + + err = error_new(E_POSIX_EOPNOTSUPP, "session not (yet?) implemented"); - lib9p_error(&ctx->ctx.basectx, - LINUX_EOPNOTSUPP, "session not (yet?) implemented"); + srv_respond(ctx, session, &resp, err); } -static void handle_Tsread(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tsread *req, - struct lib9p_msg_Rsread *resp) { - util_handler_common(ctx, req, resp); +static void handle_Tsread(struct srv_req *ctx, + struct lib9p_msg_Tsread *req) { + srv_handler_common(ctx, sread, req); - lib9p_error(&ctx->ctx.basectx, - LINUX_EOPNOTSUPP, "sread not (yet?) implemented"); + err = error_new(E_POSIX_EOPNOTSUPP, "sread not (yet?) implemented"); + + srv_respond(ctx, sread, &resp, err); } -static void handle_Tswrite(struct _lib9p_srv_req *ctx, - struct lib9p_msg_Tswrite *req, - struct lib9p_msg_Rswrite *resp) { - util_handler_common(ctx, req, resp); +static void handle_Tswrite(struct srv_req *ctx, + struct lib9p_msg_Tswrite *req) { + srv_handler_common(ctx, swrite, req); + + err = error_new(E_POSIX_EOPNOTSUPP, "swrite not (yet?) implemented"); - lib9p_error(&ctx->ctx.basectx, - LINUX_EOPNOTSUPP, "swrite not (yet?) implemented"); + srv_respond(ctx, swrite, &resp, err); } #endif diff --git a/lib9p/srv_errno.h b/lib9p/srv_errno.h new file mode 100644 index 0000000..1384f97 --- /dev/null +++ b/lib9p/srv_errno.h @@ -0,0 +1,14 @@ +/* lib9p/srv_errno.h - TODO + * + * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_SRV_ERRNO_H_ +#define _LIB9P_SRV_ERRNO_H_ + +#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L +lib9p_errno_t libmisc_to_linuxgeneric_errno(_errnum); +#endif + +#endif /* _LIB9P_SRV_ERRNO_H_ */ diff --git a/lib9p/srv_generated.c b/lib9p/srv_generated.c new file mode 100644 index 0000000..26989c5 --- /dev/null +++ b/lib9p/srv_generated.c @@ -0,0 +1,91 @@ +/* lib9p/srv_generated.c - Generated by lib9p/srv_generated.c.gen. DO NOT EDIT! */ + +#include <libmisc/error.h> +#include <lib9p/core.h> +#include "srv_errno.h" + +#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L +lib9p_errno_t libmisc_to_linuxgeneric_errno(_errnum errnum) { + LM_PARTIAL_SWITCH (errnum) { + case E_POSIX_E2BIG: return LIB9P_ERRNO_L_E2BIG; + case E_POSIX_EACCES: return LIB9P_ERRNO_L_EACCES; + case E_POSIX_EADDRINUSE: return LIB9P_ERRNO_L_EADDRINUSE; + case E_POSIX_EADDRNOTAVAIL: return LIB9P_ERRNO_L_EADDRNOTAVAIL; + case E_POSIX_EAFNOSUPPORT: return LIB9P_ERRNO_L_EAFNOSUPPORT; + case E_POSIX_EAGAIN: return LIB9P_ERRNO_L_EAGAIN; + case E_POSIX_EALREADY: return LIB9P_ERRNO_L_EALREADY; + case E_POSIX_EBADF: return LIB9P_ERRNO_L_EBADF; + case E_POSIX_EBADMSG: return LIB9P_ERRNO_L_EBADMSG; + case E_POSIX_EBUSY: return LIB9P_ERRNO_L_EBUSY; + case E_POSIX_ECANCELED: return LIB9P_ERRNO_L_ECANCELED; + case E_POSIX_ECHILD: return LIB9P_ERRNO_L_ECHILD; + case E_POSIX_ECONNABORTED: return LIB9P_ERRNO_L_ECONNABORTED; + case E_POSIX_ECONNREFUSED: return LIB9P_ERRNO_L_ECONNREFUSED; + case E_POSIX_ECONNRESET: return LIB9P_ERRNO_L_ECONNRESET; + case E_POSIX_EDEADLK: return LIB9P_ERRNO_L_EDEADLK; + case E_POSIX_EDESTADDRREQ: return LIB9P_ERRNO_L_EDESTADDRREQ; + case E_POSIX_EDOM: return LIB9P_ERRNO_L_EDOM; + case E_POSIX_EDQUOT: return LIB9P_ERRNO_L_EDQUOT; + case E_POSIX_EEXIST: return LIB9P_ERRNO_L_EEXIST; + case E_POSIX_EFAULT: return LIB9P_ERRNO_L_EFAULT; + case E_POSIX_EFBIG: return LIB9P_ERRNO_L_EFBIG; + case E_POSIX_EHOSTUNREACH: return LIB9P_ERRNO_L_EHOSTUNREACH; + case E_POSIX_EIDRM: return LIB9P_ERRNO_L_EIDRM; + case E_POSIX_EILSEQ: return LIB9P_ERRNO_L_EILSEQ; + case E_POSIX_EINPROGRESS: return LIB9P_ERRNO_L_EINPROGRESS; + case E_POSIX_EINTR: return LIB9P_ERRNO_L_EINTR; + case E_POSIX_EINVAL: return LIB9P_ERRNO_L_EINVAL; + case E_POSIX_EIO: return LIB9P_ERRNO_L_EIO; + case E_POSIX_EISCONN: return LIB9P_ERRNO_L_EISCONN; + case E_POSIX_EISDIR: return LIB9P_ERRNO_L_EISDIR; + case E_POSIX_ELOOP: return LIB9P_ERRNO_L_ELOOP; + case E_POSIX_EMFILE: return LIB9P_ERRNO_L_EMFILE; + case E_POSIX_EMLINK: return LIB9P_ERRNO_L_EMLINK; + case E_POSIX_EMSGSIZE: return LIB9P_ERRNO_L_EMSGSIZE; + case E_POSIX_EMULTIHOP: return LIB9P_ERRNO_L_EMULTIHOP; + case E_POSIX_ENAMETOOLONG: return LIB9P_ERRNO_L_ENAMETOOLONG; + case E_POSIX_ENETDOWN: return LIB9P_ERRNO_L_ENETDOWN; + case E_POSIX_ENETRESET: return LIB9P_ERRNO_L_ENETRESET; + case E_POSIX_ENETUNREACH: return LIB9P_ERRNO_L_ENETUNREACH; + case E_POSIX_ENFILE: return LIB9P_ERRNO_L_ENFILE; + case E_POSIX_ENOBUFS: return LIB9P_ERRNO_L_ENOBUFS; + case E_POSIX_ENODEV: return LIB9P_ERRNO_L_ENODEV; + case E_POSIX_ENOENT: return LIB9P_ERRNO_L_ENOENT; + case E_POSIX_ENOEXEC: return LIB9P_ERRNO_L_ENOEXEC; + case E_POSIX_ENOLCK: return LIB9P_ERRNO_L_ENOLCK; + case E_POSIX_ENOLINK: return LIB9P_ERRNO_L_ENOLINK; + case E_POSIX_ENOMEM: return LIB9P_ERRNO_L_ENOMEM; + case E_POSIX_ENOMSG: return LIB9P_ERRNO_L_ENOMSG; + case E_POSIX_ENOPROTOOPT: return LIB9P_ERRNO_L_ENOPROTOOPT; + case E_POSIX_ENOSPC: return LIB9P_ERRNO_L_ENOSPC; + case E_POSIX_ENOSYS: return LIB9P_ERRNO_L_ENOSYS; + case E_POSIX_ENOTCONN: return LIB9P_ERRNO_L_ENOTCONN; + case E_POSIX_ENOTDIR: return LIB9P_ERRNO_L_ENOTDIR; + case E_POSIX_ENOTEMPTY: return LIB9P_ERRNO_L_ENOTEMPTY; + case E_POSIX_ENOTRECOVERABLE: return LIB9P_ERRNO_L_ENOTRECOVERABLE; + case E_POSIX_ENOTSOCK: return LIB9P_ERRNO_L_ENOTSOCK; + case E_POSIX_ENOTTY: return LIB9P_ERRNO_L_ENOTTY; + case E_POSIX_ENXIO: return LIB9P_ERRNO_L_ENXIO; + case E_POSIX_EOPNOTSUPP: return LIB9P_ERRNO_L_EOPNOTSUPP; + case E_POSIX_EOVERFLOW: return LIB9P_ERRNO_L_EOVERFLOW; + case E_POSIX_EOWNERDEAD: return LIB9P_ERRNO_L_EOWNERDEAD; + case E_POSIX_EPERM: return LIB9P_ERRNO_L_EPERM; + case E_POSIX_EPIPE: return LIB9P_ERRNO_L_EPIPE; + case E_POSIX_EPROTO: return LIB9P_ERRNO_L_EPROTO; + case E_POSIX_EPROTONOSUPPORT: return LIB9P_ERRNO_L_EPROTONOSUPPORT; + case E_POSIX_EPROTOTYPE: return LIB9P_ERRNO_L_EPROTOTYPE; + case E_POSIX_ERANGE: return LIB9P_ERRNO_L_ERANGE; + case E_POSIX_EROFS: return LIB9P_ERRNO_L_EROFS; + case E_POSIX_ESOCKTNOSUPPORT: return LIB9P_ERRNO_L_ESOCKTNOSUPPORT; + case E_POSIX_ESPIPE: return LIB9P_ERRNO_L_ESPIPE; + case E_POSIX_ESRCH: return LIB9P_ERRNO_L_ESRCH; + case E_POSIX_ESTALE: return LIB9P_ERRNO_L_ESTALE; + case E_POSIX_ETIMEDOUT: return LIB9P_ERRNO_L_ETIMEDOUT; + case E_POSIX_ETXTBSY: return LIB9P_ERRNO_L_ETXTBSY; + case E_POSIX_EXDEV: return LIB9P_ERRNO_L_EXDEV; + case E_POSIX_ENOTSUP: return LIB9P_ERRNO_L_EOPNOTSUPP; + case E_POSIX_EWOULDBLOCK: return LIB9P_ERRNO_L_EAGAIN; + default: return LIB9P_ERRNO_L_EIO; + } +} +#endif diff --git a/lib9p/srv_generated.c.gen b/lib9p/srv_generated.c.gen new file mode 100755 index 0000000..6a6335a --- /dev/null +++ b/lib9p/srv_generated.c.gen @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# lib9p/srv_generated.c.gen - Generate errno translation tables +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +error_h=$1 +outfile=$2 + +{ + echo "/* ${outfile} - Generated by $0. DO NOT EDIT! */" + echo + echo '#include <libmisc/error.h>' + echo '#include <lib9p/core.h>' + echo '#include "srv_errno.h"' + echo + echo '#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L' + echo 'lib9p_errno_t libmisc_to_linuxgeneric_errno(_errnum errnum) {' + echo $'\tLM_PARTIAL_SWITCH (errnum) {' + sed -nE \ + -e 's@^(#define)?\s+(E_POSIX_([_A-Z0-9]+))[ ,][^/]*/\* ([^*(]+) (\*/|\().*@'$'\tcase \\2: return LIB9P_ERRNO_L_\\3;''@p' \ + -- "$error_h" | + grep -v -e '_ENOTSUP' -e '_EWOULDBLOCK' + echo $'\tcase E_POSIX_ENOTSUP: return LIB9P_ERRNO_L_EOPNOTSUPP;' + echo $'\tcase E_POSIX_EWOULDBLOCK: return LIB9P_ERRNO_L_EAGAIN;' + echo $'\tdefault: return LIB9P_ERRNO_L_EIO;' + echo $'\t}' + echo '}' + echo '#endif' +} >"$outfile" diff --git a/lib9p/srv_include/lib9p/srv.h b/lib9p/srv_include/lib9p/srv.h new file mode 100644 index 0000000..0f1c88b --- /dev/null +++ b/lib9p/srv_include/lib9p/srv.h @@ -0,0 +1,309 @@ +/* lib9p/srv.h - 9P server + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_SRV_H_ +#define _LIB9P_SRV_H_ + +#include <libcr/coroutine.h> +#include <libcr_ipc/chan.h> +#include <libcr_ipc/rpc.h> +#include <libhw/generic/net.h> +#include <libmisc/assert.h> +#include <libmisc/obj.h> +#include <libmisc/private.h> + +#include <lib9p/core.h> + +#ifndef CONFIG_9P_SRV_MAX_ERR_SIZE + #error config.h must define CONFIG_9P_SRV_MAX_ERR_SIZE +#endif +static_assert(CONFIG_9P_SRV_MAX_ERR_SIZE <= UINT16_MAX); + +/* context ********************************************************************/ + +struct lib9p_srv_userid { + struct lib9p_s name; +#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L + lib9p_nuid_t num; +#endif + + BEGIN_PRIVATE(LIB9P_SRV_H); + unsigned int refcount; + END_PRIVATE(LIB9P_SRV_H); +}; + +enum _lib9p_srv_flush_result { + _LIB9P_SRV_FLUSH_RFLUSH, + _LIB9P_SRV_FLUSH_SILENT, +}; + +CR_CHAN_DECLARE(_lib9p_srv_flush_ch, enum _lib9p_srv_flush_result); + +struct lib9p_srv_ctx { + struct lib9p_ctx basectx; + struct lib9p_srv_userid *user; + + BEGIN_PRIVATE(LIB9P_SRV_H); + struct _lib9p_srv_sess *parent_sess; + lib9p_tag_t tag; + uint8_t *net_bytes; + _lib9p_srv_flush_ch_t flush_ch; /* flushers for this req _read_ from here */ + bool responded; + END_PRIVATE(LIB9P_SRV_H); +}; + +/** + * Return whether there is an outstanding Tflush or Tversion + * cancellation of this request. After becoming true, this may go + * back to false if the Tflush itself is flushed. + * + * As a special case, returning E_POSIX_ECANCELED indicates that the + * flush has been observed, and a Rerror should not be sent ot the + * client. + */ +bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx); + +/* version-independent stat ***************************************************/ + +struct lib9p_srv_stat { + struct lib9p_qid qid; + lib9p_dm_t mode; + uint32_t atime_sec; /* BUG: u32 seconds means a 2106 problem */ +#if CONFIG_9P_ENABLE_9P2000_L + uint32_t atime_nsec; +#endif + uint32_t mtime_sec; /* BUG: u32 seconds means a 2106 problem */ +#if CONFIG_9P_ENABLE_9P2000_L + uint32_t mtime_nsec; + uint32_t ctime_sec; /* BUG: u32 seconds means a 2106 problem */ + uint32_t ctime_nsec; + uint32_t btime_sec; /* BUG: u32 seconds means a 2106 problem */ + uint32_t btime_nsec; +#endif + uint64_t size; + struct lib9p_s name; + struct lib9p_srv_userid owner_uid; + struct lib9p_srv_userid owner_gid; + struct lib9p_srv_userid last_modifier_uid; +#if CONFIG_9P_ENABLE_9P2000_u + struct lib9p_s extension; +#endif +}; +typedef struct lib9p_srv_stat lib9p_srv_stat; +DECLARE_ERROR_OR(lib9p_srv_stat); + +void lib9p_srv_stat_assert(struct lib9p_srv_stat stat); + +/* interface definitions ******************************************************/ + +typedef struct iovec iovec; +DECLARE_ERROR_OR(iovec); + +struct lib9p_srv_dirent { + struct lib9p_qid qid; + struct lib9p_s name; +}; +typedef struct lib9p_srv_dirent lib9p_srv_dirent; +DECLARE_ERROR_OR(lib9p_srv_dirent); + +/* FIXME: I don't like that the pointer returned by pread() has to + * remain live after it returns. Perhaps a `respond()`-callback? But + * that just reads as gross in C. + */ +#define lib9p_srv_fio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ + LO_FUNC(struct lib9p_qid , qid ) \ + LO_FUNC(void , iofree ) \ + LO_FUNC(uint32_t , iounit ) \ + LO_FUNC(iovec_list__or_error , pread , struct lib9p_srv_ctx *, \ + uint32_t byte_count, \ + uint64_t byte_offset) \ + /** \ + * If the file was append-only when fopen()ed, then byte_offset will \ + * always be 0. \ + */ \ + LO_FUNC(uint32_t_or_error , pwrite , struct lib9p_srv_ctx *, \ + void *buf, \ + uint32_t byte_count, \ + uint64_t byte_offset) +LO_INTERFACE(lib9p_srv_fio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +typedef lo_interface lib9p_srv_fio lib9p_srv_fio; +DECLARE_ERROR_OR(lib9p_srv_fio); + +#define lib9p_srv_dio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ + LO_FUNC(struct lib9p_qid , qid ) \ + LO_FUNC(void , iofree ) \ + /** \ + * Return the idx-th dirent. idx will always be either 0 or \ + * prev_idx+1. A dirent with an empty name signals EOF. The string \ + * must remain valid until the next dread() call or iofree(). \ + */ \ + LO_FUNC(lib9p_srv_dirent_or_error , dread , struct lib9p_srv_ctx *, \ + size_t idx) +LO_INTERFACE(lib9p_srv_dio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +typedef lo_interface lib9p_srv_dio lib9p_srv_dio; +DECLARE_ERROR_OR(lib9p_srv_dio); + +struct _lo_lib9p_srv_file_vtable; +lo_interface lib9p_srv_file { + void *self; + const struct _lo_lib9p_srv_file_vtable *vtable; +}; +typedef lo_interface lib9p_srv_file lib9p_srv_file; +DECLARE_ERROR_OR(lib9p_srv_file); +#define lib9p_srv_file_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ + /* resource management **********************************************/ \ + \ + /** \ + * free() is be called when all FIDs associated with the file are \ + * clunked. \ + * \ + * free() MUST NOT error. \ + */ \ + LO_FUNC(void , free ) \ + \ + /** \ + * qid() is called frequently and returns the current QID of the file. \ + * The .path field MUST never change, the .type field may change in \ + * response to wstat() calls (but the QT_DIR bit MUST NOT change), and \ + * the .vers field may change frequently in response to any number of \ + * things (wstat(), write(), or non-9P events). \ + * \ + * qid() MUST NOT error. \ + */ \ + LO_FUNC(struct lib9p_qid , qid ) \ + \ + /* non-"opened" generic I/O *****************************************/ \ + \ + /** Strings returned from stat() must remain valid until free(). */ \ + LO_FUNC(lib9p_srv_stat_or_error , stat , struct lib9p_srv_ctx *) \ + LO_FUNC(error , wstat , struct lib9p_srv_ctx *, \ + struct lib9p_srv_stat) \ + LO_FUNC(error , remove , struct lib9p_srv_ctx *) \ + \ + /* non-"opened" directory I/O ***************************************/ \ + \ + LO_FUNC(lib9p_srv_file_or_error , dwalk , struct lib9p_srv_ctx *, \ + struct lib9p_s childname) \ + LO_FUNC(lib9p_srv_file_or_error , dcreate, struct lib9p_srv_ctx *, \ + struct lib9p_s childname, \ + struct lib9p_srv_userid *user, \ + struct lib9p_srv_userid *group, \ + lib9p_dm_t perm) \ + \ + /* open() for I/O ***************************************************/ \ + \ + LO_FUNC(lib9p_srv_fio_or_error , fopen , struct lib9p_srv_ctx *, \ + bool rd, bool wr, \ + bool trunc) \ + LO_FUNC(lib9p_srv_dio_or_error , dopen , struct lib9p_srv_ctx *) +LO_INTERFACE(lib9p_srv_file); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ + +#define LIB9P_SRV_NOTDIR(TYP, NAM) \ + static lib9p_srv_file_or_error NAM##_dwalk (TYP *, struct lib9p_srv_ctx *, struct lib9p_s) { assert_notreached("not a directory"); } \ + static lib9p_srv_file_or_error NAM##_dcreate(TYP *, struct lib9p_srv_ctx *, struct lib9p_s, \ + struct lib9p_srv_userid *, struct lib9p_srv_userid *, lib9p_dm_t) { assert_notreached("not a directory"); } \ + static lib9p_srv_dio_or_error NAM##_dopen (TYP *, struct lib9p_srv_ctx *) { assert_notreached("not a directory"); } \ + LM_FORCE_SEMICOLON + +#define LIB9P_SRV_NOTFILE(TYP, NAM) \ + static lib9p_srv_fio_or_error NAM##_fopen (TYP *, struct lib9p_srv_ctx *, bool, bool, bool) { assert_notreached("not a file"); } \ + LM_FORCE_SEMICOLON + +/* main server entrypoints ****************************************************/ + +CR_RPC_DECLARE(_lib9p_srv_reqch, struct lib9p_srv_ctx *, bool); + +#if CONFIG_9P_ENABLE_9P2000_p9p +#define net_stream_conn_unix_LO_IFACE \ + LO_NEST(net_stream_conn) \ + /** Returns 0 on success, -errno on error. */ \ + LO_FUNC(int, send_unix_fd, int fd) +LO_INTERFACE(net_stream_conn_unix); +#endif + +struct lib9p_srv { + /* Things you provide */ + error /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */ + lib9p_srv_file_or_error (*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename); + void (*msglog )(struct lib9p_srv_ctx *, enum lib9p_msg_type, void *hostmsg); /* optional */ +#if CONFIG_9P_ENABLE_9P2000_p9p + lo_interface net_stream_conn_unix (*type_assert_unix)(lo_interface net_stream_conn); /* optional */ +#endif + + /* For internal use */ + BEGIN_PRIVATE(LIB9P_SRV_H); + unsigned int readers; + unsigned int writers; + _lib9p_srv_reqch_t _reqch; + END_PRIVATE(LIB9P_SRV_H); +}; + +/** + * In a loop loop, accept a connection call lib9p_srv_read() on it. + * If LO_CALL(listener, accept) fails, then the function returns. + * + * When the last lib9p_srv_accept_and_read_loop() instance for a given + * `srv` returns, it will signal all lib9p_srv_worker_loop() calls to + * return. + * + * @param srv: The server configuration and state; has an associated + * pool of lib9p_srv_worker_loop() coroutines. + * + * @param listener: The listener object to accept connections from. + */ +void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stream_listener listener); + +/** + * You should probably not call this directly; you should probably use + * lib9p_srv_accept_and_read_loop(). + * + * Given an already-established stream connection (i.e. a TCP + * connection), service that connection; return once the connection is + * closed. Requests are dispatched to a pool of + * lib9p_srv_worker_loop() coroutines with the same `srv`. + * + * Will just close the connection if a T-message has a size[4] <7. + * + * @param srv: The server configuration and state; has an associated + * pool of lib9p_srv_worker_loop() coroutines. + * + * @param conn: The listener object to accept connections from. + * + * Errors that this function itself may send to clients: + * + * @errno E_POSIX_EMSGSIZE T-message has size[4] bigger than max_msg_size + * @errno E_POSIX_EDOM Tversion specified an impossibly small max_msg_size + * @errno E_POSIX_EOPNOTSUPP T-message has an R-message type, or an unrecognized T-message type + * @errno E_POSIX_EBADMSG T-message has wrong size[4] for its content, or has invalid UTF-8 + */ +void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn conn); + +/** + * In a loop, call lib9p_srv_worker() to service requests to the + * `struct lib9p_srv *srv` argument that have been read by + * lib9p_srv_accept_and_read_loop() / lib9p_srv_read(). A "NULL" + * request causes the function to return. + * + * @param srv: The server configuration and state; has an associated + * pool of lib9p_srv_accept_and_read_loop() coroutines. + */ +void lib9p_srv_worker_loop(struct lib9p_srv *srv); + +/** + * You should probably not call this directly; you should probably use + * lib9p_srv_worker_loop(). + * + * Handle and send a response to a single request. + * + * @param req: The request to handle. + * + * Errors that this function itself may send to clients: + * + * @errno E_POSIX_ERANGE R-message does not fit into max_msg_size + */ +void lib9p_srv_worker(struct lib9p_srv_ctx *req); + +#endif /* _LIB9P_SRV_H_ */ diff --git a/lib9p/tests/client_config/config.h b/lib9p/tests/client_config/config.h new file mode 100644 index 0000000..4bba4ec --- /dev/null +++ b/lib9p/tests/client_config/config.h @@ -0,0 +1,18 @@ +/* config.h - Compile-time configuration for lib9p test clients + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#define CONFIG_9P_MAX_9P2000_e_WELEM 16 + +#define CONFIG_9P_ENABLE_9P2000 1 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_e 1 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_L 1 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_p9p 1 /* bool */ + +#endif /* _CONFIG_H_ */ diff --git a/lib9p/tests/runtest b/lib9p/tests/runtest index a745f12..6883391 100755 --- a/lib9p/tests/runtest +++ b/lib9p/tests/runtest @@ -1,65 +1,50 @@ #!/usr/bin/env bash -# lib9p/tests/runtest - Simple tests for the 9P `test_server` +# lib9p/tests/runtest - Test harness for the 9P `test_server` # # Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-License-Identifier: AGPL-3.0-or-later set -euE -o pipefail -set -x -port=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()') -valgrind --error-exitcode=2 ./tests/test_server/test_server "$port" & -server_pid=$! -# shellcheck disable=SC2064 -trap "kill $server_pid || true; wait $server_pid || true" EXIT -server_addr="localhost:${port}" +build_aux=$(realpath --canonicalize-missing -- "${BASH_SOURCE[0]}/../../../build-aux") -client=(9p -a "$server_addr") +if [[ $# != 2 ]]; then + echo >&2 "Usage: $0 CLIENTSCRIPT EXPLOG" + exit 2 +fi +clientscript="$1" +explog="$2" -expect_lines() ( +cleanup=() +cleanup() { { set +x; } &>/dev/null - printf >&2 '+ diff -u expected.txt actual.txt\n' - diff -u <(printf '%s\n' "$@") <(printf '%s\n' "$out") -) - -while [[ -d /proc/$server_pid && "$(readlink /proc/$server_pid/fd/4 2>/dev/null)" != socket:* ]]; do sleep 0.1; done - -out=$("${client[@]}" ls -l '') -expect_lines \ - 'd-r-xr-xr-x M 0 root root 0 Oct 7 15:51 Documentation' \ - '--r--r--r-- M 0 root root 166 Oct 7 15:51 README.md' \ - '---w--w--w- M 0 root root 0 Oct 7 15:51 shutdown' + local i + for ((i = ${#cleanup[@]} - 1; i >= 0; i--)); do + eval "set -x; ${cleanup[$i]}" + { set +x; } &>/dev/null + done +} +trap cleanup EXIT -out=$("${client[@]}" ls -l 'Documentation/') -expect_lines \ - '--r--r--r-- M 0 root root 166 Oct 7 15:51 x' +logfile=$(mktemp -t lib9p-log.XXXXXXXXXX) +cleanup+=("rm -f -- ${logfile@Q}") -out=$("${client[@]}" read 'README.md') -expect_lines \ - '<!--' \ - ' README.md - test static file' \ - '' \ - ' Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>' \ - ' SPDX-License-Identifier: AGPL-3.0-or-later' \ - '-->' \ - 'Hello, world!' +port=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()') -out=$("${client[@]}" read 'Documentation/x') -expect_lines \ - '<!--' \ - ' Documentation/x.txt - test static file' \ - '' \ - ' Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>' \ - ' SPDX-License-Identifier: AGPL-3.0-or-later' \ - '-->' \ - 'foo' +set -x -out=$("${client[@]}" stat 'Documentation/x') -expect_lines \ - "'x' 'root' 'root' 'root' q (0000000000000001 1 ) m 0444 at 1728337905 mt 1728337904 l 166 t 0 d 0" +"${build_aux}/valgrind" ./tests/test_server/test_server "$port" "$logfile" & +server_pid=$! +cleanup+=("kill $server_pid || true; wait $server_pid || true") +while [[ -d /proc/$server_pid ]] && ! (readlink /proc/$server_pid/fd/* 2>/dev/null | grep -q ^socket:); do sleep 0.1; done -out=$("${client[@]}" write 'shutdown' <<<1) -expect_lines '' +if [[ "$(head -c2 -- "$clientscript")" == '#!' ]]; then + "$clientscript" "$port" +else + "${build_aux}/valgrind" "$clientscript" "$port" +fi wait "$server_pid" -trap - EXIT +cleanup=("${cleanup[@]::1}") + +diff -u -- <(grep -e '^[<>]' -- "$explog") "$logfile" diff --git a/lib9p/tests/test_compile.c b/lib9p/tests/test_compile.c index 6abee05..6d7fb50 100644 --- a/lib9p/tests/test_compile.c +++ b/lib9p/tests/test_compile.c @@ -1,157 +1,1255 @@ /* lib9p/tests/test_compile.c - Generated by lib9p/tests/test_compile.c.gen. DO NOT EDIT! */ -#include <lib9p/9p.h> +#include <lib9p/core.h> int main(void) { - [[gnu::unused]] uint64_t x; - x = LIB9P_TAG_NOTAG; - x = LIB9P_FID_NOFID; - x = LIB9P_DM_DIR; - x = LIB9P_DM_APPEND; - x = LIB9P_DM_EXCL; - x = _LIB9P_DM_RESERVED_PLAN9_MOUNT; - x = LIB9P_DM_AUTH; - x = LIB9P_DM_TMP; - x = LIB9P_DM_DEVICE; - x = LIB9P_DM_NAMEDPIPE; - x = LIB9P_DM_SOCKET; - x = LIB9P_DM_SETUID; - x = LIB9P_DM_SETGID; - x = LIB9P_DM_OWNER_R; - x = LIB9P_DM_OWNER_W; - x = LIB9P_DM_OWNER_X; - x = LIB9P_DM_GROUP_R; - x = LIB9P_DM_GROUP_W; - x = LIB9P_DM_GROUP_X; - x = LIB9P_DM_OTHER_R; - x = LIB9P_DM_OTHER_W; - x = LIB9P_DM_OTHER_X; - x = LIB9P_DM_PERM_MASK; - x = LIB9P_QT_DIR; - x = LIB9P_QT_APPEND; - x = LIB9P_QT_EXCL; - x = _LIB9P_QT_RESERVED_PLAN9_MOUNT; - x = LIB9P_QT_AUTH; - x = LIB9P_QT_TMP; - x = LIB9P_QT_SYMLINK; - x = LIB9P_QT_FILE; - x = LIB9P_NUID_NONUID; - x = LIB9P_O_RCLOSE; - x = _LIB9P_O_RESERVED_CEXEC; - x = LIB9P_O_TRUNC; - x = _LIB9P_O_mode_1; - x = _LIB9P_O_mode_0; - x = LIB9P_O_READ; - x = LIB9P_O_WRITE; - x = LIB9P_O_RDWR; - x = LIB9P_O_EXEC; - x = LIB9P_O_MODE_MASK; - x = LIB9P_O_FLAG_MASK; - x = LIB9P_ERRNO_NOERROR; - x = LIB9P_SUPER_MAGIC_V9FS_MAGIC; - x = LIB9P_LO_SYNC; - x = LIB9P_LO_CLOEXEC; - x = LIB9P_LO_NOATIME; - x = LIB9P_LO_NOFOLLOW; - x = LIB9P_LO_DIRECTORY; - x = LIB9P_LO_LARGEFILE; - x = LIB9P_LO_DIRECT; - x = LIB9P_LO_BSD_FASYNC; - x = LIB9P_LO_DSYNC; - x = LIB9P_LO_NONBLOCK; - x = LIB9P_LO_APPEND; - x = LIB9P_LO_TRUNC; - x = LIB9P_LO_NOCTTY; - x = LIB9P_LO_EXCL; - x = LIB9P_LO_CREATE; - x = _LIB9P_LO_mode_1; - x = _LIB9P_LO_mode_0; - x = LIB9P_LO_RDONLY; - x = LIB9P_LO_WRONLY; - x = LIB9P_LO_RDWR; - x = LIB9P_LO_NOACCESS; - x = LIB9P_LO_MODE_MASK; - x = LIB9P_LO_FLAG_MASK; - x = LIB9P_DT_UNKNOWN; - x = LIB9P_DT_NAMED_PIPE; - x = LIB9P_DT_CHAR_DEV; - x = LIB9P_DT_DIRECTORY; - x = LIB9P_DT_BLOCK_DEV; - x = LIB9P_DT_REGULAR; - x = LIB9P_DT_SYMLINK; - x = LIB9P_DT_SOCKET; - x = LIB9P_DT_WHITEOUT; - x = _LIB9P_MODE_fmt_3; - x = _LIB9P_MODE_fmt_2; - x = _LIB9P_MODE_fmt_1; - x = _LIB9P_MODE_fmt_0; - x = LIB9P_MODE_PERM_SETGROUP; - x = LIB9P_MODE_PERM_SETUSER; - x = LIB9P_MODE_PERM_STICKY; - x = LIB9P_MODE_PERM_OWNER_R; - x = LIB9P_MODE_PERM_OWNER_W; - x = LIB9P_MODE_PERM_OWNER_X; - x = LIB9P_MODE_PERM_GROUP_R; - x = LIB9P_MODE_PERM_GROUP_W; - x = LIB9P_MODE_PERM_GROUP_X; - x = LIB9P_MODE_PERM_OTHER_R; - x = LIB9P_MODE_PERM_OTHER_W; - x = LIB9P_MODE_PERM_OTHER_X; - x = LIB9P_MODE_FMT_NAMED_PIPE; - x = LIB9P_MODE_FMT_CHAR_DEV; - x = LIB9P_MODE_FMT_DIRECTORY; - x = LIB9P_MODE_FMT_BLOCK_DEV; - x = LIB9P_MODE_FMT_REGULAR; - x = LIB9P_MODE_FMT_SYMLINK; - x = LIB9P_MODE_FMT_SOCKET; - x = LIB9P_MODE_PERM_MASK; - x = LIB9P_MODE_FMT_MASK; - x = LIB9P_B4_FALSE; - x = LIB9P_B4_TRUE; - x = LIB9P_GETATTR_DATA_VERSION; - x = LIB9P_GETATTR_GEN; - x = LIB9P_GETATTR_BTIME; - x = LIB9P_GETATTR_BLOCKS; - x = LIB9P_GETATTR_SIZE; - x = LIB9P_GETATTR_INO; - x = LIB9P_GETATTR_CTIME; - x = LIB9P_GETATTR_MTIME; - x = LIB9P_GETATTR_ATIME; - x = LIB9P_GETATTR_RDEV; - x = LIB9P_GETATTR_GID; - x = LIB9P_GETATTR_UID; - x = LIB9P_GETATTR_NLINK; - x = LIB9P_GETATTR_MODE; - x = LIB9P_GETATTR_BASIC; - x = LIB9P_GETATTR_ALL; - x = LIB9P_SETATTR_MTIME_SET; - x = LIB9P_SETATTR_ATIME_SET; - x = LIB9P_SETATTR_CTIME; - x = LIB9P_SETATTR_MTIME; - x = LIB9P_SETATTR_ATIME; - x = LIB9P_SETATTR_SIZE; - x = LIB9P_SETATTR_GID; - x = LIB9P_SETATTR_UID; - x = LIB9P_SETATTR_MODE; - x = LIB9P_LOCK_TYPE_RDLCK; - x = LIB9P_LOCK_TYPE_WRLCK; - x = LIB9P_LOCK_TYPE_UNLCK; - x = LIB9P_LOCK_FLAGS_RECLAIM; - x = LIB9P_LOCK_FLAGS_BLOCK; - x = LIB9P_LOCK_STATUS_SUCCESS; - x = LIB9P_LOCK_STATUS_BLOCKED; - x = LIB9P_LOCK_STATUS_ERROR; - x = LIB9P_LOCK_STATUS_GRACE; - x = LIB9P_TMSG_MAX_IOV; - x = LIB9P_TMSG_MAX_IOV; - x = LIB9P_TMSG_MAX_COPY; - x = LIB9P_TMSG_MAX_COPY; - x = LIB9P_TMSG_MAX_COPY; - x = LIB9P_TMSG_MAX_COPY; - x = LIB9P_TMSG_MAX_COPY; - x = LIB9P_TMSG_MAX_COPY; - x = LIB9P_RMSG_MAX_IOV; - x = LIB9P_RMSG_MAX_IOV; - x = LIB9P_RMSG_MAX_IOV; - x = LIB9P_RMSG_MAX_COPY; - return 0; + [[maybe_unused]] uint64_t x; +#ifdef LIB9P_B4_FALSE + x = LIB9P_B4_FALSE; +#endif +#ifdef LIB9P_B4_TRUE + x = LIB9P_B4_TRUE; +#endif +#ifdef LIB9P_DM_APPEND + x = LIB9P_DM_APPEND; +#endif +#ifdef LIB9P_DM_AUTH + x = LIB9P_DM_AUTH; +#endif +#ifdef LIB9P_DM_DEVICE + x = LIB9P_DM_DEVICE; +#endif +#ifdef LIB9P_DM_DIR + x = LIB9P_DM_DIR; +#endif +#ifdef LIB9P_DM_EXCL + x = LIB9P_DM_EXCL; +#endif +#ifdef LIB9P_DM_GROUP_R + x = LIB9P_DM_GROUP_R; +#endif +#ifdef LIB9P_DM_GROUP_W + x = LIB9P_DM_GROUP_W; +#endif +#ifdef LIB9P_DM_GROUP_X + x = LIB9P_DM_GROUP_X; +#endif +#ifdef LIB9P_DM_OTHER_R + x = LIB9P_DM_OTHER_R; +#endif +#ifdef LIB9P_DM_OTHER_W + x = LIB9P_DM_OTHER_W; +#endif +#ifdef LIB9P_DM_OTHER_X + x = LIB9P_DM_OTHER_X; +#endif +#ifdef LIB9P_DM_OWNER_R + x = LIB9P_DM_OWNER_R; +#endif +#ifdef LIB9P_DM_OWNER_W + x = LIB9P_DM_OWNER_W; +#endif +#ifdef LIB9P_DM_OWNER_X + x = LIB9P_DM_OWNER_X; +#endif +#ifdef LIB9P_DM_PERM_MASK + x = LIB9P_DM_PERM_MASK; +#endif +#ifdef LIB9P_DM_PIPE + x = LIB9P_DM_PIPE; +#endif +#ifdef LIB9P_DM_SETGID + x = LIB9P_DM_SETGID; +#endif +#ifdef LIB9P_DM_SETUID + x = LIB9P_DM_SETUID; +#endif +#ifdef LIB9P_DM_SOCKET + x = LIB9P_DM_SOCKET; +#endif +#ifdef LIB9P_DM_TMP + x = LIB9P_DM_TMP; +#endif +#ifdef LIB9P_DT_BLOCK_DEV + x = LIB9P_DT_BLOCK_DEV; +#endif +#ifdef LIB9P_DT_CHAR_DEV + x = LIB9P_DT_CHAR_DEV; +#endif +#ifdef LIB9P_DT_DIRECTORY + x = LIB9P_DT_DIRECTORY; +#endif +#ifdef LIB9P_DT_PIPE + x = LIB9P_DT_PIPE; +#endif +#ifdef LIB9P_DT_REGULAR + x = LIB9P_DT_REGULAR; +#endif +#ifdef LIB9P_DT_SOCKET + x = LIB9P_DT_SOCKET; +#endif +#ifdef LIB9P_DT_SYMLINK + x = LIB9P_DT_SYMLINK; +#endif +#ifdef LIB9P_DT_UNKNOWN + x = LIB9P_DT_UNKNOWN; +#endif +#ifdef LIB9P_ERRNO_L_E2BIG + x = LIB9P_ERRNO_L_E2BIG; +#endif +#ifdef LIB9P_ERRNO_L_EACCES + x = LIB9P_ERRNO_L_EACCES; +#endif +#ifdef LIB9P_ERRNO_L_EADDRINUSE + x = LIB9P_ERRNO_L_EADDRINUSE; +#endif +#ifdef LIB9P_ERRNO_L_EADDRNOTAVAIL + x = LIB9P_ERRNO_L_EADDRNOTAVAIL; +#endif +#ifdef LIB9P_ERRNO_L_EADV + x = LIB9P_ERRNO_L_EADV; +#endif +#ifdef LIB9P_ERRNO_L_EAFNOSUPPORT + x = LIB9P_ERRNO_L_EAFNOSUPPORT; +#endif +#ifdef LIB9P_ERRNO_L_EAGAIN + x = LIB9P_ERRNO_L_EAGAIN; +#endif +#ifdef LIB9P_ERRNO_L_EALREADY + x = LIB9P_ERRNO_L_EALREADY; +#endif +#ifdef LIB9P_ERRNO_L_EBADE + x = LIB9P_ERRNO_L_EBADE; +#endif +#ifdef LIB9P_ERRNO_L_EBADF + x = LIB9P_ERRNO_L_EBADF; +#endif +#ifdef LIB9P_ERRNO_L_EBADFD + x = LIB9P_ERRNO_L_EBADFD; +#endif +#ifdef LIB9P_ERRNO_L_EBADMSG + x = LIB9P_ERRNO_L_EBADMSG; +#endif +#ifdef LIB9P_ERRNO_L_EBADR + x = LIB9P_ERRNO_L_EBADR; +#endif +#ifdef LIB9P_ERRNO_L_EBADRQC + x = LIB9P_ERRNO_L_EBADRQC; +#endif +#ifdef LIB9P_ERRNO_L_EBADSLT + x = LIB9P_ERRNO_L_EBADSLT; +#endif +#ifdef LIB9P_ERRNO_L_EBFONT + x = LIB9P_ERRNO_L_EBFONT; +#endif +#ifdef LIB9P_ERRNO_L_EBUSY + x = LIB9P_ERRNO_L_EBUSY; +#endif +#ifdef LIB9P_ERRNO_L_ECANCELED + x = LIB9P_ERRNO_L_ECANCELED; +#endif +#ifdef LIB9P_ERRNO_L_ECHILD + x = LIB9P_ERRNO_L_ECHILD; +#endif +#ifdef LIB9P_ERRNO_L_ECHRNG + x = LIB9P_ERRNO_L_ECHRNG; +#endif +#ifdef LIB9P_ERRNO_L_ECOMM + x = LIB9P_ERRNO_L_ECOMM; +#endif +#ifdef LIB9P_ERRNO_L_ECONNABORTED + x = LIB9P_ERRNO_L_ECONNABORTED; +#endif +#ifdef LIB9P_ERRNO_L_ECONNREFUSED + x = LIB9P_ERRNO_L_ECONNREFUSED; +#endif +#ifdef LIB9P_ERRNO_L_ECONNRESET + x = LIB9P_ERRNO_L_ECONNRESET; +#endif +#ifdef LIB9P_ERRNO_L_EDEADLK + x = LIB9P_ERRNO_L_EDEADLK; +#endif +#ifdef LIB9P_ERRNO_L_EDESTADDRREQ + x = LIB9P_ERRNO_L_EDESTADDRREQ; +#endif +#ifdef LIB9P_ERRNO_L_EDOM + x = LIB9P_ERRNO_L_EDOM; +#endif +#ifdef LIB9P_ERRNO_L_EDOTDOT + x = LIB9P_ERRNO_L_EDOTDOT; +#endif +#ifdef LIB9P_ERRNO_L_EDQUOT + x = LIB9P_ERRNO_L_EDQUOT; +#endif +#ifdef LIB9P_ERRNO_L_EEXIST + x = LIB9P_ERRNO_L_EEXIST; +#endif +#ifdef LIB9P_ERRNO_L_EFAULT + x = LIB9P_ERRNO_L_EFAULT; +#endif +#ifdef LIB9P_ERRNO_L_EFBIG + x = LIB9P_ERRNO_L_EFBIG; +#endif +#ifdef LIB9P_ERRNO_L_EHOSTDOWN + x = LIB9P_ERRNO_L_EHOSTDOWN; +#endif +#ifdef LIB9P_ERRNO_L_EHOSTUNREACH + x = LIB9P_ERRNO_L_EHOSTUNREACH; +#endif +#ifdef LIB9P_ERRNO_L_EHWPOISON + x = LIB9P_ERRNO_L_EHWPOISON; +#endif +#ifdef LIB9P_ERRNO_L_EIDRM + x = LIB9P_ERRNO_L_EIDRM; +#endif +#ifdef LIB9P_ERRNO_L_EILSEQ + x = LIB9P_ERRNO_L_EILSEQ; +#endif +#ifdef LIB9P_ERRNO_L_EINPROGRESS + x = LIB9P_ERRNO_L_EINPROGRESS; +#endif +#ifdef LIB9P_ERRNO_L_EINTR + x = LIB9P_ERRNO_L_EINTR; +#endif +#ifdef LIB9P_ERRNO_L_EINVAL + x = LIB9P_ERRNO_L_EINVAL; +#endif +#ifdef LIB9P_ERRNO_L_EIO + x = LIB9P_ERRNO_L_EIO; +#endif +#ifdef LIB9P_ERRNO_L_EISCONN + x = LIB9P_ERRNO_L_EISCONN; +#endif +#ifdef LIB9P_ERRNO_L_EISDIR + x = LIB9P_ERRNO_L_EISDIR; +#endif +#ifdef LIB9P_ERRNO_L_EISNAM + x = LIB9P_ERRNO_L_EISNAM; +#endif +#ifdef LIB9P_ERRNO_L_EKEYEXPIRED + x = LIB9P_ERRNO_L_EKEYEXPIRED; +#endif +#ifdef LIB9P_ERRNO_L_EKEYREJECTED + x = LIB9P_ERRNO_L_EKEYREJECTED; +#endif +#ifdef LIB9P_ERRNO_L_EKEYREVOKED + x = LIB9P_ERRNO_L_EKEYREVOKED; +#endif +#ifdef LIB9P_ERRNO_L_EL2HLT + x = LIB9P_ERRNO_L_EL2HLT; +#endif +#ifdef LIB9P_ERRNO_L_EL2NSYNC + x = LIB9P_ERRNO_L_EL2NSYNC; +#endif +#ifdef LIB9P_ERRNO_L_EL3HLT + x = LIB9P_ERRNO_L_EL3HLT; +#endif +#ifdef LIB9P_ERRNO_L_EL3RST + x = LIB9P_ERRNO_L_EL3RST; +#endif +#ifdef LIB9P_ERRNO_L_ELIBACC + x = LIB9P_ERRNO_L_ELIBACC; +#endif +#ifdef LIB9P_ERRNO_L_ELIBBAD + x = LIB9P_ERRNO_L_ELIBBAD; +#endif +#ifdef LIB9P_ERRNO_L_ELIBEXEC + x = LIB9P_ERRNO_L_ELIBEXEC; +#endif +#ifdef LIB9P_ERRNO_L_ELIBMAX + x = LIB9P_ERRNO_L_ELIBMAX; +#endif +#ifdef LIB9P_ERRNO_L_ELIBSCN + x = LIB9P_ERRNO_L_ELIBSCN; +#endif +#ifdef LIB9P_ERRNO_L_ELNRNG + x = LIB9P_ERRNO_L_ELNRNG; +#endif +#ifdef LIB9P_ERRNO_L_ELOOP + x = LIB9P_ERRNO_L_ELOOP; +#endif +#ifdef LIB9P_ERRNO_L_EMEDIUMTYPE + x = LIB9P_ERRNO_L_EMEDIUMTYPE; +#endif +#ifdef LIB9P_ERRNO_L_EMFILE + x = LIB9P_ERRNO_L_EMFILE; +#endif +#ifdef LIB9P_ERRNO_L_EMLINK + x = LIB9P_ERRNO_L_EMLINK; +#endif +#ifdef LIB9P_ERRNO_L_EMSGSIZE + x = LIB9P_ERRNO_L_EMSGSIZE; +#endif +#ifdef LIB9P_ERRNO_L_EMULTIHOP + x = LIB9P_ERRNO_L_EMULTIHOP; +#endif +#ifdef LIB9P_ERRNO_L_ENAMETOOLONG + x = LIB9P_ERRNO_L_ENAMETOOLONG; +#endif +#ifdef LIB9P_ERRNO_L_ENAVAIL + x = LIB9P_ERRNO_L_ENAVAIL; +#endif +#ifdef LIB9P_ERRNO_L_ENETDOWN + x = LIB9P_ERRNO_L_ENETDOWN; +#endif +#ifdef LIB9P_ERRNO_L_ENETRESET + x = LIB9P_ERRNO_L_ENETRESET; +#endif +#ifdef LIB9P_ERRNO_L_ENETUNREACH + x = LIB9P_ERRNO_L_ENETUNREACH; +#endif +#ifdef LIB9P_ERRNO_L_ENFILE + x = LIB9P_ERRNO_L_ENFILE; +#endif +#ifdef LIB9P_ERRNO_L_ENOANO + x = LIB9P_ERRNO_L_ENOANO; +#endif +#ifdef LIB9P_ERRNO_L_ENOBUFS + x = LIB9P_ERRNO_L_ENOBUFS; +#endif +#ifdef LIB9P_ERRNO_L_ENOCSI + x = LIB9P_ERRNO_L_ENOCSI; +#endif +#ifdef LIB9P_ERRNO_L_ENODATA + x = LIB9P_ERRNO_L_ENODATA; +#endif +#ifdef LIB9P_ERRNO_L_ENODEV + x = LIB9P_ERRNO_L_ENODEV; +#endif +#ifdef LIB9P_ERRNO_L_ENOENT + x = LIB9P_ERRNO_L_ENOENT; +#endif +#ifdef LIB9P_ERRNO_L_ENOEXEC + x = LIB9P_ERRNO_L_ENOEXEC; +#endif +#ifdef LIB9P_ERRNO_L_ENOKEY + x = LIB9P_ERRNO_L_ENOKEY; +#endif +#ifdef LIB9P_ERRNO_L_ENOLCK + x = LIB9P_ERRNO_L_ENOLCK; +#endif +#ifdef LIB9P_ERRNO_L_ENOLINK + x = LIB9P_ERRNO_L_ENOLINK; +#endif +#ifdef LIB9P_ERRNO_L_ENOMEDIUM + x = LIB9P_ERRNO_L_ENOMEDIUM; +#endif +#ifdef LIB9P_ERRNO_L_ENOMEM + x = LIB9P_ERRNO_L_ENOMEM; +#endif +#ifdef LIB9P_ERRNO_L_ENOMSG + x = LIB9P_ERRNO_L_ENOMSG; +#endif +#ifdef LIB9P_ERRNO_L_ENONET + x = LIB9P_ERRNO_L_ENONET; +#endif +#ifdef LIB9P_ERRNO_L_ENOPKG + x = LIB9P_ERRNO_L_ENOPKG; +#endif +#ifdef LIB9P_ERRNO_L_ENOPROTOOPT + x = LIB9P_ERRNO_L_ENOPROTOOPT; +#endif +#ifdef LIB9P_ERRNO_L_ENOSPC + x = LIB9P_ERRNO_L_ENOSPC; +#endif +#ifdef LIB9P_ERRNO_L_ENOSR + x = LIB9P_ERRNO_L_ENOSR; +#endif +#ifdef LIB9P_ERRNO_L_ENOSTR + x = LIB9P_ERRNO_L_ENOSTR; +#endif +#ifdef LIB9P_ERRNO_L_ENOSYS + x = LIB9P_ERRNO_L_ENOSYS; +#endif +#ifdef LIB9P_ERRNO_L_ENOTBLK + x = LIB9P_ERRNO_L_ENOTBLK; +#endif +#ifdef LIB9P_ERRNO_L_ENOTCONN + x = LIB9P_ERRNO_L_ENOTCONN; +#endif +#ifdef LIB9P_ERRNO_L_ENOTDIR + x = LIB9P_ERRNO_L_ENOTDIR; +#endif +#ifdef LIB9P_ERRNO_L_ENOTEMPTY + x = LIB9P_ERRNO_L_ENOTEMPTY; +#endif +#ifdef LIB9P_ERRNO_L_ENOTNAM + x = LIB9P_ERRNO_L_ENOTNAM; +#endif +#ifdef LIB9P_ERRNO_L_ENOTRECOVERABLE + x = LIB9P_ERRNO_L_ENOTRECOVERABLE; +#endif +#ifdef LIB9P_ERRNO_L_ENOTSOCK + x = LIB9P_ERRNO_L_ENOTSOCK; +#endif +#ifdef LIB9P_ERRNO_L_ENOTTY + x = LIB9P_ERRNO_L_ENOTTY; +#endif +#ifdef LIB9P_ERRNO_L_ENOTUNIQ + x = LIB9P_ERRNO_L_ENOTUNIQ; +#endif +#ifdef LIB9P_ERRNO_L_ENXIO + x = LIB9P_ERRNO_L_ENXIO; +#endif +#ifdef LIB9P_ERRNO_L_EOPNOTSUPP + x = LIB9P_ERRNO_L_EOPNOTSUPP; +#endif +#ifdef LIB9P_ERRNO_L_EOVERFLOW + x = LIB9P_ERRNO_L_EOVERFLOW; +#endif +#ifdef LIB9P_ERRNO_L_EOWNERDEAD + x = LIB9P_ERRNO_L_EOWNERDEAD; +#endif +#ifdef LIB9P_ERRNO_L_EPERM + x = LIB9P_ERRNO_L_EPERM; +#endif +#ifdef LIB9P_ERRNO_L_EPFNOSUPPORT + x = LIB9P_ERRNO_L_EPFNOSUPPORT; +#endif +#ifdef LIB9P_ERRNO_L_EPIPE + x = LIB9P_ERRNO_L_EPIPE; +#endif +#ifdef LIB9P_ERRNO_L_EPROTO + x = LIB9P_ERRNO_L_EPROTO; +#endif +#ifdef LIB9P_ERRNO_L_EPROTONOSUPPORT + x = LIB9P_ERRNO_L_EPROTONOSUPPORT; +#endif +#ifdef LIB9P_ERRNO_L_EPROTOTYPE + x = LIB9P_ERRNO_L_EPROTOTYPE; +#endif +#ifdef LIB9P_ERRNO_L_ERANGE + x = LIB9P_ERRNO_L_ERANGE; +#endif +#ifdef LIB9P_ERRNO_L_EREMCHG + x = LIB9P_ERRNO_L_EREMCHG; +#endif +#ifdef LIB9P_ERRNO_L_EREMOTE + x = LIB9P_ERRNO_L_EREMOTE; +#endif +#ifdef LIB9P_ERRNO_L_EREMOTEIO + x = LIB9P_ERRNO_L_EREMOTEIO; +#endif +#ifdef LIB9P_ERRNO_L_ERESTART + x = LIB9P_ERRNO_L_ERESTART; +#endif +#ifdef LIB9P_ERRNO_L_ERFKILL + x = LIB9P_ERRNO_L_ERFKILL; +#endif +#ifdef LIB9P_ERRNO_L_EROFS + x = LIB9P_ERRNO_L_EROFS; +#endif +#ifdef LIB9P_ERRNO_L_ESHUTDOWN + x = LIB9P_ERRNO_L_ESHUTDOWN; +#endif +#ifdef LIB9P_ERRNO_L_ESOCKTNOSUPPORT + x = LIB9P_ERRNO_L_ESOCKTNOSUPPORT; +#endif +#ifdef LIB9P_ERRNO_L_ESPIPE + x = LIB9P_ERRNO_L_ESPIPE; +#endif +#ifdef LIB9P_ERRNO_L_ESRCH + x = LIB9P_ERRNO_L_ESRCH; +#endif +#ifdef LIB9P_ERRNO_L_ESRMNT + x = LIB9P_ERRNO_L_ESRMNT; +#endif +#ifdef LIB9P_ERRNO_L_ESTALE + x = LIB9P_ERRNO_L_ESTALE; +#endif +#ifdef LIB9P_ERRNO_L_ESTRPIPE + x = LIB9P_ERRNO_L_ESTRPIPE; +#endif +#ifdef LIB9P_ERRNO_L_ETIME + x = LIB9P_ERRNO_L_ETIME; +#endif +#ifdef LIB9P_ERRNO_L_ETIMEDOUT + x = LIB9P_ERRNO_L_ETIMEDOUT; +#endif +#ifdef LIB9P_ERRNO_L_ETOOMANYREFS + x = LIB9P_ERRNO_L_ETOOMANYREFS; +#endif +#ifdef LIB9P_ERRNO_L_ETXTBSY + x = LIB9P_ERRNO_L_ETXTBSY; +#endif +#ifdef LIB9P_ERRNO_L_EUCLEAN + x = LIB9P_ERRNO_L_EUCLEAN; +#endif +#ifdef LIB9P_ERRNO_L_EUNATCH + x = LIB9P_ERRNO_L_EUNATCH; +#endif +#ifdef LIB9P_ERRNO_L_EUSERS + x = LIB9P_ERRNO_L_EUSERS; +#endif +#ifdef LIB9P_ERRNO_L_EXDEV + x = LIB9P_ERRNO_L_EXDEV; +#endif +#ifdef LIB9P_ERRNO_L_EXFULL + x = LIB9P_ERRNO_L_EXFULL; +#endif +#ifdef LIB9P_ERRNO_NOERROR + x = LIB9P_ERRNO_NOERROR; +#endif +#ifdef LIB9P_FID_NOFID + x = LIB9P_FID_NOFID; +#endif +#ifdef LIB9P_GETATTR_ALL + x = LIB9P_GETATTR_ALL; +#endif +#ifdef LIB9P_GETATTR_ATIME + x = LIB9P_GETATTR_ATIME; +#endif +#ifdef LIB9P_GETATTR_BASIC + x = LIB9P_GETATTR_BASIC; +#endif +#ifdef LIB9P_GETATTR_BLOCKS + x = LIB9P_GETATTR_BLOCKS; +#endif +#ifdef LIB9P_GETATTR_BTIME + x = LIB9P_GETATTR_BTIME; +#endif +#ifdef LIB9P_GETATTR_CTIME + x = LIB9P_GETATTR_CTIME; +#endif +#ifdef LIB9P_GETATTR_DATA_VERSION + x = LIB9P_GETATTR_DATA_VERSION; +#endif +#ifdef LIB9P_GETATTR_GEN + x = LIB9P_GETATTR_GEN; +#endif +#ifdef LIB9P_GETATTR_GID + x = LIB9P_GETATTR_GID; +#endif +#ifdef LIB9P_GETATTR_INO + x = LIB9P_GETATTR_INO; +#endif +#ifdef LIB9P_GETATTR_MODE + x = LIB9P_GETATTR_MODE; +#endif +#ifdef LIB9P_GETATTR_MTIME + x = LIB9P_GETATTR_MTIME; +#endif +#ifdef LIB9P_GETATTR_NLINK + x = LIB9P_GETATTR_NLINK; +#endif +#ifdef LIB9P_GETATTR_RDEV + x = LIB9P_GETATTR_RDEV; +#endif +#ifdef LIB9P_GETATTR_SIZE + x = LIB9P_GETATTR_SIZE; +#endif +#ifdef LIB9P_GETATTR_UID + x = LIB9P_GETATTR_UID; +#endif +#ifdef LIB9P_LOCK_FLAGS_BLOCK + x = LIB9P_LOCK_FLAGS_BLOCK; +#endif +#ifdef LIB9P_LOCK_FLAGS_RECLAIM + x = LIB9P_LOCK_FLAGS_RECLAIM; +#endif +#ifdef LIB9P_LOCK_STATUS_BLOCKED + x = LIB9P_LOCK_STATUS_BLOCKED; +#endif +#ifdef LIB9P_LOCK_STATUS_ERROR + x = LIB9P_LOCK_STATUS_ERROR; +#endif +#ifdef LIB9P_LOCK_STATUS_GRACE + x = LIB9P_LOCK_STATUS_GRACE; +#endif +#ifdef LIB9P_LOCK_STATUS_SUCCESS + x = LIB9P_LOCK_STATUS_SUCCESS; +#endif +#ifdef LIB9P_LOCK_TYPE_RDLCK + x = LIB9P_LOCK_TYPE_RDLCK; +#endif +#ifdef LIB9P_LOCK_TYPE_UNLCK + x = LIB9P_LOCK_TYPE_UNLCK; +#endif +#ifdef LIB9P_LOCK_TYPE_WRLCK + x = LIB9P_LOCK_TYPE_WRLCK; +#endif +#ifdef LIB9P_LO_APPEND + x = LIB9P_LO_APPEND; +#endif +#ifdef LIB9P_LO_BSD_FASYNC + x = LIB9P_LO_BSD_FASYNC; +#endif +#ifdef LIB9P_LO_CLOEXEC + x = LIB9P_LO_CLOEXEC; +#endif +#ifdef LIB9P_LO_CREATE + x = LIB9P_LO_CREATE; +#endif +#ifdef LIB9P_LO_DIRECT + x = LIB9P_LO_DIRECT; +#endif +#ifdef LIB9P_LO_DIRECTORY + x = LIB9P_LO_DIRECTORY; +#endif +#ifdef LIB9P_LO_DSYNC + x = LIB9P_LO_DSYNC; +#endif +#ifdef LIB9P_LO_EXCL + x = LIB9P_LO_EXCL; +#endif +#ifdef LIB9P_LO_FLAG_MASK + x = LIB9P_LO_FLAG_MASK; +#endif +#ifdef LIB9P_LO_LARGEFILE + x = LIB9P_LO_LARGEFILE; +#endif +#ifdef LIB9P_LO_MODE_MASK + x = LIB9P_LO_MODE_MASK; +#endif +#ifdef LIB9P_LO_MODE_NOACCESS + x = LIB9P_LO_MODE_NOACCESS; +#endif +#ifdef LIB9P_LO_MODE_RDONLY + x = LIB9P_LO_MODE_RDONLY; +#endif +#ifdef LIB9P_LO_MODE_RDWR + x = LIB9P_LO_MODE_RDWR; +#endif +#ifdef LIB9P_LO_MODE_WRONLY + x = LIB9P_LO_MODE_WRONLY; +#endif +#ifdef LIB9P_LO_NOATIME + x = LIB9P_LO_NOATIME; +#endif +#ifdef LIB9P_LO_NOCTTY + x = LIB9P_LO_NOCTTY; +#endif +#ifdef LIB9P_LO_NOFOLLOW + x = LIB9P_LO_NOFOLLOW; +#endif +#ifdef LIB9P_LO_NONBLOCK + x = LIB9P_LO_NONBLOCK; +#endif +#ifdef LIB9P_LO_SYNC + x = LIB9P_LO_SYNC; +#endif +#ifdef LIB9P_LO_TRUNC + x = LIB9P_LO_TRUNC; +#endif +#ifdef LIB9P_MODE_FMT_BLOCK_DEV + x = LIB9P_MODE_FMT_BLOCK_DEV; +#endif +#ifdef LIB9P_MODE_FMT_CHAR_DEV + x = LIB9P_MODE_FMT_CHAR_DEV; +#endif +#ifdef LIB9P_MODE_FMT_DIRECTORY + x = LIB9P_MODE_FMT_DIRECTORY; +#endif +#ifdef LIB9P_MODE_FMT_MASK + x = LIB9P_MODE_FMT_MASK; +#endif +#ifdef LIB9P_MODE_FMT_PIPE + x = LIB9P_MODE_FMT_PIPE; +#endif +#ifdef LIB9P_MODE_FMT_REGULAR + x = LIB9P_MODE_FMT_REGULAR; +#endif +#ifdef LIB9P_MODE_FMT_SOCKET + x = LIB9P_MODE_FMT_SOCKET; +#endif +#ifdef LIB9P_MODE_FMT_SYMLINK + x = LIB9P_MODE_FMT_SYMLINK; +#endif +#ifdef LIB9P_MODE_PERM_GROUP_R + x = LIB9P_MODE_PERM_GROUP_R; +#endif +#ifdef LIB9P_MODE_PERM_GROUP_W + x = LIB9P_MODE_PERM_GROUP_W; +#endif +#ifdef LIB9P_MODE_PERM_GROUP_X + x = LIB9P_MODE_PERM_GROUP_X; +#endif +#ifdef LIB9P_MODE_PERM_MASK + x = LIB9P_MODE_PERM_MASK; +#endif +#ifdef LIB9P_MODE_PERM_OTHER_R + x = LIB9P_MODE_PERM_OTHER_R; +#endif +#ifdef LIB9P_MODE_PERM_OTHER_W + x = LIB9P_MODE_PERM_OTHER_W; +#endif +#ifdef LIB9P_MODE_PERM_OTHER_X + x = LIB9P_MODE_PERM_OTHER_X; +#endif +#ifdef LIB9P_MODE_PERM_OWNER_R + x = LIB9P_MODE_PERM_OWNER_R; +#endif +#ifdef LIB9P_MODE_PERM_OWNER_W + x = LIB9P_MODE_PERM_OWNER_W; +#endif +#ifdef LIB9P_MODE_PERM_OWNER_X + x = LIB9P_MODE_PERM_OWNER_X; +#endif +#ifdef LIB9P_MODE_PERM_SETGROUP + x = LIB9P_MODE_PERM_SETGROUP; +#endif +#ifdef LIB9P_MODE_PERM_SETUSER + x = LIB9P_MODE_PERM_SETUSER; +#endif +#ifdef LIB9P_MODE_PERM_STICKY + x = LIB9P_MODE_PERM_STICKY; +#endif +#ifdef LIB9P_NUID_NONUID + x = LIB9P_NUID_NONUID; +#endif +#ifdef LIB9P_O_FLAG_MASK + x = LIB9P_O_FLAG_MASK; +#endif +#ifdef LIB9P_O_MODE_EXEC + x = LIB9P_O_MODE_EXEC; +#endif +#ifdef LIB9P_O_MODE_MASK + x = LIB9P_O_MODE_MASK; +#endif +#ifdef LIB9P_O_MODE_RDWR + x = LIB9P_O_MODE_RDWR; +#endif +#ifdef LIB9P_O_MODE_READ + x = LIB9P_O_MODE_READ; +#endif +#ifdef LIB9P_O_MODE_WRITE + x = LIB9P_O_MODE_WRITE; +#endif +#ifdef LIB9P_O_RCLOSE + x = LIB9P_O_RCLOSE; +#endif +#ifdef LIB9P_O_TRUNC + x = LIB9P_O_TRUNC; +#endif +#ifdef LIB9P_QT_APPEND + x = LIB9P_QT_APPEND; +#endif +#ifdef LIB9P_QT_AUTH + x = LIB9P_QT_AUTH; +#endif +#ifdef LIB9P_QT_DIR + x = LIB9P_QT_DIR; +#endif +#ifdef LIB9P_QT_EXCL + x = LIB9P_QT_EXCL; +#endif +#ifdef LIB9P_QT_FILE + x = LIB9P_QT_FILE; +#endif +#ifdef LIB9P_QT_SYMLINK + x = LIB9P_QT_SYMLINK; +#endif +#ifdef LIB9P_QT_TMP + x = LIB9P_QT_TMP; +#endif +#ifdef LIB9P_RMSG_MAX_COPY + x = LIB9P_RMSG_MAX_COPY; +#endif +#ifdef LIB9P_RMSG_MAX_IOV + x = LIB9P_RMSG_MAX_IOV; +#endif +#ifdef LIB9P_SETATTR_ATIME + x = LIB9P_SETATTR_ATIME; +#endif +#ifdef LIB9P_SETATTR_ATIME_SET + x = LIB9P_SETATTR_ATIME_SET; +#endif +#ifdef LIB9P_SETATTR_CTIME + x = LIB9P_SETATTR_CTIME; +#endif +#ifdef LIB9P_SETATTR_GID + x = LIB9P_SETATTR_GID; +#endif +#ifdef LIB9P_SETATTR_MODE + x = LIB9P_SETATTR_MODE; +#endif +#ifdef LIB9P_SETATTR_MTIME + x = LIB9P_SETATTR_MTIME; +#endif +#ifdef LIB9P_SETATTR_MTIME_SET + x = LIB9P_SETATTR_MTIME_SET; +#endif +#ifdef LIB9P_SETATTR_SIZE + x = LIB9P_SETATTR_SIZE; +#endif +#ifdef LIB9P_SETATTR_UID + x = LIB9P_SETATTR_UID; +#endif +#ifdef LIB9P_SUPER_MAGIC_V9FS_MAGIC + x = LIB9P_SUPER_MAGIC_V9FS_MAGIC; +#endif +#ifdef LIB9P_TAG_NOTAG + x = LIB9P_TAG_NOTAG; +#endif +#ifdef LIB9P_TMSG_MAX_COPY + x = LIB9P_TMSG_MAX_COPY; +#endif +#ifdef LIB9P_TMSG_MAX_IOV + x = LIB9P_TMSG_MAX_IOV; +#endif +#ifdef _LIB9P_DM_PLAN9_MOUNT + x = _LIB9P_DM_PLAN9_MOUNT; +#endif +#ifdef _LIB9P_DM_UNUSED_10 + x = _LIB9P_DM_UNUSED_10; +#endif +#ifdef _LIB9P_DM_UNUSED_11 + x = _LIB9P_DM_UNUSED_11; +#endif +#ifdef _LIB9P_DM_UNUSED_12 + x = _LIB9P_DM_UNUSED_12; +#endif +#ifdef _LIB9P_DM_UNUSED_13 + x = _LIB9P_DM_UNUSED_13; +#endif +#ifdef _LIB9P_DM_UNUSED_14 + x = _LIB9P_DM_UNUSED_14; +#endif +#ifdef _LIB9P_DM_UNUSED_15 + x = _LIB9P_DM_UNUSED_15; +#endif +#ifdef _LIB9P_DM_UNUSED_16 + x = _LIB9P_DM_UNUSED_16; +#endif +#ifdef _LIB9P_DM_UNUSED_17 + x = _LIB9P_DM_UNUSED_17; +#endif +#ifdef _LIB9P_DM_UNUSED_22 + x = _LIB9P_DM_UNUSED_22; +#endif +#ifdef _LIB9P_DM_UNUSED_24 + x = _LIB9P_DM_UNUSED_24; +#endif +#ifdef _LIB9P_DM_UNUSED_25 + x = _LIB9P_DM_UNUSED_25; +#endif +#ifdef _LIB9P_DM_UNUSED_9 + x = _LIB9P_DM_UNUSED_9; +#endif +#ifdef _LIB9P_DT_WHITEOUT + x = _LIB9P_DT_WHITEOUT; +#endif +#ifdef _LIB9P_ENABLE_stat + x = _LIB9P_ENABLE_stat; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_14 + x = _LIB9P_GETATTR_UNUSED_14; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_15 + x = _LIB9P_GETATTR_UNUSED_15; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_16 + x = _LIB9P_GETATTR_UNUSED_16; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_17 + x = _LIB9P_GETATTR_UNUSED_17; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_18 + x = _LIB9P_GETATTR_UNUSED_18; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_19 + x = _LIB9P_GETATTR_UNUSED_19; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_20 + x = _LIB9P_GETATTR_UNUSED_20; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_21 + x = _LIB9P_GETATTR_UNUSED_21; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_22 + x = _LIB9P_GETATTR_UNUSED_22; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_23 + x = _LIB9P_GETATTR_UNUSED_23; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_24 + x = _LIB9P_GETATTR_UNUSED_24; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_25 + x = _LIB9P_GETATTR_UNUSED_25; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_26 + x = _LIB9P_GETATTR_UNUSED_26; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_27 + x = _LIB9P_GETATTR_UNUSED_27; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_28 + x = _LIB9P_GETATTR_UNUSED_28; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_29 + x = _LIB9P_GETATTR_UNUSED_29; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_30 + x = _LIB9P_GETATTR_UNUSED_30; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_31 + x = _LIB9P_GETATTR_UNUSED_31; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_32 + x = _LIB9P_GETATTR_UNUSED_32; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_33 + x = _LIB9P_GETATTR_UNUSED_33; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_34 + x = _LIB9P_GETATTR_UNUSED_34; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_35 + x = _LIB9P_GETATTR_UNUSED_35; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_36 + x = _LIB9P_GETATTR_UNUSED_36; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_37 + x = _LIB9P_GETATTR_UNUSED_37; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_38 + x = _LIB9P_GETATTR_UNUSED_38; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_39 + x = _LIB9P_GETATTR_UNUSED_39; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_40 + x = _LIB9P_GETATTR_UNUSED_40; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_41 + x = _LIB9P_GETATTR_UNUSED_41; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_42 + x = _LIB9P_GETATTR_UNUSED_42; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_43 + x = _LIB9P_GETATTR_UNUSED_43; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_44 + x = _LIB9P_GETATTR_UNUSED_44; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_45 + x = _LIB9P_GETATTR_UNUSED_45; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_46 + x = _LIB9P_GETATTR_UNUSED_46; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_47 + x = _LIB9P_GETATTR_UNUSED_47; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_48 + x = _LIB9P_GETATTR_UNUSED_48; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_49 + x = _LIB9P_GETATTR_UNUSED_49; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_50 + x = _LIB9P_GETATTR_UNUSED_50; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_51 + x = _LIB9P_GETATTR_UNUSED_51; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_52 + x = _LIB9P_GETATTR_UNUSED_52; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_53 + x = _LIB9P_GETATTR_UNUSED_53; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_54 + x = _LIB9P_GETATTR_UNUSED_54; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_55 + x = _LIB9P_GETATTR_UNUSED_55; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_56 + x = _LIB9P_GETATTR_UNUSED_56; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_57 + x = _LIB9P_GETATTR_UNUSED_57; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_58 + x = _LIB9P_GETATTR_UNUSED_58; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_59 + x = _LIB9P_GETATTR_UNUSED_59; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_60 + x = _LIB9P_GETATTR_UNUSED_60; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_61 + x = _LIB9P_GETATTR_UNUSED_61; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_62 + x = _LIB9P_GETATTR_UNUSED_62; +#endif +#ifdef _LIB9P_GETATTR_UNUSED_63 + x = _LIB9P_GETATTR_UNUSED_63; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_10 + x = _LIB9P_LOCK_FLAGS_UNUSED_10; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_11 + x = _LIB9P_LOCK_FLAGS_UNUSED_11; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_12 + x = _LIB9P_LOCK_FLAGS_UNUSED_12; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_13 + x = _LIB9P_LOCK_FLAGS_UNUSED_13; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_14 + x = _LIB9P_LOCK_FLAGS_UNUSED_14; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_15 + x = _LIB9P_LOCK_FLAGS_UNUSED_15; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_16 + x = _LIB9P_LOCK_FLAGS_UNUSED_16; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_17 + x = _LIB9P_LOCK_FLAGS_UNUSED_17; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_18 + x = _LIB9P_LOCK_FLAGS_UNUSED_18; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_19 + x = _LIB9P_LOCK_FLAGS_UNUSED_19; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_2 + x = _LIB9P_LOCK_FLAGS_UNUSED_2; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_20 + x = _LIB9P_LOCK_FLAGS_UNUSED_20; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_21 + x = _LIB9P_LOCK_FLAGS_UNUSED_21; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_22 + x = _LIB9P_LOCK_FLAGS_UNUSED_22; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_23 + x = _LIB9P_LOCK_FLAGS_UNUSED_23; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_24 + x = _LIB9P_LOCK_FLAGS_UNUSED_24; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_25 + x = _LIB9P_LOCK_FLAGS_UNUSED_25; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_26 + x = _LIB9P_LOCK_FLAGS_UNUSED_26; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_27 + x = _LIB9P_LOCK_FLAGS_UNUSED_27; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_28 + x = _LIB9P_LOCK_FLAGS_UNUSED_28; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_29 + x = _LIB9P_LOCK_FLAGS_UNUSED_29; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_3 + x = _LIB9P_LOCK_FLAGS_UNUSED_3; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_30 + x = _LIB9P_LOCK_FLAGS_UNUSED_30; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_31 + x = _LIB9P_LOCK_FLAGS_UNUSED_31; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_4 + x = _LIB9P_LOCK_FLAGS_UNUSED_4; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_5 + x = _LIB9P_LOCK_FLAGS_UNUSED_5; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_6 + x = _LIB9P_LOCK_FLAGS_UNUSED_6; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_7 + x = _LIB9P_LOCK_FLAGS_UNUSED_7; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_8 + x = _LIB9P_LOCK_FLAGS_UNUSED_8; +#endif +#ifdef _LIB9P_LOCK_FLAGS_UNUSED_9 + x = _LIB9P_LOCK_FLAGS_UNUSED_9; +#endif +#ifdef _LIB9P_LO_UNUSED_2 + x = _LIB9P_LO_UNUSED_2; +#endif +#ifdef _LIB9P_LO_UNUSED_21 + x = _LIB9P_LO_UNUSED_21; +#endif +#ifdef _LIB9P_LO_UNUSED_22 + x = _LIB9P_LO_UNUSED_22; +#endif +#ifdef _LIB9P_LO_UNUSED_23 + x = _LIB9P_LO_UNUSED_23; +#endif +#ifdef _LIB9P_LO_UNUSED_24 + x = _LIB9P_LO_UNUSED_24; +#endif +#ifdef _LIB9P_LO_UNUSED_25 + x = _LIB9P_LO_UNUSED_25; +#endif +#ifdef _LIB9P_LO_UNUSED_26 + x = _LIB9P_LO_UNUSED_26; +#endif +#ifdef _LIB9P_LO_UNUSED_27 + x = _LIB9P_LO_UNUSED_27; +#endif +#ifdef _LIB9P_LO_UNUSED_28 + x = _LIB9P_LO_UNUSED_28; +#endif +#ifdef _LIB9P_LO_UNUSED_29 + x = _LIB9P_LO_UNUSED_29; +#endif +#ifdef _LIB9P_LO_UNUSED_3 + x = _LIB9P_LO_UNUSED_3; +#endif +#ifdef _LIB9P_LO_UNUSED_30 + x = _LIB9P_LO_UNUSED_30; +#endif +#ifdef _LIB9P_LO_UNUSED_31 + x = _LIB9P_LO_UNUSED_31; +#endif +#ifdef _LIB9P_LO_UNUSED_4 + x = _LIB9P_LO_UNUSED_4; +#endif +#ifdef _LIB9P_LO_UNUSED_5 + x = _LIB9P_LO_UNUSED_5; +#endif +#ifdef _LIB9P_MODE_UNUSED_16 + x = _LIB9P_MODE_UNUSED_16; +#endif +#ifdef _LIB9P_MODE_UNUSED_17 + x = _LIB9P_MODE_UNUSED_17; +#endif +#ifdef _LIB9P_MODE_UNUSED_18 + x = _LIB9P_MODE_UNUSED_18; +#endif +#ifdef _LIB9P_MODE_UNUSED_19 + x = _LIB9P_MODE_UNUSED_19; +#endif +#ifdef _LIB9P_MODE_UNUSED_20 + x = _LIB9P_MODE_UNUSED_20; +#endif +#ifdef _LIB9P_MODE_UNUSED_21 + x = _LIB9P_MODE_UNUSED_21; +#endif +#ifdef _LIB9P_MODE_UNUSED_22 + x = _LIB9P_MODE_UNUSED_22; +#endif +#ifdef _LIB9P_MODE_UNUSED_23 + x = _LIB9P_MODE_UNUSED_23; +#endif +#ifdef _LIB9P_MODE_UNUSED_24 + x = _LIB9P_MODE_UNUSED_24; +#endif +#ifdef _LIB9P_MODE_UNUSED_25 + x = _LIB9P_MODE_UNUSED_25; +#endif +#ifdef _LIB9P_MODE_UNUSED_26 + x = _LIB9P_MODE_UNUSED_26; +#endif +#ifdef _LIB9P_MODE_UNUSED_27 + x = _LIB9P_MODE_UNUSED_27; +#endif +#ifdef _LIB9P_MODE_UNUSED_28 + x = _LIB9P_MODE_UNUSED_28; +#endif +#ifdef _LIB9P_MODE_UNUSED_29 + x = _LIB9P_MODE_UNUSED_29; +#endif +#ifdef _LIB9P_MODE_UNUSED_30 + x = _LIB9P_MODE_UNUSED_30; +#endif +#ifdef _LIB9P_MODE_UNUSED_31 + x = _LIB9P_MODE_UNUSED_31; +#endif +#ifdef _LIB9P_O_RESERVED_CEXEC + x = _LIB9P_O_RESERVED_CEXEC; +#endif +#ifdef _LIB9P_O_UNUSED_2 + x = _LIB9P_O_UNUSED_2; +#endif +#ifdef _LIB9P_O_UNUSED_3 + x = _LIB9P_O_UNUSED_3; +#endif +#ifdef _LIB9P_O_UNUSED_7 + x = _LIB9P_O_UNUSED_7; +#endif +#ifdef _LIB9P_QT_PLAN9_MOUNT + x = _LIB9P_QT_PLAN9_MOUNT; +#endif +#ifdef _LIB9P_QT_UNUSED_0 + x = _LIB9P_QT_UNUSED_0; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_10 + x = _LIB9P_SETATTR_UNUSED_10; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_11 + x = _LIB9P_SETATTR_UNUSED_11; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_12 + x = _LIB9P_SETATTR_UNUSED_12; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_13 + x = _LIB9P_SETATTR_UNUSED_13; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_14 + x = _LIB9P_SETATTR_UNUSED_14; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_15 + x = _LIB9P_SETATTR_UNUSED_15; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_16 + x = _LIB9P_SETATTR_UNUSED_16; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_17 + x = _LIB9P_SETATTR_UNUSED_17; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_18 + x = _LIB9P_SETATTR_UNUSED_18; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_19 + x = _LIB9P_SETATTR_UNUSED_19; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_20 + x = _LIB9P_SETATTR_UNUSED_20; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_21 + x = _LIB9P_SETATTR_UNUSED_21; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_22 + x = _LIB9P_SETATTR_UNUSED_22; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_23 + x = _LIB9P_SETATTR_UNUSED_23; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_24 + x = _LIB9P_SETATTR_UNUSED_24; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_25 + x = _LIB9P_SETATTR_UNUSED_25; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_26 + x = _LIB9P_SETATTR_UNUSED_26; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_27 + x = _LIB9P_SETATTR_UNUSED_27; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_28 + x = _LIB9P_SETATTR_UNUSED_28; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_29 + x = _LIB9P_SETATTR_UNUSED_29; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_30 + x = _LIB9P_SETATTR_UNUSED_30; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_31 + x = _LIB9P_SETATTR_UNUSED_31; +#endif +#ifdef _LIB9P_SETATTR_UNUSED_9 + x = _LIB9P_SETATTR_UNUSED_9; +#endif + return 0; } diff --git a/lib9p/tests/test_compile.c.gen b/lib9p/tests/test_compile.c.gen index 47046b3..ef2aee6 100755 --- a/lib9p/tests/test_compile.c.gen +++ b/lib9p/tests/test_compile.c.gen @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/env bash # lib9p/tests/test_compile.c.gen - Generate code to make sure all generated macros work # # Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> @@ -10,10 +10,10 @@ outfile=$2 { echo "/* ${outfile} - Generated by $0. DO NOT EDIT! */" echo - echo "#include <lib9p/9p.h>" + echo "#include <lib9p/core.h>" echo 'int main(void) {' - echo ' [[gnu::unused]] uint64_t x;' - sed -nE 's/^\s*#\s*define\s*(\S[^ (]*)\s.*/ x = \1;/p' <"$generated_h" - echo ' return 0;' + echo $'\t[[maybe_unused]] uint64_t x;' + <"$generated_h" sed -nE 's/^\s*#\s*define\s*(\S[^ (]*)\s.*/\1/p' | LC_COLLATE=C sort -u | sed $'s/.*/#ifdef &\\n\tx = &;\\n#endif/' + echo $'\treturn 0;' echo '}' } >"$outfile" diff --git a/lib9p/tests/test_compile_config/config.h b/lib9p/tests/test_compile_config/config.h index 38ab0c0..cb3709e 100644 --- a/lib9p/tests/test_compile_config/config.h +++ b/lib9p/tests/test_compile_config/config.h @@ -9,20 +9,13 @@ /* 9P *************************************************************************/ -#define CONFIG_9P_MAX_MSG_SIZE ((4*1024)+24) -#define CONFIG_9P_MAX_HOSTMSG_SIZE CONFIG_9P_MAX_MSG_SIZE+16 -#define CONFIG_9P_MAX_ERR_SIZE 128 -#define CONFIG_9P_MAX_9P2000_e_WELEM 16 +#define CONFIG_9P_MAX_9P2000_e_WELEM 16 -#define CONFIG_9P_SRV_MAX_FIDS 16 -#define CONFIG_9P_SRV_MAX_REQS 2 -#define CONFIG_9P_SRV_MAX_DEPTH 3 +/* 9P_SRV *********************************************************************/ -#define CONFIG_9P_ENABLE_9P2000 1 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_e 1 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_L 1 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_p9p 1 /* bool */ +#define CONFIG_9P_SRV_MAX_ERR_SIZE 128 +#define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) +#define CONFIG_9P_SRV_MAX_HOSTMSG_SIZE CONFIG_9P_SRV_MAX_MSG_SIZE+16 /* COROUTINE ******************************************************************/ @@ -33,6 +26,6 @@ #define CONFIG_COROUTINE_DEBUG 0 /* bool */ #define CONFIG_COROUTINE_VALGRIND 1 /* bool */ #define CONFIG_COROUTINE_GDB 1 /* bool */ -#define CONFIG_COROUTINE_NUM 2 +#define CONFIG_COROUTINE_NUM 8 #endif /* _CONFIG_H_ */ diff --git a/lib9p/tests/test_server/CMakeLists.txt b/lib9p/tests/test_server/CMakeLists.txt index 5313917..c61d344 100644 --- a/lib9p/tests/test_server/CMakeLists.txt +++ b/lib9p/tests/test_server/CMakeLists.txt @@ -9,6 +9,9 @@ if (PICO_PLATFORM STREQUAL "host") add_library(test_server_objs OBJECT main.c + fs_flush.c + fs_shutdown.c + fs_whoami.c ) target_include_directories(test_server_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config) target_include_directories(test_server_objs PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) @@ -16,7 +19,6 @@ target_link_libraries(test_server_objs libcr libcr_ipc libmisc - lib9p lib9p_util libhw_cr ) diff --git a/lib9p/tests/test_server/config/config.h b/lib9p/tests/test_server/config/config.h index afe6dc0..a657f60 100644 --- a/lib9p/tests/test_server/config/config.h +++ b/lib9p/tests/test_server/config/config.h @@ -7,11 +7,21 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define _CONFIG_9P_NUM_SOCKS 8 -#define CONFIG_SRV9P_NUM_CONNS _CONFIG_9P_NUM_SOCKS +#define _CONFIG_9P_MAX_CONNS 8 +#define _CONFIG_9P_MAX_REQS (2*_CONFIG_9P_MAX_CONNS) /* 9P *************************************************************************/ +#define CONFIG_9P_ENABLE_9P2000 1 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_e 0 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_L 0 /* bool */ +#define CONFIG_9P_ENABLE_9P2000_p9p 0 /* bool */ + +/* 9P_SRV *********************************************************************/ + +#define CONFIG_9P_SRV_DEBUG 1 /* bool */ + /** * This max-msg-size is sized so that a Twrite message can return * 8KiB of data. @@ -29,22 +39,14 @@ * negotiated. In Plan 9 1e it was (8*1024)+128, and was bumped to * (8*1024)+160 in 2e and 3e. */ -#define CONFIG_9P_MAX_MSG_SIZE ((4*1024)+24) +#define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) +#define CONFIG_9P_SRV_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ /** * Maximum host-data-structure size. A message may be larger in * unmarshaled-host-structures than marshaled-net-bytes due to (1) * struct padding, (2) array pointers. */ -#define CONFIG_9P_MAX_HOSTMSG_SIZE CONFIG_9P_MAX_MSG_SIZE+16 -#define CONFIG_9P_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ -#define CONFIG_9P_SRV_MAX_FIDS 16 -#define CONFIG_9P_SRV_MAX_REQS 2 -#define CONFIG_9P_SRV_MAX_DEPTH 3 -#define CONFIG_9P_ENABLE_9P2000 1 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_e 0 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_L 0 /* bool */ -#define CONFIG_9P_ENABLE_9P2000_p9p 0 /* bool */ +#define CONFIG_9P_SRV_MAX_HOSTMSG_SIZE CONFIG_9P_SRV_MAX_MSG_SIZE+16 /* COROUTINE ******************************************************************/ @@ -55,10 +57,10 @@ #define CONFIG_COROUTINE_DEBUG 0 /* bool */ #define CONFIG_COROUTINE_VALGRIND 1 /* bool */ #define CONFIG_COROUTINE_GDB 1 /* bool */ -#define CONFIG_COROUTINE_NUM ( \ - 1 /* usb_common */ + \ - 1 /* usb_keyboard */ + \ - CONFIG_SRV9P_NUM_CONNS /* accept+read */ + \ - (CONFIG_9P_SRV_MAX_REQS*CONFIG_SRV9P_NUM_CONNS) /* work+write */ ) +#define CONFIG_COROUTINE_NUM ( \ + 1 /* usb_common */ + \ + 1 /* usb_keyboard */ + \ + _CONFIG_9P_MAX_CONNS /* accept+read */ + \ + _CONFIG_9P_MAX_REQS /* work+write */ ) #endif /* _CONFIG_H_ */ diff --git a/lib9p/tests/test_server/fs_flush.c b/lib9p/tests/test_server/fs_flush.c new file mode 100644 index 0000000..63a52af --- /dev/null +++ b/lib9p/tests/test_server/fs_flush.c @@ -0,0 +1,129 @@ +/* lib9p/tests/test_server/fs_flush.c - flush-* API endpoints + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libmisc/alloc.h> + +#define IMPLEMENTATION_FOR_LIB9P_SRV_H YES /* for ctx->flush_ch */ +#include "fs_flush.h" + +LO_IMPLEMENTATION_C(lib9p_srv_file, struct flush_file, flush_file, static); + +struct flush_fio { + struct flush_file *parent; +}; +LO_IMPLEMENTATION_H(lib9p_srv_fio, struct flush_fio, flush_fio); +LO_IMPLEMENTATION_C(lib9p_srv_fio, struct flush_fio, flush_fio, static); + +/* srv_file *******************************************************************/ + +static void flush_file_free(struct flush_file *self) { + assert(self); +} +static struct lib9p_qid flush_file_qid(struct flush_file *self) { + assert(self); + return (struct lib9p_qid){ + .type = LIB9P_QT_FILE, + .vers = 1, + .path = self->pathnum, + }; +} + +static lib9p_srv_stat_or_error flush_file_stat(struct flush_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ + .qid = flush_file_qid(self), + .mode = 0444, + .atime_sec = UTIL9P_ATIME, + .mtime_sec = UTIL9P_MTIME, + .size = 6, + .name = lib9p_str(self->name), + .owner_uid = { .name = lib9p_str("root"), .num = 0 }, + .owner_gid = { .name = lib9p_str("root"), .num = 0 }, + .last_modifier_uid = { .name = lib9p_str("root"), .num = 0 }, + .extension = lib9p_str(NULL), + })); +} +static error flush_file_wstat(struct flush_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { + assert(self); + assert(ctx); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); +} +static error flush_file_remove(struct flush_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + return error_new(E_POSIX_EROFS, "cannot remove API file"); +} + +LIB9P_SRV_NOTDIR(struct flush_file, flush_file); + +static lib9p_srv_fio_or_error flush_file_fopen(struct flush_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { + assert(self); + assert(ctx); + + struct flush_fio *ret = heap_alloc(1, struct flush_fio); + ret->parent = self; + + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); +} + +/* srv_fio ********************************************************************/ + +static void flush_fio_iofree(struct flush_fio *self) { + assert(self); + free(self); +} + +static struct lib9p_qid flush_fio_qid(struct flush_fio *self) { + assert(self); + return flush_file_qid(self->parent); +} + +static uint32_t flush_fio_iounit(struct flush_fio *self) { + assert(self); + return 0; +} + +static uint32_t_or_error flush_fio_pwrite(struct flush_fio *LM_UNUSED(self), + struct lib9p_srv_ctx *LM_UNUSED(ctx), + void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(offset)) { + assert_notreached("not writable"); +} + +static iovec_or_error flush_fio_pread(struct flush_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t LM_UNUSED(byte_offset)) { + assert(self); + assert(ctx); + + /* Wait for first Tflush */ + while (!lib9p_srv_flush_requested(ctx)) + cr_yield(); + + /* Wait for the specified number of Tflush (may be higher *or* + * lower than 1; lower would mean that the first Tflush needs + * to be flushed itself). */ + while (cr_chan_num_waiters(&ctx->flush_ch) != self->parent->flush_cnt) + cr_yield(); + + /* Yield one more time, just because. */ + cr_yield(); + + /* Return */ + switch (self->parent->flush_behavior) { + case FLUSH_READ: + return ERROR_NEW_VAL(iovec, ((struct iovec){ + .iov_base = "Sloth\n", + .iov_len = 6 < byte_count ? 6 : byte_count, + })); + case FLUSH_ERROR: + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EAGAIN, "request canceled by flush")); + case FLUSH_SILENT: + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_ECANCELED, "request canceled by flush")); + default: + assert_notreached("invalid flush_behavior"); + } +} diff --git a/lib9p/tests/test_server/fs_flush.h b/lib9p/tests/test_server/fs_flush.h new file mode 100644 index 0000000..023434b --- /dev/null +++ b/lib9p/tests/test_server/fs_flush.h @@ -0,0 +1,26 @@ +/* lib9p/tests/test_server/fs_flush.h - flush-* API endpoints + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_TESTS_TEST_SERVER_FS_FLUSH_H_ +#define _LIB9P_TESTS_TEST_SERVER_FS_FLUSH_H_ + +#include <libhw/host_net.h> +#include <util9p/static.h> + +struct flush_file { + char *name; + uint64_t pathnum; + + unsigned int flush_cnt; + enum { + FLUSH_READ, + FLUSH_ERROR, + FLUSH_SILENT, + } flush_behavior; +}; +LO_IMPLEMENTATION_H(lib9p_srv_file, struct flush_file, flush_file); + +#endif /* _LIB9P_TESTS_TEST_SERVER_FS_FLUSH_H_ */ diff --git a/lib9p/tests/test_server/fs_shutdown.c b/lib9p/tests/test_server/fs_shutdown.c new file mode 100644 index 0000000..079442e --- /dev/null +++ b/lib9p/tests/test_server/fs_shutdown.c @@ -0,0 +1,103 @@ +/* lib9p/tests/test_server/fs_shutdown.c - /shutdown API endpoint + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libmisc/alloc.h> + +#include "fs_shutdown.h" + +LO_IMPLEMENTATION_C(lib9p_srv_file, struct shutdown_file, shutdown_file, static); + +struct shutdown_fio { + struct shutdown_file *parent; +}; +LO_IMPLEMENTATION_H(lib9p_srv_fio, struct shutdown_fio, shutdown_fio); +LO_IMPLEMENTATION_C(lib9p_srv_fio, struct shutdown_fio, shutdown_fio, static); + +/* srv_file *******************************************************************/ + +static void shutdown_file_free(struct shutdown_file *self) { + assert(self); +} +static struct lib9p_qid shutdown_file_qid(struct shutdown_file *self) { + assert(self); + return (struct lib9p_qid){ + .type = LIB9P_QT_FILE | LIB9P_QT_APPEND, + .vers = 1, + .path = self->pathnum, + }; +} + +static lib9p_srv_stat_or_error shutdown_file_stat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ + .qid = shutdown_file_qid(self), + .mode = 0222 | LIB9P_DM_APPEND, + .atime_sec = UTIL9P_ATIME, + .mtime_sec = UTIL9P_MTIME, + .size = 0, + .name = lib9p_str(self->name), + .owner_uid = { .name=lib9p_str("root"), .num=0 }, + .owner_gid = { .name=lib9p_str("root"), .num=0 }, + .last_modifier_uid = { .name=lib9p_str("root"), .num=0 }, + .extension = lib9p_str(NULL), + })); +} +static error shutdown_file_wstat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { + assert(self); + assert(ctx); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); +} +static error shutdown_file_remove(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + return error_new(E_POSIX_EROFS, "cannot remove API file"); +} + +LIB9P_SRV_NOTDIR(struct shutdown_file, shutdown_file); + +static lib9p_srv_fio_or_error shutdown_file_fopen(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { + assert(self); + assert(ctx); + + struct shutdown_fio *ret = heap_alloc(1, struct shutdown_fio); + ret->parent = self; + + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); +} + +/* srv_fio ********************************************************************/ + +static void shutdown_fio_iofree(struct shutdown_fio *self) { + assert(self); + free(self); +} + +static struct lib9p_qid shutdown_fio_qid(struct shutdown_fio *self) { + assert(self); + return shutdown_file_qid(self->parent); +} + +static uint32_t shutdown_fio_iounit(struct shutdown_fio *self) { + assert(self); + return 0; +} + +static uint32_t_or_error shutdown_fio_pwrite(struct shutdown_fio *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t offset) { + assert(self); + assert(ctx); + assert(buf); + assert(offset == 0); + if (byte_count == 0) + return ERROR_NEW_VAL(uint32_t, 0); + for (size_t i = 0; i < self->parent->nlisteners; i++) + LO_CALL(LO_BOX(net_stream_listener, &self->parent->listeners[i]), close); + return ERROR_NEW_VAL(uint32_t, byte_count); +} +static iovec_or_error shutdown_fio_pread(struct shutdown_fio *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), + uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset)) { + assert_notreached("not readable"); +} diff --git a/lib9p/tests/test_server/fs_shutdown.h b/lib9p/tests/test_server/fs_shutdown.h new file mode 100644 index 0000000..7b8d327 --- /dev/null +++ b/lib9p/tests/test_server/fs_shutdown.h @@ -0,0 +1,22 @@ +/* lib9p/tests/test_server/fs_shutdown.h - /shutdown API endpoint + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_TESTS_TEST_SERVER_FS_SHUTDOWN_H_ +#define _LIB9P_TESTS_TEST_SERVER_FS_SHUTDOWN_H_ + +#include <libhw/host_net.h> +#include <util9p/static.h> + +struct shutdown_file { + char *name; + uint64_t pathnum; + + struct hostnet_tcp_listener *listeners; + size_t nlisteners; +}; +LO_IMPLEMENTATION_H(lib9p_srv_file, struct shutdown_file, shutdown_file); + +#endif /* _LIB9P_TESTS_TEST_SERVER_FS_SHUTDOWN_H_ */ diff --git a/lib9p/tests/test_server/fs_whoami.c b/lib9p/tests/test_server/fs_whoami.c new file mode 100644 index 0000000..3cc0683 --- /dev/null +++ b/lib9p/tests/test_server/fs_whoami.c @@ -0,0 +1,149 @@ +/* lib9p/tests/test_server/fs_whoami.c - /whoami API endpoint + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <inttypes.h> /* for PRI* */ +#include <stdio.h> /* for snprintf() */ +#include <stdlib.h> /* for realloc(), free() */ + +#include <libmisc/alloc.h> + +#include "fs_whoami.h" + +LO_IMPLEMENTATION_C(lib9p_srv_file, struct whoami_file, whoami_file, static); + +struct whoami_fio { + struct whoami_file *parent; + size_t buf_len; + char *buf; +}; +LO_IMPLEMENTATION_H(lib9p_srv_fio, struct whoami_fio, whoami_fio); +LO_IMPLEMENTATION_C(lib9p_srv_fio, struct whoami_fio, whoami_fio, static); + +size_t whoami_len(struct lib9p_srv_ctx *ctx) { + assert(ctx); + assert(ctx->user); + + size_t len = 0; + uint32_t uid = ctx->user->num; + while (uid) { + len++; + uid /= 10; + } + if (!len) + len++; + len += 2; + len += ctx->user->name.len; + return len; +} + +/* srv_file *******************************************************************/ + +static void whoami_file_free(struct whoami_file *self) { + assert(self); +} +static struct lib9p_qid whoami_file_qid(struct whoami_file *self) { + assert(self); + return (struct lib9p_qid){ + .type = LIB9P_QT_FILE, + .vers = 1, + .path = self->pathnum, + }; +} + +static lib9p_srv_stat_or_error whoami_file_stat(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ + .qid = whoami_file_qid(self), + .mode = 0444, + .atime_sec = UTIL9P_ATIME, + .mtime_sec = UTIL9P_MTIME, + .size = whoami_len(ctx), + .name = lib9p_str(self->name), + .owner_uid = { .name=lib9p_str("root"), .num=0 }, + .owner_gid = { .name=lib9p_str("root"), .num=0 }, + .last_modifier_uid = { .name=lib9p_str("root"), .num=0 }, + .extension = lib9p_str(NULL), + })); +} +static error whoami_file_wstat(struct whoami_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { + assert(self); + assert(ctx); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); +} +static error whoami_file_remove(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + return error_new(E_POSIX_EROFS, "cannot remove API file"); +} + +LIB9P_SRV_NOTDIR(struct whoami_file, whoami_file); + +static lib9p_srv_fio_or_error whoami_file_fopen(struct whoami_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { + assert(self); + assert(ctx); + + struct whoami_fio *ret = heap_alloc(1, struct whoami_fio); + ret->parent = self; + ret->buf_len = 0; + ret->buf = NULL; + + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); +} + +/* srv_fio ********************************************************************/ + +static void whoami_fio_iofree(struct whoami_fio *self) { + assert(self); + if (self->buf) + free(self->buf); + free(self); +} + +static struct lib9p_qid whoami_fio_qid(struct whoami_fio *self) { + assert(self); + assert(self->parent); + return whoami_file_qid(self->parent); +} + +static uint32_t whoami_fio_iounit(struct whoami_fio *self) { + assert(self); + return 0; +} + +static uint32_t_or_error whoami_fio_pwrite(struct whoami_fio *LM_UNUSED(self), + struct lib9p_srv_ctx *LM_UNUSED(ctx), + void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(offset)) { + assert_notreached("not writable"); +} +static iovec_or_error whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t byte_offset) { + assert(self); + assert(ctx); + + size_t data_size = whoami_len(ctx); + if (self->buf_len < data_size+1) { + self->buf = realloc(self->buf, data_size+1); + self->buf_len = data_size+1; + } + snprintf(self->buf, self->buf_len, "%"PRIu32" %.*s\n", + ctx->user->num, ctx->user->name.len, ctx->user->name.utf8); + + if (byte_offset > (uint64_t)data_size) + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EINVAL, "offset is past end-of-file length")); + + size_t beg_off = (size_t)byte_offset; + size_t end_off = beg_off + (size_t)byte_count; + if (end_off > data_size) + end_off = data_size; + + return ERROR_NEW_VAL(iovec, ((struct iovec){ + .iov_base = &self->buf[beg_off], + .iov_len = end_off-beg_off, + })); +} diff --git a/lib9p/tests/test_server/fs_whoami.h b/lib9p/tests/test_server/fs_whoami.h new file mode 100644 index 0000000..518e11d --- /dev/null +++ b/lib9p/tests/test_server/fs_whoami.h @@ -0,0 +1,19 @@ +/* lib9p/tests/test_server/fs_whoami.h - /whoami API endpoint + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ +#define _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ + +#include <libhw/host_net.h> +#include <util9p/static.h> + +struct whoami_file { + char *name; + uint64_t pathnum; +}; +LO_IMPLEMENTATION_H(lib9p_srv_file, struct whoami_file, whoami_file); + +#endif /* _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ */ diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c index c759029..0431c40 100644 --- a/lib9p/tests/test_server/main.c +++ b/lib9p/tests/test_server/main.c @@ -4,157 +4,91 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include <error.h> +#include <errno.h> +#include <stdio.h> #include <stdlib.h> /* for atoi() */ +#define error __error +#include <error.h> +#undef error + #include <lib9p/srv.h> #include <libcr/coroutine.h> -#include <libhw/generic/net.h> #include <libhw/generic/alarmclock.h> +#include <libhw/generic/net.h> #include <libhw/host_alarmclock.h> #include <libhw/host_net.h> #include <libmisc/macro.h> #include <util9p/static.h> +#include "fs_flush.h" +#include "fs_shutdown.h" +#include "fs_whoami.h" #include "static.h" /* configuration **************************************************************/ #include "config.h" -#ifndef CONFIG_SRV9P_NUM_CONNS - #error config.h must define CONFIG_SRV9P_NUM_CONNS +#ifndef _CONFIG_9P_MAX_CONNS + #error config.h must define _CONFIG_9P_MAX_CONNS +#endif +#ifndef _CONFIG_9P_MAX_REQS + #error config.h must define _CONFIG_9P_MAX_REQS #endif /* globals ********************************************************************/ -static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *, struct lib9p_s); +static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *, struct lib9p_s); -const char *hexdig = "0123456789abcdef"; +static const char *hexdig = "0123456789abcdef"; -struct { +static struct { uint16_t port; - struct hostnet_tcp_listener listeners[CONFIG_SRV9P_NUM_CONNS]; + struct hostnet_tcp_listener listeners[_CONFIG_9P_MAX_CONNS]; struct lib9p_srv srv; + FILE *logstream; } globals = { .srv = (struct lib9p_srv){ .rootdir = get_root, }, }; -/* api ************************************************************************/ - -struct api_file { - uint64_t pathnum; -}; -LO_IMPLEMENTATION_H(lib9p_srv_file, struct api_file, api) -LO_IMPLEMENTATION_H(lib9p_srv_fio, struct api_file, api) - -LO_IMPLEMENTATION_C(lib9p_srv_file, struct api_file, api, static) -LO_IMPLEMENTATION_C(lib9p_srv_fio, struct api_file, api, static) - -static void api_free(struct api_file *self) { - assert(self); -} -static struct lib9p_qid api_qid(struct api_file *self) { - assert(self); - return (struct lib9p_qid){ - .type = LIB9P_QT_FILE, - .vers = 1, - .path = self->pathnum, - }; -} - -static struct lib9p_stat api_stat(struct api_file *self, struct lib9p_srv_ctx *ctx) { - assert(self); - assert(ctx); - return (struct lib9p_stat){ - .kern_type = 0, - .kern_dev = 0, - .file_qid = api_qid(self), - .file_mode = 0222, - .file_atime = UTIL9P_ATIME, - .file_mtime = UTIL9P_MTIME, - .file_size = 0, - .file_name = lib9p_str("shutdown"), - .file_owner_uid = lib9p_str("root"), - .file_owner_gid = lib9p_str("root"), - .file_last_modified_uid = lib9p_str("root"), - .file_extension = lib9p_str(NULL), - .file_owner_n_uid = 0, - .file_owner_n_gid = 0, - .file_last_modified_n_uid = 0, - }; -} -static void api_wstat(struct api_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { - assert(self); - assert(ctx); - lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file"); -} -static void api_remove(struct api_file *self, struct lib9p_srv_ctx *ctx) { - assert(self); - assert(ctx); - lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file"); -} - -LIB9P_SRV_NOTDIR(struct api_file, api) - -static lo_interface lib9p_srv_fio api_fopen(struct api_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { - assert(self); - assert(ctx); - return lo_box_api_as_lib9p_srv_fio(self); -} - -static void api_iofree(struct api_file *self) { - assert(self); -} - -static uint32_t api_iounit(struct api_file *self) { - assert(self); - return 0; -} - -static uint32_t api_pwrite(struct api_file *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t LM_UNUSED(offset)) { - assert(self); - assert(ctx); - assert(buf); - if (byte_count == 0) - return 0; - for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) - LO_CALL(lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i]), close); - return byte_count; -} -static void api_pread(struct api_file *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), - uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset), - struct iovec *LM_UNUSED(ret)) { - assert_notreached("not readable"); -} - -#define lo_box_api_as_lib9p_srv_file(obj) util9p_box(api, obj) - /* file tree ******************************************************************/ -enum { PATH_BASE = __COUNTER__ }; -#define PATH_COUNTER __COUNTER__ - PATH_BASE - -#define STATIC_FILE(STRNAME, SYMNAME) \ - UTIL9P_STATIC_FILE(PATH_COUNTER, STRNAME, \ +#define STATIC_FILE(N, STRNAME, SYMNAME) \ + UTIL9P_STATIC_FILE(N, STRNAME, \ .data_start = _binary_static_##SYMNAME##_start, \ .data_end = _binary_static_##SYMNAME##_end) -#define STATIC_DIR(STRNAME, ...) \ - UTIL9P_STATIC_DIR(PATH_COUNTER, STRNAME, __VA_ARGS__) - -struct lib9p_srv_file root = - STATIC_DIR("", - STATIC_DIR("Documentation", - STATIC_FILE("x", Documentation_x_txt), +#define STATIC_DIR(N, STRNAME, ...) \ + UTIL9P_STATIC_DIR(N, STRNAME, __VA_ARGS__) + +#define API_FILE(N, STRNAME, SYMNAME, ...) \ + LO_BOX(lib9p_srv_file, &((struct SYMNAME##_file){ \ + .name = STRNAME, \ + .pathnum = N \ + __VA_OPT__(,) __VA_ARGS__ \ + })) + +static struct lib9p_srv_file root = + STATIC_DIR(1, "", + STATIC_DIR(2, "Documentation", + STATIC_FILE(3, "x", Documentation_x_txt), ), - STATIC_FILE("README.md", README_md), - lo_box_api_as_lib9p_srv_file(&(struct api_file){.pathnum = PATH_COUNTER}), + STATIC_FILE(4, "README.md", README_md), + API_FILE(5, "shutdown", shutdown, + .listeners = globals.listeners, + .nlisteners = LM_ARRAY_LEN(globals.listeners)), + API_FILE(8, "whoami", whoami), + API_FILE(9, "flush-read", flush, .flush_cnt=1, .flush_behavior=FLUSH_READ), + API_FILE(10, "flush-error", flush, .flush_cnt=1, .flush_behavior=FLUSH_ERROR), + API_FILE(11, "flush-silent", flush, .flush_cnt=1, .flush_behavior=FLUSH_SILENT), + API_FILE(12, "flush-slowsilent", flush, .flush_cnt=2, .flush_behavior=FLUSH_SILENT), + API_FILE(13, "flush-slowread", flush, .flush_cnt=0, .flush_behavior=FLUSH_READ), ); -static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { - return root; +static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { + return ERROR_NEW_VAL(lib9p_srv_file, root); } /* main ***********************************************************************/ @@ -165,7 +99,15 @@ static COROUTINE read_cr(void *_i) { hostnet_tcp_listener_init(&globals.listeners[i], globals.port); - lib9p_srv_read_cr(&globals.srv, lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i])); + lib9p_srv_accept_and_read_loop(&globals.srv, LO_BOX(net_stream_listener, &globals.listeners[i])); + + cr_end(); +} + +static COROUTINE write_cr(void *) { + cr_begin(); + + lib9p_srv_worker_loop(&globals.srv); cr_end(); } @@ -173,31 +115,61 @@ static COROUTINE read_cr(void *_i) { static COROUTINE init_cr(void *) { cr_begin(); - sleep_for_ms(1); + sleep_for_ms(1); /* test that sleep works */ - for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) { + for (int i = 0; i < _CONFIG_9P_MAX_CONNS; i++) { char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'}; if (!coroutine_add(name, read_cr, &i)) - error(1, 0, "coroutine_add(read_cr, &i)"); + __error(1, 0, "coroutine_add(read_cr, &i)"); } - for (int i = 0; i < 2*CONFIG_SRV9P_NUM_CONNS; i++) { + for (int i = 0; i < _CONFIG_9P_MAX_REQS; i++) { char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'}; - if (!coroutine_add(name, lib9p_srv_write_cr, &globals.srv)) - error(1, 0, "coroutine_add(lib9p_srv_write_cr, &globals.srv)"); + if (!coroutine_add(name, write_cr, NULL)) + __error(1, 0, "coroutine_add(write_cr, NULL)"); } cr_exit(); } +struct tstlog_stdout {}; +LO_IMPLEMENTATION_H(fmt_dest, struct tstlog_stdout, tstlog_stdout); +LO_IMPLEMENTATION_C(fmt_dest, struct tstlog_stdout, tstlog_stdout, static); + +static size_t tstlog_bytes = 0; + +static void tstlog_stdout_putb(struct tstlog_stdout *, uint8_t b) { + putc(b, globals.logstream); + putchar(b); + tstlog_bytes++; +} + +static size_t tstlog_stdout_tell(struct tstlog_stdout *) { + return tstlog_bytes; +} + +static lo_interface fmt_dest tstlog_dest = { .vtable = &_lo_tstlog_stdout_fmt_dest_vtable }; + +static void tstlog_msg(struct lib9p_srv_ctx *ctx, enum lib9p_msg_type typ, void *hostmsg) { + fmt_print(tstlog_dest, typ % 2 ? "< " : "> ", (lib9p_msg, &ctx->basectx, typ, hostmsg), "\n"); + fflush(globals.logstream); +} + int main(int argc, char *argv[]) { - if (argc != 2) - error(2, 0, "usage: %s PORT_NUMBER", argv[0]); + if (argc != 3) + __error(2, 0, "usage: %s PORT_NUMBER LOGFILE", argv[0]); + globals.port = atoi(argv[1]); + globals.logstream = fopen(argv[2], "w"); + if (!globals.logstream) + __error(2, errno, "fopen"); + globals.srv.msglog = tstlog_msg; + struct hostclock clock_monotonic = { .clock_id = CLOCK_MONOTONIC, }; - bootclock = lo_box_hostclock_as_alarmclock(&clock_monotonic); + bootclock = LO_BOX(alarmclock, &clock_monotonic); coroutine_add("init", init_cr, NULL); coroutine_main(); + fclose(globals.logstream); return 0; } diff --git a/lib9p/tests/testclient-hangup.c b/lib9p/tests/testclient-hangup.c new file mode 100644 index 0000000..2efb49a --- /dev/null +++ b/lib9p/tests/testclient-hangup.c @@ -0,0 +1,100 @@ +/* lib9p/tests/testclient-hangup.c - Test the 9P `test_server`'s handling of TCP hangups + * + * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <arpa/inet.h> /* for htons(), inet_addr() */ +#include <errno.h> +#include <netinet/in.h> /* for struct sockaddr{,_in} */ +#include <stdlib.h> /* for atoi() */ +#include <sys/socket.h> /* for socket(), connect() */ +#include <sys/uio.h> /* for writev() */ +#include <unistd.h> /* for read() */ + +#define error __error +#include <error.h> +#undef error + +#include <lib9p/core.h> +#include <libmisc/assert.h> +#include <libmisc/endian.h> + +#define MAX_MSG_SIZE (8*1024) + +static void _send9p(int fd, struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body) { + struct lib9p_Tmsg_send_buf buf; + error err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); + assert(ERROR_IS_NULL(err)); + size_t exp = 0; + for (size_t i = 0; i < buf.iov_cnt; i++) + exp += buf.iov[i].iov_len; + ssize_t act = writev(fd, buf.iov, buf.iov_cnt); + if (act < 0) + __error(1, errno, "writev"); + assert((size_t)act == exp); +} + +#define send9p(typ, ...) _send9p(fd, &ctx, LIB9P_TYP_##typ, &((struct lib9p_msg_##typ){ __VA_ARGS__ })) + +static void _recv9p(int fd) { + uint8_t buf[MAX_MSG_SIZE]; + size_t goal = 4; + size_t done = 0; + while (done < goal) { + ssize_t n = read(fd, &buf[done], goal-done); + if (n < 0) + __error(1, errno, "read"); + done += n; + } + goal = uint32le_decode(buf); + assert(goal <= MAX_MSG_SIZE); + while (done < goal) { + ssize_t n = read(fd, &buf[done], goal-done); + if (n < 0) + __error(1, errno, "read"); + done += n; + } +} + +#define recv9p() _recv9p(fd) + +int main(int argc, char *argv[]) { + if (argc != 2) + __error(2, 0, "Usage: %s SERVER_PORT", argv[0]); + uint16_t server_port = atoi(argv[1]); + + union { + struct sockaddr gen; + struct sockaddr_in in; + } server_addr = {}; + server_addr.in.sin_family = AF_INET; + server_addr.in.sin_addr.s_addr = inet_addr("127.0.0.1"); + server_addr.in.sin_port = htons(server_port); + + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + __error(1, errno, "socket"); + if (connect(fd, &server_addr.gen, sizeof(server_addr)) < 0) + __error(1, errno, "connect"); + + struct lib9p_ctx ctx = { + .max_msg_size = 16*1024, + }; + + struct lib9p_s wname[1]; + + /**********************************************************************/ + + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("nobody"), .aname=lib9p_str("")); + recv9p(); /* Rattach */ + wname[0] = lib9p_str("shutdown"); send9p(Twalk, .tag=0, .fid=0, .newfid=0, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=0, .mode=LIB9P_O_MODE_WRITE); + recv9p(); /* Ropen */ + send9p(Twrite, .tag=0, .fid=0, .offset=0, .count=2, .data="1\n"); + return 0; /* Hang up without waiting for Rwrite. */ +} diff --git a/lib9p/tests/testclient-hangup.explog b/lib9p/tests/testclient-hangup.explog new file mode 100644 index 0000000..568b0fc --- /dev/null +++ b/lib9p/tests/testclient-hangup.explog @@ -0,0 +1,14 @@ +# lib9p/tests/testclient-hangup.explog - Expected 9P logfile of testclient-hangup +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later +> Tversion { tag=0 max_msg_size=8192 version="9P2000" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000" } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=0 nwname=1 wname=[ "shutdown" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(APPEND) vers=1 path=5 } ] } +> Topen { tag=0 fid=0 mode=(MODE_WRITE) } +< Ropen { tag=0 qid={ type=(APPEND) vers=1 path=5 } iounit=0 } +> Twrite { tag=0 fid=0 offset=0 count=2 data="1\n" } +< Rwrite { tag=0 count=2 } diff --git a/lib9p/tests/testclient-p9p b/lib9p/tests/testclient-p9p new file mode 100755 index 0000000..09ce746 --- /dev/null +++ b/lib9p/tests/testclient-p9p @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# lib9p/tests/testclient-p9p - Test the 9P `test_server` against Plan 9 Port's `9p` utility +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +set -euE -o pipefail + +if [[ $# != 1 ]]; then + echo >&2 "Usage: $0 SERVER_PORT" + echo >&2 "Usage: ./runtest $0 EXPLOG" + exit 2 +fi + +expect_lines() ( + { set +x; } &>/dev/null + printf >&2 '+ diff -u expected.txt actual.txt\n' + diff -u <(printf '%s\n' "$@") <(printf '%s\n' "$out") +) + +set -x +client=(unshare --user 9p -a "localhost:${1}") + +out=$("${client[@]}" ls -l '') +expect_lines \ + 'd-r-xr-xr-x M 0 root root 0 Oct 7 2024 Documentation' \ + '--r--r--r-- M 0 root root 166 Oct 7 2024 README.md' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-error' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-read' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-silent' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-slowread' \ + '--r--r--r-- M 0 root root 6 Oct 7 2024 flush-slowsilent' \ + 'a--w--w--w- M 0 root root 0 Oct 7 2024 shutdown' \ + '--r--r--r-- M 0 root root 9 Oct 7 2024 whoami' + +out=$("${client[@]}" ls -l 'Documentation/') +expect_lines \ + '--r--r--r-- M 0 root root 166 Oct 7 2024 x' + +out=$("${client[@]}" read 'README.md') +expect_lines \ + '<!--' \ + ' README.md - test static file' \ + '' \ + ' Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>' \ + ' SPDX-License-Identifier: AGPL-3.0-or-later' \ + '-->' \ + 'Hello, world!' + +out=$("${client[@]}" read 'Documentation/x') +expect_lines \ + '<!--' \ + ' Documentation/x.txt - test static file' \ + '' \ + ' Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>' \ + ' SPDX-License-Identifier: AGPL-3.0-or-later' \ + '-->' \ + 'foo' + +out=$("${client[@]}" stat 'Documentation/x') +expect_lines \ + "'x' 'root' 'root' 'root' q (0000000000000003 1 ) m 0444 at 1728337905 mt 1728337904 l 166 t 0 d 0" + +out=$("${client[@]}" write 'shutdown' <<<1) +expect_lines '' diff --git a/lib9p/tests/testclient-p9p.explog b/lib9p/tests/testclient-p9p.explog new file mode 100644 index 0000000..54f1e4b --- /dev/null +++ b/lib9p/tests/testclient-p9p.explog @@ -0,0 +1,106 @@ +# lib9p/tests/testclient-p9p.explog - Expected 9P logfile of testclient-p9p +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later +> Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } +< Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } +> Tauth { tag=0 afid=0 uname="nobody" aname="" unum=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=1 nwname=0 wname=[ ] } +< Rwalk { tag=0 nwqid=0 wqid=[ ] } +> Tstat { tag=0 fid=1 } +< Rstat { tag=0 stat={ fstype=0 fsdev=0 qid={ type=(DIR) vers=1 path=1 } mode=(DIR|0555) atime=1728337905 mtime=1728337904 length=0 name="" owner_uname="root" owner_gname="root" last_modifier_uname="root" extension="" owner_unum=0 owner_gnum=0 last_modifier_unum=0 } } +> Tclunk { tag=0 fid=1 } +< Rclunk { tag=0 } +> Twalk { tag=0 fid=0 newfid=1 nwname=0 wname=[ ] } +< Rwalk { tag=0 nwqid=0 wqid=[ ] } +> Topen { tag=0 fid=1 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(DIR) vers=1 path=1 } iounit=0 } +> Tread { tag=0 fid=1 offset=0 count=4096 } +< Rread { tag=0 count=648 data=<bytedata> } +> Tread { tag=0 fid=1 offset=648 count=4096 } +< Rread { tag=0 count=0 data="" } +> Tclunk { tag=0 fid=1 } +< Rclunk { tag=0 } +> Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } +< Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } +> Tauth { tag=0 afid=0 uname="nobody" aname="" unum=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "Documentation" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(DIR) vers=1 path=2 } ] } +> Tstat { tag=0 fid=1 } +< Rstat { tag=0 stat={ fstype=0 fsdev=0 qid={ type=(DIR) vers=1 path=2 } mode=(DIR|0555) atime=1728337905 mtime=1728337904 length=0 name="Documentation" owner_uname="root" owner_gname="root" last_modifier_uname="root" extension="" owner_unum=0 owner_gnum=0 last_modifier_unum=0 } } +> Tclunk { tag=0 fid=1 } +< Rclunk { tag=0 } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "Documentation" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(DIR) vers=1 path=2 } ] } +> Topen { tag=0 fid=1 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(DIR) vers=1 path=2 } iounit=0 } +> Tread { tag=0 fid=1 offset=0 count=4096 } +< Rread { tag=0 count=62 data=<bytedata> } +> Tread { tag=0 fid=1 offset=62 count=4096 } +< Rread { tag=0 count=0 data="" } +> Tclunk { tag=0 fid=1 } +< Rclunk { tag=0 } +> Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } +< Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } +> Tauth { tag=0 afid=0 uname="nobody" aname="" unum=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "README.md" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=4 } ] } +> Topen { tag=0 fid=1 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=4 } iounit=0 } +> Tread { tag=0 fid=1 offset=0 count=4096 } +< Rread { tag=0 count=166 data="<!--\n README.md - test static file\n\n Copyright ("... } +> Tread { tag=0 fid=1 offset=166 count=4096 } +< Rread { tag=0 count=0 data="" } +> Tclunk { tag=0 fid=1 } +< Rclunk { tag=0 } +> Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } +< Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } +> Tauth { tag=0 afid=0 uname="nobody" aname="" unum=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=1 nwname=2 wname=[ "Documentation", "x" ] } +< Rwalk { tag=0 nwqid=2 wqid=[ { type=(DIR) vers=1 path=2 }, { type=(0) vers=1 path=3 } ] } +> Topen { tag=0 fid=1 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=3 } iounit=0 } +> Tread { tag=0 fid=1 offset=0 count=4096 } +< Rread { tag=0 count=166 data="<!--\n Documentation/x.txt - test static file\n\n C"... } +> Tread { tag=0 fid=1 offset=166 count=4096 } +< Rread { tag=0 count=0 data="" } +> Tclunk { tag=0 fid=1 } +< Rclunk { tag=0 } +> Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } +< Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } +> Tauth { tag=0 afid=0 uname="nobody" aname="" unum=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=1 nwname=2 wname=[ "Documentation", "x" ] } +< Rwalk { tag=0 nwqid=2 wqid=[ { type=(DIR) vers=1 path=2 }, { type=(0) vers=1 path=3 } ] } +> Tstat { tag=0 fid=1 } +< Rstat { tag=0 stat={ fstype=0 fsdev=0 qid={ type=(0) vers=1 path=3 } mode=(0444) atime=1728337905 mtime=1728337904 length=166 name="x" owner_uname="root" owner_gname="root" last_modifier_uname="root" extension="" owner_unum=0 owner_gnum=0 last_modifier_unum=0 } } +> Tclunk { tag=0 fid=1 } +< Rclunk { tag=0 } +> Tversion { tag=NOTAG max_msg_size=8192 version="9P2000" } +< Rversion { tag=NOTAG max_msg_size=4120 version="9P2000" } +> Tauth { tag=0 afid=0 uname="nobody" aname="" unum=0 } +< Rerror { tag=0 errstr="authentication not required" errnum=L_EOPNOTSUPP } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "shutdown" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(APPEND) vers=1 path=5 } ] } +> Topen { tag=0 fid=1 mode=(TRUNC|MODE_WRITE) } +< Ropen { tag=0 qid={ type=(APPEND) vers=1 path=5 } iounit=0 } +> Twrite { tag=0 fid=1 offset=0 count=2 data="1\n" } +< Rwrite { tag=0 count=2 } +> Tclunk { tag=0 fid=1 } +< Rclunk { tag=0 } diff --git a/lib9p/tests/testclient-sess.c b/lib9p/tests/testclient-sess.c new file mode 100644 index 0000000..0cec6c6 --- /dev/null +++ b/lib9p/tests/testclient-sess.c @@ -0,0 +1,246 @@ +/* lib9p/tests/testclient-sess.c - Test the 9P `test_server`'s sessions + * + * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <arpa/inet.h> /* for htons(), inet_addr() */ +#include <errno.h> +#include <netinet/in.h> /* for struct sockaddr{,_in} */ +#include <stdlib.h> /* for atoi() */ +#include <sys/socket.h> /* for socket(), connect() */ +#include <sys/uio.h> /* for writev() */ +#include <unistd.h> /* for read() */ + +#define error __error +#include <error.h> +#undef error + +#include <lib9p/core.h> +#include <libmisc/assert.h> +#include <libmisc/endian.h> + +#define MAX_MSG_SIZE (8*1024) + +static void _send9p(int fd, struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body) { + struct lib9p_Tmsg_send_buf buf; + error err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); + assert(ERROR_IS_NULL(err)); + size_t exp = 0; + for (size_t i = 0; i < buf.iov_cnt; i++) + exp += buf.iov[i].iov_len; + ssize_t act = writev(fd, buf.iov, buf.iov_cnt); + if (act < 0) + __error(1, errno, "writev"); + assert((size_t)act == exp); +} + +#define send9p(typ, ...) _send9p(fd, &ctx, LIB9P_TYP_##typ, &((struct lib9p_msg_##typ){ __VA_ARGS__ })) + +static void _recv9p(int fd) { + uint8_t buf[MAX_MSG_SIZE]; + size_t goal = 4; + size_t done = 0; + while (done < goal) { + ssize_t n = read(fd, &buf[done], goal-done); + if (n < 0) + __error(1, errno, "read"); + done += n; + } + goal = uint32le_decode(buf); + assert(goal <= MAX_MSG_SIZE); + while (done < goal) { + ssize_t n = read(fd, &buf[done], goal-done); + if (n < 0) + __error(1, errno, "read"); + done += n; + } +} + +#define recv9p() _recv9p(fd) + +int main(int argc, char *argv[]) { + if (argc != 2) + __error(2, 0, "Usage: %s SERVER_PORT", argv[0]); + uint16_t server_port = atoi(argv[1]); + + union { + struct sockaddr gen; + struct sockaddr_in in; + } server_addr = {}; + server_addr.in.sin_family = AF_INET; + server_addr.in.sin_addr.s_addr = inet_addr("127.0.0.1"); + server_addr.in.sin_port = htons(server_port); + + int fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd < 0) + __error(1, errno, "socket"); + if (connect(fd, &server_addr.gen, sizeof(server_addr)) < 0) + __error(1, errno, "connect"); + + struct lib9p_ctx ctx = { + .max_msg_size = 16*1024, + }; + + struct lib9p_s wname[1]; + + /* numeric downgrade, unknown ext *************************************/ + send9p(Tversion, .tag=0, .max_msg_size=57, .version=lib9p_str("9P2025.x")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000; + + /* numeric downgrade, known ext ***************************************/ + send9p(Tversion, .tag=0, .max_msg_size=57, .version=lib9p_str("9P2025.u")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000_u; + + /* ext version, users *************************************************/ + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000.u")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000_u; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("alice"), .unum=1000, .aname=lib9p_str("")); + recv9p(); /* Rattach */ + send9p(Tattach, .tag=0, .fid=1, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("bob"), .unum=1001, .aname=lib9p_str("")); + recv9p(); /* Rattach */ + wname[0] = lib9p_str("whoami"); send9p(Twalk, .tag=0, .fid=0, .newfid=2, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + wname[0] = lib9p_str("whoami"); send9p(Twalk, .tag=0, .fid=1, .newfid=3, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=2, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Topen, .tag=0, .fid=3, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=2, .offset=0, .count=100); + recv9p(); /* Rread */ + send9p(Tread, .tag=0, .fid=3, .offset=0, .count=100); + recv9p(); /* Rread */ + + /* walk ***************************************************************/ + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("nobody"), .aname=lib9p_str("")); + recv9p(); /* Rattach */ + + /* dup */ + send9p(Twalk, .tag=0, .fid=0, .newfid=1, .nwname=0); + recv9p(); /* Rwalk */ + + /* "The walk request carries as arguments an existing fid"... */ + send9p(Twalk, .tag=0, .fid=2, .newfid=3, .nwname=0); + recv9p(); /* Rerror */ + + /* ..."and a proposed newfid"... */ + send9p(Twalk, .tag=0, .fid=1, .newfid=0xffffffff, .nwname=0); + recv9p(); /* Rerror */ + + /* ..."(which must not be in use"... */ + send9p(Twalk, .tag=0, .fid=1, .newfid=0, .nwname=0); + recv9p(); /* Rerror */ + + /* ..."unless it is the same as fid)"... */ + send9p(Twalk, .tag=0, .fid=1, .newfid=1, .nwname=0); + recv9p(); /* Rwalk */ + + /* ... "that the client wishes to associate with the result of + * traversing the directory hierarchy by `walking' the heierarchy using + * the successive path name elements wname."... */ + + /* ..."The fid must represent a directory"... */ + wname[0] = lib9p_str("README.md"); send9p(Twalk, .tag=0, .fid=1, .newfid=2, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + wname[0] = lib9p_str(".."); send9p(Twalk, .tag=0, .fid=2, .newfid=3, .nwname=1, .wname=wname); + recv9p(); /* Rerror */ + + /* ..."unless zero path name elements are specified." */ + send9p(Twalk, .tag=0, .fid=2, .newfid=3, .nwname=0); + recv9p(); /* Rwalk */ + + /* "The fid must be valid in the current session" (tested above)... */ + + /* ..."and must not have been opened for I/O by an open or create + * message."... */ + send9p(Topen, .tag=0, .fid=3, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Twalk, .tag=0, .fid=3, .newfid=4, .nwname=0); + recv9p(); /* Rerror */ + + /* flush **************************************************************/ + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("nobody"), .aname=lib9p_str("")); + recv9p(); /* Rattach */ + + /* flush, but original response comes back first */ + wname[0] = lib9p_str("flush-read"); send9p(Twalk, .tag=0, .fid=0, .newfid=1, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=1, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=1, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); + recv9p(); /* Rread */ + recv9p(); /* Rflush */ + + /* flush, original request is aborted with error */ + wname[0] = lib9p_str("flush-error"); send9p(Twalk, .tag=0, .fid=0, .newfid=2, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=2, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=2, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); + recv9p(); /* Rerror */ + recv9p(); /* Rflush */ + + /* flush, original request is aborted without error */ + wname[0] = lib9p_str("flush-silent"); send9p(Twalk, .tag=0, .fid=0, .newfid=3, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=3, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=3, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); + recv9p(); /* Rflush */ + + /* multiflush, original request is aborted without error */ + wname[0] = lib9p_str("flush-slowsilent"); send9p(Twalk, .tag=0, .fid=0, .newfid=4, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=4, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=4, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); + send9p(Tflush, .tag=2, .oldtag=0); + recv9p(); /* Rflush */ + + /* flush, but flush is flushed */ + wname[0] = lib9p_str("flush-slowread"); send9p(Twalk, .tag=0, .fid=0, .newfid=5, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=5, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=5, .offset=0, .count=10); + send9p(Tflush, .tag=1, .oldtag=0); + send9p(Tflush, .tag=2, .oldtag=1); + recv9p(); /* Rflush */ + recv9p(); /* Rread */ + + /* flush, unknown tag */ + send9p(Tflush, .tag=0, .oldtag=99); + recv9p(); /* Rflush */ + + /* flushed by Tversion */ + send9p(Tread, .tag=0, .fid=3, .offset=0, .count=10); + + /* shutdown ***********************************************************/ + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); + recv9p(); /* Rversion */ + ctx.version = LIB9P_VER_9P2000; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("nobody"), .aname=lib9p_str("")); + recv9p(); /* Rattach */ + /* check the newfid==fid case */ + wname[0] = lib9p_str("shutdown"); send9p(Twalk, .tag=0, .fid=0, .newfid=0, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=0, .mode=LIB9P_O_MODE_WRITE); + recv9p(); /* Ropen */ + send9p(Twrite, .tag=0, .fid=0, .offset=0, .count=2, .data="1\n"); + recv9p(); /* Rwrite */ + return 0; +} diff --git a/lib9p/tests/testclient-sess.explog b/lib9p/tests/testclient-sess.explog new file mode 100644 index 0000000..ec8d9c9 --- /dev/null +++ b/lib9p/tests/testclient-sess.explog @@ -0,0 +1,156 @@ +# lib9p/tests/testclient-sess.explog - Expected 9P logfile of testclient-sess.c +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +# numeric downgrade, unknown ext ############################################### +> Tversion { tag=0 max_msg_size=57 version="9P2025.x" } +< Rversion { tag=0 max_msg_size=57 version="9P2000" } + +# numeric downgrade, known ext ################################################# +> Tversion { tag=0 max_msg_size=57 version="9P2025.u" } +< Rversion { tag=0 max_msg_size=57 version="9P2000.u" } + +# ext version, users ########################################################### +> Tversion { tag=0 max_msg_size=8192 version="9P2000.u" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000.u" } +> Tattach { tag=0 fid=0 afid=NOFID uname="alice" aname="" unum=1000 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Tattach { tag=0 fid=1 afid=NOFID uname="bob" aname="" unum=1001 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=2 nwname=1 wname=[ "whoami" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=8 } ] } +> Twalk { tag=0 fid=1 newfid=3 nwname=1 wname=[ "whoami" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=8 } ] } +> Topen { tag=0 fid=2 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=8 } iounit=0 } +> Topen { tag=0 fid=3 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=8 } iounit=0 } +> Tread { tag=0 fid=2 offset=0 count=100 } +< Rread { tag=0 count=11 data="1000 alice\n" } +> Tread { tag=0 fid=3 offset=0 count=100 } +< Rread { tag=0 count=9 data="1001 bob\n" } + +# walk ######################################################################### +> Tversion { tag=0 max_msg_size=8192 version="9P2000" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000" } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } + +# dup +> Twalk { tag=0 fid=0 newfid=1 nwname=0 wname=[ ] } +< Rwalk { tag=0 nwqid=0 wqid=[ ] } + +# "The walk request carries as arguments an existing fid"... +> Twalk { tag=0 fid=2 newfid=3 nwname=0 wname=[ ] } +< Rerror { tag=0 errstr="bad file number 2" errnum=L_EBADF } + +# ..."and a proposed newfid"... +> Twalk { tag=0 fid=1 newfid=NOFID nwname=0 wname=[ ] } +< Rerror { tag=0 errstr="cannot assign to NOFID" errnum=L_EBADF } + +# ..."(which must not be in use"... +> Twalk { tag=0 fid=1 newfid=0 nwname=0 wname=[ ] } +< Rerror { tag=0 errstr="FID already in use" errnum=L_EBADF } + +# ..."unless it is the same as fid)"... +> Twalk { tag=0 fid=1 newfid=1 nwname=0 wname=[ ] } +< Rwalk { tag=0 nwqid=0 wqid=[ ] } + +# ... "that the client wishes to associate with the result of +# traversing the directory hierarchy by `walking' the heierarchy using +# the successive path name elements wname."... + +# ..."The fid must represent a directory"... +> Twalk { tag=0 fid=1 newfid=2 nwname=1 wname=[ "README.md" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=4 } ] } +> Twalk { tag=0 fid=2 newfid=3 nwname=1 wname=[ ".." ] } +< Rerror { tag=0 errstr="not a directory" errnum=L_ENOTDIR } + +# ..."unless zero path name elements are specified." +> Twalk { tag=0 fid=2 newfid=3 nwname=0 wname=[ ] } +< Rwalk { tag=0 nwqid=0 wqid=[ ] } + +# "The fid must be valid in the current session" (tested above)... + +# ..."and must not have been opened for I/O by an open or create +# message."... +> Topen { tag=0 fid=3 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=4 } iounit=0 } +> Twalk { tag=0 fid=3 newfid=4 nwname=0 wname=[ ] } +< Rerror { tag=0 errstr="cannot walk on FID open for I/O" errnum=L_EALREADY } + +# flush ######################################################################## +> Tversion { tag=0 max_msg_size=8192 version="9P2000" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000" } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } + +# flush, but original response comes back first +> Twalk { tag=0 fid=0 newfid=1 nwname=1 wname=[ "flush-read" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=9 } ] } +> Topen { tag=0 fid=1 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=9 } iounit=0 } +> Tread { tag=0 fid=1 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +< Rread { tag=0 count=6 data="Sloth\n" } +< Rflush { tag=1 } + +# flush, original request is aborted with error +> Twalk { tag=0 fid=0 newfid=2 nwname=1 wname=[ "flush-error" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=10 } ] } +> Topen { tag=0 fid=2 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=10 } iounit=0 } +> Tread { tag=0 fid=2 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +< Rerror { tag=0 errstr="request canceled by flush" errnum=L_EAGAIN } +< Rflush { tag=1 } + +# flush, original request is aborted without error +> Twalk { tag=0 fid=0 newfid=3 nwname=1 wname=[ "flush-silent" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=11 } ] } +> Topen { tag=0 fid=3 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=11 } iounit=0 } +> Tread { tag=0 fid=3 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +< Rflush { tag=1 } + +# multiflush, original request is aborted without error +> Twalk { tag=0 fid=0 newfid=4 nwname=1 wname=[ "flush-slowsilent" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=12 } ] } +> Topen { tag=0 fid=4 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=12 } iounit=0 } +> Tread { tag=0 fid=4 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +> Tflush { tag=2 oldtag=0 } +< Rflush { tag=2 } + +# flush, but flush is flushed +> Twalk { tag=0 fid=0 newfid=5 nwname=1 wname=[ "flush-slowread" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(0) vers=1 path=13 } ] } +> Topen { tag=0 fid=5 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=13 } iounit=0 } +> Tread { tag=0 fid=5 offset=0 count=10 } +> Tflush { tag=1 oldtag=0 } +> Tflush { tag=2 oldtag=1 } +< Rflush { tag=2 } +< Rread { tag=0 count=6 data="Sloth\n" } + +# flush, unknown tag +> Tflush { tag=0 oldtag=99 } +< Rflush { tag=0 } + +# flushed by Tversion +> Tread { tag=0 fid=3 offset=0 count=10 } + +# shutdown ##################################################################### +> Tversion { tag=0 max_msg_size=8192 version="9P2000" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000" } +> Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" unum=0 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=0 nwname=1 wname=[ "shutdown" ] } +< Rwalk { tag=0 nwqid=1 wqid=[ { type=(APPEND) vers=1 path=5 } ] } +> Topen { tag=0 fid=0 mode=(MODE_WRITE) } +< Ropen { tag=0 qid={ type=(APPEND) vers=1 path=5 } iounit=0 } +> Twrite { tag=0 fid=0 offset=0 count=2 data="1\n" } +< Rwrite { tag=0 count=2 } |