Blame


1 0a04a7c0 2023-12-19 benni #define PLEDGENAMES
2 0a04a7c0 2023-12-19 benni #include <sys/param.h>
3 0a04a7c0 2023-12-19 benni #include <sys/sysctl.h>
4 0a04a7c0 2023-12-19 benni #include <sys/proc.h>
5 0a04a7c0 2023-12-19 benni #include <sys/file.h>
6 0a04a7c0 2023-12-19 benni #include <sys/pledge.h>
7 0a04a7c0 2023-12-19 benni
8 0a04a7c0 2023-12-19 benni #include <stdbool.h>
9 0a04a7c0 2023-12-19 benni #include <assert.h>
10 0a04a7c0 2023-12-19 benni #include <stdlib.h>
11 0a04a7c0 2023-12-19 benni #include <string.h>
12 0a04a7c0 2023-12-19 benni #include <limits.h>
13 0a04a7c0 2023-12-19 benni #include <errno.h>
14 0a04a7c0 2023-12-19 benni #include <fcntl.h>
15 0a04a7c0 2023-12-19 benni #include <fuse.h>
16 0a04a7c0 2023-12-19 benni #include <kvm.h>
17 0a04a7c0 2023-12-19 benni #include <err.h>
18 0a04a7c0 2023-12-19 benni
19 0a04a7c0 2023-12-19 benni // TODO: envv: not idx, but envar name
20 0a04a7c0 2023-12-19 benni
21 0a04a7c0 2023-12-19 benni #define MY_KERN_PROC KERN_PROC_KTHREAD
22 0a04a7c0 2023-12-19 benni
23 0a04a7c0 2023-12-19 benni static kvm_t *kd;
24 0a04a7c0 2023-12-19 benni struct myfile {
25 0a04a7c0 2023-12-19 benni const char *name;
26 0a04a7c0 2023-12-19 benni int(*read)(struct kinfo_proc *, char *, size_t, off_t);
27 0a04a7c0 2023-12-19 benni };
28 0a04a7c0 2023-12-19 benni struct myfdfile {
29 0a04a7c0 2023-12-19 benni const char *name;
30 0a04a7c0 2023-12-19 benni int(*read)(struct kinfo_file *, char *, size_t, off_t);
31 0a04a7c0 2023-12-19 benni };
32 0a04a7c0 2023-12-19 benni
33 0a04a7c0 2023-12-19 benni #include "files.h"
34 0a04a7c0 2023-12-19 benni
35 0a04a7c0 2023-12-19 benni enum path_type {
36 0a04a7c0 2023-12-19 benni PATH_ROOT,
37 0a04a7c0 2023-12-19 benni PATH_PID,
38 0a04a7c0 2023-12-19 benni PATH_PID_FILE,
39 0a04a7c0 2023-12-19 benni PATH_PID_ARGV,
40 0a04a7c0 2023-12-19 benni PATH_PID_ARGV_NUM,
41 0a04a7c0 2023-12-19 benni PATH_PID_ENVV,
42 0a04a7c0 2023-12-19 benni PATH_PID_ENVV_NAME,
43 0a04a7c0 2023-12-19 benni PATH_PID_FD,
44 0a04a7c0 2023-12-19 benni PATH_PID_FD_NUM,
45 0a04a7c0 2023-12-19 benni PATH_PID_FD_NUM_FILE,
46 0a04a7c0 2023-12-19 benni };
47 0a04a7c0 2023-12-19 benni
48 0a04a7c0 2023-12-19 benni struct path {
49 0a04a7c0 2023-12-19 benni enum path_type type;
50 0a04a7c0 2023-12-19 benni int pid;
51 0a04a7c0 2023-12-19 benni int fd;
52 0a04a7c0 2023-12-19 benni int num;
53 0a04a7c0 2023-12-19 benni const char *file;
54 0a04a7c0 2023-12-19 benni };
55 0a04a7c0 2023-12-19 benni
56 0a04a7c0 2023-12-19 benni static int
57 0a04a7c0 2023-12-19 benni parse_path(const char *path, struct path *p)
58 0a04a7c0 2023-12-19 benni {
59 0a04a7c0 2023-12-19 benni const char *suffix;
60 0a04a7c0 2023-12-19 benni int num;
61 0a04a7c0 2023-12-19 benni
62 0a04a7c0 2023-12-19 benni memset(p, 0, sizeof (*p));
63 0a04a7c0 2023-12-19 benni
64 0a04a7c0 2023-12-19 benni if (strcmp(path, "/") == 0) {
65 0a04a7c0 2023-12-19 benni p->type = PATH_ROOT;
66 0a04a7c0 2023-12-19 benni return 0;
67 0a04a7c0 2023-12-19 benni } else if (sscanf(path, "/%d%n", &p->pid, &num) == 1) {
68 0a04a7c0 2023-12-19 benni suffix = path + num;
69 0a04a7c0 2023-12-19 benni
70 0a04a7c0 2023-12-19 benni if (*suffix == '\0') {
71 0a04a7c0 2023-12-19 benni p->type = PATH_PID;
72 0a04a7c0 2023-12-19 benni return 0;
73 0a04a7c0 2023-12-19 benni } else if (strncmp(suffix, "/argv", 5) == 0) {
74 0a04a7c0 2023-12-19 benni suffix += 5;
75 0a04a7c0 2023-12-19 benni if (*path == '\0') {
76 0a04a7c0 2023-12-19 benni p->type = PATH_PID_ARGV;
77 0a04a7c0 2023-12-19 benni return 0;
78 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/%d%n", &p->num, &num) == 1) {
79 0a04a7c0 2023-12-19 benni p->type = PATH_PID_ARGV_NUM;
80 0a04a7c0 2023-12-19 benni return 0;
81 0a04a7c0 2023-12-19 benni } else {
82 0a04a7c0 2023-12-19 benni return -ENOENT;
83 0a04a7c0 2023-12-19 benni }
84 0a04a7c0 2023-12-19 benni } else if (strncmp(suffix, "/envv", 5) == 0) {
85 0a04a7c0 2023-12-19 benni suffix += 5;
86 0a04a7c0 2023-12-19 benni if (*path == '\0') {
87 0a04a7c0 2023-12-19 benni p->type = PATH_PID_ENVV;
88 0a04a7c0 2023-12-19 benni return 0;
89 0a04a7c0 2023-12-19 benni } else if (strchr(suffix + 1, '/') == NULL) {
90 0a04a7c0 2023-12-19 benni p->type = PATH_PID_ENVV_NAME;
91 0a04a7c0 2023-12-19 benni p->file = suffix + 1;
92 0a04a7c0 2023-12-19 benni return 0;
93 0a04a7c0 2023-12-19 benni } else {
94 0a04a7c0 2023-12-19 benni return -ENOENT;
95 0a04a7c0 2023-12-19 benni }
96 0a04a7c0 2023-12-19 benni } else if (strncmp(suffix, "/fd", 3) == 0) {
97 0a04a7c0 2023-12-19 benni suffix += 3;
98 0a04a7c0 2023-12-19 benni if (*path == '\0') {
99 0a04a7c0 2023-12-19 benni p->type = PATH_PID_FD;
100 0a04a7c0 2023-12-19 benni return 0;
101 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/%d%n", &p->fd, &num) == 1) {
102 0a04a7c0 2023-12-19 benni suffix += num;
103 0a04a7c0 2023-12-19 benni if (*path == '\0') {
104 0a04a7c0 2023-12-19 benni p->type = PATH_PID_FD_NUM;
105 0a04a7c0 2023-12-19 benni return 0;
106 0a04a7c0 2023-12-19 benni } else {
107 0a04a7c0 2023-12-19 benni return -ENOENT;
108 0a04a7c0 2023-12-19 benni }
109 0a04a7c0 2023-12-19 benni } else {
110 0a04a7c0 2023-12-19 benni return -ENOENT;
111 0a04a7c0 2023-12-19 benni }
112 0a04a7c0 2023-12-19 benni } else {
113 0a04a7c0 2023-12-19 benni // TODO
114 0a04a7c0 2023-12-19 benni return -ENOENT;
115 0a04a7c0 2023-12-19 benni }
116 0a04a7c0 2023-12-19 benni } else {
117 0a04a7c0 2023-12-19 benni return -ENOENT;
118 0a04a7c0 2023-12-19 benni }
119 0a04a7c0 2023-12-19 benni }
120 0a04a7c0 2023-12-19 benni
121 0a04a7c0 2023-12-19 benni static int
122 0a04a7c0 2023-12-19 benni fs_readdir(const char *path, void *data, fuse_fill_dir_t filler,
123 0a04a7c0 2023-12-19 benni off_t off, struct fuse_file_info *ffi)
124 0a04a7c0 2023-12-19 benni {
125 0a04a7c0 2023-12-19 benni int pid, num;
126 0a04a7c0 2023-12-19 benni
127 0a04a7c0 2023-12-19 benni (void)ffi;
128 0a04a7c0 2023-12-19 benni
129 0a04a7c0 2023-12-19 benni printf("readdir(%s, off=%u);\n", path, (unsigned int)off);
130 0a04a7c0 2023-12-19 benni
131 0a04a7c0 2023-12-19 benni if (strcmp(path, "/") == 0) {
132 0a04a7c0 2023-12-19 benni struct kinfo_proc *kp;
133 0a04a7c0 2023-12-19 benni int nentries;
134 0a04a7c0 2023-12-19 benni
135 0a04a7c0 2023-12-19 benni kp = kvm_getprocs(kd, MY_KERN_PROC, 0, sizeof(*kp), &nentries);
136 0a04a7c0 2023-12-19 benni if (kp == NULL) {
137 0a04a7c0 2023-12-19 benni warnx("readdir(/): %s", kvm_geterr(kd));
138 0a04a7c0 2023-12-19 benni return -EIO;
139 0a04a7c0 2023-12-19 benni }
140 0a04a7c0 2023-12-19 benni
141 0a04a7c0 2023-12-19 benni filler(data, ".", NULL, 0);
142 0a04a7c0 2023-12-19 benni filler(data, "..", NULL, 0);
143 0a04a7c0 2023-12-19 benni for (int i = 0; i < nentries; ++i) {
144 0a04a7c0 2023-12-19 benni char str[32];
145 0a04a7c0 2023-12-19 benni snprintf (str, sizeof(str), "%d", kp[i].p_pid);
146 0a04a7c0 2023-12-19 benni filler(data, str, NULL, 0);
147 0a04a7c0 2023-12-19 benni }
148 0a04a7c0 2023-12-19 benni return 0;
149 0a04a7c0 2023-12-19 benni } else if (sscanf(path, "/%d%n", &pid, &num) == 1) {
150 0a04a7c0 2023-12-19 benni const char *suffix = path + num;
151 0a04a7c0 2023-12-19 benni struct kinfo_proc *kp;
152 0a04a7c0 2023-12-19 benni unsigned int idx;
153 0a04a7c0 2023-12-19 benni int nentries;
154 0a04a7c0 2023-12-19 benni
155 0a04a7c0 2023-12-19 benni kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(*kp), &nentries);
156 0a04a7c0 2023-12-19 benni if (kp == NULL || nentries == 0) {
157 0a04a7c0 2023-12-19 benni warnx("readdir(%s): %s", path, kvm_geterr(kd));
158 0a04a7c0 2023-12-19 benni return -ENOENT;
159 0a04a7c0 2023-12-19 benni } else if (nentries > 1) {
160 0a04a7c0 2023-12-19 benni warnx("readdir(%s): Too many results", path);
161 0a04a7c0 2023-12-19 benni return -EIO;
162 0a04a7c0 2023-12-19 benni }
163 0a04a7c0 2023-12-19 benni
164 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "") == 0) {
165 0a04a7c0 2023-12-19 benni filler(data, ".", NULL, 0);
166 0a04a7c0 2023-12-19 benni filler(data, "..", NULL, 0);
167 0a04a7c0 2023-12-19 benni filler(data, "parent", NULL, 0);
168 0a04a7c0 2023-12-19 benni filler(data, "argv", NULL, 0);
169 0a04a7c0 2023-12-19 benni filler(data, "envv", NULL, 0);
170 0a04a7c0 2023-12-19 benni filler(data, "fd", NULL, 0);
171 0a04a7c0 2023-12-19 benni for (const struct myfile *f = files; f->name != NULL; ++f)
172 0a04a7c0 2023-12-19 benni filler(data, f->name + 1, NULL, 0);
173 0a04a7c0 2023-12-19 benni return 0;
174 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/argv") == 0) {
175 0a04a7c0 2023-12-19 benni char **argv = kvm_getargv(kd, kp, 0);
176 0a04a7c0 2023-12-19 benni
177 0a04a7c0 2023-12-19 benni if (argv == NULL) {
178 0a04a7c0 2023-12-19 benni warnx("readdir(%s): %s", path, kvm_geterr(kd));
179 0a04a7c0 2023-12-19 benni return -EIO;
180 0a04a7c0 2023-12-19 benni }
181 0a04a7c0 2023-12-19 benni
182 0a04a7c0 2023-12-19 benni filler(data, ".", NULL, 0);
183 0a04a7c0 2023-12-19 benni filler(data, "..", NULL, 0);
184 0a04a7c0 2023-12-19 benni for (size_t i = 0; argv[i] != NULL; ++i) {
185 0a04a7c0 2023-12-19 benni char buffer[32];
186 0a04a7c0 2023-12-19 benni int n;
187 0a04a7c0 2023-12-19 benni
188 0a04a7c0 2023-12-19 benni n = snprintf(buffer, sizeof (buffer), "%zu", i);
189 0a04a7c0 2023-12-19 benni assert(n < (int)sizeof (buffer));
190 0a04a7c0 2023-12-19 benni
191 0a04a7c0 2023-12-19 benni filler(data, buffer, NULL, 0);
192 0a04a7c0 2023-12-19 benni }
193 0a04a7c0 2023-12-19 benni return 0;
194 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/envv") == 0) {
195 0a04a7c0 2023-12-19 benni char **envv = kvm_getenvv(kd, kp, 0);
196 0a04a7c0 2023-12-19 benni
197 0a04a7c0 2023-12-19 benni if (envv == NULL) {
198 0a04a7c0 2023-12-19 benni warnx("readdir(%s): %s", path, kvm_geterr(kd));
199 0a04a7c0 2023-12-19 benni return -EIO;
200 0a04a7c0 2023-12-19 benni }
201 0a04a7c0 2023-12-19 benni
202 0a04a7c0 2023-12-19 benni filler(data, ".", NULL, 0);
203 0a04a7c0 2023-12-19 benni filler(data, "..", NULL, 0);
204 0a04a7c0 2023-12-19 benni for (size_t i = 0; envv[i] != NULL; ++i) {
205 0a04a7c0 2023-12-19 benni char buffer[32];
206 0a04a7c0 2023-12-19 benni int n;
207 0a04a7c0 2023-12-19 benni
208 0a04a7c0 2023-12-19 benni n = snprintf(buffer, sizeof (buffer), "%zu", i);
209 0a04a7c0 2023-12-19 benni assert(n < (int)sizeof (buffer));
210 0a04a7c0 2023-12-19 benni
211 0a04a7c0 2023-12-19 benni filler(data, buffer, NULL, 0);
212 0a04a7c0 2023-12-19 benni }
213 0a04a7c0 2023-12-19 benni return 0;
214 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/fd") == 0) {
215 0a04a7c0 2023-12-19 benni struct kinfo_file *files;
216 0a04a7c0 2023-12-19 benni
217 0a04a7c0 2023-12-19 benni files = kvm_getfiles (kd, KERN_FILE_BYPID, pid, sizeof (*files), &nentries);
218 0a04a7c0 2023-12-19 benni
219 0a04a7c0 2023-12-19 benni if (files == NULL) {
220 0a04a7c0 2023-12-19 benni warnx("readdir(%s): %s", path, kvm_geterr(kd));
221 0a04a7c0 2023-12-19 benni return -EIO;
222 0a04a7c0 2023-12-19 benni }
223 0a04a7c0 2023-12-19 benni
224 0a04a7c0 2023-12-19 benni filler(data, ".", NULL, 0);
225 0a04a7c0 2023-12-19 benni filler(data, "..", NULL, 0);
226 0a04a7c0 2023-12-19 benni
227 0a04a7c0 2023-12-19 benni printf("nentries = %d\n", nentries);
228 0a04a7c0 2023-12-19 benni
229 0a04a7c0 2023-12-19 benni for (int i = 0; i < nentries; ++i) {
230 0a04a7c0 2023-12-19 benni char buffer[32];
231 0a04a7c0 2023-12-19 benni snprintf(buffer, sizeof (buffer), "%d", i);
232 0a04a7c0 2023-12-19 benni filler(data, buffer, NULL, 0);
233 0a04a7c0 2023-12-19 benni }
234 0a04a7c0 2023-12-19 benni
235 0a04a7c0 2023-12-19 benni return 0;
236 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/fd/%u%n", &idx, &num) == 1) {
237 0a04a7c0 2023-12-19 benni struct kinfo_file *files;
238 0a04a7c0 2023-12-19 benni
239 0a04a7c0 2023-12-19 benni suffix += num;
240 0a04a7c0 2023-12-19 benni files = kvm_getfiles(kd, KERN_FILE_BYPID, pid, sizeof (*files), &nentries);
241 0a04a7c0 2023-12-19 benni if (files == NULL) {
242 0a04a7c0 2023-12-19 benni warnx("readdir(%s): %s", path, kvm_geterr(kd));
243 0a04a7c0 2023-12-19 benni return -EIO;
244 0a04a7c0 2023-12-19 benni }
245 0a04a7c0 2023-12-19 benni
246 0a04a7c0 2023-12-19 benni if (idx >= (unsigned int)nentries)
247 0a04a7c0 2023-12-19 benni return -ENOENT;
248 0a04a7c0 2023-12-19 benni
249 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "") == 0) {
250 0a04a7c0 2023-12-19 benni filler(data, ".", NULL, 0);
251 0a04a7c0 2023-12-19 benni filler(data, "..", NULL, 0);
252 0a04a7c0 2023-12-19 benni for (const struct myfdfile *f = fd_files; f->name != NULL; ++f) {
253 0a04a7c0 2023-12-19 benni filler(data, f->name + 1, NULL, 0);
254 0a04a7c0 2023-12-19 benni }
255 0a04a7c0 2023-12-19 benni return 0;
256 0a04a7c0 2023-12-19 benni } else {
257 0a04a7c0 2023-12-19 benni for (const struct myfdfile *f = fd_files; f->name != NULL; ++f) {
258 0a04a7c0 2023-12-19 benni if (strcmp(suffix, f->name) == 0)
259 0a04a7c0 2023-12-19 benni return -ENOTDIR;
260 0a04a7c0 2023-12-19 benni }
261 0a04a7c0 2023-12-19 benni return -ENOENT;
262 0a04a7c0 2023-12-19 benni }
263 0a04a7c0 2023-12-19 benni } else {
264 0a04a7c0 2023-12-19 benni for (const struct myfile *f = files; f->name != NULL; ++f) {
265 0a04a7c0 2023-12-19 benni if (strcmp(suffix, f->name) == 0)
266 0a04a7c0 2023-12-19 benni return -ENOTDIR;
267 0a04a7c0 2023-12-19 benni }
268 0a04a7c0 2023-12-19 benni return -ENOENT;
269 0a04a7c0 2023-12-19 benni }
270 0a04a7c0 2023-12-19 benni } else {
271 0a04a7c0 2023-12-19 benni return -ENOENT;
272 0a04a7c0 2023-12-19 benni }
273 0a04a7c0 2023-12-19 benni }
274 0a04a7c0 2023-12-19 benni
275 0a04a7c0 2023-12-19 benni static int
276 0a04a7c0 2023-12-19 benni fs_read(
277 0a04a7c0 2023-12-19 benni const char *path,
278 0a04a7c0 2023-12-19 benni char *buf,
279 0a04a7c0 2023-12-19 benni size_t size,
280 0a04a7c0 2023-12-19 benni off_t off,
281 0a04a7c0 2023-12-19 benni struct fuse_file_info *ffi
282 0a04a7c0 2023-12-19 benni ) {
283 0a04a7c0 2023-12-19 benni int pid, num;
284 0a04a7c0 2023-12-19 benni
285 0a04a7c0 2023-12-19 benni (void)ffi;
286 0a04a7c0 2023-12-19 benni
287 0a04a7c0 2023-12-19 benni printf("read(%s);\n", path);
288 0a04a7c0 2023-12-19 benni
289 0a04a7c0 2023-12-19 benni if (strcmp(path, "/") == 0) {
290 0a04a7c0 2023-12-19 benni return -EISDIR;
291 0a04a7c0 2023-12-19 benni } else if (sscanf(path, "/%d%n", &pid, &num) == 1) {
292 0a04a7c0 2023-12-19 benni const char *suffix = path + num;
293 0a04a7c0 2023-12-19 benni struct kinfo_proc *kp;
294 0a04a7c0 2023-12-19 benni unsigned int idx;
295 0a04a7c0 2023-12-19 benni int nentries;
296 0a04a7c0 2023-12-19 benni
297 0a04a7c0 2023-12-19 benni kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof (*kp), &nentries);
298 0a04a7c0 2023-12-19 benni if (kp == NULL || nentries == 0) {
299 0a04a7c0 2023-12-19 benni warnx("read(%s): %s", path, kvm_geterr(kd));
300 0a04a7c0 2023-12-19 benni return -ENOENT;
301 0a04a7c0 2023-12-19 benni } else if (nentries > 1) {
302 0a04a7c0 2023-12-19 benni warnx("read(%s): Too many results", path);
303 0a04a7c0 2023-12-19 benni return -EIO;
304 0a04a7c0 2023-12-19 benni }
305 0a04a7c0 2023-12-19 benni
306 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "") == 0) {
307 0a04a7c0 2023-12-19 benni return -EISDIR;
308 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/argv") == 0) {
309 0a04a7c0 2023-12-19 benni return -EISDIR;
310 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/argv/%u%n", &idx, &num) == 1) {
311 0a04a7c0 2023-12-19 benni char **argv;
312 0a04a7c0 2023-12-19 benni
313 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
314 0a04a7c0 2023-12-19 benni return -ENOENT;
315 0a04a7c0 2023-12-19 benni
316 0a04a7c0 2023-12-19 benni argv = kvm_getargv(kd, kp, 0);
317 0a04a7c0 2023-12-19 benni if (argv == NULL) {
318 0a04a7c0 2023-12-19 benni warnx("read(%s): %s", path, kvm_geterr(kd));
319 0a04a7c0 2023-12-19 benni return -EIO;
320 0a04a7c0 2023-12-19 benni }
321 0a04a7c0 2023-12-19 benni
322 0a04a7c0 2023-12-19 benni for (nentries = 0; argv[nentries] != NULL; ++nentries);
323 0a04a7c0 2023-12-19 benni
324 0a04a7c0 2023-12-19 benni if (idx > (unsigned int)nentries)
325 0a04a7c0 2023-12-19 benni return -ENOENT;
326 0a04a7c0 2023-12-19 benni
327 0a04a7c0 2023-12-19 benni return copy_str(argv[idx], strlen(argv[idx]), buf, off, size);
328 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/envv") == 0) {
329 0a04a7c0 2023-12-19 benni return -EISDIR;
330 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/envv/%u%n", &idx, &num) == 1) {
331 0a04a7c0 2023-12-19 benni char **envv;
332 0a04a7c0 2023-12-19 benni
333 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
334 0a04a7c0 2023-12-19 benni return -ENOENT;
335 0a04a7c0 2023-12-19 benni
336 0a04a7c0 2023-12-19 benni envv = kvm_getenvv(kd, kp, 0);
337 0a04a7c0 2023-12-19 benni if (envv == NULL) {
338 0a04a7c0 2023-12-19 benni warnx("read(%s): %s", path, kvm_geterr(kd));
339 0a04a7c0 2023-12-19 benni return -EIO;
340 0a04a7c0 2023-12-19 benni }
341 0a04a7c0 2023-12-19 benni
342 0a04a7c0 2023-12-19 benni for (nentries = 0; envv[nentries] != NULL; ++nentries);
343 0a04a7c0 2023-12-19 benni
344 0a04a7c0 2023-12-19 benni if (idx > (unsigned int)nentries)
345 0a04a7c0 2023-12-19 benni return -ENOENT;
346 0a04a7c0 2023-12-19 benni
347 0a04a7c0 2023-12-19 benni return copy_str(envv[idx], strlen(envv[idx]), buf, off, size);
348 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/fd/%u%n", &idx, &num) == 1) {
349 0a04a7c0 2023-12-19 benni struct kinfo_file *files;
350 0a04a7c0 2023-12-19 benni
351 0a04a7c0 2023-12-19 benni suffix += num;
352 0a04a7c0 2023-12-19 benni files = kvm_getfiles(kd, KERN_FILE_BYPID, pid, sizeof (*files), &nentries);
353 0a04a7c0 2023-12-19 benni if (files == NULL) {
354 0a04a7c0 2023-12-19 benni warnx("read(%s): %s", path, kvm_geterr(kd));
355 0a04a7c0 2023-12-19 benni return -EIO;
356 0a04a7c0 2023-12-19 benni }
357 0a04a7c0 2023-12-19 benni
358 0a04a7c0 2023-12-19 benni if (idx >= (unsigned int)nentries)
359 0a04a7c0 2023-12-19 benni return -ENOENT;
360 0a04a7c0 2023-12-19 benni
361 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "") == 0) {
362 0a04a7c0 2023-12-19 benni return -EISDIR;
363 0a04a7c0 2023-12-19 benni } else {
364 0a04a7c0 2023-12-19 benni for (const struct myfdfile *f = fd_files; f->name != NULL; ++f) {
365 0a04a7c0 2023-12-19 benni if (strcmp(suffix, f->name) == 0)
366 0a04a7c0 2023-12-19 benni return f->read(&files[idx], buf, size, off);
367 0a04a7c0 2023-12-19 benni }
368 0a04a7c0 2023-12-19 benni return -ENOENT;
369 0a04a7c0 2023-12-19 benni }
370 0a04a7c0 2023-12-19 benni } else {
371 0a04a7c0 2023-12-19 benni for (const struct myfile *f = files; f->name != NULL; ++f) {
372 0a04a7c0 2023-12-19 benni if (strcmp(suffix, f->name) == 0)
373 0a04a7c0 2023-12-19 benni return f->read(kp, buf, size, off);
374 0a04a7c0 2023-12-19 benni }
375 0a04a7c0 2023-12-19 benni return -ENOENT;
376 0a04a7c0 2023-12-19 benni }
377 0a04a7c0 2023-12-19 benni } else {
378 0a04a7c0 2023-12-19 benni return -ENOENT;
379 0a04a7c0 2023-12-19 benni }
380 0a04a7c0 2023-12-19 benni }
381 0a04a7c0 2023-12-19 benni
382 0a04a7c0 2023-12-19 benni static int
383 0a04a7c0 2023-12-19 benni fs_open(const char *path, struct fuse_file_info *ffi)
384 0a04a7c0 2023-12-19 benni {
385 0a04a7c0 2023-12-19 benni int pid, num;
386 0a04a7c0 2023-12-19 benni
387 0a04a7c0 2023-12-19 benni (void)ffi;
388 0a04a7c0 2023-12-19 benni
389 0a04a7c0 2023-12-19 benni printf("open(%s);\n", path);
390 0a04a7c0 2023-12-19 benni
391 0a04a7c0 2023-12-19 benni if (strcmp(path, "/") == 0) {
392 0a04a7c0 2023-12-19 benni return 0;
393 0a04a7c0 2023-12-19 benni } else if (sscanf(path, "/%d%n", &pid, &num) == 1) {
394 0a04a7c0 2023-12-19 benni const char *suffix = path + num;
395 0a04a7c0 2023-12-19 benni struct kinfo_proc *kp;
396 0a04a7c0 2023-12-19 benni unsigned int idx;
397 0a04a7c0 2023-12-19 benni int nentries;
398 0a04a7c0 2023-12-19 benni bool found;
399 0a04a7c0 2023-12-19 benni
400 0a04a7c0 2023-12-19 benni kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof (*kp), &nentries);
401 0a04a7c0 2023-12-19 benni if (kp == NULL || nentries == 0) {
402 0a04a7c0 2023-12-19 benni warnx("open(%s): %s", path, kvm_geterr(kd));
403 0a04a7c0 2023-12-19 benni return -ENOENT;
404 0a04a7c0 2023-12-19 benni } else if (nentries > 1) {
405 0a04a7c0 2023-12-19 benni warnx("open(%s): Too many results", path);
406 0a04a7c0 2023-12-19 benni return -EIO;
407 0a04a7c0 2023-12-19 benni }
408 0a04a7c0 2023-12-19 benni
409 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "/argv") == 0) {
410 0a04a7c0 2023-12-19 benni return 0;
411 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/argv/%u%n", &idx, &num) == 1) {
412 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
413 0a04a7c0 2023-12-19 benni return -ENOENT;
414 0a04a7c0 2023-12-19 benni return 0;
415 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/envv") == 0) {
416 0a04a7c0 2023-12-19 benni return 0;
417 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/envv/%u%n", &idx, &num) == 1) {
418 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
419 0a04a7c0 2023-12-19 benni return -ENOENT;
420 0a04a7c0 2023-12-19 benni return 0;
421 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/fd/%u%n", &idx, &num) == 1) {
422 0a04a7c0 2023-12-19 benni suffix += num;
423 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "") == 0) {
424 0a04a7c0 2023-12-19 benni return 0;
425 0a04a7c0 2023-12-19 benni } else {
426 0a04a7c0 2023-12-19 benni found = false;
427 0a04a7c0 2023-12-19 benni for (const struct myfdfile *f = fd_files; f->name != NULL; ++f) {
428 0a04a7c0 2023-12-19 benni if (strcmp(suffix, f->name) == 0) {
429 0a04a7c0 2023-12-19 benni found = true;
430 0a04a7c0 2023-12-19 benni break;
431 0a04a7c0 2023-12-19 benni }
432 0a04a7c0 2023-12-19 benni }
433 0a04a7c0 2023-12-19 benni if (!found) {
434 0a04a7c0 2023-12-19 benni printf("Invalid fd suffix: '%s'\n", suffix);
435 0a04a7c0 2023-12-19 benni return -ENOENT;
436 0a04a7c0 2023-12-19 benni }
437 0a04a7c0 2023-12-19 benni return 0;
438 0a04a7c0 2023-12-19 benni }
439 0a04a7c0 2023-12-19 benni } else {
440 0a04a7c0 2023-12-19 benni found = false;
441 0a04a7c0 2023-12-19 benni for (const struct myfile *f = files; f->name != NULL; ++f) {
442 0a04a7c0 2023-12-19 benni if (strcmp(suffix, f->name) == 0) {
443 0a04a7c0 2023-12-19 benni found = true;
444 0a04a7c0 2023-12-19 benni break;
445 0a04a7c0 2023-12-19 benni }
446 0a04a7c0 2023-12-19 benni }
447 0a04a7c0 2023-12-19 benni if (!found) {
448 0a04a7c0 2023-12-19 benni printf("Invalid suffix: '%s'\n", suffix);
449 0a04a7c0 2023-12-19 benni return -ENOENT;
450 0a04a7c0 2023-12-19 benni }
451 0a04a7c0 2023-12-19 benni return 0;
452 0a04a7c0 2023-12-19 benni }
453 0a04a7c0 2023-12-19 benni } else {
454 0a04a7c0 2023-12-19 benni return -ENOENT;
455 0a04a7c0 2023-12-19 benni }
456 0a04a7c0 2023-12-19 benni }
457 0a04a7c0 2023-12-19 benni
458 0a04a7c0 2023-12-19 benni static int
459 0a04a7c0 2023-12-19 benni fs_getattr(const char *path, struct stat *st)
460 0a04a7c0 2023-12-19 benni {
461 0a04a7c0 2023-12-19 benni int pid, num;
462 0a04a7c0 2023-12-19 benni
463 0a04a7c0 2023-12-19 benni printf("getattr(%s);\n", path);
464 0a04a7c0 2023-12-19 benni
465 0a04a7c0 2023-12-19 benni st->st_blksize = 512;
466 0a04a7c0 2023-12-19 benni
467 0a04a7c0 2023-12-19 benni if (strcmp(path, "/") == 0) {
468 0a04a7c0 2023-12-19 benni st->st_mode = S_IFDIR | 0755;
469 0a04a7c0 2023-12-19 benni st->st_nlink = 2;
470 0a04a7c0 2023-12-19 benni st->st_size = 512;
471 0a04a7c0 2023-12-19 benni return 0;
472 0a04a7c0 2023-12-19 benni } else if (sscanf(path, "/%d%n", &pid, &num) == 1) {
473 0a04a7c0 2023-12-19 benni const char *suffix = path + num;
474 0a04a7c0 2023-12-19 benni struct kinfo_proc *kp;
475 0a04a7c0 2023-12-19 benni int nentries;
476 0a04a7c0 2023-12-19 benni unsigned int idx;
477 0a04a7c0 2023-12-19 benni
478 0a04a7c0 2023-12-19 benni kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof (*kp), &nentries);
479 0a04a7c0 2023-12-19 benni if (kp == NULL || nentries == 0) {
480 0a04a7c0 2023-12-19 benni warnx("getattr(%s): %s", path, kvm_geterr(kd));
481 0a04a7c0 2023-12-19 benni return -ENOENT;
482 0a04a7c0 2023-12-19 benni } else if (nentries > 1) {
483 0a04a7c0 2023-12-19 benni warnx("getattr(%s): Too many results", path);
484 0a04a7c0 2023-12-19 benni return -EIO;
485 0a04a7c0 2023-12-19 benni }
486 0a04a7c0 2023-12-19 benni
487 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "") == 0) {
488 0a04a7c0 2023-12-19 benni st->st_mode = S_IFDIR | 0755;
489 0a04a7c0 2023-12-19 benni st->st_nlink = 2;
490 0a04a7c0 2023-12-19 benni st->st_size = 512;
491 0a04a7c0 2023-12-19 benni return 0;
492 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/parent") == 0) {
493 0a04a7c0 2023-12-19 benni st->st_mode = S_IFLNK | 0755;
494 0a04a7c0 2023-12-19 benni st->st_nlink = 1;
495 0a04a7c0 2023-12-19 benni st->st_size = snprintf(NULL, 0, "%d", kp->p_ppid);
496 0a04a7c0 2023-12-19 benni return 0;
497 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/argv") == 0) {
498 0a04a7c0 2023-12-19 benni st->st_mode = S_IFDIR | 0755;
499 0a04a7c0 2023-12-19 benni st->st_nlink = 2;
500 0a04a7c0 2023-12-19 benni st->st_size = 512;
501 0a04a7c0 2023-12-19 benni return 0;
502 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/argv/%u%n", &idx, &num) == 1) {
503 0a04a7c0 2023-12-19 benni char **argv;
504 0a04a7c0 2023-12-19 benni
505 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
506 0a04a7c0 2023-12-19 benni return -ENOENT;
507 0a04a7c0 2023-12-19 benni
508 0a04a7c0 2023-12-19 benni argv = kvm_getargv(kd, kp, 0);
509 0a04a7c0 2023-12-19 benni if (argv == NULL) {
510 0a04a7c0 2023-12-19 benni warnx("getattr(%s): %s", path, kvm_geterr(kd));
511 0a04a7c0 2023-12-19 benni return -EIO;
512 0a04a7c0 2023-12-19 benni }
513 0a04a7c0 2023-12-19 benni
514 0a04a7c0 2023-12-19 benni for (nentries = 0; argv[nentries] != NULL; ++nentries);
515 0a04a7c0 2023-12-19 benni if (idx >= (unsigned int)nentries)
516 0a04a7c0 2023-12-19 benni return -ENOENT;
517 0a04a7c0 2023-12-19 benni
518 0a04a7c0 2023-12-19 benni st->st_mode = S_IFREG | 0644;
519 0a04a7c0 2023-12-19 benni st->st_nlink = 1;
520 0a04a7c0 2023-12-19 benni st->st_size = strlen(argv[idx]);
521 0a04a7c0 2023-12-19 benni return 0;
522 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/envv") == 0) {
523 0a04a7c0 2023-12-19 benni st->st_mode = S_IFDIR | 0755;
524 0a04a7c0 2023-12-19 benni st->st_nlink = 2;
525 0a04a7c0 2023-12-19 benni st->st_size = 512;
526 0a04a7c0 2023-12-19 benni return 0;
527 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/envv/%u%n", &idx, &num) == 1) {
528 0a04a7c0 2023-12-19 benni char **envv;
529 0a04a7c0 2023-12-19 benni
530 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
531 0a04a7c0 2023-12-19 benni return -ENOENT;
532 0a04a7c0 2023-12-19 benni
533 0a04a7c0 2023-12-19 benni envv = kvm_getenvv(kd, kp, 0);
534 0a04a7c0 2023-12-19 benni if (envv == NULL) {
535 0a04a7c0 2023-12-19 benni warnx("getattr(%s): %s", path, kvm_geterr(kd));
536 0a04a7c0 2023-12-19 benni return -EIO;
537 0a04a7c0 2023-12-19 benni }
538 0a04a7c0 2023-12-19 benni
539 0a04a7c0 2023-12-19 benni for (nentries = 0; envv[nentries] != NULL; ++nentries);
540 0a04a7c0 2023-12-19 benni if (idx >= (unsigned int)nentries)
541 0a04a7c0 2023-12-19 benni return -ENOENT;
542 0a04a7c0 2023-12-19 benni
543 0a04a7c0 2023-12-19 benni st->st_mode = S_IFREG | 0644;
544 0a04a7c0 2023-12-19 benni st->st_nlink = 1;
545 0a04a7c0 2023-12-19 benni st->st_size = strlen(envv[idx]);
546 0a04a7c0 2023-12-19 benni return 0;
547 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/fd") == 0) {
548 0a04a7c0 2023-12-19 benni st->st_mode = S_IFDIR | 0755;
549 0a04a7c0 2023-12-19 benni st->st_nlink = 2;
550 0a04a7c0 2023-12-19 benni st->st_size = 512;
551 0a04a7c0 2023-12-19 benni return 0;
552 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/fd/%u%n", &idx, &num) == 1) {
553 0a04a7c0 2023-12-19 benni struct kinfo_file *files;
554 0a04a7c0 2023-12-19 benni
555 0a04a7c0 2023-12-19 benni suffix += num;
556 0a04a7c0 2023-12-19 benni files = kvm_getfiles(kd, KERN_FILE_BYPID, pid, sizeof (*files), &nentries);
557 0a04a7c0 2023-12-19 benni if (files == NULL) {
558 0a04a7c0 2023-12-19 benni warnx("getattr(%s): %s", path, kvm_geterr(kd));
559 0a04a7c0 2023-12-19 benni return -EIO;
560 0a04a7c0 2023-12-19 benni }
561 0a04a7c0 2023-12-19 benni
562 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "") == 0) {
563 0a04a7c0 2023-12-19 benni st->st_mode = S_IFDIR | 0755;
564 0a04a7c0 2023-12-19 benni st->st_nlink = 2;
565 0a04a7c0 2023-12-19 benni st->st_size = 512;
566 0a04a7c0 2023-12-19 benni return 0;
567 0a04a7c0 2023-12-19 benni } else {
568 0a04a7c0 2023-12-19 benni for (const struct myfdfile *f = fd_files; f->name != NULL; ++f) {
569 0a04a7c0 2023-12-19 benni if (strcmp(suffix, f->name) == 0) {
570 0a04a7c0 2023-12-19 benni st->st_mode = S_IFREG | 0644;
571 0a04a7c0 2023-12-19 benni st->st_nlink = 1;
572 0a04a7c0 2023-12-19 benni st->st_size = 0;
573 0a04a7c0 2023-12-19 benni return 0;
574 0a04a7c0 2023-12-19 benni }
575 0a04a7c0 2023-12-19 benni }
576 0a04a7c0 2023-12-19 benni return -ENOENT;
577 0a04a7c0 2023-12-19 benni }
578 0a04a7c0 2023-12-19 benni } else {
579 0a04a7c0 2023-12-19 benni for (const struct myfile *f = files; f->name != NULL; ++f) {
580 0a04a7c0 2023-12-19 benni if (strcmp(suffix, f->name) == 0) {
581 0a04a7c0 2023-12-19 benni st->st_mode = S_IFREG;
582 0a04a7c0 2023-12-19 benni st->st_nlink = 1;
583 0a04a7c0 2023-12-19 benni st->st_size = 0;
584 0a04a7c0 2023-12-19 benni return 0;
585 0a04a7c0 2023-12-19 benni }
586 0a04a7c0 2023-12-19 benni }
587 0a04a7c0 2023-12-19 benni return -ENOENT;
588 0a04a7c0 2023-12-19 benni }
589 0a04a7c0 2023-12-19 benni } else {
590 0a04a7c0 2023-12-19 benni return -ENOENT;
591 0a04a7c0 2023-12-19 benni }
592 0a04a7c0 2023-12-19 benni }
593 0a04a7c0 2023-12-19 benni
594 0a04a7c0 2023-12-19 benni static int
595 0a04a7c0 2023-12-19 benni fs_readlink(const char *path, char *buf, size_t size)
596 0a04a7c0 2023-12-19 benni {
597 0a04a7c0 2023-12-19 benni int pid, num;
598 0a04a7c0 2023-12-19 benni
599 0a04a7c0 2023-12-19 benni if (sscanf(path, "/%d%n", &pid, &num) == 1) {
600 0a04a7c0 2023-12-19 benni const char *suffix = path + num;
601 0a04a7c0 2023-12-19 benni struct kinfo_proc *kp;
602 0a04a7c0 2023-12-19 benni int nentries;
603 0a04a7c0 2023-12-19 benni
604 0a04a7c0 2023-12-19 benni kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof (*kp), &nentries);
605 0a04a7c0 2023-12-19 benni if (kp == NULL || nentries == 0) {
606 0a04a7c0 2023-12-19 benni warnx("readlink(%s): %s", path, kvm_geterr(kd));
607 0a04a7c0 2023-12-19 benni return -ENOENT;
608 0a04a7c0 2023-12-19 benni } else if (nentries > 1) {
609 0a04a7c0 2023-12-19 benni warnx("readlink(%s): Too many results", path);
610 0a04a7c0 2023-12-19 benni return -EIO;
611 0a04a7c0 2023-12-19 benni }
612 0a04a7c0 2023-12-19 benni
613 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "/parent") == 0) {
614 0a04a7c0 2023-12-19 benni snprintf(buf, size, "../%d", kp->p_ppid);
615 0a04a7c0 2023-12-19 benni return 0;
616 0a04a7c0 2023-12-19 benni } else {
617 0a04a7c0 2023-12-19 benni return -EINVAL;
618 0a04a7c0 2023-12-19 benni }
619 0a04a7c0 2023-12-19 benni } else {
620 0a04a7c0 2023-12-19 benni return -ENOENT;
621 0a04a7c0 2023-12-19 benni }
622 0a04a7c0 2023-12-19 benni }
623 0a04a7c0 2023-12-19 benni
624 0a04a7c0 2023-12-19 benni struct fuse_operations fsops = {
625 0a04a7c0 2023-12-19 benni .readdir = fs_readdir,
626 0a04a7c0 2023-12-19 benni .read = fs_read,
627 0a04a7c0 2023-12-19 benni .open = fs_open,
628 0a04a7c0 2023-12-19 benni .getattr = fs_getattr,
629 0a04a7c0 2023-12-19 benni .readlink = fs_readlink,
630 0a04a7c0 2023-12-19 benni };
631 0a04a7c0 2023-12-19 benni
632 0a04a7c0 2023-12-19 benni int
633 0a04a7c0 2023-12-19 benni main(int argc, char **argv)
634 0a04a7c0 2023-12-19 benni {
635 0a04a7c0 2023-12-19 benni char errbuf[_POSIX2_LINE_MAX];
636 0a04a7c0 2023-12-19 benni kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
637 0a04a7c0 2023-12-19 benni if (kd == NULL)
638 0a04a7c0 2023-12-19 benni errx(1, "%s", errbuf);
639 0a04a7c0 2023-12-19 benni
640 0a04a7c0 2023-12-19 benni return (fuse_main(argc, argv, &fsops, NULL));
641 0a04a7c0 2023-12-19 benni }