diff options
-rw-r--r-- | lib9p/include/lib9p/srv.h | 4 | ||||
-rw-r--r-- | lib9p/srv.c | 156 | ||||
-rw-r--r-- | lib9p/tests/test_server/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_whoami.c | 156 | ||||
-rw-r--r-- | lib9p/tests/test_server/fs_whoami.h | 20 | ||||
-rw-r--r-- | lib9p/tests/test_server/main.c | 2 | ||||
-rwxr-xr-x | lib9p/tests/testclient-p9p | 3 | ||||
-rw-r--r-- | lib9p/tests/testclient-p9p.explog | 4 | ||||
-rw-r--r-- | lib9p/tests/testclient-sess.c | 22 | ||||
-rw-r--r-- | lib9p/tests/testclient-sess.explog | 24 |
10 files changed, 337 insertions, 55 deletions
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h index 1b14c32..7109179 100644 --- a/lib9p/include/lib9p/srv.h +++ b/lib9p/include/lib9p/srv.h @@ -24,6 +24,10 @@ CR_CHAN_DECLARE(_lib9p_srv_flushch, bool); struct lib9p_srv_authinfo { lib9p_nuid_t uid; struct lib9p_s uname; + + BEGIN_PRIVATE(LIB9P_SRV_H); + unsigned int refcount; + END_PRIVATE(LIB9P_SRV_H); }; struct lib9p_srv_ctx { diff --git a/lib9p/srv.c b/lib9p/srv.c index e6a92ad..50e5dae 100644 --- a/lib9p/srv.c +++ b/lib9p/srv.c @@ -98,6 +98,7 @@ struct srv_pathinfo { struct srv_fidinfo { srv_path_t path; + struct lib9p_srv_authinfo *authinfo; uint8_t flags; enum srv_filetype type; union { @@ -109,6 +110,10 @@ struct srv_fidinfo { size_t idx; uint64_t off; } dir; + struct { + struct lib9p_s aname; + bool completed; + } auth; }; }; @@ -171,6 +176,35 @@ static inline bool srv_check_perm(struct srv_req *ctx, struct lib9p_stat *stat, return mode & action; } +struct lib9p_srv_authinfo *srv_authinfo_new(struct lib9p_s uname, lib9p_nuid_t uid) { + struct lib9p_srv_authinfo *ret = malloc(sizeof(struct lib9p_srv_authinfo) + uname.len); + if (!ret) + return NULL; + ret->uid = uid; + ret->uname.len = uname.len; + ret->uname.utf8 = (void *)&ret[1]; + memcpy(ret->uname.utf8, uname.utf8, uname.len); + ret->refcount = 1; + return ret; +} + +struct lib9p_srv_authinfo *srv_authinfo_decref(struct lib9p_srv_authinfo *authinfo) { + assert(authinfo); + assert(authinfo->refcount); + authinfo->refcount--; + if (!authinfo->refcount) { + free(authinfo); + return NULL; + } + return authinfo; +} + +struct lib9p_srv_authinfo *srv_authinfo_incref(struct lib9p_srv_authinfo *authinfo) { + assert(authinfo); + authinfo->refcount++; + return authinfo; +} + /** * Ensures that `file` is saved into the pathmap, and increments the * gc_refcount by 1 (for presumptive insertion into the fidmap). @@ -228,11 +262,7 @@ static inline void srv_path_decref(struct srv_req *ctx, srv_path_t path) { static inline void srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, bool remove) { struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, fid); - if (!fidinfo) { - lib9p_errorf(&ctx->basectx, - LINUX_EBADF, "bad file number %"PRIu32, fid); - return; - } + assert(fidinfo); if (fidinfo->flags & FIDFLAG_RCLOSE) remove = true; struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); @@ -270,7 +300,8 @@ static inline void srv_fid_del(struct srv_req *ctx, lib9p_fid_t fid, bool remove } pathinfo->io_refcount--; } - srv_path_decref(ctx, LO_CALL(pathinfo->file, qid).path); + fidinfo->authinfo = srv_authinfo_decref(fidinfo->authinfo); + srv_path_decref(ctx, fidinfo->path); map_del(&ctx->parent_sess->fids, fid); } @@ -296,8 +327,9 @@ static struct srv_fidinfo *srv_fid_store(struct srv_req *ctx, lib9p_fid_t fid, s } } struct srv_fidinfo *fidinfo = map_store(&ctx->parent_sess->fids, fid, (struct srv_fidinfo){ - .path = qid.path, - .type = srv_qid_filetype(qid), + .path = qid.path, + .type = srv_qid_filetype(qid), + .authinfo = srv_authinfo_incref(ctx->authinfo), }); assert(fidinfo); return fidinfo; @@ -443,13 +475,11 @@ void lib9p_srv_read(struct lib9p_srv *srv, lo_interface net_stream_conn _conn) { } if (srv_read_exactly(conn.fd, buf, 7, &done)) break; - struct lib9p_srv_authinfo authinfo = {}; struct srv_req req = { .basectx = { .version = sess.version, .max_msg_size = sess.max_msg_size, }, - .authinfo = &authinfo, .parent_sess = &sess, .tag = uint16le_decode(&buf[5]), @@ -715,19 +745,22 @@ static void handle_Tauth(struct srv_req *ctx, struct lib9p_msg_Rauth *resp) { srv_handler_common(ctx, req, resp); - ctx->authinfo->uid = req->n_uid; - ctx->authinfo->uname = req->uname; struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv; - if (!srv->auth) { lib9p_error(&ctx->basectx, LINUX_EOPNOTSUPP, "authentication not required"); return; } + ctx->authinfo = srv_authinfo_new(req->uname, req->n_uid); + srv->auth(ctx, req->aname); + lib9p_error(&ctx->basectx, LINUX_EOPNOTSUPP, "TODO: auth not implemented"); + + if (lib9p_ctx_has_error(&ctx->basectx)) + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); } static void handle_Tattach(struct srv_req *ctx, @@ -735,58 +768,59 @@ static void handle_Tattach(struct srv_req *ctx, struct lib9p_msg_Rattach *resp) { srv_handler_common(ctx, req, resp); - ctx->authinfo->uid = req->n_uid; - ctx->authinfo->uname = req->uname; - struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv; + if (req->fid == LIB9P_FID_NOFID) { + lib9p_error(&ctx->basectx, + LINUX_EBADF, "cannot assign to NOFID"); + return; + } + struct lib9p_srv *srv = ctx->parent_sess->parent_conn->parent_srv; if (srv->auth) { - /* - struct lib9p_srv_filehandle *fh = map_get(req->afid); - if (!fh) + struct srv_fidinfo *afid = map_load(&ctx->parent_sess->fids, req->afid); + if (!afid) lib9p_error(&ctx->basectx, LINUX_EACCES, "FID provided as auth-file is not a valid FID"); - else if (fh->type != FH_AUTH) + else if (afid->type != SRV_FILETYPE_AUTH) lib9p_error(&ctx->basectx, LINUX_EACCES, "FID provided as auth-file is not an auth-file"); - else if (!lib9p_str_eq(fh->data.auth.uname, req->uname)) + else if (!lib9p_str_eq(afid->authinfo->uname, req->uname)) lib9p_errorf(&ctx->basectx, LINUX_EACCES, "FID provided as auth-file is for user=\"%.*s\" and cannot be used for user=\"%.*s\"", - fh->data.auth.uname.len, fh->data.auth.uname.utf8, + afid->authinfo->uname.len, afid->authinfo->uname.utf8, req->uname.len, req->uname.utf8); - else if (!lib9p_str_eq(fh->data.auth.aname, req->aname)) +#if CONFIG_9P_ENABLE_9P2000_u + else if (afid->authinfo->uid != req->n_uid) + lib9p_errorf(&ctx->basectx, + LINUX_EACCES, "FID provided as auth-file is for user=%"PRIu32" and cannot be used for user=%"PRIu32, + afid->authinfo->uid, req->n_uid); +#endif + else if (!lib9p_str_eq(afid->auth.aname, req->aname)) lib9p_errorf(&ctx->basectx, LINUX_EACCES, "FID provided as auth-file is for tree=\"%.*s\" and cannot be used for tree=\"%.*s\"", - fh->data.auth.aname.len, fh->data.auth.aname.utf8, + afid->auth.aname.len, afid->auth.aname.utf8, req->aname.len, req->aname.utf8); - else if (!fh->data.auth.authenticated) + else if (!afid->auth.completed) lib9p_error(&ctx->basectx, LINUX_EACCES, "FID provided as auth-file has not completed authentication"); - fh->refcount--; - if (lib9p_ctx_has_error(&ctx->ctx)) + if (lib9p_ctx_has_error(&ctx->basectx)) return; - */ - lib9p_error(&ctx->basectx, - LINUX_EOPNOTSUPP, "TODO: auth not (yet?) implemented"); - return; + ctx->authinfo = srv_authinfo_incref(afid->authinfo); } else { if (req->afid != LIB9P_FID_NOFID) { lib9p_error(&ctx->basectx, LINUX_EACCES, "FID provided as auth-file, but no auth-file is required"); return; } - } - - if (req->fid == LIB9P_FID_NOFID) { - lib9p_error(&ctx->basectx, - LINUX_EBADF, "cannot assign to NOFID"); - return; + ctx->authinfo = srv_authinfo_new(req->uname, req->n_uid); } /* 1. File object */ lo_interface lib9p_srv_file root_file = srv->rootdir(ctx, req->aname); assert(LO_IS_NULL(root_file) == lib9p_ctx_has_error(&ctx->basectx)); - if (lib9p_ctx_has_error(&ctx->basectx)) + if (lib9p_ctx_has_error(&ctx->basectx)) { + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); return; + } struct lib9p_qid root_qid = LO_CALL(root_file, qid); assert(srv_qid_filetype(root_qid) == SRV_FILETYPE_DIR); @@ -797,9 +831,11 @@ static void handle_Tattach(struct srv_req *ctx, /* 3. fidinfo */ if (!srv_fid_store(ctx, req->fid, root_pathinfo, false)) { srv_path_decref(ctx, root_qid.path); + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); return; } + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); resp->qid = root_qid; return; } @@ -831,6 +867,7 @@ static void handle_Twalk(struct srv_req *ctx, LINUX_EBADF, "bad file number %"PRIu32, req->fid); return; } + ctx->authinfo = srv_authinfo_incref(fidinfo->authinfo); struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); @@ -884,6 +921,7 @@ static void handle_Twalk(struct srv_req *ctx, if (resp->nwqid > 0) lib9p_ctx_clear_error(&ctx->basectx); } + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); } static void handle_Topen(struct srv_req *ctx, @@ -912,6 +950,7 @@ static void handle_Topen(struct srv_req *ctx, return; } } + ctx->authinfo = srv_authinfo_incref(fidinfo->authinfo); /* Variables. */ lib9p_o_t reqmode = req->mode; @@ -925,23 +964,23 @@ static void handle_Topen(struct srv_req *ctx, assert(parent); struct lib9p_stat parent_stat = LO_CALL(parent->file, stat, ctx); if (lib9p_ctx_has_error(&ctx->basectx)) - return; + goto topen_return; lib9p_stat_assert(parent_stat); if (!srv_check_perm(ctx, &parent_stat, 0b010)) { lib9p_error(&ctx->basectx, LINUX_EACCES, "permission denied to remove-on-close"); - return; + goto topen_return; } fidflags |= FIDFLAG_RCLOSE; } struct lib9p_stat stat = LO_CALL(pathinfo->file, stat, ctx); if (lib9p_ctx_has_error(&ctx->basectx)) - return; + goto topen_return; lib9p_stat_assert(stat); if ((stat.file_mode & LIB9P_DM_EXCL) && pathinfo->io_refcount) { lib9p_error(&ctx->basectx, LINUX_EEXIST, "exclusive file is already opened"); - return; + goto topen_return; } if (stat.file_mode & LIB9P_DM_APPEND) reqmode = reqmode & ~LIB9P_O_TRUNC; @@ -968,7 +1007,7 @@ static void handle_Topen(struct srv_req *ctx, if (!srv_check_perm(ctx, &stat, perm_bits)) { lib9p_error(&ctx->basectx, LINUX_EACCES, "permission denied"); - return; + goto topen_return; } /* Actually make the call. */ @@ -979,7 +1018,7 @@ static void handle_Topen(struct srv_req *ctx, fidinfo->dir.io = LO_CALL(pathinfo->file, dopen, ctx); assert(LO_IS_NULL(fidinfo->dir.io) == lib9p_ctx_has_error(&ctx->basectx)); if (lib9p_ctx_has_error(&ctx->basectx)) - return; + goto topen_return; fidinfo->dir.idx = 0; fidinfo->dir.off = 0; qid = LO_CALL(fidinfo->dir.io, qid); @@ -991,7 +1030,7 @@ static void handle_Topen(struct srv_req *ctx, reqmode & LIB9P_O_TRUNC); assert(LO_IS_NULL(fidinfo->file.io) == lib9p_ctx_has_error(&ctx->basectx)); if (lib9p_ctx_has_error(&ctx->basectx)) - return; + goto topen_return; qid = LO_CALL(fidinfo->file.io, qid); iounit = LO_CALL(fidinfo->file.io, iounit); break; @@ -1012,6 +1051,8 @@ static void handle_Topen(struct srv_req *ctx, fidinfo->flags = fidflags; resp->qid = qid; resp->iounit = iounit; + topen_return: + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); } static void handle_Tcreate(struct srv_req *ctx, @@ -1044,6 +1085,7 @@ static void handle_Tread(struct srv_req *ctx, } /* Do it. */ + ctx->authinfo = srv_authinfo_incref(fidinfo->authinfo); switch (fidinfo->type) { case SRV_FILETYPE_DIR: /* Translate byte-offset to object-index. */ @@ -1056,6 +1098,7 @@ static void handle_Tread(struct srv_req *ctx, lib9p_errorf(&ctx->basectx, LINUX_EINVAL, "invalid offset (must be 0 or %"PRIu64"): %"PRIu64, fidinfo->dir.off, req->offset); + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); return; } /* Do it. */ @@ -1087,6 +1130,7 @@ static void handle_Tread(struct srv_req *ctx, assert_notreached("TODO: auth not yet implemented"); break; } + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); } static void handle_Twrite(struct srv_req *ctx, @@ -1110,7 +1154,9 @@ static void handle_Twrite(struct srv_req *ctx, } /* Do it. */ + ctx->authinfo = srv_authinfo_incref(fidinfo->authinfo); resp->count = LO_CALL(fidinfo->file.io, pwrite, ctx, req->data, req->count, req->offset); + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); } static void handle_Tclunk(struct srv_req *ctx, @@ -1118,7 +1164,16 @@ static void handle_Tclunk(struct srv_req *ctx, struct lib9p_msg_Rclunk *resp) { srv_handler_common(ctx, req, resp); + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); + if (!fidinfo) { + lib9p_errorf(&ctx->basectx, + LINUX_EBADF, "bad file number %"PRIu32, req->fid); + return; + } + + ctx->authinfo = srv_authinfo_incref(fidinfo->authinfo); srv_fid_del(ctx, req->fid, false); + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); } static void handle_Tremove(struct srv_req *ctx, @@ -1126,7 +1181,16 @@ static void handle_Tremove(struct srv_req *ctx, struct lib9p_msg_Rremove *resp) { srv_handler_common(ctx, req, resp); + struct srv_fidinfo *fidinfo = map_load(&ctx->parent_sess->fids, req->fid); + if (!fidinfo) { + lib9p_errorf(&ctx->basectx, + LINUX_EBADF, "bad file number %"PRIu32, req->fid); + return; + } + + ctx->authinfo = srv_authinfo_incref(fidinfo->authinfo); srv_fid_del(ctx, req->fid, true); + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); } static void handle_Tstat(struct srv_req *ctx, @@ -1143,9 +1207,11 @@ static void handle_Tstat(struct srv_req *ctx, struct srv_pathinfo *pathinfo = map_load(&ctx->parent_sess->paths, fidinfo->path); assert(pathinfo); + ctx->authinfo = srv_authinfo_incref(fidinfo->authinfo); resp->stat = LO_CALL(pathinfo->file, stat, ctx); if (!lib9p_ctx_has_error(&ctx->basectx)) lib9p_stat_assert(resp->stat); + ctx->authinfo = srv_authinfo_decref(ctx->authinfo); } static void handle_Twstat(struct srv_req *ctx, diff --git a/lib9p/tests/test_server/CMakeLists.txt b/lib9p/tests/test_server/CMakeLists.txt index eb16165..681e583 100644 --- a/lib9p/tests/test_server/CMakeLists.txt +++ b/lib9p/tests/test_server/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(test_server_objs OBJECT main.c fs_shutdown.c fs_slowread.c + fs_whoami.c ) target_include_directories(test_server_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config) target_include_directories(test_server_objs PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/lib9p/tests/test_server/fs_whoami.c b/lib9p/tests/test_server/fs_whoami.c new file mode 100644 index 0000000..ff6dd25 --- /dev/null +++ b/lib9p/tests/test_server/fs_whoami.c @@ -0,0 +1,156 @@ +/* lib9p/tests/test_server/fs_whoami.c - /whoami API endpoint + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#include <stdio.h> /* for snprintf() */ +#include <stdlib.h> /* for malloc(), realloc(), free() */ + +#include "fs_whoami.h" + +LO_IMPLEMENTATION_C(lib9p_srv_file, struct whoami_file, whoami_file, static); + +struct whoami_fio { + struct whoami_file *parent; + size_t buf_len; + char *buf; +}; +LO_IMPLEMENTATION_H(lib9p_srv_fio, struct whoami_fio, whoami_fio); +LO_IMPLEMENTATION_C(lib9p_srv_fio, struct whoami_fio, whoami_fio, static); + +size_t whoami_len(struct lib9p_srv_ctx *ctx) { + assert(ctx); + assert(ctx->authinfo); + + size_t len = 0; + uint32_t uid = ctx->authinfo->uid; + while (uid) { + len++; + uid /= 10; + } + if (!len) + len++; + len += 2; + len += ctx->authinfo->uname.len; + return len; +} + +/* srv_file *******************************************************************/ + +static void whoami_file_free(struct whoami_file *self) { + assert(self); +} +static struct lib9p_qid whoami_file_qid(struct whoami_file *self) { + assert(self); + return (struct lib9p_qid){ + .type = LIB9P_QT_FILE, + .vers = 1, + .path = self->pathnum, + }; +} + +static struct lib9p_stat whoami_file_stat(struct whoami_file *self, struct lib9p_srv_ctx *ctx) { + assert(self); + assert(ctx); + + return (struct lib9p_stat){ + .kern_type = 0, + .kern_dev = 0, + .file_qid = whoami_file_qid(self), + .file_mode = 0444, + .file_atime = UTIL9P_ATIME, + .file_mtime = UTIL9P_MTIME, + .file_size = whoami_len(ctx), + .file_name = lib9p_str(self->name), + .file_owner_uid = lib9p_str("root"), + .file_owner_gid = lib9p_str("root"), + .file_last_modified_uid = lib9p_str("root"), + .file_extension = lib9p_str(NULL), + .file_owner_n_uid = 0, + .file_owner_n_gid = 0, + .file_last_modified_n_uid = 0, + }; +} +static void whoami_file_wstat(struct whoami_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 whoami_file_remove(struct whoami_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 whoami_file, whoami_file) + +static lo_interface lib9p_srv_fio whoami_file_fopen(struct whoami_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) { + assert(self); + assert(ctx); + + struct whoami_fio *ret = malloc(sizeof(struct whoami_fio)); + ret->parent = self; + ret->buf_len = 0; + ret->buf = NULL; + + return lo_box_whoami_fio_as_lib9p_srv_fio(ret); +} + +/* srv_fio ********************************************************************/ + +static void whoami_fio_iofree(struct whoami_fio *self) { + assert(self); + if (self->buf) + free(self->buf); + free(self); +} + +static struct lib9p_qid whoami_fio_qid(struct whoami_fio *self) { + assert(self); + assert(self->parent); + return whoami_file_qid(self->parent); +} + +static uint32_t whoami_fio_iounit(struct whoami_fio *self) { + assert(self); + return 0; +} + +static uint32_t whoami_fio_pwrite(struct whoami_fio *LM_UNUSED(self), + struct lib9p_srv_ctx *LM_UNUSED(ctx), + void *LM_UNUSED(buf), uint32_t LM_UNUSED(byte_count), + uint64_t LM_UNUSED(offset)) { + assert_notreached("not writable"); +} +static void whoami_fio_pread(struct whoami_fio *self, struct lib9p_srv_ctx *ctx, + uint32_t byte_count, uint64_t byte_offset, + struct iovec *ret) { + assert(self); + assert(ctx); + assert(ret); + + size_t data_size = whoami_len(ctx); + if (self->buf_len < data_size+1) { + self->buf = realloc(self->buf, data_size+1); + self->buf_len = data_size+1; + } + snprintf(self->buf, self->buf_len, "%"PRIu32" %.*s\n", + ctx->authinfo->uid, ctx->authinfo->uname.len, ctx->authinfo->uname.utf8); + + if (byte_offset > (uint64_t)data_size) { + lib9p_error(&ctx->basectx, + LINUX_EINVAL, "offset is past end-of-file length"); + return; + } + + size_t beg_off = (size_t)byte_offset; + size_t end_off = beg_off + (size_t)byte_count; + if (end_off > data_size) + end_off = data_size; + + *ret = (struct iovec){ + .iov_base = &self->buf[beg_off], + .iov_len = end_off-beg_off, + }; +} diff --git a/lib9p/tests/test_server/fs_whoami.h b/lib9p/tests/test_server/fs_whoami.h new file mode 100644 index 0000000..0d3d311 --- /dev/null +++ b/lib9p/tests/test_server/fs_whoami.h @@ -0,0 +1,20 @@ +/* lib9p/tests/test_server/fs_whoami.h - /whoami API endpoint + * + * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +#ifndef _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ +#define _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ + +#include <util9p/static.h> +#include <libhw/host_net.h> + +struct whoami_file { + char *name; + uint64_t pathnum; +}; +LO_IMPLEMENTATION_H(lib9p_srv_file, struct whoami_file, whoami_file); +#define lo_box_whoami_file_as_lib9p_srv_file(obj) util9p_box(whoami_file, obj) + +#endif /* _LIB9P_TESTS_TEST_SERVER_FS_WHOAMI_H_ */ diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c index b543892..e89a75e 100644 --- a/lib9p/tests/test_server/main.c +++ b/lib9p/tests/test_server/main.c @@ -21,6 +21,7 @@ #include "static.h" #include "fs_shutdown.h" #include "fs_slowread.h" +#include "fs_whoami.h" /* configuration **************************************************************/ @@ -76,6 +77,7 @@ struct lib9p_srv_file root = .flushable = false), API_FILE(7, "slowread-flushable", slowread, .flushable = true), + API_FILE(8, "whoami", whoami), ); static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) { diff --git a/lib9p/tests/testclient-p9p b/lib9p/tests/testclient-p9p index 2e5a6f3..9c9fb5e 100755 --- a/lib9p/tests/testclient-p9p +++ b/lib9p/tests/testclient-p9p @@ -27,7 +27,8 @@ expect_lines \ '--r--r--r-- M 0 root root 166 Oct 7 2024 README.md' \ '---w--w--w- M 0 root root 0 Oct 7 2024 shutdown' \ '--r--r--r-- M 0 root root 6 Oct 7 2024 slowread' \ - '--r--r--r-- M 0 root root 6 Oct 7 2024 slowread-flushable' + '--r--r--r-- M 0 root root 6 Oct 7 2024 slowread-flushable' \ + '--r--r--r-- M 0 root root 9 Oct 7 2024 whoami' out=$("${client[@]}" ls -l 'Documentation/') expect_lines \ diff --git a/lib9p/tests/testclient-p9p.explog b/lib9p/tests/testclient-p9p.explog index 905a60f..45651a4 100644 --- a/lib9p/tests/testclient-p9p.explog +++ b/lib9p/tests/testclient-p9p.explog @@ -19,8 +19,8 @@ > Topen { tag=0 fid=1 mode=(MODE_READ) } < Ropen { tag=0 qid={ type=(DIR) vers=1 path=1 } iounit=0 } > Tread { tag=0 fid=1 offset=0 count=4096 } -< Rread { tag=0 count=361 data=<bytedata> } -> Tread { tag=0 fid=1 offset=361 count=4096 } +< Rread { tag=0 count=428 data=<bytedata> } +> Tread { tag=0 fid=1 offset=428 count=4096 } < Rread { tag=0 count=0 data="" } > Tclunk { tag=0 fid=1 } < Rclunk { tag=0 } diff --git a/lib9p/tests/testclient-sess.c b/lib9p/tests/testclient-sess.c index 423dc2c..437c489 100644 --- a/lib9p/tests/testclient-sess.c +++ b/lib9p/tests/testclient-sess.c @@ -91,12 +91,28 @@ int main(int argc, char *argv[]) { recv9p(); /* Rversion */ ctx.version = LIB9P_VER_9P2000_u; - /* ext version ********************************************************/ - send9p(Tversion, .tag=0, .max_msg_size=57, .version=lib9p_str("9P2000.u")); + /* ext version, users *************************************************/ + send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000.u")); recv9p(); /* Rversion */ ctx.version = LIB9P_VER_9P2000_u; + send9p(Tattach, .tag=0, .fid=0, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("alice"), .n_uid=1000, .aname=lib9p_str("")); + recv9p(); /* Rattach */ + send9p(Tattach, .tag=0, .fid=1, .afid=LIB9P_FID_NOFID, .uname=lib9p_str("bob"), .n_uid=1001, .aname=lib9p_str("")); + recv9p(); /* Rattach */ + wname[0] = lib9p_str("whoami"); send9p(Twalk, .tag=0, .fid=0, .newfid=2, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + wname[0] = lib9p_str("whoami"); send9p(Twalk, .tag=0, .fid=1, .newfid=3, .nwname=1, .wname=wname); + recv9p(); /* Rwalk */ + send9p(Topen, .tag=0, .fid=2, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Topen, .tag=0, .fid=3, .mode=LIB9P_O_MODE_READ); + recv9p(); /* Ropen */ + send9p(Tread, .tag=0, .fid=2, .offset=0, .count=100); + recv9p(); /* Rread */ + send9p(Tread, .tag=0, .fid=3, .offset=0, .count=100); + recv9p(); /* Rread */ - /* main session *******************************************************/ + /* flush **************************************************************/ send9p(Tversion, .tag=0, .max_msg_size=(8*1024), .version=lib9p_str("9P2000")); recv9p(); /* Rversion */ ctx.version = LIB9P_VER_9P2000; diff --git a/lib9p/tests/testclient-sess.explog b/lib9p/tests/testclient-sess.explog index b1f3085..6aab242 100644 --- a/lib9p/tests/testclient-sess.explog +++ b/lib9p/tests/testclient-sess.explog @@ -11,11 +11,27 @@ > Tversion { tag=0 max_msg_size=57 version="9P2025.u" } < Rversion { tag=0 max_msg_size=57 version="9P2000.u" } -# ext version ################################################################## -> Tversion { tag=0 max_msg_size=57 version="9P2000.u" } -< Rversion { tag=0 max_msg_size=57 version="9P2000.u" } +# ext version, users ########################################################### +> Tversion { tag=0 max_msg_size=8192 version="9P2000.u" } +< Rversion { tag=0 max_msg_size=4120 version="9P2000.u" } +> Tattach { tag=0 fid=0 afid=NOFID uname="alice" aname="" n_uid=1000 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Tattach { tag=0 fid=1 afid=NOFID uname="bob" aname="" n_uid=1001 } +< Rattach { tag=0 qid={ type=(DIR) vers=1 path=1 } } +> Twalk { tag=0 fid=0 newfid=2 nwname=1 wname=["whoami" ] } +< Rwalk { tag=0 nwqid=1 wqid=[{ type=(0) vers=1 path=8 } ] } +> Twalk { tag=0 fid=1 newfid=3 nwname=1 wname=["whoami" ] } +< Rwalk { tag=0 nwqid=1 wqid=[{ type=(0) vers=1 path=8 } ] } +> Topen { tag=0 fid=2 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=8 } iounit=0 } +> Topen { tag=0 fid=3 mode=(MODE_READ) } +< Ropen { tag=0 qid={ type=(0) vers=1 path=8 } iounit=0 } +> Tread { tag=0 fid=2 offset=0 count=100 } +< Rread { tag=0 count=11 data="1000 alice\n" } +> Tread { tag=0 fid=3 offset=0 count=100 } +< Rread { tag=0 count=9 data="1001 bob\n" } -# main session ################################################################# +# flush ######################################################################## > Tversion { tag=0 max_msg_size=8192 version="9P2000" } < Rversion { tag=0 max_msg_size=4120 version="9P2000" } > Tattach { tag=0 fid=0 afid=NOFID uname="nobody" aname="" n_uid=0 } |