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 |
