/* lib9p/tests/test_server/fs_whoami.c - /whoami API endpoint * * Copyright (C) 2024-2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include /* for snprintf() */ #include /* 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, }; }