diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-12 20:54:28 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-02-12 20:54:28 -0700 |
commit | d148555bd86e323a51734b7881f92d09e2f08425 (patch) | |
tree | 0fa494fa06ca00e72926a6bde8158adb0ddc5a06 /lib9p | |
parent | 6cd125e1ffd44fdf62c44d22c519561a8c9d7268 (diff) | |
parent | bd0f2f3e0fe721c7fbce63aeacffaec8344e166c (diff) |
Merge branch 'lukeshu/misc'
Diffstat (limited to 'lib9p')
-rw-r--r-- | lib9p/9p.c | 32 | ||||
-rwxr-xr-x | lib9p/idl.gen | 44 | ||||
-rw-r--r-- | lib9p/internal.h | 6 | ||||
-rw-r--r-- | lib9p/map.h | 4 | ||||
-rw-r--r-- | lib9p/srv.c | 10 |
5 files changed, 67 insertions, 29 deletions
@@ -124,10 +124,12 @@ ssize_t _lib9p_validate(uint8_t xxx_low_typ_bit, struct lib9p_ctx *ctx, uint8_t *net_bytes) { /* Inspect the first 5 bytes ourselves. */ struct _validate_ctx subctx = { + /* input */ .ctx = ctx, .net_size = uint32le_decode(net_bytes), .net_bytes = net_bytes, + /* output */ .net_offset = 0, .host_extra = 0, }; @@ -171,17 +173,19 @@ static void _lib9p_unmarshal(const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0x80], struct lib9p_ctx *ctx, uint8_t *net_bytes, enum lib9p_msg_type *ret_typ, void *ret_body) { + enum lib9p_msg_type typ = net_bytes[4]; + *ret_typ = typ; + struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2]; + struct _unmarshal_ctx subctx = { + /* input */ .ctx = ctx, .net_bytes = net_bytes, + /* output */ .net_offset = 0, + .extra = ret_body + tentry.basesize, }; - - enum lib9p_msg_type typ = net_bytes[4]; - *ret_typ = typ; - struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2]; - subctx.extra = ret_body + tentry.basesize; tentry.unmarshal(&subctx, ret_body); } @@ -202,7 +206,10 @@ bool _lib9p_marshal(const struct _lib9p_send_tentry xxx_table[LIB9P_VER_NUM][0x8 struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, uint8_t *ret_bytes) { struct _marshal_ctx subctx = { + /* input */ .ctx = ctx, + + /* ouptut */ .net_bytes = ret_bytes, .net_offset = 0, }; @@ -228,10 +235,12 @@ bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *bo bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size, ssize_t *ret_host_size) { struct _validate_ctx subctx = { + /* input */ .ctx = ctx, .net_size = net_size, .net_bytes = net_bytes, + /* output */ .net_offset = 0, .host_extra = 0, }; @@ -248,11 +257,13 @@ bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_ uint32_t lib9p_stat_unmarshal(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, + /* input */ + .ctx = ctx, + .net_bytes = net_bytes, - .extra = ret_extra, + /* output */ + .net_offset = 0, + .extra = ret_extra, }; _lib9p_stat_unmarshal(&subctx, ret_obj); return subctx.net_offset; @@ -263,7 +274,10 @@ uint32_t lib9p_stat_marshal(struct lib9p_ctx *ctx, uint32_t max_net_size, struct struct lib9p_ctx _ctx = *ctx; _ctx.max_msg_size = max_net_size; struct _marshal_ctx subctx = { + /* input */ .ctx = &_ctx, + + /* output */ .net_bytes = ret_bytes, .net_offset = 0, }; diff --git a/lib9p/idl.gen b/lib9p/idl.gen index 8782771..adb15ce 100755 --- a/lib9p/idl.gen +++ b/lib9p/idl.gen @@ -53,13 +53,13 @@ def c_ver_enum(ver: str) -> str: return f"{idprefix.upper()}VER_{ver.replace('.', '_')}" -def c_ver_ifdef(versions: set[str]) -> str: +def c_ver_ifdef(versions: typing.Collection[str]) -> str: return " || ".join( f"CONFIG_9P_ENABLE_{v.replace('.', '_')}" for v in sorted(versions) ) -def c_ver_cond(versions: set[str]) -> str: +def c_ver_cond(versions: typing.Collection[str]) -> str: if len(versions) == 1: v = next(v for v in versions) return f"is_ver(ctx, {v.replace('.', '_')})" @@ -84,7 +84,7 @@ def c_typename(typ: idl.Type, parent: idl.StructMember | None = None) -> str: raise ValueError(f"not a type: {typ.__class__.__name__}") -def c_expr(expr: idl.Expr) -> str: +def c_expr(expr: idl.Expr, lookup_sym: typing.Callable[[str], str]) -> str: ret: list[str] = [] for tok in expr.tokens: match tok: @@ -92,14 +92,14 @@ def c_expr(expr: idl.Expr) -> str: ret.append(tok.op) case idl.ExprLit(): ret.append(str(tok.val)) - case idl.ExprSym(name="end"): - ret.append("ctx->net_offset") case idl.ExprSym(name="s32_max"): ret.append("INT32_MAX") case idl.ExprSym(name="s64_max"): ret.append("INT64_MAX") case idl.ExprSym(): - ret.append(f"_{tok.name[1:]}_offset") + ret.append(lookup_sym(tok.name)) + case _: + assert False return " ".join(ret) @@ -411,7 +411,7 @@ def gen_c(versions: set[str], typs: list[idl.Type]) -> str: ret += f""" /* strings ********************************************************************/ -const char *_lib9p_table_ver_name[{c_ver_enum('NUM')}] = {{ +const char *_{idprefix}table_ver_name[{c_ver_enum('NUM')}] = {{ """ for ver in ["unknown", *sorted(versions)]: if ver in versions: @@ -573,17 +573,26 @@ LM_ALWAYS_INLINE static bool validate_8(struct _validate_ctx *ctx) { return _val # Pass 4 - validate ,max= and ,val= constraints for member in typ.members: + + def lookup_sym(sym: str) -> str: + match sym: + case "end": + return "ctx->net_offset" + case _: + assert sym.startswith("&") + return f"_{sym[1:]}_offset" + if member.max: assert member.static_size nbits = member.static_size * 8 ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) - ret += f"\t || ({{ uint{nbits}_t max = {c_expr(member.max)}; (((uint{nbits}_t){member.name}) > max) &&\n" + ret += f"\t || ({{ uint{nbits}_t max = {c_expr(member.max, lookup_sym)}; (((uint{nbits}_t){member.name}) > max) &&\n" ret += f'\t lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "{member.name} value is too large (%"PRIu{nbits}" > %"PRIu{nbits}")", {member.name}, max); }})\n' if member.val: assert member.static_size nbits = member.static_size * 8 ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) - ret += f"\t || ({{ uint{nbits}_t exp = {c_expr(member.val)}; (((uint{nbits}_t){member.name}) != exp) &&\n" + ret += f"\t || ({{ uint{nbits}_t exp = {c_expr(member.val, lookup_sym)}; (((uint{nbits}_t){member.name}) != exp) &&\n" ret += f'\t lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "{member.name} value is wrong (actual:%"PRIu{nbits}" != correct:%"PRIu{nbits}")", (uint{nbits}_t){member.name}, exp); }})\n' ret += ifdef_pop(1) @@ -775,10 +784,19 @@ LM_ALWAYS_INLINE static bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) if member.val: assert member.static_size ret += ifdef_push(2, c_ver_ifdef(member.in_versions)) + + def lookup_sym(sym: str) -> str: + match sym: + case "end": + return "ctx->net_offset" + case _: + assert sym.startswith("&") + return f"_{sym[1:]}_offset" + if member.static_size == 1: - ret += f"\t || ({{ ctx->net_bytes[_{member.name}_offset] = {c_expr(member.val)}; false; }})\n" + ret += f"\t || ({{ ctx->net_bytes[_{member.name}_offset] = {c_expr(member.val, lookup_sym)}; false; }})\n" else: - ret += f"\t || ({{ uint{member.static_size*8}le_encode(&ctx->net_bytes[_{member.name}_offset], {c_expr(member.val)}); false; }})\n" + ret += f"\t || ({{ uint{member.static_size*8}le_encode(&ctx->net_bytes[_{member.name}_offset], {c_expr(member.val, lookup_sym)}); false; }})\n" ret += ifdef_pop(1) ret += "\t ;\n" @@ -815,10 +833,10 @@ LM_ALWAYS_INLINE static bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) LM_FLATTEN bool _{idprefix}stat_validate(struct _validate_ctx *ctx) {{ \treturn validate_stat(ctx); }} -LM_FLATTEN void _{idprefix}stat_unmarshal(struct _unmarshal_ctx *ctx, struct lib9p_stat *out) {{ +LM_FLATTEN void _{idprefix}stat_unmarshal(struct _unmarshal_ctx *ctx, struct {idprefix}stat *out) {{ \tunmarshal_stat(ctx, out); }} -LM_FLATTEN bool _{idprefix}stat_marshal(struct _marshal_ctx *ctx, struct lib9p_stat *val) {{ +LM_FLATTEN bool _{idprefix}stat_marshal(struct _marshal_ctx *ctx, struct {idprefix}stat *val) {{ \treturn marshal_stat(ctx, val); }} """ diff --git a/lib9p/internal.h b/lib9p/internal.h index d939d46..a648532 100644 --- a/lib9p/internal.h +++ b/lib9p/internal.h @@ -39,10 +39,12 @@ static_assert(CONFIG_9P_MAX_HOSTMSG_SIZE <= SSIZE_MAX); /* specialized contexts *******************************************************/ struct _validate_ctx { + /* input */ struct lib9p_ctx *ctx; uint32_t net_size; uint8_t *net_bytes; + /* output */ uint32_t net_offset; /* Increment `host_extra` to pre-allocate space that is * "extra" beyond sizeof(). */ @@ -51,9 +53,11 @@ struct _validate_ctx { typedef bool (*_validate_fn_t)(struct _validate_ctx *ctx); struct _unmarshal_ctx { + /* input */ struct lib9p_ctx *ctx; uint8_t *net_bytes; + /* output */ uint32_t net_offset; /* `extra` points to the beginning of unallocated space. */ void *extra; @@ -61,8 +65,10 @@ struct _unmarshal_ctx { typedef void (*_unmarshal_fn_t)(struct _unmarshal_ctx *ctx, void *out); struct _marshal_ctx { + /* input */ struct lib9p_ctx *ctx; + /* output */ uint8_t *net_bytes; uint32_t net_offset; }; diff --git a/lib9p/map.h b/lib9p/map.h index b59c83d..ab9564f 100644 --- a/lib9p/map.h +++ b/lib9p/map.h @@ -1,6 +1,6 @@ -/* lib9p/map.h - A really dumb map/dict data structur +/* lib9p/map.h - A really dumb map/dict data structure * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ diff --git a/lib9p/srv.c b/lib9p/srv.c index 0e58068..9837994 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -205,12 +205,12 @@ static void respond_error(struct _lib9p_srv_req *req) { /* read coroutine *************************************************************/ -static bool read_at_least(lo_interface net_stream_conn fd, uint8_t *buf, size_t goal, size_t *done) { +static bool read_exactly(lo_interface net_stream_conn fd, uint8_t *buf, size_t goal, size_t *done) { assert(buf); assert(goal); assert(done); while (*done < goal) { - ssize_t r = LO_CALL(fd, read, &buf[*done], CONFIG_9P_MAX_MSG_SIZE - *done); + ssize_t r = LO_CALL(fd, read, &buf[*done], goal - *done); if (r < 0) { nonrespond_errorf("read: %s", net_strerror(-r)); return true; @@ -263,14 +263,14 @@ static void handle_message(struct _lib9p_srv_req *ctx); nextmsg: /* Read the message. */ size_t done = 0; - if (read_at_least(conn.fd, buf, 4, &done)) + if (read_exactly(conn.fd, buf, 4, &done)) goto close; size_t goal = uint32le_decode(buf); if (goal < 7) { nonrespond_errorf("T-message is impossibly small"); goto close; } - if (read_at_least(conn.fd, buf, 7, &done)) + if (read_exactly(conn.fd, buf, 7, &done)) goto close; struct _lib9p_srv_req req = { .parent_sess = &sess, @@ -292,7 +292,7 @@ static void handle_message(struct _lib9p_srv_req *ctx); respond_error(&req); goto nextmsg; } - if (read_at_least(conn.fd, buf, goal, &done)) + if (read_exactly(conn.fd, buf, goal, &done)) goto close; /* Handle the message... */ |