summaryrefslogtreecommitdiff
path: root/lib9p/tests/test_server/fs_whoami.c
blob: ff6dd251948f432ce8fcdcde8867423cb2e93daa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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,
	};
}