Mercurial > minori
view dep/animia/src/fd/kvm.cc @ 187:9613d72b097e
*: multiple performance improvements
like marking `static const` when it makes sense...
date: change old stupid heap-based method to a structure which should
make copying the thing actually make a copy.
also many performance-based changes, like removing the std::tie
dependency and forward-declaring nlohmann json
*: replace every instance of QString::fromUtf8 to Strings::ToQString.
the main difference is that our function will always convert exactly
what is in the string, while some other times it would only convert
up to the nearest NUL byte
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Wed, 06 Dec 2023 13:43:54 -0500 |
parents | e44b7c428d7c |
children | 8f6f8dd2eb23 |
line wrap: on
line source
/* kvm.cc: provides support for libkvm in multiple BSDs ** ** this is really the only way to get a thing that works on ** OpenBSD AND NetBSD. ** ** Much of this file is taken from the fstat source code in ** NetBSD. */ #include <kvm.h> namespace animia::internal::kvm { static bool GetFilename(kvm_t* kvm, struct vnode *vp, std::string& name) { struct vnode vn; if (!kvm_read(kvm, vp, &vn, sizeof(*vn))) return 0; struct filestat fst; const char* type = vfilestat(vn, &fst); if (type == dead) return false; for (DEVS* d = devs; d != NULL; d = d->next) { if (d->fsid == fst->fsid && d->ino == fst->fileid) { name = d->name; break; } } return true; } static bool GetFilePath(kvm_t* kvm, fdfile_t* fp, std::string& path) { struct file file; fdfile_t fdfile; if (!kvm_read(kvm, fp, &fdfile, sizeof(fdfile))) return false; if (!fdfile.ff_file) return false; if (!kvm_read(fdfile.ff_file, &file, sizeof(file))) return false; if (file.f_type != DTYPE_VNODE) return false; return GetFilename(kvm, file.f_data, path); } static bool OpenFiles(kvm_t* kvm, struct kinfo_proc* p, open_file_proc_t open_file_proc) { if (p->proc->p_fd == 0 || p->proc->p_cwdi == 0) return false; struct filedesc filed; if (!kvm_read(kvm, p->proc->p_fd, &filed, sizeof(filed))) return false; if (filed.fd_lastfile == -1) return false; struct cwdinfo cwdi; if (!kvm_read(kvm, p->proc->p_cwdi, &cwdi, sizeof(cwdi))) return false; struct fdtab dt; if (!kvm_read(kvm, filed.fd_dt, &dt, sizeof(dt))) return false; /* check for corrupted files? */ if ((unsigned)filed.fd_lastfile >= dt.dt_nfiles || filed.fd_freefile > filed.fd_lastfile + 1) return false; /* open files */ std::unique_ptr<fdfile_t*[]> ofiles = nullptr; { ofiles.reset(malloc((filed.fd_lastfile + 1) * sizeof(fdfile_t*))); if (!ofiles.get()) return false; } if (!kvm_read(kvm, &filed.fd_dt->dt_ff, ofiles.get(), filed.fd_lastfile + 1 * (sizeof(fdfile_t*)))) return false; for (int i = 0; i <= filed.fd_lastfile; i++) { if (!ofiles[i]) continue; std::string name; GetFilePath(kvm, ofiles[i], name); if (!open_file_proc(p->proc->p_pid, name)) return false; } return true; } bool EnumerateOpenProcesses(process_proc_t process_proc) { char errbuf[_POSIX2_LINE_MAX]; kvm_t* kernel = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); if (!kernel) return false; int entries = 0; struct kinfo_proc* kinfo = kvm_getprocs(kernel, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &nentries); if (!kinfo) return false; for (int i = 0; i < entries; i++) if (!process_proc({kinfo[i].p_pid, kinfo[i].p_comm})) return false; return true; } bool EnumerateOpenFiles(std::set<pid_t>& pids, open_file_proc_t open_file_proc) { kvm_t* kernel = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); if (!kernel) return false; for (const auto& pid : pids) { int cnt; struct kinfo_proc* kinfo = kvm_getprocs(kernel, KERN_PROC_PID, pid, &cnt); if (!kinfo) return false; for (int i = 0; i < cnt; i++) { OpenFiles(kernel, kinfo, open_file_proc); } } } }