summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib9p/include/lib9p/srv.h95
-rw-r--r--lib9p/srv.c67
-rw-r--r--lib9p/tests/test_server/main.c107
-rw-r--r--lib9p_util/include/util9p/static.h12
-rw-r--r--lib9p_util/static.c177
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;
+}