diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-10-07 18:04:03 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-10-07 18:04:03 -0600 |
commit | 9c7f19c46d8fb58b6bcfe0d1d026c05657ffba96 (patch) | |
tree | 70c52d35473757bc2c72ecc5295ff90c9c05067d | |
parent | 62e8081e0ac4a4c170bc536303f7a9bd3e91fd7b (diff) |
wip
-rw-r--r-- | cmd/srv9p/main.c | 11 | ||||
-rw-r--r-- | cmd/srv9p/static.c | 77 | ||||
-rw-r--r-- | cmd/srv9p/static.h | 8 | ||||
-rw-r--r-- | lib9p/include/lib9p/srv.h | 62 | ||||
-rw-r--r-- | lib9p/srv.c | 165 |
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"); } |