Mercurial > minori
view dep/animone/src/fd/xnu.cc @ 327:b5d6c27c308f
anime: refactor Anime::SeriesSeason to Season class
ToLocalString has also been altered to take in both season
and year because lots of locales actually treat formatting
seasons differently! most notably is Russian which adds a
suffix at the end to notate seasons(??)
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Thu, 13 Jun 2024 01:49:18 -0400 |
parents | a4257370de16 |
children | a7d4e5107531 |
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; osx::util::GetProcessName(pids[i], result); if (!process_proc({pids[i], 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