summaryrefslogtreecommitdiff
path: root/lib9p
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p')
-rw-r--r--lib9p/include/lib9p/srv.h62
-rw-r--r--lib9p/srv.c165
2 files changed, 155 insertions, 72 deletions
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h
index c56ee3f..11c1fac 100644
--- a/lib9p/include/lib9p/srv.h
+++ b/lib9p/include/lib9p/srv.h
@@ -34,59 +34,67 @@ static inline int lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) {
/* vtables you must implement *************************************************/
+struct lib9p_srv_file;
+struct lib9p_srv_io;
+
struct lib9p_srv_file_vtable {
/* all */
- struct lib9p_srv_io (*io )(struct lib9p_srv_ctx *ctx, void *impl,
- lib9p_o_t flags);
- struct lib9p_stat (*stat )(struct lib9p_srv_ctx *ctx, void *impl);
- void (*wstat )(struct lib9p_srv_ctx *ctx, void *impl,
- struct lib9p_stat new);
- void (*remove )(struct lib9p_srv_ctx *ctx, void *impl);
- void (*free )(struct lib9p_srv_ctx *ctx, void *impl);
+ struct lib9p_srv_io *(*io )(struct lib9p_srv_ctx *, struct lib9p_srv_file *,
+ lib9p_o_t flags);
+ struct lib9p_stat (*stat )(struct lib9p_srv_ctx *, struct lib9p_srv_file *);
+ void (*wstat )(struct lib9p_srv_ctx *, struct lib9p_srv_file *,
+ struct lib9p_stat new);
+ void (*remove )(struct lib9p_srv_ctx *, struct lib9p_srv_file *);
+ void (*free )(struct lib9p_srv_ctx *, struct lib9p_srv_file *); /* optional */
/* dir */
- struct lib9p_srv_file (*dopen )(struct lib9p_srv_ctx *ctx, void *impl,
+ struct lib9p_srv_file *(*dopen )(struct lib9p_srv_ctx *, struct lib9p_srv_file *,
char *childname);
- struct lib9p_srv_file (*dcreate)(struct lib9p_srv_ctx *ctx, void *impl,
+ struct lib9p_srv_file *(*dcreate)(struct lib9p_srv_ctx *, struct lib9p_srv_file *,
char *childname,
lib9p_dm_t perm, lib9p_o_t flags);
};
struct lib9p_srv_io_dir_vtable {
- size_t (*readdir)(struct lib9p_srv_ctx *ctx, void *impl,
- struct lib9p_stat *buf, size_t count,
- size_t offset);
+ size_t (*readdir)(struct lib9p_srv_ctx *, struct lib9p_srv_io_dir *,
+ struct lib9p_stat *buf, size_t count,
+ size_t offset);
};
struct lib9p_srv_io_file_vtable {
- uint32_t (*pread )(struct lib9p_srv_ctx *ctx, void *impl,
- void *buf, uint32_t count,
- uint64_t offset);
- uint32_t (*pwrite )(struct lib9p_srv_ctx *ctx, void *impl,
- void *buf, uint32_t count,
- uint64_t offset);
+ uint32_t (*pread )(struct lib9p_srv_ctx *, struct lib9p_srv_io_file *,
+ void *buf, uint32_t count,
+ uint64_t offset);
+ uint32_t (*pwrite )(struct lib9p_srv_ctx *, struct lib9p_srv_io_file *,
+ void *buf, uint32_t count,
+ uint64_t offset);
};
/* objects you'll deal with ***************************************************/
struct lib9p_srv_file {
- struct lib9p_srv_file_vtable vtable;
+ struct lib9p_srv_file_vtable *vtable;
+
+ /* Managed by srv.c */
+ struct lib9p_srv_file *_parent_dir;
+ struct lib9p_srv_file *_refcount;
- struct lib9p_srv_file *parent_dir;
- void *impldata;
+ /* This is where your implementation data goes. */
+ char data[0];
};
struct lib9p_srv_io {
union {
- struct lib9p_srv_io_dir_vtable dir;
- struct lib9p_srv_io_file_vtable file;
+ struct lib9p_srv_io_dir_vtable *dir;
+ struct lib9p_srv_io_file_vtable *file;
} vtable;
struct lib9p_srv_file *file;
struct lib9p_qid qid;
uint32_t iounit;
- void *impldata;
+ /* This is where your implementation data goes. */
+ char data[0];
};
/* main server entrypoints ****************************************************/
@@ -95,9 +103,9 @@ CR_RPC_DECLARE(_lib9p_srv_reqch, struct _lib9p_srv_req *, bool)
struct lib9p_srv {
/* Things you provide */
- int sockfd;
- void /*TODO*/ (*auth )(struct lib9p_srv_ctx *ctx, char *treename);
- struct lib9p_srv_file (*rootdir)(struct lib9p_srv_ctx *ctx, char *treename);
+ int sockfd;
+ void /*TODO*/ (*auth )(struct lib9p_srv_ctx *, char *treename); /* optional */
+ struct lib9p_srv_file *(*rootdir)(struct lib9p_srv_ctx *, char *treename);
/* For internal use */
_lib9p_srv_reqch_t _reqch;
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 7dca9ec..84b3ae8 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -17,7 +17,7 @@
#define NAME fidmap
#define KEY_T uint32_t
-#define VAL_T struct lib9p_srv_file
+#define VAL_T struct lib9p_srv_file *
#define CAP CONFIG_9P_MAX_FIDS
#include "map.h"
@@ -368,6 +368,10 @@ static void handle_message(struct _lib9p_srv_req *ctx) {
static void handle_Tversion(struct _lib9p_srv_req *ctx,
struct lib9p_msg_Tversion *req,
struct lib9p_msg_Rversion *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
enum lib9p_version version = LIB9P_VER_unknown;
if (req->version.len >= 6 &&
@@ -422,10 +426,11 @@ static void handle_Tversion(struct _lib9p_srv_req *ctx,
if (ctx->parent_sess->fids.len) {
/* Close all FIDs. */
uint32_t fid;
- struct lib9p_srv_file *fptr;
- MAP_FOREACH(&ctx->parent_sess->fids, fid, fptr) {
- fptr->vtable.free(&ctx->ctx, fptr->impldata);
- fidmap_del(&ctx->parent_sess->fids, fid);
+ struct lib9p_srv_file **filepp __attribute__((unused));
+ MAP_FOREACH(&ctx->parent_sess->fids, fid, filepp) {
+ handle_Tclunk(ctx,
+ &(struct lib9p_msg_Tclunk){.fid = fid},
+ &(struct lib9p_msg_Rclunk){});
}
}
@@ -437,7 +442,11 @@ 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 *UNUSED(resp)) {
+ struct lib9p_msg_Rauth *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
ctx->ctx.uid = req->n_uname;
ctx->ctx.uname = req->uname.utf8;
struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv;
@@ -456,6 +465,10 @@ 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) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
ctx->ctx.uid = req->n_uname;
ctx->ctx.uname = req->uname.utf8;
struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv;
@@ -501,117 +514,179 @@ static void handle_Tattach(struct _lib9p_srv_req *ctx,
return;
}
- struct lib9p_srv_file rootdir = srv->rootdir(&ctx->ctx, req->aname.utf8);
+ struct lib9p_srv_file *rootdir = srv->rootdir(&ctx->ctx, req->aname.utf8);
if (lib9p_ctx_has_error(&ctx->ctx.basectx))
return;
+ rootdir->_parent_dir = rootdir;
- struct lib9p_stat stat = rootdir.vtable.stat(&ctx->ctx, rootdir.impldata);
- if (lib9p_ctx_has_error(&ctx->ctx.basectx)) {
- if (rootdir.vtable.free)
- rootdir.vtable.free(&ctx->ctx, rootdir.impldata);
+ if (!fidmap_store(&ctx->parent_sess->fids, req->fid, rootdir)) {
+ lib9p_error(&ctx->ctx.basectx,
+ LINUX_EMFILE, "too many open files");
+ if (rootdir->vtable->free)
+ rootdir->vtable->free(&ctx->ctx, rootdir);
return;
}
- struct lib9p_srv_file *rootdir_ptr = fidmap_store(&ctx->parent_sess->fids, req->fid, rootdir);
- if (!rootdir_ptr) {
- lib9p_error(&ctx->ctx.basectx,
- LINUX_EMFILE, "too many open files");
- if (rootdir.vtable.free)
- rootdir.vtable.free(&ctx->ctx, rootdir.impldata);
+ struct lib9p_stat stat = rootdir->vtable->stat(&ctx->ctx, rootdir);
+ if (lib9p_ctx_has_error(&ctx->ctx.basectx)) {
+ handle_Tclunk(ctx,
+ &(struct lib9p_msg_Tclunk){.fid = req->fid},
+ &(struct lib9p_msg_Rclunk){});
return;
}
+
resp->qid = stat.file_qid;
return;
}
static void handle_Tflush(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tflush *UNUSED(req),
- struct lib9p_msg_Rflush *UNUSED(resp)) {
+ struct lib9p_msg_Tflush *req,
+ struct lib9p_msg_Rflush *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "flush not yet implemented");
}
static void handle_Twalk(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Twalk *UNUSED(req),
- struct lib9p_msg_Rwalk *UNUSED(resp)) {
+ struct lib9p_msg_Twalk *req,
+ struct lib9p_msg_Rwalk *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "walk not yet implemented");
}
static void handle_Topen(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Topen *UNUSED(req),
- struct lib9p_msg_Ropen *UNUSED(resp)) {
+ struct lib9p_msg_Topen *req,
+ struct lib9p_msg_Ropen *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "open not yet implemented");
}
static void handle_Tcreate(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tcreate *UNUSED(req),
- struct lib9p_msg_Rcreate *UNUSED(resp)) {
+ struct lib9p_msg_Tcreate *req,
+ struct lib9p_msg_Rcreate *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "create not yet implemented");
}
static void handle_Tread(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tread *UNUSED(req),
- struct lib9p_msg_Rread *UNUSED(resp)) {
+ struct lib9p_msg_Tread *req,
+ struct lib9p_msg_Rread *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "read not yet implemented");
}
static void handle_Twrite(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Twrite *UNUSED(req),
- struct lib9p_msg_Rwrite *UNUSED(resp)) {
+ struct lib9p_msg_Twrite *req,
+ struct lib9p_msg_Rwrite *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "write not yet implemented");
}
static void handle_Tclunk(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tclunk *UNUSED(req),
- struct lib9p_msg_Rclunk *UNUSED(resp)) {
- lib9p_error(&ctx->ctx.basectx,
- LINUX_EOPNOTSUPP, "clunk not yet implemented");
+ struct lib9p_msg_Tclunk *req,
+ struct lib9p_msg_Rclunk *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
+ struct lib9p_srv_file **filepp = fidmap_load(&ctx->parent_sess->fids, req->fid);
+ if (!filepp) {
+ lib9p_errorf(&ctx->ctx.basectx,
+ LINUX_EBADF, "bad file number %"PRIu32, req->fid);
+ return;
+ }
+
+ if ((*filepp)->vtable->free)
+ (*filepp)->vtable->free(&ctx->ctx, *filepp);
+ fidmap_del(&ctx->parent_sess->fids, req->fid);
}
static void handle_Tremove(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tremove *UNUSED(req),
- struct lib9p_msg_Rremove *UNUSED(resp)) {
+ struct lib9p_msg_Tremove *req,
+ struct lib9p_msg_Rremove *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "remove not yet implemented");
}
static void handle_Tstat(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tstat *UNUSED(req),
- struct lib9p_msg_Rstat *UNUSED(resp)) {
+ struct lib9p_msg_Tstat *req,
+ struct lib9p_msg_Rstat *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "stat not yet implemented");
}
static void handle_Twstat(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Twstat *UNUSED(req),
- struct lib9p_msg_Rwstat *UNUSED(resp)) {
+ struct lib9p_msg_Twstat *req,
+ struct lib9p_msg_Rwstat *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "wstat not yet implemented");
}
static void handle_Tsession(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tsession *UNUSED(req),
- struct lib9p_msg_Rsession *UNUSED(resp)) {
+ struct lib9p_msg_Tsession *req,
+ struct lib9p_msg_Rsession *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "session not yet implemented");
}
static void handle_Tsread(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tsread *UNUSED(req),
- struct lib9p_msg_Rsread *UNUSED(resp)) {
+ struct lib9p_msg_Tsread *req,
+ struct lib9p_msg_Rsread *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "sread not yet implemented");
}
static void handle_Tswrite(struct _lib9p_srv_req *ctx,
- struct lib9p_msg_Tswrite *UNUSED(req),
- struct lib9p_msg_Rswrite *UNUSED(resp)) {
+ struct lib9p_msg_Tswrite *req,
+ struct lib9p_msg_Rswrite *resp) {
+ assert(ctx);
+ assert(req);
+ assert(resp);
+
lib9p_error(&ctx->ctx.basectx,
LINUX_EOPNOTSUPP, "swrite not yet implemented");
}