diff options
Diffstat (limited to 'lib9p')
-rw-r--r-- | lib9p/.editorconfig | 2 | ||||
-rw-r--r-- | lib9p/9p.c | 39 | ||||
-rw-r--r-- | lib9p/9p.generated.c | 1471 | ||||
-rwxr-xr-x | lib9p/idl.gen | 589 | ||||
-rw-r--r-- | lib9p/idl/0000-README.md (renamed from lib9p/idl/00-README.md) | 0 | ||||
-rw-r--r-- | lib9p/idl/1992-9P0.9p.wip | 53 | ||||
-rw-r--r-- | lib9p/idl/1995-9P1.9p.wip | 52 | ||||
-rw-r--r-- | lib9p/idl/1996-Styx.9p.wip | 15 | ||||
-rw-r--r-- | lib9p/idl/2002-9P2000.9p (renamed from lib9p/idl/01-9P2000.9p) | 4 | ||||
-rw-r--r-- | lib9p/idl/2005-9P2000.u.9p (renamed from lib9p/idl/02-9P2000.u.9p) | 4 | ||||
-rw-r--r-- | lib9p/idl/2010-9P2000.L.9p.wip (renamed from lib9p/idl/03-9P2000.L.9p.wip) | 6 | ||||
-rw-r--r-- | lib9p/idl/2012-9P2000.e.9p (renamed from lib9p/idl/02-9P2000.e.9p) | 4 | ||||
-rw-r--r-- | lib9p/include/lib9p/9p.generated.h | 2 | ||||
-rw-r--r-- | lib9p/include/lib9p/9p.h | 17 | ||||
-rw-r--r-- | lib9p/srv.c | 77 |
15 files changed, 1702 insertions, 633 deletions
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 @@ -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 <assert.h> #include <stdbool.h> @@ -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/0000-README.md index f53acf9..f53acf9 100644 --- a/lib9p/idl/00-README.md +++ b/lib9p/idl/0000-README.md 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 <lukeshu@lukeshu.com> +# 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 <lukeshu@lukeshu.com> +# 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 <lukeshu@lukeshu.com> +# 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/01-9P2000.9p b/lib9p/idl/2002-9P2000.9p index 426a8c6..ba1382e 100644 --- a/lib9p/idl/01-9P2000.9p +++ b/lib9p/idl/2002-9P2000.9p @@ -1,4 +1,4 @@ -# 01-9P2000.9p - Definitions of 9P2000 messages +# 2002-9P2000.9p - Definitions of 9P2000 messages # # Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-Licence-Identifier: AGPL-3.0-or-later @@ -19,7 +19,7 @@ version "9P2000" # tag - identify a request/response pair num tag = 2 -# file identifier +# file identifier - like a UNIX file-descriptor num fid = 4 # data - u32le `n`, then `n` bytes of data diff --git a/lib9p/idl/02-9P2000.u.9p b/lib9p/idl/2005-9P2000.u.9p index d3ca6f0..a47e9db 100644 --- a/lib9p/idl/02-9P2000.u.9p +++ b/lib9p/idl/2005-9P2000.u.9p @@ -1,4 +1,4 @@ -# 02-9P2000.u.9p - Definitions of 9P2000.u messages +# 2005-9P2000.u.9p - Definitions of 9P2000.u messages # # Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-Licence-Identifier: AGPL-3.0-or-later @@ -8,7 +8,7 @@ # https://github.com/ericvh/9p-rfc/blob/master/9p2000.u.xml version "9P2000.u" -from ./01-9P2000.9p import * +from ./2002-9P2000.9p import * struct stat += "file_extension[s]" "file_owner_n_uid[4]" diff --git a/lib9p/idl/03-9P2000.L.9p.wip b/lib9p/idl/2010-9P2000.L.9p.wip index 62186f9..a0de883 100644 --- a/lib9p/idl/03-9P2000.L.9p.wip +++ b/lib9p/idl/2010-9P2000.L.9p.wip @@ -1,4 +1,4 @@ -# 9P2000.L.txt - Definitions of 9P2000.L messages +# 2010-9P2000.L.9p - Definitions of 9P2000.L messages # # Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-Licence-Identifier: AGPL-3.0-or-later @@ -7,8 +7,8 @@ # 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 +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 diff --git a/lib9p/idl/02-9P2000.e.9p b/lib9p/idl/2012-9P2000.e.9p index b91b2c5..2f88a60 100644 --- a/lib9p/idl/02-9P2000.e.9p +++ b/lib9p/idl/2012-9P2000.e.9p @@ -1,4 +1,4 @@ -# 02-9P2000e.e.9p - Definitions of 9P2000.e messages +# 2012-9P2000.e.9p - Definitions of 9P2000.e messages # # Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> # SPDX-Licence-Identifier: AGPL-3.0-or-later @@ -8,7 +8,7 @@ # https://github.com/cloudozer/ling/blob/master/doc/9p2000e.md version "9P2000.e" -from ./01-9P2000.9p import * +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]" 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 <lib9p/9p.generated.h> directly; include <lib9p/9p.h> 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 <stdbool.h> #include <sys/types.h> /* for ssize_t */ -#include <lib9p/9p.generated.h> #include <lib9p/linux-errno.h> /* 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 <lib9p/9p.generated.h> /* *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"); |