summaryrefslogtreecommitdiff
path: root/lib9p/srv.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r--lib9p/srv.c515
1 files changed, 272 insertions, 243 deletions
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