comparison dep/animone/src/fd/xnu.cc @ 365:f81bed4e04ac

*: megacommit that probably breaks things
author Paper <paper@paper.us.eu.org>
date Wed, 02 Oct 2024 23:06:43 -0400
parents a7d4e5107531
children
comparison
equal deleted inserted replaced
364:99c961c91809 365:f81bed4e04ac
33 #endif 33 #endif
34 34
35 namespace animone::internal::xnu { 35 namespace animone::internal::xnu {
36 36
37 bool EnumerateOpenProcesses(process_proc_t process_proc) { 37 bool EnumerateOpenProcesses(process_proc_t process_proc) {
38 size_t pids_size = 256; 38 /* pre-allocate 256 pids */
39 std::unique_ptr<pid_t[]> pids; 39 std::vector<pid_t> pids(256);
40 int returned_size_bytes = 0;
40 41
41 int returned_size = 0; 42 for (;;) {
42 do { 43 returned_size_bytes = proc_listpids(PROC_ALL_PIDS, 0, pids.data(), pids.size() * sizeof(pid_t));
43 pids.reset(new pid_t[pids_size *= 2]); 44 if (returned_size_bytes <= 0) /* probably an error ? */
44 returned_size = proc_listpids(PROC_ALL_PIDS, 0, pids.get(), pids_size * sizeof(pid_t));
45 if (returned_size == -1)
46 return false; 45 return false;
47 } while ((pids_size * sizeof(size_t)) < returned_size);
48 46
49 for (int i = 0; i < pids_size; i++) { 47 /* break out of the loop if we have everything */
48 if ((pids.size() * sizeof(pid_t)) > returned_size_bytes)
49 break;
50
51 pids.resize(pids.size() * 2);
52 }
53
54 pids.resize(returned_size_bytes);
55
56 for (const auto& pid : pids) {
50 std::string result; 57 std::string result;
51 GetProcessName(pids[i], result); 58 GetProcessName(pid, result);
52 if (!process_proc({.platform = ExecutablePlatform::Xnu, .pid = pids[i], .comm = result})) 59 if (!process_proc({.platform = ExecutablePlatform::Xnu, .pid = pid, .comm = result}))
53 return false; 60 return false;
54 } 61 }
55 62
56 return true; 63 return true;
57 } 64 }
59 bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { 66 bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) {
60 if (!open_file_proc) 67 if (!open_file_proc)
61 return false; 68 return false;
62 69
63 for (const auto& pid : pids) { 70 for (const auto& pid : pids) {
64 const int bufsz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); 71 /* most processes probably don't even have that many files opened! */
65 if (bufsz < 0) 72 std::vector<struct proc_fdinfo> fds(4);
66 return false; 73 int returned_size_bytes = 0;
67 74
68 const size_t info_len = bufsz / sizeof(struct proc_fdinfo); 75 for (;;) {
69 if (info_len < 1) 76 returned_size_bytes = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds.data(), fds.size());
70 return false; 77 if (returned_size_bytes <= 0) /* probably an error ? */
78 return false;
71 79
72 std::unique_ptr<struct proc_fdinfo[]> info(new struct proc_fdinfo[info_len]); 80 /* break out of the loop if we have everything */
73 if (!info) 81 if ((fds.size() * sizeof(struct proc_fdinfo)) > returned_size_bytes)
74 return false; 82 break;
75 83
76 proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info.get(), bufsz); 84 fds.resize(fds.size() * 2);
85 }
77 86
78 for (size_t i = 0; i < info_len; i++) { 87 fds.resize(returned_size_bytes / sizeof(struct proc_fdinfo));
79 if (info[i].proc_fdtype == PROX_FDTYPE_VNODE) {
80 struct vnode_fdinfowithpath vnodeInfo;
81 88
82 int sz = proc_pidfdinfo(pid, info[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, 89 for (const auto& fd : fds) {
83 PROC_PIDFDVNODEPATHINFO_SIZE); 90 if (fd.proc_fdtype != PROX_FDTYPE_VNODE)
84 if (sz != PROC_PIDFDVNODEPATHINFO_SIZE) 91 continue;
85 return false;
86 92
87 /* why would a media player open a file in write mode? */ 93 struct vnode_fdinfowithpath vnodeInfo;
88 if (vnodeInfo.pfi.fi_openflags & FWRITE)
89 continue;
90 94
91 if (!open_file_proc({pid, vnodeInfo.pvip.vip_path})) 95 int sz = proc_pidfdinfo(pid, fd.proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo,
92 return false; 96 PROC_PIDFDVNODEPATHINFO_SIZE);
93 } 97 if (sz != PROC_PIDFDVNODEPATHINFO_SIZE)
98 return false;
99
100 /* why would a media player open a file in write mode? */
101 if (vnodeInfo.pfi.fi_openflags & FWRITE)
102 continue;
103
104 if (!open_file_proc({pid, vnodeInfo.pvip.vip_path}))
105 return false;
94 } 106 }
95 } 107 }
96 108
97 return true; 109 return true;
98 } 110 }
99 111
100 static bool GetProcessNameFromProcPidPath(pid_t pid, std::string& result) { 112 static bool GetProcessNameFromProcPidPath(pid_t pid, std::string& result) {
101 result.assign(PROC_PIDPATHINFO_MAXSIZE, '\0'); 113 result.assign(PROC_PIDPATHINFO_MAXSIZE, '\0');
102 114
103 int ret = proc_pidpath(pid, result.data(), result.size() * sizeof(char)); 115 int ret = proc_pidpath(pid, result.data(), result.size());
104 if (ret <= 0) 116 if (ret <= 0)
105 return false; 117 return false;
106 118
107 /* find the last slash, if there's none, we're done here */ 119 /* find the last slash, if there's none, we're done here */
108 size_t last_slash = result.rfind('/'); 120 size_t last_slash = result.rfind('/');
114 } 126 }
115 127
116 static bool GetProcessNameFromProcName(pid_t pid, std::string& result) { 128 static bool GetProcessNameFromProcName(pid_t pid, std::string& result) {
117 result.assign(2 * MAXCOMLEN, '\0'); 129 result.assign(2 * MAXCOMLEN, '\0');
118 130
119 int size = proc_name(pid, &result.front(), result.length()); 131 int size = proc_name(pid, result.data(), result.length());
120 132
121 /* if size is MAXCOMLEN or 2 * MAXCOMLEN, assume 133 /* if size is MAXCOMLEN or 2 * MAXCOMLEN, assume
122 * this method won't work and our result is truncated */ 134 * this method won't work and our result is truncated */
123 if (size <= 0 || size == MAXCOMLEN || size == 2 * MAXCOMLEN) 135 if (size <= 0 || size == MAXCOMLEN || size == 2 * MAXCOMLEN)
124 return false; 136 return false;