Mercurial > minori
comparison dep/animia/src/fd/xnu.cc @ 153:bd439dd6ffc5
*: make win stuff actually work, rename bsd.cc to xnu.cc
It's been OS X only for ages, and these functions are different between
most BSDs anyway
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Wed, 15 Nov 2023 13:28:18 -0500 |
parents | |
children | d43d68408d3c |
comparison
equal
deleted
inserted
replaced
152:8700806c2cc2 | 153:bd439dd6ffc5 |
---|---|
1 /* | |
2 ** fd/xnu.cpp | |
3 ** - provides support for XNU (part of Darwin) | |
4 */ | |
5 #include "animia/fd/xnu.h" | |
6 #include "animia.h" | |
7 | |
8 #include <unordered_map> | |
9 #include <vector> | |
10 #include <string> | |
11 | |
12 #include <fcntl.h> | |
13 #include <sys/sysctl.h> | |
14 #include <sys/types.h> | |
15 #include <sys/user.h> | |
16 #include <libproc.h> | |
17 | |
18 namespace animia::internal::xnu { | |
19 | |
20 static bool GetProcessName(pid_t pid, std::string& result) { | |
21 struct proc_bsdinfo proc; | |
22 | |
23 int st = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc, PROC_PIDTBSDINFO_SIZE); | |
24 if (st != PROC_PIDTBSDINFO_SIZE) | |
25 return false; | |
26 | |
27 /* fixme: is this right? pbi_comm is an alternative, but it reduces the string size to | |
28 16 chars. does pbi_name do the same, or is it different? */ | |
29 result = proc.pbi_name; | |
30 return true; | |
31 } | |
32 | |
33 /* this is a cleaned up version of a function from... Apple? | |
34 ...anyway, what it essentially does is gets the size and stuff from | |
35 sysctl() and reserves the space in a vector to store the PIDs */ | |
36 bool XnuFdTools::EnumerateOpenProcesses(process_proc_t process_proc) { | |
37 struct kinfo_proc* result = NULL; | |
38 size_t length = 0; | |
39 static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0}; | |
40 | |
41 /* get appropriate length from sysctl() | |
42 note: the reason this isn't checked is actually because this will | |
43 *always* return an error on OS X (or... maybe I'm doing it wrong :) ) */ | |
44 sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0); | |
45 | |
46 result = (struct kinfo_proc*)malloc(length); | |
47 if (result == NULL) | |
48 return false; | |
49 | |
50 /* TODO: this might actually return ENOMEM if the amount of file handles changes between the | |
51 original sysctl() call and this one, which is technically possible */ | |
52 if (sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, result, &length, NULL, 0) == ENOMEM) { | |
53 assert(result != NULL); | |
54 free(result); | |
55 return false; | |
56 } | |
57 | |
58 for (int i = 0; i < length / sizeof(*result); i++) { | |
59 const pid_t pid = result[i].kp_proc.p_pid; | |
60 if (!process_proc({pid, GetProcessName(pid)})) | |
61 return false; | |
62 } | |
63 } | |
64 | |
65 bool XnuFdTools::EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { | |
66 if (!open_file_proc) | |
67 return false; | |
68 | |
69 for (const auto& pid : pids) { | |
70 int bufsz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); | |
71 if (bufsz == -1) | |
72 return false; | |
73 | |
74 struct proc_fdinfo* info = (struct proc_fdinfo*)malloc(bufsz); | |
75 if (!info) | |
76 return false; | |
77 | |
78 proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info, bufsz); | |
79 | |
80 for (int i = 0; i < bufsz / sizeof(info[0]); i++) { | |
81 if (info[i].proc_fdtype == PROX_FDTYPE_VNODE) { | |
82 struct vnode_fdinfowithpath vnodeInfo; | |
83 | |
84 int sz = proc_pidfdinfo(pid, info[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, PROC_PIDFDVNODEPATHINFO_SIZE); | |
85 if (sz != PROC_PIDFDVNODEPATHINFO_SIZE) | |
86 return false; | |
87 | |
88 /* this doesn't work! | |
89 if (vnodeInfo.pfi.fi_openflags & O_WRONLY || vnodeInfo.pfi.fi_openflags & O_RDWR) | |
90 continue; | |
91 */ | |
92 | |
93 if (!open_file_proc({pid, vnodeInfo.pvip.vip_path})) | |
94 return false; | |
95 } | |
96 } | |
97 } | |
98 return true; | |
99 } | |
100 | |
101 } // namespace animia::internal::unix |