From 30a60acc14696551ccdb61d4006defcb5eea8cc6 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sun, 20 Apr 2025 16:58:30 -0600 Subject: libhw_generic: Switch io.h and net.h to use result.h/error.h --- lib9p/srv.c | 66 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 26 deletions(-) (limited to 'lib9p/srv.c') diff --git a/lib9p/srv.c b/lib9p/srv.c index 32e9a9a..7785e4d 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -366,23 +366,23 @@ 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]); - ssize_t r; struct lib9p_msg_Rerror host = { .tag = req->tag, .errstr = lib9p_strn(req->basectx.err_msg, @@ -408,28 +408,29 @@ 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); } /* 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 +443,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); } } @@ -517,14 +519,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); -- cgit v1.2.3-2-g168b From 8a9fc1704dcf3ec117a3bf37fd70a44a43873659 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Thu, 29 May 2025 23:39:12 -0400 Subject: lib9p: Use errnums internally --- lib9p/srv.c | 88 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 45 insertions(+), 43 deletions(-) (limited to 'lib9p/srv.c') diff --git a/lib9p/srv.c b/lib9p/srv.c index 7785e4d..d29479f 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -27,6 +27,8 @@ #define IMPLEMENTATION_FOR_LIB9P_SRV_H YES #include +#include "srv_errno.h" + /* config *********************************************************************/ #include "config.h" @@ -342,7 +344,7 @@ static inline struct srv_fidinfo *srv_fid_store(struct srv_req *ctx, lib9p_fid_t map_del(&ctx->parent_sess->fids, fid); } else { lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "FID already in use"); + E_POSIX_EBADF, "FID already in use"); return NULL; } } @@ -388,7 +390,7 @@ static void srv_respond_error(struct srv_req *req) { .errstr = lib9p_strn(req->basectx.err_msg, CONFIG_9P_MAX_ERR_SIZE), #if CONFIG_9P_ENABLE_9P2000_u - .errnum = req->basectx.err_num, + .errnum = libmisc_to_linuxgeneric_errno(req->basectx.err_num), #endif }; @@ -397,7 +399,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; @@ -497,7 +499,7 @@ 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, + lib9p_error(&req.basectx, E_POSIX_EMSGSIZE, "T-message larger than ", sess.initialized ? "negotiated" : "server", " limit", " (", goal, " > ", sess.max_msg_size, ")"); srv_respond_error(&req); @@ -760,7 +762,7 @@ static void handle_Tversion(struct srv_req *ctx, 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), + 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; } @@ -814,7 +816,7 @@ 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"); + E_POSIX_EOPNOTSUPP, "authentication not required"); goto tauth_return; } @@ -823,7 +825,7 @@ static void handle_Tauth(struct srv_req *ctx, srv->auth(ctx, req->aname); lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "TODO: auth not implemented"); + E_POSIX_EOPNOTSUPP, "TODO: auth not implemented"); if (lib9p_ctx_has_error(&ctx->basectx)) ctx->user = srv_userid_decref(ctx->user); @@ -838,7 +840,7 @@ static void handle_Tattach(struct srv_req *ctx, if (req->fid == LIB9P_FID_NOFID) { lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "cannot assign to NOFID"); + E_POSIX_EBADF, "cannot assign to NOFID"); goto tattach_return; } @@ -847,37 +849,37 @@ static void handle_Tattach(struct srv_req *ctx, 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"); + 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"); + 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, + 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, + 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, + 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"); + E_POSIX_EACCES, "FID provided as auth-file has not completed authentication"); if (lib9p_ctx_has_error(&ctx->basectx)) 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"); + 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); @@ -937,19 +939,19 @@ static void handle_Twalk(struct srv_req *ctx, if (req->newfid == LIB9P_FID_NOFID) { lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBADF, "cannot assign to NOFID"); + 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); + 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"); + E_POSIX_EALREADY, "cannot walk on FID open for I/O"); goto twalk_return; } ctx->user = srv_userid_incref(fidinfo->user); @@ -963,7 +965,7 @@ static void handle_Twalk(struct srv_req *ctx, 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"); + E_POSIX_ENOTDIR, "not a directory"); break; } @@ -988,7 +990,7 @@ static void handle_Twalk(struct srv_req *ctx, 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"); + E_POSIX_EACCES, "you do not have execute permission on that directory"); srv_path_decref(ctx, LO_CALL(new_pathinfo->file, qid).path); break; } @@ -1022,12 +1024,12 @@ static void handle_Topen(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); + 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"); + E_POSIX_EALREADY, "FID is already open"); goto topen_return; } if (fidinfo->type == SRV_FILETYPE_DIR) { @@ -1035,7 +1037,7 @@ static void handle_Topen(struct srv_req *ctx, (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"); + E_POSIX_EISDIR, "directories cannot be written, executed, truncated, or removed-on-close"); goto topen_return; } } @@ -1057,7 +1059,7 @@ static void handle_Topen(struct srv_req *ctx, 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"); + E_POSIX_EACCES, "permission denied to remove-on-close"); goto topen_return; } fidflags |= FIDFLAG_RCLOSE; @@ -1068,7 +1070,7 @@ static void handle_Topen(struct srv_req *ctx, 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"); + E_POSIX_EEXIST, "exclusive file is already opened"); goto topen_return; } if (stat.mode & LIB9P_DM_APPEND) { @@ -1097,7 +1099,7 @@ static void handle_Topen(struct srv_req *ctx, } if (!srv_check_perm(ctx, &stat, perm_bits)) { lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EACCES, "permission denied"); + E_POSIX_EACCES, "permission denied"); goto topen_return; } @@ -1153,7 +1155,7 @@ static void handle_Tcreate(struct srv_req *ctx, srv_handler_common(ctx, create, req); lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "create not (yet?) implemented"); + E_POSIX_EOPNOTSUPP, "create not (yet?) implemented"); srv_respond(ctx, create, &resp); } @@ -1192,12 +1194,12 @@ static void handle_Tread(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); + 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"); + E_POSIX_EINVAL, "FID not open for reading"); goto tread_return; } @@ -1213,7 +1215,7 @@ static void handle_Tread(struct srv_req *ctx, 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); + E_POSIX_EINVAL, "invalid offset (must be 0 or ", fidinfo->dir.off, "): ", req->offset); goto tread_return; } /* Read. */ @@ -1266,7 +1268,7 @@ static void handle_Tread(struct srv_req *ctx, if (!nbytes) { if (!resp.count) { lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_ERANGE, "stat object does not fit into negotiated max message size"); + E_POSIX_ERANGE, "stat object does not fit into negotiated max message size"); goto tread_return; } fidinfo->dir.buffered_dirent = member_dirent; @@ -1313,12 +1315,12 @@ static void handle_Twrite(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); + 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"); + E_POSIX_EINVAL, "FID not open for writing"); goto twrite_return; } if (fidinfo->flags & FIDFLAG_APPEND) @@ -1340,7 +1342,7 @@ 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); + E_POSIX_EBADF, "bad file number ", req->fid); goto tclunk_return; } @@ -1357,7 +1359,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); + E_POSIX_EBADF, "bad file number ", req->fid); goto tremove_return; } @@ -1366,7 +1368,7 @@ static void handle_Tremove(struct srv_req *ctx, assert(pathinfo); if (pathinfo->parent_dir == fidinfo->path) { lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EBUSY, "cannot remove root"); + E_POSIX_EBUSY, "cannot remove root"); remove = false; goto tremove_main; } @@ -1375,7 +1377,7 @@ static void handle_Tremove(struct srv_req *ctx, 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"); + E_POSIX_EACCES, "you do not have write permission on the parent directory"); remove = false; goto tremove_main; } @@ -1393,7 +1395,7 @@ 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); + E_POSIX_EBADF, "bad file number ", req->fid); goto tstat_return; } struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); @@ -1416,7 +1418,7 @@ static void handle_Twstat(struct srv_req *ctx, srv_handler_common(ctx, wstat, req); lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "wstat not (yet?) implemented"); + E_POSIX_EOPNOTSUPP, "wstat not (yet?) implemented"); srv_respond(ctx, wstat, &resp); } @@ -1428,7 +1430,7 @@ static void handle_Topenfd(struct srv_req *ctx, srv_handler_common(ctx, openfd, req); lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "openfd not (yet?) implemented"); + E_POSIX_EOPNOTSUPP, "openfd not (yet?) implemented"); srv_respond(ctx, openfd, &resp); } @@ -1440,7 +1442,7 @@ static void handle_Tsession(struct srv_req *ctx, srv_handler_common(ctx, session, req); lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "session not (yet?) implemented"); + E_POSIX_EOPNOTSUPP, "session not (yet?) implemented"); srv_respond(ctx, session, &resp); } @@ -1450,7 +1452,7 @@ static void handle_Tsread(struct srv_req *ctx, srv_handler_common(ctx, sread, req); lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "sread not (yet?) implemented"); + E_POSIX_EOPNOTSUPP, "sread not (yet?) implemented"); srv_respond(ctx, sread, &resp); } @@ -1460,7 +1462,7 @@ static void handle_Tswrite(struct srv_req *ctx, srv_handler_common(ctx, swrite, req); lib9p_error(&ctx->basectx, - LIB9P_ERRNO_L_EOPNOTSUPP, "swrite not (yet?) implemented"); + E_POSIX_EOPNOTSUPP, "swrite not (yet?) implemented"); srv_respond(ctx, swrite, &resp); } -- cgit v1.2.3-2-g168b From 945756b1b050bdf09d1119854cc5b22ad15efacd Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Thu, 29 May 2025 22:25:02 -0400 Subject: lib9p_core: Switch to use error.h --- lib9p/srv.c | 221 +++++++++++++++++++++++++++--------------------------------- 1 file changed, 100 insertions(+), 121 deletions(-) (limited to 'lib9p/srv.c') diff --git a/lib9p/srv.c b/lib9p/srv.c index d29479f..917b41e 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -44,6 +44,17 @@ static_assert(CONFIG_9P_SRV_MAX_HOSTMSG_SIZE <= SSIZE_MAX); /* context ********************************************************************/ +void lib9p_ctx_clear_error(struct lib9p_srv_ctx *ctx) { + assert(ctx); + ctx->err_num = 0; + ctx->err_msg[0] = '\0'; +} + +bool lib9p_ctx_has_error(struct lib9p_srv_ctx *ctx) { + assert(ctx); + return ctx->err_msg[0]; +} + bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx) { assert(ctx); return cr_chan_can_send(&ctx->flush_ch); @@ -343,8 +354,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, - E_POSIX_EBADF, "FID already in use"); + lib9p_error(ctx, E_POSIX_EBADF, "FID already in use"); return NULL; } } @@ -381,16 +391,16 @@ static void srv_write_Rmsg(struct srv_req *req, struct lib9p_Rmsg_send_buf *resp 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); + assert(req->err_num); #endif - assert(req->basectx.err_msg[0]); + assert(req->err_msg[0]); struct lib9p_msg_Rerror host = { .tag = req->tag, - .errstr = lib9p_strn(req->basectx.err_msg, - CONFIG_9P_MAX_ERR_SIZE), + .errstr = lib9p_strn(req->err_msg, + CONFIG_9P_SRV_MAX_ERR_SIZE), #if CONFIG_9P_ENABLE_9P2000_u - .errnum = libmisc_to_linuxgeneric_errno(req->basectx.err_num), + .errnum = libmisc_to_linuxgeneric_errno(req->err_num), #endif }; @@ -499,7 +509,7 @@ 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, E_POSIX_EMSGSIZE, + lib9p_error(&req, E_POSIX_EMSGSIZE, "T-message larger than ", sess.initialized ? "negotiated" : "server", " limit", " (", goal, " > ", sess.max_msg_size, ")"); srv_respond_error(&req); @@ -555,9 +565,9 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) { }; 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); + if (lib9p_ctx_has_error(&pseudoreq)) { + srv_nonrespond_error("clunk: ", (strn, pseudoreq.err_msg, CONFIG_9P_SRV_MAX_ERR_SIZE)); + lib9p_ctx_clear_error(&pseudoreq); } } map_free(&sess.fids); @@ -631,11 +641,14 @@ 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) { + size_t_or_error r = lib9p_Tmsg_validate(&ctx->basectx, ctx->net_bytes); + if (r.is_err) { + lib9p_error(ctx, r.err.num, (error, r.err)); + error_cleanup(&r.err); srv_respond_error(ctx); goto release; } + size_t host_size = r.size_t; host_req = calloc(1, host_size); assert(host_req); enum lib9p_msg_type typ; @@ -693,7 +706,7 @@ void lib9p_srv_worker(struct srv_req *ctx) { static inline void _srv_respond(struct srv_req *ctx, enum lib9p_msg_type resp_typ, void *host_resp) { assert(!ctx->responded); - if (lib9p_ctx_has_error(&ctx->basectx)) { + if (lib9p_ctx_has_error(ctx)) { error: srv_respond_error(ctx); } else if (ctx->flush_acknowledged) { @@ -701,10 +714,14 @@ static inline void _srv_respond(struct srv_req *ctx, enum lib9p_msg_type resp_ty } else { assert(host_resp); struct lib9p_Rmsg_send_buf net_resp; - if (lib9p_Rmsg_marshal(&ctx->basectx, - resp_typ, host_resp, - &net_resp)) + error err = lib9p_Rmsg_marshal(&ctx->basectx, + resp_typ, host_resp, + &net_resp); + if (!ERROR_IS_NULL(err)) { + lib9p_error(ctx, err.num, (error, err)); + error_cleanup(&err); goto error; + } srv_msglog(ctx, resp_typ, host_resp); srv_write_Rmsg(ctx, &net_resp); } @@ -761,7 +778,7 @@ 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_error(ctx, 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; @@ -794,9 +811,9 @@ 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); + if (lib9p_ctx_has_error(ctx)) { + srv_nonrespond_error("clunk: ", (strn, ctx->err_msg, CONFIG_9P_SRV_MAX_ERR_SIZE)); + lib9p_ctx_clear_error(ctx); } } @@ -815,8 +832,7 @@ 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, - E_POSIX_EOPNOTSUPP, "authentication not required"); + lib9p_error(ctx, E_POSIX_EOPNOTSUPP, "authentication not required"); goto tauth_return; } @@ -824,10 +840,9 @@ static void handle_Tauth(struct srv_req *ctx, srv->auth(ctx, req->aname); - lib9p_error(&ctx->basectx, - E_POSIX_EOPNOTSUPP, "TODO: auth not implemented"); + lib9p_error(ctx, E_POSIX_EOPNOTSUPP, "TODO: auth not implemented"); - if (lib9p_ctx_has_error(&ctx->basectx)) + if (lib9p_ctx_has_error(ctx)) ctx->user = srv_userid_decref(ctx->user); tauth_return: @@ -839,8 +854,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, - E_POSIX_EBADF, "cannot assign to NOFID"); + lib9p_error(ctx, E_POSIX_EBADF, "cannot assign to NOFID"); goto tattach_return; } @@ -848,38 +862,31 @@ 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, - E_POSIX_EACCES, "FID provided as auth-file is not a valid FID"); + lib9p_error(ctx, E_POSIX_EACCES, "FID provided as auth-file is not a valid FID"); else if (afid->type != SRV_FILETYPE_AUTH) - lib9p_error(&ctx->basectx, - E_POSIX_EACCES, "FID provided as auth-file is not an auth-file"); + lib9p_error(ctx, 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, - E_POSIX_EACCES, + lib9p_error(ctx, 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, - E_POSIX_EACCES, + lib9p_error(ctx, 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, - E_POSIX_EACCES, + lib9p_error(ctx, 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, - E_POSIX_EACCES, "FID provided as auth-file has not completed authentication"); - if (lib9p_ctx_has_error(&ctx->basectx)) + lib9p_error(ctx, E_POSIX_EACCES, "FID provided as auth-file has not completed authentication"); + if (lib9p_ctx_has_error(ctx)) goto tattach_return; ctx->user = srv_userid_incref(afid->user); } else { if (req->afid != LIB9P_FID_NOFID) { - lib9p_error(&ctx->basectx, - E_POSIX_EACCES, "FID provided as auth-file, but no auth-file is required"); + lib9p_error(ctx, 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); @@ -887,8 +894,8 @@ static void handle_Tattach(struct srv_req *ctx, /* 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)) + assert(LO_IS_NULL(root_file) == lib9p_ctx_has_error(ctx)); + if (lib9p_ctx_has_error(ctx)) goto tattach_return; struct lib9p_qid root_qid = LO_CALL(root_file, qid); @@ -938,20 +945,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, - E_POSIX_EBADF, "cannot assign to NOFID"); + lib9p_error(ctx, 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, - E_POSIX_EBADF, "bad file number ", req->fid); + lib9p_error(ctx, E_POSIX_EBADF, "bad file number ", req->fid); goto twalk_return; } if (fidinfo->flags & FIDFLAG_OPEN) { - lib9p_error(&ctx->basectx, - E_POSIX_EALREADY, "cannot walk on FID open for I/O"); + lib9p_error(ctx, E_POSIX_EALREADY, "cannot walk on FID open for I/O"); goto twalk_return; } ctx->user = srv_userid_incref(fidinfo->user); @@ -964,8 +968,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, - E_POSIX_ENOTDIR, "not a directory"); + lib9p_error(ctx, E_POSIX_ENOTDIR, "not a directory"); break; } @@ -976,8 +979,8 @@ static void handle_Twalk(struct srv_req *ctx, 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)) + assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(ctx)); + if (lib9p_ctx_has_error(ctx)) break; new_pathinfo = srv_path_save(ctx, member_file, LO_CALL(pathinfo->file, qid).path); assert(new_pathinfo); @@ -985,12 +988,11 @@ static void handle_Twalk(struct srv_req *ctx, 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)) + if (lib9p_ctx_has_error(ctx)) break; lib9p_srv_stat_assert(stat); if (!srv_check_perm(ctx, &stat, 0b001)) { - lib9p_error(&ctx->basectx, - E_POSIX_EACCES, "you do not have execute permission on that directory"); + lib9p_error(ctx, E_POSIX_EACCES, "you do not have execute permission on that directory"); srv_path_decref(ctx, LO_CALL(new_pathinfo->file, qid).path); break; } @@ -1005,10 +1007,10 @@ static void handle_Twalk(struct srv_req *ctx, if (!srv_fid_store(ctx, req->newfid, pathinfo, req->newfid == req->fid)) srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); } else { - assert(lib9p_ctx_has_error(&ctx->basectx)); + assert(lib9p_ctx_has_error(ctx)); srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); if (resp.nwqid > 0) - lib9p_ctx_clear_error(&ctx->basectx); + lib9p_ctx_clear_error(ctx); } twalk_return: if (ctx->user) @@ -1023,21 +1025,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, - E_POSIX_EBADF, "bad file number ", req->fid); + lib9p_error(ctx, E_POSIX_EBADF, "bad file number ", req->fid); goto topen_return; } if (fidinfo->flags & FIDFLAG_OPEN) { - lib9p_error(&ctx->basectx, - E_POSIX_EALREADY, "FID is already open"); + lib9p_error(ctx, 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, - E_POSIX_EISDIR, "directories cannot be written, executed, truncated, or removed-on-close"); + lib9p_error(ctx, E_POSIX_EISDIR, "directories cannot be written, executed, truncated, or removed-on-close"); goto topen_return; } } @@ -1054,23 +1053,21 @@ static void handle_Topen(struct srv_req *ctx, 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)) + if (lib9p_ctx_has_error(ctx)) goto topen_return; lib9p_srv_stat_assert(parent_stat); if (!srv_check_perm(ctx, &parent_stat, 0b010)) { - lib9p_error(&ctx->basectx, - E_POSIX_EACCES, "permission denied to remove-on-close"); + lib9p_error(ctx, 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)) + if (lib9p_ctx_has_error(ctx)) goto topen_return; lib9p_srv_stat_assert(stat); if ((stat.mode & LIB9P_DM_EXCL) && pathinfo->io_refcount) { - lib9p_error(&ctx->basectx, - E_POSIX_EEXIST, "exclusive file is already opened"); + lib9p_error(ctx, E_POSIX_EEXIST, "exclusive file is already opened"); goto topen_return; } if (stat.mode & LIB9P_DM_APPEND) { @@ -1098,8 +1095,7 @@ static void handle_Topen(struct srv_req *ctx, break; } if (!srv_check_perm(ctx, &stat, perm_bits)) { - lib9p_error(&ctx->basectx, - E_POSIX_EACCES, "permission denied"); + lib9p_error(ctx, E_POSIX_EACCES, "permission denied"); goto topen_return; } @@ -1109,8 +1105,8 @@ static void handle_Topen(struct srv_req *ctx, 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)) + assert(LO_IS_NULL(fidinfo->dir.io) == lib9p_ctx_has_error(ctx)); + if (lib9p_ctx_has_error(ctx)) goto topen_return; fidinfo->dir.idx = 0; fidinfo->dir.off = 0; @@ -1121,8 +1117,8 @@ static void handle_Topen(struct srv_req *ctx, 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)) + assert(LO_IS_NULL(fidinfo->file.io) == lib9p_ctx_has_error(ctx)); + if (lib9p_ctx_has_error(ctx)) goto topen_return; qid = LO_CALL(fidinfo->file.io, qid); iounit = LO_CALL(fidinfo->file.io, iounit); @@ -1154,8 +1150,7 @@ static void handle_Tcreate(struct srv_req *ctx, struct lib9p_msg_Tcreate *req) { srv_handler_common(ctx, create, req); - lib9p_error(&ctx->basectx, - E_POSIX_EOPNOTSUPP, "create not (yet?) implemented"); + lib9p_error(ctx, E_POSIX_EOPNOTSUPP, "create not (yet?) implemented"); srv_respond(ctx, create, &resp); } @@ -1193,13 +1188,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, - E_POSIX_EBADF, "bad file number ", req->fid); + lib9p_error(ctx, E_POSIX_EBADF, "bad file number ", req->fid); goto tread_return; } if (!(fidinfo->flags & FIDFLAG_OPEN_R)) { - lib9p_error(&ctx->basectx, - E_POSIX_EINVAL, "FID not open for reading"); + lib9p_error(ctx, E_POSIX_EINVAL, "FID not open for reading"); goto tread_return; } @@ -1214,8 +1207,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, - E_POSIX_EINVAL, "invalid offset (must be 0 or ", fidinfo->dir.off, "): ", req->offset); + lib9p_error(ctx, E_POSIX_EINVAL, "invalid offset (must be 0 or ", fidinfo->dir.off, "): ", req->offset); goto tread_return; } /* Read. */ @@ -1229,10 +1221,10 @@ static void handle_Tread(struct srv_req *ctx, 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 (lib9p_ctx_has_error(ctx)) { if (!resp.count) goto tread_return; - lib9p_ctx_clear_error(&ctx->basectx); + lib9p_ctx_clear_error(ctx); break; } } @@ -1247,16 +1239,16 @@ static void handle_Tread(struct srv_req *ctx, 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)) + assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(ctx)); + if (!lib9p_ctx_has_error(ctx)) member_stat = LO_CALL(member_file, stat, ctx); } - if (lib9p_ctx_has_error(&ctx->basectx)) { + if (lib9p_ctx_has_error(ctx)) { if (!LO_IS_NULL(member_file)) LO_CALL(member_file, free); if (!resp.count) goto tread_return; - lib9p_ctx_clear_error(&ctx->basectx); + lib9p_ctx_clear_error(ctx); break; } lib9p_srv_stat_assert(member_stat); @@ -1267,8 +1259,7 @@ static void handle_Tread(struct srv_req *ctx, LO_CALL(member_file, free); if (!nbytes) { if (!resp.count) { - lib9p_error(&ctx->basectx, - E_POSIX_ERANGE, "stat object does not fit into negotiated max message size"); + lib9p_error(ctx, E_POSIX_ERANGE, "stat object does not fit into negotiated max message size"); goto tread_return; } fidinfo->dir.buffered_dirent = member_dirent; @@ -1286,7 +1277,7 @@ static void handle_Tread(struct srv_req *ctx, 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) { + if (!lib9p_ctx_has_error(ctx) && !ctx->flush_acknowledged) { resp.count = iov.iov_len; resp.data = iov.iov_base; if (resp.count > req->count) @@ -1314,13 +1305,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, - E_POSIX_EBADF, "bad file number ", req->fid); + lib9p_error(ctx, E_POSIX_EBADF, "bad file number ", req->fid); goto twrite_return; } if (!(fidinfo->flags & FIDFLAG_OPEN_W)) { - lib9p_error(&ctx->basectx, - E_POSIX_EINVAL, "FID not open for writing"); + lib9p_error(ctx, E_POSIX_EINVAL, "FID not open for writing"); goto twrite_return; } if (fidinfo->flags & FIDFLAG_APPEND) @@ -1341,8 +1330,7 @@ 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, - E_POSIX_EBADF, "bad file number ", req->fid); + lib9p_error(ctx, E_POSIX_EBADF, "bad file number ", req->fid); goto tclunk_return; } @@ -1358,8 +1346,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, - E_POSIX_EBADF, "bad file number ", req->fid); + lib9p_error(ctx, E_POSIX_EBADF, "bad file number ", req->fid); goto tremove_return; } @@ -1367,17 +1354,15 @@ 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, - E_POSIX_EBUSY, "cannot remove root"); + lib9p_error(ctx, 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, - E_POSIX_EACCES, "you do not have write permission on the parent directory"); + if (!lib9p_ctx_has_error(ctx) && !srv_check_perm(ctx, &parent_stat, 0b010)) { + lib9p_error(ctx, E_POSIX_EACCES, "you do not have write permission on the parent directory"); remove = false; goto tremove_main; } @@ -1394,8 +1379,7 @@ 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, - E_POSIX_EBADF, "bad file number ", req->fid); + lib9p_error(ctx, E_POSIX_EBADF, "bad file number ", req->fid); goto tstat_return; } struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); @@ -1403,7 +1387,7 @@ static void handle_Tstat(struct srv_req *ctx, 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)) + if (lib9p_ctx_has_error(ctx)) goto tstat_return; lib9p_srv_stat_assert(stat); resp.stat = srv_stat_to_net_stat(stat); @@ -1417,8 +1401,7 @@ static void handle_Twstat(struct srv_req *ctx, struct lib9p_msg_Twstat *req) { srv_handler_common(ctx, wstat, req); - lib9p_error(&ctx->basectx, - E_POSIX_EOPNOTSUPP, "wstat not (yet?) implemented"); + lib9p_error(ctx, E_POSIX_EOPNOTSUPP, "wstat not (yet?) implemented"); srv_respond(ctx, wstat, &resp); } @@ -1429,8 +1412,7 @@ static void handle_Topenfd(struct srv_req *ctx, struct lib9p_msg_Topenfd *req) { srv_handler_common(ctx, openfd, req); - lib9p_error(&ctx->basectx, - E_POSIX_EOPNOTSUPP, "openfd not (yet?) implemented"); + lib9p_error(ctx, E_POSIX_EOPNOTSUPP, "openfd not (yet?) implemented"); srv_respond(ctx, openfd, &resp); } @@ -1441,8 +1423,7 @@ static void handle_Tsession(struct srv_req *ctx, struct lib9p_msg_Tsession *req) { srv_handler_common(ctx, session, req); - lib9p_error(&ctx->basectx, - E_POSIX_EOPNOTSUPP, "session not (yet?) implemented"); + lib9p_error(ctx, E_POSIX_EOPNOTSUPP, "session not (yet?) implemented"); srv_respond(ctx, session, &resp); } @@ -1451,8 +1432,7 @@ static void handle_Tsread(struct srv_req *ctx, struct lib9p_msg_Tsread *req) { srv_handler_common(ctx, sread, req); - lib9p_error(&ctx->basectx, - E_POSIX_EOPNOTSUPP, "sread not (yet?) implemented"); + lib9p_error(ctx, E_POSIX_EOPNOTSUPP, "sread not (yet?) implemented"); srv_respond(ctx, sread, &resp); } @@ -1461,8 +1441,7 @@ static void handle_Tswrite(struct srv_req *ctx, struct lib9p_msg_Tswrite *req) { srv_handler_common(ctx, swrite, req); - lib9p_error(&ctx->basectx, - E_POSIX_EOPNOTSUPP, "swrite not (yet?) implemented"); + lib9p_error(ctx, E_POSIX_EOPNOTSUPP, "swrite not (yet?) implemented"); srv_respond(ctx, swrite, &resp); } -- cgit v1.2.3-2-g168b From 7b0f4d3ac1a64f4015148e89eeeeedf0a617cbc5 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Thu, 29 May 2025 22:25:02 -0400 Subject: lib9p_srv: Change the public API to use error.h --- lib9p/srv.c | 121 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 84 insertions(+), 37 deletions(-) (limited to 'lib9p/srv.c') diff --git a/lib9p/srv.c b/lib9p/srv.c index 917b41e..05d7144 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -44,28 +44,66 @@ static_assert(CONFIG_9P_SRV_MAX_HOSTMSG_SIZE <= SSIZE_MAX); /* context ********************************************************************/ -void lib9p_ctx_clear_error(struct lib9p_srv_ctx *ctx) { +static void lib9p_ctx_clear_error(struct lib9p_srv_ctx *ctx) { assert(ctx); ctx->err_num = 0; ctx->err_msg[0] = '\0'; } -bool lib9p_ctx_has_error(struct lib9p_srv_ctx *ctx) { +static bool lib9p_ctx_has_error(struct lib9p_srv_ctx *ctx) { assert(ctx); return ctx->err_msg[0]; } +/** Write a -style error into ctx, return -1. */ +#define lib9p_error(ctx, libmisc_errno, ...) ({ \ + if (!lib9p_ctx_has_error(ctx)) { \ + (ctx)->err_num = libmisc_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; \ +}) + +#define CTX_ERR_OR(TYP, func, ctx, ...) \ + ({ \ + TYP##_or_error r = func(ctx __VA_OPT__(,) __VA_ARGS__); \ + TYP v = {}; \ + if (r.is_err && !lib9p_ctx_has_error(ctx)) { \ + (ctx)->err_num = r.err.num; \ + strncpy((ctx)->err_msg, error_msg(r.err), CONFIG_9P_SRV_MAX_ERR_SIZE); \ + error_cleanup(&r.err); \ + } \ + if (!r.is_err) \ + v = r.TYP; \ + v; \ + }) + +#define CTX_LO_ERR_OR(TYP, obj, func, ctx, ...) \ + ({ \ + TYP##_or_error r = LO_CALL(obj, func, ctx __VA_OPT__(,) __VA_ARGS__); \ + TYP v = {}; \ + if (r.is_err && !lib9p_ctx_has_error(ctx)) { \ + (ctx)->err_num = r.err.num; \ + strncpy((ctx)->err_msg, error_msg(r.err), CONFIG_9P_SRV_MAX_ERR_SIZE); \ + error_cleanup(&r.err); \ + } \ + if (!r.is_err) \ + v = r.TYP; \ + v; \ + }) + bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx) { assert(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(), ": ", \ @@ -707,10 +745,12 @@ void lib9p_srv_worker(struct srv_req *ctx) { static inline void _srv_respond(struct srv_req *ctx, enum lib9p_msg_type resp_typ, void *host_resp) { assert(!ctx->responded); if (lib9p_ctx_has_error(ctx)) { - error: - srv_respond_error(ctx); - } else if (ctx->flush_acknowledged) { - /* do nothing */ + if (ctx->err_num == E_POSIX_ECANCELED && lib9p_srv_flush_requested(ctx)) { + /* do nothing */ + } else { + error: + srv_respond_error(ctx); + } } else { assert(host_resp); struct lib9p_Rmsg_send_buf net_resp; @@ -893,7 +933,7 @@ static void handle_Tattach(struct srv_req *ctx, } /* 1. File object */ - lo_interface lib9p_srv_file root_file = srv->rootdir(ctx, req->aname); + lo_interface lib9p_srv_file root_file = CTX_ERR_OR(lib9p_srv_file, srv->rootdir, ctx, req->aname); assert(LO_IS_NULL(root_file) == lib9p_ctx_has_error(ctx)); if (lib9p_ctx_has_error(ctx)) goto tattach_return; @@ -929,12 +969,14 @@ 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); @@ -978,7 +1020,7 @@ 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]); + lo_interface lib9p_srv_file member_file = CTX_LO_ERR_OR(lib9p_srv_file, pathinfo->file, dwalk, ctx, req->wname[resp.nwqid]); assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(ctx)); if (lib9p_ctx_has_error(ctx)) break; @@ -987,7 +1029,7 @@ static void handle_Twalk(struct srv_req *ctx, } if (new_pathinfo->type == SRV_FILETYPE_DIR) { - struct lib9p_srv_stat stat = LO_CALL(new_pathinfo->file, stat, ctx); + struct lib9p_srv_stat stat = CTX_LO_ERR_OR(lib9p_srv_stat, new_pathinfo->file, stat, ctx); if (lib9p_ctx_has_error(ctx)) break; lib9p_srv_stat_assert(stat); @@ -1052,7 +1094,7 @@ 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); + struct lib9p_srv_stat parent_stat = CTX_LO_ERR_OR(lib9p_srv_stat, parent->file, stat, ctx); if (lib9p_ctx_has_error(ctx)) goto topen_return; lib9p_srv_stat_assert(parent_stat); @@ -1062,7 +1104,7 @@ static void handle_Topen(struct srv_req *ctx, } fidflags |= FIDFLAG_RCLOSE; } - struct lib9p_srv_stat stat = LO_CALL(pathinfo->file, stat, ctx); + struct lib9p_srv_stat stat = CTX_LO_ERR_OR(lib9p_srv_stat, pathinfo->file, stat, ctx); if (lib9p_ctx_has_error(ctx)) goto topen_return; lib9p_srv_stat_assert(stat); @@ -1104,7 +1146,7 @@ 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); + fidinfo->dir.io = CTX_LO_ERR_OR(lib9p_srv_dio, pathinfo->file, dopen, ctx); assert(LO_IS_NULL(fidinfo->dir.io) == lib9p_ctx_has_error(ctx)); if (lib9p_ctx_has_error(ctx)) goto topen_return; @@ -1114,9 +1156,9 @@ static void handle_Topen(struct srv_req *ctx, iounit = 0; break; case SRV_FILETYPE_FILE: - fidinfo->file.io = LO_CALL(pathinfo->file, fopen, ctx, - rd, wr, - reqmode & LIB9P_O_TRUNC); + fidinfo->file.io = CTX_LO_ERR_OR(lib9p_srv_fio, pathinfo->file, fopen, ctx, + rd, wr, + reqmode & LIB9P_O_TRUNC); assert(LO_IS_NULL(fidinfo->file.io) == lib9p_ctx_has_error(ctx)); if (lib9p_ctx_has_error(ctx)) goto topen_return; @@ -1220,7 +1262,7 @@ 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); + member_dirent = CTX_LO_ERR_OR(lib9p_srv_dirent, fidinfo->dir.io, dread, ctx, fidinfo->dir.idx); if (lib9p_ctx_has_error(ctx)) { if (!resp.count) goto tread_return; @@ -1233,17 +1275,23 @@ static void handle_Tread(struct srv_req *ctx, 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); + member_stat = CTX_LO_ERR_OR(lib9p_srv_stat, member_pathinfo->file, stat, ctx); + if (lib9p_ctx_has_error(ctx)) + goto member_err; } 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); + member_file = CTX_LO_ERR_OR(lib9p_srv_file, dir_pathinfo->file, dwalk, ctx, member_dirent.name); assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(ctx)); - if (!lib9p_ctx_has_error(ctx)) - member_stat = LO_CALL(member_file, stat, ctx); + if (lib9p_ctx_has_error(ctx)) + goto member_err; + member_stat = CTX_LO_ERR_OR(lib9p_srv_stat, member_file, stat, ctx); + if (lib9p_ctx_has_error(ctx)) + goto member_err; } - if (lib9p_ctx_has_error(ctx)) { + if (false) { + member_err: if (!LO_IS_NULL(member_file)) LO_CALL(member_file, free); if (!resp.count) @@ -1275,9 +1323,8 @@ 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) && !ctx->flush_acknowledged) { + struct iovec iov = CTX_LO_ERR_OR(iovec, fidinfo->file.io, pread, ctx, req->count, req->offset); + if (!lib9p_ctx_has_error(ctx)) { resp.count = iov.iov_len; resp.data = iov.iov_base; if (resp.count > req->count) @@ -1317,7 +1364,7 @@ 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); + resp.count = CTX_LO_ERR_OR(uint32_t, fidinfo->file.io, pwrite, ctx, req->data, req->count, req->offset); twrite_return: if (ctx->user) ctx->user = srv_userid_decref(ctx->user); @@ -1360,7 +1407,7 @@ static void handle_Tremove(struct srv_req *ctx, } 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); + struct lib9p_srv_stat parent_stat = CTX_LO_ERR_OR(lib9p_srv_stat, parent->file, stat, ctx); if (!lib9p_ctx_has_error(ctx) && !srv_check_perm(ctx, &parent_stat, 0b010)) { lib9p_error(ctx, E_POSIX_EACCES, "you do not have write permission on the parent directory"); remove = false; @@ -1386,7 +1433,7 @@ static void handle_Tstat(struct srv_req *ctx, assert(pathinfo); ctx->user = srv_userid_incref(fidinfo->user); - struct lib9p_srv_stat stat = LO_CALL(pathinfo->file, stat, ctx); + struct lib9p_srv_stat stat = CTX_LO_ERR_OR(lib9p_srv_stat, pathinfo->file, stat, ctx); if (lib9p_ctx_has_error(ctx)) goto tstat_return; lib9p_srv_stat_assert(stat); -- cgit v1.2.3-2-g168b From b85e2a4c1bc272cb6ede732751beb55906f7e298 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Thu, 29 May 2025 22:25:02 -0400 Subject: lib9p_srv: Switch to use error.h internally --- lib9p/srv.c | 437 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 212 insertions(+), 225 deletions(-) (limited to 'lib9p/srv.c') diff --git a/lib9p/srv.c b/lib9p/srv.c index 05d7144..085cc8b 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -44,61 +44,6 @@ static_assert(CONFIG_9P_SRV_MAX_HOSTMSG_SIZE <= SSIZE_MAX); /* context ********************************************************************/ -static void lib9p_ctx_clear_error(struct lib9p_srv_ctx *ctx) { - assert(ctx); - ctx->err_num = 0; - ctx->err_msg[0] = '\0'; -} - -static bool lib9p_ctx_has_error(struct lib9p_srv_ctx *ctx) { - assert(ctx); - return ctx->err_msg[0]; -} - -/** Write a -style error into ctx, return -1. */ -#define lib9p_error(ctx, libmisc_errno, ...) ({ \ - if (!lib9p_ctx_has_error(ctx)) { \ - (ctx)->err_num = libmisc_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; \ -}) - -#define CTX_ERR_OR(TYP, func, ctx, ...) \ - ({ \ - TYP##_or_error r = func(ctx __VA_OPT__(,) __VA_ARGS__); \ - TYP v = {}; \ - if (r.is_err && !lib9p_ctx_has_error(ctx)) { \ - (ctx)->err_num = r.err.num; \ - strncpy((ctx)->err_msg, error_msg(r.err), CONFIG_9P_SRV_MAX_ERR_SIZE); \ - error_cleanup(&r.err); \ - } \ - if (!r.is_err) \ - v = r.TYP; \ - v; \ - }) - -#define CTX_LO_ERR_OR(TYP, obj, func, ctx, ...) \ - ({ \ - TYP##_or_error r = LO_CALL(obj, func, ctx __VA_OPT__(,) __VA_ARGS__); \ - TYP v = {}; \ - if (r.is_err && !lib9p_ctx_has_error(ctx)) { \ - (ctx)->err_num = r.err.num; \ - strncpy((ctx)->err_msg, error_msg(r.err), CONFIG_9P_SRV_MAX_ERR_SIZE); \ - error_cleanup(&r.err); \ - } \ - if (!r.is_err) \ - v = r.TYP; \ - v; \ - }) - bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx) { assert(ctx); return cr_chan_can_send(&ctx->flush_ch); @@ -174,6 +119,8 @@ struct srv_fidinfo { } auth; }; }; +typedef struct srv_fidinfo *srv_fidinfop; +DECLARE_ERROR_OR(srv_fidinfop); /* contexts ************************************** * @@ -330,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); @@ -343,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) { @@ -364,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; } /** @@ -371,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); @@ -392,8 +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, E_POSIX_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){ @@ -402,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 *************************************************************/ @@ -427,18 +377,14 @@ static void srv_write_Rmsg(struct srv_req *req, struct lib9p_Rmsg_send_buf *resp srv_nonrespond_error("write: (", r.size_t, ", ", (error, r.err), ")"); } -static void srv_respond_error(struct srv_req *req) { -#if CONFIG_9P_ENABLE_9P2000_u || CONFIG_9P_ENABLE_9P2000_L - assert(req->err_num); -#endif - assert(req->err_msg[0]); +static void srv_respond_error(struct srv_req *req, error err) { + assert(!ERROR_IS_NULL(err)); struct lib9p_msg_Rerror host = { .tag = req->tag, - .errstr = lib9p_strn(req->err_msg, - CONFIG_9P_SRV_MAX_ERR_SIZE), + .errstr = lib9p_str((char *)error_msg(err)), /* cast to discard `const` */ #if CONFIG_9P_ENABLE_9P2000_u - .errnum = libmisc_to_linuxgeneric_errno(req->err_num), + .errnum = libmisc_to_linuxgeneric_errno(err.num), #endif }; @@ -459,6 +405,7 @@ static void srv_respond_error(struct srv_req *req) { srv_msglog(req, LIB9P_TYP_Rerror, &host); srv_write_Rmsg(req, &net); + error_cleanup(&err); } /* read coroutine *************************************************************/ @@ -547,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, E_POSIX_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); @@ -602,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)) { - srv_nonrespond_error("clunk: ", (strn, pseudoreq.err_msg, CONFIG_9P_SRV_MAX_ERR_SIZE)); - lib9p_ctx_clear_error(&pseudoreq); + 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); @@ -681,9 +627,7 @@ void lib9p_srv_worker(struct srv_req *ctx) { /* Unmarshal it. *****************************************************/ size_t_or_error r = lib9p_Tmsg_validate(&ctx->basectx, ctx->net_bytes); if (r.is_err) { - lib9p_error(ctx, r.err.num, (error, r.err)); - error_cleanup(&r.err); - srv_respond_error(ctx); + srv_respond_error(ctx, r.err); goto release; } size_t host_size = r.size_t; @@ -742,34 +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)) { - if (ctx->err_num == E_POSIX_ECANCELED && lib9p_srv_flush_requested(ctx)) { - /* 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); + srv_respond_error(ctx, err); } } else { assert(host_resp); struct lib9p_Rmsg_send_buf net_resp; - error err = lib9p_Rmsg_marshal(&ctx->basectx, - resp_typ, host_resp, - &net_resp); - if (!ERROR_IS_NULL(err)) { - lib9p_error(ctx, err.num, (error, err)); - error_cleanup(&err); + 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* ******************************************************************/ @@ -778,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) { @@ -818,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, - E_POSIX_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; } @@ -850,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)) { - srv_nonrespond_error("clunk: ", (strn, ctx->err_msg, CONFIG_9P_SRV_MAX_ERR_SIZE)); - lib9p_ctx_clear_error(ctx); + error fiderr = srv_fid_del(ctx, fid, fidinfo, false); + if (!ERROR_IS_NULL(fiderr)) { + srv_nonrespond_error("clunk: ", (error, fiderr)); + error_cleanup(&fiderr); } } @@ -862,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 @@ -872,21 +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, E_POSIX_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, E_POSIX_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)) - 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, @@ -894,7 +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, E_POSIX_EBADF, "cannot assign to NOFID"); + err = error_new(E_POSIX_EBADF, "cannot assign to NOFID"); goto tattach_return; } @@ -902,41 +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, E_POSIX_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, E_POSIX_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, 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)); + 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, E_POSIX_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, 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)); + 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, E_POSIX_EACCES, "FID provided as auth-file has not completed authentication"); - if (lib9p_ctx_has_error(ctx)) + 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, E_POSIX_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 = CTX_ERR_OR(lib9p_srv_file, srv->rootdir, ctx, req->aname); - assert(LO_IS_NULL(root_file) == lib9p_ctx_has_error(ctx)); - if (lib9p_ctx_has_error(ctx)) + 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); @@ -945,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; } @@ -954,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, @@ -979,7 +925,7 @@ static void handle_Tflush(struct srv_req *ctx, return; } } - srv_respond(ctx, flush, &resp); + srv_respond(ctx, flush, &resp, err); } static void handle_Twalk(struct srv_req *ctx, @@ -987,17 +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, E_POSIX_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, E_POSIX_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, E_POSIX_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); @@ -1010,7 +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, E_POSIX_ENOTDIR, "not a directory"); + err = error_new(E_POSIX_ENOTDIR, "not a directory"); break; } @@ -1020,21 +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 = CTX_LO_ERR_OR(lib9p_srv_file, pathinfo->file, dwalk, ctx, req->wname[resp.nwqid]); - assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(ctx)); - if (lib9p_ctx_has_error(ctx)) + 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 = CTX_LO_ERR_OR(lib9p_srv_stat, new_pathinfo->file, stat, ctx); - if (lib9p_ctx_has_error(ctx)) + 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, E_POSIX_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; } @@ -1046,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)); + assert(!ERROR_IS_NULL(err)); srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); if (resp.nwqid > 0) - lib9p_ctx_clear_error(ctx); + 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, @@ -1067,18 +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, E_POSIX_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, E_POSIX_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, E_POSIX_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; } } @@ -1094,25 +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 = CTX_LO_ERR_OR(lib9p_srv_stat, parent->file, stat, ctx); - if (lib9p_ctx_has_error(ctx)) + 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, E_POSIX_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 = CTX_LO_ERR_OR(lib9p_srv_stat, pathinfo->file, stat, ctx); - if (lib9p_ctx_has_error(ctx)) + 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, E_POSIX_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; } @@ -1136,8 +1092,8 @@ static void handle_Topen(struct srv_req *ctx, rd = true; break; } - if (!srv_check_perm(ctx, &stat, perm_bits)) { - lib9p_error(ctx, E_POSIX_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; } @@ -1146,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 = CTX_LO_ERR_OR(lib9p_srv_dio, pathinfo->file, dopen, ctx); - assert(LO_IS_NULL(fidinfo->dir.io) == lib9p_ctx_has_error(ctx)); - if (lib9p_ctx_has_error(ctx)) + 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 = CTX_LO_ERR_OR(lib9p_srv_fio, pathinfo->file, fopen, ctx, - rd, wr, - reqmode & LIB9P_O_TRUNC); - assert(LO_IS_NULL(fidinfo->file.io) == lib9p_ctx_has_error(ctx)); - if (lib9p_ctx_has_error(ctx)) + 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; @@ -1185,16 +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, E_POSIX_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) { @@ -1230,11 +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, E_POSIX_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, E_POSIX_EINVAL, "FID not open for reading"); + err = error_new(E_POSIX_EINVAL, "FID not open for reading"); goto tread_return; } @@ -1249,7 +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, E_POSIX_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. */ @@ -1262,33 +1224,45 @@ static void handle_Tread(struct srv_req *ctx, if (fidinfo->dir.buffered_dirent.name.len) { member_dirent = fidinfo->dir.buffered_dirent; } else { - member_dirent = CTX_LO_ERR_OR(lib9p_srv_dirent, fidinfo->dir.io, dread, ctx, fidinfo->dir.idx); - if (lib9p_ctx_has_error(ctx)) { - 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); + } + 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 = CTX_LO_ERR_OR(lib9p_srv_stat, member_pathinfo->file, stat, ctx); - if (lib9p_ctx_has_error(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 = CTX_LO_ERR_OR(lib9p_srv_file, dir_pathinfo->file, dwalk, ctx, member_dirent.name); - assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(ctx)); - if (lib9p_ctx_has_error(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_stat = CTX_LO_ERR_OR(lib9p_srv_stat, member_file, stat, ctx); - if (lib9p_ctx_has_error(ctx)) + } + 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 (false) { member_err: @@ -1296,7 +1270,7 @@ static void handle_Tread(struct srv_req *ctx, LO_CALL(member_file, free); if (!resp.count) goto tread_return; - lib9p_ctx_clear_error(ctx); + error_cleanup(&err); break; } lib9p_srv_stat_assert(member_stat); @@ -1307,7 +1281,7 @@ static void handle_Tread(struct srv_req *ctx, LO_CALL(member_file, free); if (!nbytes) { if (!resp.count) { - lib9p_error(ctx, E_POSIX_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; @@ -1323,10 +1297,12 @@ static void handle_Tread(struct srv_req *ctx, #endif break; case SRV_FILETYPE_FILE: - struct iovec iov = CTX_LO_ERR_OR(iovec, fidinfo->file.io, pread, ctx, req->count, req->offset); - if (!lib9p_ctx_has_error(ctx)) { - 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; } @@ -1338,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); } @@ -1352,11 +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, E_POSIX_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, E_POSIX_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) @@ -1364,11 +1340,15 @@ static void handle_Twrite(struct srv_req *ctx, /* Do it. */ ctx->user = srv_userid_incref(fidinfo->user); - resp.count = CTX_LO_ERR_OR(uint32_t, 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, @@ -1377,14 +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, E_POSIX_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, @@ -1393,7 +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, E_POSIX_EBADF, "bad file number ", req->fid); + err = error_new(E_POSIX_EBADF, "bad file number ", req->fid); goto tremove_return; } @@ -1401,15 +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, E_POSIX_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 = CTX_LO_ERR_OR(lib9p_srv_stat, parent->file, stat, ctx); - if (!lib9p_ctx_has_error(ctx) && !srv_check_perm(ctx, &parent_stat, 0b010)) { - lib9p_error(ctx, E_POSIX_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; } @@ -1417,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, @@ -1426,31 +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, E_POSIX_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 = CTX_LO_ERR_OR(lib9p_srv_stat, pathinfo->file, stat, ctx); - if (lib9p_ctx_has_error(ctx)) + 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, E_POSIX_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 @@ -1459,9 +1446,9 @@ static void handle_Topenfd(struct srv_req *ctx, struct lib9p_msg_Topenfd *req) { srv_handler_common(ctx, openfd, req); - lib9p_error(ctx, E_POSIX_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 @@ -1470,26 +1457,26 @@ static void handle_Tsession(struct srv_req *ctx, struct lib9p_msg_Tsession *req) { srv_handler_common(ctx, session, req); - lib9p_error(ctx, E_POSIX_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, E_POSIX_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, E_POSIX_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 -- cgit v1.2.3-2-g168b