diff options
45 files changed, 2280 insertions, 1691 deletions
diff --git a/.editorconfig b/.editorconfig index b7ad057..42c5a67 100644 --- a/.editorconfig +++ b/.editorconfig @@ -48,7 +48,7 @@ _mode = gitignore [{build-aux/embed-sources.h.gen,build-aux/valgrind}] _mode = sh -[{build-aux/lint-{src,bin},build-aux/gcov-prune,libusb/include/libusb/tusb_helpers.h.gen}] +[{build-aux/lint-{src,bin},build-aux/gcov-prune,libmisc/error_generated.c.gen,libusb/include/libusb/tusb_helpers.h.gen}] _mode = bash [{build-aux/stack.c.gen,libmisc/wrap-cc}] @@ -70,7 +70,7 @@ _mode = 9p-log [lib9p/tests/test_server/static.h.gen] _mode = sh -[{lib9p/linux-errno.txt.gen,lib9p/tests/test_compile.c.gen,lib9p/tests/runtest,lib9p/tests/testclient-p9p}] +[{lib9p/linux-errno.txt.gen,lib9p/srv_generated.c.gen,lib9p/tests/test_compile.c.gen,lib9p/tests/runtest,lib9p/tests/testclient-p9p}] _mode = bash [{lib9p/core.gen,lib9p/idl/2010-9P2000.L.9p.gen}] diff --git a/GNUmakefile b/GNUmakefile index fa76266..51f01aa 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -37,6 +37,10 @@ generate/files += 3rd-party/linux-errno.txt 3rd-party/linux-errno.txt: lib9p/linux-errno.txt.gen $< $(linux.git) $@ +generate/files += libmisc/error_generated.c +libmisc/error_generated.c: %: %.gen libmisc/include/libmisc/error.h + $^ $@ + generate/files += lib9p/idl/2010-9P2000.L.9p lib9p/idl/2010-9P2000.L.9p: %: %.gen 3rd-party/linux-errno.txt $^ >$@ @@ -45,6 +49,10 @@ generate/files += lib9p/core_generated.c lib9p/core_include/lib9p/_core_generate lib9p/core_generated.c lib9p/core_include/lib9p/_core_generated.h &: lib9p/core.gen lib9p/idl/__init__.py lib9p/core_gen lib9p/core_gen/*.py lib9p/idl lib9p/idl/2010-9P2000.L.9p lib9p/idl/*.9p $< $(sort $(filter %.9p,$^)) +generate/files += lib9p/srv_generated.c +lib9p/srv_generated.c: %: %.gen libmisc/include/libmisc/error.h + $^ $@ + generate/files += lib9p/tests/test_compile.c lib9p/tests/test_compile.c: %: %.gen lib9p/core_include/lib9p/_core_generated.h $^ $@ diff --git a/cmd/sbc_harness/config/config.h b/cmd/sbc_harness/config/config.h index 7a91001..61745e5 100644 --- a/cmd/sbc_harness/config/config.h +++ b/cmd/sbc_harness/config/config.h @@ -37,8 +37,6 @@ /* 9P *************************************************************************/ -#define CONFIG_9P_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ - #define CONFIG_9P_ENABLE_9P2000 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_e 0 /* bool */ @@ -67,6 +65,7 @@ * (8*1024)+160 in 2e and 3e. */ #define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) +#define CONFIG_9P_SRV_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ /** * Maximum host-data-structure size. A message may be larger in * unmarshaled-host-structures than marshaled-net-bytes due to (1) diff --git a/cmd/sbc_harness/fs_harness_flash_bin.c b/cmd/sbc_harness/fs_harness_flash_bin.c index 8bd144e..ea60447 100644 --- a/cmd/sbc_harness/fs_harness_flash_bin.c +++ b/cmd/sbc_harness/fs_harness_flash_bin.c @@ -148,11 +148,11 @@ static struct lib9p_qid flash_file_qid(struct flash_file *self) { }; } -static struct lib9p_srv_stat flash_file_stat(struct flash_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error flash_file_stat(struct flash_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = flash_file_qid(self), .mode = LIB9P_DM_EXCL|0666, .atime_sec = UTIL9P_ATIME, @@ -163,25 +163,25 @@ static struct lib9p_srv_stat flash_file_stat(struct flash_file *self, struct lib .owner_gid = { .name = lib9p_str("root"), .num = 0 }, .last_modifier_uid = { .name = lib9p_str("root"), .num = 0 }, .extension = lib9p_str(NULL), - }; + })); } -static void flash_file_wstat(struct flash_file *self, struct lib9p_srv_ctx *ctx, +static error flash_file_wstat(struct flash_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); + return error_new(E_POSIX_EROFS, "read-only part of filesystem"); } -static void flash_file_remove(struct flash_file *self, struct lib9p_srv_ctx *ctx) { +static error flash_file_remove(struct flash_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); + return error_new(E_POSIX_EROFS, "read-only part of filesystem"); } LIB9P_SRV_NOTDIR(struct flash_file, flash_file); -static lo_interface lib9p_srv_fio flash_file_fopen(struct flash_file *self, struct lib9p_srv_ctx *ctx, +static lib9p_srv_fio_or_error flash_file_fopen(struct flash_file *self, struct lib9p_srv_ctx *ctx, bool rd, bool wr, bool trunc) { assert(self); assert(ctx); @@ -201,7 +201,7 @@ static lo_interface lib9p_srv_fio flash_file_fopen(struct flash_file *self, stru self->wbuf.ok = false; } - return LO_BOX(lib9p_srv_fio, self); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, self)); } /* srv_fio ********************************************************************/ @@ -221,18 +221,13 @@ static void flash_file_iofree(struct flash_file *self) { ab_flash_finalize(self->wbuf.dat); } -static void flash_file_pread(struct flash_file *self, struct lib9p_srv_ctx *ctx, - uint32_t byte_count, uint64_t byte_offset, - struct iovec *ret) { +static iovec_or_error flash_file_pread(struct flash_file *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t byte_offset) { assert(self); assert(ctx); - assert(ret); - if (byte_offset > DATA_SIZE) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "offset is past the chip size"); - return; - } + if (byte_offset > DATA_SIZE) + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EINVAL, "offset is past the chip size")); /* Assume that somewhere down the line the iovec we return * will be passed to DMA. We don't want the DMA engine to hit @@ -241,12 +236,10 @@ static void flash_file_pread(struct flash_file *self, struct lib9p_srv_ctx *ctx, * data to a buffer in (fast) RAM first. It's lame that the * DMA engine can only have a DREQ on one side of the channel. */ - if (byte_offset == DATA_SIZE) { - *ret = (struct iovec){ + if (byte_offset == DATA_SIZE) + return ERROR_NEW_VAL(iovec, ((struct iovec){ .iov_len = 0, - }; - return; - } + })); size_t sector_base = LM_ROUND_DOWN(byte_offset, FLASH_SECTOR_SIZE); if (byte_offset + byte_count > sector_base + FLASH_SECTOR_SIZE) byte_count = (sector_base + FLASH_SECTOR_SIZE) - byte_offset; @@ -258,34 +251,28 @@ static void flash_file_pread(struct flash_file *self, struct lib9p_srv_ctx *ctx, memcpy(self->rbuf.dat, DATA_START+sector_base, FLASH_SECTOR_SIZE); } - *ret = (struct iovec){ + return ERROR_NEW_VAL(iovec, ((struct iovec){ .iov_base = &self->rbuf.dat[byte_offset-sector_base], .iov_len = byte_count, - }; + })); } /* TODO: Short/corrupt writes are dangerous. This should either (1) * check a checksum, (2) use uf2 instead of verbatim data, or (3) use * ihex instead of verbatim data. */ -static uint32_t flash_file_pwrite(struct flash_file *self, struct lib9p_srv_ctx *ctx, - void *buf, - uint32_t byte_count, - uint64_t byte_offset) { +static uint32_t_or_error flash_file_pwrite(struct flash_file *self, struct lib9p_srv_ctx *ctx, + void *buf, + uint32_t byte_count, + uint64_t byte_offset) { assert(self); assert(ctx); - if (byte_offset > DATA_HSIZE) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "offset is past half the chip size"); - return 0; - } + if (byte_offset > DATA_HSIZE) + return ERROR_NEW_ERR(uint32_t, error_new(E_POSIX_EINVAL, "offset is past half the chip size")); if (byte_count == 0) - return 0; - if (byte_offset == DATA_HSIZE) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "offset is at half the chip size"); - return 0; - } + return ERROR_NEW_VAL(uint32_t, 0); + if (byte_offset == DATA_HSIZE) + return ERROR_NEW_ERR(uint32_t, error_new(E_POSIX_EINVAL, "offset is at half the chip size")); size_t sector_base = LM_ROUND_DOWN(byte_offset, FLASH_SECTOR_SIZE); if (byte_offset + byte_count > sector_base + FLASH_SECTOR_SIZE) @@ -303,5 +290,5 @@ static uint32_t flash_file_pwrite(struct flash_file *self, struct lib9p_srv_ctx memcpy(&self->wbuf.dat[byte_offset-sector_base], buf, byte_count); self->written = true; - return byte_count; + return ERROR_NEW_VAL(uint32_t, byte_count); } diff --git a/cmd/sbc_harness/fs_harness_uptime_txt.c b/cmd/sbc_harness/fs_harness_uptime_txt.c index 23ac9d4..021a8bd 100644 --- a/cmd/sbc_harness/fs_harness_uptime_txt.c +++ b/cmd/sbc_harness/fs_harness_uptime_txt.c @@ -37,7 +37,7 @@ static struct lib9p_qid uptime_file_qid(struct uptime_file *self) { }; } -static struct lib9p_srv_stat uptime_file_stat(struct uptime_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error uptime_file_stat(struct uptime_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); @@ -51,7 +51,7 @@ static struct lib9p_srv_stat uptime_file_stat(struct uptime_file *self, struct l size++; size += 3; - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = uptime_file_qid(self), .mode = 0444, .atime_sec = UTIL9P_ATIME, @@ -62,26 +62,26 @@ static struct lib9p_srv_stat uptime_file_stat(struct uptime_file *self, struct l .owner_gid = { .name = lib9p_str("root"), .num = 0 }, .last_modifier_uid = { .name = lib9p_str("root"), .num = 0 }, .extension = lib9p_str(NULL), - }; + })); } -static void uptime_file_wstat(struct uptime_file *self, struct lib9p_srv_ctx *ctx, - struct lib9p_srv_stat) { +static error uptime_file_wstat(struct uptime_file *self, struct lib9p_srv_ctx *ctx, + struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); + return error_new(E_POSIX_EROFS, "read-only part of filesystem"); } -static void uptime_file_remove(struct uptime_file *self, struct lib9p_srv_ctx *ctx) { +static error uptime_file_remove(struct uptime_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); + return error_new(E_POSIX_EROFS, "read-only part of filesystem"); } LIB9P_SRV_NOTDIR(struct uptime_file, uptime_file); -static lo_interface lib9p_srv_fio uptime_file_fopen(struct uptime_file *self, struct lib9p_srv_ctx *ctx, - bool LM_UNUSED(rd), bool LM_UNUSED(wr), bool LM_UNUSED(trunc)) { +static lib9p_srv_fio_or_error uptime_file_fopen(struct uptime_file *self, struct lib9p_srv_ctx *ctx, + bool LM_UNUSED(rd), bool LM_UNUSED(wr), bool LM_UNUSED(trunc)) { assert(self); assert(ctx); @@ -89,7 +89,7 @@ static lo_interface lib9p_srv_fio uptime_file_fopen(struct uptime_file *self, st ret->parent = self; ret->buf_len = 0; - return LO_BOX(lib9p_srv_fio, ret); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); } /* srv_fio ********************************************************************/ @@ -110,41 +110,35 @@ static struct lib9p_qid uptime_fio_qid(struct uptime_fio *self) { return uptime_file_qid(self->parent); } -static void uptime_fio_pread(struct uptime_fio *self, struct lib9p_srv_ctx *ctx, - uint32_t byte_count, uint64_t byte_offset, - struct iovec *ret) { +static iovec_or_error uptime_fio_pread(struct uptime_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t byte_offset) { assert(self); assert(ctx); - assert(ret); if (byte_offset == 0 || self->buf_len == 0) { uint64_t now = LO_CALL(bootclock, get_time_ns); self->buf_len = fmt_snprint(self->buf, sizeof(self->buf), now, "ns\n"); } - if (byte_offset > (uint64_t)self->buf_len) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "offset is past end-of-file length"); - return; - } + if (byte_offset > (uint64_t)self->buf_len) + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EINVAL, "offset is past end-of-file length")); size_t beg_off = (size_t)byte_offset; size_t end_off = beg_off + (size_t)byte_count; if (end_off > self->buf_len) end_off = self->buf_len; - *ret = (struct iovec){ + return ERROR_NEW_VAL(iovec, ((struct iovec){ .iov_base = &self->buf[beg_off], .iov_len = end_off-beg_off, - }; + })); } -static uint32_t uptime_fio_pwrite(struct uptime_fio *self, struct lib9p_srv_ctx *ctx, +static uint32_t_or_error uptime_fio_pwrite(struct uptime_fio *self, struct lib9p_srv_ctx *ctx, void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset)) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); - return 0; + return ERROR_NEW_ERR(uint32_t, error_new(E_POSIX_EROFS, "read-only part of filesystem")); } diff --git a/cmd/sbc_harness/main.c b/cmd/sbc_harness/main.c index d32b775..82519ae 100644 --- a/cmd/sbc_harness/main.c +++ b/cmd/sbc_harness/main.c @@ -114,8 +114,8 @@ static struct lib9p_srv_file root = ), ); -static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { - return root; +static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { + return ERROR_NEW_VAL(lib9p_srv_file, root); } /* Code ***********************************************************************/ diff --git a/lib9p/CMakeLists.txt b/lib9p/CMakeLists.txt index 3433417..e81e7b9 100644 --- a/lib9p/CMakeLists.txt +++ b/lib9p/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(lib9p_srv INTERFACE) target_include_directories(lib9p_srv PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/srv_include) target_sources(lib9p_srv INTERFACE srv.c + srv_generated.c ) target_link_libraries(lib9p_srv INTERFACE lib9p_core diff --git a/lib9p/core.c b/lib9p/core.c index d64e23a..58fe538 100644 --- a/lib9p/core.c +++ b/lib9p/core.c @@ -45,21 +45,6 @@ bool lib9p_str_eq(struct lib9p_s a, struct lib9p_s b) { (a.len == 0 || memcmp(a.utf8, b.utf8, a.len) == 0); } -/* ctx ************************************************************************/ - -void lib9p_ctx_clear_error(struct lib9p_ctx *ctx) { - assert(ctx); -#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L - ctx->err_num = 0; -#endif - ctx->err_msg[0] = '\0'; -} - -bool lib9p_ctx_has_error(struct lib9p_ctx *ctx) { - assert(ctx); - return ctx->err_msg[0]; -} - /* bounds checks **************************************************************/ static inline void assert_ver(enum lib9p_version ver) { @@ -109,29 +94,31 @@ void fmt_print_lib9p_msg(lo_interface fmt_dest w, struct lib9p_ctx *ctx, enum li _lib9p_table_msg[ctx->version][typ].print(w, ctx, body); } -#define _lib9p_validate(LOW_TYP_BIT, ERRMSG, TABLE) do { \ - assert_ver(ctx->version); \ - /* Inspect the first 5 bytes ourselves. */ \ - uint32_t net_size = uint32le_decode(net_bytes); \ - if (net_size < 5) \ - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message is impossibly short"); \ - uint8_t typ = net_bytes[4]; \ - if (typ % 2 != LOW_TYP_BIT) \ - return lib9p_error(ctx, LIB9P_ERRNO_L_EOPNOTSUPP, ERRMSG ": message_type=", lib9p_msgtype_str(ctx->version, typ)); \ - struct _lib9p_recv_tentry tentry = TABLE[ctx->version][typ/2]; \ - if (!tentry.validate) \ - return lib9p_error(ctx, LIB9P_ERRNO_L_EOPNOTSUPP, "unknown message type: ", lib9p_msgtype_str(ctx->version, typ), \ - " (protocol_version=", lib9p_version_str(ctx->version), ")"); \ - \ - /* Now use the message-type-specific tentry to process the whole thing. */ \ - return tentry.validate(ctx, net_size, net_bytes); \ +#define _lib9p_validate(LOW_TYP_BIT, ERRMSG, TABLE) do { \ + assert_ver(ctx->version); \ + /* Inspect the first 5 bytes ourselves. */ \ + uint32_t net_size = uint32le_decode(net_bytes); \ + if (net_size < 5) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is impossibly short")); \ + uint8_t typ = net_bytes[4]; \ + if (typ % 2 != LOW_TYP_BIT) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EOPNOTSUPP, ERRMSG ": message_type=", \ + lib9p_msgtype_str(ctx->version, typ))); \ + struct _lib9p_recv_tentry tentry = TABLE[ctx->version][typ/2]; \ + if (!tentry.validate) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EOPNOTSUPP, "unknown message type: ", \ + lib9p_msgtype_str(ctx->version, typ), \ + " (protocol_version=", lib9p_version_str(ctx->version), ")")); \ + \ + /* Now use the message-type-specific tentry to process the whole thing. */ \ + return tentry.validate(ctx, net_size, net_bytes); \ } while (0) -ssize_t lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) { +size_t_or_error lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) { _lib9p_validate(0, "expected a T-message but got an R-message", _lib9p_table_Tmsg_recv); } -ssize_t lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) { +size_t_or_error lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes) { _lib9p_validate(1, "expected an R-message but got a T-message", _lib9p_table_Rmsg_recv); } @@ -171,20 +158,20 @@ void lib9p_Rmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, struct _lib9p_send_tentry tentry = TABLE[ctx->version][typ/2]; \ assert(tentry.marshal); \ \ - bool ret_erred = tentry.marshal(ctx, body, &_ret); \ + error ret_err = tentry.marshal(ctx, body, &_ret); \ if (_ret.net_iov[_ret.net_iov_cnt-1].iov_len == 0) \ _ret.net_iov_cnt--; \ \ ret->iov_cnt = _ret.net_iov_cnt; \ - return ret_erred; \ + return ret_err; \ } while (0) -bool lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, +error lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, struct lib9p_Tmsg_send_buf *ret) { _lib9p_marshal(0, _lib9p_table_Tmsg_send); } -bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, +error lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, struct lib9p_Rmsg_send_buf *ret) { _lib9p_marshal(1, _lib9p_table_Rmsg_send); } @@ -192,14 +179,14 @@ bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *bo /* `struct lib9p_stat` helpers ************************************************/ #if _LIB9P_ENABLE_stat -bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, +error lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size, size_t *ret_host_size) { - ssize_t host_size = _lib9p_stat_validate(ctx, net_size, net_bytes, ret_net_size); - if (host_size < 0) - return true; + size_t_or_error host_size = _lib9p_stat_validate(ctx, net_size, net_bytes, ret_net_size); + if (host_size.is_err) + return host_size.err; if (ret_host_size) - *ret_host_size = (size_t)host_size; - return false; + *ret_host_size = host_size.size_t; + return ERROR_NULL; } void lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, diff --git a/lib9p/core_gen/c.py b/lib9p/core_gen/c.py index 0947ec2..ab34387 100644 --- a/lib9p/core_gen/c.py +++ b/lib9p/core_gen/c.py @@ -175,7 +175,7 @@ def gen_c(versions: set[str], typs: list[idl.UserType]) -> str: ret += f""" {cutil.ifdef_push(1, c9util.ver_ifdef(next(typ for typ in typs if typ.typname == 'stat').in_versions)).rstrip()} -LM_FLATTEN ssize_t {c9util.ident('_stat_validate')}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{ +LM_FLATTEN size_t_or_error {c9util.ident('_stat_validate')}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{ \treturn validate_stat(ctx, net_size, net_bytes, ret_net_size); }} LM_FLATTEN void {c9util.ident('_stat_unmarshal')}(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out) {{ diff --git a/lib9p/core_gen/c_marshal.py b/lib9p/core_gen/c_marshal.py index bddf55f..86d82e4 100644 --- a/lib9p/core_gen/c_marshal.py +++ b/lib9p/core_gen/c_marshal.py @@ -365,7 +365,10 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str: assert isinstance(typ, idl.Struct) ret += "\n" ret += cutil.ifdef_push(1, c9util.ver_ifdef(typ.in_versions)) - ret += f"static bool marshal_{typ.typname}(struct lib9p_ctx *ctx, {c9util.typename(typ)} *val, struct _marshal_ret *ret) {{\n" + if not isinstance(typ, idl.Message): # SPECIAL (bool for stat) + ret += f"static bool marshal_{typ.typname}(struct lib9p_ctx *ctx, {c9util.typename(typ)} *val, struct _marshal_ret *ret) {{\n" + else: + ret += f"static error marshal_{typ.typname}(struct lib9p_ctx *ctx, {c9util.typename(typ)} *val, struct _marshal_ret *ret) {{\n" # Pass 1 - check size max_size = max(typ.max_size(v) for v in typ.in_versions) @@ -380,11 +383,12 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str: ret += "\tif (needed_size > (uint64_t)(ctx->max_msg_size)) {\n" else: ret += "\tif (needed_size > ctx->max_msg_size) {\n" - if isinstance(typ, idl.Message): # SPECIAL (disable for stat) - ret += f'\t\tlib9p_error(ctx, {c9util.IDENT("ERRNO_L_ERANGE")}, "{typ.typname} message too large to marshal into ",\n' + if not isinstance(typ, idl.Message): # SPECIAL (bool for stat) + ret += "\t\treturn true;\n" + else: + ret += f'\t\treturn error_new(E_POSIX_ERANGE, "{typ.typname} message too large to marshal into ",\n' ret += f'\t\t\tctx->version ? "negotiated" : "{'client' if typ.msgid % 2 == 0 else 'server'}", " limit",\n' ret += '\t\t\t" (", needed_size, " > ", ctx->max_msg_size, ")");\n' - ret += "\t\treturn true;\n" ret += "\t}\n" # Pass 2 - write data @@ -396,7 +400,10 @@ def gen_c_marshal(versions: set[str], typs: list[idl.UserType]) -> str: ret += cutil.ifdef_pop(ifdef_lvl()) # Return - ret += "\treturn false;\n" + if not isinstance(typ, idl.Message): # SPECIAL (bool for stat) + ret += "\treturn false;\n" + else: + ret += "\treturn ERROR_NULL;\n" ret += "}\n" ret += cutil.ifdef_pop(0) return ret diff --git a/lib9p/core_gen/c_validate.py b/lib9p/core_gen/c_validate.py index 8997237..1bfe329 100644 --- a/lib9p/core_gen/c_validate.py +++ b/lib9p/core_gen/c_validate.py @@ -57,9 +57,9 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: "\t\t/* If needed-net-size overflowed uint32_t, then\n" "\t\t * there's no way that actual-net-size will live up to\n" "\t\t * that. */\n" - f'\t\treturn lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EBADMSG")}, "message is too short for content");\n' + '\t\treturn ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content"));\n' "\tif (net_offset > net_size)\n" - f'\t\treturn lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EBADMSG")}, "message is too short for content (", net_offset, " > ", net_size, ")");\n' + '\t\treturn ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content (", net_offset, " > ", net_size, ")"));\n' ) ret += cutil.macro( "#define VALIDATE_NET_UTF8(n)\n" @@ -67,16 +67,16 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: "\t\tsize_t len = n;\n" "\t\tVALIDATE_NET_BYTES(len);\n" "\t\tif (!utf8_is_valid_without_nul(&net_bytes[net_offset-len], len))\n" - f'\t\t\treturn lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EILSEQ")}, "message contains invalid UTF-8");\n' + '\t\t\treturn ERROR_NEW_ERR(size_t, error_new(E_POSIX_EILSEQ, "message contains invalid UTF-8"));\n' "\t}\n" ) ret += cutil.macro( "#define RESERVE_HOST_BYTES(n)\n" "\tif (__builtin_add_overflow(host_size, n, &host_size))\n" - "\t\t/* If needed-host-size overflowed ssize_t, then there's\n" + "\t\t/* If needed-host-size overflowed size_t, then there's\n" "\t\t * no way that actual-net-size will live up to\n" "\t\t * that. */\n" - f'\t\treturn lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EBADMSG")}, "message is too short for content");\n' + '\t\treturn ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content"));\n' ) ret += "#define GET_U8LE(off) (net_bytes[off])\n" @@ -193,7 +193,7 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: act = f"GET_U{nbits}LE({lookup_sym(f'&{child.membname}')})" exp = f"{c9util.idl_expr(child.val, lookup_sym)}" ret += f"{'\t'*indent_lvl()}if ({act} != {exp})\n" - ret += f'{"\t"*(indent_lvl()+1)}return lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EBADMSG")}, "{path} value is wrong: actual:", (base10, {act}), " != correct:", (base10, {exp}));\n' + ret += f'{"\t"*(indent_lvl()+1)}return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "{path} value is wrong: actual:", (base10, {act}), " != correct:", (base10, {exp})));\n' if child.max: incr_flush() assert child.typ.static_size @@ -207,15 +207,15 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: act = f"GET_U{nbits}LE({lookup_sym(f'&{child.membname}')})" exp = f"{c9util.idl_expr(child.max, lookup_sym)}" ret += f"{'\t'*indent_lvl()}if ({act} > {exp})\n" - ret += f'{"\t"*(indent_lvl()+1)}return lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EBADMSG")}, "{path} value is too large: ", (base10, {act}), " > ", (base10, {exp}));\n' + ret += f'{"\t"*(indent_lvl()+1)}return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "{path} value is too large: ", (base10, {act}), " > ", (base10, {exp})));\n' if isinstance(child.typ, idl.Bitfield): incr_flush() nbytes = child.typ.static_size nbits = nbytes * 8 act = f"GET_U{nbits}LE({lookup_sym(f'&{child.membname}')})" ret += f"{'\t'*indent_lvl()}if ({act} & ~{child.typ.typname}_masks[ctx->version])\n" - ret += f'{"\t"*(indent_lvl()+1)}return lib9p_error(ctx, {c9util.IDENT("ERRNO_L_EBADMSG")}, "unknown bits in {child.typ.typname} bitfield: ",\n' - ret += f"{'\t'*(indent_lvl()+2)}(base16_u{nbits}_, {act} & ~{child.typ.typname}_masks[ctx->version]));\n" + ret += f'{"\t"*(indent_lvl()+1)}return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in {child.typ.typname} bitfield: ",\n' + ret += f"{'\t'*(indent_lvl()+2)}(base16_u{nbits}_, {act} & ~{child.typ.typname}_masks[ctx->version])));\n" def handle( path: idlutil.Path, @@ -271,12 +271,12 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: ret += "\n" ret += cutil.ifdef_push(1, c9util.ver_ifdef(typ.in_versions)) if typ.typname == "stat": # SPECIAL (stat) - ret += f"static ssize_t validate_{typ.typname}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{\n" + ret += f"static size_t_or_error validate_{typ.typname}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{\n" else: - ret += f"static ssize_t validate_{typ.typname}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) {{\n" + ret += f"static size_t_or_error validate_{typ.typname}([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) {{\n" ret += "\tuint32_t net_offset = 0;\n" - ret += f"\tssize_t host_size = sizeof({c9util.typename(typ)});\n" + ret += f"\tsize_t host_size = sizeof({c9util.typename(typ)});\n" incr_buf = 0 indent_stack = [IndentLevel(ifdef=True)] @@ -291,7 +291,7 @@ def gen_c_validate(versions: set[str], typs: list[idl.UserType]) -> str: if typ.typname == "stat": # SPECIAL (stat) ret += "\tif (ret_net_size)\n" ret += "\t\t*ret_net_size = net_offset;\n" - ret += "\treturn (ssize_t)host_size;\n" + ret += "\treturn ERROR_NEW_VAL(size_t, host_size);\n" ret += "}\n" ret += cutil.ifdef_pop(0) return ret diff --git a/lib9p/core_generated.c b/lib9p/core_generated.c index ad7b210..08ab4f0 100644 --- a/lib9p/core_generated.c +++ b/lib9p/core_generated.c @@ -221,27 +221,27 @@ static const lib9p_lock_flags_t lock_flags_masks[LIB9P_VER_NUM] = { /* validate_* *****************************************************************/ -#define VALIDATE_NET_BYTES(n) \ - if (__builtin_add_overflow(net_offset, n, &net_offset)) \ - /* If needed-net-size overflowed uint32_t, then \ - * there's no way that actual-net-size will live up to \ - * that. */ \ - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message is too short for content"); \ - if (net_offset > net_size) \ - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message is too short for content (", net_offset, " > ", net_size, ")"); -#define VALIDATE_NET_UTF8(n) \ - { \ - size_t len = n; \ - VALIDATE_NET_BYTES(len); \ - if (!utf8_is_valid_without_nul(&net_bytes[net_offset-len], len)) \ - return lib9p_error(ctx, LIB9P_ERRNO_L_EILSEQ, "message contains invalid UTF-8"); \ - } -#define RESERVE_HOST_BYTES(n) \ - if (__builtin_add_overflow(host_size, n, &host_size)) \ - /* If needed-host-size overflowed ssize_t, then there's \ - * no way that actual-net-size will live up to \ - * that. */ \ - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "message is too short for content"); +#define VALIDATE_NET_BYTES(n) \ + if (__builtin_add_overflow(net_offset, n, &net_offset)) \ + /* If needed-net-size overflowed uint32_t, then \ + * there's no way that actual-net-size will live up to \ + * that. */ \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content")); \ + if (net_offset > net_size) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content (", net_offset, " > ", net_size, ")")); +#define VALIDATE_NET_UTF8(n) \ + { \ + size_t len = n; \ + VALIDATE_NET_BYTES(len); \ + if (!utf8_is_valid_without_nul(&net_bytes[net_offset-len], len)) \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EILSEQ, "message contains invalid UTF-8")); \ + } +#define RESERVE_HOST_BYTES(n) \ + if (__builtin_add_overflow(host_size, n, &host_size)) \ + /* If needed-host-size overflowed size_t, then there's \ + * no way that actual-net-size will live up to \ + * that. */ \ + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "message is too short for content")); #define GET_U8LE(off) (net_bytes[off]) #define GET_U16LE(off) uint16le_decode(&net_bytes[off]) #define GET_U32LE(off) uint32le_decode(&net_bytes[off]) @@ -252,16 +252,16 @@ static const lib9p_lock_flags_t lock_flags_masks[LIB9P_VER_NUM] = { #define LAST_U64LE() GET_U64LE(net_offset-8) #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) { +static size_t_or_error validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_stat); + size_t host_size = sizeof(struct lib9p_stat); uint32_t offsetof__stat_size = net_offset + 0; uint32_t offsetof_fstype = net_offset + 2; uint32_t offsetof_qid_type = net_offset + 8; VALIDATE_NET_BYTES(21); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_mode = net_offset + 0; VALIDATE_NET_BYTES(22); VALIDATE_NET_UTF8(LAST_U16LE()); @@ -280,52 +280,52 @@ static ssize_t validate_stat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t * #endif /* CONFIG_9P_ENABLE_9P2000_u */ uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof__stat_size) != offsetof_end - offsetof_fstype) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "stat->_stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof__stat_size)), " != correct:", (base10, offsetof_end - offsetof_fstype)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "stat->_stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof__stat_size)), " != correct:", (base10, offsetof_end - offsetof_fstype))); if (GET_U32LE(offsetof_mode) & ~dm_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in dm bitfield: ", - (base16_u32_, GET_U32LE(offsetof_mode) & ~dm_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in dm bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~dm_masks[ctx->version]))); if (ret_net_size) *ret_net_size = net_offset; - return (ssize_t)host_size; + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized -static ssize_t validate_Tversion(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tversion([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tversion); + size_t host_size = sizeof(struct lib9p_msg_Tversion); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tversion->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tversion->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 100) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tversion->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 100)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tversion->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 100))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rversion(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rversion([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rversion); + size_t host_size = sizeof(struct lib9p_msg_Rversion); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rversion->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rversion->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 101) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rversion->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 101)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rversion->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 101))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Tauth(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tauth([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tauth); + size_t host_size = sizeof(struct lib9p_msg_Tauth); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -339,33 +339,33 @@ static ssize_t validate_Tauth(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t #endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tauth->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tauth->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 102) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tauth->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 102)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tauth->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 102))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rauth(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rauth([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rauth); + size_t host_size = sizeof(struct lib9p_msg_Rauth); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_aqid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_aqid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_aqid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_aqid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rauth->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rauth->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 103) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rauth->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 103)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rauth->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 103))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tattach(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tattach([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tattach); + size_t host_size = sizeof(struct lib9p_msg_Tattach); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(17); @@ -379,35 +379,35 @@ static ssize_t validate_Tattach(struct lib9p_ctx *ctx, uint32_t net_size, uint8_ #endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tattach->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tattach->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 104) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tattach->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 104)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tattach->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 104))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rattach(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rattach([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rattach); + size_t host_size = sizeof(struct lib9p_msg_Rattach); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rattach->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rattach->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 105) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rattach->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 105)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rattach->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 105))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized -static ssize_t validate_Rerror(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rerror([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rerror); + size_t host_size = sizeof(struct lib9p_msg_Rerror); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(9); @@ -419,45 +419,45 @@ static ssize_t validate_Rerror(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t #endif /* CONFIG_9P_ENABLE_9P2000_u */ uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rerror->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rerror->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 107) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rerror->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 107)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rerror->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 107))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Tflush(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tflush([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tflush); + size_t host_size = sizeof(struct lib9p_msg_Tflush); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 9; VALIDATE_NET_BYTES(9); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tflush->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tflush->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 108) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tflush->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 108)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tflush->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 108))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rflush(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rflush([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rflush); + size_t host_size = sizeof(struct lib9p_msg_Rflush); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rflush->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rflush->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 109) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rflush->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 109)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rflush->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 109))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Twalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Twalk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Twalk); + size_t host_size = sizeof(struct lib9p_msg_Twalk); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_nwname = net_offset + 15; @@ -469,17 +469,17 @@ static ssize_t validate_Twalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t } uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 110) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 110)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 110))); if (GET_U16LE(offsetof_nwname) > 16) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twalk->nwname value is too large: ", (base10, GET_U16LE(offsetof_nwname)), " > ", (base10, 16)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twalk->nwname value is too large: ", (base10, GET_U16LE(offsetof_nwname)), " > ", (base10, 16))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rwalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rwalk); + size_t host_size = sizeof(struct lib9p_msg_Rwalk); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_nwqid = net_offset + 7; @@ -489,61 +489,61 @@ static ssize_t validate_Rwalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t uint32_t offsetof_wqid_type = net_offset + 0; VALIDATE_NET_BYTES(13); if (GET_U8LE(offsetof_wqid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_wqid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_wqid_type) & ~qt_masks[ctx->version]))); } uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 111) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 111)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 111))); if (GET_U16LE(offsetof_nwqid) > 16) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rwalk->nwqid value is too large: ", (base10, GET_U16LE(offsetof_nwqid)), " > ", (base10, 16)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwalk->nwqid value is too large: ", (base10, GET_U16LE(offsetof_nwqid)), " > ", (base10, 16))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Topen(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Topen([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Topen); + size_t host_size = sizeof(struct lib9p_msg_Topen); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_mode = net_offset + 11; uint32_t offsetof_end = net_offset + 12; VALIDATE_NET_BYTES(12); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Topen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Topen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 112) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Topen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 112)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Topen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 112))); if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in o bitfield: ", - (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in o bitfield: ", + (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Ropen(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Ropen([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Ropen); + size_t host_size = sizeof(struct lib9p_msg_Ropen); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 4; VALIDATE_NET_BYTES(4); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Ropen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Ropen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 113) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Ropen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 113)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Ropen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 113))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tcreate); + size_t host_size = sizeof(struct lib9p_msg_Tcreate); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -553,42 +553,42 @@ static ssize_t validate_Tcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_ uint32_t offsetof_end = net_offset + 5; VALIDATE_NET_BYTES(5); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 114) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 114)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 114))); if (GET_U32LE(offsetof_perm) & ~dm_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in dm bitfield: ", - (base16_u32_, GET_U32LE(offsetof_perm) & ~dm_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in dm bitfield: ", + (base16_u32_, GET_U32LE(offsetof_perm) & ~dm_masks[ctx->version]))); if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in o bitfield: ", - (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in o bitfield: ", + (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rcreate); + size_t host_size = sizeof(struct lib9p_msg_Rcreate); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 4; VALIDATE_NET_BYTES(4); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 115) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 115)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 115))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Tread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tread([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tread); + size_t host_size = sizeof(struct lib9p_msg_Tread); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_offset = net_offset + 11; @@ -596,19 +596,19 @@ static ssize_t validate_Tread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t uint32_t offsetof_end = net_offset + 23; VALIDATE_NET_BYTES(23); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 116) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 116)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 116))); if (GET_U64LE(offsetof_offset) > INT64_MAX) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tread->offset value is too large: ", (base10, GET_U64LE(offsetof_offset)), " > ", (base10, INT64_MAX)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tread->offset value is too large: ", (base10, GET_U64LE(offsetof_offset)), " > ", (base10, INT64_MAX))); if (GET_U32LE(offsetof_count) > INT32_MAX) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tread->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tread->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rread([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rread); + size_t host_size = sizeof(struct lib9p_msg_Rread); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_count = net_offset + 7; @@ -616,17 +616,17 @@ static ssize_t validate_Rread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t VALIDATE_NET_BYTES(LAST_U32LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 117) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 117)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 117))); if (GET_U32LE(offsetof_count) > INT32_MAX) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rread->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rread->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Twrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Twrite([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Twrite); + size_t host_size = sizeof(struct lib9p_msg_Twrite); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_offset = net_offset + 11; @@ -635,108 +635,108 @@ static ssize_t validate_Twrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t VALIDATE_NET_BYTES(LAST_U32LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 118) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 118)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 118))); if (GET_U64LE(offsetof_offset) > INT64_MAX) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twrite->offset value is too large: ", (base10, GET_U64LE(offsetof_offset)), " > ", (base10, INT64_MAX)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twrite->offset value is too large: ", (base10, GET_U64LE(offsetof_offset)), " > ", (base10, INT64_MAX))); if (GET_U32LE(offsetof_count) > INT32_MAX) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twrite->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twrite->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rwrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rwrite([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rwrite); + size_t host_size = sizeof(struct lib9p_msg_Rwrite); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_count = net_offset + 7; uint32_t offsetof_end = net_offset + 11; VALIDATE_NET_BYTES(11); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rwrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 119) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rwrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 119)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 119))); if (GET_U32LE(offsetof_count) > INT32_MAX) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rwrite->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwrite->count value is too large: ", (base10, GET_U32LE(offsetof_count)), " > ", (base10, INT32_MAX))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tclunk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tclunk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tclunk); + size_t host_size = sizeof(struct lib9p_msg_Tclunk); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 11; VALIDATE_NET_BYTES(11); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tclunk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tclunk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 120) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tclunk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 120)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tclunk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 120))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rclunk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rclunk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rclunk); + size_t host_size = sizeof(struct lib9p_msg_Rclunk); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rclunk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rclunk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 121) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rclunk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 121)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rclunk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 121))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tremove(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tremove([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tremove); + size_t host_size = sizeof(struct lib9p_msg_Tremove); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 11; VALIDATE_NET_BYTES(11); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tremove->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tremove->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 122) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tremove->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 122)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tremove->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 122))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rremove(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rremove([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rremove); + size_t host_size = sizeof(struct lib9p_msg_Rremove); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rremove->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rremove->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 123) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rremove->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 123)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rremove->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 123))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static ssize_t validate_Tstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tstat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tstat); + size_t host_size = sizeof(struct lib9p_msg_Tstat); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 11; VALIDATE_NET_BYTES(11); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 124) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 124)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 124))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rstat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rstat); + size_t host_size = sizeof(struct lib9p_msg_Rstat); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_nstat = net_offset + 7; @@ -746,8 +746,8 @@ static ssize_t validate_Rstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t uint32_t offsetof_stat_qid_type = net_offset + 17; VALIDATE_NET_BYTES(30); if (GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_stat_mode = net_offset + 0; VALIDATE_NET_BYTES(22); VALIDATE_NET_UTF8(LAST_U16LE()); @@ -766,23 +766,23 @@ static ssize_t validate_Rstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t #endif /* CONFIG_9P_ENABLE_9P2000_u */ uint32_t offsetof_stat_end = net_offset + 0; if (GET_U32LE(offsetof_stat__stat_size) != offsetof_stat_end - offsetof_stat_fstype) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rstat->stat._stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof_stat__stat_size)), " != correct:", (base10, offsetof_stat_end - offsetof_stat_fstype)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstat->stat._stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof_stat__stat_size)), " != correct:", (base10, offsetof_stat_end - offsetof_stat_fstype))); if (GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in dm bitfield: ", - (base16_u32_, GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in dm bitfield: ", + (base16_u32_, GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 125) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 125)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 125))); if (GET_U32LE(offsetof_nstat) != offsetof_end - offsetof_stat) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rstat->nstat value is wrong: actual:", (base10, GET_U32LE(offsetof_nstat)), " != correct:", (base10, offsetof_end - offsetof_stat)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstat->nstat value is wrong: actual:", (base10, GET_U32LE(offsetof_nstat)), " != correct:", (base10, offsetof_end - offsetof_stat))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Twstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Twstat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Twstat); + size_t host_size = sizeof(struct lib9p_msg_Twstat); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_nstat = net_offset + 11; @@ -792,8 +792,8 @@ static ssize_t validate_Twstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t uint32_t offsetof_stat_qid_type = net_offset + 21; VALIDATE_NET_BYTES(34); if (GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_stat_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_stat_mode = net_offset + 0; VALIDATE_NET_BYTES(22); VALIDATE_NET_UTF8(LAST_U16LE()); @@ -812,157 +812,157 @@ static ssize_t validate_Twstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t #endif /* CONFIG_9P_ENABLE_9P2000_u */ uint32_t offsetof_stat_end = net_offset + 0; if (GET_U32LE(offsetof_stat__stat_size) != offsetof_stat_end - offsetof_stat_fstype) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twstat->stat._stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof_stat__stat_size)), " != correct:", (base10, offsetof_stat_end - offsetof_stat_fstype)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twstat->stat._stat_size value is wrong: actual:", (base10, GET_U32LE(offsetof_stat__stat_size)), " != correct:", (base10, offsetof_stat_end - offsetof_stat_fstype))); if (GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in dm bitfield: ", - (base16_u32_, GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in dm bitfield: ", + (base16_u32_, GET_U32LE(offsetof_stat_mode) & ~dm_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 126) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 126)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 126))); if (GET_U32LE(offsetof_nstat) != offsetof_end - offsetof_stat) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Twstat->nstat value is wrong: actual:", (base10, GET_U32LE(offsetof_nstat)), " != correct:", (base10, offsetof_end - offsetof_stat)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Twstat->nstat value is wrong: actual:", (base10, GET_U32LE(offsetof_nstat)), " != correct:", (base10, offsetof_end - offsetof_stat))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rwstat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rwstat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rwstat); + size_t host_size = sizeof(struct lib9p_msg_Rwstat); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rwstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwstat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 127) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rwstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 127)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rwstat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 127))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000_p9p -static ssize_t validate_Topenfd(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Topenfd([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Topenfd); + size_t host_size = sizeof(struct lib9p_msg_Topenfd); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_mode = net_offset + 11; uint32_t offsetof_end = net_offset + 12; VALIDATE_NET_BYTES(12); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Topenfd->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Topenfd->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 98) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Topenfd->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 98)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Topenfd->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 98))); if (GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in o bitfield: ", - (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in o bitfield: ", + (base16_u8_, GET_U8LE(offsetof_mode) & ~o_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Ropenfd(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Ropenfd([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Ropenfd); + size_t host_size = sizeof(struct lib9p_msg_Ropenfd); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 8; VALIDATE_NET_BYTES(8); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Ropenfd->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Ropenfd->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 99) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Ropenfd->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 99)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Ropenfd->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 99))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000_p9p */ #if CONFIG_9P_ENABLE_9P2000_L -static ssize_t validate_Rlerror(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rlerror([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlerror); + size_t host_size = sizeof(struct lib9p_msg_Rlerror); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 11; VALIDATE_NET_BYTES(11); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlerror->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlerror->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 7) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlerror->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 7)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlerror->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 7))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tstatfs(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tstatfs([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tstatfs); + size_t host_size = sizeof(struct lib9p_msg_Tstatfs); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 11; VALIDATE_NET_BYTES(11); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tstatfs->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tstatfs->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 8) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tstatfs->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 8)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tstatfs->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 8))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rstatfs(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rstatfs([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rstatfs); + size_t host_size = sizeof(struct lib9p_msg_Rstatfs); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 67; VALIDATE_NET_BYTES(67); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rstatfs->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstatfs->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 9) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rstatfs->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 9)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rstatfs->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 9))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tlopen(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tlopen([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tlopen); + size_t host_size = sizeof(struct lib9p_msg_Tlopen); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_flags = net_offset + 11; uint32_t offsetof_end = net_offset + 15; VALIDATE_NET_BYTES(15); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tlopen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlopen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 12) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tlopen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 12)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlopen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 12))); if (GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in lo bitfield: ", - (base16_u32_, GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in lo bitfield: ", + (base16_u32_, GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rlopen(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rlopen([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlopen); + size_t host_size = sizeof(struct lib9p_msg_Rlopen); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 4; VALIDATE_NET_BYTES(4); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlopen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlopen->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 13) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlopen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 13)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlopen->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 13))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tlcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tlcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tlcreate); + size_t host_size = sizeof(struct lib9p_msg_Tlcreate); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -972,40 +972,40 @@ static ssize_t validate_Tlcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8 uint32_t offsetof_end = net_offset + 12; VALIDATE_NET_BYTES(12); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tlcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 14) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tlcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 14)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 14))); if (GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in lo bitfield: ", - (base16_u32_, GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in lo bitfield: ", + (base16_u32_, GET_U32LE(offsetof_flags) & ~lo_masks[ctx->version]))); if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in mode bitfield: ", - (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rlcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rlcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlcreate); + size_t host_size = sizeof(struct lib9p_msg_Rlcreate); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 4; VALIDATE_NET_BYTES(4); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 15) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 15)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 15))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tsymlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tsymlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tsymlink); + size_t host_size = sizeof(struct lib9p_msg_Tsymlink); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -1015,33 +1015,33 @@ static ssize_t validate_Tsymlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8 uint32_t offsetof_end = net_offset + 4; VALIDATE_NET_BYTES(4); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tsymlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsymlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 16) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tsymlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 16)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsymlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 16))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rsymlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rsymlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rsymlink); + size_t host_size = sizeof(struct lib9p_msg_Rsymlink); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rsymlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsymlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 17) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rsymlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 17)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsymlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 17))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tmknod(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tmknod([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tmknod); + size_t host_size = sizeof(struct lib9p_msg_Tmknod); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -1050,139 +1050,139 @@ static ssize_t validate_Tmknod(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t uint32_t offsetof_end = net_offset + 16; VALIDATE_NET_BYTES(16); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tmknod->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tmknod->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 18) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tmknod->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 18)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tmknod->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 18))); if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in mode bitfield: ", - (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rmknod(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rmknod([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rmknod); + size_t host_size = sizeof(struct lib9p_msg_Rmknod); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rmknod->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rmknod->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 19) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rmknod->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 19)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rmknod->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 19))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Trename(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Trename([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Trename); + size_t host_size = sizeof(struct lib9p_msg_Trename); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(17); VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Trename->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Trename->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 20) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Trename->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 20)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Trename->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 20))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rrename(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rrename([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rrename); + size_t host_size = sizeof(struct lib9p_msg_Rrename); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rrename->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rrename->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 21) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rrename->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 21)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rrename->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 21))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Treadlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Treadlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Treadlink); + size_t host_size = sizeof(struct lib9p_msg_Treadlink); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 11; VALIDATE_NET_BYTES(11); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Treadlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Treadlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 22) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Treadlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 22)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Treadlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 22))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rreadlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rreadlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rreadlink); + size_t host_size = sizeof(struct lib9p_msg_Rreadlink); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(9); VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rreadlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rreadlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 23) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rreadlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 23)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rreadlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 23))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tgetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tgetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tgetattr); + size_t host_size = sizeof(struct lib9p_msg_Tgetattr); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_request_mask = net_offset + 11; uint32_t offsetof_end = net_offset + 19; VALIDATE_NET_BYTES(19); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tgetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tgetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 24) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tgetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 24)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tgetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 24))); if (GET_U64LE(offsetof_request_mask) & ~getattr_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in getattr bitfield: ", - (base16_u64_, GET_U64LE(offsetof_request_mask) & ~getattr_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in getattr bitfield: ", + (base16_u64_, GET_U64LE(offsetof_request_mask) & ~getattr_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rgetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rgetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rgetattr); + size_t host_size = sizeof(struct lib9p_msg_Rgetattr); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_valid = net_offset + 7; uint32_t offsetof_qid_type = net_offset + 15; VALIDATE_NET_BYTES(28); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_mode = net_offset + 0; uint32_t offsetof_end = net_offset + 132; VALIDATE_NET_BYTES(132); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rgetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rgetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 25) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rgetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 25)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rgetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 25))); if (GET_U64LE(offsetof_valid) & ~getattr_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in getattr bitfield: ", - (base16_u64_, GET_U64LE(offsetof_valid) & ~getattr_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in getattr bitfield: ", + (base16_u64_, GET_U64LE(offsetof_valid) & ~getattr_masks[ctx->version]))); if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in mode bitfield: ", - (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tsetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tsetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tsetattr); + size_t host_size = sizeof(struct lib9p_msg_Tsetattr); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_valid = net_offset + 11; @@ -1190,64 +1190,64 @@ static ssize_t validate_Tsetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8 uint32_t offsetof_end = net_offset + 67; VALIDATE_NET_BYTES(67); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tsetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 26) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tsetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 26)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 26))); if (GET_U32LE(offsetof_valid) & ~setattr_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in setattr bitfield: ", - (base16_u32_, GET_U32LE(offsetof_valid) & ~setattr_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in setattr bitfield: ", + (base16_u32_, GET_U32LE(offsetof_valid) & ~setattr_masks[ctx->version]))); if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in mode bitfield: ", - (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rsetattr(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rsetattr([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rsetattr); + size_t host_size = sizeof(struct lib9p_msg_Rsetattr); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rsetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsetattr->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 27) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rsetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 27)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsetattr->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 27))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Txattrwalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Txattrwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Txattrwalk); + size_t host_size = sizeof(struct lib9p_msg_Txattrwalk); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(17); VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Txattrwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Txattrwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 30) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Txattrwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 30)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Txattrwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 30))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rxattrwalk(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rxattrwalk([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rxattrwalk); + size_t host_size = sizeof(struct lib9p_msg_Rxattrwalk); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 15; VALIDATE_NET_BYTES(15); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rxattrwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rxattrwalk->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 31) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rxattrwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 31)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rxattrwalk->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 31))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Txattrcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Txattrcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Txattrcreate); + size_t host_size = sizeof(struct lib9p_msg_Txattrcreate); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -1255,86 +1255,86 @@ static ssize_t validate_Txattrcreate(struct lib9p_ctx *ctx, uint32_t net_size, u uint32_t offsetof_end = net_offset + 12; VALIDATE_NET_BYTES(12); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Txattrcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Txattrcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 32) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Txattrcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 32)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Txattrcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 32))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rxattrcreate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rxattrcreate([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rxattrcreate); + size_t host_size = sizeof(struct lib9p_msg_Rxattrcreate); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rxattrcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rxattrcreate->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 33) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rxattrcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 33)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rxattrcreate->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 33))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Treaddir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Treaddir([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Treaddir); + size_t host_size = sizeof(struct lib9p_msg_Treaddir); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 23; VALIDATE_NET_BYTES(23); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Treaddir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Treaddir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 40) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Treaddir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 40)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Treaddir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 40))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rreaddir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rreaddir([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rreaddir); + size_t host_size = sizeof(struct lib9p_msg_Rreaddir); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(11); VALIDATE_NET_BYTES(LAST_U32LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rreaddir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rreaddir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 41) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rreaddir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 41)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rreaddir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 41))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tfsync(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tfsync([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tfsync); + size_t host_size = sizeof(struct lib9p_msg_Tfsync); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 15; VALIDATE_NET_BYTES(15); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tfsync->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tfsync->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 50) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tfsync->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 50)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tfsync->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 50))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rfsync(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rfsync([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rfsync); + size_t host_size = sizeof(struct lib9p_msg_Rfsync); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rfsync->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rfsync->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 51) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rfsync->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 51)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rfsync->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 51))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tlock([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tlock); + size_t host_size = sizeof(struct lib9p_msg_Tlock); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_flags = net_offset + 12; @@ -1342,91 +1342,91 @@ static ssize_t validate_Tlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 52) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 52)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 52))); if (GET_U32LE(offsetof_flags) & ~lock_flags_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in lock_flags bitfield: ", - (base16_u32_, GET_U32LE(offsetof_flags) & ~lock_flags_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in lock_flags bitfield: ", + (base16_u32_, GET_U32LE(offsetof_flags) & ~lock_flags_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rlock([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlock); + size_t host_size = sizeof(struct lib9p_msg_Rlock); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 8; VALIDATE_NET_BYTES(8); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 53) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 53)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 53))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tgetlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tgetlock([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tgetlock); + size_t host_size = sizeof(struct lib9p_msg_Tgetlock); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(34); VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tgetlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tgetlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 54) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tgetlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 54)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tgetlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 54))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rgetlock(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rgetlock([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rgetlock); + size_t host_size = sizeof(struct lib9p_msg_Rgetlock); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(30); VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rgetlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rgetlock->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 55) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rgetlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 55)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rgetlock->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 55))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tlink); + size_t host_size = sizeof(struct lib9p_msg_Tlink); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(17); VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 70) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 70)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 70))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rlink(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rlink([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rlink); + size_t host_size = sizeof(struct lib9p_msg_Rlink); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlink->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 71) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 71)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rlink->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 71))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tmkdir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tmkdir([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tmkdir); + size_t host_size = sizeof(struct lib9p_msg_Tmkdir); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -1435,36 +1435,36 @@ static ssize_t validate_Tmkdir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t uint32_t offsetof_end = net_offset + 8; VALIDATE_NET_BYTES(8); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tmkdir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tmkdir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 72) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tmkdir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 72)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tmkdir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 72))); if (GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in mode bitfield: ", - (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version])); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in mode bitfield: ", + (base16_u32_, GET_U32LE(offsetof_mode) & ~mode_masks[ctx->version]))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rmkdir(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rmkdir([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rmkdir); + size_t host_size = sizeof(struct lib9p_msg_Rmkdir); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_qid_type = net_offset + 7; VALIDATE_NET_BYTES(20); if (GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "unknown bits in qt bitfield: ", - (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version])); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "unknown bits in qt bitfield: ", + (base16_u8_, GET_U8LE(offsetof_qid_type) & ~qt_masks[ctx->version]))); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rmkdir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rmkdir->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 73) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rmkdir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 73)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rmkdir->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 73))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Trenameat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Trenameat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Trenameat); + size_t host_size = sizeof(struct lib9p_msg_Trenameat); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -1473,29 +1473,29 @@ static ssize_t validate_Trenameat(struct lib9p_ctx *ctx, uint32_t net_size, uint VALIDATE_NET_UTF8(LAST_U16LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Trenameat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Trenameat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 74) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Trenameat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 74)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Trenameat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 74))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rrenameat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rrenameat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rrenameat); + size_t host_size = sizeof(struct lib9p_msg_Rrenameat); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rrenameat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rrenameat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 75) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rrenameat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 75)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rrenameat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 75))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tunlinkat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tunlinkat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tunlinkat); + size_t host_size = sizeof(struct lib9p_msg_Tunlinkat); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -1503,59 +1503,59 @@ static ssize_t validate_Tunlinkat(struct lib9p_ctx *ctx, uint32_t net_size, uint uint32_t offsetof_end = net_offset + 4; VALIDATE_NET_BYTES(4); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tunlinkat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tunlinkat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 76) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tunlinkat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 76)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tunlinkat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 76))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Runlinkat(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Runlinkat([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Runlinkat); + size_t host_size = sizeof(struct lib9p_msg_Runlinkat); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Runlinkat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Runlinkat->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 77) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Runlinkat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 77)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Runlinkat->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 77))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000_L */ #if CONFIG_9P_ENABLE_9P2000_e -static ssize_t validate_Tsession(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tsession([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tsession); + size_t host_size = sizeof(struct lib9p_msg_Tsession); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 15; VALIDATE_NET_BYTES(15); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tsession->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsession->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 150) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tsession->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 150)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsession->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 150))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rsession(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rsession([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rsession); + size_t host_size = sizeof(struct lib9p_msg_Rsession); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 7; VALIDATE_NET_BYTES(7); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rsession->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsession->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 151) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rsession->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 151)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsession->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 151))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tsread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tsread([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tsread); + size_t host_size = sizeof(struct lib9p_msg_Tsread); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -1566,30 +1566,30 @@ static ssize_t validate_Tsread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t } uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tsread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 152) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tsread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 152)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tsread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 152))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rsread(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rsread([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rsread); + size_t host_size = sizeof(struct lib9p_msg_Rsread); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(11); VALIDATE_NET_BYTES(LAST_U32LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rsread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsread->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 153) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rsread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 153)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rsread->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 153))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Tswrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Tswrite([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Tswrite); + size_t host_size = sizeof(struct lib9p_msg_Tswrite); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; VALIDATE_NET_BYTES(13); @@ -1602,24 +1602,24 @@ static ssize_t validate_Tswrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_ VALIDATE_NET_BYTES(LAST_U32LE()); uint32_t offsetof_end = net_offset + 0; if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tswrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tswrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 154) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Tswrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 154)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Tswrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 154))); + return ERROR_NEW_VAL(size_t, host_size); } -static ssize_t validate_Rswrite(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { +static size_t_or_error validate_Rswrite([[maybe_unused]] struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes) { uint32_t net_offset = 0; - ssize_t host_size = sizeof(struct lib9p_msg_Rswrite); + size_t host_size = sizeof(struct lib9p_msg_Rswrite); uint32_t offsetof_size = net_offset + 0; uint32_t offsetof_typ = net_offset + 4; uint32_t offsetof_end = net_offset + 11; VALIDATE_NET_BYTES(11); if (GET_U32LE(offsetof_size) != offsetof_end - offsetof_size) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rswrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size)); + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rswrite->size value is wrong: actual:", (base10, GET_U32LE(offsetof_size)), " != correct:", (base10, offsetof_end - offsetof_size))); if (GET_U8LE(offsetof_typ) != 155) - return lib9p_error(ctx, LIB9P_ERRNO_L_EBADMSG, "Rswrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 155)); - return (ssize_t)host_size; + return ERROR_NEW_ERR(size_t, error_new(E_POSIX_EBADMSG, "Rswrite->typ value is wrong: actual:", (base10, GET_U8LE(offsetof_typ)), " != correct:", (base10, 155))); + return ERROR_NEW_VAL(size_t, host_size); } #endif /* CONFIG_9P_ENABLE_9P2000_e */ @@ -2766,13 +2766,12 @@ static bool marshal_stat(struct lib9p_ctx *ctx, struct lib9p_stat *val, struct _ #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized -static bool marshal_Tversion(struct lib9p_ctx *ctx, struct lib9p_msg_Tversion *val, struct _marshal_ret *ret) { +static error marshal_Tversion(struct lib9p_ctx *ctx, struct lib9p_msg_Tversion *val, struct _marshal_ret *ret) { uint32_t needed_size = 13 + val->version.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tversion message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tversion message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2782,16 +2781,15 @@ static bool marshal_Tversion(struct lib9p_ctx *ctx, struct lib9p_msg_Tversion *v MARSHAL_U32LE(ctx, val->max_msg_size); MARSHAL_U16LE(ctx, val->version.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->version.utf8, val->version.len); - return false; + return ERROR_NULL; } -static bool marshal_Rversion(struct lib9p_ctx *ctx, struct lib9p_msg_Rversion *val, struct _marshal_ret *ret) { +static error marshal_Rversion(struct lib9p_ctx *ctx, struct lib9p_msg_Rversion *val, struct _marshal_ret *ret) { uint32_t needed_size = 13 + val->version.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rversion message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rversion message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2801,12 +2799,12 @@ static bool marshal_Rversion(struct lib9p_ctx *ctx, struct lib9p_msg_Rversion *v MARSHAL_U32LE(ctx, val->max_msg_size); MARSHAL_U16LE(ctx, val->version.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->version.utf8, val->version.len); - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Tauth(struct lib9p_ctx *ctx, struct lib9p_msg_Tauth *val, struct _marshal_ret *ret) { +static error marshal_Tauth(struct lib9p_ctx *ctx, struct lib9p_msg_Tauth *val, struct _marshal_ret *ret) { uint32_t needed_size = 15 + val->uname.len + val->aname.len; #if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u if ( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) ) { @@ -2814,10 +2812,9 @@ static bool marshal_Tauth(struct lib9p_ctx *ctx, struct lib9p_msg_Tauth *val, st } #endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tauth message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tauth message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2834,16 +2831,15 @@ static bool marshal_Tauth(struct lib9p_ctx *ctx, struct lib9p_msg_Tauth *val, st MARSHAL_U32LE(ctx, val->unum); } #endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ - return false; + return ERROR_NULL; } -static bool marshal_Rauth(struct lib9p_ctx *ctx, struct lib9p_msg_Rauth *val, struct _marshal_ret *ret) { +static error marshal_Rauth(struct lib9p_ctx *ctx, struct lib9p_msg_Rauth *val, struct _marshal_ret *ret) { uint32_t needed_size = 20; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rauth message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rauth message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2853,10 +2849,10 @@ static bool marshal_Rauth(struct lib9p_ctx *ctx, struct lib9p_msg_Rauth *val, st MARSHAL_U8LE(ctx, val->aqid.type & qt_masks[ctx->version]); MARSHAL_U32LE(ctx, val->aqid.vers); MARSHAL_U64LE(ctx, val->aqid.path); - return false; + return ERROR_NULL; } -static bool marshal_Tattach(struct lib9p_ctx *ctx, struct lib9p_msg_Tattach *val, struct _marshal_ret *ret) { +static error marshal_Tattach(struct lib9p_ctx *ctx, struct lib9p_msg_Tattach *val, struct _marshal_ret *ret) { uint32_t needed_size = 19 + val->uname.len + val->aname.len; #if CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u if ( is_ver(ctx, 9P2000_L) || is_ver(ctx, 9P2000_u) ) { @@ -2864,10 +2860,9 @@ static bool marshal_Tattach(struct lib9p_ctx *ctx, struct lib9p_msg_Tattach *val } #endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tattach message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tattach message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2885,16 +2880,15 @@ static bool marshal_Tattach(struct lib9p_ctx *ctx, struct lib9p_msg_Tattach *val MARSHAL_U32LE(ctx, val->unum); } #endif /* CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_u */ - return false; + return ERROR_NULL; } -static bool marshal_Rattach(struct lib9p_ctx *ctx, struct lib9p_msg_Rattach *val, struct _marshal_ret *ret) { +static error marshal_Rattach(struct lib9p_ctx *ctx, struct lib9p_msg_Rattach *val, struct _marshal_ret *ret) { uint32_t needed_size = 20; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rattach message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rattach message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2904,12 +2898,12 @@ static bool marshal_Rattach(struct lib9p_ctx *ctx, struct lib9p_msg_Rattach *val MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); MARSHAL_U32LE(ctx, val->qid.vers); MARSHAL_U64LE(ctx, val->qid.path); - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized -static bool marshal_Rerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rerror *val, struct _marshal_ret *ret) { +static error marshal_Rerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rerror *val, struct _marshal_ret *ret) { uint32_t needed_size = 9 + val->errstr.len; #if CONFIG_9P_ENABLE_9P2000_u if is_ver(ctx, 9P2000_u) { @@ -2917,10 +2911,9 @@ static bool marshal_Rerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rerror *val, } #endif /* CONFIG_9P_ENABLE_9P2000_u */ if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rerror message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rerror message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2934,18 +2927,17 @@ static bool marshal_Rerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rerror *val, MARSHAL_U32LE(ctx, val->errnum); } #endif /* CONFIG_9P_ENABLE_9P2000_u */ - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_uninitialized */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Tflush(struct lib9p_ctx *ctx, struct lib9p_msg_Tflush *val, struct _marshal_ret *ret) { +static error marshal_Tflush(struct lib9p_ctx *ctx, struct lib9p_msg_Tflush *val, struct _marshal_ret *ret) { uint32_t needed_size = 9; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tflush message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tflush message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2953,35 +2945,33 @@ static bool marshal_Tflush(struct lib9p_ctx *ctx, struct lib9p_msg_Tflush *val, MARSHAL_U8LE(ctx, 108); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U16LE(ctx, val->oldtag); - return false; + return ERROR_NULL; } -static bool marshal_Rflush(struct lib9p_ctx *ctx, struct lib9p_msg_Rflush *val, struct _marshal_ret *ret) { +static error marshal_Rflush(struct lib9p_ctx *ctx, struct lib9p_msg_Rflush *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rflush message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rflush message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 109); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Twalk(struct lib9p_ctx *ctx, struct lib9p_msg_Twalk *val, struct _marshal_ret *ret) { +static error marshal_Twalk(struct lib9p_ctx *ctx, struct lib9p_msg_Twalk *val, struct _marshal_ret *ret) { uint32_t needed_size = 17; for (uint16_t i = 0; i < val->nwname; i++) { needed_size += 2 + val->wname[i].len; } if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Twalk message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Twalk message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -2995,16 +2985,15 @@ static bool marshal_Twalk(struct lib9p_ctx *ctx, struct lib9p_msg_Twalk *val, st MARSHAL_U16LE(ctx, val->wname[i].len); MARSHAL_BYTES_ZEROCOPY(ctx, val->wname[i].utf8, val->wname[i].len); } - return false; + return ERROR_NULL; } -static bool marshal_Rwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rwalk *val, struct _marshal_ret *ret) { +static error marshal_Rwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rwalk *val, struct _marshal_ret *ret) { uint32_t needed_size = 9 + (val->nwqid)*13; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rwalk message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rwalk message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3017,18 +3006,17 @@ static bool marshal_Rwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rwalk *val, st MARSHAL_U32LE(ctx, val->wqid[i].vers); MARSHAL_U64LE(ctx, val->wqid[i].path); } - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Topen(struct lib9p_ctx *ctx, struct lib9p_msg_Topen *val, struct _marshal_ret *ret) { +static error marshal_Topen(struct lib9p_ctx *ctx, struct lib9p_msg_Topen *val, struct _marshal_ret *ret) { uint32_t needed_size = 12; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Topen message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Topen message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3037,16 +3025,15 @@ static bool marshal_Topen(struct lib9p_ctx *ctx, struct lib9p_msg_Topen *val, st MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); - return false; + return ERROR_NULL; } -static bool marshal_Ropen(struct lib9p_ctx *ctx, struct lib9p_msg_Ropen *val, struct _marshal_ret *ret) { +static error marshal_Ropen(struct lib9p_ctx *ctx, struct lib9p_msg_Ropen *val, struct _marshal_ret *ret) { uint32_t needed_size = 24; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Ropen message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Ropen message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3057,16 +3044,15 @@ static bool marshal_Ropen(struct lib9p_ctx *ctx, struct lib9p_msg_Ropen *val, st MARSHAL_U32LE(ctx, val->qid.vers); MARSHAL_U64LE(ctx, val->qid.path); MARSHAL_U32LE(ctx, val->iounit); - return false; + return ERROR_NULL; } -static bool marshal_Tcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tcreate *val, struct _marshal_ret *ret) { +static error marshal_Tcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tcreate *val, struct _marshal_ret *ret) { uint32_t needed_size = 18 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tcreate message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tcreate message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3078,16 +3064,15 @@ static bool marshal_Tcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tcreate *val MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); MARSHAL_U32LE(ctx, val->perm & dm_masks[ctx->version]); MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); - return false; + return ERROR_NULL; } -static bool marshal_Rcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rcreate *val, struct _marshal_ret *ret) { +static error marshal_Rcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rcreate *val, struct _marshal_ret *ret) { uint32_t needed_size = 24; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rcreate message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rcreate message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3098,18 +3083,17 @@ static bool marshal_Rcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rcreate *val MARSHAL_U32LE(ctx, val->qid.vers); MARSHAL_U64LE(ctx, val->qid.path); MARSHAL_U32LE(ctx, val->iounit); - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Tread(struct lib9p_ctx *ctx, struct lib9p_msg_Tread *val, struct _marshal_ret *ret) { +static error marshal_Tread(struct lib9p_ctx *ctx, struct lib9p_msg_Tread *val, struct _marshal_ret *ret) { uint32_t needed_size = 23; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tread message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tread message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3119,16 +3103,15 @@ static bool marshal_Tread(struct lib9p_ctx *ctx, struct lib9p_msg_Tread *val, st MARSHAL_U32LE(ctx, val->fid); MARSHAL_U64LE(ctx, val->offset); MARSHAL_U32LE(ctx, val->count); - return false; + return ERROR_NULL; } -static bool marshal_Rread(struct lib9p_ctx *ctx, struct lib9p_msg_Rread *val, struct _marshal_ret *ret) { +static error marshal_Rread(struct lib9p_ctx *ctx, struct lib9p_msg_Rread *val, struct _marshal_ret *ret) { uint32_t needed_size = 11 + val->count; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rread message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rread message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3137,16 +3120,15 @@ static bool marshal_Rread(struct lib9p_ctx *ctx, struct lib9p_msg_Rread *val, st MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->count); MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; + return ERROR_NULL; } -static bool marshal_Twrite(struct lib9p_ctx *ctx, struct lib9p_msg_Twrite *val, struct _marshal_ret *ret) { +static error marshal_Twrite(struct lib9p_ctx *ctx, struct lib9p_msg_Twrite *val, struct _marshal_ret *ret) { uint32_t needed_size = 23 + val->count; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Twrite message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Twrite message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3157,16 +3139,15 @@ static bool marshal_Twrite(struct lib9p_ctx *ctx, struct lib9p_msg_Twrite *val, MARSHAL_U64LE(ctx, val->offset); MARSHAL_U32LE(ctx, val->count); MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; + return ERROR_NULL; } -static bool marshal_Rwrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rwrite *val, struct _marshal_ret *ret) { +static error marshal_Rwrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rwrite *val, struct _marshal_ret *ret) { uint32_t needed_size = 11; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rwrite message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rwrite message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3174,16 +3155,15 @@ static bool marshal_Rwrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rwrite *val, MARSHAL_U8LE(ctx, 119); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->count); - return false; + return ERROR_NULL; } -static bool marshal_Tclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Tclunk *val, struct _marshal_ret *ret) { +static error marshal_Tclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Tclunk *val, struct _marshal_ret *ret) { uint32_t needed_size = 11; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tclunk message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tclunk message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3191,32 +3171,30 @@ static bool marshal_Tclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Tclunk *val, MARSHAL_U8LE(ctx, 120); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); - return false; + return ERROR_NULL; } -static bool marshal_Rclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Rclunk *val, struct _marshal_ret *ret) { +static error marshal_Rclunk(struct lib9p_ctx *ctx, struct lib9p_msg_Rclunk *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rclunk message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rclunk message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 121); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Tremove(struct lib9p_ctx *ctx, struct lib9p_msg_Tremove *val, struct _marshal_ret *ret) { +static error marshal_Tremove(struct lib9p_ctx *ctx, struct lib9p_msg_Tremove *val, struct _marshal_ret *ret) { uint32_t needed_size = 11; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tremove message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tremove message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3224,34 +3202,32 @@ static bool marshal_Tremove(struct lib9p_ctx *ctx, struct lib9p_msg_Tremove *val MARSHAL_U8LE(ctx, 122); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); - return false; + return ERROR_NULL; } -static bool marshal_Rremove(struct lib9p_ctx *ctx, struct lib9p_msg_Rremove *val, struct _marshal_ret *ret) { +static error marshal_Rremove(struct lib9p_ctx *ctx, struct lib9p_msg_Rremove *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rremove message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rremove message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 123); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_L || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -static bool marshal_Tstat(struct lib9p_ctx *ctx, struct lib9p_msg_Tstat *val, struct _marshal_ret *ret) { +static error marshal_Tstat(struct lib9p_ctx *ctx, struct lib9p_msg_Tstat *val, struct _marshal_ret *ret) { uint32_t needed_size = 11; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tstat message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tstat message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3259,10 +3235,10 @@ static bool marshal_Tstat(struct lib9p_ctx *ctx, struct lib9p_msg_Tstat *val, st MARSHAL_U8LE(ctx, 124); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); - return false; + return ERROR_NULL; } -static bool marshal_Rstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rstat *val, struct _marshal_ret *ret) { +static error marshal_Rstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rstat *val, struct _marshal_ret *ret) { uint32_t needed_size = 58 + val->stat.name.len + val->stat.owner_uname.len + val->stat.owner_gname.len + val->stat.last_modifier_uname.len; #if CONFIG_9P_ENABLE_9P2000_u if is_ver(ctx, 9P2000_u) { @@ -3270,10 +3246,9 @@ static bool marshal_Rstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rstat *val, st } #endif /* CONFIG_9P_ENABLE_9P2000_u */ if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rstat message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rstat message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3316,10 +3291,10 @@ static bool marshal_Rstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rstat *val, st MARSHAL_U32LE(ctx, val->stat.last_modifier_unum); } #endif /* CONFIG_9P_ENABLE_9P2000_u */ - return false; + return ERROR_NULL; } -static bool marshal_Twstat(struct lib9p_ctx *ctx, struct lib9p_msg_Twstat *val, struct _marshal_ret *ret) { +static error marshal_Twstat(struct lib9p_ctx *ctx, struct lib9p_msg_Twstat *val, struct _marshal_ret *ret) { uint32_t needed_size = 62 + val->stat.name.len + val->stat.owner_uname.len + val->stat.owner_gname.len + val->stat.last_modifier_uname.len; #if CONFIG_9P_ENABLE_9P2000_u if is_ver(ctx, 9P2000_u) { @@ -3327,10 +3302,9 @@ static bool marshal_Twstat(struct lib9p_ctx *ctx, struct lib9p_msg_Twstat *val, } #endif /* CONFIG_9P_ENABLE_9P2000_u */ if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Twstat message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Twstat message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3374,34 +3348,32 @@ static bool marshal_Twstat(struct lib9p_ctx *ctx, struct lib9p_msg_Twstat *val, MARSHAL_U32LE(ctx, val->stat.last_modifier_unum); } #endif /* CONFIG_9P_ENABLE_9P2000_u */ - return false; + return ERROR_NULL; } -static bool marshal_Rwstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rwstat *val, struct _marshal_ret *ret) { +static error marshal_Rwstat(struct lib9p_ctx *ctx, struct lib9p_msg_Rwstat *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rwstat message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rwstat message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 127); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u */ #if CONFIG_9P_ENABLE_9P2000_p9p -static bool marshal_Topenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Topenfd *val, struct _marshal_ret *ret) { +static error marshal_Topenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Topenfd *val, struct _marshal_ret *ret) { uint32_t needed_size = 12; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Topenfd message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Topenfd message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3410,16 +3382,15 @@ static bool marshal_Topenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Topenfd *val MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); MARSHAL_U8LE(ctx, val->mode & o_masks[ctx->version]); - return false; + return ERROR_NULL; } -static bool marshal_Ropenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Ropenfd *val, struct _marshal_ret *ret) { +static error marshal_Ropenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Ropenfd *val, struct _marshal_ret *ret) { uint32_t needed_size = 28; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Ropenfd message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Ropenfd message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3431,18 +3402,17 @@ static bool marshal_Ropenfd(struct lib9p_ctx *ctx, struct lib9p_msg_Ropenfd *val MARSHAL_U64LE(ctx, val->qid.path); MARSHAL_U32LE(ctx, val->iounit); MARSHAL_U32LE(ctx, val->unixfd); - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000_p9p */ #if CONFIG_9P_ENABLE_9P2000_L -static bool marshal_Rlerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rlerror *val, struct _marshal_ret *ret) { +static error marshal_Rlerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rlerror *val, struct _marshal_ret *ret) { uint32_t needed_size = 11; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rlerror message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rlerror message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3450,16 +3420,15 @@ static bool marshal_Rlerror(struct lib9p_ctx *ctx, struct lib9p_msg_Rlerror *val MARSHAL_U8LE(ctx, 7); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->errnum); - return false; + return ERROR_NULL; } -static bool marshal_Tstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Tstatfs *val, struct _marshal_ret *ret) { +static error marshal_Tstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Tstatfs *val, struct _marshal_ret *ret) { uint32_t needed_size = 11; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tstatfs message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tstatfs message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3467,16 +3436,15 @@ static bool marshal_Tstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Tstatfs *val MARSHAL_U8LE(ctx, 8); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); - return false; + return ERROR_NULL; } -static bool marshal_Rstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Rstatfs *val, struct _marshal_ret *ret) { +static error marshal_Rstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Rstatfs *val, struct _marshal_ret *ret) { uint32_t needed_size = 67; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rstatfs message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rstatfs message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3492,16 +3460,15 @@ static bool marshal_Rstatfs(struct lib9p_ctx *ctx, struct lib9p_msg_Rstatfs *val MARSHAL_U64LE(ctx, val->ffree); MARSHAL_U64LE(ctx, val->fsid); MARSHAL_U32LE(ctx, val->namelen); - return false; + return ERROR_NULL; } -static bool marshal_Tlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Tlopen *val, struct _marshal_ret *ret) { +static error marshal_Tlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Tlopen *val, struct _marshal_ret *ret) { uint32_t needed_size = 15; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tlopen message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tlopen message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3510,16 +3477,15 @@ static bool marshal_Tlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Tlopen *val, MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); MARSHAL_U32LE(ctx, val->flags & lo_masks[ctx->version]); - return false; + return ERROR_NULL; } -static bool marshal_Rlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Rlopen *val, struct _marshal_ret *ret) { +static error marshal_Rlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Rlopen *val, struct _marshal_ret *ret) { uint32_t needed_size = 24; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rlopen message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rlopen message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3530,16 +3496,15 @@ static bool marshal_Rlopen(struct lib9p_ctx *ctx, struct lib9p_msg_Rlopen *val, MARSHAL_U32LE(ctx, val->qid.vers); MARSHAL_U64LE(ctx, val->qid.path); MARSHAL_U32LE(ctx, val->iounit); - return false; + return ERROR_NULL; } -static bool marshal_Tlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tlcreate *val, struct _marshal_ret *ret) { +static error marshal_Tlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tlcreate *val, struct _marshal_ret *ret) { uint32_t needed_size = 25 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tlcreate message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tlcreate message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3552,16 +3517,15 @@ static bool marshal_Tlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Tlcreate *v MARSHAL_U32LE(ctx, val->flags & lo_masks[ctx->version]); MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); MARSHAL_U32LE(ctx, val->gid); - return false; + return ERROR_NULL; } -static bool marshal_Rlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rlcreate *val, struct _marshal_ret *ret) { +static error marshal_Rlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rlcreate *val, struct _marshal_ret *ret) { uint32_t needed_size = 24; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rlcreate message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rlcreate message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3572,16 +3536,15 @@ static bool marshal_Rlcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rlcreate *v MARSHAL_U32LE(ctx, val->qid.vers); MARSHAL_U64LE(ctx, val->qid.path); MARSHAL_U32LE(ctx, val->iounit); - return false; + return ERROR_NULL; } -static bool marshal_Tsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tsymlink *val, struct _marshal_ret *ret) { +static error marshal_Tsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tsymlink *val, struct _marshal_ret *ret) { uint32_t needed_size = 19 + val->name.len + val->symtgt.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tsymlink message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tsymlink message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3594,16 +3557,15 @@ static bool marshal_Tsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tsymlink *v MARSHAL_U16LE(ctx, val->symtgt.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->symtgt.utf8, val->symtgt.len); MARSHAL_U32LE(ctx, val->gid); - return false; + return ERROR_NULL; } -static bool marshal_Rsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rsymlink *val, struct _marshal_ret *ret) { +static error marshal_Rsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rsymlink *val, struct _marshal_ret *ret) { uint32_t needed_size = 20; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rsymlink message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rsymlink message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3613,16 +3575,15 @@ static bool marshal_Rsymlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rsymlink *v MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); MARSHAL_U32LE(ctx, val->qid.vers); MARSHAL_U64LE(ctx, val->qid.path); - return false; + return ERROR_NULL; } -static bool marshal_Tmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Tmknod *val, struct _marshal_ret *ret) { +static error marshal_Tmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Tmknod *val, struct _marshal_ret *ret) { uint32_t needed_size = 29 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tmknod message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tmknod message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3636,16 +3597,15 @@ static bool marshal_Tmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Tmknod *val, MARSHAL_U32LE(ctx, val->major); MARSHAL_U32LE(ctx, val->minor); MARSHAL_U32LE(ctx, val->gid); - return false; + return ERROR_NULL; } -static bool marshal_Rmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Rmknod *val, struct _marshal_ret *ret) { +static error marshal_Rmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Rmknod *val, struct _marshal_ret *ret) { uint32_t needed_size = 20; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rmknod message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rmknod message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3655,16 +3615,15 @@ static bool marshal_Rmknod(struct lib9p_ctx *ctx, struct lib9p_msg_Rmknod *val, MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); MARSHAL_U32LE(ctx, val->qid.vers); MARSHAL_U64LE(ctx, val->qid.path); - return false; + return ERROR_NULL; } -static bool marshal_Trename(struct lib9p_ctx *ctx, struct lib9p_msg_Trename *val, struct _marshal_ret *ret) { +static error marshal_Trename(struct lib9p_ctx *ctx, struct lib9p_msg_Trename *val, struct _marshal_ret *ret) { uint32_t needed_size = 17 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Trename message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Trename message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3675,32 +3634,30 @@ static bool marshal_Trename(struct lib9p_ctx *ctx, struct lib9p_msg_Trename *val MARSHAL_U32LE(ctx, val->dfid); MARSHAL_U16LE(ctx, val->name.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - return false; + return ERROR_NULL; } -static bool marshal_Rrename(struct lib9p_ctx *ctx, struct lib9p_msg_Rrename *val, struct _marshal_ret *ret) { +static error marshal_Rrename(struct lib9p_ctx *ctx, struct lib9p_msg_Rrename *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rrename message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rrename message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 21); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Treadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Treadlink *val, struct _marshal_ret *ret) { +static error marshal_Treadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Treadlink *val, struct _marshal_ret *ret) { uint32_t needed_size = 11; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Treadlink message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Treadlink message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3708,16 +3665,15 @@ static bool marshal_Treadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Treadlink MARSHAL_U8LE(ctx, 22); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); - return false; + return ERROR_NULL; } -static bool marshal_Rreadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rreadlink *val, struct _marshal_ret *ret) { +static error marshal_Rreadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rreadlink *val, struct _marshal_ret *ret) { uint32_t needed_size = 9 + val->target.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rreadlink message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rreadlink message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3726,16 +3682,15 @@ static bool marshal_Rreadlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rreadlink MARSHAL_U16LE(ctx, val->tag); MARSHAL_U16LE(ctx, val->target.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->target.utf8, val->target.len); - return false; + return ERROR_NULL; } -static bool marshal_Tgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetattr *val, struct _marshal_ret *ret) { +static error marshal_Tgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetattr *val, struct _marshal_ret *ret) { uint32_t needed_size = 19; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tgetattr message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tgetattr message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3744,16 +3699,15 @@ static bool marshal_Tgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetattr *v MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); MARSHAL_U64LE(ctx, val->request_mask & getattr_masks[ctx->version]); - return false; + return ERROR_NULL; } -static bool marshal_Rgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetattr *val, struct _marshal_ret *ret) { +static error marshal_Rgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetattr *val, struct _marshal_ret *ret) { uint32_t needed_size = 160; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rgetattr message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rgetattr message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3782,16 +3736,15 @@ static bool marshal_Rgetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetattr *v MARSHAL_U64LE(ctx, val->btime_nsec); MARSHAL_U64LE(ctx, val->gen); MARSHAL_U64LE(ctx, val->data_version); - return false; + return ERROR_NULL; } -static bool marshal_Tsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tsetattr *val, struct _marshal_ret *ret) { +static error marshal_Tsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tsetattr *val, struct _marshal_ret *ret) { uint32_t needed_size = 67; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tsetattr message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tsetattr message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3808,32 +3761,30 @@ static bool marshal_Tsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Tsetattr *v MARSHAL_U64LE(ctx, val->atime_nsec); MARSHAL_U64LE(ctx, val->mtime_sec); MARSHAL_U64LE(ctx, val->mtime_nsec); - return false; + return ERROR_NULL; } -static bool marshal_Rsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rsetattr *val, struct _marshal_ret *ret) { +static error marshal_Rsetattr(struct lib9p_ctx *ctx, struct lib9p_msg_Rsetattr *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rsetattr message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rsetattr message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 27); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Txattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrwalk *val, struct _marshal_ret *ret) { +static error marshal_Txattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrwalk *val, struct _marshal_ret *ret) { uint32_t needed_size = 17 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Txattrwalk message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Txattrwalk message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3844,16 +3795,15 @@ static bool marshal_Txattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrwal MARSHAL_U32LE(ctx, val->newfid); MARSHAL_U16LE(ctx, val->name.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - return false; + return ERROR_NULL; } -static bool marshal_Rxattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrwalk *val, struct _marshal_ret *ret) { +static error marshal_Rxattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrwalk *val, struct _marshal_ret *ret) { uint32_t needed_size = 15; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rxattrwalk message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rxattrwalk message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3861,16 +3811,15 @@ static bool marshal_Rxattrwalk(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrwal MARSHAL_U8LE(ctx, 31); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U64LE(ctx, val->attr_size); - return false; + return ERROR_NULL; } -static bool marshal_Txattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrcreate *val, struct _marshal_ret *ret) { +static error marshal_Txattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrcreate *val, struct _marshal_ret *ret) { uint32_t needed_size = 25 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Txattrcreate message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Txattrcreate message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3882,32 +3831,30 @@ static bool marshal_Txattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Txattrc MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); MARSHAL_U64LE(ctx, val->attr_size); MARSHAL_U32LE(ctx, val->flags); - return false; + return ERROR_NULL; } -static bool marshal_Rxattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrcreate *val, struct _marshal_ret *ret) { +static error marshal_Rxattrcreate(struct lib9p_ctx *ctx, struct lib9p_msg_Rxattrcreate *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rxattrcreate message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rxattrcreate message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 33); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Treaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Treaddir *val, struct _marshal_ret *ret) { +static error marshal_Treaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Treaddir *val, struct _marshal_ret *ret) { uint32_t needed_size = 23; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Treaddir message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Treaddir message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3917,16 +3864,15 @@ static bool marshal_Treaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Treaddir *v MARSHAL_U32LE(ctx, val->fid); MARSHAL_U64LE(ctx, val->offset); MARSHAL_U32LE(ctx, val->count); - return false; + return ERROR_NULL; } -static bool marshal_Rreaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Rreaddir *val, struct _marshal_ret *ret) { +static error marshal_Rreaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Rreaddir *val, struct _marshal_ret *ret) { uint64_t needed_size = 11 + val->count; if (needed_size > (uint64_t)(ctx->max_msg_size)) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rreaddir message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rreaddir message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = (uint32_t)needed_size; uint32_t offsetof_size = 0; @@ -3935,16 +3881,15 @@ static bool marshal_Rreaddir(struct lib9p_ctx *ctx, struct lib9p_msg_Rreaddir *v MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->count); MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; + return ERROR_NULL; } -static bool marshal_Tfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Tfsync *val, struct _marshal_ret *ret) { +static error marshal_Tfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Tfsync *val, struct _marshal_ret *ret) { uint32_t needed_size = 15; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tfsync message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tfsync message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3953,32 +3898,30 @@ static bool marshal_Tfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Tfsync *val, MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->fid); MARSHAL_U32LE(ctx, val->datasync); - return false; + return ERROR_NULL; } -static bool marshal_Rfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Rfsync *val, struct _marshal_ret *ret) { +static error marshal_Rfsync(struct lib9p_ctx *ctx, struct lib9p_msg_Rfsync *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rfsync message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rfsync message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 51); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Tlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tlock *val, struct _marshal_ret *ret) { +static error marshal_Tlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tlock *val, struct _marshal_ret *ret) { uint32_t needed_size = 38 + val->client_id.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tlock message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tlock message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -3993,16 +3936,15 @@ static bool marshal_Tlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tlock *val, st MARSHAL_U32LE(ctx, val->proc_id); MARSHAL_U16LE(ctx, val->client_id.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); - return false; + return ERROR_NULL; } -static bool marshal_Rlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rlock *val, struct _marshal_ret *ret) { +static error marshal_Rlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rlock *val, struct _marshal_ret *ret) { uint32_t needed_size = 8; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rlock message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rlock message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4010,16 +3952,15 @@ static bool marshal_Rlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rlock *val, st MARSHAL_U8LE(ctx, 53); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U8LE(ctx, val->status); - return false; + return ERROR_NULL; } -static bool marshal_Tgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetlock *val, struct _marshal_ret *ret) { +static error marshal_Tgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetlock *val, struct _marshal_ret *ret) { uint32_t needed_size = 34 + val->client_id.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tgetlock message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tgetlock message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4033,16 +3974,15 @@ static bool marshal_Tgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Tgetlock *v MARSHAL_U32LE(ctx, val->proc_id); MARSHAL_U16LE(ctx, val->client_id.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); - return false; + return ERROR_NULL; } -static bool marshal_Rgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetlock *val, struct _marshal_ret *ret) { +static error marshal_Rgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetlock *val, struct _marshal_ret *ret) { uint32_t needed_size = 30 + val->client_id.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rgetlock message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rgetlock message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4055,16 +3995,15 @@ static bool marshal_Rgetlock(struct lib9p_ctx *ctx, struct lib9p_msg_Rgetlock *v MARSHAL_U32LE(ctx, val->proc_id); MARSHAL_U16LE(ctx, val->client_id.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->client_id.utf8, val->client_id.len); - return false; + return ERROR_NULL; } -static bool marshal_Tlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tlink *val, struct _marshal_ret *ret) { +static error marshal_Tlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tlink *val, struct _marshal_ret *ret) { uint32_t needed_size = 17 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tlink message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tlink message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4075,32 +4014,30 @@ static bool marshal_Tlink(struct lib9p_ctx *ctx, struct lib9p_msg_Tlink *val, st MARSHAL_U32LE(ctx, val->fid); MARSHAL_U16LE(ctx, val->name.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); - return false; + return ERROR_NULL; } -static bool marshal_Rlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rlink *val, struct _marshal_ret *ret) { +static error marshal_Rlink(struct lib9p_ctx *ctx, struct lib9p_msg_Rlink *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rlink message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rlink message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 71); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Tmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Tmkdir *val, struct _marshal_ret *ret) { +static error marshal_Tmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Tmkdir *val, struct _marshal_ret *ret) { uint32_t needed_size = 21 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tmkdir message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tmkdir message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4112,16 +4049,15 @@ static bool marshal_Tmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Tmkdir *val, MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); MARSHAL_U32LE(ctx, val->mode & mode_masks[ctx->version]); MARSHAL_U32LE(ctx, val->gid); - return false; + return ERROR_NULL; } -static bool marshal_Rmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Rmkdir *val, struct _marshal_ret *ret) { +static error marshal_Rmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Rmkdir *val, struct _marshal_ret *ret) { uint32_t needed_size = 20; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rmkdir message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rmkdir message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4131,16 +4067,15 @@ static bool marshal_Rmkdir(struct lib9p_ctx *ctx, struct lib9p_msg_Rmkdir *val, MARSHAL_U8LE(ctx, val->qid.type & qt_masks[ctx->version]); MARSHAL_U32LE(ctx, val->qid.vers); MARSHAL_U64LE(ctx, val->qid.path); - return false; + return ERROR_NULL; } -static bool marshal_Trenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Trenameat *val, struct _marshal_ret *ret) { +static error marshal_Trenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Trenameat *val, struct _marshal_ret *ret) { uint32_t needed_size = 19 + val->oldname.len + val->newname.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Trenameat message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Trenameat message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4153,32 +4088,30 @@ static bool marshal_Trenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Trenameat MARSHAL_U32LE(ctx, val->newdirfid); MARSHAL_U16LE(ctx, val->newname.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->newname.utf8, val->newname.len); - return false; + return ERROR_NULL; } -static bool marshal_Rrenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Rrenameat *val, struct _marshal_ret *ret) { +static error marshal_Rrenameat(struct lib9p_ctx *ctx, struct lib9p_msg_Rrenameat *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rrenameat message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rrenameat message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 75); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Tunlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Tunlinkat *val, struct _marshal_ret *ret) { +static error marshal_Tunlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Tunlinkat *val, struct _marshal_ret *ret) { uint32_t needed_size = 17 + val->name.len; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tunlinkat message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tunlinkat message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4189,34 +4122,32 @@ static bool marshal_Tunlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Tunlinkat MARSHAL_U16LE(ctx, val->name.len); MARSHAL_BYTES_ZEROCOPY(ctx, val->name.utf8, val->name.len); MARSHAL_U32LE(ctx, val->flags); - return false; + return ERROR_NULL; } -static bool marshal_Runlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Runlinkat *val, struct _marshal_ret *ret) { +static error marshal_Runlinkat(struct lib9p_ctx *ctx, struct lib9p_msg_Runlinkat *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Runlinkat message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Runlinkat message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 77); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000_L */ #if CONFIG_9P_ENABLE_9P2000_e -static bool marshal_Tsession(struct lib9p_ctx *ctx, struct lib9p_msg_Tsession *val, struct _marshal_ret *ret) { +static error marshal_Tsession(struct lib9p_ctx *ctx, struct lib9p_msg_Tsession *val, struct _marshal_ret *ret) { uint32_t needed_size = 15; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tsession message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tsession message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4224,35 +4155,33 @@ static bool marshal_Tsession(struct lib9p_ctx *ctx, struct lib9p_msg_Tsession *v MARSHAL_U8LE(ctx, 150); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U64LE(ctx, val->key); - return false; + return ERROR_NULL; } -static bool marshal_Rsession(struct lib9p_ctx *ctx, struct lib9p_msg_Rsession *val, struct _marshal_ret *ret) { +static error marshal_Rsession(struct lib9p_ctx *ctx, struct lib9p_msg_Rsession *val, struct _marshal_ret *ret) { uint32_t needed_size = 7; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rsession message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rsession message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; MARSHAL_U32LE(ctx, offsetof_end - offsetof_size); MARSHAL_U8LE(ctx, 151); MARSHAL_U16LE(ctx, val->tag); - return false; + return ERROR_NULL; } -static bool marshal_Tsread(struct lib9p_ctx *ctx, struct lib9p_msg_Tsread *val, struct _marshal_ret *ret) { +static error marshal_Tsread(struct lib9p_ctx *ctx, struct lib9p_msg_Tsread *val, struct _marshal_ret *ret) { uint64_t needed_size = 13; for (uint16_t i = 0; i < val->nwname; i++) { needed_size += 2 + val->wname[i].len; } if (needed_size > (uint64_t)(ctx->max_msg_size)) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tsread message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tsread message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = (uint32_t)needed_size; uint32_t offsetof_size = 0; @@ -4265,16 +4194,15 @@ static bool marshal_Tsread(struct lib9p_ctx *ctx, struct lib9p_msg_Tsread *val, MARSHAL_U16LE(ctx, val->wname[i].len); MARSHAL_BYTES_ZEROCOPY(ctx, val->wname[i].utf8, val->wname[i].len); } - return false; + return ERROR_NULL; } -static bool marshal_Rsread(struct lib9p_ctx *ctx, struct lib9p_msg_Rsread *val, struct _marshal_ret *ret) { +static error marshal_Rsread(struct lib9p_ctx *ctx, struct lib9p_msg_Rsread *val, struct _marshal_ret *ret) { uint64_t needed_size = 11 + val->count; if (needed_size > (uint64_t)(ctx->max_msg_size)) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rsread message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rsread message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = (uint32_t)needed_size; uint32_t offsetof_size = 0; @@ -4283,19 +4211,18 @@ static bool marshal_Rsread(struct lib9p_ctx *ctx, struct lib9p_msg_Rsread *val, MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->count); MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; + return ERROR_NULL; } -static bool marshal_Tswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Tswrite *val, struct _marshal_ret *ret) { +static error marshal_Tswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Tswrite *val, struct _marshal_ret *ret) { uint64_t needed_size = 17 + val->count; for (uint16_t i = 0; i < val->nwname; i++) { needed_size += 2 + val->wname[i].len; } if (needed_size > (uint64_t)(ctx->max_msg_size)) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Tswrite message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Tswrite message too large to marshal into ", ctx->version ? "negotiated" : "client", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = (uint32_t)needed_size; uint32_t offsetof_size = 0; @@ -4310,16 +4237,15 @@ static bool marshal_Tswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Tswrite *val } MARSHAL_U32LE(ctx, val->count); MARSHAL_BYTES_ZEROCOPY(ctx, val->data, val->count); - return false; + return ERROR_NULL; } -static bool marshal_Rswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rswrite *val, struct _marshal_ret *ret) { +static error marshal_Rswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rswrite *val, struct _marshal_ret *ret) { uint32_t needed_size = 11; if (needed_size > ctx->max_msg_size) { - lib9p_error(ctx, LIB9P_ERRNO_L_ERANGE, "Rswrite message too large to marshal into ", + return error_new(E_POSIX_ERANGE, "Rswrite message too large to marshal into ", ctx->version ? "negotiated" : "server", " limit", " (", needed_size, " > ", ctx->max_msg_size, ")"); - return true; } uint32_t offsetof_end = needed_size; uint32_t offsetof_size = 0; @@ -4327,7 +4253,7 @@ static bool marshal_Rswrite(struct lib9p_ctx *ctx, struct lib9p_msg_Rswrite *val MARSHAL_U8LE(ctx, 155); MARSHAL_U16LE(ctx, val->tag); MARSHAL_U32LE(ctx, val->count); - return false; + return ERROR_NULL; } #endif /* CONFIG_9P_ENABLE_9P2000_e */ @@ -8177,7 +8103,7 @@ const struct _lib9p_send_tentry _lib9p_table_Rmsg_send[LIB9P_VER_NUM][0x80] = { }; #if CONFIG_9P_ENABLE_9P2000 || CONFIG_9P_ENABLE_9P2000_e || CONFIG_9P_ENABLE_9P2000_p9p || CONFIG_9P_ENABLE_9P2000_u -LM_FLATTEN ssize_t _lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) { +LM_FLATTEN size_t_or_error _lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) { return validate_stat(ctx, net_size, net_bytes, ret_net_size); } LM_FLATTEN void _lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out) { diff --git a/lib9p/core_include/lib9p/core.h b/lib9p/core_include/lib9p/core.h index 27553a3..9d92312 100644 --- a/lib9p/core_include/lib9p/core.h +++ b/lib9p/core_include/lib9p/core.h @@ -20,11 +20,6 @@ #include <lib9p/_core_generated.h> /* _after_ other includes, including config.h */ -#ifndef CONFIG_9P_MAX_ERR_SIZE - #error config.h must define CONFIG_9P_MAX_ERR_SIZE -#endif -static_assert(CONFIG_9P_MAX_ERR_SIZE <= UINT16_MAX); - /* constants ******************************************************************/ enum { @@ -49,40 +44,8 @@ struct lib9p_ctx { /* negotiated */ enum lib9p_version version; uint32_t max_msg_size; - - /* state */ -#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L - lib9p_errno_t err_num; -#endif - [[gnu::nonstring]] char err_msg[CONFIG_9P_MAX_ERR_SIZE]; }; -void lib9p_ctx_clear_error(struct lib9p_ctx *ctx); - -bool lib9p_ctx_has_error(struct lib9p_ctx *ctx); - -#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L - #define _lib9p_set_err_num(ctx, linux_errno) do { (ctx)->err_num = linux_errno; } while (0) -#else - #define _lib9p_set_err_num(ctx, linux_errno) do { } while (0) -#endif - -/** Write a <libmisc/fmt.h>-style error into ctx, return -1. */ -#define lib9p_error(ctx, linux_errno, ...) ({ \ - if (!lib9p_ctx_has_error(ctx)) { \ - _lib9p_set_err_num(ctx, linux_errno); \ - struct fmt_buf _w = { \ - .dat = (ctx)->err_msg, \ - .cap = sizeof((ctx)->err_msg), \ - }; \ - lo_interface fmt_dest w = LO_BOX(fmt_dest, &_w); \ - fmt_print(w, __VA_ARGS__); \ - if (_w.len < _w.cap) \ - memset(_w.dat + _w.len, 0, _w.cap - _w.len); \ - } \ - -1; \ -}) - /* misc utilities *************************************************************/ uint32_t lib9p_version_min_Rerror_size(enum lib9p_version); @@ -100,19 +63,19 @@ void fmt_print_lib9p_msg(lo_interface fmt_dest w, struct lib9p_ctx *ctx, enum li * number may be larger than net_bytes due to (1) struct padding, (2) * array pointers. * - * @param ctx : negotiated protocol parameters, where to record errors + * @param ctx : negotiated protocol parameters * @param net_bytes : the complete request, starting with the "size[4]" * - * @return required size, or -1 on error + * @return required size, or an error * - * @errno L_EOPNOTSUPP: message is an R-message - * @errno L_EOPNOTSUPP: message has unknown type - * @errno L_EBADMSG: message is wrong size for content - * @errno L_EILSEQ: message contains invalid UTF-8, or the UTF-8 contains a nul-byte - * @errno L_EBADMSG: message contains a bitfield with unknown bits - * @errno L_EMSGSIZE: would-be return value overflows SSIZE_MAX + * @errno E_POSIX_EOPNOTSUPP: message is an R-message + * @errno E_POSIX_EOPNOTSUPP: message has unknown type + * @errno E_POSIX_EBADMSG: message is wrong size for content + * @errno E_POSIX_EILSEQ: message contains invalid UTF-8, or the UTF-8 contains a nul-byte + * @errno E_POSIX_EBADMSG: message contains a bitfield with unknown bits + * @errno E_POSIX_EMSGSIZE: would-be return value overflows SSIZE_MAX */ -ssize_t lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); +size_t_or_error lib9p_Tmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); /** * Unmarshal the 9P message `net_bytes` into the C struct `ret_body`. @@ -138,27 +101,27 @@ void lib9p_Tmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, * 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 ctx : negotiated protocol parameters * @param typ : the message type * @param msg : the message to encode (`struct lib9p_msg_XXXX` according to `typ`) * * @return ret : the buffer to encode to - * @return whether there was an error (false=success, true=error) + * @return error * - * @errno L_ERANGE: reply does not fit in ctx->max_msg_size + * @errno E_POSIX_ERANGE: reply does not fit in ctx->max_msg_size */ -bool lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, - struct lib9p_Tmsg_send_buf *ret); +error lib9p_Tmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, + struct lib9p_Tmsg_send_buf *ret); /* main R-message functions ***************************************************/ /** Same as above, but for R-messages instead of T-messages. */ -ssize_t lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); +size_t_or_error lib9p_Rmsg_validate(struct lib9p_ctx *ctx, uint8_t *net_bytes); void lib9p_Rmsg_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, enum lib9p_msg_type *ret_typ, void *ret_body); -bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, - struct lib9p_Rmsg_send_buf *ret); +error lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body, + struct lib9p_Rmsg_send_buf *ret); /* `struct lib9p_stat` helpers ************************************************/ @@ -170,16 +133,16 @@ void fmt_print_lib9p_stat(lo_interface fmt_dest w, struct lib9p_ctx *ctx, struct /** * Validate a message's `stat` structure. * - * @param ctx : negotiated protocol parameters, where to record errors + * @param ctx : negotiated protocol parameters * @param net_bytes : network-encoded stat structure * @param net_size : the number of net_bytes that may be read * * @return ret_net_size : number of bytes consumed; <=net_size * @return ret_host_size : number of bytes that lib9p_stat_unmarshal would take - * @return whether there was an error + * @return error */ -bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, - uint32_t *ret_net_size, size_t *ret_host_size); +error lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, + uint32_t *ret_net_size, size_t *ret_host_size); /** * Unmarshal the 9P `net_bytes` into the C struct `ret_obj`. diff --git a/lib9p/core_tables.h b/lib9p/core_tables.h index e3dc8f4..8f8c8d6 100644 --- a/lib9p/core_tables.h +++ b/lib9p/core_tables.h @@ -27,7 +27,7 @@ struct _lib9p_msg_tentry { _print_fn_t print; }; -typedef ssize_t (*_validate_fn_t)(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes); +typedef size_t_or_error (*_validate_fn_t)(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes); typedef void (*_unmarshal_fn_t)(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out); struct _lib9p_recv_tentry { _validate_fn_t validate; @@ -40,7 +40,7 @@ struct _marshal_ret { size_t net_copied_size; uint8_t *net_copied; }; -typedef bool (*_marshal_fn_t)(struct lib9p_ctx *ctx, void *host_val, struct _marshal_ret *ret); +typedef error (*_marshal_fn_t)(struct lib9p_ctx *ctx, void *host_val, struct _marshal_ret *ret); struct _lib9p_send_tentry { _marshal_fn_t marshal; }; @@ -54,7 +54,7 @@ extern const struct _lib9p_send_tentry _lib9p_table_Rmsg_send[LIB9P_VER_NUM][0x8 /* stat ***********************************************************************/ #if _LIB9P_ENABLE_stat -ssize_t _lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size); +size_t_or_error _lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size); void _lib9p_stat_unmarshal(struct lib9p_ctx *ctx, uint8_t *net_bytes, void *out); bool _lib9p_stat_marshal(struct lib9p_ctx *ctx, struct lib9p_stat *val, struct _marshal_ret *ret); #endif diff --git a/lib9p/srv.c b/lib9p/srv.c index 32e9a9a..085cc8b 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -27,6 +27,8 @@ #define IMPLEMENTATION_FOR_LIB9P_SRV_H YES #include <lib9p/srv.h> +#include "srv_errno.h" + /* config *********************************************************************/ #include "config.h" @@ -47,12 +49,6 @@ bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx) { return cr_chan_can_send(&ctx->flush_ch); } -void lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) { - assert(ctx); - assert(cr_chan_can_send(&ctx->flush_ch)); - ctx->flush_acknowledged = true; -} - #define req_debug(...) \ log_debugln( \ "cid=", cr_getcid(), ": ", \ @@ -123,6 +119,8 @@ struct srv_fidinfo { } auth; }; }; +typedef struct srv_fidinfo *srv_fidinfop; +DECLARE_ERROR_OR(srv_fidinfop); /* contexts ************************************** * @@ -279,11 +277,13 @@ static inline void srv_path_decref(struct srv_req *ctx, srv_path_t path) { } } -static inline void srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, struct srv_fidinfo *fidinfo, bool remove) { +static inline error srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, struct srv_fidinfo *fidinfo, bool remove) { assert(ctx); assert(!ctx->user); assert(fidinfo); + error err = {}; + if (fidinfo->flags & FIDFLAG_RCLOSE) remove = true; ctx->user = srv_userid_incref(fidinfo->user); @@ -292,7 +292,7 @@ static inline void srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, struct srv_ assert(pathinfo); if (remove) - LO_CALL(pathinfo->file, remove, ctx); + err = LO_CALL(pathinfo->file, remove, ctx); if (fidinfo->flags & FIDFLAG_OPEN) { switch (fidinfo->type) { @@ -313,6 +313,8 @@ static inline void srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, struct srv_ map_del(&ctx->parent_sess->fids, fid); ctx->user = srv_userid_decref(ctx->user); + + return err; } /** @@ -320,7 +322,7 @@ static inline void srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, struct srv_ * pathinfo->gc_refcount has already been incremented; does *not* * decrement it on failure. */ -static inline struct srv_fidinfo *srv_fid_store(struct srv_req *ctx, lib9p_fid_t fid, struct srv_pathinfo *pathinfo, bool overwrite) { +static inline srv_fidinfop_or_error srv_fid_store(struct srv_req *ctx, lib9p_fid_t fid, struct srv_pathinfo *pathinfo, bool overwrite) { assert(ctx); assert(fid != LIB9P_FID_NOFID); assert(pathinfo); @@ -341,9 +343,7 @@ static inline struct srv_fidinfo *srv_fid_store(struct srv_req *ctx, lib9p_fid_t srv_path_decref(ctx, old_fidinfo->path); map_del(&ctx->parent_sess->fids, fid); } else { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "FID already in use"); - return NULL; + return ERROR_NEW_ERR(srv_fidinfop, error_new(E_POSIX_EBADF, "FID already in use")); } } struct srv_fidinfo *fidinfo = map_store(&ctx->parent_sess->fids, fid, (struct srv_fidinfo){ @@ -352,7 +352,7 @@ static inline struct srv_fidinfo *srv_fid_store(struct srv_req *ctx, lib9p_fid_t .user = srv_userid_incref(ctx->user), }); assert(fidinfo); - return fidinfo; + return ERROR_NEW_VAL(srv_fidinfop, fidinfo); } /* base utilities *************************************************************/ @@ -366,29 +366,25 @@ static void srv_msglog(struct srv_req *req, enum lib9p_msg_type typ, void *hostm log_infoln(typ % 2 ? "< " : "> ", (lib9p_msg, &req->basectx, typ, hostmsg)); } -static ssize_t srv_write_Rmsg(struct srv_req *req, struct lib9p_Rmsg_send_buf *resp) { - ssize_t r; +#define srv_nonrespond_error log_errorln + +static void srv_write_Rmsg(struct srv_req *req, struct lib9p_Rmsg_send_buf *resp) { + size_t_and_error r; cr_mutex_lock(&req->parent_sess->parent_conn->writelock); r = io_writev(req->parent_sess->parent_conn->fd, resp->iov, resp->iov_cnt); cr_mutex_unlock(&req->parent_sess->parent_conn->writelock); - return r; + if (!ERROR_IS_NULL(r.err)) + srv_nonrespond_error("write: (", r.size_t, ", ", (error, r.err), ")"); } -#define srv_nonrespond_error log_errorln - -static void srv_respond_error(struct srv_req *req) { -#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L - assert(req->basectx.err_num); -#endif - assert(req->basectx.err_msg[0]); +static void srv_respond_error(struct srv_req *req, error err) { + assert(!ERROR_IS_NULL(err)); - ssize_t r; struct lib9p_msg_Rerror host = { .tag = req->tag, - .errstr = lib9p_strn(req->basectx.err_msg, - CONFIG_9P_MAX_ERR_SIZE), + .errstr = lib9p_str((char *)error_msg(err)), /* cast to discard `const` */ #if CONFIG_9P_ENABLE_9P2000_u - .errnum = req->basectx.err_num, + .errnum = libmisc_to_linuxgeneric_errno(err.num), #endif }; @@ -397,7 +393,7 @@ static void srv_respond_error(struct srv_req *req) { uint32_t overhead = lib9p_version_min_Rerror_size(sess->version); /* Truncate the error-string if necessary to avoid needing to - * return LIB9P_ERRNO_L_ERANGE. */ + * return E_POSIX_ERANGE. */ if (((uint32_t)host.errstr.len) + overhead > sess->max_msg_size) host.errstr.len = sess->max_msg_size - overhead; @@ -408,28 +404,30 @@ static void srv_respond_error(struct srv_req *req) { &net); srv_msglog(req, LIB9P_TYP_Rerror, &host); - r = srv_write_Rmsg(req, &net); - if (r < 0) - srv_nonrespond_error("write: ", net_strerror(-r)); + srv_write_Rmsg(req, &net); + error_cleanup(&err); } /* read coroutine *************************************************************/ +/** Return whether to `break`. */ static inline bool srv_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 = io_read(fd, &buf[*done], goal - *done); - if (r < 0) { - srv_nonrespond_error("read: ", net_strerror(-r)); - return true; - } else if (r == 0) { - if (*done != 0) - srv_nonrespond_error("read: unexpected EOF"); + size_t_or_error r = io_read(fd, &buf[*done], goal - *done); + if (r.is_err) { + if (r.err.num == E_EOF) { + if (*done != 0) + srv_nonrespond_error("read: unexpected EOF"); + } else { + srv_nonrespond_error("read: ", (error, r.err)); + } + error_cleanup(&r.err); return true; } - *done += r; + *done += r.size_t; } return false; } @@ -442,16 +440,17 @@ void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stre srv->readers++; for (;;) { - lo_interface net_stream_conn conn = LO_CALL(listener, accept); - if (LO_IS_NULL(conn)) { - srv_nonrespond_error("accept: error"); + net_stream_conn_or_error r = LO_CALL(listener, accept); + if (r.is_err) { + srv_nonrespond_error("accept: ", (error, r.err)); + error_cleanup(&r.err); srv->readers--; if (srv->readers == 0) while (srv->writers > 0) cr_rpc_send_req(&srv->_reqch, NULL); return; } - lib9p_srv_read(srv, conn); + lib9p_srv_read(srv, r.net_stream_conn); } } @@ -495,10 +494,9 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) { .net_bytes = buf, }; if (goal > sess.max_msg_size) { - lib9p_error(&req.basectx, LIB9P_ERRNO_L_EMSGSIZE, - "T-message larger than ", sess.initialized ? "negotiated" : "server", " limit", - " (", goal, " > ", sess.max_msg_size, ")"); - srv_respond_error(&req); + srv_respond_error(&req, error_new(E_POSIX_EMSGSIZE, + "T-message larger than ", sess.initialized ? "negotiated" : "server", " limit", + " (", goal, " > ", sess.max_msg_size, ")")); continue; } req.net_bytes = malloc(goal); @@ -517,14 +515,26 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) { /* ...but usually in another coroutine. */ cr_rpc_send_req(&srv->_reqch, &req); } - if (map_len(&sess.reqs) == 0) - io_close(conn.fd); - else { - io_close_read(conn.fd); + if (map_len(&sess.reqs) == 0) { + error err = io_close(conn.fd); + if (!ERROR_IS_NULL(err)) { + srv_nonrespond_error("conn close: ", (error, err)); + error_cleanup(&err); + } + } else { + error err = io_close_read(conn.fd); + if (!ERROR_IS_NULL(err)) { + srv_nonrespond_error("conn close: ", (error, err)); + error_cleanup(&err); + } sess.closing = true; cr_pause_and_yield(); assert(map_len(&sess.reqs) == 0); - io_close_write(conn.fd); + err = io_close_write(conn.fd); + if (!ERROR_IS_NULL(err)) { + srv_nonrespond_error("conn close: ", (error, err)); + error_cleanup(&err); + } } assert(map_len(&sess.reqs) == 0); @@ -538,10 +548,10 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) { .parent_sess = &sess, }; MAP_FOREACH(&sess.fids, fid, fidinfo) { - srv_fid_del(&pseudoreq, fid, fidinfo, false); - if (lib9p_ctx_has_error(&pseudoreq.basectx)) { - srv_nonrespond_error("clunk: ", (strn, pseudoreq.basectx.err_msg, CONFIG_9P_MAX_ERR_SIZE)); - lib9p_ctx_clear_error(&pseudoreq.basectx); + error err = srv_fid_del(&pseudoreq, fid, fidinfo, false); + if (!ERROR_IS_NULL(err)) { + srv_nonrespond_error("clunk: ", (error, err)); + error_cleanup(&err); } } map_free(&sess.fids); @@ -615,11 +625,12 @@ void lib9p_srv_worker(struct srv_req *ctx) { uint8_t *host_req = NULL; /* Unmarshal it. *****************************************************/ - ssize_t host_size = lib9p_Tmsg_validate(&ctx->basectx, ctx->net_bytes); - if (host_size < 0) { - srv_respond_error(ctx); + size_t_or_error r = lib9p_Tmsg_validate(&ctx->basectx, ctx->net_bytes); + if (r.is_err) { + srv_respond_error(ctx, r.err); goto release; } + size_t host_size = r.size_t; host_req = calloc(1, host_size); assert(host_req); enum lib9p_msg_type typ; @@ -675,28 +686,31 @@ void lib9p_srv_worker(struct srv_req *ctx) { free(ctx->net_bytes); } -static inline void _srv_respond(struct srv_req *ctx, enum lib9p_msg_type resp_typ, void *host_resp) { +static inline void _srv_respond(struct srv_req *ctx, enum lib9p_msg_type resp_typ, void *host_resp, error err) { assert(!ctx->responded); - if (lib9p_ctx_has_error(&ctx->basectx)) { - error: - srv_respond_error(ctx); - } else if (ctx->flush_acknowledged) { - /* do nothing */ + if (!ERROR_IS_NULL(err)) { + if (err.num == E_POSIX_ECANCELED && lib9p_srv_flush_requested(ctx)) { + error_cleanup(&err); + } else { + error: + srv_respond_error(ctx, err); + } } else { assert(host_resp); struct lib9p_Rmsg_send_buf net_resp; - if (lib9p_Rmsg_marshal(&ctx->basectx, - resp_typ, host_resp, - &net_resp)) + err = lib9p_Rmsg_marshal(&ctx->basectx, + resp_typ, host_resp, + &net_resp); + if (!ERROR_IS_NULL(err)) goto error; srv_msglog(ctx, resp_typ, host_resp); srv_write_Rmsg(ctx, &net_resp); } ctx->responded = true; } -#define srv_respond(CTX, TYP, HOST_RESP) do { \ - struct lib9p_msg_R##TYP *_host_resp = HOST_RESP; \ - _srv_respond(CTX, LIB9P_TYP_R##TYP, _host_resp); \ +#define srv_respond(CTX, TYP, HOST_RESP, ERR) do { \ + struct lib9p_msg_R##TYP *_host_resp = HOST_RESP; \ + _srv_respond(CTX, LIB9P_TYP_R##TYP, _host_resp, ERR); \ } while (0) /* handle_T* ******************************************************************/ @@ -705,7 +719,8 @@ static inline void _srv_respond(struct srv_req *ctx, enum lib9p_msg_type resp_ty assert(ctx); \ assert(req); \ struct lib9p_msg_T##typ *_typecheck_req [[maybe_unused]] = req; \ - struct lib9p_msg_R##typ resp = { .tag = ctx->tag } + struct lib9p_msg_R##typ resp = { .tag = ctx->tag }; \ + error err = {} static void handle_Tversion(struct srv_req *ctx, struct lib9p_msg_Tversion *req) { @@ -745,9 +760,8 @@ static void handle_Tversion(struct srv_req *ctx, uint32_t min_msg_size = _LIB9P_MAX(lib9p_version_min_Rerror_size(ctx->basectx.version), lib9p_version_min_Rread_size(ctx->basectx.version)+1); if (req->max_msg_size < min_msg_size) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EDOM, "requested max_msg_size is less than minimum for ", lib9p_version_str(version), - " (", req->max_msg_size, " < ", min_msg_size, ")"); + err = error_new(E_POSIX_EDOM, "requested max_msg_size is less than minimum for ", lib9p_version_str(version), + " (", req->max_msg_size, " < ", min_msg_size, ")"); goto tversion_return; } @@ -777,10 +791,10 @@ static void handle_Tversion(struct srv_req *ctx, } /* Close all FIDs. */ MAP_FOREACH(&ctx->parent_sess->fids, fid, fidinfo) { - srv_fid_del(ctx, fid, fidinfo, false); - if (lib9p_ctx_has_error(&ctx->basectx)) { - srv_nonrespond_error("clunk: ", (strn, ctx->basectx.err_msg, CONFIG_9P_MAX_ERR_SIZE)); - lib9p_ctx_clear_error(&ctx->basectx); + error fiderr = srv_fid_del(ctx, fid, fidinfo, false); + if (!ERROR_IS_NULL(fiderr)) { + srv_nonrespond_error("clunk: ", (error, fiderr)); + error_cleanup(&fiderr); } } @@ -789,7 +803,7 @@ static void handle_Tversion(struct srv_req *ctx, ctx->parent_sess->max_msg_size = resp.max_msg_size; tversion_return: - srv_respond(ctx, version, &resp); + srv_respond(ctx, version, &resp, err); } #if _LIB9P_ENABLE_stat @@ -799,23 +813,22 @@ static void handle_Tauth(struct srv_req *ctx, struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv; if (!srv->auth) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "authentication not required"); + err = error_new(E_POSIX_EOPNOTSUPP, "authentication not required"); goto tauth_return; } ctx->user = srv_userid_new(req->uname, req->unum); - srv->auth(ctx, req->aname); - - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "TODO: auth not implemented"); + err = srv->auth(ctx, req->aname); + if (!ERROR_IS_NULL(err)) + goto tauth_return; - if (lib9p_ctx_has_error(&ctx->basectx)) - ctx->user = srv_userid_decref(ctx->user); + err = error_new(E_POSIX_EOPNOTSUPP, "TODO: auth not implemented"); tauth_return: - srv_respond(ctx, auth, &resp); + if (!ERROR_IS_NULL(err) && ctx->user) + ctx->user = srv_userid_decref(ctx->user); + srv_respond(ctx, auth, &resp, err); } static void handle_Tattach(struct srv_req *ctx, @@ -823,8 +836,7 @@ static void handle_Tattach(struct srv_req *ctx, srv_handler_common(ctx, attach, req); if (req->fid == LIB9P_FID_NOFID) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "cannot assign to NOFID"); + err = error_new(E_POSIX_EBADF, "cannot assign to NOFID"); goto tattach_return; } @@ -832,48 +844,43 @@ static void handle_Tattach(struct srv_req *ctx, if (srv->auth) { struct srv_fidinfo *afid = map_load(&ctx->parent_sess->fids, req->afid); if (!afid) - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "FID provided as auth-file is not a valid FID"); + err = error_new(E_POSIX_EACCES, "FID provided as auth-file is not a valid FID"); else if (afid->type != SRV_FILETYPE_AUTH) - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "FID provided as auth-file is not an auth-file"); + err = error_new(E_POSIX_EACCES, "FID provided as auth-file is not an auth-file"); else if (!lib9p_str_eq(afid->user->name, req->uname)) - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, - "FID provided as auth-file is for user=", (qmem, afid->user->name.utf8, afid->user->name.len), - " and cannot be used for user=", (qmem, req->uname.utf8, req->uname.len)); + err = error_new(E_POSIX_EACCES, + "FID provided as auth-file is for user=", (qmem, afid->user->name.utf8, afid->user->name.len), + " and cannot be used for user=", (qmem, req->uname.utf8, req->uname.len)); #if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L else if (afid->user->num != req->unum) - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, - "FID provided as auth-file is for user=", afid->user->num, - " and cannot be used for user=", req->unum); + err = error_new(E_POSIX_EACCES, + "FID provided as auth-file is for user=", afid->user->num, + " and cannot be used for user=", req->unum); #endif else if (!lib9p_str_eq(afid->auth.aname, req->aname)) - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, - "FID provided as auth-file is for tree=", (qmem, afid->auth.aname.utf8, afid->auth.aname.len), - " and cannot be used for tree=", (qmem, req->aname.utf8, req->aname.len)); + err = error_new(E_POSIX_EACCES, + "FID provided as auth-file is for tree=", (qmem, afid->auth.aname.utf8, afid->auth.aname.len), + " and cannot be used for tree=", (qmem, req->aname.utf8, req->aname.len)); else if (!afid->auth.completed) - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "FID provided as auth-file has not completed authentication"); - if (lib9p_ctx_has_error(&ctx->basectx)) + err = error_new(E_POSIX_EACCES, "FID provided as auth-file has not completed authentication"); + if (!ERROR_IS_NULL(err)) goto tattach_return; ctx->user = srv_userid_incref(afid->user); } else { if (req->afid != LIB9P_FID_NOFID) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "FID provided as auth-file, but no auth-file is required"); + err = error_new(E_POSIX_EACCES, "FID provided as auth-file, but no auth-file is required"); goto tattach_return; } ctx->user = srv_userid_new(req->uname, req->unum); } /* 1. File object */ - lo_interface lib9p_srv_file root_file = srv->rootdir(ctx, req->aname); - assert(LO_IS_NULL(root_file) == lib9p_ctx_has_error(&ctx->basectx)); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_srv_file_or_error root_file_r = srv->rootdir(ctx, req->aname); + if (root_file_r.is_err) { + err = root_file_r.err; goto tattach_return; + } + lo_interface lib9p_srv_file root_file = root_file_r.lib9p_srv_file; struct lib9p_qid root_qid = LO_CALL(root_file, qid); assert(srv_qid_filetype(root_qid) == SRV_FILETYPE_DIR); @@ -882,7 +889,9 @@ static void handle_Tattach(struct srv_req *ctx, struct srv_pathinfo *root_pathinfo = srv_path_save(ctx, root_file, root_qid.path); /* 3. fidinfo */ - if (!srv_fid_store(ctx, req->fid, root_pathinfo, false)) { + srv_fidinfop_or_error fidinfo = srv_fid_store(ctx, req->fid, root_pathinfo, false); + if (fidinfo.is_err) { + err = fidinfo.err; srv_path_decref(ctx, root_qid.path); goto tattach_return; } @@ -891,7 +900,7 @@ static void handle_Tattach(struct srv_req *ctx, tattach_return: if (ctx->user) ctx->user = srv_userid_decref(ctx->user); - srv_respond(ctx, attach, &resp); + srv_respond(ctx, attach, &resp, err); } static void handle_Tflush(struct srv_req *ctx, @@ -906,15 +915,17 @@ static void handle_Tflush(struct srv_req *ctx, CR_SELECT_SEND(&ctx->flush_ch, &res))) { case 0: /* original request returned */ req_debug("original request (tag=", req->oldtag, ") returned"); - ctx->flush_acknowledged = (res == _LIB9P_SRV_FLUSH_SILENT); + if (res == _LIB9P_SRV_FLUSH_SILENT) { + ctx->responded = true; + return; + } break; case 1: /* flush itself got flushed */ - req_debug("flush itself flushed"); - ctx->flush_acknowledged = true; - break; + ctx->responded = true; + return; } } - srv_respond(ctx, flush, &resp); + srv_respond(ctx, flush, &resp, err); } static void handle_Twalk(struct srv_req *ctx, @@ -922,20 +933,17 @@ static void handle_Twalk(struct srv_req *ctx, srv_handler_common(ctx, walk, req); if (req->newfid == LIB9P_FID_NOFID) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "cannot assign to NOFID"); + err = error_new(E_POSIX_EBADF, "cannot assign to NOFID"); goto twalk_return; } struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "bad file number ", req->fid); + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); goto twalk_return; } if (fidinfo->flags & FIDFLAG_OPEN) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EALREADY, "cannot walk on FID open for I/O"); + err = error_new(E_POSIX_EALREADY, "cannot walk on FID open for I/O"); goto twalk_return; } ctx->user = srv_userid_incref(fidinfo->user); @@ -948,8 +956,7 @@ static void handle_Twalk(struct srv_req *ctx, resp.wqid = _resp_qid; for (resp.nwqid = 0; resp.nwqid < req->nwname; resp.nwqid++) { if (pathinfo->type != SRV_FILETYPE_DIR) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_ENOTDIR, "not a directory"); + err = error_new(E_POSIX_ENOTDIR, "not a directory"); break; } @@ -959,22 +966,24 @@ static void handle_Twalk(struct srv_req *ctx, assert(new_pathinfo); new_pathinfo->gc_refcount++; } else { - lo_interface lib9p_srv_file member_file = LO_CALL(pathinfo->file, dwalk, ctx, req->wname[resp.nwqid]); - assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(&ctx->basectx)); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_srv_file_or_error member_file = LO_CALL(pathinfo->file, dwalk, ctx, req->wname[resp.nwqid]); + if (member_file.is_err) { + err = member_file.err; break; - new_pathinfo = srv_path_save(ctx, member_file, LO_CALL(pathinfo->file, qid).path); + } + new_pathinfo = srv_path_save(ctx, member_file.lib9p_srv_file, LO_CALL(pathinfo->file, qid).path); assert(new_pathinfo); } if (new_pathinfo->type == SRV_FILETYPE_DIR) { - struct lib9p_srv_stat stat = LO_CALL(new_pathinfo->file, stat, ctx); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_srv_stat_or_error stat = LO_CALL(new_pathinfo->file, stat, ctx); + if (stat.is_err) { + err = stat.err; break; - lib9p_srv_stat_assert(stat); - if (!srv_check_perm(ctx, &stat, 0b001)) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "you do not have execute permission on that directory"); + } + lib9p_srv_stat_assert(stat.lib9p_srv_stat); + if (!srv_check_perm(ctx, &stat.lib9p_srv_stat, 0b001)) { + err = error_new(E_POSIX_EACCES, "you do not have execute permission on that directory"); srv_path_decref(ctx, LO_CALL(new_pathinfo->file, qid).path); break; } @@ -986,18 +995,21 @@ static void handle_Twalk(struct srv_req *ctx, pathinfo = new_pathinfo; } if (resp.nwqid == req->nwname) { - if (!srv_fid_store(ctx, req->newfid, pathinfo, req->newfid == req->fid)) + srv_fidinfop_or_error fidinfo = srv_fid_store(ctx, req->newfid, pathinfo, req->newfid == req->fid); + if (fidinfo.is_err) { + err = fidinfo.err; srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); + } } else { - assert(lib9p_ctx_has_error(&ctx->basectx)); + assert(!ERROR_IS_NULL(err)); srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); if (resp.nwqid > 0) - lib9p_ctx_clear_error(&ctx->basectx); + error_cleanup(&err); } twalk_return: if (ctx->user) ctx->user = srv_userid_decref(ctx->user); - srv_respond(ctx, walk, &resp); + srv_respond(ctx, walk, &resp, err); } static void handle_Topen(struct srv_req *ctx, @@ -1007,21 +1019,18 @@ static void handle_Topen(struct srv_req *ctx, /* Check that the FID is valid for this. */ struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "bad file number ", req->fid); + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); goto topen_return; } if (fidinfo->flags & FIDFLAG_OPEN) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EALREADY, "FID is already open"); + err = error_new(E_POSIX_EALREADY, "FID is already open"); goto topen_return; } if (fidinfo->type == SRV_FILETYPE_DIR) { if ( ((req->mode & LIB9P_O_MODE_MASK) != LIB9P_O_MODE_READ) || (req->mode & LIB9P_O_TRUNC) || (req->mode & LIB9P_O_RCLOSE) ) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EISDIR, "directories cannot be written, executed, truncated, or removed-on-close"); + err = error_new(E_POSIX_EISDIR, "directories cannot be written, executed, truncated, or removed-on-close"); goto topen_return; } } @@ -1037,27 +1046,29 @@ static void handle_Topen(struct srv_req *ctx, if (reqmode & LIB9P_O_RCLOSE) { struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(parent); - struct lib9p_srv_stat parent_stat = LO_CALL(parent->file, stat, ctx); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_srv_stat_or_error parent_stat = LO_CALL(parent->file, stat, ctx); + if (parent_stat.is_err) { + err = parent_stat.err; goto topen_return; - lib9p_srv_stat_assert(parent_stat); - if (!srv_check_perm(ctx, &parent_stat, 0b010)) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "permission denied to remove-on-close"); + } + lib9p_srv_stat_assert(parent_stat.lib9p_srv_stat); + if (!srv_check_perm(ctx, &parent_stat.lib9p_srv_stat, 0b010)) { + err = error_new(E_POSIX_EACCES, "permission denied to remove-on-close"); goto topen_return; } fidflags |= FIDFLAG_RCLOSE; } - struct lib9p_srv_stat stat = LO_CALL(pathinfo->file, stat, ctx); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_srv_stat_or_error stat = LO_CALL(pathinfo->file, stat, ctx); + if (stat.is_err) { + err = stat.err; goto topen_return; - lib9p_srv_stat_assert(stat); - if ((stat.mode & LIB9P_DM_EXCL) && pathinfo->io_refcount) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EEXIST, "exclusive file is already opened"); + } + lib9p_srv_stat_assert(stat.lib9p_srv_stat); + if ((stat.lib9p_srv_stat.mode & LIB9P_DM_EXCL) && pathinfo->io_refcount) { + err = error_new(E_POSIX_EEXIST, "exclusive file is already opened"); goto topen_return; } - if (stat.mode & LIB9P_DM_APPEND) { + if (stat.lib9p_srv_stat.mode & LIB9P_DM_APPEND) { fidflags |= FIDFLAG_APPEND; reqmode = reqmode & ~LIB9P_O_TRUNC; } @@ -1081,9 +1092,8 @@ static void handle_Topen(struct srv_req *ctx, rd = true; break; } - if (!srv_check_perm(ctx, &stat, perm_bits)) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "permission denied"); + if (!srv_check_perm(ctx, &stat.lib9p_srv_stat, perm_bits)) { + err = error_new(E_POSIX_EACCES, "permission denied"); goto topen_return; } @@ -1092,22 +1102,28 @@ static void handle_Topen(struct srv_req *ctx, struct lib9p_qid qid; switch (pathinfo->type) { case SRV_FILETYPE_DIR: - fidinfo->dir.io = LO_CALL(pathinfo->file, dopen, ctx); - assert(LO_IS_NULL(fidinfo->dir.io) == lib9p_ctx_has_error(&ctx->basectx)); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_srv_dio_or_error dio_r = + LO_CALL(pathinfo->file, dopen, ctx); + if (dio_r.is_err) { + err = dio_r.err; goto topen_return; + } + fidinfo->dir.io = dio_r.lib9p_srv_dio; fidinfo->dir.idx = 0; fidinfo->dir.off = 0; qid = LO_CALL(fidinfo->dir.io, qid); iounit = 0; break; case SRV_FILETYPE_FILE: - fidinfo->file.io = LO_CALL(pathinfo->file, fopen, ctx, - rd, wr, - reqmode & LIB9P_O_TRUNC); - assert(LO_IS_NULL(fidinfo->file.io) == lib9p_ctx_has_error(&ctx->basectx)); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_srv_fio_or_error fio_r = + LO_CALL(pathinfo->file, fopen, ctx, + rd, wr, + reqmode & LIB9P_O_TRUNC); + if (fio_r.is_err) { + err = fio_r.err; goto topen_return; + } + fidinfo->file.io = fio_r.lib9p_srv_fio; qid = LO_CALL(fidinfo->file.io, qid); iounit = LO_CALL(fidinfo->file.io, iounit); break; @@ -1131,17 +1147,16 @@ static void handle_Topen(struct srv_req *ctx, topen_return: if (ctx->user) ctx->user = srv_userid_decref(ctx->user); - srv_respond(ctx, open, &resp); + srv_respond(ctx, open, &resp, err); } static void handle_Tcreate(struct srv_req *ctx, struct lib9p_msg_Tcreate *req) { srv_handler_common(ctx, create, req); - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "create not (yet?) implemented"); + err = error_new(E_POSIX_EOPNOTSUPP, "create not (yet?) implemented"); - srv_respond(ctx, create, &resp); + srv_respond(ctx, create, &resp, err); } static inline struct lib9p_stat srv_stat_to_net_stat(struct lib9p_srv_stat in) { @@ -1177,13 +1192,11 @@ static void handle_Tread(struct srv_req *ctx, /* Check that the FID is valid for this. */ struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "bad file number ", req->fid); + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); goto tread_return; } if (!(fidinfo->flags & FIDFLAG_OPEN_R)) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "FID not open for reading"); + err = error_new(E_POSIX_EINVAL, "FID not open for reading"); goto tread_return; } @@ -1198,8 +1211,7 @@ static void handle_Tread(struct srv_req *ctx, fidinfo->dir.off = 0; fidinfo->dir.buffered_dirent = (struct lib9p_srv_dirent){}; } else if (req->offset != fidinfo->dir.off) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "invalid offset (must be 0 or ", fidinfo->dir.off, "): ", req->offset); + err = error_new(E_POSIX_EINVAL, "invalid offset (must be 0 or ", fidinfo->dir.off, "): ", req->offset); goto tread_return; } /* Read. */ @@ -1212,35 +1224,53 @@ static void handle_Tread(struct srv_req *ctx, if (fidinfo->dir.buffered_dirent.name.len) { member_dirent = fidinfo->dir.buffered_dirent; } else { - member_dirent = LO_CALL(fidinfo->dir.io, dread, ctx, fidinfo->dir.idx); - if (lib9p_ctx_has_error(&ctx->basectx)) { - if (!resp.count) + lib9p_srv_dirent_or_error member_dirent_r; + member_dirent_r = LO_CALL(fidinfo->dir.io, dread, ctx, fidinfo->dir.idx); + if (member_dirent_r.is_err) { + if (!resp.count) { + err = member_dirent_r.err; goto tread_return; - lib9p_ctx_clear_error(&ctx->basectx); + } + error_cleanup(&member_dirent_r.err); break; } + member_dirent = member_dirent_r.lib9p_srv_dirent; } if (!member_dirent.name.len) break; struct lib9p_srv_stat member_stat; struct srv_pathinfo *member_pathinfo = map_load(&ctx->parent_sess->paths, member_dirent.qid.path); if (member_pathinfo) { - member_stat = LO_CALL(member_pathinfo->file, stat, ctx); + lib9p_srv_stat_or_error r = LO_CALL(member_pathinfo->file, stat, ctx); + if (r.is_err) { + err = r.err; + goto member_err; + } + member_stat = r.lib9p_srv_stat; } else { if (!dir_pathinfo) dir_pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(dir_pathinfo); - member_file = LO_CALL(dir_pathinfo->file, dwalk, ctx, member_dirent.name); - assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(&ctx->basectx)); - if (!lib9p_ctx_has_error(&ctx->basectx)) - member_stat = LO_CALL(member_file, stat, ctx); + lib9p_srv_file_or_error file_r = LO_CALL(dir_pathinfo->file, dwalk, ctx, member_dirent.name); + if (file_r.is_err) { + err = file_r.err; + goto member_err; + } + member_file = file_r.lib9p_srv_file; + lib9p_srv_stat_or_error stat_r = LO_CALL(member_file, stat, ctx); + if (stat_r.is_err) { + err = stat_r.err; + goto member_err; + } + member_stat = stat_r.lib9p_srv_stat; } - if (lib9p_ctx_has_error(&ctx->basectx)) { + if (false) { + member_err: if (!LO_IS_NULL(member_file)) LO_CALL(member_file, free); if (!resp.count) goto tread_return; - lib9p_ctx_clear_error(&ctx->basectx); + error_cleanup(&err); break; } lib9p_srv_stat_assert(member_stat); @@ -1251,8 +1281,7 @@ static void handle_Tread(struct srv_req *ctx, LO_CALL(member_file, free); if (!nbytes) { if (!resp.count) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_ERANGE, "stat object does not fit into negotiated max message size"); + err = error_new(E_POSIX_ERANGE, "stat object does not fit into negotiated max message size"); goto tread_return; } fidinfo->dir.buffered_dirent = member_dirent; @@ -1268,11 +1297,12 @@ static void handle_Tread(struct srv_req *ctx, #endif break; case SRV_FILETYPE_FILE: - struct iovec iov; - LO_CALL(fidinfo->file.io, pread, ctx, req->count, req->offset, &iov); - if (!lib9p_ctx_has_error(&ctx->basectx) && !ctx->flush_acknowledged) { - resp.count = iov.iov_len; - resp.data = iov.iov_base; + iovec_or_error iov = LO_CALL(fidinfo->file.io, pread, ctx, req->count, req->offset); + if (iov.is_err) { + err = iov.err; + } else { + resp.count = iov.iovec.iov_len; + resp.data = iov.iovec.iov_base; if (resp.count > req->count) resp.count = req->count; } @@ -1284,7 +1314,7 @@ static void handle_Tread(struct srv_req *ctx, tread_return: if (ctx->user) ctx->user = srv_userid_decref(ctx->user); - srv_respond(ctx, read, &resp); + srv_respond(ctx, read, &resp, err); if (heap) free(heap); } @@ -1298,13 +1328,11 @@ static void handle_Twrite(struct srv_req *ctx, /* Check that the FID is valid for this. */ struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "bad file number ", req->fid); + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); goto twrite_return; } if (!(fidinfo->flags & FIDFLAG_OPEN_W)) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "FID not open for writing"); + err = error_new(E_POSIX_EINVAL, "FID not open for writing"); goto twrite_return; } if (fidinfo->flags & FIDFLAG_APPEND) @@ -1312,11 +1340,15 @@ static void handle_Twrite(struct srv_req *ctx, /* Do it. */ ctx->user = srv_userid_incref(fidinfo->user); - resp.count = LO_CALL(fidinfo->file.io, pwrite, ctx, req->data, req->count, req->offset); + uint32_t_or_error count = LO_CALL(fidinfo->file.io, pwrite, ctx, req->data, req->count, req->offset); + if (count.is_err) + err = count.err; + else + resp.count = count.uint32_t; twrite_return: if (ctx->user) ctx->user = srv_userid_decref(ctx->user); - srv_respond(ctx, write, &resp); + srv_respond(ctx, write, &resp, err); } static void handle_Tclunk(struct srv_req *ctx, @@ -1325,15 +1357,14 @@ static void handle_Tclunk(struct srv_req *ctx, struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "bad file number ", req->fid); + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); goto tclunk_return; } srv_fid_del(ctx, req->fid, fidinfo, false); tclunk_return: - srv_respond(ctx, clunk, &resp); + srv_respond(ctx, clunk, &resp, err); } static void handle_Tremove(struct srv_req *ctx, @@ -1342,8 +1373,7 @@ static void handle_Tremove(struct srv_req *ctx, struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "bad file number ", req->fid); + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); goto tremove_return; } @@ -1351,17 +1381,20 @@ static void handle_Tremove(struct srv_req *ctx, struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); if (pathinfo->parent_dir == fidinfo->path) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBUSY, "cannot remove root"); + err = error_new(E_POSIX_EBUSY, "cannot remove root"); remove = false; goto tremove_main; } struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(parent); - struct lib9p_srv_stat parent_stat = LO_CALL(parent->file, stat, ctx); - if (!lib9p_ctx_has_error(&ctx->basectx) && !srv_check_perm(ctx, &parent_stat, 0b010)) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "you do not have write permission on the parent directory"); + lib9p_srv_stat_or_error r = LO_CALL(parent->file, stat, ctx); + if (r.is_err) { + err = r.err; + goto tremove_main; + } + struct lib9p_srv_stat parent_stat = r.lib9p_srv_stat; + if (!srv_check_perm(ctx, &parent_stat, 0b010)) { + err = error_new(E_POSIX_EACCES, "you do not have write permission on the parent directory"); remove = false; goto tremove_main; } @@ -1369,7 +1402,7 @@ static void handle_Tremove(struct srv_req *ctx, tremove_main: srv_fid_del(ctx, req->fid, fidinfo, remove); tremove_return: - srv_respond(ctx, remove, &resp); + srv_respond(ctx, remove, &resp, err); } static void handle_Tstat(struct srv_req *ctx, @@ -1378,33 +1411,33 @@ static void handle_Tstat(struct srv_req *ctx, struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "bad file number ", req->fid); + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); goto tstat_return; } struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); ctx->user = srv_userid_incref(fidinfo->user); - struct lib9p_srv_stat stat = LO_CALL(pathinfo->file, stat, ctx); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_srv_stat_or_error r = LO_CALL(pathinfo->file, stat, ctx); + if (r.is_err) { + err = r.err; goto tstat_return; - lib9p_srv_stat_assert(stat); - resp.stat = srv_stat_to_net_stat(stat); + } + lib9p_srv_stat_assert(r.lib9p_srv_stat); + resp.stat = srv_stat_to_net_stat(r.lib9p_srv_stat); tstat_return: if (ctx->user) ctx->user = srv_userid_decref(ctx->user); - srv_respond(ctx, stat, &resp); + srv_respond(ctx, stat, &resp, err); } static void handle_Twstat(struct srv_req *ctx, struct lib9p_msg_Twstat *req) { srv_handler_common(ctx, wstat, req); - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "wstat not (yet?) implemented"); + err = error_new(E_POSIX_EOPNOTSUPP, "wstat not (yet?) implemented"); - srv_respond(ctx, wstat, &resp); + srv_respond(ctx, wstat, &resp, err); } #endif @@ -1413,10 +1446,9 @@ static void handle_Topenfd(struct srv_req *ctx, struct lib9p_msg_Topenfd *req) { srv_handler_common(ctx, openfd, req); - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "openfd not (yet?) implemented"); + err = error_new(E_POSIX_EOPNOTSUPP, "openfd not (yet?) implemented"); - srv_respond(ctx, openfd, &resp); + srv_respond(ctx, openfd, &resp, err); } #endif @@ -1425,29 +1457,26 @@ static void handle_Tsession(struct srv_req *ctx, struct lib9p_msg_Tsession *req) { srv_handler_common(ctx, session, req); - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "session not (yet?) implemented"); + err = error_new(E_POSIX_EOPNOTSUPP, "session not (yet?) implemented"); - srv_respond(ctx, session, &resp); + srv_respond(ctx, session, &resp, err); } static void handle_Tsread(struct srv_req *ctx, struct lib9p_msg_Tsread *req) { srv_handler_common(ctx, sread, req); - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "sread not (yet?) implemented"); + err = error_new(E_POSIX_EOPNOTSUPP, "sread not (yet?) implemented"); - srv_respond(ctx, sread, &resp); + srv_respond(ctx, sread, &resp, err); } static void handle_Tswrite(struct srv_req *ctx, struct lib9p_msg_Tswrite *req) { srv_handler_common(ctx, swrite, req); - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "swrite not (yet?) implemented"); + err = error_new(E_POSIX_EOPNOTSUPP, "swrite not (yet?) implemented"); - srv_respond(ctx, swrite, &resp); + srv_respond(ctx, swrite, &resp, err); } #endif diff --git a/lib9p/srv_errno.h b/lib9p/srv_errno.h new file mode 100644 index 0000000..1384f97 --- /dev/null +++ b/lib9p/srv_errno.h @@ -0,0 +1,14 @@ +/* lib9p/srv_errno.h - TODO + * + * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_SRV_ERRNO_H_ +#define _LIB9P_SRV_ERRNO_H_ + +#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L +lib9p_errno_t libmisc_to_linuxgeneric_errno(_errnum); +#endif + +#endif /* _LIB9P_SRV_ERRNO_H_ */ diff --git a/lib9p/srv_generated.c b/lib9p/srv_generated.c new file mode 100644 index 0000000..26989c5 --- /dev/null +++ b/lib9p/srv_generated.c @@ -0,0 +1,91 @@ +/* lib9p/srv_generated.c - Generated by lib9p/srv_generated.c.gen. DO NOT EDIT! */ + +#include <libmisc/error.h> +#include <lib9p/core.h> +#include "srv_errno.h" + +#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L +lib9p_errno_t libmisc_to_linuxgeneric_errno(_errnum errnum) { + LM_PARTIAL_SWITCH (errnum) { + case E_POSIX_E2BIG: return LIB9P_ERRNO_L_E2BIG; + case E_POSIX_EACCES: return LIB9P_ERRNO_L_EACCES; + case E_POSIX_EADDRINUSE: return LIB9P_ERRNO_L_EADDRINUSE; + case E_POSIX_EADDRNOTAVAIL: return LIB9P_ERRNO_L_EADDRNOTAVAIL; + case E_POSIX_EAFNOSUPPORT: return LIB9P_ERRNO_L_EAFNOSUPPORT; + case E_POSIX_EAGAIN: return LIB9P_ERRNO_L_EAGAIN; + case E_POSIX_EALREADY: return LIB9P_ERRNO_L_EALREADY; + case E_POSIX_EBADF: return LIB9P_ERRNO_L_EBADF; + case E_POSIX_EBADMSG: return LIB9P_ERRNO_L_EBADMSG; + case E_POSIX_EBUSY: return LIB9P_ERRNO_L_EBUSY; + case E_POSIX_ECANCELED: return LIB9P_ERRNO_L_ECANCELED; + case E_POSIX_ECHILD: return LIB9P_ERRNO_L_ECHILD; + case E_POSIX_ECONNABORTED: return LIB9P_ERRNO_L_ECONNABORTED; + case E_POSIX_ECONNREFUSED: return LIB9P_ERRNO_L_ECONNREFUSED; + case E_POSIX_ECONNRESET: return LIB9P_ERRNO_L_ECONNRESET; + case E_POSIX_EDEADLK: return LIB9P_ERRNO_L_EDEADLK; + case E_POSIX_EDESTADDRREQ: return LIB9P_ERRNO_L_EDESTADDRREQ; + case E_POSIX_EDOM: return LIB9P_ERRNO_L_EDOM; + case E_POSIX_EDQUOT: return LIB9P_ERRNO_L_EDQUOT; + case E_POSIX_EEXIST: return LIB9P_ERRNO_L_EEXIST; + case E_POSIX_EFAULT: return LIB9P_ERRNO_L_EFAULT; + case E_POSIX_EFBIG: return LIB9P_ERRNO_L_EFBIG; + case E_POSIX_EHOSTUNREACH: return LIB9P_ERRNO_L_EHOSTUNREACH; + case E_POSIX_EIDRM: return LIB9P_ERRNO_L_EIDRM; + case E_POSIX_EILSEQ: return LIB9P_ERRNO_L_EILSEQ; + case E_POSIX_EINPROGRESS: return LIB9P_ERRNO_L_EINPROGRESS; + case E_POSIX_EINTR: return LIB9P_ERRNO_L_EINTR; + case E_POSIX_EINVAL: return LIB9P_ERRNO_L_EINVAL; + case E_POSIX_EIO: return LIB9P_ERRNO_L_EIO; + case E_POSIX_EISCONN: return LIB9P_ERRNO_L_EISCONN; + case E_POSIX_EISDIR: return LIB9P_ERRNO_L_EISDIR; + case E_POSIX_ELOOP: return LIB9P_ERRNO_L_ELOOP; + case E_POSIX_EMFILE: return LIB9P_ERRNO_L_EMFILE; + case E_POSIX_EMLINK: return LIB9P_ERRNO_L_EMLINK; + case E_POSIX_EMSGSIZE: return LIB9P_ERRNO_L_EMSGSIZE; + case E_POSIX_EMULTIHOP: return LIB9P_ERRNO_L_EMULTIHOP; + case E_POSIX_ENAMETOOLONG: return LIB9P_ERRNO_L_ENAMETOOLONG; + case E_POSIX_ENETDOWN: return LIB9P_ERRNO_L_ENETDOWN; + case E_POSIX_ENETRESET: return LIB9P_ERRNO_L_ENETRESET; + case E_POSIX_ENETUNREACH: return LIB9P_ERRNO_L_ENETUNREACH; + case E_POSIX_ENFILE: return LIB9P_ERRNO_L_ENFILE; + case E_POSIX_ENOBUFS: return LIB9P_ERRNO_L_ENOBUFS; + case E_POSIX_ENODEV: return LIB9P_ERRNO_L_ENODEV; + case E_POSIX_ENOENT: return LIB9P_ERRNO_L_ENOENT; + case E_POSIX_ENOEXEC: return LIB9P_ERRNO_L_ENOEXEC; + case E_POSIX_ENOLCK: return LIB9P_ERRNO_L_ENOLCK; + case E_POSIX_ENOLINK: return LIB9P_ERRNO_L_ENOLINK; + case E_POSIX_ENOMEM: return LIB9P_ERRNO_L_ENOMEM; + case E_POSIX_ENOMSG: return LIB9P_ERRNO_L_ENOMSG; + case E_POSIX_ENOPROTOOPT: return LIB9P_ERRNO_L_ENOPROTOOPT; + case E_POSIX_ENOSPC: return LIB9P_ERRNO_L_ENOSPC; + case E_POSIX_ENOSYS: return LIB9P_ERRNO_L_ENOSYS; + case E_POSIX_ENOTCONN: return LIB9P_ERRNO_L_ENOTCONN; + case E_POSIX_ENOTDIR: return LIB9P_ERRNO_L_ENOTDIR; + case E_POSIX_ENOTEMPTY: return LIB9P_ERRNO_L_ENOTEMPTY; + case E_POSIX_ENOTRECOVERABLE: return LIB9P_ERRNO_L_ENOTRECOVERABLE; + case E_POSIX_ENOTSOCK: return LIB9P_ERRNO_L_ENOTSOCK; + case E_POSIX_ENOTTY: return LIB9P_ERRNO_L_ENOTTY; + case E_POSIX_ENXIO: return LIB9P_ERRNO_L_ENXIO; + case E_POSIX_EOPNOTSUPP: return LIB9P_ERRNO_L_EOPNOTSUPP; + case E_POSIX_EOVERFLOW: return LIB9P_ERRNO_L_EOVERFLOW; + case E_POSIX_EOWNERDEAD: return LIB9P_ERRNO_L_EOWNERDEAD; + case E_POSIX_EPERM: return LIB9P_ERRNO_L_EPERM; + case E_POSIX_EPIPE: return LIB9P_ERRNO_L_EPIPE; + case E_POSIX_EPROTO: return LIB9P_ERRNO_L_EPROTO; + case E_POSIX_EPROTONOSUPPORT: return LIB9P_ERRNO_L_EPROTONOSUPPORT; + case E_POSIX_EPROTOTYPE: return LIB9P_ERRNO_L_EPROTOTYPE; + case E_POSIX_ERANGE: return LIB9P_ERRNO_L_ERANGE; + case E_POSIX_EROFS: return LIB9P_ERRNO_L_EROFS; + case E_POSIX_ESOCKTNOSUPPORT: return LIB9P_ERRNO_L_ESOCKTNOSUPPORT; + case E_POSIX_ESPIPE: return LIB9P_ERRNO_L_ESPIPE; + case E_POSIX_ESRCH: return LIB9P_ERRNO_L_ESRCH; + case E_POSIX_ESTALE: return LIB9P_ERRNO_L_ESTALE; + case E_POSIX_ETIMEDOUT: return LIB9P_ERRNO_L_ETIMEDOUT; + case E_POSIX_ETXTBSY: return LIB9P_ERRNO_L_ETXTBSY; + case E_POSIX_EXDEV: return LIB9P_ERRNO_L_EXDEV; + case E_POSIX_ENOTSUP: return LIB9P_ERRNO_L_EOPNOTSUPP; + case E_POSIX_EWOULDBLOCK: return LIB9P_ERRNO_L_EAGAIN; + default: return LIB9P_ERRNO_L_EIO; + } +} +#endif diff --git a/lib9p/srv_generated.c.gen b/lib9p/srv_generated.c.gen new file mode 100755 index 0000000..6a6335a --- /dev/null +++ b/lib9p/srv_generated.c.gen @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# lib9p/srv_generated.c.gen - Generate errno translation tables +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +error_h=$1 +outfile=$2 + +{ + echo "/* ${outfile} - Generated by $0. DO NOT EDIT! */" + echo + echo '#include <libmisc/error.h>' + echo '#include <lib9p/core.h>' + echo '#include "srv_errno.h"' + echo + echo '#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L' + echo 'lib9p_errno_t libmisc_to_linuxgeneric_errno(_errnum errnum) {' + echo $'\tLM_PARTIAL_SWITCH (errnum) {' + sed -nE \ + -e 's@^(#define)?\s+(E_POSIX_([_A-Z0-9]+))[ ,][^/]*/\* ([^*(]+) (\*/|\().*@'$'\tcase \\2: return LIB9P_ERRNO_L_\\3;''@p' \ + -- "$error_h" | + grep -v -e '_ENOTSUP' -e '_EWOULDBLOCK' + echo $'\tcase E_POSIX_ENOTSUP: return LIB9P_ERRNO_L_EOPNOTSUPP;' + echo $'\tcase E_POSIX_EWOULDBLOCK: return LIB9P_ERRNO_L_EAGAIN;' + echo $'\tdefault: return LIB9P_ERRNO_L_EIO;' + echo $'\t}' + echo '}' + echo '#endif' +} >"$outfile" diff --git a/lib9p/srv_include/lib9p/srv.h b/lib9p/srv_include/lib9p/srv.h index 89dc986..ce82e59 100644 --- a/lib9p/srv_include/lib9p/srv.h +++ b/lib9p/srv_include/lib9p/srv.h @@ -17,6 +17,11 @@ #include <lib9p/core.h> +#ifndef CONFIG_9P_SRV_MAX_ERR_SIZE + #error config.h must define CONFIG_9P_SRV_MAX_ERR_SIZE +#endif +static_assert(CONFIG_9P_SRV_MAX_ERR_SIZE <= UINT16_MAX); + /* context ********************************************************************/ struct lib9p_srv_userid { @@ -45,8 +50,7 @@ struct lib9p_srv_ctx { struct _lib9p_srv_sess *parent_sess; lib9p_tag_t tag; uint8_t *net_bytes; - _lib9p_srv_flush_ch_t flush_ch; - bool flush_acknowledged; + _lib9p_srv_flush_ch_t flush_ch; /* flushers for this req _read_ from here */ bool responded; END_PRIVATE(LIB9P_SRV_H); }; @@ -55,20 +59,13 @@ struct lib9p_srv_ctx { * Return whether there is an outstanding Tflush or Tversion * cancellation of this request. After becoming true, this may go * back to false if the Tflush itself is flushed. + * + * As a special case, returning E_POSIX_ECANCELED indicates that the + * flush has been observed, and a Rerror should not be sent ot the + * client. */ bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx); -/** - * Acknowledge that the handler is responding to an outstanding flush; - * a non-Rerror R-message will be elided in favor of Rflush/Rversion. - * lib9p_srv_flush_requested() must be true; so do not cr_yield() - * between checking lib9p_srv_flush_requested() and calling - * lib9p_srv_acknowledge_flush(). These are separate calls to - * facilitate cases where a flush merely truncates a call, instead of - * totally canceling it. - */ -void lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx); - /* version-independent stat ***************************************************/ struct lib9p_srv_stat { @@ -95,18 +92,22 @@ struct lib9p_srv_stat { struct lib9p_s extension; #endif }; +typedef struct lib9p_srv_stat lib9p_srv_stat; +DECLARE_ERROR_OR(lib9p_srv_stat); void lib9p_srv_stat_assert(struct lib9p_srv_stat stat); /* interface definitions ******************************************************/ +typedef struct iovec iovec; +DECLARE_ERROR_OR(iovec); + struct lib9p_srv_dirent { struct lib9p_qid qid; struct lib9p_s name; }; - -lo_interface lib9p_srv_fio; -lo_interface lib9p_srv_dio; +typedef struct lib9p_srv_dirent lib9p_srv_dirent; +DECLARE_ERROR_OR(lib9p_srv_dirent); /* FIXME: I don't like that the pointer returned by pread() has to * remain live after it returns. Perhaps a `respond()`-callback? But @@ -114,6 +115,46 @@ lo_interface lib9p_srv_dio; * * FIXME: It would be nice if pread() could return more than 1 iovec. */ +#define lib9p_srv_fio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ + LO_FUNC(struct lib9p_qid , qid ) \ + LO_FUNC(void , iofree ) \ + LO_FUNC(uint32_t , iounit ) \ + LO_FUNC(iovec_or_error , pread , struct lib9p_srv_ctx *, \ + uint32_t byte_count, \ + uint64_t byte_offset) \ + /** \ + * If the file was append-only when fopen()ed, then byte_offset will \ + * always be 0. \ + */ \ + LO_FUNC(uint32_t_or_error , pwrite , struct lib9p_srv_ctx *, \ + void *buf, \ + uint32_t byte_count, \ + uint64_t byte_offset) +LO_INTERFACE(lib9p_srv_fio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +typedef lo_interface lib9p_srv_fio lib9p_srv_fio; +DECLARE_ERROR_OR(lib9p_srv_fio); + +#define lib9p_srv_dio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ + LO_FUNC(struct lib9p_qid , qid ) \ + LO_FUNC(void , iofree ) \ + /** \ + * Return the idx-th dirent. idx will always be either 0 or \ + * prev_idx+1. A dirent with an empty name signals EOF. The string \ + * must remain valid until the next dread() call or iofree(). \ + */ \ + LO_FUNC(lib9p_srv_dirent_or_error , dread , struct lib9p_srv_ctx *, \ + size_t idx) +LO_INTERFACE(lib9p_srv_dio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +typedef lo_interface lib9p_srv_dio lib9p_srv_dio; +DECLARE_ERROR_OR(lib9p_srv_dio); + +struct _lo_lib9p_srv_file_vtable; +lo_interface lib9p_srv_file { + void *self; + const struct _lo_lib9p_srv_file_vtable *vtable; +}; +typedef lo_interface lib9p_srv_file lib9p_srv_file; +DECLARE_ERROR_OR(lib9p_srv_file); #define lib9p_srv_file_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ /* resource management **********************************************/ \ \ @@ -139,16 +180,16 @@ lo_interface lib9p_srv_dio; /* non-"opened" generic I/O *****************************************/ \ \ /** Strings returned from stat() must remain valid until free(). */ \ - LO_FUNC(struct lib9p_srv_stat , stat , struct lib9p_srv_ctx *) \ - LO_FUNC(void , wstat , struct lib9p_srv_ctx *, \ + LO_FUNC(lib9p_srv_stat_or_error , stat , struct lib9p_srv_ctx *) \ + LO_FUNC(error , wstat , struct lib9p_srv_ctx *, \ struct lib9p_srv_stat) \ - LO_FUNC(void , remove , struct lib9p_srv_ctx *) \ + LO_FUNC(error , remove , struct lib9p_srv_ctx *) \ \ /* non-"opened" directory I/O ***************************************/ \ \ - LO_FUNC(lo_interface lib9p_srv_file, dwalk , struct lib9p_srv_ctx *, \ + LO_FUNC(lib9p_srv_file_or_error , dwalk , struct lib9p_srv_ctx *, \ struct lib9p_s childname) \ - LO_FUNC(lo_interface lib9p_srv_file, dcreate, struct lib9p_srv_ctx *, \ + LO_FUNC(lib9p_srv_file_or_error , dcreate, struct lib9p_srv_ctx *, \ struct lib9p_s childname, \ struct lib9p_srv_userid *user, \ struct lib9p_srv_userid *group, \ @@ -156,50 +197,22 @@ lo_interface lib9p_srv_dio; \ /* open() for I/O ***************************************************/ \ \ - LO_FUNC(lo_interface lib9p_srv_fio , fopen , struct lib9p_srv_ctx *, \ + LO_FUNC(lib9p_srv_fio_or_error , fopen , struct lib9p_srv_ctx *, \ bool rd, bool wr, \ bool trunc) \ - LO_FUNC(lo_interface lib9p_srv_dio , dopen , struct lib9p_srv_ctx *) + LO_FUNC(lib9p_srv_dio_or_error , dopen , struct lib9p_srv_ctx *) LO_INTERFACE(lib9p_srv_file); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ -#define lib9p_srv_fio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ - LO_FUNC(struct lib9p_qid , qid ) \ - LO_FUNC(void , iofree ) \ - LO_FUNC(uint32_t , iounit ) \ - LO_FUNC(void , pread , struct lib9p_srv_ctx *, \ - uint32_t byte_count, \ - uint64_t byte_offset, \ - struct iovec *ret) \ - /** \ - * If the file was append-only when fopen()ed, then byte_offset will \ - * always be 0. \ - */ \ - LO_FUNC(uint32_t , pwrite , struct lib9p_srv_ctx *, \ - void *buf, \ - uint32_t byte_count, \ - uint64_t byte_offset) -LO_INTERFACE(lib9p_srv_fio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - -#define lib9p_srv_dio_LO_IFACE /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ \ - LO_FUNC(struct lib9p_qid , qid ) \ - LO_FUNC(void , iofree ) \ - /** \ - * Return the idx-th dirent. idx will always be either 0 or \ - * prev_idx+1. A dirent with an empty name signals EOF. The string \ - * must remain valid until the next dread() call or iofree(). \ - */ \ - LO_FUNC(struct lib9p_srv_dirent , dread , struct lib9p_srv_ctx *, \ - size_t idx) -LO_INTERFACE(lib9p_srv_dio); /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ - #define LIB9P_SRV_NOTDIR(TYP, NAM) \ - static lo_interface lib9p_srv_file NAM##_dwalk (TYP *, struct lib9p_srv_ctx *, struct lib9p_s) { assert_notreached("not a directory"); } \ - static lo_interface lib9p_srv_file NAM##_dcreate(TYP *, struct lib9p_srv_ctx *, struct lib9p_s, \ - struct lib9p_srv_userid *, struct lib9p_srv_userid *, lib9p_dm_t) { assert_notreached("not a directory"); } \ - static lo_interface lib9p_srv_dio NAM##_dopen (TYP *, struct lib9p_srv_ctx *) { assert_notreached("not a directory"); } + static lib9p_srv_file_or_error NAM##_dwalk (TYP *, struct lib9p_srv_ctx *, struct lib9p_s) { assert_notreached("not a directory"); } \ + static lib9p_srv_file_or_error NAM##_dcreate(TYP *, struct lib9p_srv_ctx *, struct lib9p_s, \ + struct lib9p_srv_userid *, struct lib9p_srv_userid *, lib9p_dm_t) { assert_notreached("not a directory"); } \ + static lib9p_srv_dio_or_error NAM##_dopen (TYP *, struct lib9p_srv_ctx *) { assert_notreached("not a directory"); } \ + LM_FORCE_SEMICOLON #define LIB9P_SRV_NOTFILE(TYP, NAM) \ - static lo_interface lib9p_srv_fio NAM##_fopen (TYP *, struct lib9p_srv_ctx *, bool, bool, bool) { assert_notreached("not a file"); } + static lib9p_srv_fio_or_error NAM##_fopen (TYP *, struct lib9p_srv_ctx *, bool, bool, bool) { assert_notreached("not a file"); } \ + LM_FORCE_SEMICOLON /* main server entrypoints ****************************************************/ @@ -215,9 +228,9 @@ LO_INTERFACE(net_stream_conn_unix); struct lib9p_srv { /* Things you provide */ - void /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */ - lo_interface lib9p_srv_file (*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename); - void (*msglog )(struct lib9p_srv_ctx *, enum lib9p_msg_type, void *hostmsg); /* optional */ + error /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */ + lib9p_srv_file_or_error (*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename); + void (*msglog )(struct lib9p_srv_ctx *, enum lib9p_msg_type, void *hostmsg); /* optional */ #if CONFIG_9P_ENABLE_9P2000_p9p lo_interface net_stream_conn_unix (*type_assert_unix)(lo_interface net_stream_conn); /* optional */ #endif @@ -263,10 +276,10 @@ void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stre * * Errors that this function itself may send to clients: * - * @errno L_EMSGSIZE T-message has size[4] bigger than max_msg_size - * @errno L_EDOM Tversion specified an impossibly small max_msg_size - * @errno L_EOPNOTSUPP T-message has an R-message type, or an unrecognized T-message type - * @errno L_EBADMSG T-message has wrong size[4] for its content, or has invalid UTF-8 + * @errno E_POSIX_EMSGSIZE T-message has size[4] bigger than max_msg_size + * @errno E_POSIX_EDOM Tversion specified an impossibly small max_msg_size + * @errno E_POSIX_EOPNOTSUPP T-message has an R-message type, or an unrecognized T-message type + * @errno E_POSIX_EBADMSG T-message has wrong size[4] for its content, or has invalid UTF-8 */ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn conn); @@ -291,7 +304,7 @@ void lib9p_srv_worker_loop(struct lib9p_srv *srv); * * Errors that this function itself may send to clients: * - * @errno L_ERANGE R-message does not fit into max_msg_size + * @errno E_POSIX_ERANGE R-message does not fit into max_msg_size */ void lib9p_srv_worker(struct lib9p_srv_ctx *req); diff --git a/lib9p/tests/client_config/config.h b/lib9p/tests/client_config/config.h index bcf030d..4bba4ec 100644 --- a/lib9p/tests/client_config/config.h +++ b/lib9p/tests/client_config/config.h @@ -7,7 +7,6 @@ #ifndef _CONFIG_H_ #define _CONFIG_H_ -#define CONFIG_9P_MAX_ERR_SIZE 128 #define CONFIG_9P_MAX_9P2000_e_WELEM 16 #define CONFIG_9P_ENABLE_9P2000 1 /* bool */ diff --git a/lib9p/tests/test_compile_config/config.h b/lib9p/tests/test_compile_config/config.h index 02cb8e5..cb3709e 100644 --- a/lib9p/tests/test_compile_config/config.h +++ b/lib9p/tests/test_compile_config/config.h @@ -9,11 +9,11 @@ /* 9P *************************************************************************/ -#define CONFIG_9P_MAX_ERR_SIZE 128 #define CONFIG_9P_MAX_9P2000_e_WELEM 16 /* 9P_SRV *********************************************************************/ +#define CONFIG_9P_SRV_MAX_ERR_SIZE 128 #define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) #define CONFIG_9P_SRV_MAX_HOSTMSG_SIZE CONFIG_9P_SRV_MAX_MSG_SIZE+16 diff --git a/lib9p/tests/test_server/config/config.h b/lib9p/tests/test_server/config/config.h index f49894b..a657f60 100644 --- a/lib9p/tests/test_server/config/config.h +++ b/lib9p/tests/test_server/config/config.h @@ -12,8 +12,6 @@ /* 9P *************************************************************************/ -#define CONFIG_9P_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ - #define CONFIG_9P_ENABLE_9P2000 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_u 1 /* bool */ #define CONFIG_9P_ENABLE_9P2000_e 0 /* bool */ @@ -42,6 +40,7 @@ * (8*1024)+160 in 2e and 3e. */ #define CONFIG_9P_SRV_MAX_MSG_SIZE ((4*1024)+24) +#define CONFIG_9P_SRV_MAX_ERR_SIZE 128 /* 128 is what Plan 9 4e uses */ /** * Maximum host-data-structure size. A message may be larger in * unmarshaled-host-structures than marshaled-net-bytes due to (1) diff --git a/lib9p/tests/test_server/fs_flush.c b/lib9p/tests/test_server/fs_flush.c index fade0a1..63a52af 100644 --- a/lib9p/tests/test_server/fs_flush.c +++ b/lib9p/tests/test_server/fs_flush.c @@ -31,10 +31,10 @@ static struct lib9p_qid flush_file_qid(struct flush_file *self) { }; } -static struct lib9p_srv_stat flush_file_stat(struct flush_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error flush_file_stat(struct flush_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = flush_file_qid(self), .mode = 0444, .atime_sec = UTIL9P_ATIME, @@ -45,29 +45,29 @@ static struct lib9p_srv_stat flush_file_stat(struct flush_file *self, struct lib .owner_gid = { .name = lib9p_str("root"), .num = 0 }, .last_modifier_uid = { .name = lib9p_str("root"), .num = 0 }, .extension = lib9p_str(NULL), - }; + })); } -static void flush_file_wstat(struct flush_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { +static error flush_file_wstat(struct flush_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); } -static void flush_file_remove(struct flush_file *self, struct lib9p_srv_ctx *ctx) { +static error flush_file_remove(struct flush_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); + return error_new(E_POSIX_EROFS, "cannot remove API file"); } -LIB9P_SRV_NOTDIR(struct flush_file, flush_file) +LIB9P_SRV_NOTDIR(struct flush_file, flush_file); -static lo_interface lib9p_srv_fio flush_file_fopen(struct flush_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { +static lib9p_srv_fio_or_error flush_file_fopen(struct flush_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { assert(self); assert(ctx); struct flush_fio *ret = heap_alloc(1, struct flush_fio); ret->parent = self; - return LO_BOX(lib9p_srv_fio, ret); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); } /* srv_fio ********************************************************************/ @@ -87,19 +87,17 @@ static uint32_t flush_fio_iounit(struct flush_fio *self) { return 0; } -static uint32_t flush_fio_pwrite(struct flush_fio *LM_UNUSED(self), +static uint32_t_or_error flush_fio_pwrite(struct flush_fio *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(offset)) { assert_notreached("not writable"); } -static void flush_fio_pread(struct flush_fio *self, struct lib9p_srv_ctx *ctx, - uint32_t byte_count, uint64_t LM_UNUSED(byte_offset), - struct iovec *ret) { +static iovec_or_error flush_fio_pread(struct flush_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t LM_UNUSED(byte_offset)) { assert(self); assert(ctx); - assert(ret); /* Wait for first Tflush */ while (!lib9p_srv_flush_requested(ctx)) @@ -111,21 +109,21 @@ static void flush_fio_pread(struct flush_fio *self, struct lib9p_srv_ctx *ctx, while (cr_chan_num_waiters(&ctx->flush_ch) != self->parent->flush_cnt) cr_yield(); + /* Yield one more time, just because. */ + cr_yield(); + /* Return */ switch (self->parent->flush_behavior) { case FLUSH_READ: - *ret = (struct iovec){ + return ERROR_NEW_VAL(iovec, ((struct iovec){ .iov_base = "Sloth\n", .iov_len = 6 < byte_count ? 6 : byte_count, - }; - break; + })); case FLUSH_ERROR: - lib9p_srv_acknowledge_flush(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_ECANCELED, "request canceled by flush"); - break; + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EAGAIN, "request canceled by flush")); case FLUSH_SILENT: - lib9p_srv_acknowledge_flush(ctx); - break; + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_ECANCELED, "request canceled by flush")); + default: + assert_notreached("invalid flush_behavior"); } - cr_yield(); } diff --git a/lib9p/tests/test_server/fs_shutdown.c b/lib9p/tests/test_server/fs_shutdown.c index 0dd473d..079442e 100644 --- a/lib9p/tests/test_server/fs_shutdown.c +++ b/lib9p/tests/test_server/fs_shutdown.c @@ -30,10 +30,10 @@ static struct lib9p_qid shutdown_file_qid(struct shutdown_file *self) { }; } -static struct lib9p_srv_stat shutdown_file_stat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error shutdown_file_stat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = shutdown_file_qid(self), .mode = 0222 | LIB9P_DM_APPEND, .atime_sec = UTIL9P_ATIME, @@ -44,29 +44,29 @@ static struct lib9p_srv_stat shutdown_file_stat(struct shutdown_file *self, stru .owner_gid = { .name=lib9p_str("root"), .num=0 }, .last_modifier_uid = { .name=lib9p_str("root"), .num=0 }, .extension = lib9p_str(NULL), - }; + })); } -static void shutdown_file_wstat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { +static error shutdown_file_wstat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); } -static void shutdown_file_remove(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { +static error shutdown_file_remove(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); + return error_new(E_POSIX_EROFS, "cannot remove API file"); } -LIB9P_SRV_NOTDIR(struct shutdown_file, shutdown_file) +LIB9P_SRV_NOTDIR(struct shutdown_file, shutdown_file); -static lo_interface lib9p_srv_fio shutdown_file_fopen(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { +static lib9p_srv_fio_or_error shutdown_file_fopen(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { assert(self); assert(ctx); struct shutdown_fio *ret = heap_alloc(1, struct shutdown_fio); ret->parent = self; - return LO_BOX(lib9p_srv_fio, ret); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); } /* srv_fio ********************************************************************/ @@ -86,19 +86,18 @@ static uint32_t shutdown_fio_iounit(struct shutdown_fio *self) { return 0; } -static uint32_t shutdown_fio_pwrite(struct shutdown_fio *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t offset) { +static uint32_t_or_error shutdown_fio_pwrite(struct shutdown_fio *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t offset) { assert(self); assert(ctx); assert(buf); assert(offset == 0); if (byte_count == 0) - return 0; + return ERROR_NEW_VAL(uint32_t, 0); for (size_t i = 0; i < self->parent->nlisteners; i++) LO_CALL(LO_BOX(net_stream_listener, &self->parent->listeners[i]), close); - return byte_count; + return ERROR_NEW_VAL(uint32_t, byte_count); } -static void shutdown_fio_pread(struct shutdown_fio *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), - uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset), - struct iovec *LM_UNUSED(ret)) { +static iovec_or_error shutdown_fio_pread(struct shutdown_fio *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx), + uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset)) { assert_notreached("not readable"); } diff --git a/lib9p/tests/test_server/fs_whoami.c b/lib9p/tests/test_server/fs_whoami.c index 6cc46ac..3cc0683 100644 --- a/lib9p/tests/test_server/fs_whoami.c +++ b/lib9p/tests/test_server/fs_whoami.c @@ -53,11 +53,11 @@ static struct lib9p_qid whoami_file_qid(struct whoami_file *self) { }; } -static struct lib9p_srv_stat whoami_file_stat(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error whoami_file_stat(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = whoami_file_qid(self), .mode = 0444, .atime_sec = UTIL9P_ATIME, @@ -68,22 +68,22 @@ static struct lib9p_srv_stat whoami_file_stat(struct whoami_file *self, struct l .owner_gid = { .name=lib9p_str("root"), .num=0 }, .last_modifier_uid = { .name=lib9p_str("root"), .num=0 }, .extension = lib9p_str(NULL), - }; + })); } -static void whoami_file_wstat(struct whoami_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { +static error whoami_file_wstat(struct whoami_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot wstat API file"); + return error_new(E_POSIX_EROFS, "cannot wstat API file"); } -static void whoami_file_remove(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { +static error whoami_file_remove(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "cannot remove API file"); + return error_new(E_POSIX_EROFS, "cannot remove API file"); } -LIB9P_SRV_NOTDIR(struct whoami_file, whoami_file) +LIB9P_SRV_NOTDIR(struct whoami_file, whoami_file); -static lo_interface lib9p_srv_fio whoami_file_fopen(struct whoami_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { +static lib9p_srv_fio_or_error whoami_file_fopen(struct whoami_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { assert(self); assert(ctx); @@ -92,7 +92,7 @@ static lo_interface lib9p_srv_fio whoami_file_fopen(struct whoami_file *self, st ret->buf_len = 0; ret->buf = NULL; - return LO_BOX(lib9p_srv_fio, ret); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, ret)); } /* srv_fio ********************************************************************/ @@ -115,18 +115,16 @@ static uint32_t whoami_fio_iounit(struct whoami_fio *self) { return 0; } -static uint32_t whoami_fio_pwrite(struct whoami_fio *LM_UNUSED(self), - struct lib9p_srv_ctx *LM_UNUSED(ctx), - void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), - uint64_t LM_UNUSED(offset)) { +static uint32_t_or_error whoami_fio_pwrite(struct whoami_fio *LM_UNUSED(self), + struct lib9p_srv_ctx *LM_UNUSED(ctx), + void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(offset)) { assert_notreached("not writable"); } -static void whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, - uint32_t byte_count, uint64_t byte_offset, - struct iovec *ret) { +static iovec_or_error whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t byte_offset) { assert(self); assert(ctx); - assert(ret); size_t data_size = whoami_len(ctx); if (self->buf_len < data_size+1) { @@ -136,19 +134,16 @@ static void whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, snprintf(self->buf, self->buf_len, "%"PRIu32" %.*s\n", ctx->user->num, ctx->user->name.len, ctx->user->name.utf8); - if (byte_offset > (uint64_t)data_size) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "offset is past end-of-file length"); - return; - } + if (byte_offset > (uint64_t)data_size) + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EINVAL, "offset is past end-of-file length")); size_t beg_off = (size_t)byte_offset; size_t end_off = beg_off + (size_t)byte_count; if (end_off > data_size) end_off = data_size; - *ret = (struct iovec){ + return ERROR_NEW_VAL(iovec, ((struct iovec){ .iov_base = &self->buf[beg_off], .iov_len = end_off-beg_off, - }; + })); } diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c index 052d180..0431c40 100644 --- a/lib9p/tests/test_server/main.c +++ b/lib9p/tests/test_server/main.c @@ -5,10 +5,13 @@ */ #include <errno.h> -#include <error.h> #include <stdio.h> #include <stdlib.h> /* for atoi() */ +#define error __error +#include <error.h> +#undef error + #include <lib9p/srv.h> #include <libcr/coroutine.h> #include <libhw/generic/alarmclock.h> @@ -36,7 +39,7 @@ /* globals ********************************************************************/ -static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *, struct lib9p_s); +static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *, struct lib9p_s); static const char *hexdig = "0123456789abcdef"; @@ -84,8 +87,8 @@ static struct lib9p_srv_file root = API_FILE(13, "flush-slowread", flush, .flush_cnt=0, .flush_behavior=FLUSH_READ), ); -static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { - return root; +static lib9p_srv_file_or_error get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { + return ERROR_NEW_VAL(lib9p_srv_file, root); } /* main ***********************************************************************/ @@ -117,12 +120,12 @@ static COROUTINE init_cr(void *) { for (int i = 0; i < _CONFIG_9P_MAX_CONNS; i++) { char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'}; if (!coroutine_add(name, read_cr, &i)) - error(1, 0, "coroutine_add(read_cr, &i)"); + __error(1, 0, "coroutine_add(read_cr, &i)"); } for (int i = 0; i < _CONFIG_9P_MAX_REQS; i++) { char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'}; if (!coroutine_add(name, write_cr, NULL)) - error(1, 0, "coroutine_add(write_cr, NULL)"); + __error(1, 0, "coroutine_add(write_cr, NULL)"); } cr_exit(); @@ -153,12 +156,12 @@ static void tstlog_msg(struct lib9p_srv_ctx *ctx, enum lib9p_msg_type typ, void int main(int argc, char *argv[]) { if (argc != 3) - error(2, 0, "usage: %s PORT_NUMBER LOGFILE", argv[0]); + __error(2, 0, "usage: %s PORT_NUMBER LOGFILE", argv[0]); globals.port = atoi(argv[1]); globals.logstream = fopen(argv[2], "w"); if (!globals.logstream) - error(2, errno, "fopen"); + __error(2, errno, "fopen"); globals.srv.msglog = tstlog_msg; struct hostclock clock_monotonic = { diff --git a/lib9p/tests/testclient-hangup.c b/lib9p/tests/testclient-hangup.c index a819e80..2efb49a 100644 --- a/lib9p/tests/testclient-hangup.c +++ b/lib9p/tests/testclient-hangup.c @@ -24,8 +24,8 @@ static void _send9p(int fd, struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body) { struct lib9p_Tmsg_send_buf buf; - bool err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); - assert(!err); + error err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); + assert(ERROR_IS_NULL(err)); size_t exp = 0; for (size_t i = 0; i < buf.iov_cnt; i++) exp += buf.iov[i].iov_len; diff --git a/lib9p/tests/testclient-sess.c b/lib9p/tests/testclient-sess.c index 276f932..0cec6c6 100644 --- a/lib9p/tests/testclient-sess.c +++ b/lib9p/tests/testclient-sess.c @@ -6,13 +6,16 @@ #include <arpa/inet.h> /* for htons(), inet_addr() */ #include <errno.h> -#include <error.h> #include <netinet/in.h> /* for struct sockaddr{,_in} */ #include <stdlib.h> /* for atoi() */ #include <sys/socket.h> /* for socket(), connect() */ #include <sys/uio.h> /* for writev() */ #include <unistd.h> /* for read() */ +#define error __error +#include <error.h> +#undef error + #include <lib9p/core.h> #include <libmisc/assert.h> #include <libmisc/endian.h> @@ -21,14 +24,14 @@ static void _send9p(int fd, struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *body) { struct lib9p_Tmsg_send_buf buf; - bool err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); - assert(!err); + error err = lib9p_Tmsg_marshal(ctx, typ, body, &buf); + assert(ERROR_IS_NULL(err)); size_t exp = 0; for (size_t i = 0; i < buf.iov_cnt; i++) exp += buf.iov[i].iov_len; ssize_t act = writev(fd, buf.iov, buf.iov_cnt); if (act < 0) - error(1, errno, "writev"); + __error(1, errno, "writev"); assert((size_t)act == exp); } @@ -41,7 +44,7 @@ static void _recv9p(int fd) { while (done < goal) { ssize_t n = read(fd, &buf[done], goal-done); if (n < 0) - error(1, errno, "read"); + __error(1, errno, "read"); done += n; } goal = uint32le_decode(buf); @@ -49,7 +52,7 @@ static void _recv9p(int fd) { while (done < goal) { ssize_t n = read(fd, &buf[done], goal-done); if (n < 0) - error(1, errno, "read"); + __error(1, errno, "read"); done += n; } } @@ -58,7 +61,7 @@ static void _recv9p(int fd) { int main(int argc, char *argv[]) { if (argc != 2) - error(2, 0, "Usage: %s SERVER_PORT", argv[0]); + __error(2, 0, "Usage: %s SERVER_PORT", argv[0]); uint16_t server_port = atoi(argv[1]); union { @@ -71,9 +74,9 @@ int main(int argc, char *argv[]) { int fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) - error(1, errno, "socket"); + __error(1, errno, "socket"); if (connect(fd, &server_addr.gen, sizeof(server_addr)) < 0) - error(1, errno, "connect"); + __error(1, errno, "connect"); struct lib9p_ctx ctx = { .max_msg_size = 16*1024, diff --git a/lib9p/tests/testclient-sess.explog b/lib9p/tests/testclient-sess.explog index a3838ac..ec8d9c9 100644 --- a/lib9p/tests/testclient-sess.explog +++ b/lib9p/tests/testclient-sess.explog @@ -103,7 +103,7 @@ < Ropen { tag=0 qid={ type=(0) vers=1 path=10 } iounit=0 } > Tread { tag=0 fid=2 offset=0 count=10 } > Tflush { tag=1 oldtag=0 } -< Rerror { tag=0 errstr="request canceled by flush" errnum=L_ECANCELED } +< Rerror { tag=0 errstr="request canceled by flush" errnum=L_EAGAIN } < Rflush { tag=1 } # flush, original request is aborted without error diff --git a/lib9p_util/static.c b/lib9p_util/static.c index 40810b5..6861869 100644 --- a/lib9p_util/static.c +++ b/lib9p_util/static.c @@ -33,11 +33,11 @@ static struct lib9p_qid util9p_static_dir_qid(struct util9p_static_dir *self) { }; } -static struct lib9p_srv_stat util9p_static_dir_stat(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error util9p_static_dir_stat(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = util9p_static_dir_qid(self), .mode = LIB9P_DM_DIR | (self->c.perm & 0555), .atime_sec = self->c.atime, @@ -48,80 +48,77 @@ static struct lib9p_srv_stat util9p_static_dir_stat(struct util9p_static_dir *se .owner_gid = { .name = lib9p_str(self->c.g_name), .num = self->c.g_num }, .last_modifier_uid = { .name = lib9p_str(self->c.m_name), .num = self->c.m_num }, .extension = lib9p_str(NULL), - }; + })); } -static void util9p_static_dir_wstat(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, - struct lib9p_srv_stat) { +static error util9p_static_dir_wstat(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, + struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); + return error_new(E_POSIX_EROFS, "read-only part of filesystem"); } -static void util9p_static_dir_remove(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx) { +static error util9p_static_dir_remove(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); + return error_new(E_POSIX_EROFS, "read-only part of filesystem"); } -static lo_interface lib9p_srv_file util9p_static_dir_dwalk(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, - struct lib9p_s childname) { +static lib9p_srv_file_or_error util9p_static_dir_dwalk(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, + struct lib9p_s childname) { assert(self); assert(ctx); for (size_t i = 0; !LO_IS_NULL(self->members[i]); i++) { lo_interface lib9p_srv_file file = self->members[i]; - struct lib9p_srv_stat stat = LO_CALL(file, stat, ctx); - if (lib9p_ctx_has_error(&ctx->basectx)) - break; - lib9p_srv_stat_assert(stat); - if (lib9p_str_eq(stat.name, childname)) - return file; + lib9p_srv_stat_or_error stat = LO_CALL(file, stat, ctx); + if (stat.is_err) + return ERROR_NEW_ERR(lib9p_srv_file, stat.err); + lib9p_srv_stat_assert(stat.lib9p_srv_stat); + if (lib9p_str_eq(stat.lib9p_srv_stat.name, childname)) + return ERROR_NEW_VAL(lib9p_srv_file, file); } - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_ENOENT, "no such file or directory"); - return LO_NULL(lib9p_srv_file); + return ERROR_NEW_ERR(lib9p_srv_file, error_new(E_POSIX_ENOENT, "no such file or directory")); } -static lo_interface lib9p_srv_file util9p_static_dir_dcreate(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, - struct lib9p_s LM_UNUSED(childname), - struct lib9p_srv_userid *LM_UNUSED(user), - struct lib9p_srv_userid *LM_UNUSED(group), - lib9p_dm_t LM_UNUSED(perm)) { +static lib9p_srv_file_or_error util9p_static_dir_dcreate(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, + struct lib9p_s LM_UNUSED(childname), + struct lib9p_srv_userid *LM_UNUSED(user), + struct lib9p_srv_userid *LM_UNUSED(group), + lib9p_dm_t LM_UNUSED(perm)) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); - return LO_NULL(lib9p_srv_file); + return ERROR_NEW_ERR(lib9p_srv_file, error_new(E_POSIX_EROFS, "read-only part of filesystem")); } LIB9P_SRV_NOTFILE(struct util9p_static_dir, util9p_static_dir); -static lo_interface lib9p_srv_dio util9p_static_dir_dopen(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_dio_or_error util9p_static_dir_dopen(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return LO_BOX(lib9p_srv_dio, self); + return ERROR_NEW_VAL(lib9p_srv_dio, LO_BOX(lib9p_srv_dio, self)); } static void util9p_static_dir_iofree(struct util9p_static_dir *self) { assert(self); } -static struct lib9p_srv_dirent util9p_static_dir_dread(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, size_t idx) { +static lib9p_srv_dirent_or_error util9p_static_dir_dread(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, size_t idx) { assert(self); assert(ctx); lo_interface lib9p_srv_file file = self->members[idx]; if (LO_IS_NULL(file)) - return (struct lib9p_srv_dirent){}; + return ERROR_NEW_VAL(lib9p_srv_dirent, (struct lib9p_srv_dirent){}); - struct lib9p_srv_stat stat = LO_CALL(file, stat, ctx); - if (lib9p_ctx_has_error(&ctx->basectx)) - return (struct lib9p_srv_dirent){}; - lib9p_srv_stat_assert(stat); + lib9p_srv_stat_or_error stat = LO_CALL(file, stat, ctx); + if (stat.is_err) + return ERROR_NEW_ERR(lib9p_srv_dirent, stat.err); + lib9p_srv_stat_assert(stat.lib9p_srv_stat); - return (struct lib9p_srv_dirent){ - .qid = stat.qid, - .name = stat.name, - }; + return ERROR_NEW_VAL(lib9p_srv_dirent, ((struct lib9p_srv_dirent){ + .qid = stat.lib9p_srv_stat.qid, + .name = stat.lib9p_srv_stat.name, + })); } /* file ***********************************************************************/ @@ -151,11 +148,11 @@ static inline size_t util9p_static_file_size(struct util9p_static_file *file) { } -static struct lib9p_srv_stat util9p_static_file_stat(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx) { +static lib9p_srv_stat_or_error util9p_static_file_stat(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - return (struct lib9p_srv_stat){ + return ERROR_NEW_VAL(lib9p_srv_stat, ((struct lib9p_srv_stat){ .qid = util9p_static_file_qid(self), .mode = self->c.perm & 0444, .atime_sec = self->c.atime, @@ -166,32 +163,32 @@ static struct lib9p_srv_stat util9p_static_file_stat(struct util9p_static_file * .owner_gid = { .name = lib9p_str(self->c.g_name), .num = self->c.g_num }, .last_modifier_uid = { .name = lib9p_str(self->c.m_name), .num = self->c.m_num }, .extension = lib9p_str(NULL), - }; + })); } -static void util9p_static_file_wstat(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, +static error util9p_static_file_wstat(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_srv_stat) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); + return error_new(E_POSIX_EROFS, "read-only part of filesystem"); } -static void util9p_static_file_remove(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx) { +static error util9p_static_file_remove(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); + return error_new(E_POSIX_EROFS, "read-only part of filesystem"); } LIB9P_SRV_NOTDIR(struct util9p_static_file, util9p_static_file); -static lo_interface lib9p_srv_fio util9p_static_file_fopen(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, - bool rd, bool wr, bool trunc) { +static lib9p_srv_fio_or_error util9p_static_file_fopen(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, + bool rd, bool wr, bool trunc) { assert(self); assert(ctx); assert(rd); assert(!wr); assert(!trunc); - return LO_BOX(lib9p_srv_fio, self); + return ERROR_NEW_VAL(lib9p_srv_fio, LO_BOX(lib9p_srv_fio, self)); } static void util9p_static_file_iofree(struct util9p_static_file *self) { assert(self); @@ -200,35 +197,31 @@ static uint32_t util9p_static_file_iounit(struct util9p_static_file *self) { assert(self); return 0; } -static void util9p_static_file_pread(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, - uint32_t byte_count, uint64_t byte_offset, - struct iovec *ret) { +static iovec_or_error util9p_static_file_pread(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t byte_offset) { assert(self); assert(ctx); - assert(ret); size_t data_size = util9p_static_file_size(self); - if (byte_offset > (uint64_t)data_size) { - lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EINVAL, "offset is past end-of-file length"); - return; - } + if (byte_offset > (uint64_t)data_size) + return ERROR_NEW_ERR(iovec, error_new(E_POSIX_EINVAL, "offset is past end-of-file length")); size_t beg_off = (size_t)byte_offset; size_t end_off = beg_off + (size_t)byte_count; if (end_off > data_size) end_off = data_size; - ret->iov_base = &self->data_start[beg_off]; - ret->iov_len = end_off-beg_off; + return ERROR_NEW_VAL(iovec, ((struct iovec){ + .iov_base = &self->data_start[beg_off], + .iov_len = end_off-beg_off, + })); } -static uint32_t util9p_static_file_pwrite(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, - void *LM_UNUSED(buf), - uint32_t LM_UNUSED(byte_count), - uint64_t LM_UNUSED(byte_offset)) { +static uint32_t_or_error util9p_static_file_pwrite(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, + void *LM_UNUSED(buf), + uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(byte_offset)) { assert(self); assert(ctx); - lib9p_error(&ctx->basectx, LIB9P_ERRNO_L_EROFS, "read-only part of filesystem"); - return 0; + return ERROR_NEW_ERR(uint32_t, error_new(E_POSIX_EROFS, "read-only part of filesystem")); } diff --git a/libdhcp/dhcp_client.c b/libdhcp/dhcp_client.c index 57a2f60..1164355 100644 --- a/libdhcp/dhcp_client.c +++ b/libdhcp/dhcp_client.c @@ -252,11 +252,8 @@ static inline enum requirement dhcp_table5(typeof((struct dhcp_client){}.state) * @param client->lease_client_addr (sometimes) * @param client->lease_server_id (sometimes) * @param client->sock - * - * @return client->last_sent_msgtyp - * @return whether there was an error */ -static bool dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const char *errstr, struct dhcp_msg *scratch_msg) { +static error dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const char *errstr, struct dhcp_msg *scratch_msg) { /**********************************************************************\ * Preconditions * \**********************************************************************/ @@ -462,14 +459,14 @@ static bool dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const c * Send * \**********************************************************************/ log_debugln("state ", state_strs[client->state], ": sending DHCP ", dhcp_msgtyp_str(msgtyp)); - ssize_t r = LO_CALL(client->sock, sendto, scratch_msg, DHCP_MSG_BASE_SIZE + optlen, - client_broadcasts ? net_ip4_addr_broadcast : client->lease_server_id, DHCP_PORT_SERVER); - if (r < 0) { - log_debugln("error: sendto: ", r); - return true; + error err = LO_CALL(client->sock, sendto, scratch_msg, DHCP_MSG_BASE_SIZE + optlen, + client_broadcasts ? net_ip4_addr_broadcast : client->lease_server_id, DHCP_PORT_SERVER); + if (!ERROR_IS_NULL(err)) { + log_debugln("error: sendto: ", (error, err)); + return err; } client->last_sent_msgtyp = msgtyp; - return false; + return ERROR_NULL; } struct dhcp_recv_msg { @@ -565,24 +562,20 @@ static inline enum requirement dhcp_table3(uint8_t req_msgtyp, uint8_t resp_msgt * @param client->self_eth_addr * @param client->xid * @param client->lease_server_id - * - * @return - * - <0: -errno - * - 0: success - * - >0: should not happen */ -static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg *ret) { +static error dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg *ret) { struct net_ip4_addr srv_addr; uint16_t srv_port; - ssize_t msg_len; + size_t msg_len; assert(client); ignore: - msg_len = LO_CALL(client->sock, recvfrom, &ret->raw, sizeof(ret->raw), &srv_addr, &srv_port); - if (msg_len < 0) + size_t_or_error r = LO_CALL(client->sock, recvfrom, &ret->raw, sizeof(ret->raw), &srv_addr, &srv_port); + if (r.is_err) /* msg_len is -errno */ - return msg_len; + return r.err; + msg_len = r.size_t; /* Validate L3: IP */ /* Don't validate that srv_addr matches client->server_id @@ -595,10 +588,10 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg goto ignore; /* Validate L5: DHCP. */ - if ((size_t)msg_len < DHCP_MSG_BASE_SIZE + sizeof(dhcp_magic_cookie)) + if (msg_len < DHCP_MSG_BASE_SIZE + sizeof(dhcp_magic_cookie)) /* ignore impossibly short message */ goto ignore; - if ((size_t)msg_len > sizeof(ret->raw)) + if (msg_len > sizeof(ret->raw)) /* ignore message that is larger than the specified * DHCP_OPT_DHCP_MAX_MSG_SIZE */ goto ignore; @@ -698,7 +691,7 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg goto ignore; } - return 0; + return ERROR_NULL; } static void dhcp_client_take_lease(struct dhcp_client *client, struct dhcp_recv_msg *msg, bool ifup) { @@ -748,18 +741,19 @@ static void dhcp_client_take_lease(struct dhcp_client *client, struct dhcp_recv_ static void dhcp_client_setstate(struct dhcp_client *client, typeof((struct dhcp_client){}.state) newstate, uint8_t send_msgtyp, const char *errstr, struct dhcp_recv_msg *scratch_msg) { - if (send_msgtyp) - (void)dhcp_client_send(client, send_msgtyp, errstr, &scratch_msg->raw); + if (send_msgtyp) { + error err = dhcp_client_send(client, send_msgtyp, errstr, &scratch_msg->raw); + error_cleanup(&err); + } client->state = newstate; } [[noreturn]] static void dhcp_client_run(struct dhcp_client *client, struct dhcp_recv_msg *scratch_msg) { assert(client); - ssize_t r; - /* State transition diagram: https://datatracker.ietf.org/doc/html/rfc2131#page-35 */ for (;;) { + [[gnu::cleanup(error_cleanup)]] error err = {}; log_debugln("loop: state=", state_strs[client->state]); switch (client->state) { case STATE_INIT: @@ -769,8 +763,8 @@ static void dhcp_client_setstate(struct dhcp_client *client, break; case STATE_SELECTING: LO_CALL(client->sock, set_recv_deadline, client->time_ns_init+CONFIG_DHCP_SELECTING_NS); - switch ((r = dhcp_client_recv(client, scratch_msg))) { - case 0: + LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) { + case E_NOERROR: switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) { case DHCP_MSGTYP_OFFER: /* Accept the first offer. */ @@ -781,18 +775,17 @@ static void dhcp_client_setstate(struct dhcp_client *client, /* ignore */ } break; - case -NET_ERECV_TIMEOUT: + case E_NET_ERECV_TIMEOUT: dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg); break; default: - assert(r < 0); - log_debugln("error: recvfrom: ", r); + log_debugln("error: recvfrom: ", (error, err)); } break; case STATE_REQUESTING: LO_CALL(client->sock, set_recv_deadline, 0); - switch ((r = dhcp_client_recv(client, scratch_msg))) { - case 0: + LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) { + case E_NOERROR: switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) { case DHCP_MSGTYP_NAK: dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg); @@ -811,22 +804,20 @@ static void dhcp_client_setstate(struct dhcp_client *client, } break; default: - assert(r < 0); - log_debugln("error: recvfrom: ", r); + log_debugln("error: recvfrom: ", (error, err)); } break; case STATE_BOUND: LO_CALL(client->sock, set_recv_deadline, client->lease_time_ns_t1); - switch ((r = dhcp_client_recv(client, scratch_msg))) { - case 0: + LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) { + case E_NOERROR: /* discard */ break; - case -NET_ERECV_TIMEOUT: + case E_NET_ERECV_TIMEOUT: dhcp_client_setstate(client, STATE_RENEWING, DHCP_MSGTYP_REQUEST, NULL, scratch_msg); break; default: - assert(r < 0); - log_debugln("error: recvfrom: ", r); + log_debugln("error: recvfrom: ", (error, err)); } break; case STATE_RENEWING: @@ -834,8 +825,8 @@ static void dhcp_client_setstate(struct dhcp_client *client, client->time_ns_init = LO_CALL(bootclock, get_time_ns); LO_CALL(client->sock, set_recv_deadline, client->lease_time_ns_t2); - switch ((r = dhcp_client_recv(client, scratch_msg))) { - case 0: + LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) { + case E_NOERROR: switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) { case DHCP_MSGTYP_NAK: LO_CALL(client->iface, ifdown); @@ -849,19 +840,18 @@ static void dhcp_client_setstate(struct dhcp_client *client, /* ignore */ } break; - case -NET_ERECV_TIMEOUT: + case E_NET_ERECV_TIMEOUT: client->lease_server_id = net_ip4_addr_zero; dhcp_client_setstate(client, STATE_REBINDING, DHCP_MSGTYP_REQUEST, NULL, scratch_msg); break; default: - assert(r < 0); - log_debugln("error: recvfrom: ", r); + log_debugln("error: recvfrom: ", (error, err)); } break; case STATE_REBINDING: LO_CALL(client->sock, set_recv_deadline, client->lease_time_ns_end); - switch ((r = dhcp_client_recv(client, scratch_msg))) { - case 0: + LM_PARTIAL_SWITCH ((err = dhcp_client_recv(client, scratch_msg)).num) { + case E_NOERROR: switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) { case DHCP_MSGTYP_NAK: LO_CALL(client->iface, ifdown); @@ -875,13 +865,12 @@ static void dhcp_client_setstate(struct dhcp_client *client, /* ignore */ } break; - case -NET_ERECV_TIMEOUT: + case E_NET_ERECV_TIMEOUT: LO_CALL(client->iface, ifdown); dhcp_client_setstate(client, STATE_BOUND, 0, NULL, scratch_msg); break; default: - assert(r < 0); - log_debugln("error: recvfrom: ", r); + log_debugln("error: recvfrom: ", (error, err)); } break; case STATE_INIT_REBOOT: diff --git a/libdhcp/tests/test_client.c b/libdhcp/tests/test_client.c index 09557e5..cf76653 100644 --- a/libdhcp/tests/test_client.c +++ b/libdhcp/tests/test_client.c @@ -23,14 +23,14 @@ LO_IMPLEMENTATION_C(io_closer, struct test_udp, test_udp, static); LO_IMPLEMENTATION_H(net_packet_conn, struct test_udp, test_udp); LO_IMPLEMENTATION_C(net_packet_conn, struct test_udp, test_udp, static); -static ssize_t test_udp_sendto(struct test_udp *LM_UNUSED(self), void *LM_UNUSED(buf), size_t len, struct net_ip4_addr LM_UNUSED(node), uint16_t LM_UNUSED(port)) { +static error test_udp_sendto(struct test_udp *LM_UNUSED(self), void *LM_UNUSED(buf), size_t LM_UNUSED(len), struct net_ip4_addr LM_UNUSED(node), uint16_t LM_UNUSED(port)) { static unsigned cnt = 0; if (cnt++ % 2 == 0) - return -NET_EOTHER; - return len; + return error_new(E_EUNKNOWN); + return ERROR_NULL; } -static ssize_t test_udp_recvfrom(struct test_udp *LM_UNUSED(self), void *buf, size_t len, struct net_ip4_addr *ret_node, uint16_t *ret_port) { +static size_t_or_error test_udp_recvfrom(struct test_udp *LM_UNUSED(self), void *buf, size_t len, struct net_ip4_addr *ret_node, uint16_t *ret_port) { static const uint8_t resp_offer[] = {0x02,0x01,0x06,0x00,0xE8,0x40,0xC6,0x79,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0xC0,0xA8,0x0A,0x78,0xC0,0xA8,0x0A,0x01,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x82,0x53,0x63,0x35,0x01,0x02,0x36,0x04,0xC0,0xA8,0x0A,0x01,0x33,0x04,0x00,0x00,0xA8,0xC0,0x3A,0x04,0x00,0x00,0x54,0x60,0x3B,0x04,0x00,0x00,0x93,0xA8,0x01,0x04,0xFF,0xFF,0xFF,0x00,0x1C,0x04,0xC0,0xA8,0x0A,0xFF,0x03,0x04,0xC0,0xA8,0x0A,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; static const uint8_t resp_ack[] = {0x02,0x01,0x06,0x00,0xE8,0x40,0xC6,0x79,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0xC0,0xA8,0x0A,0x78,0xC0,0xA8,0x0A,0x01,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x82,0x53,0x63,0x35,0x01,0x05,0x36,0x04,0xC0,0xA8,0x0A,0x01,0x33,0x04,0x00,0x00,0xA8,0xC0,0x3A,0x04,0x00,0x00,0x54,0x60,0x3B,0x04,0x00,0x00,0x93,0xA8,0x01,0x04,0xFF,0xFF,0xFF,0x00,0x1C,0x04,0xC0,0xA8,0x0A,0xFF,0x03,0x04,0xC0,0xA8,0x0A,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; @@ -38,24 +38,24 @@ static ssize_t test_udp_recvfrom(struct test_udp *LM_UNUSED(self), void *buf, si const void *resp; size_t resp_len; switch (cnt++) { - case 0: return -NET_EOTHER; + case 0: return ERROR_NEW_ERR(size_t, error_new(E_EUNKNOWN)); case 1: resp = resp_offer; resp_len = sizeof(resp_offer); break; - case 2: return -NET_EOTHER; + case 2: return ERROR_NEW_ERR(size_t, error_new(E_EUNKNOWN)); case 3: resp = resp_ack; resp_len = sizeof(resp_ack); break; - default: return -NET_ERECV_TIMEOUT; + default: return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT)); } test_assert(len >= resp_len); memcpy(buf, resp, resp_len); *ret_node = ((struct net_ip4_addr){{192,168,10,1}}); *ret_port = 67; - return resp_len; + return ERROR_NEW_VAL(size_t, resp_len); } static void test_udp_set_recv_deadline(struct test_udp *LM_UNUSED(self), uint64_t LM_UNUSED(ns_since_boot)) { /* Do nothing? */ } -static int test_udp_close(struct test_udp *LM_UNUSED(self)) { +static error test_udp_close(struct test_udp *LM_UNUSED(self)) { assert_notreached("not implemented"); } @@ -90,7 +90,7 @@ static lo_interface net_stream_listener test_tcp_listen(struct test_iface *LM_UN assert_notreached("not implemented"); } -static lo_interface net_stream_conn test_tcp_dial(struct test_iface *LM_UNUSED(self), struct net_ip4_addr LM_UNUSED(remote_node), uint16_t LM_UNUSED(remote_port)) { +static net_stream_conn_or_error test_tcp_dial(struct test_iface *LM_UNUSED(self), struct net_ip4_addr LM_UNUSED(remote_node), uint16_t LM_UNUSED(remote_port)) { assert_notreached("not implemented"); } diff --git a/libhw_cr/host_alarmclock.c b/libhw_cr/host_alarmclock.c index ac2093c..325f7e0 100644 --- a/libhw_cr/host_alarmclock.c +++ b/libhw_cr/host_alarmclock.c @@ -5,9 +5,12 @@ */ #include <errno.h> -#include <error.h> #include <signal.h> +#define error __error +#include <error.h> +#undef error + #include <libcr/coroutine.h> #include <libmisc/assert.h> @@ -27,7 +30,7 @@ static uint64_t hostclock_get_time_ns(struct hostclock *alarmclock) { struct timespec ts; if (clock_gettime(alarmclock->clock_id, &ts) != 0) - error(1, errno, "clock_gettime(%d)", (int)alarmclock->clock_id); + __error(1, errno, "clock_gettime(%d)", (int)alarmclock->clock_id); return ns_from_host_ns_time(ts); } @@ -52,7 +55,7 @@ static void hostclock_handle_sig_alarm(int LM_UNUSED(sig), siginfo_t *info, void .it_interval = {}, }; if (timer_settime(alarmclock->timer_id, TIMER_ABSTIME, &alarmspec, NULL) != 0) - error(1, errno, "timer_settime"); + __error(1, errno, "timer_settime"); } } @@ -93,9 +96,9 @@ static bool hostclock_add_trigger(struct hostclock *alarmclock, .sa_sigaction = hostclock_handle_sig_alarm, }; if (sigaction(how_to_notify.sigev_signo, &action, NULL) != 0) - error(1, errno, "sigaction"); + __error(1, errno, "sigaction"); if (timer_create(alarmclock->clock_id, &how_to_notify, &alarmclock->timer_id) != 0) - error(1, errno, "timer_create(%d)", (int)alarmclock->clock_id); + __error(1, errno, "timer_create(%d)", (int)alarmclock->clock_id); alarmclock->initialized = true; } if (alarmclock->queue == trigger) { @@ -104,7 +107,7 @@ static bool hostclock_add_trigger(struct hostclock *alarmclock, .it_interval = {}, }; if (timer_settime(alarmclock->timer_id, TIMER_ABSTIME, &alarmspec, NULL) != 0) - error(1, errno, "timer_settime"); + __error(1, errno, "timer_settime"); } cr_restore_interrupts(saved); diff --git a/libhw_cr/host_net.c b/libhw_cr/host_net.c index c8d4472..39bfd46 100644 --- a/libhw_cr/host_net.c +++ b/libhw_cr/host_net.c @@ -7,7 +7,9 @@ #define _GNU_SOURCE /* for pthread_sigqueue(3gnu) */ /* misc */ #include <errno.h> /* for errno, EAGAIN, EINVAL */ +#define error __error #include <error.h> /* for error(3gnu) */ +#undef error #include <stdlib.h> /* for abs(), shutdown(), SHUT_RD, SHUT_WR, SHUT_RDWR */ #include <unistd.h> /* for read(), write() */ /* net */ @@ -63,7 +65,7 @@ static void hostnet_init(void) { action.sa_flags = SA_SIGINFO; action.sa_sigaction = hostnet_handle_sig_io; if (sigaction(hostnet_sig_io, &action, NULL) < 0) - error(1, errno, "sigaction"); + __error(1, errno, "sigaction"); } #define WAKE_COROUTINE(args) do { \ @@ -78,46 +80,47 @@ static void hostnet_init(void) { } while (r == EAGAIN); \ } while (0) -static inline bool RUN_PTHREAD(void *(*fn)(void *), void *args) { +static inline host_errno_t RUN_PTHREAD(void *(*fn)(void *), void *args) { pthread_t thread; + host_errno_t r; bool saved = cr_save_and_disable_interrupts(); - if (pthread_create(&thread, NULL, fn, args)) - return true; + r = pthread_create(&thread, NULL, fn, args); + if (r) { + cr_restore_interrupts(saved); + return r; + } cr_pause_and_yield(); cr_restore_interrupts(saved); - if (pthread_join(thread, NULL)) - return true; - return false; + return pthread_join(thread, NULL); } enum hostnet_timeout_op { - OP_NONE, + OP_CLOSE, OP_SEND, OP_RECV, }; -static inline ssize_t hostnet_map_negerrno(ssize_t v, enum hostnet_timeout_op op) { - if (v >= 0) - return v; - switch (v) { - case -EHOSTUNREACH: - return -NET_EARP_TIMEOUT; - case -ETIMEDOUT: +static inline error hostnet_error(host_errno_t errnum, enum hostnet_timeout_op op) { + assert(errnum > 0); + switch (errnum) { + case EHOSTUNREACH: + return error_new(E_NET_EARP_TIMEOUT); + case ETIMEDOUT: switch (op) { - case OP_NONE: + case OP_CLOSE: assert_notreached("impossible ETIMEDOUT"); case OP_SEND: - return -NET_EACK_TIMEOUT; + return error_new(E_NET_EACK_TIMEOUT); case OP_RECV: - return -NET_ERECV_TIMEOUT; + return error_new(E_NET_ERECV_TIMEOUT); } assert_notreached("invalid timeout op"); - case -EBADF: - return -NET_ECLOSED; - case -EMSGSIZE: - return -NET_EMSGSIZE; + case EBADF: + return error_new(E_NET_ECLOSED); + case EMSGSIZE: + return error_new(E_POSIX_EMSGSIZE); default: - return -NET_EOTHER; + return errno2lm(errnum); } } @@ -136,15 +139,15 @@ void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port) addr.in.sin_port = htons(port); listenerfd = socket(AF_INET, SOCK_STREAM, 0); if (listenerfd < 0) - error(1, errno, "socket"); + __error(1, errno, "socket"); if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) - error(1, errno, "setsockopt(fd=%d, SO_REUSEADDR=1)", listenerfd); + __error(1, errno, "setsockopt(fd=%d, SO_REUSEADDR=1)", listenerfd); if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int)) < 0) - error(1, errno, "setsockopt(fd=%d, SO_REUSEPORT=1)", listenerfd); + __error(1, errno, "setsockopt(fd=%d, SO_REUSEPORT=1)", listenerfd); if (bind(listenerfd, &addr.gen, sizeof addr) < 0) - error(1, errno, "bind(fd=%d)", listenerfd); + __error(1, errno, "bind(fd=%d)", listenerfd); if (listen(listenerfd, 0) < 0) - error(1, errno, "listen(fd=%d)", listenerfd); + __error(1, errno, "listen(fd=%d)", listenerfd); self->fd = listenerfd; } @@ -158,44 +161,48 @@ struct hostnet_pthread_accept_args { int listenerfd; int *ret_connfd; + host_errno_t *ret_errno; }; static void *hostnet_pthread_accept(void *_args) { struct hostnet_pthread_accept_args *args = _args; *(args->ret_connfd) = accept(args->listenerfd, NULL, NULL); - if (*(args->ret_connfd) < 0) - *(args->ret_connfd) = -errno; + *(args->ret_errno) = errno; WAKE_COROUTINE(args); return NULL; } -static lo_interface net_stream_conn hostnet_tcplist_accept(struct hostnet_tcp_listener *listener) { +static net_stream_conn_or_error hostnet_tcplist_accept(struct hostnet_tcp_listener *listener) { assert(listener); int ret_connfd; + host_errno_t ret_errno; struct hostnet_pthread_accept_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), .listenerfd = listener->fd, .ret_connfd = &ret_connfd, + .ret_errno = &ret_errno, }; - if (RUN_PTHREAD(hostnet_pthread_accept, &args)) - return LO_NULL(net_stream_conn); - + host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_accept, &args); + if (thread_errno) + return ERROR_NEW_ERR(net_stream_conn, errno2lm(thread_errno)); if (ret_connfd < 0) - return LO_NULL(net_stream_conn); + return ERROR_NEW_ERR(net_stream_conn, hostnet_error(ret_errno, OP_RECV)); listener->active_conn.fd = ret_connfd; listener->active_conn.read_deadline_ns = 0; - return LO_BOX(net_stream_conn, &listener->active_conn); + return ERROR_NEW_VAL(net_stream_conn, LO_BOX(net_stream_conn, &listener->active_conn)); } /* TCP listener close() *******************************************************/ -static int hostnet_tcplist_close(struct hostnet_tcp_listener *listener) { +static error hostnet_tcplist_close(struct hostnet_tcp_listener *listener) { assert(listener); - return hostnet_map_negerrno(shutdown(listener->fd, SHUT_RDWR) ? -errno : 0, OP_NONE); + if (shutdown(listener->fd, SHUT_RDWR)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } /* TCP read() *****************************************************************/ @@ -215,29 +222,36 @@ struct hostnet_pthread_readv_args { const struct iovec *iov; int iovcnt; - ssize_t *ret; + size_t *ret_size; + host_errno_t *ret_errno; }; static void *hostnet_pthread_readv(void *_args) { struct hostnet_pthread_readv_args *args = _args; - *(args->ret) = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO, - &args->timeout, sizeof(args->timeout)); - if (*(args->ret) < 0) + int r_i = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO, + &args->timeout, sizeof(args->timeout)); + if (r_i) { + *args->ret_size = 0; + *args->ret_errno = errno; goto end; + } - *(args->ret) = readv(args->connfd, args->iov, args->iovcnt); - if (*(args->ret) < 0) + ssize_t r_ss = readv(args->connfd, args->iov, args->iovcnt); + if (r_ss < 0) { + *args->ret_size = 0; + *args->ret_errno = errno; goto end; + } + *args->ret_size = r_ss; + *args->ret_errno = 0; end: - if (*(args->ret) < 0) - *(args->ret) = hostnet_map_negerrno(-errno, OP_SEND); WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) { +static size_t_or_error hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) { assert(conn); assert(iov); assert(iovcnt > 0); @@ -246,7 +260,8 @@ static ssize_t hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct io count += iov[i].iov_len; assert(count); - ssize_t ret; + size_t ret_size; + host_errno_t ret_errno; struct hostnet_pthread_readv_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), @@ -255,20 +270,26 @@ static ssize_t hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct io .iov = iov, .iovcnt = iovcnt, - .ret = &ret, + .ret_size = &ret_size, + .ret_errno = &ret_errno, }; if (conn->read_deadline_ns) { uint64_t now_ns = LO_CALL(bootclock, get_time_ns); if (conn->read_deadline_ns < now_ns) - return -NET_ERECV_TIMEOUT; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT)); args.timeout = ns_to_host_us_time(conn->read_deadline_ns-now_ns); } else { args.timeout = (host_us_time_t){}; } - if (RUN_PTHREAD(hostnet_pthread_readv, &args)) - return -NET_ETHREAD; - return ret; + host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_readv, &args); + if (thread_errno) + return ERROR_NEW_ERR(size_t, errno2lm(thread_errno)); + if (ret_errno) + return ERROR_NEW_ERR(size_t, hostnet_error(ret_errno, OP_RECV)); + if (!ret_size) + return ERROR_NEW_ERR(size_t, error_new(E_EOF)); + return ERROR_NEW_VAL(size_t, ret_size); } /* TCP write() ****************************************************************/ @@ -281,7 +302,8 @@ struct hostnet_pthread_writev_args { const struct iovec *iov; int iovcnt; - ssize_t *ret; + size_t *ret_size; + host_errno_t *ret_errno; }; static void *hostnet_pthread_writev(void *_args) { @@ -299,7 +321,7 @@ static void *hostnet_pthread_writev(void *_args) { while (done < count) { ssize_t r = writev(args->connfd, iov, iovcnt); if (r < 0) { - hostnet_map_negerrno(-errno, OP_RECV); + *args->ret_errno = errno; break; } done += r; @@ -314,12 +336,13 @@ static void *hostnet_pthread_writev(void *_args) { } } if (done == count) - *(args->ret) = done; + *args->ret_errno = 0; + *args->ret_size = done; WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) { +static size_t_and_error hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) { assert(conn); assert(iov); assert(iovcnt > 0); @@ -328,7 +351,8 @@ static ssize_t hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct i count += iov[i].iov_len; assert(count); - ssize_t ret; + size_t ret_size; + host_errno_t ret_errno; struct hostnet_pthread_writev_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), @@ -337,26 +361,34 @@ static ssize_t hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct i .iov = iov, .iovcnt = iovcnt, - .ret = &ret, + .ret_size = &ret_size, + .ret_errno = &ret_errno, }; - if (RUN_PTHREAD(hostnet_pthread_writev, &args)) - return -NET_ETHREAD; - return ret; + int thread_errno = RUN_PTHREAD(hostnet_pthread_writev, &args); + if (thread_errno) + return ERROR_AND(size_t, 0, errno2lm(thread_errno)); + return ERROR_AND(size_t, ret_size, ret_errno ? hostnet_error(ret_errno, OP_SEND) : ERROR_NULL); } /* TCP close() ****************************************************************/ -static int hostnet_tcp_close(struct _hostnet_tcp_conn *conn) { +static error hostnet_tcp_close(struct _hostnet_tcp_conn *conn) { assert(conn); - return hostnet_map_negerrno(shutdown(conn->fd, SHUT_RDWR) ? -errno : 0, OP_NONE); + if (shutdown(conn->fd, SHUT_RDWR)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } -static int hostnet_tcp_close_read(struct _hostnet_tcp_conn *conn) { +static error hostnet_tcp_close_read(struct _hostnet_tcp_conn *conn) { assert(conn); - return hostnet_map_negerrno(shutdown(conn->fd, SHUT_RD) ? -errno : 0, OP_NONE); + if (shutdown(conn->fd, SHUT_RD)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } -static int hostnet_tcp_close_write(struct _hostnet_tcp_conn *conn) { +static error hostnet_tcp_close_write(struct _hostnet_tcp_conn *conn) { assert(conn); - return hostnet_map_negerrno(shutdown(conn->fd, SHUT_WR) ? -errno : 0, OP_NONE); + if (shutdown(conn->fd, SHUT_WR)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } /* UDP init() *****************************************************************/ @@ -375,11 +407,11 @@ void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) { addr.in.sin_port = htons(port); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) - error(1, errno, "socket"); + __error(1, errno, "socket"); if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &(int){1}, sizeof(int)) < 0) - error(1, errno, "setsockopt(fd=%d, SO_BROADCAST=1)", fd); + __error(1, errno, "setsockopt(fd=%d, SO_BROADCAST=1)", fd); if (bind(fd, &addr.gen, sizeof addr) < 0) - error(1, errno, "bind"); + __error(1, errno, "bind"); self->fd = fd; self->read_deadline_ns = 0; @@ -397,7 +429,8 @@ struct hostnet_pthread_sendto_args { struct net_ip4_addr node; uint16_t port; - ssize_t *ret; + size_t *ret_size; + host_errno_t *ret_errno; }; static void *hostnet_pthread_sendto(void *_args) { @@ -415,18 +448,24 @@ static void *hostnet_pthread_sendto(void *_args) { (((uint32_t)args->node.octets[1])<< 8) | (((uint32_t)args->node.octets[0])<< 0) ; addr.in.sin_port = htons(args->port); - *(args->ret) = sendto(args->connfd, args->buf, args->count, 0, &addr.gen, sizeof(addr)); - if (*(args->ret) < 0) - *(args->ret) = hostnet_map_negerrno(-errno, OP_SEND); + ssize_t r = sendto(args->connfd, args->buf, args->count, 0, &addr.gen, sizeof(addr)); + if (r < 0) { + *args->ret_size = 0; + *args->ret_errno = errno; + } else { + *args->ret_size = r; + *args->ret_errno = 0; + } WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size_t count, - struct net_ip4_addr node, uint16_t port) { +static error hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size_t count, + struct net_ip4_addr node, uint16_t port) { assert(conn); - ssize_t ret; + size_t ret_size; + host_errno_t ret_errno; struct hostnet_pthread_sendto_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), @@ -437,11 +476,15 @@ static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size .node = node, .port = port, - .ret = &ret, + .ret_size = &ret_size, + .ret_errno = &ret_errno, }; - if (RUN_PTHREAD(hostnet_pthread_sendto, &args)) - return -NET_ETHREAD; - return ret; + int thread_errno = RUN_PTHREAD(hostnet_pthread_sendto, &args); + if (thread_errno) + return errno2lm(thread_errno); + if (ret_errno) + return hostnet_error(ret_errno, OP_SEND); + return ERROR_NULL; } /* UDP recvfrom() *************************************************************/ @@ -462,7 +505,8 @@ struct hostnet_pthread_recvfrom_args { void *buf; size_t count; - ssize_t *ret_size; + size_t *ret_size; + host_errno_t *ret_errno; struct net_ip4_addr *ret_node; uint16_t *ret_port; }; @@ -477,15 +521,23 @@ static void *hostnet_pthread_recvfrom(void *_args) { } addr = {}; socklen_t addr_size = sizeof(addr); - *(args->ret_size) = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO, - &args->timeout, sizeof(args->timeout)); - if (*(args->ret_size) < 0) + int r_i = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO, + &args->timeout, sizeof(args->timeout)); + if (r_i) { + *args->ret_size = 0; + *args->ret_errno = errno; goto end; + } - *(args->ret_size) = recvfrom(args->connfd, args->buf, args->count, - MSG_TRUNC, &addr.gen, &addr_size); - if (*(args->ret_size) < 0) + ssize_t r_ss = recvfrom(args->connfd, args->buf, args->count, + MSG_TRUNC, &addr.gen, &addr_size); + if (r_ss < 0) { + *args->ret_size = 0; + *args->ret_errno = errno; goto end; + } + *args->ret_size = r_ss; + *args->ret_errno = 0; assert(addr.in.sin_family == AF_INET); if (args->ret_node) { @@ -499,17 +551,16 @@ static void *hostnet_pthread_recvfrom(void *_args) { } end: - if (*(args->ret_size) < 0) - *(args->ret_size) = hostnet_map_negerrno(-errno, OP_RECV); WAKE_COROUTINE(args); return NULL; } -static ssize_t hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, size_t count, - struct net_ip4_addr *ret_node, uint16_t *ret_port) { +static size_t_or_error hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, size_t count, + struct net_ip4_addr *ret_node, uint16_t *ret_port) { assert(conn); - ssize_t ret; + size_t ret_size; + host_errno_t ret_errno; struct hostnet_pthread_recvfrom_args args = { .cr_thread = pthread_self(), .cr_coroutine = cr_getcid(), @@ -518,28 +569,34 @@ static ssize_t hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, si .buf = buf, .count = count, - .ret_size = &ret, + .ret_size = &ret_size, + .ret_errno = &ret_errno, .ret_node = ret_node, .ret_port = ret_port, }; if (conn->read_deadline_ns) { uint64_t now_ns = LO_CALL(bootclock, get_time_ns); if (conn->read_deadline_ns < now_ns) - return -NET_ERECV_TIMEOUT; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT)); args.timeout = ns_to_host_us_time(conn->read_deadline_ns-now_ns); } else { args.timeout = (host_us_time_t){}; } - if (RUN_PTHREAD(hostnet_pthread_recvfrom, &args)) - return -NET_ETHREAD; - return ret; + host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_recvfrom, &args); + if (thread_errno) + return ERROR_NEW_ERR(size_t, errno2lm(thread_errno)); + if (ret_errno) + return ERROR_NEW_ERR(size_t, hostnet_error(ret_errno, OP_RECV)); + return ERROR_NEW_VAL(size_t, ret_size); } /* UDP close() ****************************************************************/ -static int hostnet_udp_close(struct hostnet_udp_conn *conn) { +static error hostnet_udp_close(struct hostnet_udp_conn *conn) { assert(conn); - return hostnet_map_negerrno(close(conn->fd) ? -errno : 0, OP_NONE); + if (close(conn->fd)) + return hostnet_error(errno, OP_CLOSE); + return ERROR_NULL; } diff --git a/libhw_cr/host_util.c b/libhw_cr/host_util.c index 8cacd57..2d45490 100644 --- a/libhw_cr/host_util.c +++ b/libhw_cr/host_util.c @@ -4,9 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include <error.h> /* for error(3gnu) */ +#include <errno.h> /* for E* */ #include <signal.h> /* for SIGRTMIN, SIGRTMAX */ +#define error __error +#include <error.h> +#undef error + #include <libhw/generic/alarmclock.h> /* for {X}S_PER_S */ #include "host_util.h" @@ -18,7 +22,7 @@ int host_sigrt_alloc(void) { next = SIGRTMIN; int ret = next++; if (ret > SIGRTMAX) - error(1, 0, "SIGRTMAX exceeded"); + __error(1, 0, "SIGRTMAX exceeded"); return ret; } @@ -48,3 +52,94 @@ uint64_t ns_from_host_ns_time(host_ns_time_t host_time) { return (((uint64_t)host_time.tv_sec) * NS_PER_S) + ((uint64_t)host_time.tv_nsec); } + +_errnum errno_host2lm(host_errno_t host) { + switch (host) { + case E2BIG: return E_POSIX_E2BIG; + case EACCES: return E_POSIX_EACCES; + case EADDRINUSE: return E_POSIX_EADDRINUSE; + case EADDRNOTAVAIL: return E_POSIX_EADDRNOTAVAIL; + case EAFNOSUPPORT: return E_POSIX_EAFNOSUPPORT; + case EAGAIN: return E_POSIX_EAGAIN; + case EALREADY: return E_POSIX_EALREADY; + case EBADF: return E_POSIX_EBADF; + case EBADMSG: return E_POSIX_EBADMSG; + case EBUSY: return E_POSIX_EBUSY; + case ECANCELED: return E_POSIX_ECANCELED; + case ECHILD: return E_POSIX_ECHILD; + case ECONNABORTED: return E_POSIX_ECONNABORTED; + case ECONNREFUSED: return E_POSIX_ECONNREFUSED; + case ECONNRESET: return E_POSIX_ECONNRESET; + case EDEADLK: return E_POSIX_EDEADLK; + case EDESTADDRREQ: return E_POSIX_EDESTADDRREQ; + case EDOM: return E_POSIX_EDOM; + case EDQUOT: return E_POSIX_EDQUOT; + case EEXIST: return E_POSIX_EEXIST; + case EFAULT: return E_POSIX_EFAULT; + case EFBIG: return E_POSIX_EFBIG; + case EHOSTUNREACH: return E_POSIX_EHOSTUNREACH; + case EIDRM: return E_POSIX_EIDRM; + case EILSEQ: return E_POSIX_EILSEQ; + case EINPROGRESS: return E_POSIX_EINPROGRESS; + case EINTR: return E_POSIX_EINTR; + case EINVAL: return E_POSIX_EINVAL; + case EIO: return E_POSIX_EIO; + case EISCONN: return E_POSIX_EISCONN; + case EISDIR: return E_POSIX_EISDIR; + case ELOOP: return E_POSIX_ELOOP; + case EMFILE: return E_POSIX_EMFILE; + case EMLINK: return E_POSIX_EMLINK; + case EMSGSIZE: return E_POSIX_EMSGSIZE; + case EMULTIHOP: return E_POSIX_EMULTIHOP; + case ENAMETOOLONG: return E_POSIX_ENAMETOOLONG; + case ENETDOWN: return E_POSIX_ENETDOWN; + case ENETRESET: return E_POSIX_ENETRESET; + case ENETUNREACH: return E_POSIX_ENETUNREACH; + case ENFILE: return E_POSIX_ENFILE; + case ENOBUFS: return E_POSIX_ENOBUFS; + case ENODEV: return E_POSIX_ENODEV; + case ENOENT: return E_POSIX_ENOENT; + case ENOEXEC: return E_POSIX_ENOEXEC; + case ENOLCK: return E_POSIX_ENOLCK; + case ENOLINK: return E_POSIX_ENOLINK; + case ENOMEM: return E_POSIX_ENOMEM; + case ENOMSG: return E_POSIX_ENOMSG; + case ENOPROTOOPT: return E_POSIX_ENOPROTOOPT; + case ENOSPC: return E_POSIX_ENOSPC; + case ENOSYS: return E_POSIX_ENOSYS; + case ENOTCONN: return E_POSIX_ENOTCONN; + case ENOTDIR: return E_POSIX_ENOTDIR; + case ENOTEMPTY: return E_POSIX_ENOTEMPTY; + case ENOTRECOVERABLE: return E_POSIX_ENOTRECOVERABLE; + case ENOTSOCK: return E_POSIX_ENOTSOCK; + case ENOTSUP: return E_POSIX_ENOTSUP; + case ENOTTY: return E_POSIX_ENOTTY; + case ENXIO: return E_POSIX_ENXIO; + case EOVERFLOW: return E_POSIX_EOVERFLOW; + case EOWNERDEAD: return E_POSIX_EOWNERDEAD; + case EPERM: return E_POSIX_EPERM; + case EPIPE: return E_POSIX_EPIPE; + case EPROTO: return E_POSIX_EPROTO; + case EPROTONOSUPPORT: return E_POSIX_EPROTONOSUPPORT; + case EPROTOTYPE: return E_POSIX_EPROTOTYPE; + case ERANGE: return E_POSIX_ERANGE; + case EROFS: return E_POSIX_EROFS; + case ESOCKTNOSUPPORT: return E_POSIX_ESOCKTNOSUPPORT; + case ESPIPE: return E_POSIX_ESPIPE; + case ESRCH: return E_POSIX_ESRCH; + case ESTALE: return E_POSIX_ESTALE; + case ETIMEDOUT: return E_POSIX_ETIMEDOUT; + case ETXTBSY: return E_POSIX_ETXTBSY; + case EXDEV: return E_POSIX_EXDEV; + default: + switch (host) { + case EOPNOTSUPP: return E_POSIX_EOPNOTSUPP; + case EWOULDBLOCK: return E_POSIX_EWOULDBLOCK; + default: return E_EUNKNOWN; + } + } +} + +error errno2lm(host_errno_t host) { + return error_new(errno_host2lm(host)); +} diff --git a/libhw_cr/host_util.h b/libhw_cr/host_util.h index 4adb94e..7e559ef 100644 --- a/libhw_cr/host_util.h +++ b/libhw_cr/host_util.h @@ -11,6 +11,8 @@ #include <sys/time.h> /* for struct timeval */ #include <time.h> /* for struct timespec */ +#include <libmisc/error.h> /* for _errnum, error */ + int host_sigrt_alloc(void); typedef struct timeval host_us_time_t; @@ -21,4 +23,8 @@ host_ns_time_t ns_to_host_ns_time(uint64_t time_ns); uint64_t ns_from_host_us_time(host_us_time_t host_time); uint64_t ns_from_host_ns_time(host_ns_time_t host_time); +#define host_errno_t int +_errnum errno_host2lm(host_errno_t host); +error errno2lm(host_errno_t host); + #endif /* _LIBHW_CR_HOST_UTIL_H_ */ diff --git a/libhw_cr/rp2040_hwspi.c b/libhw_cr/rp2040_hwspi.c index a7840e8..d717a79 100644 --- a/libhw_cr/rp2040_hwspi.c +++ b/libhw_cr/rp2040_hwspi.c @@ -136,7 +136,7 @@ void _rp2040_hwspi_init(struct rp2040_hwspi *self, dmairq_set_and_enable_exclusive_handler(DMAIRQ_0, self->dma_rx_data, rp2040_hwspi_intrhandler, self); } -static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct duplex_iovec *iov, int iovcnt) { +static size_t_and_error rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct duplex_iovec *iov, int iovcnt) { assert(self); assert(self->inst); assert(iov); @@ -268,4 +268,5 @@ static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct dupl cr_restore_interrupts(saved); cr_sema_wait(&self->sema); self->dead_until_ns = LO_CALL(bootclock, get_time_ns) + self->min_delay_ns; + return ERROR_AND(size_t, count, ERROR_NULL); } diff --git a/libhw_cr/w5500.c b/libhw_cr/w5500.c index 58715c9..594b391 100644 --- a/libhw_cr/w5500.c +++ b/libhw_cr/w5500.c @@ -462,8 +462,8 @@ static lo_interface net_stream_listener w5500_if_tcp_listen(struct w5500 *chip, return LO_BOX(net_stream_listener, sock); } -static lo_interface net_stream_conn w5500_if_tcp_dial(struct w5500 *chip, - struct net_ip4_addr node, uint16_t port) { +static net_stream_conn_or_error w5500_if_tcp_dial(struct w5500 *chip, + struct net_ip4_addr node, uint16_t port) { assert(chip); assert(memcmp(node.octets, net_ip4_addr_zero.octets, 4)); assert(memcmp(node.octets, net_ip4_addr_broadcast.octets, 4)); @@ -472,7 +472,7 @@ static lo_interface net_stream_conn w5500_if_tcp_dial(struct w5500 *chip, struct _w5500_socket *socket = w5500_alloc_socket(chip); if (!socket) { log_debugln("tcp_dial() => no sock"); - return LO_NULL(net_stream_conn); + return ERROR_NEW_ERR(net_stream_conn, error_new(E_POSIX_ENOTSOCK)); } uint8_t socknum = socket->socknum; log_debugln("tcp_dial() => sock[", socknum, "]"); @@ -509,7 +509,7 @@ static lo_interface net_stream_conn w5500_if_tcp_dial(struct w5500 *chip, cr_yield(); break; case STATE_TCP_ESTABLISHED: - return LO_BOX(net_stream_conn, socket); + return ERROR_NEW_VAL(net_stream_conn, LO_BOX(net_stream_conn, socket)); default: goto restart; } @@ -559,20 +559,20 @@ static bool w5500_if_arp_ping(struct w5500 *chip, struct net_ip4_addr addr) { sock = &chip->sockets[i]; } assert(sock); - ssize_t v = w5500_udp_sendto(sock, "BOGUS_PACKET_TO_TRIGGER_AN_ARP", 17, addr, 5000); - log_debugln("arp_ping => ", v); - return v != -NET_EARP_TIMEOUT; + error err = w5500_udp_sendto(sock, "BOGUS_PACKET_TO_TRIGGER_AN_ARP", 17, addr, 5000); + log_debugln("arp_ping => ", (error, err)); + return err.num != E_NET_EARP_TIMEOUT; } /* tcp_listener methods *******************************************************/ -static lo_interface net_stream_conn w5500_tcplist_accept(struct _w5500_socket *socket) { +static net_stream_conn_or_error w5500_tcplist_accept(struct _w5500_socket *socket) { ASSERT_SELF(stream_listener, TCP); restart: if (!socket->list_open) { log_debugln("tcp_listener.accept() => already closed"); - return LO_NULL(net_stream_conn); + return ERROR_NEW_ERR(net_stream_conn, error_new(E_NET_ECLOSED)); } cr_mutex_lock(&chip->mu); @@ -601,25 +601,25 @@ static lo_interface net_stream_conn w5500_tcplist_accept(struct _w5500_socket *s [[fallthrough]]; case STATE_TCP_CLOSE_WAIT: socket->write_open = true; - return LO_BOX(net_stream_conn, socket); + return ERROR_NEW_VAL(net_stream_conn, LO_BOX(net_stream_conn, socket)); default: goto restart; } } } -static int w5500_tcplist_close(struct _w5500_socket *socket) { +static error w5500_tcplist_close(struct _w5500_socket *socket) { log_debugln("tcp_listener.close()"); ASSERT_SELF(stream_listener, TCP); socket->list_open = false; w5500_tcp_maybe_free(chip, socket); - return 0; + return ERROR_NULL; } /* tcp_conn methods ***********************************************************/ -static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) { +static size_t_and_error w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) { assert(iov); assert(iovcnt > 0); size_t count = 0; @@ -653,14 +653,14 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec while (done < count) { if (!socket->write_open) { log_debugln(" => soft closed"); - return -NET_ECLOSED; + return ERROR_AND(size_t, done, error_new(E_NET_ECLOSED)); } cr_mutex_lock(&chip->mu); uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state); if (state != STATE_TCP_ESTABLISHED && state != STATE_TCP_CLOSE_WAIT) { cr_mutex_unlock(&chip->mu); log_debugln(" => hard closed"); - return -NET_ECLOSED; + return ERROR_AND(size_t, done, error_new(E_NET_ECLOSED)); } uint16_t freesize = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_free_size)); @@ -689,7 +689,7 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec break; case SOCKINTR_SEND_TIMEOUT: log_debugln(" => ACK timeout"); - return -NET_EACK_TIMEOUT; + return ERROR_AND(size_t, done, error_new(E_NET_EACK_TIMEOUT)); case SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT: assert_notreached("send both OK and timed out?"); default: @@ -697,7 +697,7 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec } } log_debugln(" => send finished"); - return done; + return ERROR_AND(size_t, done, ERROR_NULL); } static void w5500_tcp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) { @@ -711,7 +711,7 @@ static void w5500_tcp_alarm_handler(void *_arg) { cr_sema_signal_from_intrhandler(&socket->read_sema); } -static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) { +static size_t_or_error w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) { assert(iov); assert(iovcnt > 0); size_t count = 0; @@ -734,12 +734,12 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec if (!socket->read_open) { LO_CALL(bootclock, del_trigger, &trigger); log_debugln(" => soft closed"); - return -NET_ECLOSED; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ECLOSED)); } if (socket->read_deadline_ns && socket->read_deadline_ns <= LO_CALL(bootclock, get_time_ns)) { LO_CALL(bootclock, del_trigger, &trigger); log_debugln(" => recv timeout"); - return -NET_ERECV_TIMEOUT; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT)); } cr_mutex_lock(&chip->mu); uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state); @@ -752,7 +752,7 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec LO_CALL(bootclock, del_trigger, &trigger); cr_mutex_unlock(&chip->mu); log_debugln(" => hard closed"); - return -NET_ECLOSED; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ECLOSED)); } avail = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_size)); @@ -763,7 +763,7 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec LO_CALL(bootclock, del_trigger, &trigger); cr_mutex_unlock(&chip->mu); log_debugln(" => EOF"); - return 0; + return ERROR_NEW_ERR(size_t, error_new(E_EOF)); } cr_mutex_unlock(&chip->mu); @@ -782,10 +782,10 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec /* Return. */ LO_CALL(bootclock, del_trigger, &trigger); cr_mutex_unlock(&chip->mu); - return avail; + return ERROR_NEW_VAL(size_t, avail); } -static int w5500_tcp_close_inner(struct _w5500_socket *socket, bool rd, bool wr) { +static error w5500_tcp_close_inner(struct _w5500_socket *socket, bool rd, bool wr) { log_debugln("tcp_conn.close(rd=", rd, ", wr=", wr, ")"); ASSERT_SELF(stream_conn, TCP); @@ -813,17 +813,17 @@ static int w5500_tcp_close_inner(struct _w5500_socket *socket, bool rd, bool wr) } w5500_tcp_maybe_free(chip, socket); - return 0; + return ERROR_NULL; } -static int w5500_tcp_close(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, true); } -static int w5500_tcp_close_read(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, false); } -static int w5500_tcp_close_write(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, false, true); } +static error w5500_tcp_close(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, true); } +static error w5500_tcp_close_read(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, false); } +static error w5500_tcp_close_write(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, false, true); } /* udp_conn methods ***********************************************************/ -static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count, - struct net_ip4_addr node, uint16_t port) { +static error w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count, + struct net_ip4_addr node, uint16_t port) { log_debugln("udp_conn.sendto()"); ASSERT_SELF(packet_conn, UDP); assert(buf); @@ -832,7 +832,7 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t uint16_t bufsize = ((uint16_t)w5500ll_read_sock_reg(chip->spidev, socknum, tx_buf_size))*1024; if (count > bufsize) { log_debugln(" => msg too large"); - return -NET_EMSGSIZE; + return error_new(E_POSIX_EMSGSIZE); } for (;;) { @@ -841,7 +841,7 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t if (state != STATE_UDP) { cr_mutex_unlock(&chip->mu); log_debugln(" => closed"); - return -NET_ECLOSED; + return error_new(E_NET_ECLOSED); } uint16_t freesize = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_free_size)); @@ -871,10 +871,10 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t switch (cr_chan_recv(&socket->write_ch)) { case SOCKINTR_SEND_OK: log_debugln(" => sent"); - return count; + return ERROR_NULL; case SOCKINTR_SEND_TIMEOUT: log_debugln(" => ARP timeout"); - return -NET_EARP_TIMEOUT; + return error_new(E_NET_EARP_TIMEOUT); case SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT: assert_notreached("send both OK and timed out?"); default: @@ -893,8 +893,8 @@ static void w5500_udp_alarm_handler(void *_arg) { cr_sema_signal_from_intrhandler(&socket->read_sema); } -static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_t count, - struct net_ip4_addr *ret_node, uint16_t *ret_port) { +static size_t_or_error w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_t count, + struct net_ip4_addr *ret_node, uint16_t *ret_port) { log_debugln("udp_conn.recvfrom()"); ASSERT_SELF(packet_conn, UDP); assert(buf); @@ -913,14 +913,14 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_ if (socket->read_deadline_ns && socket->read_deadline_ns <= LO_CALL(bootclock, get_time_ns)) { LO_CALL(bootclock, del_trigger, &trigger); log_debugln(" => recv timeout"); - return -NET_ERECV_TIMEOUT; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT)); } cr_mutex_lock(&chip->mu); uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state); if (state != STATE_UDP) { LO_CALL(bootclock, del_trigger, &trigger); log_debugln(" => hard closed"); - return -NET_ECLOSED; + return ERROR_NEW_ERR(size_t, error_new(E_NET_ECLOSED)); } avail = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_size)); @@ -964,14 +964,14 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_ /* Return. */ LO_CALL(bootclock, del_trigger, &trigger); cr_mutex_unlock(&chip->mu); - return len; + return ERROR_NEW_VAL(size_t, len); } -static int w5500_udp_close(struct _w5500_socket *socket) { +static error w5500_udp_close(struct _w5500_socket *socket) { log_debugln("udp_conn.close()"); ASSERT_SELF(packet_conn, UDP); w5500_socket_close(socket); w5500_free_socket(chip, socket); - return 0; + return ERROR_NULL; } diff --git a/libhw_generic/include/libhw/generic/io.h b/libhw_generic/include/libhw/generic/io.h index 8b3fb9c..ebbd6cb 100644 --- a/libhw_generic/include/libhw/generic/io.h +++ b/libhw_generic/include/libhw/generic/io.h @@ -9,8 +9,8 @@ #include <stddef.h> /* for size_t */ #include <stdint.h> /* for uintptr_t */ -#include <sys/types.h> /* for ssize_t */ +#include <libmisc/error.h> #include <libmisc/obj.h> /* structs ********************************************************************/ @@ -58,20 +58,19 @@ void io_slice_wr_to_duplex(struct duplex_iovec *dst, const struct iovec *src, in /* basic interfaces ***********************************************************/ /** - * Return bytes-read on success, 0 on EOF, -errno on error; a short - * read is *not* an error. + * Return bytes-read on success. A short read is *not* an error + * (unlike writev). * * It is invalid to call readv when the sum length of iovecs is 0. */ #define io_reader_LO_IFACE \ - LO_FUNC(ssize_t, readv, const struct iovec *iov, int iovcnt) + LO_FUNC(size_t_or_error, readv, const struct iovec *iov, int iovcnt) LO_INTERFACE(io_reader); #define io_readv(r, iov, iovcnt) LO_CALL(r, readv, iov, iovcnt) #define io_read(r, buf, count) LO_CALL(r, readv, &((struct iovec){.iov_base = buf, .iov_len = count}), 1) /** - * Return `count` on success, -errno on error; a short write *is* an - * error. + * Return bytes-written. A short write *is* an error (unlike readv) * * Writes are *not* guaranteed to be atomic, so if you have concurrent * writers then you should arrange for a mutex to protect the writer. @@ -79,38 +78,35 @@ LO_INTERFACE(io_reader); * It is invalid to call writev when the sum length of iovecs is 0. */ #define io_writer_LO_IFACE \ - LO_FUNC(ssize_t, writev, const struct iovec *iov, int iovcnt) + LO_FUNC(size_t_and_error, writev, const struct iovec *iov, int iovcnt) LO_INTERFACE(io_writer); #define io_writev(w, iov, iovcnt) LO_CALL(w, writev, iov, iovcnt) #define io_write(w, buf, count) LO_CALL(w, writev, &((struct iovec){.iov_base = buf, .iov_len = count}), 1) -/** - * Return 0 on success, -errno on error. - */ #define io_closer_LO_IFACE \ - LO_FUNC(int, close) + LO_FUNC(error, close) LO_INTERFACE(io_closer); #define io_close(c) LO_CALL(c, close) -/** - * All methods return 0 on success, -errno on error. - */ #define io_bidi_closer_LO_IFACE \ LO_NEST(io_closer) \ - LO_FUNC(int, close_read) \ - LO_FUNC(int, close_write) + LO_FUNC(error, close_read) \ + LO_FUNC(error, close_write) LO_INTERFACE(io_bidi_closer); #define io_close_read(c) LO_CALL(c, close_read) #define io_close_write(c) LO_CALL(c, close_write) /** - * Return bytes-read and bytes-written on success, -errno on error; a - * short read/write *is* an error. + * A short read/write *is* an error (like writev and unlike readv). + * + * Reads/writes are *not* guaranteed to be atomic, so if you have + * concurrent readers/writers then you should arrange for a mutex to + * protect the duplex_readwriter. * * It is invalid to call readwritev when the sum length of iovecs is 0. */ #define io_duplex_readwriter_LO_IFACE \ - LO_FUNC(void, readwritev, const struct duplex_iovec *iov, int iovcnt) + LO_FUNC(size_t_and_error, readwritev, const struct duplex_iovec *iov, int iovcnt) LO_INTERFACE(io_duplex_readwriter); #define io_readwritev(rw, iov, iovcnt) \ diff --git a/libhw_generic/include/libhw/generic/net.h b/libhw_generic/include/libhw/generic/net.h index 55e4a6f..d1d4194 100644 --- a/libhw_generic/include/libhw/generic/net.h +++ b/libhw_generic/include/libhw/generic/net.h @@ -9,23 +9,10 @@ #include <stddef.h> /* for size_t */ #include <stdint.h> /* for uint{n}_t} */ -#include <sys/types.h> /* for ssize_t */ #include <libhw/generic/io.h> #include <libmisc/fmt.h> -/* Errnos *********************************************************************/ - -#define NET_EOTHER 1 -#define NET_EARP_TIMEOUT 2 -#define NET_EACK_TIMEOUT 3 -#define NET_ERECV_TIMEOUT 4 -#define NET_ETHREAD 5 -#define NET_ECLOSED 6 -#define NET_EMSGSIZE 7 - -const char *net_strerror(int net_errno); - /* Address types **************************************************************/ struct net_ip4_addr { @@ -44,22 +31,6 @@ void fmt_print_net_eth_addr(lo_interface fmt_dest, struct net_eth_addr); /* Streams (e.g. TCP) *********************************************************/ -lo_interface net_stream_conn; - -#define net_stream_listener_LO_IFACE \ - /** \ - * It is invalid to accept() a new connection if an existing \ - * connection is still open. \ - */ \ - LO_FUNC(lo_interface net_stream_conn, accept) \ - \ - /** \ - * The net_stream_conn returned from accept() may still be \ - * valid after the listener is closed. \ - */ \ - LO_NEST(io_closer) -LO_INTERFACE(net_stream_listener); - #define net_stream_conn_LO_IFACE \ LO_NEST(io_readwriter) \ LO_NEST(io_bidi_closer) \ @@ -78,10 +49,27 @@ LO_INTERFACE(net_stream_listener); LO_FUNC(void, set_read_deadline, uint64_t ns_since_boot) LO_INTERFACE(net_stream_conn); +typedef lo_interface net_stream_conn net_stream_conn; +DECLARE_ERROR_OR(net_stream_conn); + +#define net_stream_listener_LO_IFACE \ + /** \ + * It is invalid to accept() a new connection if an existing \ + * connection is still open. \ + */ \ + LO_FUNC(net_stream_conn_or_error, accept) \ + \ + /** \ + * The net_stream_conn returned from accept() may still be \ + * valid after the listener is closed. \ + */ \ + LO_NEST(io_closer) +LO_INTERFACE(net_stream_listener); + /* Packets (e.g. UDP) *********************************************************/ #define net_packet_conn_LO_IFACE \ - LO_FUNC(ssize_t, sendto, \ + LO_FUNC(error, sendto, \ void *buf, size_t len, \ struct net_ip4_addr node, uint16_t port) \ \ @@ -90,7 +78,7 @@ LO_INTERFACE(net_stream_conn); * than the given `len` (as if the Linux MSG_TRUNC flag were \ * given). \ */ \ - LO_FUNC(ssize_t, recvfrom, \ + LO_FUNC(size_t_or_error, recvfrom, \ void *buf, size_t len, \ struct net_ip4_addr *ret_node, uint16_t *ret_port) \ \ @@ -125,7 +113,7 @@ struct net_iface_config { LO_FUNC(void , ifdown ) \ \ LO_FUNC(lo_interface net_stream_listener, tcp_listen, uint16_t local_port) \ - LO_FUNC(lo_interface net_stream_conn , tcp_dial , struct net_ip4_addr remote_node, uint16_t remote_port) \ + LO_FUNC(net_stream_conn_or_error , tcp_dial , struct net_ip4_addr remote_node, uint16_t remote_port) \ LO_FUNC(lo_interface net_packet_conn , udp_conn , uint16_t local_port) \ \ /** FIXME: arp_ping should probably have an explicit timeout or something. */ \ diff --git a/libmisc/CMakeLists.txt b/libmisc/CMakeLists.txt index 07f154b..9bb282b 100644 --- a/libmisc/CMakeLists.txt +++ b/libmisc/CMakeLists.txt @@ -8,6 +8,8 @@ target_include_directories(libmisc PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/ target_sources(libmisc INTERFACE assert.c endian.c + error.c + error_generated.c fmt.c hash.c intercept.c diff --git a/libmisc/error.c b/libmisc/error.c new file mode 100644 index 0000000..dfe4e80 --- /dev/null +++ b/libmisc/error.c @@ -0,0 +1,26 @@ +/* libmisc/error.c - Go-esque errors + * + * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <libmisc/error.h> + +const char *error_msg(error err) { + return (err._msg && err._msg[0]) + ? err._msg + : _errnum_str_msg(err.num); +} + +void error_cleanup(error *errptr) { + if (!errptr) + return; + if (errptr->_msg) + free(errptr->_msg); + errptr->num = E_NOERROR; + errptr->_msg = NULL; +} + +void fmt_print_error(lo_interface fmt_dest w, error err) { + fmt_print(w, (str, error_msg(err)), " (", _errnum_str_sym(err.num), ")"); +} diff --git a/libmisc/error_generated.c b/libmisc/error_generated.c new file mode 100644 index 0000000..e0afcab --- /dev/null +++ b/libmisc/error_generated.c @@ -0,0 +1,186 @@ +/* libmisc/error_generated.c - Generated by libmisc/error_generated.c.gen. DO NOT EDIT! */ + +#include <libmisc/error.h> + +const char *_errnum_str_sym(_errnum errnum) { + switch (errnum) { + case E_NOERROR: return "E_NOERROR"; + case E_EOF: return "E_EOF"; + case E_NET_EARP_TIMEOUT: return "E_NET_EARP_TIMEOUT"; + case E_NET_EACK_TIMEOUT: return "E_NET_EACK_TIMEOUT"; + case E_NET_ERECV_TIMEOUT: return "E_NET_ERECV_TIMEOUT"; + case E_NET_ECLOSED: return "E_NET_ECLOSED"; + case E_POSIX_E2BIG: return "E_POSIX_E2BIG"; + case E_POSIX_EACCES: return "E_POSIX_EACCES"; + case E_POSIX_EADDRINUSE: return "E_POSIX_EADDRINUSE"; + case E_POSIX_EADDRNOTAVAIL: return "E_POSIX_EADDRNOTAVAIL"; + case E_POSIX_EAFNOSUPPORT: return "E_POSIX_EAFNOSUPPORT"; + case E_POSIX_EAGAIN: return "E_POSIX_EAGAIN"; + case E_POSIX_EALREADY: return "E_POSIX_EALREADY"; + case E_POSIX_EBADF: return "E_POSIX_EBADF"; + case E_POSIX_EBADMSG: return "E_POSIX_EBADMSG"; + case E_POSIX_EBUSY: return "E_POSIX_EBUSY"; + case E_POSIX_ECANCELED: return "E_POSIX_ECANCELED"; + case E_POSIX_ECHILD: return "E_POSIX_ECHILD"; + case E_POSIX_ECONNABORTED: return "E_POSIX_ECONNABORTED"; + case E_POSIX_ECONNREFUSED: return "E_POSIX_ECONNREFUSED"; + case E_POSIX_ECONNRESET: return "E_POSIX_ECONNRESET"; + case E_POSIX_EDEADLK: return "E_POSIX_EDEADLK"; + case E_POSIX_EDESTADDRREQ: return "E_POSIX_EDESTADDRREQ"; + case E_POSIX_EDOM: return "E_POSIX_EDOM"; + case E_POSIX_EDQUOT: return "E_POSIX_EDQUOT"; + case E_POSIX_EEXIST: return "E_POSIX_EEXIST"; + case E_POSIX_EFAULT: return "E_POSIX_EFAULT"; + case E_POSIX_EFBIG: return "E_POSIX_EFBIG"; + case E_POSIX_EHOSTUNREACH: return "E_POSIX_EHOSTUNREACH"; + case E_POSIX_EIDRM: return "E_POSIX_EIDRM"; + case E_POSIX_EILSEQ: return "E_POSIX_EILSEQ"; + case E_POSIX_EINPROGRESS: return "E_POSIX_EINPROGRESS"; + case E_POSIX_EINTR: return "E_POSIX_EINTR"; + case E_POSIX_EINVAL: return "E_POSIX_EINVAL"; + case E_POSIX_EIO: return "E_POSIX_EIO"; + case E_POSIX_EISCONN: return "E_POSIX_EISCONN"; + case E_POSIX_EISDIR: return "E_POSIX_EISDIR"; + case E_POSIX_ELOOP: return "E_POSIX_ELOOP"; + case E_POSIX_EMFILE: return "E_POSIX_EMFILE"; + case E_POSIX_EMLINK: return "E_POSIX_EMLINK"; + case E_POSIX_EMSGSIZE: return "E_POSIX_EMSGSIZE"; + case E_POSIX_EMULTIHOP: return "E_POSIX_EMULTIHOP"; + case E_POSIX_ENAMETOOLONG: return "E_POSIX_ENAMETOOLONG"; + case E_POSIX_ENETDOWN: return "E_POSIX_ENETDOWN"; + case E_POSIX_ENETRESET: return "E_POSIX_ENETRESET"; + case E_POSIX_ENETUNREACH: return "E_POSIX_ENETUNREACH"; + case E_POSIX_ENFILE: return "E_POSIX_ENFILE"; + case E_POSIX_ENOBUFS: return "E_POSIX_ENOBUFS"; + case E_POSIX_ENODEV: return "E_POSIX_ENODEV"; + case E_POSIX_ENOENT: return "E_POSIX_ENOENT"; + case E_POSIX_ENOEXEC: return "E_POSIX_ENOEXEC"; + case E_POSIX_ENOLCK: return "E_POSIX_ENOLCK"; + case E_POSIX_ENOLINK: return "E_POSIX_ENOLINK"; + case E_POSIX_ENOMEM: return "E_POSIX_ENOMEM"; + case E_POSIX_ENOMSG: return "E_POSIX_ENOMSG"; + case E_POSIX_ENOPROTOOPT: return "E_POSIX_ENOPROTOOPT"; + case E_POSIX_ENOSPC: return "E_POSIX_ENOSPC"; + case E_POSIX_ENOSYS: return "E_POSIX_ENOSYS"; + case E_POSIX_ENOTCONN: return "E_POSIX_ENOTCONN"; + case E_POSIX_ENOTDIR: return "E_POSIX_ENOTDIR"; + case E_POSIX_ENOTEMPTY: return "E_POSIX_ENOTEMPTY"; + case E_POSIX_ENOTRECOVERABLE: return "E_POSIX_ENOTRECOVERABLE"; + case E_POSIX_ENOTSOCK: return "E_POSIX_ENOTSOCK"; + case E_POSIX_ENOTSUP: return "E_POSIX_ENOTSUP"; + case E_POSIX_ENOTTY: return "E_POSIX_ENOTTY"; + case E_POSIX_ENXIO: return "E_POSIX_ENXIO"; + case E_POSIX_EOPNOTSUPP: return "E_POSIX_EOPNOTSUPP"; + case E_POSIX_EOVERFLOW: return "E_POSIX_EOVERFLOW"; + case E_POSIX_EOWNERDEAD: return "E_POSIX_EOWNERDEAD"; + case E_POSIX_EPERM: return "E_POSIX_EPERM"; + case E_POSIX_EPIPE: return "E_POSIX_EPIPE"; + case E_POSIX_EPROTO: return "E_POSIX_EPROTO"; + case E_POSIX_EPROTONOSUPPORT: return "E_POSIX_EPROTONOSUPPORT"; + case E_POSIX_EPROTOTYPE: return "E_POSIX_EPROTOTYPE"; + case E_POSIX_ERANGE: return "E_POSIX_ERANGE"; + case E_POSIX_EROFS: return "E_POSIX_EROFS"; + case E_POSIX_ESOCKTNOSUPPORT: return "E_POSIX_ESOCKTNOSUPPORT"; + case E_POSIX_ESPIPE: return "E_POSIX_ESPIPE"; + case E_POSIX_ESRCH: return "E_POSIX_ESRCH"; + case E_POSIX_ESTALE: return "E_POSIX_ESTALE"; + case E_POSIX_ETIMEDOUT: return "E_POSIX_ETIMEDOUT"; + case E_POSIX_ETXTBSY: return "E_POSIX_ETXTBSY"; + case E_POSIX_EWOULDBLOCK: return "E_POSIX_EWOULDBLOCK"; + case E_POSIX_EXDEV: return "E_POSIX_EXDEV"; + case E_EUNKNOWN: return "E_EUNKNOWN"; + default: return "E_<invalid>"; + } +} + +const char *_errnum_str_msg(_errnum errnum) { + switch (errnum) { + case E_NOERROR: return "no error"; + case E_EOF: return "EOF"; + case E_NET_EARP_TIMEOUT: return "ARP timeout"; + case E_NET_EACK_TIMEOUT: return "TCP ACK timeout"; + case E_NET_ERECV_TIMEOUT: return "receive timeout"; + case E_NET_ECLOSED: return "already closed"; + case E_POSIX_E2BIG: return "Argument list too long"; + case E_POSIX_EACCES: return "Permission denied"; + case E_POSIX_EADDRINUSE: return "Address in use"; + case E_POSIX_EADDRNOTAVAIL: return "Address not available"; + case E_POSIX_EAFNOSUPPORT: return "Address family not supported"; + case E_POSIX_EAGAIN: return "Resource unavailable, try again"; + case E_POSIX_EALREADY: return "Connection already in progress"; + case E_POSIX_EBADF: return "Bad file descriptor"; + case E_POSIX_EBADMSG: return "Bad message"; + case E_POSIX_EBUSY: return "Device or resource busy"; + case E_POSIX_ECANCELED: return "Operation canceled"; + case E_POSIX_ECHILD: return "No child processes"; + case E_POSIX_ECONNABORTED: return "Connection aborted"; + case E_POSIX_ECONNREFUSED: return "Connection refused"; + case E_POSIX_ECONNRESET: return "Connection reset"; + case E_POSIX_EDEADLK: return "Resource deadlock would occur"; + case E_POSIX_EDESTADDRREQ: return "Destination address required"; + case E_POSIX_EDOM: return "Mathematics argument out of domain of function"; + case E_POSIX_EDQUOT: return "Reserved"; + case E_POSIX_EEXIST: return "File exists"; + case E_POSIX_EFAULT: return "Bad address"; + case E_POSIX_EFBIG: return "File too large"; + case E_POSIX_EHOSTUNREACH: return "Host is unreachable"; + case E_POSIX_EIDRM: return "Identifier removed"; + case E_POSIX_EILSEQ: return "Illegal byte sequence"; + case E_POSIX_EINPROGRESS: return "Operation in progress"; + case E_POSIX_EINTR: return "Interrupted function"; + case E_POSIX_EINVAL: return "Invalid argument"; + case E_POSIX_EIO: return "I/O error"; + case E_POSIX_EISCONN: return "Socket is connected"; + case E_POSIX_EISDIR: return "Is a directory"; + case E_POSIX_ELOOP: return "Too many levels of symbolic links"; + case E_POSIX_EMFILE: return "File descriptor value too large"; + case E_POSIX_EMLINK: return "Too many hard links"; + case E_POSIX_EMSGSIZE: return "Message too large"; + case E_POSIX_EMULTIHOP: return "Reserved"; + case E_POSIX_ENAMETOOLONG: return "Filename too long"; + case E_POSIX_ENETDOWN: return "Network is down"; + case E_POSIX_ENETRESET: return "Connection aborted by network"; + case E_POSIX_ENETUNREACH: return "Network unreachable"; + case E_POSIX_ENFILE: return "Too many files open in system"; + case E_POSIX_ENOBUFS: return "No buffer space available"; + case E_POSIX_ENODEV: return "No such device"; + case E_POSIX_ENOENT: return "No such file or directory"; + case E_POSIX_ENOEXEC: return "Executable file format error"; + case E_POSIX_ENOLCK: return "No locks available"; + case E_POSIX_ENOLINK: return "Reserved"; + case E_POSIX_ENOMEM: return "Not enough space"; + case E_POSIX_ENOMSG: return "No message of the desired type"; + case E_POSIX_ENOPROTOOPT: return "Protocol not available"; + case E_POSIX_ENOSPC: return "No space left on device"; + case E_POSIX_ENOSYS: return "Functionality not supported"; + case E_POSIX_ENOTCONN: return "The socket is not connected"; + case E_POSIX_ENOTDIR: return "Not a directory or a symbolic link to a directory"; + case E_POSIX_ENOTEMPTY: return "Directory not empty"; + case E_POSIX_ENOTRECOVERABLE: return "State not recoverable"; + case E_POSIX_ENOTSOCK: return "Not a socket"; + case E_POSIX_ENOTSUP: return "Not supported"; + case E_POSIX_ENOTTY: return "Inappropriate I/O control operation"; + case E_POSIX_ENXIO: return "No such device or address"; + case E_POSIX_EOPNOTSUPP: return "Operation not supported on socket"; + case E_POSIX_EOVERFLOW: return "Value too large to be stored in data type"; + case E_POSIX_EOWNERDEAD: return "Previous owner died"; + case E_POSIX_EPERM: return "Operation not permitted"; + case E_POSIX_EPIPE: return "Broken pipe"; + case E_POSIX_EPROTO: return "Protocol error"; + case E_POSIX_EPROTONOSUPPORT: return "Protocol not supported"; + case E_POSIX_EPROTOTYPE: return "Protocol wrong type for socket"; + case E_POSIX_ERANGE: return "Result too large"; + case E_POSIX_EROFS: return "Read-only file system"; + case E_POSIX_ESOCKTNOSUPPORT: return "Socket type not supported"; + case E_POSIX_ESPIPE: return "Invalid seek"; + case E_POSIX_ESRCH: return "No such process"; + case E_POSIX_ESTALE: return "Reserved"; + case E_POSIX_ETIMEDOUT: return "Connection timed out"; + case E_POSIX_ETXTBSY: return "Text file busy"; + case E_POSIX_EWOULDBLOCK: return "Operation would block"; + case E_POSIX_EXDEV: return "Improper hard link"; + case E_EUNKNOWN: + default: + return "unknown error"; + } +} diff --git a/libmisc/error_generated.c.gen b/libmisc/error_generated.c.gen new file mode 100755 index 0000000..944d909 --- /dev/null +++ b/libmisc/error_generated.c.gen @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# libmisc/error_generated.c.gen - Generate _errnum strings +# +# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +error_h=$1 +outfile=$2 + +{ + echo "/* ${outfile} - Generated by $0. DO NOT EDIT! */" + echo + echo '#include <libmisc/error.h>' + echo + echo 'const char *_errnum_str_sym(_errnum errnum) {' + echo $'\tswitch (errnum) {' + sed -nE \ + -e 's@^(#define)?\s+(E_[_A-Z0-9]+)[ ,][^/]*/\* ([^*(]+) (\*/|\().*@'$'\tcase \\2: return "\\2";''@p' \ + -- "$error_h" + echo $'\tcase E_EUNKNOWN: return "E_EUNKNOWN";' + echo $'\tdefault: return "E_<invalid>";' + echo $'\t}' + echo '}' + echo + echo 'const char *_errnum_str_msg(_errnum errnum) {' + echo $'\tswitch (errnum) {' + sed -nE \ + -e 's@^(#define)?\s+(E_[_A-Z0-9]+)[ ,][^/]*/\* ([^*(]+) (\*/|\().*@'$'\tcase \\2: return "\\3";''@p' \ + -- "$error_h" + echo $'\tcase E_EUNKNOWN:' + echo $'\tdefault:' + echo $'\t\treturn "unknown error";' + echo $'\t}' + echo '}' +} >"$outfile" diff --git a/libmisc/include/libmisc/error.h b/libmisc/include/libmisc/error.h new file mode 100644 index 0000000..4110626 --- /dev/null +++ b/libmisc/include/libmisc/error.h @@ -0,0 +1,167 @@ +/* libmisc/error.h - Go-esque errors + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIBMISC_ERROR_H_ +#define _LIBMISC_ERROR_H_ + +#include <stddef.h> /* for size_t */ +#include <stdint.h> /* for uint{n}_t */ + +#include <libmisc/assert.h> +#include <libmisc/fmt.h> + +/* _errnum ********************************************************************/ + +typedef enum { + /* Original to libmisc */ + E_NOERROR = 0, /* no error */ + E_EOF, /* EOF */ + E_NET_EARP_TIMEOUT, /* ARP timeout */ + E_NET_EACK_TIMEOUT, /* TCP ACK timeout */ + E_NET_ERECV_TIMEOUT, /* receive timeout */ + E_NET_ECLOSED, /* already closed */ + /* At least C99 through C23 */ + E_STDC_EDOM, + E_STDC_EILSEQ, + E_STDC_ERANGE, + /* POSIX-2024 */ + E_POSIX_E2BIG, /* Argument list too long */ + E_POSIX_EACCES, /* Permission denied */ + E_POSIX_EADDRINUSE, /* Address in use */ + E_POSIX_EADDRNOTAVAIL, /* Address not available */ + E_POSIX_EAFNOSUPPORT, /* Address family not supported */ + E_POSIX_EAGAIN, /* Resource unavailable, try again (may be the same value as [EWOULDBLOCK]) */ + E_POSIX_EALREADY, /* Connection already in progress */ + E_POSIX_EBADF, /* Bad file descriptor */ + E_POSIX_EBADMSG, /* Bad message */ + E_POSIX_EBUSY, /* Device or resource busy */ + E_POSIX_ECANCELED, /* Operation canceled */ + E_POSIX_ECHILD, /* No child processes */ + E_POSIX_ECONNABORTED, /* Connection aborted */ + E_POSIX_ECONNREFUSED, /* Connection refused */ + E_POSIX_ECONNRESET, /* Connection reset */ + E_POSIX_EDEADLK, /* Resource deadlock would occur */ + E_POSIX_EDESTADDRREQ, /* Destination address required */ +#define E_POSIX_EDOM E_STDC_EDOM /* Mathematics argument out of domain of function */ + E_POSIX_EDQUOT, /* Reserved */ + E_POSIX_EEXIST, /* File exists */ + E_POSIX_EFAULT, /* Bad address */ + E_POSIX_EFBIG, /* File too large */ + E_POSIX_EHOSTUNREACH, /* Host is unreachable */ + E_POSIX_EIDRM, /* Identifier removed */ +#define E_POSIX_EILSEQ E_STDC_EILSEQ /* Illegal byte sequence */ /* (in the context of text encoding) */ + E_POSIX_EINPROGRESS, /* Operation in progress */ + E_POSIX_EINTR, /* Interrupted function */ + E_POSIX_EINVAL, /* Invalid argument */ + E_POSIX_EIO, /* I/O error */ + E_POSIX_EISCONN, /* Socket is connected */ + E_POSIX_EISDIR, /* Is a directory */ + E_POSIX_ELOOP, /* Too many levels of symbolic links */ + E_POSIX_EMFILE, /* File descriptor value too large */ + E_POSIX_EMLINK, /* Too many hard links */ + E_POSIX_EMSGSIZE, /* Message too large */ + E_POSIX_EMULTIHOP, /* Reserved */ + E_POSIX_ENAMETOOLONG, /* Filename too long */ + E_POSIX_ENETDOWN, /* Network is down */ + E_POSIX_ENETRESET, /* Connection aborted by network */ + E_POSIX_ENETUNREACH, /* Network unreachable */ + E_POSIX_ENFILE, /* Too many files open in system */ + E_POSIX_ENOBUFS, /* No buffer space available */ + E_POSIX_ENODEV, /* No such device */ + E_POSIX_ENOENT, /* No such file or directory */ + E_POSIX_ENOEXEC, /* Executable file format error */ + E_POSIX_ENOLCK, /* No locks available */ + E_POSIX_ENOLINK, /* Reserved */ + E_POSIX_ENOMEM, /* Not enough space */ + E_POSIX_ENOMSG, /* No message of the desired type */ + E_POSIX_ENOPROTOOPT, /* Protocol not available */ + E_POSIX_ENOSPC, /* No space left on device */ + E_POSIX_ENOSYS, /* Functionality not supported */ + E_POSIX_ENOTCONN, /* The socket is not connected */ + E_POSIX_ENOTDIR, /* Not a directory or a symbolic link to a directory */ + E_POSIX_ENOTEMPTY, /* Directory not empty */ + E_POSIX_ENOTRECOVERABLE, /* State not recoverable */ /* Added in POSIX-2008 */ + E_POSIX_ENOTSOCK, /* Not a socket */ + E_POSIX_ENOTSUP, /* Not supported (may be the same value as [EOPNOTSUPP]) */ + E_POSIX_ENOTTY, /* Inappropriate I/O control operation */ + E_POSIX_ENXIO, /* No such device or address */ + E_POSIX_EOPNOTSUPP, /* Operation not supported on socket (may be the same value as [ENOTSUP]) */ + E_POSIX_EOVERFLOW, /* Value too large to be stored in data type */ + E_POSIX_EOWNERDEAD, /* Previous owner died */ /* Added in POSIX-2008 */ + E_POSIX_EPERM, /* Operation not permitted */ + E_POSIX_EPIPE, /* Broken pipe */ + E_POSIX_EPROTO, /* Protocol error */ + E_POSIX_EPROTONOSUPPORT, /* Protocol not supported */ + E_POSIX_EPROTOTYPE, /* Protocol wrong type for socket */ +#define E_POSIX_ERANGE E_STDC_ERANGE /* Result too large */ + E_POSIX_EROFS, /* Read-only file system */ + E_POSIX_ESOCKTNOSUPPORT, /* Socket type not supported */ + E_POSIX_ESPIPE, /* Invalid seek */ + E_POSIX_ESRCH, /* No such process */ + E_POSIX_ESTALE, /* Reserved */ + E_POSIX_ETIMEDOUT, /* Connection timed out */ + E_POSIX_ETXTBSY, /* Text file busy */ + E_POSIX_EWOULDBLOCK, /* Operation would block (may be the same value as [EAGAIN]) */ + E_POSIX_EXDEV, /* Improper hard link */ + /* End cap */ + E_EUNKNOWN, +} _errnum; + +const char *_errnum_str_sym(_errnum); +const char *_errnum_str_msg(_errnum); + +/* error **********************************************************************/ + +typedef struct { + _errnum num; + char *_msg; +} error; + +#ifdef NDEBUG +#define error_new(ERRNUM, ...) ((error){ \ + .num = ERRNUM , \ + __VA_OPT__(._msg = fmt_asprint(__VA_ARGS__),) \ +}) +#else +#define error_new(ERRNUM, ...) ((error){ \ + .num = ERRNUM, \ + ._msg = fmt_asprint("" __VA_OPT__(,) __VA_ARGS__), \ +}) +#endif + +#define ERROR_NULL ((error){}) +#define ERROR_IS_NULL(err) ((err).num == 0 && (err)._msg == NULL) + +const char *error_msg(error err); +void error_cleanup(error *errptr); +void fmt_print_error(lo_interface fmt_dest w, error err); + +/* or_error ******************************************************************/ + +#define DECLARE_ERROR_OR(TYP) typedef struct { union { TYP TYP; error err; }; bool is_err; } TYP##_or_error +#define ERROR_NEW_VAL(TYP, VAL) ((TYP##_or_error){ .TYP = (VAL), .is_err = false }) +#define ERROR_NEW_ERR(TYP, ERR) ((TYP##_or_error){ .err = (ERR), .is_err = true }) + +/* and_error *****************************************************************/ + +#define DECLARE_ERROR_AND(TYP) typedef struct { TYP TYP; error err; } TYP##_and_error +#define ERROR_AND(TYP, VAL, ERR) ((TYP##_and_error){ .TYP = (VAL), .err = (ERR) }) + +/* some pre-defined types ****************************************************/ + +DECLARE_ERROR_OR(size_t); +DECLARE_ERROR_OR(uint8_t); +DECLARE_ERROR_OR(uint16_t); +DECLARE_ERROR_OR(uint32_t); +DECLARE_ERROR_OR(uint64_t); + +DECLARE_ERROR_AND(size_t); +DECLARE_ERROR_AND(uint8_t); +DECLARE_ERROR_AND(uint16_t); +DECLARE_ERROR_AND(uint32_t); +DECLARE_ERROR_AND(uint64_t); + +#endif /* _LIBMISC_ERROR_H_ */ |