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>
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>
19 0a04a7c0 2023-12-19 benni // TODO: envv: not idx, but envar name
21 0a04a7c0 2023-12-19 benni #define MY_KERN_PROC KERN_PROC_KTHREAD
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);
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);
33 0a04a7c0 2023-12-19 benni #include "files.h"
35 0a04a7c0 2023-12-19 benni enum path_type {
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,
48 0a04a7c0 2023-12-19 benni struct path {
49 0a04a7c0 2023-12-19 benni enum path_type type;
53 0a04a7c0 2023-12-19 benni const char *file;
57 0a04a7c0 2023-12-19 benni parse_path(const char *path, struct path *p)
59 0a04a7c0 2023-12-19 benni const char *suffix;
62 0a04a7c0 2023-12-19 benni memset(p, 0, sizeof (*p));
64 0a04a7c0 2023-12-19 benni if (strcmp(path, "/") == 0) {
65 0a04a7c0 2023-12-19 benni p->type = PATH_ROOT;
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;
70 0a04a7c0 2023-12-19 benni if (*suffix == '\0') {
71 0a04a7c0 2023-12-19 benni p->type = PATH_PID;
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;
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;
82 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
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;
94 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
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;
107 0a04a7c0 2023-12-19 benni return -ENOENT;
110 0a04a7c0 2023-12-19 benni return -ENOENT;
114 0a04a7c0 2023-12-19 benni return -ENOENT;
117 0a04a7c0 2023-12-19 benni return -ENOENT;
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)
125 0a04a7c0 2023-12-19 benni int pid, num;
127 0a04a7c0 2023-12-19 benni (void)ffi;
129 0a04a7c0 2023-12-19 benni printf("readdir(%s, off=%u);\n", path, (unsigned int)off);
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;
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;
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);
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;
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;
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);
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);
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;
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];
188 0a04a7c0 2023-12-19 benni n = snprintf(buffer, sizeof (buffer), "%zu", i);
189 0a04a7c0 2023-12-19 benni assert(n < (int)sizeof (buffer));
191 0a04a7c0 2023-12-19 benni filler(data, buffer, NULL, 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);
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;
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];
208 0a04a7c0 2023-12-19 benni n = snprintf(buffer, sizeof (buffer), "%zu", i);
209 0a04a7c0 2023-12-19 benni assert(n < (int)sizeof (buffer));
211 0a04a7c0 2023-12-19 benni filler(data, buffer, NULL, 0);
214 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/fd") == 0) {
215 0a04a7c0 2023-12-19 benni struct kinfo_file *files;
217 0a04a7c0 2023-12-19 benni files = kvm_getfiles (kd, KERN_FILE_BYPID, pid, sizeof (*files), &nentries);
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;
224 0a04a7c0 2023-12-19 benni filler(data, ".", NULL, 0);
225 0a04a7c0 2023-12-19 benni filler(data, "..", NULL, 0);
227 0a04a7c0 2023-12-19 benni printf("nentries = %d\n", nentries);
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);
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;
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;
246 0a04a7c0 2023-12-19 benni if (idx >= (unsigned int)nentries)
247 0a04a7c0 2023-12-19 benni return -ENOENT;
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);
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;
261 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
268 0a04a7c0 2023-12-19 benni return -ENOENT;
271 0a04a7c0 2023-12-19 benni return -ENOENT;
275 0a04a7c0 2023-12-19 benni static int
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
283 0a04a7c0 2023-12-19 benni int pid, num;
285 0a04a7c0 2023-12-19 benni (void)ffi;
287 0a04a7c0 2023-12-19 benni printf("read(%s);\n", path);
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;
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;
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;
313 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
314 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
322 0a04a7c0 2023-12-19 benni for (nentries = 0; argv[nentries] != NULL; ++nentries);
324 0a04a7c0 2023-12-19 benni if (idx > (unsigned int)nentries)
325 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
333 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
334 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
342 0a04a7c0 2023-12-19 benni for (nentries = 0; envv[nentries] != NULL; ++nentries);
344 0a04a7c0 2023-12-19 benni if (idx > (unsigned int)nentries)
345 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
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;
358 0a04a7c0 2023-12-19 benni if (idx >= (unsigned int)nentries)
359 0a04a7c0 2023-12-19 benni return -ENOENT;
361 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "") == 0) {
362 0a04a7c0 2023-12-19 benni return -EISDIR;
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);
368 0a04a7c0 2023-12-19 benni return -ENOENT;
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);
375 0a04a7c0 2023-12-19 benni return -ENOENT;
378 0a04a7c0 2023-12-19 benni return -ENOENT;
382 0a04a7c0 2023-12-19 benni static int
383 0a04a7c0 2023-12-19 benni fs_open(const char *path, struct fuse_file_info *ffi)
385 0a04a7c0 2023-12-19 benni int pid, num;
387 0a04a7c0 2023-12-19 benni (void)ffi;
389 0a04a7c0 2023-12-19 benni printf("open(%s);\n", path);
391 0a04a7c0 2023-12-19 benni if (strcmp(path, "/") == 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;
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;
409 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "/argv") == 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;
415 0a04a7c0 2023-12-19 benni } else if (strcmp(suffix, "/envv") == 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;
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) {
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;
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;
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;
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;
454 0a04a7c0 2023-12-19 benni return -ENOENT;
458 0a04a7c0 2023-12-19 benni static int
459 0a04a7c0 2023-12-19 benni fs_getattr(const char *path, struct stat *st)
461 0a04a7c0 2023-12-19 benni int pid, num;
463 0a04a7c0 2023-12-19 benni printf("getattr(%s);\n", path);
465 0a04a7c0 2023-12-19 benni st->st_blksize = 512;
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;
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;
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;
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;
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);
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;
502 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/argv/%u%n", &idx, &num) == 1) {
503 0a04a7c0 2023-12-19 benni char **argv;
505 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
506 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
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;
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]);
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;
527 0a04a7c0 2023-12-19 benni } else if (sscanf(suffix, "/envv/%u%n", &idx, &num) == 1) {
528 0a04a7c0 2023-12-19 benni char **envv;
530 0a04a7c0 2023-12-19 benni if (suffix[num] != '\0')
531 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
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;
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]);
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;
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;
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;
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;
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;
576 0a04a7c0 2023-12-19 benni return -ENOENT;
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;
587 0a04a7c0 2023-12-19 benni return -ENOENT;
590 0a04a7c0 2023-12-19 benni return -ENOENT;
594 0a04a7c0 2023-12-19 benni static int
595 0a04a7c0 2023-12-19 benni fs_readlink(const char *path, char *buf, size_t size)
597 0a04a7c0 2023-12-19 benni int pid, num;
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;
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;
613 0a04a7c0 2023-12-19 benni if (strcmp(suffix, "/parent") == 0) {
614 0a04a7c0 2023-12-19 benni snprintf(buf, size, "../%d", kp->p_ppid);
617 0a04a7c0 2023-12-19 benni return -EINVAL;
620 0a04a7c0 2023-12-19 benni return -ENOENT;
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,
633 0a04a7c0 2023-12-19 benni main(int argc, char **argv)
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);
640 0a04a7c0 2023-12-19 benni return (fuse_main(argc, argv, &fsops, NULL));