summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/srv9p/main.c11
-rw-r--r--cmd/srv9p/static.c77
-rw-r--r--cmd/srv9p/static.h8
-rw-r--r--lib9p/include/lib9p/srv.h62
-rw-r--r--lib9p/srv.c165
5 files changed, 214 insertions, 109 deletions
diff --git a/cmd/srv9p/main.c b/cmd/srv9p/main.c
index 6ed4b79..236bf60 100644
--- a/cmd/srv9p/main.c
+++ b/cmd/srv9p/main.c
@@ -19,7 +19,9 @@
#define UNUSED(name) /* name __attribute__((unused)) */
-static struct static_dir_data root = {
+static struct static_dir root = {
+ .header = { .vtable = &static_dir_vtable },
+
.u_name = "root", .u_num = 0, /* owner user */
.g_name = "root", .g_num = 0, /* owner group */
.m_name = "root", .m_num = 0, /* last-modified-by user */
@@ -35,11 +37,8 @@ static struct static_dir_data root = {
},
};
-struct lib9p_srv_file fs_root(struct lib9p_srv_ctx *UNUSED(ctx), char *UNUSED(treename)) {
- return (struct lib9p_srv_file){
- .vtable = static_dir_vtable,
- .impldata = &root,
- };
+struct lib9p_srv_file *fs_root(struct lib9p_srv_ctx *UNUSED(ctx), char *UNUSED(treename)) {
+ return &root.header;
}
int main() {
diff --git a/cmd/srv9p/static.c b/cmd/srv9p/static.c
index f992764..920daf2 100644
--- a/cmd/srv9p/static.c
+++ b/cmd/srv9p/static.c
@@ -4,67 +4,88 @@
#define UNUSED(name) /* name __attribute__((unused)) */
-static struct lib9p_srv_io static_dir_io(struct lib9p_srv_ctx *ctx, void *UNUSED(impl), lib9p_o_t UNUSED(flags)) {
- struct lib9p_srv_io iohandle = {0};
+static struct lib9p_srv_io *static_dir_io(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *_file, lib9p_o_t UNUSED(flags)) {
+ assert(ctx);
+ struct static_dir *file = (struct static_dir *)_file;
+ assert(file);
+
lib9p_error(&ctx->basectx, LINUX_EFAULT, "TODO: io");
- return iohandle;
+ return NULL;
}
#define p9_str(cstr) ((struct lib9p_s){ .len = strlen(cstr), .utf8 = cstr })
#define p9_nulstr ((struct lib9p_s){ .len = 0, .utf8 = NULL })
-static struct lib9p_stat static_dir_stat(struct lib9p_srv_ctx *UNUSED(ctx), void *_data) {
- struct static_dir_data *data = _data;
- assert(data);
+static struct lib9p_stat static_dir_stat(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *_file) {
+ assert(ctx);
+ struct static_dir *file = (struct static_dir *)_file;
+ assert(file);
- struct lib9p_stat stat = {
+ return (struct lib9p_stat){
.kern_type = 0,
.kern_dev = 0,
.file_qid = {
.type = LIB9P_QT_DIR,
.vers = 1,
- .path = data->pathnum,
+ .path = file->pathnum,
},
- .file_mode = LIB9P_DM_DIR | (data->perm & 0555),
- .file_atime = data->atime,
- .file_mtime = data->mtime,
+ .file_mode = LIB9P_DM_DIR | (file->perm & 0555),
+ .file_atime = file->atime,
+ .file_mtime = file->mtime,
.file_size = 0,
- .file_name = p9_str(data->name),
- .file_owner_uid = p9_str(data->u_name),
- .file_owner_gid = p9_str(data->g_name),
- .file_last_modified_uid = p9_str(data->m_name),
+ .file_name = p9_str(file->name),
+ .file_owner_uid = p9_str(file->u_name),
+ .file_owner_gid = p9_str(file->g_name),
+ .file_last_modified_uid = p9_str(file->m_name),
.file_extension = p9_nulstr,
- .file_owner_n_uid = data->u_num,
- .file_owner_n_gid = data->g_num,
- .file_last_modified_n_uid = data->m_num,
+ .file_owner_n_uid = file->u_num,
+ .file_owner_n_gid = file->g_num,
+ .file_last_modified_n_uid = file->m_num,
};
- return stat;
}
-static void static_dir_wstat(struct lib9p_srv_ctx *ctx, void *UNUSED(_data),
+static void static_dir_wstat(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *_file,
struct lib9p_stat UNUSED(new)) {
+ assert(ctx);
+ struct static_dir *file = (struct static_dir *)_file;
+ assert(file);
+
lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem");
}
-static void static_dir_remove(struct lib9p_srv_ctx *ctx, void *UNUSED(_data)) {
+static void static_dir_remove(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *_file) {
+ assert(ctx);
+ struct static_dir *file = (struct static_dir *)_file;
+ assert(file);
+
lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem");
}
-static void static_dir_free(struct lib9p_srv_ctx *UNUSED(ctx), void *UNUSED(_data)) {}
+static void static_dir_free(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *_file) {
+ assert(ctx);
+ struct static_dir *file = (struct static_dir *)_file;
+ assert(file);
+}
-static struct lib9p_srv_file static_dir_dopen(struct lib9p_srv_ctx *ctx, void *UNUSED(_data),
+static struct lib9p_srv_file *static_dir_dopen(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *_dir,
char *UNUSED(childname)) {
- struct lib9p_srv_file file= {0};
+ assert(ctx);
+ struct static_dir *dir = (struct static_dir *)_dir;
+ assert(dir);
+
lib9p_error(&ctx->basectx, LINUX_EFAULT, "TODO: dopen");
- return file;
+ return NULL;
}
-static struct lib9p_srv_file static_dir_dcreate(struct lib9p_srv_ctx *ctx, void *UNUSED(_data),
+static struct lib9p_srv_file *static_dir_dcreate(struct lib9p_srv_ctx *ctx, struct lib9p_srv_file *_dir,
char *UNUSED(childname),
lib9p_dm_t UNUSED(perm), lib9p_o_t UNUSED(flags)) {
- struct lib9p_srv_file file = {0};
+ assert(ctx);
+ struct static_dir *dir = (struct static_dir *)_dir;
+ assert(dir);
+
lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem");
- return file;
+ return NULL;
}
struct lib9p_srv_file_vtable static_dir_vtable = {
diff --git a/cmd/srv9p/static.h b/cmd/srv9p/static.h
index 90bad4b..afb5a3f 100644
--- a/cmd/srv9p/static.h
+++ b/cmd/srv9p/static.h
@@ -3,7 +3,11 @@
#include <lib9p/srv.h>
-struct static_dir_data {
+extern struct lib9p_srv_file_vtable static_dir_vtable;
+
+struct static_dir {
+ struct lib9p_srv_file header;
+
char *u_name;
uint32_t u_num;
char *g_name;
@@ -20,8 +24,6 @@ struct static_dir_data {
struct lib9p_srv_file *members[];
};
-extern struct lib9p_srv_file_vtable static_dir_vtable;
-
//extern struct lib9p_srv_io_dir_vtable static_dir_io_vtable;
#endif /* _STATIC_H_ */
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");
}