From eb4e0bc7dd140b356a62071bf8e0427fc0cee816 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sat, 12 Oct 2024 17:53:05 -0600 Subject: get read working correctly --- lib9p/include/lib9p/9p.h | 11 ++++++++ lib9p/srv.c | 66 ++++++++++++++++++++++++++---------------------- 2 files changed, 47 insertions(+), 30 deletions(-) (limited to 'lib9p') diff --git a/lib9p/include/lib9p/9p.h b/lib9p/include/lib9p/9p.h index 2511e3d..e7ddb15 100644 --- a/lib9p/include/lib9p/9p.h +++ b/lib9p/include/lib9p/9p.h @@ -56,6 +56,17 @@ static bool lib9p_ctx_has_error(struct lib9p_ctx *ctx) { return ctx->err_msg[0]; } +/** Assert that a `struct lib9p_stat` object looks valid. */ +static inline void lib9p_assert_stat(struct lib9p_stat stat) { + assert( ((bool)(stat.file_mode & LIB9P_DM_DIR )) == ((bool)(stat.file_qid.type & LIB9P_QT_DIR )) ); + assert( ((bool)(stat.file_mode & LIB9P_DM_APPEND )) == ((bool)(stat.file_qid.type & LIB9P_QT_APPEND )) ); + assert( ((bool)(stat.file_mode & LIB9P_DM_EXCL )) == ((bool)(stat.file_qid.type & LIB9P_QT_EXCL )) ); + assert( ((bool)(stat.file_mode & _LIB9P_DM_PLAN9_MOUNT)) == ((bool)(stat.file_qid.type & _LIB9P_QT_PLAN9_MOUNT)) ); + assert( ((bool)(stat.file_mode & LIB9P_DM_AUTH )) == ((bool)(stat.file_qid.type & LIB9P_QT_AUTH )) ); + assert( ((bool)(stat.file_mode & LIB9P_DM_TMP )) == ((bool)(stat.file_qid.type & LIB9P_QT_TMP )) ); + assert( (stat.file_size == 0) || !(stat.file_mode & LIB9P_DM_DIR) ); +} + /** Write an static error into ctx, return -1. */ int lib9p_error(struct lib9p_ctx *ctx, uint32_t linux_errno, char const *msg); /** Write a printf-style error into ctx, return -1. */ diff --git a/lib9p/srv.c b/lib9p/srv.c index 1f62e27..6953687 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -386,14 +386,14 @@ static void handle_message(struct _lib9p_srv_req *ctx) { } } -#define handler_common(ctx, req, resp) do { \ +#define util_handler_common(ctx, req, resp) do { \ assert(ctx); \ assert(req); \ assert(resp); \ resp->tag = req->tag; \ } while (0) -static inline bool check_perm(struct lib9p_srv_ctx *ctx, struct lib9p_stat *stat, uint8_t action) { +static inline bool util_check_perm(struct lib9p_srv_ctx *ctx, struct lib9p_stat *stat, uint8_t action) { assert(ctx); assert(stat); assert(action); @@ -404,12 +404,12 @@ static inline bool check_perm(struct lib9p_srv_ctx *ctx, struct lib9p_stat *stat return mode & action; } -static inline bool release(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *file) { +static inline bool util_release(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *file) { assert(file); file->_refcount--; if (file->_refcount == 0) { if (file->_parent_dir != file) - release(ctx, file->_parent_dir); + util_release(ctx, file->_parent_dir); file->vtable->free(ctx, file); } return lib9p_ctx_has_error(&ctx->basectx); @@ -418,7 +418,7 @@ static inline bool release(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *fil static void handle_Tversion(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tversion *req, struct lib9p_msg_Rversion *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); enum lib9p_version version = LIB9P_VER_unknown; @@ -494,7 +494,7 @@ static void handle_Tversion(struct _lib9p_srv_req *ctx, static void handle_Tauth(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tauth *req, struct lib9p_msg_Rauth *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); ctx->ctx.uid = req->n_uname; ctx->ctx.uname = req->uname.utf8; @@ -514,7 +514,7 @@ static void handle_Tauth(struct _lib9p_srv_req *ctx, static void handle_Tattach(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tattach *req, struct lib9p_msg_Rattach *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); ctx->ctx.uid = req->n_uname; ctx->ctx.uname = req->uname.utf8; @@ -574,7 +574,7 @@ static void handle_Tattach(struct _lib9p_srv_req *ctx, })) { lib9p_error(&ctx->ctx.basectx, LINUX_EMFILE, "too many open files"); - release(&ctx->ctx, rootdir); + util_release(&ctx->ctx, rootdir); return; } @@ -585,6 +585,7 @@ static void handle_Tattach(struct _lib9p_srv_req *ctx, &(struct lib9p_msg_Rclunk){}); return; } + lib9p_assert_stat(stat); assert(stat.file_mode & LIB9P_DM_DIR); @@ -595,7 +596,7 @@ static void handle_Tattach(struct _lib9p_srv_req *ctx, static void handle_Tflush(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tflush *req, struct lib9p_msg_Rflush *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); struct _lib9p_srv_req **oldreqp = reqmap_load(&ctx->parent_sess->reqs, req->oldtag); if (oldreqp) @@ -605,7 +606,7 @@ static void handle_Tflush(struct _lib9p_srv_req *ctx, static void handle_Twalk(struct _lib9p_srv_req *ctx, struct lib9p_msg_Twalk *req, struct lib9p_msg_Rwalk *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { @@ -632,7 +633,7 @@ static void handle_Twalk(struct _lib9p_srv_req *ctx, resp->wqid = (struct lib9p_qid *)(&resp[1]); for (resp->nwqid = 0; resp->nwqid < req->nwname; resp->nwqid++) { struct lib9p_srv_file *member; - if (strcmp(req->wname[resp->nwqid].utf8, "..")) { + if (strcmp(req->wname[resp->nwqid].utf8, "..") == 0) { member = dir->_parent_dir; } else { if (!isdir) { @@ -652,21 +653,22 @@ static void handle_Twalk(struct _lib9p_srv_req *ctx, struct lib9p_stat stat = member->vtable->stat(&ctx->ctx, member); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) { - release(&ctx->ctx, member); /* presumption of taking ref-A failed */ + util_release(&ctx->ctx, member); /* presumption of taking ref-A failed */ break; } + lib9p_assert_stat(stat); isdir = stat.file_mode & LIB9P_DM_DIR; - if (isdir && !check_perm(&ctx->ctx, &stat, 0b001)) { + if (isdir && !util_check_perm(&ctx->ctx, &stat, 0b001)) { lib9p_error(&ctx->ctx.basectx, LINUX_EACCES, "you do not have execute permission on that directory"); - release(&ctx->ctx, member); /* presumption of taking ref-A failed */ + util_release(&ctx->ctx, member); /* presumption of taking ref-A failed */ break; } resp->wqid[resp->nwqid] = stat.file_qid; /* presumption of taking ref-A succeeded */ - release(&ctx->ctx, dir); + util_release(&ctx->ctx, dir); dir = member; } if (resp->nwqid == req->nwname) { @@ -681,12 +683,12 @@ static void handle_Twalk(struct _lib9p_srv_req *ctx, })) { lib9p_error(&ctx->ctx.basectx, LINUX_EMFILE, "too many open files"); - release(&ctx->ctx, dir); /* presumption of insertion failed */ + util_release(&ctx->ctx, dir); /* presumption of insertion failed */ } } else { assert(lib9p_ctx_has_error(&ctx->ctx.basectx)); if (req->newfid != req->fid) - release(&ctx->ctx, dir); /* presumption of insertion failed */ + util_release(&ctx->ctx, dir); /* presumption of insertion failed */ if (resp->nwqid > 0) lib9p_ctx_clear_error(&ctx->ctx.basectx); } @@ -695,7 +697,7 @@ static void handle_Twalk(struct _lib9p_srv_req *ctx, static void handle_Topen(struct _lib9p_srv_req *ctx, struct lib9p_msg_Topen *req, struct lib9p_msg_Ropen *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); /* Check that the FID is valid for this. */ struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); @@ -729,7 +731,8 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, struct lib9p_stat parent_stat = file->_parent_dir->vtable->stat(&ctx->ctx, file->_parent_dir); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) return; - if (!check_perm(&ctx->ctx, &parent_stat, 0b010)) { + lib9p_assert_stat(parent_stat); + if (!util_check_perm(&ctx->ctx, &parent_stat, 0b010)) { lib9p_error(&ctx->ctx.basectx, LINUX_EACCES, "permission denied to remove-on-close"); return; @@ -739,6 +742,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, struct lib9p_stat stat = file->vtable->stat(&ctx->ctx, file); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) return; + lib9p_assert_stat(stat); if (stat.file_mode & LIB9P_QT_APPEND) reqmode = reqmode & ~LIB9P_O_TRUNC; uint8_t perm_bits = 0; @@ -760,7 +764,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, fidflags = fidflags | FIDFLAG_OPEN_R; break; } - if (!check_perm(&ctx->ctx, &stat, perm_bits)) { + if (!util_check_perm(&ctx->ctx, &stat, perm_bits)) { lib9p_error(&ctx->ctx.basectx, LINUX_EACCES, "permission denied"); } @@ -779,7 +783,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, static void handle_Tcreate(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tcreate *req, struct lib9p_msg_Rcreate *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "create not (yet?) implemented"); @@ -788,7 +792,7 @@ static void handle_Tcreate(struct _lib9p_srv_req *ctx, static void handle_Tread(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tread *req, struct lib9p_msg_Rread *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); /* Check that the FID is valid for this. */ struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); @@ -837,7 +841,7 @@ static void handle_Tread(struct _lib9p_srv_req *ctx, static void handle_Twrite(struct _lib9p_srv_req *ctx, struct lib9p_msg_Twrite *req, struct lib9p_msg_Rwrite *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); /* Check that the FID is valid for this. */ struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); @@ -862,7 +866,7 @@ static void handle_Twrite(struct _lib9p_srv_req *ctx, static void handle_Tclunk(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tclunk *req, struct lib9p_msg_Rclunk *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { @@ -884,7 +888,7 @@ static void handle_Tclunk(struct _lib9p_srv_req *ctx, static void handle_Tremove(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tremove *req, struct lib9p_msg_Rremove *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "remove not (yet?) implemented"); @@ -893,7 +897,7 @@ static void handle_Tremove(struct _lib9p_srv_req *ctx, static void handle_Tstat(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tstat *req, struct lib9p_msg_Rstat *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, req->fid); if (!fidinfo) { @@ -903,12 +907,14 @@ static void handle_Tstat(struct _lib9p_srv_req *ctx, } resp->stat = fidinfo->file->vtable->stat(&ctx->ctx, fidinfo->file); + if (!lib9p_ctx_has_error(&ctx->ctx.basectx)) + lib9p_assert_stat(resp->stat); } static void handle_Twstat(struct _lib9p_srv_req *ctx, struct lib9p_msg_Twstat *req, struct lib9p_msg_Rwstat *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "wstat not (yet?) implemented"); @@ -918,7 +924,7 @@ static void handle_Twstat(struct _lib9p_srv_req *ctx, static void handle_Tsession(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tsession *req, struct lib9p_msg_Rsession *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "session not (yet?) implemented"); @@ -927,7 +933,7 @@ static void handle_Tsession(struct _lib9p_srv_req *ctx, static void handle_Tsread(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tsread *req, struct lib9p_msg_Rsread *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "sread not (yet?) implemented"); @@ -936,7 +942,7 @@ static void handle_Tsread(struct _lib9p_srv_req *ctx, static void handle_Tswrite(struct _lib9p_srv_req *ctx, struct lib9p_msg_Tswrite *req, struct lib9p_msg_Rswrite *resp) { - handler_common(ctx, req, resp); + util_handler_common(ctx, req, resp); lib9p_error(&ctx->ctx.basectx, LINUX_EOPNOTSUPP, "swrite not (yet?) implemented"); -- cgit v1.2.3-2-g168b