Mercurial > minori
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; |
