summaryrefslogtreecommitdiff
path: root/lib9p
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-10-12 17:53:05 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-10-12 17:53:05 -0600
commiteb4e0bc7dd140b356a62071bf8e0427fc0cee816 (patch)
treec71d7daf1dfccf7e261c2fe22d7d5a0bd55bf34d /lib9p
parent7508de2e4ec10baf46c7cde6e7774051ac19e95a (diff)
get read working correctly
Diffstat (limited to 'lib9p')
-rw-r--r--lib9p/include/lib9p/9p.h11
-rw-r--r--lib9p/srv.c66
2 files changed, 47 insertions, 30 deletions
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");