Mercurial > minori
view dep/animone/src/fd/xnu.cc @ 337:a7d4e5107531
dep/animone: REFACTOR ALL THE THINGS
1: animone now has its own syntax divergent from anisthesia,
making different platforms actually have their own sections
2: process names in animone are now called `comm' (this will
probably break things). this is what its called in bsd/linux
so I'm just going to use it everywhere
3: the X11 code now checks for the existence of a UTF-8 window title
and passes it if available
4: ANYTHING THATS NOT LINUX IS 100% UNTESTED AND CAN AND WILL BREAK!
I still actually need to test the bsd code. to be honest I'm probably
going to move all of the bsds into separate files because they're
all essentially different operating systems at this point
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Wed, 19 Jun 2024 12:51:15 -0400 |
parents | a4257370de16 |
children | f81bed4e04ac |
line wrap: on
line source
/* * fd/xnu.cc: support for macOS's kernel * * this used to have all sorts of hacks for getting the process name, * but ultimately I just decided that it's better to just parse the * PID path from xnu, which should work perfectly fine. */ #include "animone/fd/xnu.h" #include "animone.h" #include <cassert> #include <memory> #include <string> #include <unordered_map> #include <vector> #include <fcntl.h> #include <libproc.h> #include <sys/sysctl.h> #include <sys/types.h> #include <sys/user.h> /* you may be asking: WTF is FWRITE? * well, from bsd/sys/fcntl.h in the XNU kernel: * * Kernel encoding of open mode; separate read and write bits that are * independently testable: 1 greater than [O_RDONLY and O_WRONLY]. * * It's just how the kernel defines write mode. */ #ifndef FWRITE #define FWRITE 0x0002 #endif namespace animone::internal::xnu { bool EnumerateOpenProcesses(process_proc_t process_proc) { size_t pids_size = 256; std::unique_ptr<pid_t[]> pids; int returned_size = 0; do { pids.reset(new pid_t[pids_size *= 2]); returned_size = proc_listpids(PROC_ALL_PIDS, 0, pids.get(), pids_size * sizeof(pid_t)); if (returned_size == -1) return false; } while ((pids_size * sizeof(size_t)) < returned_size); for (int i = 0; i < pids_size; i++) { std::string result; GetProcessName(pids[i], result); if (!process_proc({.platform = ExecutablePlatform::Xnu, .pid = pids[i], .comm = result})) return false; } return true; } bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { if (!open_file_proc) return false; for (const auto& pid : pids) { const int bufsz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); if (bufsz < 0) return false; const size_t info_len = bufsz / sizeof(struct proc_fdinfo); if (info_len < 1) return false; std::unique_ptr<struct proc_fdinfo[]> info(new struct proc_fdinfo[info_len]); if (!info) return false; proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info.get(), bufsz); for (size_t i = 0; i < info_len; i++) { if (info[i].proc_fdtype == PROX_FDTYPE_VNODE) { struct vnode_fdinfowithpath vnodeInfo; int sz = proc_pidfdinfo(pid, info[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, PROC_PIDFDVNODEPATHINFO_SIZE); if (sz != PROC_PIDFDVNODEPATHINFO_SIZE) return false; /* why would a media player open a file in write mode? */ if (vnodeInfo.pfi.fi_openflags & FWRITE) continue; if (!open_file_proc({pid, vnodeInfo.pvip.vip_path})) return false; } } } return true; } static bool GetProcessNameFromProcPidPath(pid_t pid, std::string& result) { result.assign(PROC_PIDPATHINFO_MAXSIZE, '\0'); int ret = proc_pidpath(pid, result.data(), result.size() * sizeof(char)); if (ret <= 0) return false; /* find the last slash, if there's none, we're done here */ size_t last_slash = result.rfind('/'); if (last_slash == std::string::npos) return true; result.erase(0, last_slash + 1); return true; } static bool GetProcessNameFromProcName(pid_t pid, std::string& result) { result.assign(2 * MAXCOMLEN, '\0'); int size = proc_name(pid, &result.front(), result.length()); /* if size is MAXCOMLEN or 2 * MAXCOMLEN, assume * this method won't work and our result is truncated */ if (size <= 0 || size == MAXCOMLEN || size == 2 * MAXCOMLEN) return false; result.resize(size); return true; } bool GetProcessName(pid_t pid, std::string& result) { if (GetProcessNameFromProcName(pid, result)) return true; if (GetProcessNameFromProcPidPath(pid, result)) return true; return false; } } // namespace animone::internal::xnu