From bb5afed7a0eeaf361be1e29b3a3ab8ace2865b39 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Wed, 9 Oct 2024 17:01:06 -0600 Subject: lib9p: finish refactor --- lib9p/.editorconfig | 2 +- lib9p/9p.c | 39 +- lib9p/9p.generated.c | 1471 ++++++++++++++++++++++++++++++------ lib9p/idl.gen | 589 ++++++++------- lib9p/idl/00-README.md | 48 -- lib9p/idl/0000-README.md | 48 ++ lib9p/idl/01-9P2000.9p | 147 ---- lib9p/idl/02-9P2000.e.9p | 18 - lib9p/idl/02-9P2000.u.9p | 29 - lib9p/idl/03-9P2000.L.9p.wip | 56 -- lib9p/idl/1992-9P0.9p.wip | 53 ++ lib9p/idl/1995-9P1.9p.wip | 52 ++ lib9p/idl/1996-Styx.9p.wip | 15 + lib9p/idl/2002-9P2000.9p | 147 ++++ lib9p/idl/2005-9P2000.u.9p | 29 + lib9p/idl/2010-9P2000.L.9p.wip | 56 ++ lib9p/idl/2012-9P2000.e.9p | 18 + lib9p/include/lib9p/9p.generated.h | 2 +- lib9p/include/lib9p/9p.h | 17 +- lib9p/srv.c | 77 +- 20 files changed, 1991 insertions(+), 922 deletions(-) delete mode 100644 lib9p/idl/00-README.md create mode 100644 lib9p/idl/0000-README.md delete mode 100644 lib9p/idl/01-9P2000.9p delete mode 100644 lib9p/idl/02-9P2000.e.9p delete mode 100644 lib9p/idl/02-9P2000.u.9p delete mode 100644 lib9p/idl/03-9P2000.L.9p.wip create mode 100644 lib9p/idl/1992-9P0.9p.wip create mode 100644 lib9p/idl/1995-9P1.9p.wip create mode 100644 lib9p/idl/1996-Styx.9p.wip create mode 100644 lib9p/idl/2002-9P2000.9p create mode 100644 lib9p/idl/2005-9P2000.u.9p create mode 100644 lib9p/idl/2010-9P2000.L.9p.wip create mode 100644 lib9p/idl/2012-9P2000.e.9p (limited to 'lib9p') diff --git a/lib9p/.editorconfig b/lib9p/.editorconfig index ee1a38f..5243d26 100644 --- a/lib9p/.editorconfig +++ b/lib9p/.editorconfig @@ -1,3 +1,3 @@ -[{9p.gen,linux-errno.h.gen}] +[{idl.gen,linux-errno.h.gen}] indent_style = space indent_size = 4 diff --git a/lib9p/9p.c b/lib9p/9p.c index 8633a44..0e71071 100644 --- a/lib9p/9p.c +++ b/lib9p/9p.c @@ -36,24 +36,24 @@ int lib9p_errorf(struct lib9p_ctx *ctx, uint32_t linux_errno, char const *fmt, . } ssize_t lib9p_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) { - /* Header */ + /* Inspect the first 5 bytes ourselves. */ struct _validate_ctx subctx = { .ctx = ctx, .net_size = decode_u32le(net_bytes), .net_bytes = net_bytes, - .net_offset = 7, + .net_offset = 0, .host_extra = 0, }; - if (subctx.net_size < subctx.net_offset) - return lib9p_error(ctx, LINUX_EBADMSG, "message is too short"); + if (subctx.net_size < 5) + return lib9p_error(ctx, LINUX_EBADMSG, "message is impossibly short"); uint8_t typ = net_bytes[4]; - - /* Body */ struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[typ]; if (!vtable.validate) return lib9p_errorf(ctx, LINUX_EOPNOTSUPP, "unknown message type: %s (protocol_version=%s)", lib9p_msg_type_str(typ), lib9p_version_str(ctx->version)); + + /* Now use the message-type-specific vtable to process the whole thing. */ if (vtable.validate(&subctx)) return -1; assert(subctx.net_offset <= subctx.net_size); @@ -61,49 +61,36 @@ ssize_t lib9p_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) { return lib9p_errorf(ctx, LINUX_EBADMSG, "message has %"PRIu32" extra bytes", subctx.net_size - subctx.net_offset); + /* Return. */ ssize_t ret; if (__builtin_add_overflow(vtable.basesize, subctx.host_extra, &ret)) return lib9p_error(ctx, LINUX_EMSGSIZE, "unmarshalled payload overflows SSIZE_MAX"); - return ret; } void lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, - enum lib9p_msg_type *ret_typ, uint16_t *ret_tag, void *ret_body) { - /* Header */ + enum lib9p_msg_type *ret_typ, void *ret_body) { struct _unmarshal_ctx subctx = { .ctx = ctx, .net_bytes = net_bytes, - .net_offset = 7, + .net_offset = 0, }; - *ret_typ = net_bytes[4]; - *ret_tag = decode_u16le(&net_bytes[5]); - /* Body */ + *ret_typ = net_bytes[4]; struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[*ret_typ]; subctx.extra = ret_body + vtable.basesize; vtable.unmarshal(&subctx, ret_body); } -bool lib9p_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, uint16_t tag, void *body, +bool lib9p_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, uint8_t *ret_bytes) { - /* Header */ struct _marshal_ctx subctx = { .ctx = ctx, .net_bytes = ret_bytes, - .net_offset = 7, + .net_offset = 0, }; - ret_bytes[4] = typ; - encode_u16le(tag, &ret_bytes[5]); - /* Body */ struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[typ]; - if (vtable.marshal(&subctx, body)) - return true; - - /* Header, again */ - encode_u32le(subctx.net_offset, ret_bytes); - - return false; + return vtable.marshal(&subctx, body); } diff --git a/lib9p/9p.generated.c b/lib9p/9p.generated.c index a93316b..341acd0 100644 --- a/lib9p/9p.generated.c +++ b/lib9p/9p.generated.c @@ -1,4 +1,4 @@ -/* Generated by `./lib9p/idl.gen lib9p/idl/01-9P2000.9p lib9p/idl/02-9P2000.e.9p lib9p/idl/02-9P2000.u.9p`. DO NOT EDIT! */ +/* Generated by `./lib9p/idl.gen lib9p/idl/2002-9P2000.9p lib9p/idl/2005-9P2000.u.9p lib9p/idl/2012-9P2000.e.9p`. DO NOT EDIT! */ #include #include @@ -359,49 +359,45 @@ static ALWAYS_INLINE bool validate_s(struct _validate_ctx *ctx) { return false; } -static ALWAYS_INLINE bool validate_dm(struct _validate_ctx *ctx) { - if (validate_4(ctx)) - return true; - static const lib9p_dm_t masks[LIB9P_VER_NUM] = { +static const lib9p_dm_t dm_masks[LIB9P_VER_NUM] = { #if defined(CONFIG_9P_ENABLE_9P2000) - [LIB9P_VER_9P2000] = 0b11101100000000000000000111111111, + [LIB9P_VER_9P2000] = 0b11101100000000000000000111111111, #endif /* defined(CONFIG_9P_ENABLE_9P2000) */ #if defined(CONFIG_9P_ENABLE_9P2000_e) - [LIB9P_VER_9P2000_e] = 0b11101100000000000000000111111111, + [LIB9P_VER_9P2000_e] = 0b11101100000000000000000111111111, #endif /* defined(CONFIG_9P_ENABLE_9P2000_e) */ #if defined(CONFIG_9P_ENABLE_9P2000_u) - [LIB9P_VER_9P2000_u] = 0b11101100101111000000000111111111, + [LIB9P_VER_9P2000_u] = 0b11101100101111000000000111111111, #endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ - }; - lib9p_dm_t mask = masks[ctx->ctx->version]; +}; +static ALWAYS_INLINE bool validate_dm(struct _validate_ctx *ctx) { + if (validate_4(ctx)) + return true; + lib9p_dm_t mask = dm_masks[ctx->ctx->version]; lib9p_dm_t val = decode_u32le(&ctx->net_bytes[ctx->net_offset-4]); if (val & ~mask) - return lib9p_errorf(ctx->ctx, - LINUX_EBADMSG, "unknown bits in dm bitfield: %#04"PRIx32, - val & ~mask); + return lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "unknown bits in dm bitfield: %#04"PRIx32, val & ~mask); return false; } -static ALWAYS_INLINE bool validate_qt(struct _validate_ctx *ctx) { - if (validate_1(ctx)) - return true; - static const lib9p_qt_t masks[LIB9P_VER_NUM] = { +static const lib9p_qt_t qt_masks[LIB9P_VER_NUM] = { #if defined(CONFIG_9P_ENABLE_9P2000) - [LIB9P_VER_9P2000] = 0b11101100, + [LIB9P_VER_9P2000] = 0b11101100, #endif /* defined(CONFIG_9P_ENABLE_9P2000) */ #if defined(CONFIG_9P_ENABLE_9P2000_e) - [LIB9P_VER_9P2000_e] = 0b11101100, + [LIB9P_VER_9P2000_e] = 0b11101100, #endif /* defined(CONFIG_9P_ENABLE_9P2000_e) */ #if defined(CONFIG_9P_ENABLE_9P2000_u) - [LIB9P_VER_9P2000_u] = 0b11101110, + [LIB9P_VER_9P2000_u] = 0b11101110, #endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ - }; - lib9p_qt_t mask = masks[ctx->ctx->version]; +}; +static ALWAYS_INLINE bool validate_qt(struct _validate_ctx *ctx) { + if (validate_1(ctx)) + return true; + lib9p_qt_t mask = qt_masks[ctx->ctx->version]; lib9p_qt_t val = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); if (val & ~mask) - return lib9p_errorf(ctx->ctx, - LINUX_EBADMSG, "unknown bits in qt bitfield: %#01"PRIx8, - val & ~mask); + return lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#01"PRIx8, val & ~mask); return false; } @@ -435,33 +431,29 @@ static ALWAYS_INLINE bool validate_stat(struct _validate_ctx *ctx) { || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) ) || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) ) #endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ - || ({ uint32_t exp = ctx->net_offset - _kern_type_offset; (((uint32_t)stat_size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "stat_size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)stat_size, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "stat_size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)stat_size, exp); }) ; } -static ALWAYS_INLINE bool validate_o(struct _validate_ctx *ctx) { - if (validate_1(ctx)) - return true; - static const lib9p_o_t masks[LIB9P_VER_NUM] = { +static const lib9p_o_t o_masks[LIB9P_VER_NUM] = { #if defined(CONFIG_9P_ENABLE_9P2000) - [LIB9P_VER_9P2000] = 0b01010011, + [LIB9P_VER_9P2000] = 0b01010011, #endif /* defined(CONFIG_9P_ENABLE_9P2000) */ #if defined(CONFIG_9P_ENABLE_9P2000_e) - [LIB9P_VER_9P2000_e] = 0b01010011, + [LIB9P_VER_9P2000_e] = 0b01010011, #endif /* defined(CONFIG_9P_ENABLE_9P2000_e) */ #if defined(CONFIG_9P_ENABLE_9P2000_u) - [LIB9P_VER_9P2000_u] = 0b01010011, + [LIB9P_VER_9P2000_u] = 0b01010011, #endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ - }; - lib9p_o_t mask = masks[ctx->ctx->version]; +}; +static ALWAYS_INLINE bool validate_o(struct _validate_ctx *ctx) { + if (validate_1(ctx)) + return true; + lib9p_o_t mask = o_masks[ctx->ctx->version]; lib9p_o_t val = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); if (val & ~mask) - return lib9p_errorf(ctx->ctx, - LINUX_EBADMSG, "unknown bits in o bitfield: %#01"PRIx8, - val & ~mask); + return lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "unknown bits in o bitfield: %#01"PRIx8, val & ~mask); return false; } @@ -475,14 +467,10 @@ static FLATTEN bool validate_Tversion(struct _validate_ctx *ctx) { || validate_tag(ctx) || validate_4(ctx) || validate_s(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 100; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -496,14 +484,10 @@ static FLATTEN bool validate_Rversion(struct _validate_ctx *ctx) { || validate_tag(ctx) || validate_4(ctx) || validate_s(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 101; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -521,14 +505,10 @@ static FLATTEN bool validate_Tauth(struct _validate_ctx *ctx) { #if defined(CONFIG_9P_ENABLE_9P2000_u) || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) ) #endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 102; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -541,14 +521,10 @@ static FLATTEN bool validate_Rauth(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_qid(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 103; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -567,14 +543,10 @@ static FLATTEN bool validate_Tattach(struct _validate_ctx *ctx) { #if defined(CONFIG_9P_ENABLE_9P2000_u) || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) ) #endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 104; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -587,14 +559,10 @@ static FLATTEN bool validate_Rattach(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_qid(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 105; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -610,14 +578,10 @@ static FLATTEN bool validate_Rerror(struct _validate_ctx *ctx) { #if defined(CONFIG_9P_ENABLE_9P2000_u) || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && validate_4(ctx) ) #endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 107; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -630,14 +594,10 @@ static FLATTEN bool validate_Tflush(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_2(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 108; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -649,14 +609,10 @@ static FLATTEN bool validate_Rflush(struct _validate_ctx *ctx) { || (({ _size_offset = ctx->net_offset; validate_4(ctx); }) || ({ size = decode_u32le(&ctx->net_bytes[ctx->net_offset-4]); false; })) || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 109; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -673,18 +629,12 @@ static FLATTEN bool validate_Twalk(struct _validate_ctx *ctx) { || validate_fid(ctx) || (validate_2(ctx) || ({ nwname = decode_u16le(&ctx->net_bytes[ctx->net_offset-2]); false; })) || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), validate_s, sizeof(struct lib9p_s)) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 110; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) || ({ uint32_t max = 16; (((uint32_t)nwname) > max) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "nwname value too large (%"PRIu32" > %"PRIu32")", nwname, max); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "nwname value is too large (%"PRIu32" > %"PRIu32")", nwname, max); }) ; } @@ -699,18 +649,12 @@ static FLATTEN bool validate_Rwalk(struct _validate_ctx *ctx) { || validate_tag(ctx) || (validate_2(ctx) || ({ nwqid = decode_u16le(&ctx->net_bytes[ctx->net_offset-2]); false; })) || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), validate_qid, sizeof(struct lib9p_qid)) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 111; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) || ({ uint32_t max = 16; (((uint32_t)nwqid) > max) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "nwqid value too large (%"PRIu32" > %"PRIu32")", nwqid, max); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "nwqid value is too large (%"PRIu32" > %"PRIu32")", nwqid, max); }) ; } @@ -724,14 +668,10 @@ static FLATTEN bool validate_Topen(struct _validate_ctx *ctx) { || validate_tag(ctx) || validate_fid(ctx) || validate_o(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 112; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -745,14 +685,10 @@ static FLATTEN bool validate_Ropen(struct _validate_ctx *ctx) { || validate_tag(ctx) || validate_qid(ctx) || validate_4(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 113; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -768,14 +704,10 @@ static FLATTEN bool validate_Tcreate(struct _validate_ctx *ctx) { || validate_s(ctx) || validate_dm(ctx) || validate_o(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 114; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -789,14 +721,10 @@ static FLATTEN bool validate_Rcreate(struct _validate_ctx *ctx) { || validate_tag(ctx) || validate_qid(ctx) || validate_4(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 115; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -811,14 +739,10 @@ static FLATTEN bool validate_Tread(struct _validate_ctx *ctx) { || validate_fid(ctx) || validate_8(ctx) || validate_4(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 116; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -831,14 +755,10 @@ static FLATTEN bool validate_Rread(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_d(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 117; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -853,14 +773,10 @@ static FLATTEN bool validate_Twrite(struct _validate_ctx *ctx) { || validate_fid(ctx) || validate_8(ctx) || validate_d(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 118; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -873,14 +789,10 @@ static FLATTEN bool validate_Rwrite(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_4(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 119; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -893,14 +805,10 @@ static FLATTEN bool validate_Tclunk(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_fid(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 120; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -912,14 +820,10 @@ static FLATTEN bool validate_Rclunk(struct _validate_ctx *ctx) { || (({ _size_offset = ctx->net_offset; validate_4(ctx); }) || ({ size = decode_u32le(&ctx->net_bytes[ctx->net_offset-4]); false; })) || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 121; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -932,14 +836,10 @@ static FLATTEN bool validate_Tremove(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_fid(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 122; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -951,14 +851,10 @@ static FLATTEN bool validate_Rremove(struct _validate_ctx *ctx) { || (({ _size_offset = ctx->net_offset; validate_4(ctx); }) || ({ size = decode_u32le(&ctx->net_bytes[ctx->net_offset-4]); false; })) || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 123; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -971,14 +867,10 @@ static FLATTEN bool validate_Tstat(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_fid(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 124; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -994,18 +886,12 @@ static FLATTEN bool validate_Rstat(struct _validate_ctx *ctx) { || validate_tag(ctx) || (validate_2(ctx) || ({ nstat = decode_u16le(&ctx->net_bytes[ctx->net_offset-2]); false; })) || ({ _stat_offset = ctx->net_offset; validate_stat(ctx); }) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 125; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) || ({ uint32_t exp = ctx->net_offset - _stat_offset; (((uint32_t)nstat) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "nstat value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)nstat, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "nstat value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)nstat, exp); }) ; } @@ -1022,18 +908,12 @@ static FLATTEN bool validate_Twstat(struct _validate_ctx *ctx) { || validate_fid(ctx) || (validate_2(ctx) || ({ nstat = decode_u16le(&ctx->net_bytes[ctx->net_offset-2]); false; })) || ({ _stat_offset = ctx->net_offset; validate_stat(ctx); }) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 126; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) || ({ uint32_t exp = ctx->net_offset - _stat_offset; (((uint32_t)nstat) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "nstat value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)nstat, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "nstat value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)nstat, exp); }) ; } @@ -1045,14 +925,10 @@ static FLATTEN bool validate_Rwstat(struct _validate_ctx *ctx) { || (({ _size_offset = ctx->net_offset; validate_4(ctx); }) || ({ size = decode_u32le(&ctx->net_bytes[ctx->net_offset-4]); false; })) || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 127; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -1067,14 +943,10 @@ static FLATTEN bool validate_Tsession(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_8(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 150; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -1086,14 +958,10 @@ static FLATTEN bool validate_Rsession(struct _validate_ctx *ctx) { || (({ _size_offset = ctx->net_offset; validate_4(ctx); }) || ({ size = decode_u32le(&ctx->net_bytes[ctx->net_offset-4]); false; })) || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 151; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -1108,14 +976,10 @@ static FLATTEN bool validate_Tsread(struct _validate_ctx *ctx) { || validate_4(ctx) || validate_2(ctx) || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), validate_s, sizeof(struct lib9p_s)) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 152; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -1128,14 +992,10 @@ static FLATTEN bool validate_Rsread(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_d(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 153; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -1151,14 +1011,10 @@ static FLATTEN bool validate_Tswrite(struct _validate_ctx *ctx) { || validate_2(ctx) || _validate_list(ctx, decode_u16le(&ctx->net_bytes[ctx->net_offset-2]), validate_s, sizeof(struct lib9p_s)) || validate_d(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) - + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) || ({ uint32_t exp = 154; (((uint32_t)typ) != exp) && - - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) ; } @@ -1171,14 +1027,1133 @@ static FLATTEN bool validate_Rswrite(struct _validate_ctx *ctx) { || (validate_1(ctx) || ({ typ = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); false; })) || validate_tag(ctx) || validate_4(ctx) - || ({ uint32_t exp = ctx->net_offset - _size_offset; (((uint32_t)size) != exp) && + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) + || ({ uint32_t exp = 155; (((uint32_t)typ) != exp) && + lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) + ; +} +#endif /* defined(CONFIG_9P_ENABLE_9P2000_e) */ - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "size value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)size, exp); }) +/* unmarshal_* ****************************************************************/ - || ({ uint32_t exp = 155; (((uint32_t)typ) != exp) && +static ALWAYS_INLINE void unmarshal_1(struct _unmarshal_ctx *ctx, uint8_t *out) { + *out = decode_u8le(&ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 1; +} + +static ALWAYS_INLINE void unmarshal_2(struct _unmarshal_ctx *ctx, uint16_t *out) { + *out = decode_u16le(&ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 2; +} + +static ALWAYS_INLINE void unmarshal_4(struct _unmarshal_ctx *ctx, uint32_t *out) { + *out = decode_u32le(&ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 4; +} + +static ALWAYS_INLINE void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *out) { + *out = decode_u64le(&ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 8; +} + +#if defined(CONFIG_9P_ENABLE_9P2000) || defined(CONFIG_9P_ENABLE_9P2000_e) || defined(CONFIG_9P_ENABLE_9P2000_u) +static ALWAYS_INLINE void unmarshal_tag(struct _unmarshal_ctx *ctx, lib9p_tag_t *out) { + unmarshal_2(ctx, (uint16_t *)out); +} + +static ALWAYS_INLINE void unmarshal_fid(struct _unmarshal_ctx *ctx, lib9p_fid_t *out) { + unmarshal_4(ctx, (uint32_t *)out); +} + +static ALWAYS_INLINE void unmarshal_d(struct _unmarshal_ctx *ctx, struct lib9p_d *out) { + memset(out, 0, sizeof(*out)); + unmarshal_4(ctx, &out->len); + out->dat = ctx->extra; + ctx->extra += sizeof(out->dat[0]) * out->len; + for (typeof(out->len) i = 0; i < out->len; i++) + unmarshal_1(ctx, (uint8_t *)&out->dat[i]); +} + +static ALWAYS_INLINE void unmarshal_s(struct _unmarshal_ctx *ctx, struct lib9p_s *out) { + memset(out, 0, sizeof(*out)); + unmarshal_2(ctx, &out->len); + out->utf8 = ctx->extra; + ctx->extra += sizeof(out->utf8[0]) * out->len; + for (typeof(out->len) i = 0; i < out->len; i++) + unmarshal_1(ctx, (uint8_t *)&out->utf8[i]); + ctx->extra++; + out->utf8[out->len] = '\0'; +} + +static ALWAYS_INLINE void unmarshal_dm(struct _unmarshal_ctx *ctx, lib9p_dm_t *out) { + unmarshal_4(ctx, (uint32_t *)out); +} + +static ALWAYS_INLINE void unmarshal_qt(struct _unmarshal_ctx *ctx, lib9p_qt_t *out) { + unmarshal_1(ctx, (uint8_t *)out); +} + +static ALWAYS_INLINE void unmarshal_qid(struct _unmarshal_ctx *ctx, struct lib9p_qid *out) { + memset(out, 0, sizeof(*out)); + unmarshal_qt(ctx, &out->type); + unmarshal_4(ctx, &out->vers); + unmarshal_8(ctx, &out->path); +} + +static ALWAYS_INLINE void unmarshal_stat(struct _unmarshal_ctx *ctx, struct lib9p_stat *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 2; + unmarshal_2(ctx, &out->kern_type); + unmarshal_4(ctx, &out->kern_dev); + unmarshal_qid(ctx, &out->file_qid); + unmarshal_dm(ctx, &out->file_mode); + unmarshal_4(ctx, &out->file_atime); + unmarshal_4(ctx, &out->file_mtime); + unmarshal_8(ctx, &out->file_size); + unmarshal_s(ctx, &out->file_name); + unmarshal_s(ctx, &out->file_owner_uid); + unmarshal_s(ctx, &out->file_owner_gid); + unmarshal_s(ctx, &out->file_last_modified_uid); +#if defined(CONFIG_9P_ENABLE_9P2000_u) + if ( (ctx->ctx->version==LIB9P_VER_9P2000_u) ) unmarshal_s(ctx, &out->file_extension); + if ( (ctx->ctx->version==LIB9P_VER_9P2000_u) ) unmarshal_4(ctx, &out->file_owner_n_uid); + if ( (ctx->ctx->version==LIB9P_VER_9P2000_u) ) unmarshal_4(ctx, &out->file_owner_n_gid); + if ( (ctx->ctx->version==LIB9P_VER_9P2000_u) ) unmarshal_4(ctx, &out->file_last_modified_n_uid); +#endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ +} + +static ALWAYS_INLINE void unmarshal_o(struct _unmarshal_ctx *ctx, lib9p_o_t *out) { + unmarshal_1(ctx, (uint8_t *)out); +} + +static FLATTEN void unmarshal_Tversion(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tversion *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_4(ctx, &out->max_msg_size); + unmarshal_s(ctx, &out->version); +} + +static FLATTEN void unmarshal_Rversion(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rversion *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_4(ctx, &out->max_msg_size); + unmarshal_s(ctx, &out->version); +} + +static FLATTEN void unmarshal_Tauth(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tauth *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->afid); + unmarshal_s(ctx, &out->uname); + unmarshal_s(ctx, &out->aname); +#if defined(CONFIG_9P_ENABLE_9P2000_u) + if ( (ctx->ctx->version==LIB9P_VER_9P2000_u) ) unmarshal_4(ctx, &out->n_uname); +#endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ +} + +static FLATTEN void unmarshal_Rauth(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rauth *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_qid(ctx, &out->aqid); +} + +static FLATTEN void unmarshal_Tattach(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tattach *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); + unmarshal_fid(ctx, &out->afid); + unmarshal_s(ctx, &out->uname); + unmarshal_s(ctx, &out->aname); +#if defined(CONFIG_9P_ENABLE_9P2000_u) + if ( (ctx->ctx->version==LIB9P_VER_9P2000_u) ) unmarshal_4(ctx, &out->n_uname); +#endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ +} + +static FLATTEN void unmarshal_Rattach(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rattach *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_qid(ctx, &out->qid); +} + +static FLATTEN void unmarshal_Rerror(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rerror *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_s(ctx, &out->ename); +#if defined(CONFIG_9P_ENABLE_9P2000_u) + if ( (ctx->ctx->version==LIB9P_VER_9P2000_u) ) unmarshal_4(ctx, &out->errno); +#endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ +} + +static FLATTEN void unmarshal_Tflush(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tflush *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_2(ctx, &out->oldtag); +} + +static FLATTEN void unmarshal_Rflush(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rflush *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); +} + +static FLATTEN void unmarshal_Twalk(struct _unmarshal_ctx *ctx, struct lib9p_msg_Twalk *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); + unmarshal_fid(ctx, &out->newfid); + unmarshal_2(ctx, &out->nwname); + out->wname = ctx->extra; + ctx->extra += sizeof(out->wname[0]) * out->nwname; + for (typeof(out->nwname) i = 0; i < out->nwname; i++) + unmarshal_s(ctx, &out->wname[i]); +} + +static FLATTEN void unmarshal_Rwalk(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rwalk *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_2(ctx, &out->nwqid); + out->wqid = ctx->extra; + ctx->extra += sizeof(out->wqid[0]) * out->nwqid; + for (typeof(out->nwqid) i = 0; i < out->nwqid; i++) + unmarshal_qid(ctx, &out->wqid[i]); +} + +static FLATTEN void unmarshal_Topen(struct _unmarshal_ctx *ctx, struct lib9p_msg_Topen *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); + unmarshal_o(ctx, &out->mode); +} + +static FLATTEN void unmarshal_Ropen(struct _unmarshal_ctx *ctx, struct lib9p_msg_Ropen *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_qid(ctx, &out->qid); + unmarshal_4(ctx, &out->iounit); +} + +static FLATTEN void unmarshal_Tcreate(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tcreate *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); + unmarshal_s(ctx, &out->name); + unmarshal_dm(ctx, &out->perm); + unmarshal_o(ctx, &out->mode); +} + +static FLATTEN void unmarshal_Rcreate(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rcreate *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_qid(ctx, &out->qid); + unmarshal_4(ctx, &out->iounit); +} + +static FLATTEN void unmarshal_Tread(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tread *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); + unmarshal_8(ctx, &out->offset); + unmarshal_4(ctx, &out->count); +} + +static FLATTEN void unmarshal_Rread(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rread *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_d(ctx, &out->data); +} + +static FLATTEN void unmarshal_Twrite(struct _unmarshal_ctx *ctx, struct lib9p_msg_Twrite *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); + unmarshal_8(ctx, &out->offset); + unmarshal_d(ctx, &out->data); +} + +static FLATTEN void unmarshal_Rwrite(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rwrite *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_4(ctx, &out->count); +} + +static FLATTEN void unmarshal_Tclunk(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tclunk *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); +} + +static FLATTEN void unmarshal_Rclunk(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rclunk *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); +} + +static FLATTEN void unmarshal_Tremove(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tremove *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); +} + +static FLATTEN void unmarshal_Rremove(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rremove *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); +} - lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "typ value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t)typ, exp); }) +static FLATTEN void unmarshal_Tstat(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tstat *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); +} + +static FLATTEN void unmarshal_Rstat(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rstat *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + ctx->net_offset += 2; + unmarshal_stat(ctx, &out->stat); +} + +static FLATTEN void unmarshal_Twstat(struct _unmarshal_ctx *ctx, struct lib9p_msg_Twstat *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_fid(ctx, &out->fid); + ctx->net_offset += 2; + unmarshal_stat(ctx, &out->stat); +} + +static FLATTEN void unmarshal_Rwstat(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rwstat *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); +} + +#endif /* defined(CONFIG_9P_ENABLE_9P2000) || defined(CONFIG_9P_ENABLE_9P2000_e) || defined(CONFIG_9P_ENABLE_9P2000_u) */ +#if defined(CONFIG_9P_ENABLE_9P2000_e) +static FLATTEN void unmarshal_Tsession(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tsession *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_8(ctx, &out->key); +} + +static FLATTEN void unmarshal_Rsession(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rsession *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); +} + +static FLATTEN void unmarshal_Tsread(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tsread *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_4(ctx, &out->fid); + unmarshal_2(ctx, &out->nwname); + out->wname = ctx->extra; + ctx->extra += sizeof(out->wname[0]) * out->nwname; + for (typeof(out->nwname) i = 0; i < out->nwname; i++) + unmarshal_s(ctx, &out->wname[i]); +} + +static FLATTEN void unmarshal_Rsread(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rsread *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_d(ctx, &out->data); +} + +static FLATTEN void unmarshal_Tswrite(struct _unmarshal_ctx *ctx, struct lib9p_msg_Tswrite *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_4(ctx, &out->fid); + unmarshal_2(ctx, &out->nwname); + out->wname = ctx->extra; + ctx->extra += sizeof(out->wname[0]) * out->nwname; + for (typeof(out->nwname) i = 0; i < out->nwname; i++) + unmarshal_s(ctx, &out->wname[i]); + unmarshal_d(ctx, &out->data); +} + +static FLATTEN void unmarshal_Rswrite(struct _unmarshal_ctx *ctx, struct lib9p_msg_Rswrite *out) { + memset(out, 0, sizeof(*out)); + ctx->net_offset += 4; + ctx->net_offset += 1; + unmarshal_tag(ctx, &out->tag); + unmarshal_4(ctx, &out->count); +} +#endif /* defined(CONFIG_9P_ENABLE_9P2000_e) */ + +/* marshal_* ******************************************************************/ + +static ALWAYS_INLINE bool _marshal_too_large(struct _marshal_ctx *ctx) { + lib9p_errorf(ctx->ctx, LINUX_ERANGE, "%s too large to marshal into %s limit (limit=%"PRIu32")", + (ctx->net_bytes[4] % 2 == 0) ? "T-message" : "R-message", + ctx->ctx->version ? "negotiated" : ((ctx->net_bytes[4] % 2 == 0) ? "client" : "server"), + ctx->ctx->max_msg_size); + return true; +} + +static ALWAYS_INLINE bool marshal_1(struct _marshal_ctx *ctx, uint8_t *val) { + if (ctx->net_offset + 1 > ctx->ctx->max_msg_size) + return _marshal_too_large(ctx); + ctx->net_bytes[ctx->net_offset] = *val; + ctx->net_offset += 1; + return false; +} + +static ALWAYS_INLINE bool marshal_2(struct _marshal_ctx *ctx, uint16_t *val) { + if (ctx->net_offset + 2 > ctx->ctx->max_msg_size) + return _marshal_too_large(ctx); + encode_u16le(*val, &ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 2; + return false; +} + +static ALWAYS_INLINE bool marshal_4(struct _marshal_ctx *ctx, uint32_t *val) { + if (ctx->net_offset + 4 > ctx->ctx->max_msg_size) + return true; + encode_u32le(*val, &ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 4; + return false; +} + +static ALWAYS_INLINE bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) { + if (ctx->net_offset + 8 > ctx->ctx->max_msg_size) + return true; + encode_u64le(*val, &ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 8; + return false; +} + +#if defined(CONFIG_9P_ENABLE_9P2000) || defined(CONFIG_9P_ENABLE_9P2000_e) || defined(CONFIG_9P_ENABLE_9P2000_u) +static ALWAYS_INLINE bool marshal_tag(struct _marshal_ctx *ctx, lib9p_tag_t *val) { + return marshal_2(ctx, (uint16_t *)val); +} + +static ALWAYS_INLINE bool marshal_fid(struct _marshal_ctx *ctx, lib9p_fid_t *val) { + return marshal_4(ctx, (uint32_t *)val); +} + +static ALWAYS_INLINE bool marshal_d(struct _marshal_ctx *ctx, struct lib9p_d *val) { + return false + || marshal_4(ctx, &val->len) + || ({ bool err = false; + for (typeof(val->len) i = 0; i < val->len && !err; i++) + err = marshal_1(ctx, (uint8_t *)&val->dat[i]); + err; }) + ; +} + +static ALWAYS_INLINE bool marshal_s(struct _marshal_ctx *ctx, struct lib9p_s *val) { + return false + || marshal_2(ctx, &val->len) + || ({ bool err = false; + for (typeof(val->len) i = 0; i < val->len && !err; i++) + err = marshal_1(ctx, (uint8_t *)&val->utf8[i]); + err; }) + ; +} + +static ALWAYS_INLINE bool marshal_dm(struct _marshal_ctx *ctx, lib9p_dm_t *val) { + lib9p_dm_t masked_val = *val & dm_masks[ctx->ctx->version]; + return marshal_4(ctx, (uint32_t *)&masked_val); +} + +static ALWAYS_INLINE bool marshal_qt(struct _marshal_ctx *ctx, lib9p_qt_t *val) { + lib9p_qt_t masked_val = *val & qt_masks[ctx->ctx->version]; + return marshal_1(ctx, (uint8_t *)&masked_val); +} + +static ALWAYS_INLINE bool marshal_qid(struct _marshal_ctx *ctx, struct lib9p_qid *val) { + return false + || marshal_qt(ctx, &val->type) + || marshal_4(ctx, &val->vers) + || marshal_8(ctx, &val->path) + ; +} + +static ALWAYS_INLINE bool marshal_stat(struct _marshal_ctx *ctx, struct lib9p_stat *val) { + uint32_t _stat_size_offset; + + uint32_t _kern_type_offset; return false + || ({ _stat_size_offset = ctx->net_offset; ({ ctx->net_offset += 2; false; }); }) + || ({ _kern_type_offset = ctx->net_offset; marshal_2(ctx, &val->kern_type); }) + || marshal_4(ctx, &val->kern_dev) + || marshal_qid(ctx, &val->file_qid) + || marshal_dm(ctx, &val->file_mode) + || marshal_4(ctx, &val->file_atime) + || marshal_4(ctx, &val->file_mtime) + || marshal_8(ctx, &val->file_size) + || marshal_s(ctx, &val->file_name) + || marshal_s(ctx, &val->file_owner_uid) + || marshal_s(ctx, &val->file_owner_gid) + || marshal_s(ctx, &val->file_last_modified_uid) +#if defined(CONFIG_9P_ENABLE_9P2000_u) + || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_s(ctx, &val->file_extension) ) + || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->file_owner_n_uid) ) + || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->file_owner_n_gid) ) + || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->file_last_modified_n_uid) ) +#endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ + || ({ encode_u16le(ctx->net_offset - _kern_type_offset, &ctx->net_bytes[_stat_size_offset]); false; }) + ; +} + +static ALWAYS_INLINE bool marshal_o(struct _marshal_ctx *ctx, lib9p_o_t *val) { + lib9p_o_t masked_val = *val & o_masks[ctx->ctx->version]; + return marshal_1(ctx, (uint8_t *)&masked_val); +} + +static FLATTEN bool marshal_Tversion(struct _marshal_ctx *ctx, struct lib9p_msg_Tversion *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_4(ctx, &val->max_msg_size) + || marshal_s(ctx, &val->version) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(100, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rversion(struct _marshal_ctx *ctx, struct lib9p_msg_Rversion *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_4(ctx, &val->max_msg_size) + || marshal_s(ctx, &val->version) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(101, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tauth(struct _marshal_ctx *ctx, struct lib9p_msg_Tauth *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->afid) + || marshal_s(ctx, &val->uname) + || marshal_s(ctx, &val->aname) +#if defined(CONFIG_9P_ENABLE_9P2000_u) + || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->n_uname) ) +#endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(102, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rauth(struct _marshal_ctx *ctx, struct lib9p_msg_Rauth *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_qid(ctx, &val->aqid) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(103, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tattach(struct _marshal_ctx *ctx, struct lib9p_msg_Tattach *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || marshal_fid(ctx, &val->afid) + || marshal_s(ctx, &val->uname) + || marshal_s(ctx, &val->aname) +#if defined(CONFIG_9P_ENABLE_9P2000_u) + || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->n_uname) ) +#endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(104, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rattach(struct _marshal_ctx *ctx, struct lib9p_msg_Rattach *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_qid(ctx, &val->qid) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(105, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rerror(struct _marshal_ctx *ctx, struct lib9p_msg_Rerror *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_s(ctx, &val->ename) +#if defined(CONFIG_9P_ENABLE_9P2000_u) + || ( (ctx->ctx->version==LIB9P_VER_9P2000_u) && marshal_4(ctx, &val->errno) ) +#endif /* defined(CONFIG_9P_ENABLE_9P2000_u) */ + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(107, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tflush(struct _marshal_ctx *ctx, struct lib9p_msg_Tflush *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_2(ctx, &val->oldtag) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(108, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rflush(struct _marshal_ctx *ctx, struct lib9p_msg_Rflush *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(109, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Twalk(struct _marshal_ctx *ctx, struct lib9p_msg_Twalk *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || marshal_fid(ctx, &val->newfid) + || marshal_2(ctx, &val->nwname) + || ({ bool err = false; + for (typeof(val->nwname) i = 0; i < val->nwname && !err; i++) + err = marshal_s(ctx, &val->wname[i]); + err; }) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(110, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rwalk(struct _marshal_ctx *ctx, struct lib9p_msg_Rwalk *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_2(ctx, &val->nwqid) + || ({ bool err = false; + for (typeof(val->nwqid) i = 0; i < val->nwqid && !err; i++) + err = marshal_qid(ctx, &val->wqid[i]); + err; }) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(111, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Topen(struct _marshal_ctx *ctx, struct lib9p_msg_Topen *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || marshal_o(ctx, &val->mode) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(112, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Ropen(struct _marshal_ctx *ctx, struct lib9p_msg_Ropen *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_qid(ctx, &val->qid) + || marshal_4(ctx, &val->iounit) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(113, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tcreate(struct _marshal_ctx *ctx, struct lib9p_msg_Tcreate *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || marshal_s(ctx, &val->name) + || marshal_dm(ctx, &val->perm) + || marshal_o(ctx, &val->mode) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(114, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rcreate(struct _marshal_ctx *ctx, struct lib9p_msg_Rcreate *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_qid(ctx, &val->qid) + || marshal_4(ctx, &val->iounit) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(115, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tread(struct _marshal_ctx *ctx, struct lib9p_msg_Tread *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || marshal_8(ctx, &val->offset) + || marshal_4(ctx, &val->count) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(116, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rread(struct _marshal_ctx *ctx, struct lib9p_msg_Rread *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_d(ctx, &val->data) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(117, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Twrite(struct _marshal_ctx *ctx, struct lib9p_msg_Twrite *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || marshal_8(ctx, &val->offset) + || marshal_d(ctx, &val->data) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(118, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rwrite(struct _marshal_ctx *ctx, struct lib9p_msg_Rwrite *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_4(ctx, &val->count) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(119, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tclunk(struct _marshal_ctx *ctx, struct lib9p_msg_Tclunk *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(120, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rclunk(struct _marshal_ctx *ctx, struct lib9p_msg_Rclunk *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(121, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tremove(struct _marshal_ctx *ctx, struct lib9p_msg_Tremove *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(122, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rremove(struct _marshal_ctx *ctx, struct lib9p_msg_Rremove *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(123, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tstat(struct _marshal_ctx *ctx, struct lib9p_msg_Tstat *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(124, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rstat(struct _marshal_ctx *ctx, struct lib9p_msg_Rstat *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + uint32_t _nstat_offset; + + uint32_t _stat_offset; return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || ({ _nstat_offset = ctx->net_offset; ({ ctx->net_offset += 2; false; }); }) + || ({ _stat_offset = ctx->net_offset; marshal_stat(ctx, &val->stat); }) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(125, &ctx->net_bytes[_typ_offset]); false; }) + || ({ encode_u16le(ctx->net_offset - _stat_offset, &ctx->net_bytes[_nstat_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Twstat(struct _marshal_ctx *ctx, struct lib9p_msg_Twstat *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + uint32_t _nstat_offset; + + uint32_t _stat_offset; return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_fid(ctx, &val->fid) + || ({ _nstat_offset = ctx->net_offset; ({ ctx->net_offset += 2; false; }); }) + || ({ _stat_offset = ctx->net_offset; marshal_stat(ctx, &val->stat); }) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(126, &ctx->net_bytes[_typ_offset]); false; }) + || ({ encode_u16le(ctx->net_offset - _stat_offset, &ctx->net_bytes[_nstat_offset]); false; }) ; } + +static FLATTEN bool marshal_Rwstat(struct _marshal_ctx *ctx, struct lib9p_msg_Rwstat *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(127, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +#endif /* defined(CONFIG_9P_ENABLE_9P2000) || defined(CONFIG_9P_ENABLE_9P2000_e) || defined(CONFIG_9P_ENABLE_9P2000_u) */ +#if defined(CONFIG_9P_ENABLE_9P2000_e) +static FLATTEN bool marshal_Tsession(struct _marshal_ctx *ctx, struct lib9p_msg_Tsession *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_8(ctx, &val->key) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(150, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rsession(struct _marshal_ctx *ctx, struct lib9p_msg_Rsession *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(151, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tsread(struct _marshal_ctx *ctx, struct lib9p_msg_Tsread *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_4(ctx, &val->fid) + || marshal_2(ctx, &val->nwname) + || ({ bool err = false; + for (typeof(val->nwname) i = 0; i < val->nwname && !err; i++) + err = marshal_s(ctx, &val->wname[i]); + err; }) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(152, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rsread(struct _marshal_ctx *ctx, struct lib9p_msg_Rsread *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_d(ctx, &val->data) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(153, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Tswrite(struct _marshal_ctx *ctx, struct lib9p_msg_Tswrite *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_4(ctx, &val->fid) + || marshal_2(ctx, &val->nwname) + || ({ bool err = false; + for (typeof(val->nwname) i = 0; i < val->nwname && !err; i++) + err = marshal_s(ctx, &val->wname[i]); + err; }) + || marshal_d(ctx, &val->data) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(154, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +static FLATTEN bool marshal_Rswrite(struct _marshal_ctx *ctx, struct lib9p_msg_Rswrite *val) { + uint32_t _size_offset; + uint32_t _typ_offset; + return false + || ({ _size_offset = ctx->net_offset; ({ ctx->net_offset += 4; false; }); }) + || ({ _typ_offset = ctx->net_offset; ({ ctx->net_offset += 1; false; }); }) + || marshal_tag(ctx, &val->tag) + || marshal_4(ctx, &val->count) + || ({ encode_u32le(ctx->net_offset - _size_offset, &ctx->net_bytes[_size_offset]); false; }) + || ({ encode_u8le(155, &ctx->net_bytes[_typ_offset]); false; }) + ; +} + +/* vtables ********************************************************************/ + +#define _MSG(typ) [LIB9P_TYP_##typ] = { \ + .basesize = sizeof(struct lib9p_msg_##typ), \ + .validate = validate_##typ, \ + .unmarshal = (_unmarshal_fn_t)unmarshal_##typ, \ + .marshal = (_marshal_fn_t)marshal_##typ, \ + } + +struct _vtable_version _lib9p_vtables[LIB9P_VER_NUM] = { + [LIB9P_VER_unknown] = { .msgs = { + _MSG(Tversion), + _MSG(Rversion), + _MSG(Rerror), + }}, #endif /* defined(CONFIG_9P_ENABLE_9P2000_e) */ +#if defined(CONFIG_9P_ENABLE_9P2000) + [LIB9P_VER_9P2000] = { .msgs = { + _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 /* defined(CONFIG_9P_ENABLE_9P2000) */ +#if defined(CONFIG_9P_ENABLE_9P2000_e) + [LIB9P_VER_9P2000_e] = { .msgs = { + _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 /* defined(CONFIG_9P_ENABLE_9P2000_e) */ +#if defined(CONFIG_9P_ENABLE_9P2000_u) + [LIB9P_VER_9P2000_u] = { .msgs = { + _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 /* defined(CONFIG_9P_ENABLE_9P2000_u) */ +}; diff --git a/lib9p/idl.gen b/lib9p/idl.gen index 1f5e48c..8e7639a 100755 --- a/lib9p/idl.gen +++ b/lib9p/idl.gen @@ -17,6 +17,7 @@ from typing import Callable, Final, Literal, TypeAlias, TypeVar, cast # Types ######################################################################## + class Primitive(enum.Enum): u8 = 1 u16 = 2 @@ -128,7 +129,7 @@ class StructMember: # from left-to-right when parsing cnt: str | None = None name: str - typ: 'Type' + typ: "Type" max: Expr val: Expr @@ -174,7 +175,7 @@ class Message(Struct): Type: TypeAlias = Primitive | Number | Bitfield | Struct | Message -#type Type = Primitive | Number | Bitfield | Struct | Message # Change to this once we have Python 3.13 +# type Type = Primitive | Number | Bitfield | Struct | Message # Change to this once we have Python 3.13 T = TypeVar("T", Number, Bitfield, Struct, Message) # Parse *.9p ################################################################### @@ -234,6 +235,8 @@ def parse_expr(expr: str) -> Expr: ret = Expr() for tok in re.split("([-+])", expr): if tok == "-" or tok == "+": + # I, for the life of me, do not understand why I need this + # cast() to keep mypy happy. ret.tokens += [ExprOp(cast(Literal["-", "+"], tok))] elif re.fullmatch("[0-9]+", tok): ret.tokens += [ExprLit(int(tok))] @@ -451,8 +454,10 @@ def parse_file( # Generate C ################################################################### +idprefix = "lib9p_" + -def c_ver_enum(idprefix: str, ver: str) -> str: +def c_ver_enum(ver: str) -> str: return f"{idprefix.upper()}VER_{ver.replace('.', '_')}" @@ -462,15 +467,13 @@ def c_ver_ifdef(versions: set[str]) -> str: ) -def c_ver_cond(idprefix: str, versions: set[str]) -> str: +def c_ver_cond(versions: set[str]) -> str: if len(versions) == 1: - return f"(ctx->ctx->version=={c_ver_enum(idprefix, next(v for v in versions))})" - return ( - "( " + (" || ".join(c_ver_cond(idprefix, {v}) for v in sorted(versions))) + " )" - ) + return f"(ctx->ctx->version=={c_ver_enum(next(v for v in versions))})" + return "( " + (" || ".join(c_ver_cond({v}) for v in sorted(versions))) + " )" -def c_typename(idprefix: str, typ: Type) -> str: +def c_typename(typ: Type) -> str: match typ: case Primitive(): return f"uint{typ.value*8}_t" @@ -517,6 +520,7 @@ def ifdef_push(n: int, _newval: str) -> str: ret += f"#if {newval}\n" return ret + def ifdef_pop(n: int) -> str: global _ifdef_stack ret = "" @@ -527,7 +531,7 @@ def ifdef_pop(n: int) -> str: return ret -def gen_h(idprefix: str, versions: set[str], typs: list[Type]) -> str: +def gen_h(versions: set[str], typs: list[Type]) -> str: global _ifdef_stack _ifdef_stack = [] @@ -550,10 +554,10 @@ enum {idprefix}version {{ for ver in fullversions: if ver in versions: ret += ifdef_push(1, c_ver_ifdef({ver})) - ret += f"\t{c_ver_enum(idprefix, ver)}," + ret += f"\t{c_ver_enum(ver)}," ret += (" " * (verwidth - len(ver))) + ' /* "' + ver.split()[0] + '" */\n' ret += ifdef_pop(0) - ret += f"\t{c_ver_enum(idprefix, 'NUM')},\n" + ret += f"\t{c_ver_enum('NUM')},\n" ret += "};\n" ret += "\n" ret += f"const char *{idprefix}version_str(enum {idprefix}version);\n" @@ -566,9 +570,9 @@ enum {idprefix}version {{ ret += ifdef_push(1, c_ver_ifdef(typ.in_versions)) match typ: case Number(): - ret += f"typedef {c_typename(idprefix, typ.prim)} {c_typename(idprefix, typ)};\n" + ret += f"typedef {c_typename(typ.prim)} {c_typename(typ)};\n" case Bitfield(): - ret += f"typedef {c_typename(idprefix, typ.prim)} {c_typename(idprefix, typ)};\n" + ret += f"typedef {c_typename(typ.prim)} {c_typename(typ)};\n" names = [ *reversed( [typ.bits[n] or f" {n}" for n in range(0, len(typ.bits))] @@ -584,28 +588,36 @@ enum {idprefix}version {{ ret += "\n" elif name.startswith(" "): ret += ifdef_push(2, c_ver_ifdef(typ.in_versions)) - sp = ' '*(len('# define ')+len(idprefix)+len(typ.name)+1+namewidth+2-len("/* unused")) - ret += f"/* unused{sp}(({c_typename(idprefix, typ)})(1<<{name[1:]})) */\n" + sp = " " * ( + len("# define ") + + len(idprefix) + + len(typ.name) + + 1 + + namewidth + + 2 + - len("/* unused") + ) + ret += f"/* unused{sp}(({c_typename(typ)})(1<<{name[1:]})) */\n" else: ret += ifdef_push(2, c_ver_ifdef(typ.names[name].in_versions)) if name.startswith("_"): c_name = f"_{idprefix.upper()}{typ.name.upper()}_{name[1:]}" else: c_name = f"{idprefix.upper()}{typ.name.upper()}_{name}" - sp1 = ' ' if _ifdef_stack[-1] else '' - sp2 = ' ' if _ifdef_stack[-1] else ' ' - sp3 = ' '*(2+namewidth-len(name)) - ret += f"#{sp1}define{sp2}{c_name}{sp3}(({c_typename(idprefix, typ)})({typ.names[name].val}))\n" + sp1 = " " if _ifdef_stack[-1] else "" + sp2 = " " if _ifdef_stack[-1] else " " + sp3 = " " * (2 + namewidth - len(name)) + ret += f"#{sp1}define{sp2}{c_name}{sp3}(({c_typename(typ)})({typ.names[name].val}))\n" ret += ifdef_pop(1) case Struct(): - typewidth = max(len(c_typename(idprefix, m.typ)) for m in typ.members) + typewidth = max(len(c_typename(m.typ)) for m in typ.members) - ret += c_typename(idprefix, typ) + " {\n" + ret += c_typename(typ) + " {\n" for member in typ.members: if member.val: continue ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) - c_type = c_typename(idprefix, member.typ) + c_type = c_typename(member.typ) if (typ.name in ["d", "s"]) and member.cnt: # SPECIAL c_type = "char" ret += f"\t{c_type.ljust(typewidth)} {'*' if member.cnt else ' '}{member.name};\n" @@ -630,19 +642,19 @@ enum {idprefix}version {{ for msg in [msg for msg in typs if isinstance(msg, Message)]: ret += "\n" ret += ifdef_push(1, c_ver_ifdef(msg.in_versions)) - ret += c_typename(idprefix, msg) + " {" + ret += c_typename(msg) + " {" if not msg.members: ret += "};\n" continue ret += "\n" - typewidth = max(len(c_typename(idprefix, m.typ)) for m in msg.members) + typewidth = max(len(c_typename(m.typ)) for m in msg.members) for member in msg.members: if member.val: continue ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) - ret += f"\t{c_typename(idprefix, member.typ).ljust(typewidth)} {'*' if member.cnt else ' '}{member.name};\n" + ret += f"\t{c_typename(member.typ).ljust(typewidth)} {'*' if member.cnt else ' '}{member.name};\n" ret += ifdef_pop(1) ret += "};\n" ret += ifdef_pop(0) @@ -665,7 +677,7 @@ def c_expr(expr: Expr) -> str: return " ".join(ret) -def gen_c(idprefix: str, versions: set[str], typs: list[Type]) -> str: +def gen_c(versions: set[str], typs: list[Type]) -> str: global _ifdef_stack _ifdef_stack = [] @@ -692,17 +704,17 @@ def gen_c(idprefix: str, versions: set[str], typs: list[Type]) -> str: ret += f""" /* strings ********************************************************************/ -static const char *version_strs[{c_ver_enum(idprefix, 'NUM')}] = {{ +static const char *version_strs[{c_ver_enum('NUM')}] = {{ """ for ver in ["unknown", *sorted(versions)]: if ver in versions: ret += ifdef_push(1, c_ver_ifdef({ver})) - ret += f'\t[{c_ver_enum(idprefix, ver)}] = "{ver}",\n' + ret += f'\t[{c_ver_enum(ver)}] = "{ver}",\n' ret += ifdef_pop(0) ret += "};\n" ret += f""" const char *{idprefix}version_str(enum {idprefix}version ver) {{ - assert(0 <= ver && ver < {c_ver_enum(idprefix, 'NUM')}); + assert(0 <= ver && ver < {c_ver_enum('NUM')}); return version_strs[ver]; }} @@ -764,6 +776,23 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx, argfn = unused if (isinstance(typ, Struct) and not typ.members) else used ret += "\n" ret += ifdef_push(1, c_ver_ifdef(typ.in_versions)) + + if isinstance(typ, Bitfield): + ret += f"static const {c_typename(typ)} {typ.name}_masks[{c_ver_enum('NUM')}] = {{\n" + verwidth = max(len(ver) for ver in versions) + for ver in sorted(versions): + ret += ifdef_push(2, c_ver_ifdef({ver})) + ret += ( + f"\t[{c_ver_enum(ver)}]{' '*(verwidth-len(ver))} = 0b" + + "".join( + "1" if typ.bit_is_valid(bitname, ver) else "0" + for bitname in reversed(typ.bits) + ) + + ",\n" + ) + ret += ifdef_pop(1) + ret += "};\n" + ret += f"static {inline} bool validate_{typ.name}(struct _validate_ctx *{argfn('ctx')}) {{\n" if typ.name == "d": # SPECIAL @@ -797,28 +826,12 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx, case Bitfield(): ret += f"\t if (validate_{typ.static_size}(ctx))\n" ret += "\t\treturn true;\n" - ret += f"\tstatic const {c_typename(idprefix, typ)} masks[{c_ver_enum(idprefix, 'NUM')}] = {{\n" - verwidth = max(len(ver) for ver in versions) - for ver in sorted(versions): - ret += ifdef_push(2, c_ver_ifdef({ver})) - ret += ( - f"\t\t[{c_ver_enum(idprefix, ver)}]{' '*(verwidth-len(ver))} = 0b" - + "".join( - "1" if typ.bit_is_valid(bitname, ver) else "0" - for bitname in reversed(typ.bits) - ) - + ",\n" - ) - ret += ifdef_pop(1) - ret += "\t};\n" ret += ( - f"\t{c_typename(idprefix, typ)} mask = masks[ctx->ctx->version];\n" + f"\t{c_typename(typ)} mask = {typ.name}_masks[ctx->ctx->version];\n" ) - ret += f"\t{c_typename(idprefix, typ)} val = decode_u{typ.static_size*8}le(&ctx->net_bytes[ctx->net_offset-{typ.static_size}]);\n" + ret += f"\t{c_typename(typ)} val = decode_u{typ.static_size*8}le(&ctx->net_bytes[ctx->net_offset-{typ.static_size}]);\n" ret += f"\tif (val & ~mask)\n" - ret += "\t\treturn lib9p_errorf(ctx->ctx,\n" - ret += f'\t\t LINUX_EBADMSG, "unknown bits in {typ.name} bitfield: %#0{typ.static_size}"PRIx{typ.static_size*8},\n' - ret += "\t\t val & ~mask);\n" + ret += f'\t\treturn lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "unknown bits in {typ.name} bitfield: %#0{typ.static_size}"PRIx{typ.static_size*8}, val & ~mask);\n' ret += "\treturn false;\n" case Struct(): # and Message() if len(typ.members) == 0: @@ -826,14 +839,14 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx, ret += "}\n" continue - # Pass 1 + # Pass 1 - declare value variables for member in typ.members: if member.max or member.val: ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) - ret += f"\t{c_typename(idprefix, member.typ)} {member.name};\n" + ret += f"\t{c_typename(member.typ)} {member.name};\n" ret += ifdef_pop(1) - # Pass 2 + # Pass 2 - declare offset variables mark_offset: set[str] = set() for member in typ.members: for tok in [*member.max.tokens, *member.val.tokens]: @@ -842,17 +855,17 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx, ret += f"\tuint32_t _{tok.name[1:]}_offset;\n" mark_offset.add(tok.name[1:]) - # Pass 3 + # Pass 3 - main pass ret += "\treturn false\n" prev_size: int | None = None for member in typ.members: ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) ret += f"\t || " if member.in_versions != typ.in_versions: - ret += "( " + c_ver_cond(idprefix, member.in_versions) + " && " + ret += "( " + c_ver_cond(member.in_versions) + " && " if member.cnt is not None: assert prev_size - ret += f"_validate_list(ctx, decode_u{prev_size*8}le(&ctx->net_bytes[ctx->net_offset-{prev_size}]), validate_{member.typ.name}, sizeof({c_typename(idprefix, member.typ)}))" + ret += f"_validate_list(ctx, decode_u{prev_size*8}le(&ctx->net_bytes[ctx->net_offset-{prev_size}]), validate_{member.typ.name}, sizeof({c_typename(member.typ)}))" else: if member.max or member.val: ret += "(" @@ -871,252 +884,244 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx, ret += "\n" prev_size = member.static_size - # Pass 4 + # Pass 4 - validate ,max= and ,val= constraints for member in typ.members: if member.max: ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) - ret += f"\n\t || ({{ uint32_t max = {c_expr(member.max)}; (((uint32_t){member.name}) > max) &&\n" - ret += f'\n\t lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "{member.name} value too large (%"PRIu32" > %"PRIu32")", {member.name}, max); }})\n' + ret += f"\t || ({{ uint32_t max = {c_expr(member.max)}; (((uint32_t){member.name}) > max) &&\n" + ret += f'\t lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "{member.name} value is too large (%"PRIu32" > %"PRIu32")", {member.name}, max); }})\n' if member.val: ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) - ret += f"\n\t || ({{ uint32_t exp = {c_expr(member.val)}; (((uint32_t){member.name}) != exp) &&\n" - ret += f'\n\t lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "{member.name} value wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t){member.name}, exp); }})\n' + ret += f"\t || ({{ uint32_t exp = {c_expr(member.val)}; (((uint32_t){member.name}) != exp) &&\n" + ret += f'\t lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "{member.name} value is wrong (actual:%"PRIu32" != correct:%"PRIu32")", (uint32_t){member.name}, exp); }})\n' ret += ifdef_pop(1) ret += "\t ;\n" ret += "}\n" ret += ifdef_pop(0) - # # unmarshal_* ############################################################## - # ret += """ - # /* unmarshal_* ****************************************************************/ - - # static ALWAYS_INLINE void unmarshal_1(struct _unmarshal_ctx *ctx, uint8_t *out) { - # *out = decode_u8le(&ctx->net_bytes[ctx->net_offset]); - # ctx->net_offset += 1; - # } - - # static ALWAYS_INLINE void unmarshal_2(struct _unmarshal_ctx *ctx, uint16_t *out) { - # *out = decode_u16le(&ctx->net_bytes[ctx->net_offset]); - # ctx->net_offset += 2; - # } - - # static ALWAYS_INLINE void unmarshal_4(struct _unmarshal_ctx *ctx, uint32_t *out) { - # *out = decode_u32le(&ctx->net_bytes[ctx->net_offset]); - # ctx->net_offset += 4; - # } - - # static ALWAYS_INLINE void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *out) { - # *out = decode_u64le(&ctx->net_bytes[ctx->net_offset]); - # ctx->net_offset += 8; - # } - # """ - # for typ in typs: - # inline = ( - # " FLATTEN" - # if (isinstance(typ, Struct) and typ.msgid is not None) - # else " ALWAYS_INLINE" - # ) - # argfn = unused if (isinstance(typ, Struct) and not typ.members) else used - # ret += "\n" - # ret += f"static{inline} void unmarshal_{typ.name}(struct _unmarshal_ctx *{argfn('ctx')}, {c_typename(idprefix, typ)} *out) {{\n" - # match typ: - # case Bitfield(): - # ret += f"\tunmarshal_{typ.static_size}(ctx, (uint{typ.static_size*8}_t *)out);\n" - # case Struct(): - # ret += "\tmemset(out, 0, sizeof(*out));\n" - - # if typ.members: - # struct_versions = typ.members[0].ver - # for member in typ.members: - # if member.valexpr: - # ret += f"\tctx->net_offset += {member.static_size};\n" - # continue - # ret += "\t" - # prefix = "\t" - # if member.ver != struct_versions: - # ret += "if ( " + c_ver_cond(idprefix, member.ver) + " ) " - # prefix = "\t\t" - # if member.cnt: - # if member.ver != struct_versions: - # ret += f"{{\n{prefix}" - # ret += f"out->{member.name} = ctx->extra;\n" - # ret += f"{prefix}ctx->extra += sizeof(out->{member.name}[0]) * out->{member.cnt};\n" - # ret += f"{prefix}for (typeof(out->{member.cnt}) i = 0; i < out->{member.cnt}; i++)\n" - # if typ.name in ["d", "s"]: # SPECIAL - # ret += f"{prefix}\tunmarshal_{member.typ.name}(ctx, (uint8_t *)&out->{member.name}[i]);\n" - # else: - # ret += f"{prefix}\tunmarshal_{member.typ.name}(ctx, &out->{member.name}[i]);\n" - # if member.ver != struct_versions: - # ret += "\t}\n" - # else: - # ret += ( - # f"unmarshal_{member.typ.name}(ctx, &out->{member.name});\n" - # ) - # if typ.name == "s": # SPECIAL - # ret += "\tctx->extra++;\n" - # ret += "\tout->utf8[out->len] = '\\0';\n" - # ret += "}\n" - - # # marshal_* ################################################################ - # ret += """ - # /* marshal_* ******************************************************************/ - - # static ALWAYS_INLINE bool _marshal_too_large(struct _marshal_ctx *ctx) { - # lib9p_errorf(ctx->ctx, LINUX_ERANGE, "%s too large to marshal into %s limit (limit=%"PRIu32")", - # (ctx->net_bytes[4] % 2 == 0) ? "T-message" : "R-message", - # ctx->ctx->version ? "negotiated" : ((ctx->net_bytes[4] % 2 == 0) ? "client" : "server"), - # ctx->ctx->max_msg_size); - # return true; - # } - - # static ALWAYS_INLINE bool marshal_1(struct _marshal_ctx *ctx, uint8_t *val) { - # if (ctx->net_offset + 1 > ctx->ctx->max_msg_size) - # return _marshal_too_large(ctx); - # ctx->net_bytes[ctx->net_offset] = *val; - # ctx->net_offset += 1; - # return false; - # } - - # static ALWAYS_INLINE bool marshal_2(struct _marshal_ctx *ctx, uint16_t *val) { - # if (ctx->net_offset + 2 > ctx->ctx->max_msg_size) - # return _marshal_too_large(ctx); - # encode_u16le(*val, &ctx->net_bytes[ctx->net_offset]); - # ctx->net_offset += 2; - # return false; - # } - - # static ALWAYS_INLINE bool marshal_4(struct _marshal_ctx *ctx, uint32_t *val) { - # if (ctx->net_offset + 4 > ctx->ctx->max_msg_size) - # return true; - # encode_u32le(*val, &ctx->net_bytes[ctx->net_offset]); - # ctx->net_offset += 4; - # return false; - # } - - # static ALWAYS_INLINE bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) { - # if (ctx->net_offset + 8 > ctx->ctx->max_msg_size) - # return true; - # encode_u64le(*val, &ctx->net_bytes[ctx->net_offset]); - # ctx->net_offset += 8; - # return false; - # } - # """ - # for typ in typs: - # inline = ( - # " FLATTEN" - # if (isinstance(typ, Struct) and typ.msgid is not None) - # else " ALWAYS_INLINE" - # ) - # argfn = unused if (isinstance(typ, Struct) and not typ.members) else used - # ret += "\n" - # ret += f"static{inline} bool marshal_{typ.name}(struct _marshal_ctx *{argfn('ctx')}, {c_typename(idprefix, typ)} *{argfn('val')}) {{" - # match typ: - # case Bitfield(): - # ret += "\n" - # ret += f"\treturn marshal_{typ.static_size}(ctx, (uint{typ.static_size*8}_t *)val);\n" - # case Struct(): - # if len(typ.members) == 0: - # ret += "\n\treturn false;\n" - # ret += "}\n" - # continue - - # mark_offset = set() - # for member in typ.members: - # if member.valexpr: - # if member.name not in mark_offset: - # ret += f"\n\tuint32_t _{member.name}_offset;" - # mark_offset.add(member.name) - # for tok in member.valexpr: - # if ( - # isinstance(tok, ExprVal) - # and tok.name.startswith("&") - # and tok.name[1:] not in mark_offset - # ): - # ret += f"\n\tuint32_t _{tok.name[1:]}_offset;" - # mark_offset.add(tok.name[1:]) - - # prefix0 = "\treturn " - # prefix1 = "\t || " - # prefix2 = "\t " - - # struct_versions = typ.members[0].ver - # prefix = prefix0 - # for member in typ.members: - # ret += f"\n{prefix}" - # if member.ver != struct_versions: - # ret += "( " + c_ver_cond(idprefix, member.ver) + " && " - # if member.name in mark_offset: - # ret += f"({{ _{member.name}_offset = ctx->net_offset; " - # if member.cnt: - # ret += "({" - # ret += f"\n{prefix2}\tbool err = false;" - # ret += f"\n{prefix2}\tfor (typeof(val->{member.cnt}) i = 0; i < val->{member.cnt} && !err; i++)" - # if typ.name in ["d", "s"]: # SPECIAL - # ret += f"\n{prefix2}\t\terr = marshal_{member.typ.name}(ctx, (uint8_t *)&val->{member.name}[i]);" - # else: - # ret += f"\n{prefix2}\t\terr = marshal_{member.typ.name}(ctx, &val->{member.name}[i]);" - # ret += f"\n{prefix2}\terr;" - # ret += f"\n{prefix2}}})" - # elif member.valexpr: - # assert member.static_size - # ret += ( - # f"({{ ctx->net_offset += {member.static_size}; false; }})" - # ) - # else: - # ret += f"marshal_{member.typ.name}(ctx, &val->{member.name})" - # if member.name in mark_offset: - # ret += "; })" - # if member.ver != struct_versions: - # ret += " )" - # prefix = prefix1 - - # for member in typ.members: - # if member.valexpr: - # assert member.static_size - # ret += f"\n{prefix}" - # ret += f"({{ encode_u{member.static_size*8}le(" - # for tok in member.valexpr: - # match tok: - # case ExprOp(): - # ret += f" {tok.op}" - # case ExprVal(name="end"): - # ret += " ctx->net_offset" - # case ExprVal(): - # ret += f" _{tok.name[1:]}_offset" - # ret += f", &ctx->net_bytes[_{member.name}_offset]); false; }})" - - # ret += ";\n" - # ret += "}\n" - - # # vtables ################################################################## - # ret += f""" - # /* vtables ********************************************************************/ - - # #define _MSG(typ) [{idprefix.upper()}TYP_##typ] = {{ \\ - # .basesize = sizeof(struct {idprefix}msg_##typ), \\ - # .validate = validate_##typ, \\ - # .unmarshal = (_unmarshal_fn_t)unmarshal_##typ, \\ - # .marshal = (_marshal_fn_t)marshal_##typ, \\ - # }} - - # struct _vtable_version _{idprefix}vtables[{c_ver_enum(idprefix, 'NUM')}] = {{ - # """ - - # ret += f"\t[{c_ver_enum(idprefix, 'unknown')}] = {{ .msgs = {{\n" - # for msg in just_structs_msg(typs): - # if msg.name in ["Tversion", "Rversion", "Rerror"]: # SPECIAL - # ret += f"\t\t_MSG({msg.name}),\n" - # ret += "\t}},\n" - - # for ver in sorted(versions): - # ret += f"\t[{c_ver_enum(idprefix, ver)}] = {{ .msgs = {{\n" - # for msg in just_structs_msg(typs): - # if ver not in msg.msgver: - # continue - # ret += f"\t\t_MSG({msg.name}),\n" - # ret += "\t}},\n" - # ret += "};\n" + # unmarshal_* ############################################################## + ret += """ +/* unmarshal_* ****************************************************************/ + +static ALWAYS_INLINE void unmarshal_1(struct _unmarshal_ctx *ctx, uint8_t *out) { + *out = decode_u8le(&ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 1; +} + +static ALWAYS_INLINE void unmarshal_2(struct _unmarshal_ctx *ctx, uint16_t *out) { + *out = decode_u16le(&ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 2; +} + +static ALWAYS_INLINE void unmarshal_4(struct _unmarshal_ctx *ctx, uint32_t *out) { + *out = decode_u32le(&ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 4; +} + +static ALWAYS_INLINE void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *out) { + *out = decode_u64le(&ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 8; +} +""" + for typ in typs: + inline = "FLATTEN" if isinstance(typ, Message) else "ALWAYS_INLINE" + argfn = unused if (isinstance(typ, Struct) and not typ.members) else used + ret += "\n" + ret += ifdef_push(1, c_ver_ifdef(typ.in_versions)) + ret += f"static {inline} void unmarshal_{typ.name}(struct _unmarshal_ctx *{argfn('ctx')}, {c_typename(typ)} *out) {{\n" + match typ: + case Number(): + ret += f"\tunmarshal_{typ.prim.name}(ctx, ({c_typename(typ.prim)} *)out);\n" + case Bitfield(): + ret += f"\tunmarshal_{typ.prim.name}(ctx, ({c_typename(typ.prim)} *)out);\n" + case Struct(): + ret += "\tmemset(out, 0, sizeof(*out));\n" + + for member in typ.members: + ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) + if member.val: + ret += f"\tctx->net_offset += {member.static_size};\n" + continue + ret += "\t" + + prefix = "\t" + if member.in_versions != typ.in_versions: + ret += "if ( " + c_ver_cond(member.in_versions) + " ) " + prefix = "\t\t" + if member.cnt: + if member.in_versions != typ.in_versions: + ret += "{\n" + ret += prefix + ret += f"out->{member.name} = ctx->extra;\n" + ret += f"{prefix}ctx->extra += sizeof(out->{member.name}[0]) * out->{member.cnt};\n" + ret += f"{prefix}for (typeof(out->{member.cnt}) i = 0; i < out->{member.cnt}; i++)\n" + if typ.name in ["d", "s"]: # SPECIAL + ret += f"{prefix}\tunmarshal_{member.typ.name}(ctx, (uint8_t *)&out->{member.name}[i]);\n" + else: + ret += f"{prefix}\tunmarshal_{member.typ.name}(ctx, &out->{member.name}[i]);\n" + if member.in_versions != typ.in_versions: + ret += "\t}\n" + else: + ret += ( + f"unmarshal_{member.typ.name}(ctx, &out->{member.name});\n" + ) + if typ.name == "s": # SPECIAL + ret += "\tctx->extra++;\n" + ret += "\tout->utf8[out->len] = '\\0';\n" + ret += ifdef_pop(1) + ret += "}\n" + ret += ifdef_pop(0) + + # marshal_* ################################################################ + ret += """ +/* marshal_* ******************************************************************/ + +static ALWAYS_INLINE bool _marshal_too_large(struct _marshal_ctx *ctx) { + lib9p_errorf(ctx->ctx, LINUX_ERANGE, "%s too large to marshal into %s limit (limit=%"PRIu32")", + (ctx->net_bytes[4] % 2 == 0) ? "T-message" : "R-message", + ctx->ctx->version ? "negotiated" : ((ctx->net_bytes[4] % 2 == 0) ? "client" : "server"), + ctx->ctx->max_msg_size); + return true; +} + +static ALWAYS_INLINE bool marshal_1(struct _marshal_ctx *ctx, uint8_t *val) { + if (ctx->net_offset + 1 > ctx->ctx->max_msg_size) + return _marshal_too_large(ctx); + ctx->net_bytes[ctx->net_offset] = *val; + ctx->net_offset += 1; + return false; +} + +static ALWAYS_INLINE bool marshal_2(struct _marshal_ctx *ctx, uint16_t *val) { + if (ctx->net_offset + 2 > ctx->ctx->max_msg_size) + return _marshal_too_large(ctx); + encode_u16le(*val, &ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 2; + return false; +} + +static ALWAYS_INLINE bool marshal_4(struct _marshal_ctx *ctx, uint32_t *val) { + if (ctx->net_offset + 4 > ctx->ctx->max_msg_size) + return true; + encode_u32le(*val, &ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 4; + return false; +} + +static ALWAYS_INLINE bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) { + if (ctx->net_offset + 8 > ctx->ctx->max_msg_size) + return true; + encode_u64le(*val, &ctx->net_bytes[ctx->net_offset]); + ctx->net_offset += 8; + return false; +} +""" + for typ in typs: + inline = "FLATTEN" if isinstance(typ, Message) else "ALWAYS_INLINE" + argfn = unused if (isinstance(typ, Struct) and not typ.members) else used + ret += "\n" + ret += ifdef_push(1, c_ver_ifdef(typ.in_versions)) + ret += f"static {inline} bool marshal_{typ.name}(struct _marshal_ctx *{argfn('ctx')}, {c_typename(typ)} *{argfn('val')}) {{\n" + match typ: + case Number(): + ret += f"\treturn marshal_{typ.prim.name}(ctx, ({c_typename(typ.prim)} *)val);\n" + case Bitfield(): + ret += f"\t{c_typename(typ)} masked_val = *val & {typ.name}_masks[ctx->ctx->version];\n" + ret += f"\treturn marshal_{typ.prim.name}(ctx, ({c_typename(typ.prim)} *)&masked_val);\n" + case Struct(): + if len(typ.members) == 0: + ret += "\treturn false;\n" + ret += "}\n" + continue + + # Pass 1 - declare offset variables + mark_offset = set() + for member in typ.members: + if member.val: + if member.name not in mark_offset: + ret += f"\tuint32_t _{member.name}_offset;\n" + mark_offset.add(member.name) + for tok in member.val.tokens: + if isinstance(tok, ExprSym) and tok.name.startswith("&"): + if tok.name[1:] not in mark_offset: + ret += f"\n\tuint32_t _{tok.name[1:]}_offset;" + mark_offset.add(tok.name[1:]) + + # Pass 2 - main pass + ret += "\treturn false\n" + for member in typ.members: + ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) + ret += "\t || " + if member.in_versions != typ.in_versions: + ret += "( " + c_ver_cond(member.in_versions) + " && " + if member.name in mark_offset: + ret += f"({{ _{member.name}_offset = ctx->net_offset; " + if member.cnt: + ret += "({ bool err = false;\n" + ret += f"\t for (typeof(val->{member.cnt}) i = 0; i < val->{member.cnt} && !err; i++)\n" + ret += "\t \terr = " + if typ.name in ["d", "s"]: # SPECIAL + # Special-case is that we cast from `char` to `uint8_t`. + ret += f"marshal_{member.typ.name}(ctx, (uint8_t *)&val->{member.name}[i]);\n" + else: + ret += f"marshal_{member.typ.name}(ctx, &val->{member.name}[i]);\n" + ret += f"\t err; }})" + elif member.val: + # Just increment net_offset, don't actually marsha anything (yet). + assert member.static_size + ret += ( + f"({{ ctx->net_offset += {member.static_size}; false; }})" + ) + else: + ret += f"marshal_{member.typ.name}(ctx, &val->{member.name})" + if member.name in mark_offset: + ret += "; })" + if member.in_versions != typ.in_versions: + ret += " )" + ret += "\n" + + # Pass 3 - marshal ,val= members + for member in typ.members: + if member.val: + assert member.static_size + ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) + ret += f"\t || ({{ encode_u{member.static_size*8}le({c_expr(member.val)}, &ctx->net_bytes[_{member.name}_offset]); false; }})\n" + + ret += ifdef_pop(1) + ret += "\t ;\n" + ret += "}\n" + + # vtables ################################################################## + ret += f""" +/* vtables ********************************************************************/ + +#define _MSG(typ) [{idprefix.upper()}TYP_##typ] = {{ \\ + .basesize = sizeof(struct {idprefix}msg_##typ), \\ + .validate = validate_##typ, \\ + .unmarshal = (_unmarshal_fn_t)unmarshal_##typ, \\ + .marshal = (_marshal_fn_t)marshal_##typ, \\ + }} + +struct _vtable_version _{idprefix}vtables[{c_ver_enum('NUM')}] = {{ +""" + + ret += f"\t[{c_ver_enum('unknown')}] = {{ .msgs = {{\n" + for msg in [msg for msg in typs if isinstance(msg, Message)]: + if msg.name in ["Tversion", "Rversion", "Rerror"]: # SPECIAL + ret += f"\t\t_MSG({msg.name}),\n" + ret += "\t}},\n" + + for ver in sorted(versions): + ret += ifdef_push(1, c_ver_ifdef({ver})) + ret += f"\t[{c_ver_enum(ver)}] = {{ .msgs = {{\n" + for msg in [msg for msg in typs if isinstance(msg, Message)]: + if ver not in msg.in_versions: + continue + ret += f"\t\t_MSG({msg.name}),\n" + ret += "\t}},\n" + ret += ifdef_pop(0) + ret += "};\n" ############################################################################ return ret @@ -1165,6 +1170,6 @@ if __name__ == "__main__": 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") as fh: - fh.write(gen_h("lib9p_", versions, typs)) + fh.write(gen_h(versions, typs)) with open(os.path.join(outdir, "9p.generated.c"), "w") as fh: - fh.write(gen_c("lib9p_", versions, typs)) + fh.write(gen_c(versions, typs)) diff --git a/lib9p/idl/00-README.md b/lib9p/idl/00-README.md deleted file mode 100644 index f53acf9..0000000 --- a/lib9p/idl/00-README.md +++ /dev/null @@ -1,48 +0,0 @@ -# 9P protocol definitions - - -This directory contains several `*.9p` files, each of which describes -a 9P protocol variant. - -In the 9P protocol, each message has a type, and message types come -in pairs (except "Rerror"); "T" and "R"; T-messages are -client->server requests, and R-messages are server->client responses -(the client "Transmits" T-messages and "Receives" R-messages). The -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: - - - 1 = u8 - - 2 = u16le - - 4 = u32le - - 8 = u16le - -Out of these primitives, we can make other numeric types, - - num NUMNAME = PRIMITIVE_TYPE - -bitfields, - - bitfield BFNAME = PRIMITIVE_TYPE "NBIT=NAME... ALIAS=VAL..." - -structures, - - struct STRUCTNAME = "FILENAME[FIELDTYPE]..." - -and messages (which are a special-case of structures). - - msg Tname = "size[4,val=end-&size] typ[1,val=TYP] tag[tag] REST..." - -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. - -`,val=` and `,max` take a string of `+`/`-` tokens and values; a value -can either be a decimal numeric constant (eg: `107`), the `&fieldname` -to refer to the offset of a field name in that struct, or the special -value `end` to refer to the offset of the end of the struct. diff --git a/lib9p/idl/0000-README.md b/lib9p/idl/0000-README.md new file mode 100644 index 0000000..f53acf9 --- /dev/null +++ b/lib9p/idl/0000-README.md @@ -0,0 +1,48 @@ +# 9P protocol definitions + + +This directory contains several `*.9p` files, each of which describes +a 9P protocol variant. + +In the 9P protocol, each message has a type, and message types come +in pairs (except "Rerror"); "T" and "R"; T-messages are +client->server requests, and R-messages are server->client responses +(the client "Transmits" T-messages and "Receives" R-messages). The +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: + + - 1 = u8 + - 2 = u16le + - 4 = u32le + - 8 = u16le + +Out of these primitives, we can make other numeric types, + + num NUMNAME = PRIMITIVE_TYPE + +bitfields, + + bitfield BFNAME = PRIMITIVE_TYPE "NBIT=NAME... ALIAS=VAL..." + +structures, + + struct STRUCTNAME = "FILENAME[FIELDTYPE]..." + +and messages (which are a special-case of structures). + + msg Tname = "size[4,val=end-&size] typ[1,val=TYP] tag[tag] REST..." + +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. + +`,val=` and `,max` take a string of `+`/`-` tokens and values; a value +can either be a decimal numeric constant (eg: `107`), the `&fieldname` +to refer to the offset of a field name in that struct, or the special +value `end` to refer to the offset of the end of the struct. diff --git a/lib9p/idl/01-9P2000.9p b/lib9p/idl/01-9P2000.9p deleted file mode 100644 index 426a8c6..0000000 --- a/lib9p/idl/01-9P2000.9p +++ /dev/null @@ -1,147 +0,0 @@ -# 01-9P2000.9p - Definitions of 9P2000 messages -# -# Copyright (C) 2024 Luke T. Shumaker -# SPDX-Licence-Identifier: AGPL-3.0-or-later - -# "9P2000" base protocol -# https://ericvh.github.io/9p-rfc/rfc9p2000.html -# https://github.com/ericvh/9p-rfc/blob/master/9p2000.xml -# -# But due to incompleteness of the draft RFC, the Plan 9 manual -# section-5 and the Plan 9 headers (particularly fcall.h) are often -# better references. -# -# https://github.com/plan9foundation/plan9/tree/main/sys/man/5 -# https://man.cat-v.org/plan_9/5/ -# https://github.com/plan9foundation/plan9/blob/main/sys/include/fcall.h -version "9P2000" - -# tag - identify a request/response pair -num tag = 2 - -# file identifier -num fid = 4 - -# data - u32le `n`, then `n` bytes of data -struct d = "len[4] len*(dat[1])" - -# string - u16le `n`, then `n` bytes of UTF-8, without any nul-bytes -struct s = "len[2] len*(utf8[1])" - -# "d"? mode - file permissions and attributes -bitfield dm = 4 - "31=DIR" - "30=APPEND" - "29=EXCL" - # DMMOUNT has been around in Plan 9 forever, 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=_PLAN9_MOUNT" - "27=AUTH" - "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" - - "PERM=0777" # {OWNER,GROUP,OTHER}_{R,W,X} - -# QID Type - see `struct qid` below -bitfield qt = 1 - "7=DIR" - "6=APPEND" - "5=EXCL" - "4=_PLAN9_MOUNT" # see "MOUNT" in "dm" above - "3=AUTH" - # Fun historical fact: QTTMP was a relatively late addition to - # Plan 9, in 2003-12. - "2=TMP" - #"1=unused" - - # "The name QTFILE, defined to be zero, identifies the value - # of the type for a plain file." - "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 -# the same directory, the old and new path components of the qids -# should be different" -# -# - "vers" "is a version number for a file; typically, it is -# incremented every time the file is modified. -# -# - "type" indicates "whether the file is a directory, append-only -# file, etc."; is an instance of the qt bitfield. -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]" - -# "O"pen flags (flags to pass to Topen and Tcreate) -bitfield o = 1 - "0=rwx_0" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum - "1=rwx_1" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum" - #"2=unused" - #"3=unused" - "4=TRUNC" - #"5=unused" - "6=RCLOSE" # remove-on-close - #"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() - -msg Tversion = "size[4,val=end-&size] typ[1,val=100] tag[tag] max_msg_size[4] version[s]" -msg Rversion = "size[4,val=end-&size] typ[1,val=101] tag[tag] max_msg_size[4] version[s]" -msg Tauth = "size[4,val=end-&size] typ[1,val=102] tag[tag] afid[fid] uname[s] aname[s]" -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 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])" -msg Rwalk = "size[4,val=end-&size] typ[1,val=111] tag[tag] nwqid[2,max=16] nwqid*(wqid[qid])" -msg Topen = "size[4,val=end-&size] typ[1,val=112] tag[tag] fid[fid] mode[o]" -msg Ropen = "size[4,val=end-&size] typ[1,val=113] tag[tag] qid[qid] iounit[4]" -msg Tcreate = "size[4,val=end-&size] typ[1,val=114] tag[tag] fid[fid] name[s] perm[dm] mode[o]" -msg Rcreate = "size[4,val=end-&size] typ[1,val=115] tag[tag] qid[qid] iounit[4]" -msg Tread = "size[4,val=end-&size] typ[1,val=116] tag[tag] fid[fid] offset[8] count[4]" -msg Rread = "size[4,val=end-&size] typ[1,val=117] tag[tag] data[d]" # for directories, `data` is the sequence "cnt*(entries[stat])" -msg Twrite = "size[4,val=end-&size] typ[1,val=118] tag[tag] fid[fid] offset[8] data[d]" -msg Rwrite = "size[4,val=end-&size] typ[1,val=119] tag[tag] count[4]" -msg Tclunk = "size[4,val=end-&size] typ[1,val=120] tag[tag] fid[fid]" -msg Rclunk = "size[4,val=end-&size] typ[1,val=121] tag[tag]" -msg Tremove = "size[4,val=end-&size] typ[1,val=122] tag[tag] fid[fid]" -msg Rremove = "size[4,val=end-&size] typ[1,val=123] tag[tag]" -msg Tstat = "size[4,val=end-&size] typ[1,val=124] tag[tag] fid[fid]" -msg Rstat = "size[4,val=end-&size] typ[1,val=125] tag[tag] nstat[2,val=end-&stat] stat[stat]" # See the "BUG" note in the RFC for the nstat field -msg Twstat = "size[4,val=end-&size] typ[1,val=126] tag[tag] fid[fid] nstat[2,val=end-&stat] stat[stat]" # See the "BUG" note in the RFC for the nstat field -msg Rwstat = "size[4,val=end-&size] typ[1,val=127] tag[tag]" diff --git a/lib9p/idl/02-9P2000.e.9p b/lib9p/idl/02-9P2000.e.9p deleted file mode 100644 index b91b2c5..0000000 --- a/lib9p/idl/02-9P2000.e.9p +++ /dev/null @@ -1,18 +0,0 @@ -# 02-9P2000e.e.9p - Definitions of 9P2000.e messages -# -# Copyright (C) 2024 Luke T. Shumaker -# SPDX-Licence-Identifier: AGPL-3.0-or-later - -# "9P2000.e" Erlang extension -# https://erlangonxen.org/more/9p2000e -# https://github.com/cloudozer/ling/blob/master/doc/9p2000e.md -version "9P2000.e" - -from ./01-9P2000.9p import * - -msg Tsession = "size[4,val=end-&size] typ[1,val=150] tag[tag] key[8]" -msg Rsession = "size[4,val=end-&size] typ[1,val=151] tag[tag]" -msg Tsread = "size[4,val=end-&size] typ[1,val=152] tag[tag] fid[4] nwname[2] nwname*(wname[s])" -msg Rsread = "size[4,val=end-&size] typ[1,val=153] tag[tag] data[d]" -msg Tswrite = "size[4,val=end-&size] typ[1,val=154] tag[tag] fid[4] nwname[2] nwname*(wname[s]) data[d]" -msg Rswrite = "size[4,val=end-&size] typ[1,val=155] tag[tag] count[4]" diff --git a/lib9p/idl/02-9P2000.u.9p b/lib9p/idl/02-9P2000.u.9p deleted file mode 100644 index d3ca6f0..0000000 --- a/lib9p/idl/02-9P2000.u.9p +++ /dev/null @@ -1,29 +0,0 @@ -# 02-9P2000.u.9p - Definitions of 9P2000.u messages -# -# Copyright (C) 2024 Luke T. Shumaker -# SPDX-Licence-Identifier: AGPL-3.0-or-later - -# "9P2000.u" Unix extension -# https://ericvh.github.io/9p-rfc/rfc9p2000.u.html -# https://github.com/ericvh/9p-rfc/blob/master/9p2000.u.xml -version "9P2000.u" - -from ./01-9P2000.9p import * - -struct stat += "file_extension[s]" - "file_owner_n_uid[4]" - "file_owner_n_gid[4]" - "file_last_modified_n_uid[4]" - -msg Tauth += "n_uname[4]" -msg Tattach += "n_uname[4]" - -msg Rerror += "errno[4]" - -bitfield dm += "23=DEVICE" - "21=NAMEDPIPE" - "20=SOCKET" - "19=SETUID" - "18=SETGID" - -bitfield qt += "1=SYMLINK" diff --git a/lib9p/idl/03-9P2000.L.9p.wip b/lib9p/idl/03-9P2000.L.9p.wip deleted file mode 100644 index 62186f9..0000000 --- a/lib9p/idl/03-9P2000.L.9p.wip +++ /dev/null @@ -1,56 +0,0 @@ -# 9P2000.L.txt - Definitions of 9P2000.L messages -# -# Copyright (C) 2024 Luke T. Shumaker -# SPDX-Licence-Identifier: AGPL-3.0-or-later - -# "9P2000.L" Linux extension -# https://github.com/chaos/diod/blob/master/protocol.md -version "9P2000.L" - -from ./01-9P2000.9p import * -from ./02-9P2000.u.9p import Tauth, Tattach - -#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[4]" # analogous to 107/Rerror -msg Tstatfs = "size[4,val=end-&size] typ[1,val=8] tag[tag] TODO" -msg Rstatfs = "size[4,val=end-&size] typ[1,val=9] tag[tag] TODO" -msg Tlopen = "size[4,val=end-&size] typ[1,val=12] tag[tag] TODO" # analogous to 112/Topen -msg Rlopen = "size[4,val=end-&size] typ[1,val=13] tag[tag] TODO" # analogous to 113/Ropen -msg Tlcreate = "size[4,val=end-&size] typ[1,val=14] tag[tag] TODO" # analogous to 114/Tcreate -msg Rlcreate = "size[4,val=end-&size] typ[1,val=15] tag[tag] TODO" # analogous to 115/Rcreate -msg Tsymlink = "size[4,val=end-&size] typ[1,val=16] tag[tag] TODO" -msg Rsymlink = "size[4,val=end-&size] typ[1,val=17] tag[tag] TODO" -msg Tmknod = "size[4,val=end-&size] typ[1,val=18] tag[tag] TODO" -msg Rmknod = "size[4,val=end-&size] typ[1,val=19] tag[tag] TODO" -msg Trename = "size[4,val=end-&size] typ[1,val=20] tag[tag] TODO" -msg Rrename = "size[4,val=end-&size] typ[1,val=21] tag[tag] TODO" -msg Treadlink = "size[4,val=end-&size] typ[1,val=22] tag[tag] TODO" -msg Rreadlink = "size[4,val=end-&size] typ[1,val=23] tag[tag] TODO" -msg Tgetattr = "size[4,val=end-&size] typ[1,val=24] tag[tag] TODO" -msg Rgetattr = "size[4,val=end-&size] typ[1,val=25] tag[tag] TODO" -msg Tsetattr = "size[4,val=end-&size] typ[1,val=26] tag[tag] TODO" -msg Rsetattr = "size[4,val=end-&size] typ[1,val=27] tag[tag] TODO" -#... -msg Txattrwalk = "size[4,val=end-&size] typ[1,val=30] tag[tag] TODO" -msg Rxattrwalk = "size[4,val=end-&size] typ[1,val=31] tag[tag] TODO" -msg Txattrcreate = "size[4,val=end-&size] typ[1,val=32] tag[tag] TODO" -msg Rxattrcreate = "size[4,val=end-&size] typ[1,val=33] tag[tag] TODO" -#... -msg Treaddir = "size[4,val=end-&size] typ[1,val=40] tag[tag] TODO" -msg Rreaddir = "size[4,val=end-&size] typ[1,val=41] tag[tag] TODO" -#... -msg Tfsync = "size[4,val=end-&size] typ[1,val=50] tag[tag] TODO" -msg Rfsync = "size[4,val=end-&size] typ[1,val=51] tag[tag] TODO" -msg Tlock = "size[4,val=end-&size] typ[1,val=52] tag[tag] TODO" -msg Rlock = "size[4,val=end-&size] typ[1,val=53] tag[tag] TODO" -msg Tgetlock = "size[4,val=end-&size] typ[1,val=54] tag[tag] TODO" -msg Rgetlock = "size[4,val=end-&size] typ[1,val=55] tag[tag] TODO" -# ... -msg Tlink = "size[4,val=end-&size] typ[1,val=70] tag[tag] TODO" -msg Rlink = "size[4,val=end-&size] typ[1,val=71] tag[tag] TODO" -msg Tmkdir = "size[4,val=end-&size] typ[1,val=72] tag[tag] TODO" -msg Tmkdir = "size[4,val=end-&size] typ[1,val=73] tag[tag] TODO" -msg Trenameat = "size[4,val=end-&size] typ[1,val=74] tag[tag] TODO" -msg Rrenameat = "size[4,val=end-&size] typ[1,val=75] tag[tag] TODO" -msg Tunlinkat = "size[4,val=end-&size] typ[1,val=76] tag[tag] TODO" -msg Runlinkat = "size[4,val=end-&size] typ[1,val=77] tag[tag] TODO" diff --git a/lib9p/idl/1992-9P0.9p.wip b/lib9p/idl/1992-9P0.9p.wip new file mode 100644 index 0000000..c8db485 --- /dev/null +++ b/lib9p/idl/1992-9P0.9p.wip @@ -0,0 +1,53 @@ +# 1992-9P0.9p - Definitions of 9P0 (Plan 9 1st ed) messages +# +# Copyright (C) 2024 Luke T. Shumaker +# SPDX-Licence-Identifier: AGPL-3.0-or-later + +# https://man.cat-v.org/plan_9_1st_ed/5/ +version "9P0" + +# tag - identify a request/response pair +num tag = 2 + +# file identifier - like a UNIX file-descriptor +num fid = 2 + +# uni"Q"ue "ID"entification +struct qid = "path[4] version[4]" + +# a nul-padded string +struct name = 28*(txt[1]) + +msg Tnop = "typ[1,val=TODO] tag[tag,val=0xFFFF]" +msg Rnop = "typ[1,val=TODO] tag[tag,val=0xFFFF]" +msg Tsession = "typ[1,val=TODO] tag[tag,val=0xFFFF]" +msg Rsession = "typ[1,val=TODO] tag[tag,val=0xFFFF]" +msg Rerror = "typ[1,val=TODO] tag[tag] ename[64]" +msg Tflush = "typ[1,val=TODO] tag[tag] oldtag[tag]" +msg Rflush = "typ[1,val=TODO] tag[tag]" +msg Tauth = "typ[1,val=TODO] tag[tag] fid[fid] uid[28] chal[36]" +msg Rauth = "typ[1,val=TODO] tag[tag] fid[fid] chal[30]" +msg Tattach = "typ[1,val=TODO] tag[tag] fid[fid] uid[28] aname[28] auth[28]" +msg Rattach = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Tclone = "typ[1,val=TODO] tag[tag] fid[fid] newfid[fid]" +msg Rclone = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Tclwalk = "typ[1,val=TODO] tag[tag] fid[fid] newfid[fid] name[28]" +msg Rclwalk = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Twalk = "typ[1,val=TODO] tag[tag] fid[fid] name[28]" +msg Rwalk = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Topen = "typ[1,val=TODO] tag[tag] fid[fid] mode[1]" +msg Ropen = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Tcreate = "typ[1,val=TODO] tag[tag] fid[fid] name[28] perm[4] mode[1]" +msg Rcreate = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Tread = "typ[1,val=TODO] tag[tag] fid[fid] offset[8] count[2,max=8192]" +msg Rread = "typ[1,val=TODO] tag[tag] fid[fid] count[2,max=8192] pad[1] count*(data[1])" +msg Twrite = "typ[1,val=TODO] tag[tag] fid[fid] offset[8] count[2,max=8192] pad[1] count*(data[1])" +msg Rwrite = "typ[1,val=TODO] tag[tag] fid[fid] count[2,max=8192]" +msg Tclunk = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Rclunk = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Tremove = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Rremove = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Tstat = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Rstat = "typ[1,val=TODO] tag[tag] fid[fid] stat[116]" +msg Twstat = "typ[1,val=TODO] tag[tag] fid[fid] stat[116]" +msg Rwstat = "typ[1,val=TODO] tag[tag] fid[fid]" diff --git a/lib9p/idl/1995-9P1.9p.wip b/lib9p/idl/1995-9P1.9p.wip new file mode 100644 index 0000000..2f4ed93 --- /dev/null +++ b/lib9p/idl/1995-9P1.9p.wip @@ -0,0 +1,52 @@ +# 1995-9P1.9p - Definitions of 9P1 (Plan 9 2nd ed and 3rd ed) messages +# +# Copyright (C) 2024 Luke T. Shumaker +# SPDX-Licence-Identifier: AGPL-3.0-or-later + +# https://man.cat-v.org/plan_9_2nd_ed/5/ +# https://man.cat-v.org/plan_9_3rd_ed/5/ +version "9P1" + +# tag - identify a request/response pair +num tag = 2 + +# file identifier - like a UNIX file-descriptor +num fid = 2 + +# uni"Q"ue "ID"entification +struct qid = "path[4] version[4]" + +# a nul-padded string +struct name = 28*(txt[1]) + +msg Tnop = "typ[1,val=TODO] tag[tag,val=0xFFFF]" +msg Rnop = "typ[1,val=TODO] tag[tag,val=0xFFFF]" +msg Tsession = "typ[1,val=TODO] tag[tag,val=0xFFFF] chal[8]" +msg Rsession = "typ[1,val=TODO] tag[tag,val=0xFFFF] chal[8] authid[28] authdom[48]" +msg Rerror = "typ[1,val=TODO] tag[tag] ename[64]" +msg Tflush = "typ[1,val=TODO] tag[tag] oldtag[tag]" +msg Rflush = "typ[1,val=TODO] tag[tag]" +msg Tattach = "typ[1,val=TODO] tag[tag] fid[fid] uid[28] aname[28] ticket[72] auth[13]" +msg Rattach = "typ[1,val=TODO] tag[tag] fid[fid] qid[8] rauth[13]" +msg Tclone = "typ[1,val=TODO] tag[tag] fid[fid] newfid[fid]" +msg Rclone = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Tclwalk = "typ[1,val=TODO] tag[tag] fid[fid] newfid[fid] name[28]" +msg Rclwalk = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Twalk = "typ[1,val=TODO] tag[tag] fid[fid] name[28]" +msg Rwalk = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Topen = "typ[1,val=TODO] tag[tag] fid[fid] mode[1]" +msg Ropen = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Tcreate = "typ[1,val=TODO] tag[tag] fid[fid] name[28] perm[4] mode[1]" +msg Rcreate = "typ[1,val=TODO] tag[tag] fid[fid] qid[8]" +msg Tread = "typ[1,val=TODO] tag[tag] fid[fid] offset[8] count[2,max=8192]" +msg Rread = "typ[1,val=TODO] tag[tag] fid[fid] count[2,max=8192] pad[1] count*(data[1])" +msg Twrite = "typ[1,val=TODO] tag[tag] fid[fid] offset[8] count[2,max=8192] pad[1] count*(data[1])" +msg Rwrite = "typ[1,val=TODO] tag[tag] fid[fid] count[2,max=8192]" +msg Tclunk = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Rclunk = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Tremove = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Rremove = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Tstat = "typ[1,val=TODO] tag[tag] fid[fid]" +msg Rstat = "typ[1,val=TODO] tag[tag] fid[fid] stat[116]" +msg Twstat = "typ[1,val=TODO] tag[tag] fid[fid] stat[116]" +msg Rwstat = "typ[1,val=TODO] tag[tag] fid[fid]" diff --git a/lib9p/idl/1996-Styx.9p.wip b/lib9p/idl/1996-Styx.9p.wip new file mode 100644 index 0000000..599abc8 --- /dev/null +++ b/lib9p/idl/1996-Styx.9p.wip @@ -0,0 +1,15 @@ +# 1996-Styx.9p - Definitions of Styx messages +# +# Copyright (C) 2024 Luke T. Shumaker +# SPDX-Licence-Identifier: AGPL-3.0-or-later + +# Styx was a variant of the 9P protocol used by the Inferno operating +# system. Message framing looks like 9P1 (1995), but semantics look +# more like 9P2000 (2002). I am not sure whether there are Styx +# protocol differences between Inferno 1e, 2e, or 3e (4e adopted +# 9P2000). +# +# - 1996 beta +# - 1997 1.0 +# - 1999 2nd ed +# - 2001 3rd ed diff --git a/lib9p/idl/2002-9P2000.9p b/lib9p/idl/2002-9P2000.9p new file mode 100644 index 0000000..ba1382e --- /dev/null +++ b/lib9p/idl/2002-9P2000.9p @@ -0,0 +1,147 @@ +# 2002-9P2000.9p - Definitions of 9P2000 messages +# +# Copyright (C) 2024 Luke T. Shumaker +# SPDX-Licence-Identifier: AGPL-3.0-or-later + +# "9P2000" base protocol +# https://ericvh.github.io/9p-rfc/rfc9p2000.html +# https://github.com/ericvh/9p-rfc/blob/master/9p2000.xml +# +# But due to incompleteness of the draft RFC, the Plan 9 manual +# section-5 and the Plan 9 headers (particularly fcall.h) are often +# better references. +# +# https://github.com/plan9foundation/plan9/tree/main/sys/man/5 +# https://man.cat-v.org/plan_9/5/ +# https://github.com/plan9foundation/plan9/blob/main/sys/include/fcall.h +version "9P2000" + +# tag - identify a request/response pair +num tag = 2 + +# file identifier - like a UNIX file-descriptor +num fid = 4 + +# data - u32le `n`, then `n` bytes of data +struct d = "len[4] len*(dat[1])" + +# string - u16le `n`, then `n` bytes of UTF-8, without any nul-bytes +struct s = "len[2] len*(utf8[1])" + +# "d"? mode - file permissions and attributes +bitfield dm = 4 + "31=DIR" + "30=APPEND" + "29=EXCL" + # DMMOUNT has been around in Plan 9 forever, 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=_PLAN9_MOUNT" + "27=AUTH" + "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" + + "PERM=0777" # {OWNER,GROUP,OTHER}_{R,W,X} + +# QID Type - see `struct qid` below +bitfield qt = 1 + "7=DIR" + "6=APPEND" + "5=EXCL" + "4=_PLAN9_MOUNT" # see "MOUNT" in "dm" above + "3=AUTH" + # Fun historical fact: QTTMP was a relatively late addition to + # Plan 9, in 2003-12. + "2=TMP" + #"1=unused" + + # "The name QTFILE, defined to be zero, identifies the value + # of the type for a plain file." + "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 +# the same directory, the old and new path components of the qids +# should be different" +# +# - "vers" "is a version number for a file; typically, it is +# incremented every time the file is modified. +# +# - "type" indicates "whether the file is a directory, append-only +# file, etc."; is an instance of the qt bitfield. +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]" + +# "O"pen flags (flags to pass to Topen and Tcreate) +bitfield o = 1 + "0=rwx_0" # low bit of the 2-bit READ/WRITE/RDWR/EXEC enum + "1=rwx_1" # high bit of the 2-bit READ/WRITE/RDWR/EXEC enum" + #"2=unused" + #"3=unused" + "4=TRUNC" + #"5=unused" + "6=RCLOSE" # remove-on-close + #"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() + +msg Tversion = "size[4,val=end-&size] typ[1,val=100] tag[tag] max_msg_size[4] version[s]" +msg Rversion = "size[4,val=end-&size] typ[1,val=101] tag[tag] max_msg_size[4] version[s]" +msg Tauth = "size[4,val=end-&size] typ[1,val=102] tag[tag] afid[fid] uname[s] aname[s]" +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 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])" +msg Rwalk = "size[4,val=end-&size] typ[1,val=111] tag[tag] nwqid[2,max=16] nwqid*(wqid[qid])" +msg Topen = "size[4,val=end-&size] typ[1,val=112] tag[tag] fid[fid] mode[o]" +msg Ropen = "size[4,val=end-&size] typ[1,val=113] tag[tag] qid[qid] iounit[4]" +msg Tcreate = "size[4,val=end-&size] typ[1,val=114] tag[tag] fid[fid] name[s] perm[dm] mode[o]" +msg Rcreate = "size[4,val=end-&size] typ[1,val=115] tag[tag] qid[qid] iounit[4]" +msg Tread = "size[4,val=end-&size] typ[1,val=116] tag[tag] fid[fid] offset[8] count[4]" +msg Rread = "size[4,val=end-&size] typ[1,val=117] tag[tag] data[d]" # for directories, `data` is the sequence "cnt*(entries[stat])" +msg Twrite = "size[4,val=end-&size] typ[1,val=118] tag[tag] fid[fid] offset[8] data[d]" +msg Rwrite = "size[4,val=end-&size] typ[1,val=119] tag[tag] count[4]" +msg Tclunk = "size[4,val=end-&size] typ[1,val=120] tag[tag] fid[fid]" +msg Rclunk = "size[4,val=end-&size] typ[1,val=121] tag[tag]" +msg Tremove = "size[4,val=end-&size] typ[1,val=122] tag[tag] fid[fid]" +msg Rremove = "size[4,val=end-&size] typ[1,val=123] tag[tag]" +msg Tstat = "size[4,val=end-&size] typ[1,val=124] tag[tag] fid[fid]" +msg Rstat = "size[4,val=end-&size] typ[1,val=125] tag[tag] nstat[2,val=end-&stat] stat[stat]" # See the "BUG" note in the RFC for the nstat field +msg Twstat = "size[4,val=end-&size] typ[1,val=126] tag[tag] fid[fid] nstat[2,val=end-&stat] stat[stat]" # See the "BUG" note in the RFC for the nstat field +msg Rwstat = "size[4,val=end-&size] typ[1,val=127] tag[tag]" diff --git a/lib9p/idl/2005-9P2000.u.9p b/lib9p/idl/2005-9P2000.u.9p new file mode 100644 index 0000000..a47e9db --- /dev/null +++ b/lib9p/idl/2005-9P2000.u.9p @@ -0,0 +1,29 @@ +# 2005-9P2000.u.9p - Definitions of 9P2000.u messages +# +# Copyright (C) 2024 Luke T. Shumaker +# SPDX-Licence-Identifier: AGPL-3.0-or-later + +# "9P2000.u" Unix extension +# https://ericvh.github.io/9p-rfc/rfc9p2000.u.html +# https://github.com/ericvh/9p-rfc/blob/master/9p2000.u.xml +version "9P2000.u" + +from ./2002-9P2000.9p import * + +struct stat += "file_extension[s]" + "file_owner_n_uid[4]" + "file_owner_n_gid[4]" + "file_last_modified_n_uid[4]" + +msg Tauth += "n_uname[4]" +msg Tattach += "n_uname[4]" + +msg Rerror += "errno[4]" + +bitfield dm += "23=DEVICE" + "21=NAMEDPIPE" + "20=SOCKET" + "19=SETUID" + "18=SETGID" + +bitfield qt += "1=SYMLINK" diff --git a/lib9p/idl/2010-9P2000.L.9p.wip b/lib9p/idl/2010-9P2000.L.9p.wip new file mode 100644 index 0000000..a0de883 --- /dev/null +++ b/lib9p/idl/2010-9P2000.L.9p.wip @@ -0,0 +1,56 @@ +# 2010-9P2000.L.9p - Definitions of 9P2000.L messages +# +# Copyright (C) 2024 Luke T. Shumaker +# SPDX-Licence-Identifier: AGPL-3.0-or-later + +# "9P2000.L" Linux extension +# https://github.com/chaos/diod/blob/master/protocol.md +version "9P2000.L" + +from ./2002-9P2000.9p import * +from ./2005-9P2000.u.9p import Tauth, Tattach + +#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[4]" # analogous to 107/Rerror +msg Tstatfs = "size[4,val=end-&size] typ[1,val=8] tag[tag] TODO" +msg Rstatfs = "size[4,val=end-&size] typ[1,val=9] tag[tag] TODO" +msg Tlopen = "size[4,val=end-&size] typ[1,val=12] tag[tag] TODO" # analogous to 112/Topen +msg Rlopen = "size[4,val=end-&size] typ[1,val=13] tag[tag] TODO" # analogous to 113/Ropen +msg Tlcreate = "size[4,val=end-&size] typ[1,val=14] tag[tag] TODO" # analogous to 114/Tcreate +msg Rlcreate = "size[4,val=end-&size] typ[1,val=15] tag[tag] TODO" # analogous to 115/Rcreate +msg Tsymlink = "size[4,val=end-&size] typ[1,val=16] tag[tag] TODO" +msg Rsymlink = "size[4,val=end-&size] typ[1,val=17] tag[tag] TODO" +msg Tmknod = "size[4,val=end-&size] typ[1,val=18] tag[tag] TODO" +msg Rmknod = "size[4,val=end-&size] typ[1,val=19] tag[tag] TODO" +msg Trename = "size[4,val=end-&size] typ[1,val=20] tag[tag] TODO" +msg Rrename = "size[4,val=end-&size] typ[1,val=21] tag[tag] TODO" +msg Treadlink = "size[4,val=end-&size] typ[1,val=22] tag[tag] TODO" +msg Rreadlink = "size[4,val=end-&size] typ[1,val=23] tag[tag] TODO" +msg Tgetattr = "size[4,val=end-&size] typ[1,val=24] tag[tag] TODO" +msg Rgetattr = "size[4,val=end-&size] typ[1,val=25] tag[tag] TODO" +msg Tsetattr = "size[4,val=end-&size] typ[1,val=26] tag[tag] TODO" +msg Rsetattr = "size[4,val=end-&size] typ[1,val=27] tag[tag] TODO" +#... +msg Txattrwalk = "size[4,val=end-&size] typ[1,val=30] tag[tag] TODO" +msg Rxattrwalk = "size[4,val=end-&size] typ[1,val=31] tag[tag] TODO" +msg Txattrcreate = "size[4,val=end-&size] typ[1,val=32] tag[tag] TODO" +msg Rxattrcreate = "size[4,val=end-&size] typ[1,val=33] tag[tag] TODO" +#... +msg Treaddir = "size[4,val=end-&size] typ[1,val=40] tag[tag] TODO" +msg Rreaddir = "size[4,val=end-&size] typ[1,val=41] tag[tag] TODO" +#... +msg Tfsync = "size[4,val=end-&size] typ[1,val=50] tag[tag] TODO" +msg Rfsync = "size[4,val=end-&size] typ[1,val=51] tag[tag] TODO" +msg Tlock = "size[4,val=end-&size] typ[1,val=52] tag[tag] TODO" +msg Rlock = "size[4,val=end-&size] typ[1,val=53] tag[tag] TODO" +msg Tgetlock = "size[4,val=end-&size] typ[1,val=54] tag[tag] TODO" +msg Rgetlock = "size[4,val=end-&size] typ[1,val=55] tag[tag] TODO" +# ... +msg Tlink = "size[4,val=end-&size] typ[1,val=70] tag[tag] TODO" +msg Rlink = "size[4,val=end-&size] typ[1,val=71] tag[tag] TODO" +msg Tmkdir = "size[4,val=end-&size] typ[1,val=72] tag[tag] TODO" +msg Tmkdir = "size[4,val=end-&size] typ[1,val=73] tag[tag] TODO" +msg Trenameat = "size[4,val=end-&size] typ[1,val=74] tag[tag] TODO" +msg Rrenameat = "size[4,val=end-&size] typ[1,val=75] tag[tag] TODO" +msg Tunlinkat = "size[4,val=end-&size] typ[1,val=76] tag[tag] TODO" +msg Runlinkat = "size[4,val=end-&size] typ[1,val=77] tag[tag] TODO" diff --git a/lib9p/idl/2012-9P2000.e.9p b/lib9p/idl/2012-9P2000.e.9p new file mode 100644 index 0000000..2f88a60 --- /dev/null +++ b/lib9p/idl/2012-9P2000.e.9p @@ -0,0 +1,18 @@ +# 2012-9P2000.e.9p - Definitions of 9P2000.e messages +# +# Copyright (C) 2024 Luke T. Shumaker +# SPDX-Licence-Identifier: AGPL-3.0-or-later + +# "9P2000.e" Erlang extension +# https://erlangonxen.org/more/9p2000e +# https://github.com/cloudozer/ling/blob/master/doc/9p2000e.md +version "9P2000.e" + +from ./2002-9P2000.9p import * + +msg Tsession = "size[4,val=end-&size] typ[1,val=150] tag[tag] key[8]" +msg Rsession = "size[4,val=end-&size] typ[1,val=151] tag[tag]" +msg Tsread = "size[4,val=end-&size] typ[1,val=152] tag[tag] fid[4] nwname[2] nwname*(wname[s])" +msg Rsread = "size[4,val=end-&size] typ[1,val=153] tag[tag] data[d]" +msg Tswrite = "size[4,val=end-&size] typ[1,val=154] tag[tag] fid[4] nwname[2] nwname*(wname[s]) data[d]" +msg Rswrite = "size[4,val=end-&size] typ[1,val=155] tag[tag] count[4]" diff --git a/lib9p/include/lib9p/9p.generated.h b/lib9p/include/lib9p/9p.generated.h index 2fb7a3e..6248ec7 100644 --- a/lib9p/include/lib9p/9p.generated.h +++ b/lib9p/include/lib9p/9p.generated.h @@ -1,4 +1,4 @@ -/* Generated by `./lib9p/idl.gen lib9p/idl/01-9P2000.9p lib9p/idl/02-9P2000.e.9p lib9p/idl/02-9P2000.u.9p`. DO NOT EDIT! */ +/* Generated by `./lib9p/idl.gen lib9p/idl/2002-9P2000.9p lib9p/idl/2005-9P2000.u.9p lib9p/idl/2012-9P2000.e.9p`. DO NOT EDIT! */ #ifndef _LIB9P_9P_H_ # error Do not include directly; include instead diff --git a/lib9p/include/lib9p/9p.h b/lib9p/include/lib9p/9p.h index 616a0e1..3ad52f1 100644 --- a/lib9p/include/lib9p/9p.h +++ b/lib9p/include/lib9p/9p.h @@ -11,7 +11,6 @@ #include #include /* for ssize_t */ -#include #include /* configuration **************************************************************/ @@ -21,9 +20,14 @@ #ifndef CONFIG_9P_MAX_ERR_SIZE # error config.h must define CONFIG_9P_MAX_ERR_SIZE #endif +#ifndef CONFIG_9P_ENABLE_9P2000 +# define CONFIG_9P_ENABLE_9P2000 +#endif /******************************************************************************/ +#include /* *after* config.h */ + #define LIB9P_NOTAG ((uint16_t)~0U) #define LIB9P_NOFID ((uint32_t)~0U) @@ -85,21 +89,22 @@ ssize_t lib9p_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); * @param net_bytes : the complete message, starting with the "size[4]" * * @return ret_typ : the mesage type - * @return ret_tag : the message-ID tag * @return ret_body : the message body, must be at least lib9p_validate() bytes */ void lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, - enum lib9p_msg_type *ret_typ, uint16_t *ret_tag, void *ret_body); + enum lib9p_msg_type *ret_typ, void *ret_body); /** * Marshal a `struct lib9p_msg_{typ}` structure into a byte-array. * * lib9p_marshal does no validation; it trusts that the programmer - * won't give it garbage input. + * won't give it garbage input. However, just as it doesn't marshal + * struct fields that aren't in ctx->version, it won't 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 typ : the message type - * @param tag : the message-ID tag * @param msg : the message to encode * * @return ret_bytes : the buffer to encode to, must be at be at least lib9p_ctx_max_msg_size(ctx) bytes @@ -107,7 +112,7 @@ void lib9p_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, * * @errno LINUX_ERANGE: reply does not fit in ctx->max_msg_size */ -bool lib9p_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, uint16_t tag, void *body, +bool lib9p_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, uint8_t *ret_bytes); #endif _LIB9P_9P_H_ diff --git a/lib9p/srv.c b/lib9p/srv.c index 5af0971..9d1b4ed 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -81,9 +81,8 @@ static uint32_t rerror_overhead_for_version(enum lib9p_version version, bool e; e = lib9p_marshal(&empty_ctx, LIB9P_TYP_Rerror, - 0, /* tag */ &empty_error, /* host_body */ - scratch); /* net_bytes */ + scratch); /* net_bytes */ assert(!e); uint32_t min_msg_size = decode_u32le(scratch); @@ -105,6 +104,7 @@ static void respond_error(struct _lib9p_srv_req *req) { ssize_t r; struct lib9p_msg_Rerror host = { + .tag = req->tag, .ename = { .len = strnlen(req->ctx.basectx.err_msg, CONFIG_9P_MAX_ERR_SIZE), @@ -123,7 +123,7 @@ static void respond_error(struct _lib9p_srv_req *req) { host.ename.len = sess->max_msg_size - sess->rerror_overhead; lib9p_marshal(&req->ctx.basectx, LIB9P_TYP_Rerror, - req->tag, &host, req->net_bytes); + &host, req->net_bytes); cr_mutex_lock(&sess->parent_conn->writelock); r = netio_write(sess->parent_conn->fd, @@ -345,7 +345,7 @@ static void handle_message(struct _lib9p_srv_req *ctx) { goto write; } lib9p_unmarshal(&ctx->ctx.basectx, ctx->net_bytes, - &typ, &ctx->tag, host_req); + &typ, host_req); /* Handle it. */ tmessage_handlers[typ](ctx, (void *)host_req, (void *)host_resp); @@ -354,7 +354,7 @@ static void handle_message(struct _lib9p_srv_req *ctx) { if (lib9p_ctx_has_error(&ctx->ctx.basectx)) respond_error(ctx); else { - if (lib9p_marshal(&ctx->ctx.basectx, typ+1, ctx->tag, host_resp, + if (lib9p_marshal(&ctx->ctx.basectx, typ+1, host_resp, ctx->net_bytes)) goto write; @@ -440,12 +440,17 @@ static void handle_Tversion(struct _lib9p_srv_req *ctx, ctx->parent_sess->rerror_overhead = min_msg_size; } +#define handler_common(ctx, req, resp) do { \ + assert(ctx); \ + assert(req); \ + assert(resp); \ + resp->tag = req->tag; \ + } while (0) + static void handle_Tauth(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tauth *req, struct lib9p_msg_Rauth *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); ctx->ctx.uid = req->n_uname; ctx->ctx.uname = req->uname.utf8; @@ -465,9 +470,7 @@ static void handle_Tauth(struct _lib9p_srv_req *ctx, static void handle_Tattach(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tattach *req, struct lib9p_msg_Rattach *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); ctx->ctx.uid = req->n_uname; ctx->ctx.uname = req->uname.utf8; @@ -543,9 +546,7 @@ static void handle_Tattach(struct _lib9p_srv_req *ctx, static void handle_Tflush(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tflush *req, struct lib9p_msg_Rflush *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp);; lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "flush not yet implemented"); @@ -554,9 +555,7 @@ static void handle_Tflush(struct _lib9p_srv_req *ctx, static void handle_Twalk(struct _lib9p_srv_req *ctx, struct lib9p_msg_Twalk *req, struct lib9p_msg_Rwalk *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); struct lib9p_srv_file **dirpp = fidmap_load(&ctx->parent_sess->fids, req->fid); if (!dirpp) { @@ -627,9 +626,7 @@ static void handle_Twalk(struct _lib9p_srv_req *ctx, static void handle_Topen(struct _lib9p_srv_req *ctx, struct lib9p_msg_Topen *req, struct lib9p_msg_Ropen *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp);; lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "open not yet implemented"); @@ -638,9 +635,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, static void handle_Tcreate(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tcreate *req, struct lib9p_msg_Rcreate *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "create not yet implemented"); @@ -649,9 +644,7 @@ static void handle_Tcreate(struct _lib9p_srv_req *ctx, static void handle_Tread(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tread *req, struct lib9p_msg_Rread *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "read not yet implemented"); @@ -660,9 +653,7 @@ static void handle_Tread(struct _lib9p_srv_req *ctx, static void handle_Twrite(struct _lib9p_srv_req *ctx, struct lib9p_msg_Twrite *req, struct lib9p_msg_Rwrite *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "write not yet implemented"); @@ -671,9 +662,7 @@ static void handle_Twrite(struct _lib9p_srv_req *ctx, static void handle_Tclunk(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tclunk *req, struct lib9p_msg_Rclunk *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); struct lib9p_srv_file **filepp = fidmap_load(&ctx->parent_sess->fids, req->fid); if (!filepp) { @@ -689,9 +678,7 @@ static void handle_Tclunk(struct _lib9p_srv_req *ctx, static void handle_Tremove(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tremove *req, struct lib9p_msg_Rremove *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "remove not yet implemented"); @@ -700,9 +687,7 @@ static void handle_Tremove(struct _lib9p_srv_req *ctx, static void handle_Tstat(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tstat *req, struct lib9p_msg_Rstat *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); struct lib9p_srv_file **filepp = fidmap_load(&ctx->parent_sess->fids, req->fid); if (!filepp) { @@ -717,9 +702,7 @@ static void handle_Tstat(struct _lib9p_srv_req *ctx, static void handle_Twstat(struct _lib9p_srv_req *ctx, struct lib9p_msg_Twstat *req, struct lib9p_msg_Rwstat *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp);; lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "wstat not yet implemented"); @@ -728,9 +711,7 @@ static void handle_Twstat(struct _lib9p_srv_req *ctx, static void handle_Tsession(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tsession *req, struct lib9p_msg_Rsession *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "session not yet implemented"); @@ -739,9 +720,7 @@ static void handle_Tsession(struct _lib9p_srv_req *ctx, static void handle_Tsread(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tsread *req, struct lib9p_msg_Rsread *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "sread not yet implemented"); @@ -750,9 +729,7 @@ static void handle_Tsread(struct _lib9p_srv_req *ctx, static void handle_Tswrite(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tswrite *req, struct lib9p_msg_Rswrite *resp) { - assert(ctx); - assert(req); - assert(resp); + handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "swrite not yet implemented"); -- cgit v1.2.3-2-g168b