diff dep/animia/src/fd/kvm.cc @ 212:6b08fbd7f206

chore: merge branches
author Paper <mrpapersonic@gmail.com>
date Sun, 07 Jan 2024 09:54:50 -0500
parents 71832ffe425a
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dep/animia/src/fd/kvm.cc	Sun Jan 07 09:54:50 2024 -0500
@@ -0,0 +1,103 @@
+/* kvm.cc: provides support for OpenBSD's libkvm
+**
+** Theoretically, this code *should* work, but I haven't
+** even tested it.
+**
+** This also contains some code to support NetBSD, although
+** it calls the kernel instead of kvm.
+*/
+
+#include "animia/fd/kvm.h"
+#include "animia/fd.h"
+#include "animia.h"
+
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/param.h>
+#include <sys/vnode.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include <kvm.h>
+
+#include <string>
+
+namespace animia::internal::kvm {
+
+bool EnumerateOpenProcesses(process_proc_t process_proc) {
+	char errbuf[_POSIX2_LINE_MAX];
+	kvm_t* kernel = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+	if (!kernel)
+		return false;
+
+	int entries = 0;
+	struct kinfo_proc* kinfo = kvm_getprocs(kernel, KERN_PROC_ALL, 0, &entries);
+	if (!kinfo)
+		return false;
+
+	for (int i = 0; i < entries; i++)
+		if (!process_proc({kinfo[i].ki_paddr->p_pid, kinfo[i].ki_paddr->p_comm}))
+			return false;
+
+	kvm_close(kernel);
+
+	return true;
+}
+
+bool EnumerateOpenFiles(std::set<pid_t>& pids, open_file_proc_t open_file_proc) {
+#ifdef HAVE_KVM_GETFILES
+	char errbuf[_POSIX2_LINE_MAX];
+	kvm_t* kernel = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+	if (!kernel)
+		return false;
+
+	for (const auto& pid : pids) {
+		int cnt;
+		struct kinfo_file* kfile = kvm_getfiles(kernel, KERN_FILE_BYPID, pid, &cnt);
+		if (!kfile)
+			return false;
+
+		for (int i = 0; i < cnt; i++)
+			if (!open_file_proc({pid, kfile[i].kf_path}))
+				return false;
+	}
+
+	kvm_close(kernel);
+
+	return true;
+#else /* For NetBSD... I think */
+	for (const auto& pid : pids) {
+		int mib[6] = {
+			CTL_KERN,
+			KERN_FILE2,
+			KERN_FILE_BYPID,
+			pid,
+			sizeof(struct kinfo_file),
+			0
+		};
+
+		size_t len = 0;
+		if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), NULL, &len, NULL, 0) == -1)
+			return false;
+
+		mib[5] = len / sizeof(struct kinfo_file);
+
+		std::unique_ptr<struct kinfo_file[]> buf(new struct kinfo_file[mib[5]]);
+		if (!buf)
+			return false;
+
+		if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), buf.get(), &len, NULL, 0) == -1)
+			return false;
+
+		for (size_t i = 0; i < cnt; i++)
+			if (!open_file_proc({pid, kfile[i].kf_path}))
+				return false;
+	}
+
+	return true;
+#endif
+}
+
+}