Mercurial > minori
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 |