diff options
-rw-r--r-- | lib9p/include/lib9p/srv.h | 95 | ||||
-rw-r--r-- | lib9p/srv.c | 67 | ||||
-rw-r--r-- | lib9p/tests/test_server/main.c | 107 | ||||
-rw-r--r-- | lib9p_util/include/util9p/static.h | 12 | ||||
-rw-r--r-- | lib9p_util/static.c | 177 |
5 files changed, 229 insertions, 229 deletions
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h index 0fc9011..83aabc0 100644 --- a/lib9p/include/lib9p/srv.h +++ b/lib9p/include/lib9p/srv.h @@ -11,7 +11,9 @@ #include <libcr_ipc/rpc.h> #include <libcr_ipc/chan.h> #include <libhw/generic/net.h> +#include <libmisc/assert.h> #include <libmisc/private.h> +#include <libobj/obj.h> #include <lib9p/9p.h> @@ -35,48 +37,53 @@ int lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx); /* interface definitions ******************************************************/ -struct lib9p_srv_file_vtable; - -typedef struct { - struct lib9p_srv_file_vtable *vtable; -} implements_lib9p_srv_file; - -struct lib9p_srv_file_vtable { - /* all - resource management */ - void (*free )(implements_lib9p_srv_file *); /* must not error */ - struct lib9p_qid (*qid )(implements_lib9p_srv_file *); /* must not error */ - uint32_t (*chio )(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, - bool rd, bool wr, bool trunc); - - /* all - syscalls */ - struct lib9p_stat (*stat )(implements_lib9p_srv_file *, struct lib9p_srv_ctx *); - void (*wstat )(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, - struct lib9p_stat new); - void (*remove )(implements_lib9p_srv_file *, struct lib9p_srv_ctx *); - - /* directories - base */ - implements_lib9p_srv_file *(*dopen )(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, - struct lib9p_s childname); - implements_lib9p_srv_file *(*dcreate)(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, - struct lib9p_s childname, - lib9p_dm_t perm, lib9p_o_t flags); - - /* directories - once opened */ - size_t /* <- obj cnt */ (*dread )(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, - uint8_t *buf, - uint32_t byte_count, /* <- num bytes */ - size_t obj_offset); /* <- starting at this object */ - - /* non-directories - once opened */ - uint32_t (*pread )(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, - void *buf, - uint32_t byte_count, - uint64_t byte_offset); - uint32_t (*pwrite )(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, - void *buf, - uint32_t byte_count, - uint64_t byte_offset); -}; +#define lib9p_srv_file_LO_IFACE \ + /* all - resource management */ \ + LO_FUNC(void , free ) /* must not error */ \ + LO_FUNC(struct lib9p_qid , qid ) /* must not error */ \ + LO_FUNC(uint32_t , chio , struct lib9p_srv_ctx *, \ + bool rd, bool wr, \ + bool trunc) \ + \ + /* all - syscalls */ \ + LO_FUNC(struct lib9p_stat , stat , struct lib9p_srv_ctx *) \ + LO_FUNC(void , wstat , struct lib9p_srv_ctx *, \ + struct lib9p_stat new) \ + LO_FUNC(void , remove , struct lib9p_srv_ctx *) \ + \ + /* directories - base */ \ + LO_FUNC(lo_interface lib9p_srv_file, dopen , struct lib9p_srv_ctx *, \ + struct lib9p_s childname) \ + LO_FUNC(lo_interface lib9p_srv_file, dcreate, struct lib9p_srv_ctx *, \ + struct lib9p_s childname, \ + lib9p_dm_t perm, \ + lib9p_o_t flags) \ + \ + /* directories - once opened */ \ + LO_FUNC(size_t /* <- obj cnt */ , dread , struct lib9p_srv_ctx *, \ + uint8_t *buf, \ + /* num bytes -> */ uint32_t byte_count, \ + /* starting at this object -> */ size_t obj_offset) \ + \ + /* non-directories - once opened */ \ + LO_FUNC(uint32_t , pread , struct lib9p_srv_ctx *, \ + void *buf, \ + uint32_t byte_count, \ + uint64_t byte_offset) \ + LO_FUNC(uint32_t , pwrite , struct lib9p_srv_ctx *, \ + void *buf, \ + uint32_t byte_count, \ + uint64_t byte_offset) +LO_INTERFACE(lib9p_srv_file) + +#define LIB9P_SRV_NOTDIR(TYP, NAM) \ + static lo_interface lib9p_srv_file NAM##_dopen (TYP *, struct lib9p_srv_ctx *, struct lib9p_s) { assert_notreached("not a directory"); } \ + static lo_interface lib9p_srv_file NAM##_dcreate(TYP *, struct lib9p_srv_ctx *, struct lib9p_s, lib9p_dm_t, lib9p_o_t) { assert_notreached("not a directory"); } \ + static size_t NAM##_dread (TYP *, struct lib9p_srv_ctx *, uint8_t *, uint32_t, size_t) { assert_notreached("not a directory"); } + +#define LIB9P_SRV_NOTFILE(TYP, NAM) \ + static uint32_t NAM##_pread (TYP *, struct lib9p_srv_ctx *, void *, uint32_t, uint64_t) { assert_notreached("not a file"); } \ + static uint32_t NAM##_pwrite(TYP *, struct lib9p_srv_ctx *, void *, uint32_t, uint64_t) { assert_notreached("not a file"); } /* main server entrypoints ****************************************************/ @@ -84,8 +91,8 @@ CR_RPC_DECLARE(_lib9p_srv_reqch, struct _lib9p_srv_req *, bool) struct lib9p_srv { /* Things you provide */ - void /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */ - implements_lib9p_srv_file *(*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename); + void /*TODO*/ (*auth )(struct lib9p_srv_ctx *, struct lib9p_s treename); /* optional */ + lo_interface lib9p_srv_file (*rootdir)(struct lib9p_srv_ctx *, struct lib9p_s treename); /* For internal use */ BEGIN_PRIVATE(LIB9P_SRV_H) diff --git a/lib9p/srv.c b/lib9p/srv.c index 0bfe5da..0e58068 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -12,7 +12,6 @@ #include <libcr_ipc/mutex.h> #include <libcr_ipc/select.h> #include <libmisc/assert.h> -#include <libmisc/vcall.h> #include <libhw/generic/net.h> #define LOG_NAME 9P_SRV @@ -54,7 +53,7 @@ int lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) { typedef typeof( ((struct lib9p_qid){}).path ) srv_path_t; struct srv_pathinfo { - implements_lib9p_srv_file *file; + lo_interface lib9p_srv_file file; srv_path_t parent_dir; /* References from other srv_pathinfos (via .parent_dir) or @@ -470,15 +469,15 @@ static inline bool srv_util_check_perm(struct _lib9p_srv_req *ctx, struct lib9p_ * Returns a pointer to the stored pathinfo. */ static inline struct srv_pathinfo *srv_util_pathsave(struct _lib9p_srv_req *ctx, - implements_lib9p_srv_file *file, + lo_interface lib9p_srv_file file, srv_path_t parent_path) { assert(ctx); - assert(file); + assert(!LO_IS_NULL(file)); - struct lib9p_qid qid = VCALL(file, qid); + struct lib9p_qid qid = LO_CALL(file, qid); struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, qid.path); if (pathinfo) - assert(pathinfo->file == file); + assert(LO_EQ(pathinfo->file, file)); else { pathinfo = pathmap_store(&ctx->parent_sess->paths, qid.path, (struct srv_pathinfo){ @@ -512,14 +511,14 @@ static inline void srv_util_pathfree(struct _lib9p_srv_req *ctx, srv_path_t path if (pathinfo->gc_refcount == 0) { if (pathinfo->parent_dir != path) srv_util_pathfree(ctx, pathinfo->parent_dir); - VCALL(pathinfo->file, free); + LO_CALL(pathinfo->file, free); pathmap_del(&ctx->parent_sess->paths, path); } } static inline bool srv_util_pathisdir(struct srv_pathinfo *pathinfo) { assert(pathinfo); - return VCALL(pathinfo->file, qid).type & LIB9P_QT_DIR; + return LO_CALL(pathinfo->file, qid).type & LIB9P_QT_DIR; } /** @@ -532,7 +531,7 @@ static inline struct _srv_fidinfo *srv_util_fidsave(struct _lib9p_srv_req *ctx, assert(fid != LIB9P_FID_NOFID); assert(pathinfo); - struct lib9p_qid qid = VCALL(pathinfo->file, qid); + struct lib9p_qid qid = LO_CALL(pathinfo->file, qid); struct _srv_fidinfo *fidinfo = fidmap_load(&ctx->parent_sess->fids, fid); if (fidinfo) { @@ -703,12 +702,12 @@ static void handle_Tattach(struct _lib9p_srv_req *ctx, } /* 1. File object */ - implements_lib9p_srv_file *root_file = srv->rootdir(&ctx->ctx, req->aname); - assert((root_file == NULL) == lib9p_ctx_has_error(&ctx->ctx.basectx)); + lo_interface lib9p_srv_file root_file = srv->rootdir(&ctx->ctx, req->aname); + assert(LO_IS_NULL(root_file) == lib9p_ctx_has_error(&ctx->ctx.basectx)); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) return; - struct lib9p_qid root_qid = VCALL(root_file, qid); + struct lib9p_qid root_qid = LO_CALL(root_file, qid); assert(root_qid.type & LIB9P_QT_DIR); /* 2. pathinfo */ @@ -770,37 +769,37 @@ static void handle_Twalk(struct _lib9p_srv_req *ctx, break; } - implements_lib9p_srv_file *member_file = VCALL(pathinfo->file, dopen, &ctx->ctx, req->wname[resp->nwqid]); - assert((member_file == NULL) == lib9p_ctx_has_error(&ctx->ctx.basectx)); + lo_interface lib9p_srv_file member_file = LO_CALL(pathinfo->file, dopen, &ctx->ctx, req->wname[resp->nwqid]); + assert(LO_IS_NULL(member_file) == lib9p_ctx_has_error(&ctx->ctx.basectx)); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) break; - new_pathinfo = srv_util_pathsave(ctx, member_file, VCALL(pathinfo->file, qid).path); + new_pathinfo = srv_util_pathsave(ctx, member_file, LO_CALL(pathinfo->file, qid).path); } if (srv_util_pathisdir(new_pathinfo)) { - struct lib9p_stat stat = VCALL(new_pathinfo->file, stat, &ctx->ctx); + struct lib9p_stat stat = LO_CALL(new_pathinfo->file, stat, &ctx->ctx); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) break; lib9p_stat_assert(stat); if (!srv_util_check_perm(ctx, &stat, 0b001)) { lib9p_error(&ctx->ctx.basectx, LINUX_EACCES, "you do not have execute permission on that directory"); - srv_util_pathfree(ctx, VCALL(new_pathinfo->file, qid).path); + srv_util_pathfree(ctx, LO_CALL(new_pathinfo->file, qid).path); break; } } - resp->wqid[resp->nwqid] = VCALL(new_pathinfo->file, qid); + resp->wqid[resp->nwqid] = LO_CALL(new_pathinfo->file, qid); - srv_util_pathfree(ctx, VCALL(pathinfo->file, qid).path); + srv_util_pathfree(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, VCALL(pathinfo->file, qid).path); + srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path); } else { assert(lib9p_ctx_has_error(&ctx->ctx.basectx)); - srv_util_pathfree(ctx, VCALL(pathinfo->file, qid).path); + srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path); if (resp->nwqid > 0) lib9p_ctx_clear_error(&ctx->ctx.basectx); } @@ -844,7 +843,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, if (reqmode & LIB9P_O_RCLOSE) { struct srv_pathinfo *parent = pathmap_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(parent); - struct lib9p_stat parent_stat = VCALL(parent->file, stat, &ctx->ctx); + struct lib9p_stat parent_stat = LO_CALL(parent->file, stat, &ctx->ctx); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) return; lib9p_stat_assert(parent_stat); @@ -855,7 +854,7 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, } fidflags = fidflags | FIDFLAG_RCLOSE; } - struct lib9p_stat stat = VCALL(pathinfo->file, stat, &ctx->ctx); + struct lib9p_stat stat = LO_CALL(pathinfo->file, stat, &ctx->ctx); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) return; lib9p_stat_assert(stat); @@ -893,10 +892,10 @@ static void handle_Topen(struct _lib9p_srv_req *ctx, /* Actually make the call. */ if ((reqmode & LIB9P_O_TRUNC) || (rd && !pathinfo->rd_refcount) || (wr && !pathinfo->wr_refcount) ) { - iounit = VCALL(pathinfo->file, chio, &ctx->ctx, - fidflags & FIDFLAG_OPEN_R, - fidflags & FIDFLAG_OPEN_W, - reqmode & LIB9P_O_TRUNC); + iounit = LO_CALL(pathinfo->file, chio, &ctx->ctx, + fidflags & FIDFLAG_OPEN_R, + fidflags & FIDFLAG_OPEN_W, + reqmode & LIB9P_O_TRUNC); if (lib9p_ctx_has_error(&ctx->ctx.basectx)) return; } @@ -962,7 +961,7 @@ static void handle_Tread(struct _lib9p_srv_req *ctx, return; } /* Do it. */ - size_t num = VCALL(pathinfo->file, dread, &ctx->ctx, (uint8_t *)resp->data, req->count, idx); + size_t num = LO_CALL(pathinfo->file, dread, &ctx->ctx, (uint8_t *)resp->data, req->count, idx); /* Translate object-count back to byte-count. */ uint32_t len = 0; for (size_t i = 0; i < num; i++) { @@ -975,7 +974,7 @@ static void handle_Tread(struct _lib9p_srv_req *ctx, fidinfo->dir_idx = idx+num; fidinfo->dir_off = req->offset + len; } else - resp->count = VCALL(pathinfo->file, pread, &ctx->ctx, resp->data, req->count, req->offset); + resp->count = LO_CALL(pathinfo->file, pread, &ctx->ctx, resp->data, req->count, req->offset); } static void handle_Twrite(struct _lib9p_srv_req *ctx, @@ -1001,7 +1000,7 @@ static void handle_Twrite(struct _lib9p_srv_req *ctx, assert(pathinfo); /* Do it. */ - resp->count = VCALL(pathinfo->file, pwrite, &ctx->ctx, req->data, req->count, req->offset); + resp->count = LO_CALL(pathinfo->file, pwrite, &ctx->ctx, req->data, req->count, req->offset); } static void clunkremove(struct _lib9p_srv_req *ctx, lib9p_fid_t fid, bool remove) { @@ -1024,17 +1023,17 @@ static void clunkremove(struct _lib9p_srv_req *ctx, lib9p_fid_t fid, bool remove } struct srv_pathinfo *parent = pathmap_load(&ctx->parent_sess->paths, pathinfo->parent_dir); assert(parent); - struct lib9p_stat parent_stat = VCALL(parent->file, stat, &ctx->ctx); + struct lib9p_stat parent_stat = LO_CALL(parent->file, stat, &ctx->ctx); if (!srv_util_check_perm(ctx, &parent_stat, 0b010)) { lib9p_error(&ctx->ctx.basectx, LINUX_EACCES, "you do not have write permission on the parent directory"); goto clunk; } - VCALL(pathinfo->file, remove, &ctx->ctx); + LO_CALL(pathinfo->file, remove, &ctx->ctx); } clunk: - srv_util_pathfree(ctx, VCALL(pathinfo->file, qid).path); + srv_util_pathfree(ctx, LO_CALL(pathinfo->file, qid).path); fidmap_del(&ctx->parent_sess->fids, fid); } @@ -1069,7 +1068,7 @@ static void handle_Tstat(struct _lib9p_srv_req *ctx, struct srv_pathinfo *pathinfo = pathmap_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); - resp->stat = VCALL(pathinfo->file, stat, &ctx->ctx); + resp->stat = LO_CALL(pathinfo->file, stat, &ctx->ctx); if (!lib9p_ctx_has_error(&ctx->ctx.basectx)) lib9p_stat_assert(resp->stat); } diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c index 6655f67..10f67a3 100644 --- a/lib9p/tests/test_server/main.c +++ b/lib9p/tests/test_server/main.c @@ -13,7 +13,6 @@ #include <libhw/host_alarmclock.h> #include <libhw/host_net.h> #include <libmisc/macro.h> -#include <libmisc/vcall.h> #include <util9p/static.h> #include "static.h" @@ -28,7 +27,7 @@ /* globals ********************************************************************/ -static implements_lib9p_srv_file *get_root(struct lib9p_srv_ctx *, struct lib9p_s); +static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *, struct lib9p_s); const char *hexdig = "0123456789abcdef"; @@ -44,31 +43,31 @@ struct { /* api ************************************************************************/ struct api_file { - implements_lib9p_srv_file; - uint64_t pathnum; }; +LO_IMPLEMENTATION_H(lib9p_srv_file, struct api_file, api) +LO_IMPLEMENTATION_C(lib9p_srv_file, struct api_file, api, static) -static void api_free(implements_lib9p_srv_file *) {} -static uint32_t api_chio(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, bool, bool, bool) { return 0; } - -static void api_wstat(implements_lib9p_srv_file *, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file"); } -static void api_remove(implements_lib9p_srv_file *, struct lib9p_srv_ctx *ctx) { lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file"); } - -static struct lib9p_qid api_qid(implements_lib9p_srv_file *_self) { - struct api_file *self = VCALL_SELF(struct api_file, implements_lib9p_srv_file, _self); +static void api_free(struct api_file *self) { + assert(self); +} +static struct lib9p_qid api_qid(struct api_file *self) { assert(self); - return (struct lib9p_qid){ .type = LIB9P_QT_FILE, .vers = 1, .path = self->pathnum, }; } -static struct lib9p_stat api_stat(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *) { - struct api_file *self = VCALL_SELF(struct api_file, implements_lib9p_srv_file, _self); +static uint32_t api_chio(struct api_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { assert(self); + assert(ctx); + return 0; +} +static struct lib9p_stat api_stat(struct api_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); return (struct lib9p_stat){ .kern_type = 0, .kern_dev = 0, @@ -87,37 +86,50 @@ static struct lib9p_stat api_stat(implements_lib9p_srv_file *_self, struct lib9p .file_last_modified_n_uid = 0, }; } -static uint32_t api_pwrite(implements_lib9p_srv_file *, struct lib9p_srv_ctx *, void *, uint32_t byte_count, uint64_t) { +static void api_wstat(struct api_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_stat) { + assert(self); + assert(ctx); + lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file"); +} +static void api_remove(struct api_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file"); +} + +LIB9P_SRV_NOTDIR(struct api_file, api) + +static uint32_t api_pwrite(struct api_file *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t LM_UNUSED(offset)) { + assert(self); + assert(ctx); + assert(buf); if (byte_count == 0) return 0; for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) LO_CALL(lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i]), close); return byte_count; } - -static struct lib9p_srv_file_vtable api_file_vtable = { - .free = api_free, - .qid = api_qid, - .chio = api_chio, - - .stat = api_stat, - .wstat = api_wstat, - .remove = api_remove, - - .pread = NULL, - .pwrite = api_pwrite, -}; +static uint32_t api_pread(struct api_file *, struct lib9p_srv_ctx *, void *, uint32_t, uint64_t) { + assert_notreached("not readable"); +} /* file tree ******************************************************************/ +#define _box(nam, obj) \ + ((struct lib9p_srv_file){ \ + .self = obj, \ + .vtable = (void*)&_lo_##nam##_lib9p_srv_file_vtable, \ + }) +#define lo_box_util9p_static_file_as_lib9p_srv_file(obj) _box(util9p_static_file, obj) +#define lo_box_util9p_static_dir_as_lib9p_srv_file(obj) _box(util9p_static_dir, obj) +#define lo_box_api_as_lib9p_srv_file(obj) _box(api, obj) + enum { PATH_BASE = __COUNTER__ }; #define PATH_COUNTER __COUNTER__ - PATH_BASE #define STATIC_FILE(STRNAME, SYMNAME) \ - ((struct util9p_static_file){ \ + lo_box_util9p_static_file_as_lib9p_srv_file(&((struct util9p_static_file){ \ ._util9p_static_common = { \ - .vtable = &util9p_static_file_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 */ \ @@ -130,13 +142,11 @@ enum { PATH_BASE = __COUNTER__ }; }, \ .data_start = _binary_static_##SYMNAME##_start, \ .data_end = _binary_static_##SYMNAME##_end, \ - }) + })) #define STATIC_DIR(STRNAME, ...) \ - ((struct util9p_static_dir){ \ + lo_box_util9p_static_dir_as_lib9p_srv_file(&((struct util9p_static_dir){ \ ._util9p_static_common = { \ - .vtable = &util9p_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 */ \ @@ -147,19 +157,18 @@ enum { PATH_BASE = __COUNTER__ }; .atime = 1728337905, \ .mtime = 1728337904, \ }, \ - .members = { __VA_ARGS__ __VA_OPT__(,) NULL }, \ - }) - -/* NB: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118814 */ -static struct util9p_static_dir root = - STATIC_DIR("", - &STATIC_DIR("Documentation", - &STATIC_FILE("x", Documentation_x)), - &STATIC_FILE("README.md", README_md), - &((struct api_file){.vtable = &api_file_vtable, .pathnum = PATH_COUNTER})); - -static implements_lib9p_srv_file *get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { - return &root; + .members = { __VA_ARGS__ __VA_OPT__(,) LO_NULL(lib9p_srv_file) }, \ + })) + +struct lib9p_srv_file root = + STATIC_DIR("", + STATIC_DIR("Documentation", + STATIC_FILE("x", Documentation_x)), + STATIC_FILE("README.md", README_md), + lo_box_api_as_lib9p_srv_file(&(struct api_file){.pathnum = PATH_COUNTER})); + +static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { + return root; } /* main ***********************************************************************/ diff --git a/lib9p_util/include/util9p/static.h b/lib9p_util/include/util9p/static.h index 9ec03ef..4afdb51 100644 --- a/lib9p_util/include/util9p/static.h +++ b/lib9p_util/include/util9p/static.h @@ -1,6 +1,6 @@ /* util9p/static.h - Serve static files over 9P * - * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com> + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> * SPDX-License-Identifier: AGPL-3.0-or-later */ @@ -10,8 +10,6 @@ #include <lib9p/srv.h> typedef struct { - implements_lib9p_srv_file; - char *u_name; uint32_t u_num; char *g_name; @@ -29,9 +27,9 @@ struct util9p_static_dir { _util9p_static_common; /* NULL-terminated */ - implements_lib9p_srv_file *members[]; + lo_interface lib9p_srv_file members[]; }; - +LO_IMPLEMENTATION_H(lib9p_srv_file, struct util9p_static_dir, util9p_static_dir); struct util9p_static_file { _util9p_static_common; @@ -40,8 +38,6 @@ struct util9p_static_file { char *data_end; /* may be NULL, in which case data_size is used */ size_t data_size; /* only used if .data_end==NULL */ }; - -extern struct lib9p_srv_file_vtable util9p_static_dir_vtable; -extern struct lib9p_srv_file_vtable util9p_static_file_vtable; +LO_IMPLEMENTATION_H(lib9p_srv_file, struct util9p_static_file, util9p_static_file); #endif /* _UTIL9P_STATIC_H_ */ diff --git a/lib9p_util/static.c b/lib9p_util/static.c index 0f0efad..a6ea8f6 100644 --- a/lib9p_util/static.c +++ b/lib9p_util/static.c @@ -6,49 +6,18 @@ #include <libmisc/assert.h> #include <libmisc/macro.h> -#include <libmisc/vcall.h> #include <util9p/static.h> -/* common *********************************************************************/ +LO_IMPLEMENTATION_C(lib9p_srv_file, struct util9p_static_dir, util9p_static_dir, static); +LO_IMPLEMENTATION_C(lib9p_srv_file, struct util9p_static_file, util9p_static_file, static); -static void util9p_static_common_free(implements_lib9p_srv_file *_self) { - _util9p_static_common *self = VCALL_SELF(_util9p_static_common, implements_lib9p_srv_file, _self); - assert(self); - - /* do nothing */ -} - -static uint32_t util9p_static_common_chio(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx, - bool LM_UNUSED(rd), bool LM_UNUSED(wr), bool LM_UNUSED(trunc)) { - _util9p_static_common *self = VCALL_SELF(_util9p_static_common, implements_lib9p_srv_file, _self); - assert(self); - assert(ctx); - - return 0; -} +/* dir ************************************************************************/ -static void util9p_static_common_wstat(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx, - struct lib9p_stat LM_UNUSED(new)) { - _util9p_static_common *self = VCALL_SELF(_util9p_static_common, implements_lib9p_srv_file, _self); +static void util9p_static_dir_free(struct util9p_static_dir *self) { assert(self); - assert(ctx); - - lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem"); } - -static void util9p_static_common_remove(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx) { - _util9p_static_common *self = VCALL_SELF(_util9p_static_common, implements_lib9p_srv_file, _self); - assert(self); - assert(ctx); - - lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem"); -} - -/* dir ************************************************************************/ - -static struct lib9p_qid util9p_static_dir_qid(implements_lib9p_srv_file *_self) { - struct util9p_static_dir *self = VCALL_SELF(struct util9p_static_dir, implements_lib9p_srv_file, _self); +static struct lib9p_qid util9p_static_dir_qid(struct util9p_static_dir *self) { assert(self); return (struct lib9p_qid){ @@ -57,9 +26,13 @@ static struct lib9p_qid util9p_static_dir_qid(implements_lib9p_srv_file *_self) .path = self->pathnum, }; } +static uint32_t util9p_static_dir_chio(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { + assert(self); + assert(ctx); + return 0; +} -static struct lib9p_stat util9p_static_dir_stat(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx) { - struct util9p_static_dir *self = VCALL_SELF(struct util9p_static_dir, implements_lib9p_srv_file, _self); +static struct lib9p_stat util9p_static_dir_stat(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); @@ -81,51 +54,61 @@ static struct lib9p_stat util9p_static_dir_stat(implements_lib9p_srv_file *_self .file_last_modified_n_uid = self->m_num, }; } +static void util9p_static_dir_wstat(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, + struct lib9p_stat) { + assert(self); + assert(ctx); -static implements_lib9p_srv_file *util9p_static_dir_dopen(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx, - struct lib9p_s childname) { - struct util9p_static_dir *self = VCALL_SELF(struct util9p_static_dir, implements_lib9p_srv_file, _self); + lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem"); +} +static void util9p_static_dir_remove(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); - for (size_t i = 0; self->members[i]; i++) { - implements_lib9p_srv_file *filep = self->members[i]; - struct lib9p_stat stat = VCALL(filep, stat, ctx); + lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem"); +} + +static lo_interface lib9p_srv_file util9p_static_dir_dopen(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, + struct lib9p_s childname) { + assert(self); + assert(ctx); + + for (size_t i = 0; !LO_IS_NULL(self->members[i]); i++) { + lo_interface lib9p_srv_file file = self->members[i]; + struct lib9p_stat stat = LO_CALL(file, stat, ctx); if (lib9p_ctx_has_error(&ctx->basectx)) break; lib9p_stat_assert(stat); if (lib9p_str_eq(stat.file_name, childname)) - return filep; + return file; } lib9p_error(&ctx->basectx, LINUX_ENOENT, "no such file or directory"); - return NULL; + return LO_NULL(lib9p_srv_file); } -static implements_lib9p_srv_file *util9p_static_dir_dcreate(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx, - struct lib9p_s LM_UNUSED(childname), - lib9p_dm_t LM_UNUSED(perm), lib9p_o_t LM_UNUSED(flags)) { - struct util9p_static_dir *self = VCALL_SELF(struct util9p_static_dir, implements_lib9p_srv_file, _self); +static lo_interface lib9p_srv_file util9p_static_dir_dcreate(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, + struct lib9p_s LM_UNUSED(childname), + lib9p_dm_t LM_UNUSED(perm), lib9p_o_t LM_UNUSED(flags)) { assert(self); assert(ctx); lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem"); - return NULL; + return LO_NULL(lib9p_srv_file); } -static size_t util9p_static_dir_dread(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx, +static size_t util9p_static_dir_dread(struct util9p_static_dir *self, struct lib9p_srv_ctx *ctx, uint8_t *buf, uint32_t byte_count, size_t _obj_offset) { - struct util9p_static_dir *self = VCALL_SELF(struct util9p_static_dir, implements_lib9p_srv_file, _self); assert(self); assert(ctx); uint32_t byte_offset = 0; size_t obj_offset = _obj_offset; - while (self->members[obj_offset]) { - implements_lib9p_srv_file *filep = self->members[obj_offset]; - struct lib9p_stat stat = VCALL(filep, stat, ctx); + while (!LO_IS_NULL(self->members[obj_offset])) { + lo_interface lib9p_srv_file file = self->members[obj_offset]; + struct lib9p_stat stat = LO_CALL(file, stat, ctx); if (lib9p_ctx_has_error(&ctx->basectx)) break; lib9p_stat_assert(stat); @@ -143,22 +126,27 @@ static size_t util9p_static_dir_dread(implements_lib9p_srv_file *_self, struct l return obj_offset - _obj_offset; } -struct lib9p_srv_file_vtable util9p_static_dir_vtable = { - .free = util9p_static_common_free, - .qid = util9p_static_dir_qid, - .chio = util9p_static_common_chio, - - .stat = util9p_static_dir_stat, - .wstat = util9p_static_common_wstat, - .remove = util9p_static_common_remove, +LIB9P_SRV_NOTFILE(struct util9p_static_dir, util9p_static_dir) - .dopen = util9p_static_dir_dopen, - .dcreate = util9p_static_dir_dcreate, +/* file ***********************************************************************/ - .dread = util9p_static_dir_dread, -}; +static void util9p_static_file_free(struct util9p_static_file *self) { + assert(self); +} +static struct lib9p_qid util9p_static_file_qid(struct util9p_static_file *self) { + assert(self); -/* file ***********************************************************************/ + return (struct lib9p_qid){ + .type = LIB9P_QT_FILE, + .vers = 1, + .path = self->pathnum, + }; +} +static uint32_t util9p_static_file_chio(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { + assert(self); + assert(ctx); + return 0; +} static inline size_t util9p_static_file_size(struct util9p_static_file *file) { assert(file); @@ -171,19 +159,8 @@ static inline size_t util9p_static_file_size(struct util9p_static_file *file) { return (size_t)((uintptr_t)file->data_end - (uintptr_t)file->data_start); } -static struct lib9p_qid util9p_static_file_qid(implements_lib9p_srv_file *_self) { - struct util9p_static_file *self = VCALL_SELF(struct util9p_static_file, implements_lib9p_srv_file, _self); - assert(self); - - return (struct lib9p_qid){ - .type = LIB9P_QT_FILE, - .vers = 1, - .path = self->pathnum, - }; -} -static struct lib9p_stat util9p_static_file_stat(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx) { - struct util9p_static_file *self = VCALL_SELF(struct util9p_static_file, implements_lib9p_srv_file, _self); +static struct lib9p_stat util9p_static_file_stat(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx) { assert(self); assert(ctx); @@ -205,12 +182,26 @@ static struct lib9p_stat util9p_static_file_stat(implements_lib9p_srv_file *_sel .file_last_modified_n_uid = self->m_num, }; } +static void util9p_static_file_wstat(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, + struct lib9p_stat) { + assert(self); + assert(ctx); + + lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem"); +} +static void util9p_static_file_remove(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); -static uint32_t util9p_static_file_pread(implements_lib9p_srv_file *_self, struct lib9p_srv_ctx *ctx, + lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem"); +} + +LIB9P_SRV_NOTDIR(struct util9p_static_file, util9p_static_file) + +static uint32_t util9p_static_file_pread(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t byte_offset) { - struct util9p_static_file *self = VCALL_SELF(struct util9p_static_file, implements_lib9p_srv_file, _self); assert(self); assert(ctx); @@ -230,15 +221,13 @@ static uint32_t util9p_static_file_pread(implements_lib9p_srv_file *_self, struc return (uint32_t)(end_off-beg_off); } -struct lib9p_srv_file_vtable util9p_static_file_vtable = { - .free = util9p_static_common_free, - .qid = util9p_static_file_qid, - .chio = util9p_static_common_chio, - - .stat = util9p_static_file_stat, - .wstat = util9p_static_common_wstat, - .remove = util9p_static_common_remove, +static uint32_t util9p_static_file_pwrite(struct util9p_static_file *self, struct lib9p_srv_ctx *ctx, + void *LM_UNUSED(buf), + uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(byte_offset)) { + assert(self); + assert(ctx); - .pread = util9p_static_file_pread, - .pwrite = NULL, -}; + lib9p_error(&ctx->basectx, LINUX_EROFS, "read-only part of filesystem"); + return 0; +} |