diff dep/animone/src/fd/kvm.cc @ 258:862d0d8619f6

*: HUUUGE changes animia has been renamed to animone, so instead of thinking of a health condition, you think of a beautiful flower :) I've also edited some of the code for animone, but I have no idea if it even works or not because I don't have a mac or windows machine lying around. whoops! ... anyway, all of the changes divergent from Anisthesia are now licensed under BSD. it's possible that I could even rewrite most of the code to where I don't even have to keep the MIT license, but that's thinking too far into the future I've been slacking off on implementing the anime seasons page, mostly out of laziness. I think I'd have to create another db file specifically for the seasons anyway, this code is being pushed *primarily* because the hard drive it's on is failing! yay :)
author Paper <paper@paper.us.eu.org>
date Mon, 01 Apr 2024 02:43:44 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dep/animone/src/fd/kvm.cc	Mon Apr 01 02:43:44 2024 -0400
@@ -0,0 +1,151 @@
+/* kvm.cc: provides support for *BSD.
+ */
+
+#include "animone/fd/kvm.h"
+#include "animone.h"
+#include "animone/fd.h"
+
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <sys/vnode.h>
+
+#include <kvm.h>
+#ifdef LIBUTIL
+#	include <libutil.h>
+#endif
+
+#include <string>
+
+namespace animone::internal::kvm {
+
+bool GetProcessName(pid_t pid, std::string& name) {
+	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_PID, pid, &entries);
+	if (!kinfo) {
+		kvm_close(kernel);
+		return false;
+	}
+
+	if (entries < 1) {
+		kvm_close(kernel);
+		return false;
+	}
+
+	name = kinfo[0].ki_paddr->p_comm;
+
+	return true;
+}
+
+/* Most of the BSDs share the common kvm library,
+ * so accessing this information can be trivial.
+ */
+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) {
+		kvm_close(kernel);
+		return false;
+	}
+
+	for (int i = 0; i < entries; i++) {
+		if (!process_proc({kinfo[i].ki_paddr->p_pid, kinfo[i].ki_paddr->p_comm})) {
+			kvm_close(kernel);
+			return false;
+		}
+	}
+
+	kvm_close(kernel);
+
+	return true;
+}
+
+bool EnumerateOpenFiles(std::set<pid_t>& pids, open_file_proc_t open_file_proc) {
+#ifdef __OpenBSD__
+	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) {
+			kvm_close(kernel);
+			return false;
+		}
+
+		for (int i = 0; i < cnt; i++) {
+			if (!open_file_proc({pid, kfile[i].kf_path})) {
+				kvm_close(kernel);
+				return false;
+			}
+		}
+	}
+
+	kvm_close(kernel);
+
+	return true;
+#elif defined(LIBUTIL)
+	/* does this code even work? */
+	for (const auto& pid : pids) {
+		int cnt;
+		std::unique_ptr<struct kinfo_file[]> files(kinfo_getfile(pid, &cnt));
+		if (!files)
+			return false;
+
+		for (int i = 0; i < cnt; i++) {
+			const struct kinfo_file& current = files[i];
+			if (current.kf_vnode_type != KF_VTYPE_VREG)
+				continue;
+
+			if (!open_file_proc({pid, current.kf_path}))
+				return false;
+		}
+	}
+
+	return true;
+#elif defined(__NetBSD__)
+	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;
+
+		/* TODO: check kfile[i].ki_ofileflags */
+		for (size_t i = 0; i < mib[5]; i++)
+			if (!open_file_proc({pid, kfile[i].kf_path}))
+				return false;
+	}
+
+	return true;
+#else
+	return false;
+#endif
+}
+
+} // namespace animone::internal::kvm