comparison dep/animone/src/fd/openbsd.cc @ 338:f63dfa309380

dep/animone: separate *BSD into separate files they are wholly different operating systems with very different kernels on the inside
author Paper <paper@paper.us.eu.org>
date Wed, 19 Jun 2024 13:06:10 -0400
parents
children
comparison
equal deleted inserted replaced
337:a7d4e5107531 338:f63dfa309380
1 /*
2 * fd/openbsd.cc: support for OpenBSD
3 *
4 * COMPLETELY UNTESTED. may or may not work.
5 */
6 #include "animone/fd/bsd.h"
7 #include "animone.h"
8 #include "animone/fd.h"
9
10 #include <sys/file.h>
11 #include <sys/filedesc.h>
12 #include <sys/param.h>
13 #include <sys/queue.h>
14 #include <sys/sysctl.h>
15 #include <sys/types.h>
16 #include <sys/user.h>
17 #include <sys/vnode.h>
18
19 #include <kvm.h>
20 #include <fts.h>
21
22 #include <string>
23
24 namespace animone::internal::openbsd {
25
26 /* XXX is this necessary */
27 static std::string Basename(const std::string& name) {
28 size_t s = name.find_last_of('/');
29
30 if (s == std::string::npos)
31 return name;
32
33 return name.substr(s, name.size());
34 }
35
36 bool GetProcessName(pid_t pid, std::string& name) {
37 char errbuf[_POSIX2_LINE_MAX];
38 kvm_t* kernel = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
39 if (!kernel)
40 return false;
41
42 int entries = 0;
43 struct kinfo_proc* kinfo = kvm_getprocs(kernel, KERN_PROC_PID, pid, &entries);
44 if (!kinfo) {
45 kvm_close(kernel);
46 return false;
47 }
48
49 if (entries < 1) {
50 kvm_close(kernel);
51 return false;
52 }
53
54 name = Basename(kinfo[0].ki_paddr->p_comm);
55
56 return true;
57 }
58
59 bool EnumerateOpenProcesses(process_proc_t process_proc) {
60 char errbuf[_POSIX2_LINE_MAX];
61 kvm_t* kernel = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
62 if (!kernel)
63 return false;
64
65 int entries = 0;
66 struct kinfo_proc* kinfo = kvm_getprocs(kernel, KERN_PROC_ALL, 0, &entries);
67 if (!kinfo) {
68 kvm_close(kernel);
69 return false;
70 }
71
72 for (int i = 0; i < entries; i++) {
73 if (!process_proc({.platform = ExecutablePlatform::Posix, .pid = kinfo[i].ki_paddr->p_pid, .comm = Basename(kinfo[i].ki_paddr->p_comm)})) {
74 kvm_close(kernel);
75 return false;
76 }
77 }
78
79 kvm_close(kernel);
80
81 return true;
82 }
83
84 static bool GetOpenFileName(const struct kinfo_file& file, std::string& name) {
85 /* OpenBSD doesn't provide a native API for this, so we have
86 * to do it ourselves */
87 static constexpr std::string_view root = "/";
88
89 FTS* file_system = fts_open(root.data(), FTS_COMFOLLOW | FTS_NOCHDIR, nullptr);
90 if (!file_system)
91 return false;
92
93 /* Search through the filesystem for a file that matches our
94 * kinfo_file structure */
95 FTSENT* parent = nullptr;
96 while ((parent = fts_read(file_system))) {
97 FTSENT* child = fts_children(file_system, 0);
98 while (child && child->fts_link) {
99 child = child->fts_link;
100 if (!S_ISREG(child->fts_statp->st_mode) || !S_ISLNK(child->fts_statp->st_mode))
101 continue;
102
103 if (child->fts_statp->st_dev != file->va_fsid)
104 continue;
105
106 if (child->fts_statp->st_ino != file->va_fileid)
107 continue;
108
109 name = std::string(child->fts_path) + child->fts_name;
110 fts_close(file_system);
111 return true;
112 }
113 }
114
115 fts_close(filesystem);
116 return false;
117 }
118
119 bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) {
120 char errbuf[_POSIX2_LINE_MAX];
121 kvm_t* kernel = kvm_openfiles(nullptr, nullptr, nullptr, O_RDONLY, errbuf);
122 if (!kernel)
123 return false;
124
125 for (const auto& pid : pids) {
126 int cnt;
127 struct kinfo_file* kfile = kvm_getfiles(kernel, KERN_FILE_BYPID, pid, &cnt);
128 if (!kfile) {
129 kvm_close(kernel);
130 return false;
131 }
132
133 for (int i = 0; i < cnt; i++) {
134 uint32_t oflags = kfile[i].kf_flags & O_ACCMODE;
135 if (oflags == O_WRONLY || oflags == O_RDWR)
136 continue;
137
138 std::string name;
139 if (!GetOpenFileName(kfile[i], name))
140 continue;
141
142 if (!open_file_proc({pid, name})) {
143 kvm_close(kernel);
144 return false;
145 }
146 }
147 }
148
149 kvm_close(kernel);
150 return true;
151 }
152
153 } // namespace animone::internal::openbsd