summaryrefslogtreecommitdiff
path: root/lib9p/srv.c
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-13 01:04:59 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-04-13 02:33:42 -0600
commitb267e241f0545b68864fb2bcf593c02f3bc2cf19 (patch)
tree5fb86e8ce4033a9b2c30546ee39d768fcac39b11 /lib9p/srv.c
parent06cc1184f375ce5929010254781483277d9447d2 (diff)
lib9p: srv: Try to go for consistent naming
Diffstat (limited to 'lib9p/srv.c')
-rw-r--r--lib9p/srv.c502
1 files changed, 260 insertions, 242 deletions
diff --git a/lib9p/srv.c b/lib9p/srv.c
index b8b6683..ac65699 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -67,10 +67,19 @@ void lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) {
/* structs ********************************************************************/
+enum srv_filetype {
+ SRV_FILETYPE_FILE,
+ SRV_FILETYPE_DIR,
+ SRV_FILETYPE_AUTH,
+};
+
+/* path *****************************************/
+
typedef typeof( ((struct lib9p_qid){}).path ) srv_path_t;
struct srv_pathinfo {
lo_interface lib9p_srv_file file;
+ enum srv_filetype type;
srv_path_t parent_dir;
/* References from other srv_pathinfos (via .parent_dir) or
@@ -80,7 +89,7 @@ struct srv_pathinfo {
unsigned int io_refcount;
};
-MAP_DECLARE(pathmap, srv_path_t, struct srv_pathinfo);
+/* fid ******************************************/
#define FIDFLAG_OPEN_R (1<<0)
#define FIDFLAG_OPEN_W (1<<1)
@@ -90,6 +99,7 @@ MAP_DECLARE(pathmap, srv_path_t, struct srv_pathinfo);
struct srv_fidinfo {
srv_path_t path;
uint8_t flags;
+ enum srv_filetype type;
union {
struct {
lo_interface lib9p_srv_fio io;
@@ -102,10 +112,9 @@ struct srv_fidinfo {
};
};
-MAP_DECLARE(fidmap, lib9p_fid_t, struct srv_fidinfo);
-MAP_DECLARE(reqmap, lib9p_tag_t, struct lib9p_srv_ctx *);
-
-/* The hierarchy of concepts is:
+/* contexts **************************************
+ *
+ * The hierarchy of contexts is:
*
* server -> connection -> session -> request
*
@@ -123,6 +132,9 @@ struct srv_conn {
};
#define srv_sess _lib9p_srv_sess
+MAP_DECLARE(srv_pathmap, srv_path_t, struct srv_pathinfo);
+MAP_DECLARE(srv_fidmap, lib9p_fid_t, struct srv_fidinfo);
+MAP_DECLARE(srv_reqmap, lib9p_tag_t, struct lib9p_srv_ctx *);
struct srv_sess {
/* immutable */
struct srv_conn *parent_conn;
@@ -131,16 +143,169 @@ struct srv_sess {
/* mutable */
bool initialized;
bool closing;
- struct pathmap paths; /* srv_path_t => `lib9p_srv_file` + metadata */
- struct fidmap fids; /* lib9p_fid_t => `lib9p_srv_{fio,dio}` + metadata */
- struct reqmap reqs; /* lib9p_tag_t => `struct srv_req *` */
+ struct srv_pathmap paths; /* srv_path_t => `lib9p_srv_file` + metadata */
+ struct srv_fidmap fids; /* lib9p_fid_t => `lib9p_srv_{fio,dio}` + metadata */
+ struct srv_reqmap reqs; /* lib9p_tag_t => `struct srv_req *` */
};
#define srv_req lib9p_srv_ctx /* struct lib9p_srv_ctx {} is defined in <lib9p/srv.h> */
+/* utilities for the above types **********************************************/
+
+static inline enum srv_filetype srv_qid_filetype(struct lib9p_qid qid) {
+ if (qid.type & LIB9P_QT_AUTH)
+ return SRV_FILETYPE_AUTH;
+ if (qid.type & LIB9P_QT_DIR)
+ return SRV_FILETYPE_DIR;
+ return SRV_FILETYPE_FILE;
+}
+
+static inline bool srv_check_perm(struct srv_req *ctx, struct lib9p_stat *stat, uint8_t action) {
+ assert(ctx);
+ assert(stat);
+ assert(action);
+
+ /* TODO actually check user and group instead of just assuming "other". */
+ uint8_t mode = (uint8_t)(stat->file_mode & 07);
+
+ return mode & action;
+}
+
+/**
+ * Ensures that `file` is saved into the pathmap, and increments the
+ * gc_refcount by 1 (for presumptive insertion into the fidmap).
+ * parent_path's gc_refcount is also incremented as appropriate.
+ *
+ * Returns a pointer to the stored pathinfo.
+ */
+static inline struct srv_pathinfo *srv_path_save(struct srv_req *ctx,
+ lo_interface lib9p_srv_file file,
+ srv_path_t parent_path) {
+ assert(ctx);
+ assert(!LO_IS_NULL(file));
+
+ struct lib9p_qid qid = LO_CALL(file, qid);
+ struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, qid.path);
+ if (pathinfo)
+ assert(LO_EQ(pathinfo->file, file));
+ else {
+ pathinfo = map_store(&ctx->parent_sess->paths, qid.path,
+ (struct srv_pathinfo){
+ .file = file,
+ .type = srv_qid_filetype(qid),
+ .parent_dir = parent_path,
+ .gc_refcount = 0,
+ .io_refcount = 0,
+ });
+ assert(pathinfo);
+ if (parent_path != qid.path) {
+ struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, parent_path);
+ assert(parent);
+ parent->gc_refcount++;
+ }
+ }
+ pathinfo->gc_refcount++;
+ return pathinfo;
+}
+
+/**
+ * Decrement the path's gc_refcount, and trigger garbage collection as
+ * appropriate.
+ */
+static inline void srv_path_decref(struct srv_req *ctx, srv_path_t path) {
+ assert(ctx);
+
+ struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, path);
+ assert(pathinfo);
+ pathinfo->gc_refcount--;
+ if (pathinfo->gc_refcount == 0) {
+ if (pathinfo->parent_dir != path)
+ srv_path_decref(ctx, pathinfo->parent_dir);
+ LO_CALL(pathinfo->file, free);
+ map_del(&ctx->parent_sess->paths, 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);
+ if (!fidinfo) {
+ lib9p_errorf(&ctx->basectx,
+ LINUX_EBADF, "bad file number %"PRIu32, fid);
+ return;
+ }
+ if (fidinfo->flags & FIDFLAG_RCLOSE)
+ remove = true;
+ struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path);
+ assert(pathinfo);
+
+ if (remove) {
+ if (pathinfo->parent_dir == fidinfo->path) {
+ lib9p_errorf(&ctx->basectx,
+ LINUX_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,
+ LINUX_EACCES, "remove: you do not have write permission on the parent directory");
+ goto clunk;
+ }
+ LO_CALL(pathinfo->file, remove, ctx);
+ }
+
+ clunk:
+ if (fidinfo->flags & FIDFLAG_OPEN) {
+ switch (fidinfo->type) {
+ case SRV_FILETYPE_DIR:
+ LO_CALL(fidinfo->dir.io, iofree);
+ break;
+ case SRV_FILETYPE_FILE:
+ LO_CALL(fidinfo->file.io, iofree);
+ break;
+ case SRV_FILETYPE_AUTH:
+ assert_notreached("TODO: auth not yet implemented");
+ break;
+ }
+ pathinfo->io_refcount--;
+ }
+ srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path);
+ map_del(&ctx->parent_sess->fids, fid);
+}
+
+/**
+ * Store fid as pointing to pathinfo. Assumes that
+ * pathinfo->gc_refcount has already been incremented; does *not*
+ * decrement it on failure.
+ */
+static struct srv_fidinfo *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);
+
+ struct lib9p_qid qid = LO_CALL(pathinfo->file, qid);
+
+ if (map_load(&ctx->parent_sess->fids, fid)) {
+ if (overwrite) {
+ srv_fid_del(ctx, fid, false);
+ } else {
+ lib9p_error(&ctx->basectx,
+ LINUX_EBADF, "FID already in use");
+ return NULL;
+ }
+ }
+ struct srv_fidinfo *fidinfo = map_store(&ctx->parent_sess->fids, fid, (struct srv_fidinfo){
+ .path = qid.path,
+ .type = srv_qid_filetype(qid),
+ });
+ assert(fidinfo);
+ return fidinfo;
+}
+
/* base utilities *************************************************************/
-static void msglog(struct srv_req *req, enum lib9p_msg_type typ, void *hostmsg) {
+static void srv_msglog(struct srv_req *req, enum lib9p_msg_type typ, void *hostmsg) {
struct lib9p_srv *srv = req->parent_sess->parent_conn->parent_srv;
if (srv->msglog) {
srv->msglog(req, typ, hostmsg);
@@ -155,9 +320,7 @@ static void msglog(struct srv_req *req, enum lib9p_msg_type typ, void *hostmsg)
#pragma GCC diagnostic pop
}
-#define nonrespond_errorf errorf
-
-static ssize_t write_Rmsg(struct srv_req *req, struct lib9p_Rmsg_send_buf *resp) {
+static ssize_t srv_write_Rmsg(struct srv_req *req, struct lib9p_Rmsg_send_buf *resp) {
ssize_t r;
cr_mutex_lock(&req->parent_sess->parent_conn->writelock);
r = io_writev(req->parent_sess->parent_conn->fd, resp->iov, resp->iov_cnt);
@@ -165,7 +328,9 @@ static ssize_t write_Rmsg(struct srv_req *req, struct lib9p_Rmsg_send_buf *resp)
return r;
}
-static void respond_error(struct srv_req *req) {
+#define srv_nonrespond_errorf errorf
+
+static void srv_respond_error(struct srv_req *req) {
#if CONFIG_9P_ENABLE_9P2000_u
assert(req->basectx.err_num);
#endif
@@ -199,26 +364,26 @@ static void respond_error(struct srv_req *req) {
LIB9P_TYP_Rerror, &host,
&net);
- msglog(req, LIB9P_TYP_Rerror, &host);
- r = write_Rmsg(req, &net);
+ srv_msglog(req, LIB9P_TYP_Rerror, &host);
+ r = srv_write_Rmsg(req, &net);
if (r < 0)
- nonrespond_errorf("write: %s", net_strerror(-r));
+ srv_nonrespond_errorf("write: %s", net_strerror(-r));
}
/* read coroutine *************************************************************/
-static bool read_exactly(lo_interface net_stream_conn fd, uint8_t *buf, size_t goal, size_t *done) {
+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) {
- nonrespond_errorf("read: %s", net_strerror(-r));
+ srv_nonrespond_errorf("read: %s", net_strerror(-r));
return true;
} else if (r == 0) {
if (*done != 0)
- nonrespond_errorf("read: unexpected EOF");
+ srv_nonrespond_errorf("read: unexpected EOF");
return true;
}
*done += r;
@@ -226,8 +391,6 @@ static bool read_exactly(lo_interface net_stream_conn fd, uint8_t *buf, size_t g
return false;
}
-static void handle_message(struct srv_req *ctx);
-
void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stream_listener listener) {
assert(srv);
assert(srv->rootdir);
@@ -238,7 +401,7 @@ void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stre
for (;;) {
lo_interface net_stream_conn conn = LO_CALL(listener, accept);
if (LO_IS_NULL(conn)) {
- nonrespond_errorf("accept: error");
+ srv_nonrespond_errorf("accept: error");
srv->readers--;
if (srv->readers == 0)
while (srv->writers > 0)
@@ -249,7 +412,7 @@ void lib9p_srv_accept_and_read_loop(struct lib9p_srv *srv, lo_interface net_stre
}
}
-static void clunkremove(struct srv_req *ctx, lib9p_fid_t fid, bool remove);
+static void handle_message(struct srv_req *ctx);
void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) {
assert(srv);
@@ -271,14 +434,14 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) {
/* Read the message. */
size_t done = 0;
uint8_t buf[7];
- if (read_exactly(conn.fd, buf, 4, &done))
+ if (srv_read_exactly(conn.fd, buf, 4, &done))
break;
size_t goal = uint32le_decode(buf);
if (goal < 7) {
- nonrespond_errorf("T-message is impossibly small");
+ srv_nonrespond_errorf("T-message is impossibly small");
break;
}
- if (read_exactly(conn.fd, buf, 7, &done))
+ if (srv_read_exactly(conn.fd, buf, 7, &done))
break;
struct lib9p_srv_authinfo authinfo = {};
struct srv_req req = {
@@ -298,13 +461,13 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) {
sess.initialized ? "negotiated" : "server",
goal,
sess.max_msg_size);
- respond_error(&req);
+ srv_respond_error(&req);
continue;
}
req.net_bytes = malloc(goal);
assert(req.net_bytes);
memcpy(req.net_bytes, buf, done);
- if (read_exactly(conn.fd, req.net_bytes, goal, &done)) {
+ if (srv_read_exactly(conn.fd, req.net_bytes, goal, &done)) {
free(req.net_bytes);
break;
}
@@ -338,7 +501,7 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) {
},
.parent_sess = &sess,
};
- clunkremove(&req, fid, false);
+ 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);
}
@@ -448,151 +611,41 @@ static void handle_message(struct srv_req *ctx) {
enum lib9p_msg_type typ;
lib9p_Tmsg_unmarshal(&ctx->basectx, ctx->net_bytes,
&typ, host_req);
- msglog(ctx, typ, host_req);
+ srv_msglog(ctx, typ, host_req);
/* Handle it. */
tmessage_handlers[typ](ctx, (void *)host_req, (void *)host_resp);
write:
if (lib9p_ctx_has_error(&ctx->basectx))
- respond_error(ctx);
+ srv_respond_error(ctx);
else {
struct lib9p_Rmsg_send_buf net_resp;
if (lib9p_Rmsg_marshal(&ctx->basectx,
typ+1, host_resp,
&net_resp))
goto write;
- msglog(ctx, typ+1, &host_resp);
- write_Rmsg(ctx, &net_resp);
+ srv_msglog(ctx, typ+1, &host_resp);
+ srv_write_Rmsg(ctx, &net_resp);
}
if (host_req)
free(host_req);
free(ctx->net_bytes);
}
-#define util_handler_common(ctx, req, resp) do { \
- assert(ctx); \
- assert(req); \
- assert(resp); \
- resp->tag = req->tag; \
- } while (0)
-
-static inline bool srv_util_check_perm(struct srv_req *ctx, struct lib9p_stat *stat, uint8_t action) {
- assert(ctx);
- assert(stat);
- assert(action);
-
- /* TODO actually check user and group instead of just assuming "other". */
- uint8_t mode = (uint8_t)(stat->file_mode & 07);
-
- return mode & action;
-}
-
-/**
- * Ensures that `file` is saved into the pathmap, and increments the
- * gc_refcount by 1 (for presumptive insertion into the fidmap).
- * parent_path's gc_refcount is also incremented as appropriate.
- *
- * Returns a pointer to the stored pathinfo.
- */
-static inline struct srv_pathinfo *srv_util_pathsave(struct srv_req *ctx,
- lo_interface lib9p_srv_file file,
- srv_path_t parent_path) {
- assert(ctx);
- assert(!LO_IS_NULL(file));
-
- struct lib9p_qid qid = LO_CALL(file, qid);
- struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, qid.path);
- if (pathinfo)
- assert(LO_EQ(pathinfo->file, file));
- else {
- pathinfo = map_store(&ctx->parent_sess->paths, qid.path,
- (struct srv_pathinfo){
- .file = file,
- .parent_dir = parent_path,
- .gc_refcount = 0,
- .io_refcount = 0,
- });
- assert(pathinfo);
- if (parent_path != qid.path) {
- struct srv_pathinfo *parent = map_load(&ctx->parent_sess->paths, parent_path);
- assert(parent);
- parent->gc_refcount++;
- }
- }
- pathinfo->gc_refcount++;
- return pathinfo;
-}
-
-/**
- * Decrement the path's gc_refcount, and trigger garbage collection as
- * appropriate.
- */
-static inline void srv_util_pathfree(struct srv_req *ctx, srv_path_t path) {
- assert(ctx);
-
- struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, path);
- assert(pathinfo);
- pathinfo->gc_refcount--;
- if (pathinfo->gc_refcount == 0) {
- if (pathinfo->parent_dir != path)
- srv_util_pathfree(ctx, pathinfo->parent_dir);
- LO_CALL(pathinfo->file, free);
- map_del(&ctx->parent_sess->paths, path);
- }
-}
-
-static inline bool srv_util_pathisdir(struct srv_pathinfo *pathinfo) {
- assert(pathinfo);
- return LO_CALL(pathinfo->file, qid).type & LIB9P_QT_DIR;
-}
-
-/**
- * Store fid as pointing to pathinfo. Assumes that
- * pathinfo->gc_refcount has already been incremented; does *not*
- * decrement it on failure.
- */
-static inline struct srv_fidinfo *srv_util_fidsave(struct srv_req *ctx, lib9p_fid_t fid, struct srv_pathinfo *pathinfo, bool overwrite) {
- assert(ctx);
- assert(fid != LIB9P_FID_NOFID);
- assert(pathinfo);
- infof("pathinfo=%p", pathinfo);
-
- struct lib9p_qid qid = LO_CALL(pathinfo->file, qid);
-
- struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, fid);
- if (fidinfo) {
- if (overwrite) {
- struct srv_pathinfo *old_pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path);
- assert(old_pathinfo);
- if (srv_util_pathisdir(old_pathinfo)) {
- if (!LO_IS_NULL(fidinfo->dir.io))
- LO_CALL(fidinfo->dir.io, iofree);
- } else {
- if (!LO_IS_NULL(fidinfo->file.io))
- LO_CALL(fidinfo->file.io, iofree);
- }
- srv_util_pathfree(ctx, fidinfo->path);
- } else {
- lib9p_error(&ctx->basectx,
- LINUX_EBADF, "FID already in use");
- return NULL;
- }
- } else {
- fidinfo = map_store(&ctx->parent_sess->fids, fid, (struct srv_fidinfo){});
- assert(fidinfo);
- }
- *fidinfo = (struct srv_fidinfo){
- .path = qid.path,
- };
- return fidinfo;
-}
+/* handle_T* ******************************************************************/
+#define srv_handler_common(ctx, req, resp) do { \
+ assert(ctx); \
+ assert(req); \
+ assert(resp); \
+ resp->tag = req->tag; \
+ } while (0)
static void handle_Tversion(struct srv_req *ctx,
struct lib9p_msg_Tversion *req,
struct lib9p_msg_Rversion *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
enum lib9p_version version = LIB9P_VER_unknown;
@@ -660,7 +713,7 @@ static void handle_Tversion(struct srv_req *ctx,
static void handle_Tauth(struct srv_req *ctx,
struct lib9p_msg_Tauth *req,
struct lib9p_msg_Rauth *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
ctx->authinfo->uid = req->n_uid;
ctx->authinfo->uname = req->uname;
@@ -680,7 +733,7 @@ static void handle_Tauth(struct srv_req *ctx,
static void handle_Tattach(struct srv_req *ctx,
struct lib9p_msg_Tattach *req,
struct lib9p_msg_Rattach *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
ctx->authinfo->uid = req->n_uid;
ctx->authinfo->uname = req->uname;
@@ -736,14 +789,14 @@ static void handle_Tattach(struct srv_req *ctx,
return;
struct lib9p_qid root_qid = LO_CALL(root_file, qid);
- assert(root_qid.type & LIB9P_QT_DIR);
+ assert(srv_qid_filetype(root_qid) == SRV_FILETYPE_DIR);
/* 2. pathinfo */
- struct srv_pathinfo *root_pathinfo = srv_util_pathsave(ctx, root_file, root_qid.path);
+ struct srv_pathinfo *root_pathinfo = srv_path_save(ctx, root_file, root_qid.path);
/* 3. fidinfo */
- if (!srv_util_fidsave(ctx, req->fid, root_pathinfo, false)) {
- srv_util_pathfree(ctx, root_qid.path);
+ if (!srv_fid_store(ctx, req->fid, root_pathinfo, false)) {
+ srv_path_decref(ctx, root_qid.path);
return;
}
@@ -754,7 +807,7 @@ static void handle_Tattach(struct srv_req *ctx,
static void handle_Tflush(struct srv_req *ctx,
struct lib9p_msg_Tflush *req,
struct lib9p_msg_Rflush *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
struct srv_req **oldreqp = map_load(&ctx->parent_sess->reqs, req->oldtag);
if (oldreqp)
@@ -764,7 +817,7 @@ static void handle_Tflush(struct srv_req *ctx,
static void handle_Twalk(struct srv_req *ctx,
struct lib9p_msg_Twalk *req,
struct lib9p_msg_Rwalk *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
if (req->newfid == LIB9P_FID_NOFID) {
lib9p_error(&ctx->basectx,
@@ -791,7 +844,7 @@ static void handle_Twalk(struct srv_req *ctx,
assert(new_pathinfo);
new_pathinfo->gc_refcount++;
} else {
- if (!srv_util_pathisdir(pathinfo)) {
+ if (pathinfo->type != SRV_FILETYPE_DIR) {
lib9p_error(&ctx->basectx,
LINUX_ENOTDIR, "not a directory");
break;
@@ -801,33 +854,33 @@ static void handle_Twalk(struct srv_req *ctx,
assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(&ctx->basectx));
if (lib9p_ctx_has_error(&ctx->basectx))
break;
- new_pathinfo = srv_util_pathsave(ctx, member_file, LO_CALL(pathinfo->file, qid).path);
+ new_pathinfo = srv_path_save(ctx, member_file, LO_CALL(pathinfo->file, qid).path);
}
- if (srv_util_pathisdir(new_pathinfo)) {
+ if (new_pathinfo->type == SRV_FILETYPE_DIR) {
struct lib9p_stat stat = LO_CALL(new_pathinfo->file, stat, ctx);
if (lib9p_ctx_has_error(&ctx->basectx))
break;
lib9p_stat_assert(stat);
- if (!srv_util_check_perm(ctx, &stat, 0b001)) {
+ if (!srv_check_perm(ctx, &stat, 0b001)) {
lib9p_error(&ctx->basectx,
LINUX_EACCES, "you do not have execute permission on that directory");
- srv_util_pathfree(ctx, LO_CALL(new_pathinfo->file, qid).path);
+ srv_path_decref(ctx, LO_CALL(new_pathinfo->file, qid).path);
break;
}
}
resp->wqid[resp->nwqid] = LO_CALL(new_pathinfo->file, qid);
- srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path);
+ srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path);
pathinfo = new_pathinfo;
}
if (resp->nwqid == req->nwname) {
- if (!srv_util_fidsave(ctx, req->newfid, pathinfo, req->newfid == req->fid))
- srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path);
+ 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));
- srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path);
+ srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path);
if (resp->nwqid > 0)
lib9p_ctx_clear_error(&ctx->basectx);
}
@@ -836,7 +889,7 @@ static void handle_Twalk(struct srv_req *ctx,
static void handle_Topen(struct srv_req *ctx,
struct lib9p_msg_Topen *req,
struct lib9p_msg_Ropen *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
/* Check that the FID is valid for this. */
struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid);
@@ -850,9 +903,7 @@ static void handle_Topen(struct srv_req *ctx,
LINUX_EALREADY, "FID is already open");
return;
}
- struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path);
- assert(pathinfo);
- if (srv_util_pathisdir(pathinfo)) {
+ 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) ) {
@@ -863,8 +914,10 @@ static void handle_Topen(struct srv_req *ctx,
}
/* Variables. */
- lib9p_o_t reqmode = req->mode;
- uint8_t fidflags = fidinfo->flags;
+ lib9p_o_t reqmode = req->mode;
+ uint8_t fidflags = fidinfo->flags;
+ struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path);
+ assert(pathinfo);
/* Check permissions. */
if (reqmode & LIB9P_O_RCLOSE) {
@@ -874,7 +927,7 @@ static void handle_Topen(struct srv_req *ctx,
if (lib9p_ctx_has_error(&ctx->basectx))
return;
lib9p_stat_assert(parent_stat);
- if (!srv_util_check_perm(ctx, &parent_stat, 0b010)) {
+ if (!srv_check_perm(ctx, &parent_stat, 0b010)) {
lib9p_error(&ctx->basectx,
LINUX_EACCES, "permission denied to remove-on-close");
return;
@@ -912,7 +965,7 @@ static void handle_Topen(struct srv_req *ctx,
rd = true;
break;
}
- if (!srv_util_check_perm(ctx, &stat, perm_bits)) {
+ if (!srv_check_perm(ctx, &stat, perm_bits)) {
lib9p_error(&ctx->basectx,
LINUX_EACCES, "permission denied");
return;
@@ -921,7 +974,8 @@ static void handle_Topen(struct srv_req *ctx,
/* Actually make the call. */
uint32_t iounit;
struct lib9p_qid qid;
- if (srv_util_pathisdir(pathinfo)) {
+ 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))
@@ -930,7 +984,8 @@ static void handle_Topen(struct srv_req *ctx,
fidinfo->dir.off = 0;
qid = LO_CALL(fidinfo->dir.io, qid);
iounit = 0;
- } else {
+ break;
+ case SRV_FILETYPE_FILE:
fidinfo->file.io = LO_CALL(pathinfo->file, fopen, ctx,
rd, wr,
reqmode & LIB9P_O_TRUNC);
@@ -939,6 +994,13 @@ static void handle_Topen(struct srv_req *ctx,
return;
qid = LO_CALL(fidinfo->file.io, qid);
iounit = LO_CALL(fidinfo->file.io, iounit);
+ break;
+ case SRV_FILETYPE_AUTH:
+ assert_notreached("TODO: auth not yet implemented");
+ break;
+ default:
+ assert_notreached("invalid srv_filetype");
+ break;
}
/* Success. */
@@ -955,7 +1017,7 @@ static void handle_Topen(struct srv_req *ctx,
static void handle_Tcreate(struct srv_req *ctx,
struct lib9p_msg_Tcreate *req,
struct lib9p_msg_Rcreate *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
lib9p_error(&ctx->basectx,
LINUX_EOPNOTSUPP, "create not (yet?) implemented");
@@ -964,7 +1026,7 @@ static void handle_Tcreate(struct srv_req *ctx,
static void handle_Tread(struct srv_req *ctx,
struct lib9p_msg_Tread *req,
struct lib9p_msg_Rread *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
/* TODO: serialize simultaneous reads to the same FID */
@@ -981,12 +1043,9 @@ static void handle_Tread(struct srv_req *ctx,
return;
}
- /* Variables. */
- struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path);
- assert(pathinfo);
-
/* Do it. */
- if (srv_util_pathisdir(pathinfo)) {
+ switch (fidinfo->type) {
+ case SRV_FILETYPE_DIR:
/* Translate byte-offset to object-index. */
size_t idx;
if (req->offset == 0)
@@ -1013,7 +1072,8 @@ static void handle_Tread(struct srv_req *ctx,
/* Remember. */
fidinfo->dir.idx = idx+num;
fidinfo->dir.off = req->offset + len;
- } else {
+ 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)) {
@@ -1022,13 +1082,17 @@ static void handle_Tread(struct srv_req *ctx,
if (resp->count > req->count)
resp->count = req->count;
}
+ break;
+ case SRV_FILETYPE_AUTH:
+ assert_notreached("TODO: auth not yet implemented");
+ break;
}
}
static void handle_Twrite(struct srv_req *ctx,
struct lib9p_msg_Twrite *req,
struct lib9p_msg_Rwrite *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
/* TODO: serialize simultaneous writes to the same FID */
@@ -1045,76 +1109,30 @@ static void handle_Twrite(struct srv_req *ctx,
return;
}
- /* Variables. */
- struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path);
- assert(pathinfo);
-
/* Do it. */
resp->count = LO_CALL(fidinfo->file.io, pwrite, ctx, req->data, req->count, req->offset);
}
-static void clunkremove(struct srv_req *ctx, lib9p_fid_t fid, bool remove) {
- struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, fid);
- if (!fidinfo) {
- lib9p_errorf(&ctx->basectx,
- LINUX_EBADF, "bad file number %"PRIu32, fid);
- return;
- }
- if (fidinfo->flags & FIDFLAG_RCLOSE)
- remove = true;
- struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path);
- assert(pathinfo);
-
- if (remove) {
- if (pathinfo->parent_dir == fidinfo->path) {
- lib9p_errorf(&ctx->basectx,
- LINUX_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_util_check_perm(ctx, &parent_stat, 0b010)) {
- lib9p_error(&ctx->basectx,
- LINUX_EACCES, "you do not have write permission on the parent directory");
- goto clunk;
- }
- LO_CALL(pathinfo->file, remove, ctx);
- }
-
- clunk:
- if (fidinfo->flags & FIDFLAG_OPEN) {
- if (srv_util_pathisdir(pathinfo))
- LO_CALL(fidinfo->dir.io, iofree);
- else
- LO_CALL(fidinfo->file.io, iofree);
- pathinfo->io_refcount--;
- }
- srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path);
- map_del(&ctx->parent_sess->fids, fid);
-}
-
static void handle_Tclunk(struct srv_req *ctx,
struct lib9p_msg_Tclunk *req,
struct lib9p_msg_Rclunk *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
- clunkremove(ctx, req->fid, false);
+ srv_fid_del(ctx, req->fid, false);
}
-
static void handle_Tremove(struct srv_req *ctx,
struct lib9p_msg_Tremove *req,
struct lib9p_msg_Rremove *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
- clunkremove(ctx, req->fid, true);
+ srv_fid_del(ctx, req->fid, true);
}
static void handle_Tstat(struct srv_req *ctx,
struct lib9p_msg_Tstat *req,
struct lib9p_msg_Rstat *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid);
if (!fidinfo) {
@@ -1133,7 +1151,7 @@ static void handle_Tstat(struct srv_req *ctx,
static void handle_Twstat(struct srv_req *ctx,
struct lib9p_msg_Twstat *req,
struct lib9p_msg_Rwstat *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
lib9p_error(&ctx->basectx,
LINUX_EOPNOTSUPP, "wstat not (yet?) implemented");
@@ -1143,7 +1161,7 @@ static void handle_Twstat(struct srv_req *ctx,
static void handle_Tsession(struct srv_req *ctx,
struct lib9p_msg_Tsession *req,
struct lib9p_msg_Rsession *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
lib9p_error(&ctx->basectx,
LINUX_EOPNOTSUPP, "session not (yet?) implemented");
@@ -1152,7 +1170,7 @@ static void handle_Tsession(struct srv_req *ctx,
static void handle_Tsread(struct srv_req *ctx,
struct lib9p_msg_Tsread *req,
struct lib9p_msg_Rsread *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
lib9p_error(&ctx->basectx,
LINUX_EOPNOTSUPP, "sread not (yet?) implemented");
@@ -1161,7 +1179,7 @@ static void handle_Tsread(struct srv_req *ctx,
static void handle_Tswrite(struct srv_req *ctx,
struct lib9p_msg_Tswrite *req,
struct lib9p_msg_Rswrite *resp) {
- util_handler_common(ctx, req, resp);
+ srv_handler_common(ctx, req, resp);
lib9p_error(&ctx->basectx,
LINUX_EOPNOTSUPP, "swrite not (yet?) implemented");