Mercurial > minori
comparison dep/animone/src/fd/bsd.cc @ 270:0718f538c5f9
dep/animone: filter open files by access mode
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Fri, 12 Apr 2024 19:13:50 -0400 |
parents | 1a6a5d3a94cd |
children | 65df2813d0de |
comparison
equal
deleted
inserted
replaced
269:3efac0541151 | 270:0718f538c5f9 |
---|---|
11 #include <sys/user.h> | 11 #include <sys/user.h> |
12 #include <sys/vnode.h> | 12 #include <sys/vnode.h> |
13 | 13 |
14 #ifdef HAVE_KVM_GETFILES | 14 #ifdef HAVE_KVM_GETFILES |
15 # include <kvm.h> | 15 # include <kvm.h> |
16 # include <fts.h> | |
16 #elif defined(LIBUTIL) | 17 #elif defined(LIBUTIL) |
17 # include <libutil.h> | 18 # include <libutil.h> |
18 #endif | 19 #endif |
19 | 20 |
20 #include <string> | 21 #include <string> |
108 | 109 |
109 if (!result.get()) | 110 if (!result.get()) |
110 return false; | 111 return false; |
111 | 112 |
112 /* actually get our results */ | 113 /* actually get our results */ |
113 if (sysctl((const int*)mib, (sizeof(mib) / sizeof(*mib)) - 1, result.get(), &length, NULL, 0) == ENOMEM) { | 114 if (sysctl((const int*)mib, (sizeof(mib) / sizeof(*mib)) - 1, result.get(), &length, NULL, 0) == ENOMEM) |
114 result.reset(); | 115 return false; |
115 throw std::bad_alloc(); | |
116 } | |
117 | 116 |
118 if (length < sizeof(struct kinfo_proc)) | 117 if (length < sizeof(struct kinfo_proc)) |
119 return false; | 118 return false; |
120 | 119 |
121 for (int i = 0; i < length / sizeof(result[0]); i++) | 120 for (int i = 0; i < length / sizeof(result[0]); i++) |
124 | 123 |
125 return true; | 124 return true; |
126 #endif | 125 #endif |
127 } | 126 } |
128 | 127 |
128 #ifdef HAVE_KVM_GETFILES | |
129 static bool GetOpenFileName(const struct kinfo_file& file, std::string& name) { | |
130 /* OpenBSD doesn't provide a native API for this, so we have | |
131 * to do it ourselves */ | |
132 static constexpr std::string_view root = "/"; | |
133 | |
134 FTS* file_system = fts_open(root.data(), FTS_COMFOLLOW | FTS_NOCHDIR, nullptr); | |
135 if (!file_system) | |
136 return false; | |
137 | |
138 /* Search through the filesystem for a file that matches our | |
139 * kinfo_file structure */ | |
140 FTSENT* parent = nullptr; | |
141 while ((parent = fts_read(file_system))) { | |
142 FTSENT* child = fts_children(file_system, 0); | |
143 while (child && child->fts_link) { | |
144 child = child->fts_link; | |
145 if (!S_ISREG(child->fts_statp->st_mode) || !S_ISLNK(child->fts_statp->st_mode)) | |
146 continue; | |
147 | |
148 if (child->fts_statp->st_dev != file->va_fsid) | |
149 continue; | |
150 | |
151 if (child->fts_statp->st_ino != file->va_fileid) | |
152 continue; | |
153 | |
154 name = std::string(child->fts_path) + child->fts_name; | |
155 fts_close(file_system); | |
156 return true; | |
157 } | |
158 } | |
159 | |
160 fts_close(filesystem); | |
161 return false; | |
162 } | |
163 #endif /* HAVE_KVM_GETFILES */ | |
164 | |
129 bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { | 165 bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { |
130 #ifdef HAVE_KVM_GETFILES | 166 #ifdef HAVE_KVM_GETFILES |
131 char errbuf[_POSIX2_LINE_MAX]; | 167 char errbuf[_POSIX2_LINE_MAX]; |
132 kvm_t* kernel = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); | 168 kvm_t* kernel = kvm_openfiles(nullptr, nullptr, nullptr, O_RDONLY, errbuf); |
133 if (!kernel) | 169 if (!kernel) |
134 return false; | 170 return false; |
135 | 171 |
136 for (const auto& pid : pids) { | 172 for (const auto& pid : pids) { |
137 int cnt; | 173 int cnt; |
140 kvm_close(kernel); | 176 kvm_close(kernel); |
141 return false; | 177 return false; |
142 } | 178 } |
143 | 179 |
144 for (int i = 0; i < cnt; i++) { | 180 for (int i = 0; i < cnt; i++) { |
145 if (!open_file_proc({pid, kfile[i].kf_path})) { | 181 uint32_t oflags = kfile[i].kf_flags & O_ACCMODE; |
182 if (oflags == O_WRONLY || oflags == O_RDWR) | |
183 continue; | |
184 | |
185 std::string name; | |
186 if (!GetOpenFileName(kfile[i], name)) | |
187 continue; | |
188 | |
189 if (!open_file_proc({pid, name})) { | |
146 kvm_close(kernel); | 190 kvm_close(kernel); |
147 return false; | 191 return false; |
148 } | 192 } |
149 } | 193 } |
150 } | 194 } |
151 | 195 |
152 kvm_close(kernel); | 196 kvm_close(kernel); |
153 | |
154 return true; | 197 return true; |
155 #elif defined(LIBUTIL) | 198 #elif defined(LIBUTIL) |
156 /* does this code even work? */ | |
157 for (const auto& pid : pids) { | 199 for (const auto& pid : pids) { |
158 int cnt; | 200 int cnt; |
159 std::unique_ptr<struct kinfo_file[]> files(kinfo_getfile(pid, &cnt)); | 201 std::unique_ptr<struct kinfo_file[]> files(kinfo_getfile(pid, &cnt)); |
160 if (!files) | 202 if (!files) |
161 return false; | 203 return false; |
162 | 204 |
163 for (int i = 0; i < cnt; i++) { | 205 for (int i = 0; i < cnt; i++) { |
164 const struct kinfo_file& current = files[i]; | 206 const struct kinfo_file& current = files[i]; |
165 if (current.kf_vnode_type != KF_VTYPE_VREG) | 207 if (current.kf_vnode_type != KF_VTYPE_VREG || current.kf_vnode_type != KF_VTYPE_VLNK) |
208 continue; | |
209 | |
210 const int oflags = current.kf_flags & O_ACCMODE; | |
211 if (oflags == O_WRONLY || oflags == O_RDWR) | |
166 continue; | 212 continue; |
167 | 213 |
168 if (!open_file_proc({pid, current.kf_path})) | 214 if (!open_file_proc({pid, current.kf_path})) |
169 return false; | 215 return false; |
170 } | 216 } |
171 } | 217 } |
172 | 218 |
173 return true; | 219 return true; |
174 #else | 220 #else |
175 for (const auto& pid : pids) { | 221 /* NetBSD doesn't even provide a real API for this */ |
176 int mib[6] = {CTL_KERN, KERN_FILE2, KERN_FILE_BYPID, pid, sizeof(struct kinfo_file), 0}; | 222 return false; |
177 | |
178 size_t len = 0; | |
179 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &len, NULL, 0) == -1) | |
180 return false; | |
181 | |
182 mib[5] = len / sizeof(struct kinfo_file); | |
183 | |
184 std::unique_ptr<struct kinfo_file[]> buf(new struct kinfo_file[mib[5]]); | |
185 if (!buf) | |
186 return false; | |
187 | |
188 if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf.get(), &len, NULL, 0) == -1) | |
189 return false; | |
190 | |
191 /* TODO: check kfile[i].ki_ofileflags */ | |
192 for (size_t i = 0; i < mib[5]; i++) | |
193 if (!open_file_proc({pid, kfile[i].kf_path})) | |
194 return false; | |
195 } | |
196 | |
197 return true; | |
198 #endif | 223 #endif |
199 } | 224 } |
200 | 225 |
201 } // namespace animone::internal::kvm | 226 } // namespace animone::internal::kvm |