summaryrefslogtreecommitdiff
path: root/lib9p/srv.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-18 01:02:02 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-19 12:53:32 -0600
commitb5d409009efa48714852411d7a2e2eb106333893 (patch)
tree98eb8e21b2a0e1e141c9867140f06fb4dd4553fd /lib9p/srv.c
parent539004128822db8c2289544271019d8fd2038c41 (diff)
lib9p_srv: Rework srv_fid_del()
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r--lib9p/srv.c96
1 files changed, 52 insertions, 44 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c
index edb39ba..0196a0e 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -200,11 +200,9 @@ static struct lib9p_srv_userid *srv_userid_decref(struct lib9p_srv_userid *useri
assert(userid);
assert(userid->refcount);
userid->refcount--;
- if (!userid->refcount) {
+ if (!userid->refcount)
free(userid);
- return NULL;
- }
- return userid;
+ return NULL;
}
static struct lib9p_srv_userid *srv_userid_incref(struct lib9p_srv_userid *userid) {
@@ -272,32 +270,21 @@ 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, bool remove) {
- struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, fid);
+static inline void srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, struct srv_fidinfo *fidinfo, bool remove) {
+ assert(ctx);
+ assert(!ctx->user);
assert(fidinfo);
+
if (fidinfo->flags & FIDFLAG_RCLOSE)
remove = true;
+ ctx->user = srv_userid_incref(fidinfo->user);
+
struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path);
assert(pathinfo);
- if (remove) {
- if (pathinfo->parent_dir == fidinfo->path) {
- lib9p_error(&ctx->basectx,
- LIB9P_ERRNO_L_EBUSY, "cannot remove root");
- goto clunk;
- }
- struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir);
- assert(parent);
- struct lib9p_stat parent_stat = LO_CALL(parent->file, stat, ctx);
- if (!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");
- goto clunk;
- }
+ if (remove)
LO_CALL(pathinfo->file, remove, ctx);
- }
- clunk:
if (fidinfo->flags & FIDFLAG_OPEN) {
switch (fidinfo->type) {
case SRV_FILETYPE_DIR:
@@ -315,6 +302,8 @@ static inline void srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, bool remove
fidinfo->user = srv_userid_decref(fidinfo->user);
srv_path_decref(ctx, fidinfo->path);
map_del(&ctx->parent_sess->fids, fid);
+
+ ctx->user = srv_userid_decref(ctx->user);
}
/**
@@ -543,17 +532,19 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) {
assert(map_len(&sess.reqs) == 0);
map_free(&sess.reqs);
+ struct srv_req pseudoreq = {
+ .basectx = {
+ .version = sess.version,
+ .max_msg_size = sess.max_msg_size,
+ },
+ .parent_sess = &sess,
+ };
MAP_FOREACH(&sess.fids, fid, fidinfo) {
- struct srv_req req = {
- .basectx = {
- .version = sess.version,
- .max_msg_size = sess.max_msg_size,
- },
- .parent_sess = &sess,
- };
- srv_fid_del(&req, fid, false);
- if (lib9p_ctx_has_error(&req.basectx))
- errorf("clunk: %.*s", CONFIG_9P_MAX_ERR_SIZE, req.basectx.err_msg);
+ srv_fid_del(&pseudoreq, fid, fidinfo, false);
+ if (lib9p_ctx_has_error(&pseudoreq.basectx)) {
+ srv_nonrespond_errorf("clunk: %.*s", CONFIG_9P_MAX_ERR_SIZE, pseudoreq.basectx.err_msg);
+ lib9p_ctx_clear_error(&pseudoreq.basectx);
+ }
}
map_free(&sess.fids);
@@ -781,10 +772,12 @@ static void handle_Tversion(struct srv_req *ctx,
cr_select_v(i, args);
}
}
- if (map_len(&ctx->parent_sess->fids)) {
- /* Close all FIDs. */
- MAP_FOREACH(&ctx->parent_sess->fids, fid, fidinfo) {
- srv_fid_del(ctx, fid, false);
+ /* 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_errorf("clunk: %.*s", CONFIG_9P_MAX_ERR_SIZE, ctx->basectx.err_msg);
+ lib9p_ctx_clear_error(&ctx->basectx);
}
}
@@ -1260,11 +1253,9 @@ static void handle_Tclunk(struct srv_req *ctx,
goto tclunk_return;
}
- ctx->user = srv_userid_incref(fidinfo->user);
- srv_fid_del(ctx, req->fid, false);
+ srv_fid_del(ctx, req->fid, fidinfo, false);
+
tclunk_return:
- if (ctx->user)
- ctx->user = srv_userid_decref(ctx->user);
srv_respond(ctx, clunk, &resp);
}
@@ -1279,11 +1270,28 @@ static void handle_Tremove(struct srv_req *ctx,
goto tremove_return;
}
- ctx->user = srv_userid_incref(fidinfo->user);
- srv_fid_del(ctx, req->fid, true);
+ bool remove = true;
+ 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");
+ remove = false;
+ goto tremove_main;
+ }
+ struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, pathinfo->parent_dir);
+ assert(parent);
+ struct lib9p_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");
+ remove = false;
+ goto tremove_main;
+ }
+
+ tremove_main:
+ srv_fid_del(ctx, req->fid, fidinfo, remove);
tremove_return:
- if (ctx->user)
- ctx->user = srv_userid_decref(ctx->user);
srv_respond(ctx, remove, &resp);
}