summaryrefslogtreecommitdiff
path: root/lib9p
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p')
-rw-r--r--lib9p/types.c6
-rwxr-xr-xlib9p/types.gen111
2 files changed, 65 insertions, 52 deletions
diff --git a/lib9p/types.c b/lib9p/types.c
index 071e3c8..f4718b6 100644
--- a/lib9p/types.c
+++ b/lib9p/types.c
@@ -805,6 +805,12 @@ struct _vtable_version _lib9p_vtables[LIB9P_VER_NUM] = {
.unmarshal = (_unmarshal_fn_t)unmarshal_Rversion,
.marshal = (_marshal_fn_t)marshal_Rversion,
},
+ [LIB9P_TYP_Rerror] = {
+ .unmarshal_basesize = sizeof(struct lib9p_msg_Rerror),
+ .unmarshal_extrasize = checksize_Rerror,
+ .unmarshal = (_unmarshal_fn_t)unmarshal_Rerror,
+ .marshal = (_marshal_fn_t)marshal_Rerror,
+ },
}},
[LIB9P_VER_9P2000] = { .msgs = {
[LIB9P_TYP_Tversion] = {
diff --git a/lib9p/types.gen b/lib9p/types.gen
index 44eebbe..70f4697 100755
--- a/lib9p/types.gen
+++ b/lib9p/types.gen
@@ -10,6 +10,10 @@ import os.path
import re
from typing import Callable
+# This strives to be "general-purpose" in that it just acts on the
+# *.txt inputs; but (unfortunately?) there are a few special-cases in
+# this script, marked with "SPECIAL".
+
# Parse *.txt ##################################################################
@@ -392,54 +396,54 @@ static inline bool _checksize_list(struct _checksize_ctx *ctx,
ret += "}\n"
continue
+ if struct.name == "d": # SPECIAL
+ # Optimize... maybe the compiler could figure out to do
+ # this, but let's make it obvious.
+ ret += "\n"
+ ret += "\tuint32_t base_offset = ctx->net_offset;\n"
+ ret += "\tif (checksize_4(ctx))\n"
+ ret += "\t\treturn true;\n"
+ ret += "\tuint32_t len = decode_u32le(&ctx->net_bytes[base_offset]);\n"
+ ret += "\treturn _checksize_net(ctx, len) || _checksize_host(ctx, len);\n"
+ ret += "}\n"
+ continue
+ if struct.name == "s": # SPECIAL
+ # Add an extra nul-byte on the host, and validate UTF-8
+ # (also, similar optimization to "d").
+ ret += "\n"
+ ret += "\tuint32_t base_offset = ctx->net_offset;\n"
+ ret += "\tif (checksize_2(ctx))\n"
+ ret += "\t\treturn true;\n"
+ ret += "\tuint16_t len = decode_u16le(&ctx->net_bytes[base_offset]);\n"
+ ret += "\tif (_checksize_net(ctx, len) || _checksize_host(ctx, ((size_t)len)+1))\n"
+ ret += "\t\treturn true;\n"
+ ret += "\tif (!is_valid_utf8_without_nul(&ctx->net_bytes[base_offset+2], len))\n"
+ ret += '\t\treturn lib9p_error(ctx->ctx, LINUX_EBADMSG, "message contains invalid UTF-8");\n'
+ ret += "\treturn false;\n"
+ ret += "}\n"
+ continue
+
prefix0 = "\treturn "
prefix1 = "\t || "
- match struct.name:
- case "d":
- # Optimize... maybe the compiler could figure out to do
- # this, but let's make it obvious.
- ret += "\n"
- ret += "\tuint32_t base_offset = ctx->net_offset;\n"
- ret += "\tif (checksize_4(ctx))\n"
- ret += "\t\treturn true;\n"
- ret += "\tuint32_t len = decode_u32le(&ctx->net_bytes[base_offset]);\n"
- ret += (
- "\treturn _checksize_net(ctx, len) || _checksize_host(ctx, len);\n"
- )
- ret += "}\n"
- case "s":
- # Add an extra nul-byte on the host, and validate
- # UTF-8 (also, similar optimization to "d").
- ret += "\n"
- ret += "\tuint32_t base_offset = ctx->net_offset;\n"
- ret += "\tif (checksize_2(ctx))\n"
- ret += "\t\treturn true;\n"
- ret += "\tuint16_t len = decode_u16le(&ctx->net_bytes[base_offset]);\n"
- ret += "\tif (_checksize_net(ctx, len) || _checksize_host(ctx, ((size_t)len)+1))\n"
- ret += "\t\treturn true;\n"
- ret += "\tif (!is_valid_utf8_without_nul(&ctx->net_bytes[base_offset+2], len))\n"
- ret += '\t\treturn lib9p_error(ctx->ctx, LINUX_EBADMSG, "message contains invalid UTF-8");\n'
- ret += "\treturn false;\n"
- ret += "}\n"
- case _:
- struct_versions = struct.members[0].ver
- prefix = prefix0
- prev_size: int | None = None
- for member in struct.members:
- ret += f"\n{prefix}"
- if member.ver != struct_versions:
- ret += "( " + c_vercond(idprefix, member.ver) + " && "
- if member.cnt is not None:
- assert prev_size
- ret += f"_checksize_list(ctx, decode_u{prev_size*8}le(&ctx->net_bytes[ctx->net_offset-{prev_size}]), checksize_{member.typ.name}, sizeof({c_typename(idprefix, member.typ)}))"
- else:
- ret += f"checksize_{member.typ.name}(ctx)"
- if member.ver != struct_versions:
- ret += " )"
- prefix = prefix1
- prev_size = member.static_size
- ret += ";\n}\n"
+ struct_versions = struct.members[0].ver
+
+ prefix = prefix0
+ prev_size: int | None = None
+ for member in struct.members:
+ ret += f"\n{prefix}"
+ if member.ver != struct_versions:
+ ret += "( " + c_vercond(idprefix, member.ver) + " && "
+ if member.cnt is not None:
+ assert prev_size
+ ret += f"_checksize_list(ctx, decode_u{prev_size*8}le(&ctx->net_bytes[ctx->net_offset-{prev_size}]), checksize_{member.typ.name}, sizeof({c_typename(idprefix, member.typ)}))"
+ else:
+ ret += f"checksize_{member.typ.name}(ctx)"
+ if member.ver != struct_versions:
+ ret += " )"
+ prefix = prefix1
+ prev_size = member.static_size
+ ret += ";\n}\n"
# unmarshal_* ##############################################################
ret += """
@@ -547,7 +551,7 @@ static inline bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) {
ret += "}\n"
continue
- if struct.name == "Rerror":
+ if struct.name == "Rerror": # SPECIAL
ret += "\n\t/* Truncate the error-string if necessary to avoid returning ERANGE. */"
ret += "\n\tif (((uint32_t)val->ename.len) + ctx->ctx->Rerror_overhead > ctx->ctx->max_msg_size)"
ret += "\n\t\tval->ename.len = ctx->ctx->max_msg_size - ctx->ctx->Rerror_overhead;"
@@ -584,24 +588,27 @@ static inline bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) {
ret += f"\t\t\t.unmarshal_extrasize = checksize_{msg.name},\n"
ret += f"\t\t\t.unmarshal = (_unmarshal_fn_t)unmarshal_{msg.name},\n"
ret += f"\t\t\t.marshal = (_marshal_fn_t)marshal_{msg.name},\n"
- ret += "\t\t}"
+ ret += "\t\t},\n"
return ret
ret += f"""
/* vtables ********************************************************************/
struct _vtable_version _{idprefix}vtables[LIB9P_VER_NUM] = {{
- [{idprefix.upper()}VER_UNINITIALIZED] = {{ .msgs = {{
-{msg_entry(next(msg for msg in structs if msg.name == 'Tversion'))},
-{msg_entry(next(msg for msg in structs if msg.name == 'Rversion'))},
- }}}},
"""
+
+ ret += f"\t[{idprefix.upper()}VER_UNINITIALIZED] = {{ .msgs = {{\n"
+ for msg in structs:
+ if msg.name in ["Tversion", "Rversion", "Rerror"]: # SPECIAL
+ ret += msg_entry(msg)
+ ret += "\t}},\n"
+
for ver in sorted(versions):
ret += f"\t[{c_verenum(idprefix, ver)}] = {{ .msgs = {{\n"
for msg in structs:
if ver not in msg.msgver:
continue
- ret += msg_entry(msg) + ",\n"
+ ret += msg_entry(msg)
ret += "\t}},\n"
ret += "};\n"