diff options
Diffstat (limited to 'lib9p/9p.c')
-rw-r--r-- | lib9p/9p.c | 47 |
1 files changed, 47 insertions, 0 deletions
@@ -98,3 +98,50 @@ bool lib9p_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, struct _vtable_msg vtable = _lib9p_vtables[ctx->version].msgs[typ]; return vtable.marshal(&subctx, body); } + +bool lib9p_validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, + uint32_t *ret_net_size, ssize_t *ret_host_size) { + struct _validate_ctx subctx = { + .ctx = ctx, + .net_size = net_size, + .net_bytes = net_bytes, + + .net_offset = 0, + .host_extra = 0, + }; + if (_lib9p_validate_stat(&subctx)) + return true; + if (ret_net_size) + *ret_net_size = subctx.net_offset; + if (ret_host_size) + if (__builtin_add_overflow(sizeof(struct lib9p_stat), subctx.host_extra, ret_host_size)) + return lib9p_error(ctx, LINUX_EMSGSIZE, "unmarshalled stat object overflows SSIZE_MAX"); + return false; +} + +uint32_t lib9p_unmarshal_stat(struct lib9p_ctx *ctx, uint8_t *net_bytes, + struct lib9p_stat *ret_obj, void *ret_extra) { + struct _unmarshal_ctx subctx = { + .ctx = ctx, + .net_bytes = net_bytes, + .net_offset = 0, + + .extra = ret_extra, + }; + _lib9p_unmarshal_stat(&subctx, ret_obj); + return subctx.net_offset; +} + +uint32_t lib9p_marshal_stat(struct lib9p_ctx *ctx, uint32_t max_net_size, struct lib9p_stat *obj, + uint8_t *ret_bytes) { + struct lib9p_ctx _ctx = *ctx; + _ctx.max_msg_size = max_net_size; + struct _marshal_ctx subctx = { + .ctx = &_ctx, + .net_bytes = ret_bytes, + .net_offset = 0, + }; + if (_lib9p_marshal_stat(&subctx, obj)) + return 0; + return subctx.net_offset; +} |