comparison dep/animia/src/fd/bsd.cc @ 152:8700806c2cc2

dep/animia: awesome new breaking changes! I'm so tired
author Paper <mrpapersonic@gmail.com>
date Wed, 15 Nov 2023 02:34:59 -0500
parents 54744a48a7d7
children
comparison
equal deleted inserted replaced
151:54744a48a7d7 152:8700806c2cc2
1 /** 1 /*
2 * fd/bsd.cpp 2 ** fd/bsd.cpp
3 * - this ONLY* supports OS X as of now 3 ** - this ONLY* supports OS X as of now
4 * (*there is some FreeBSD support code) 4 ** (*there is some FreeBSD support code)
5 **/ 5 */
6 #include "animia/fd/bsd.h" 6 #include "animia/fd/bsd.h"
7 #include "animia.h"
7 8
8 #include <unordered_map> 9 #include <unordered_map>
9 #include <vector> 10 #include <vector>
10 #include <iostream>
11 #include <string> 11 #include <string>
12 12
13 #include <fcntl.h> 13 #include <fcntl.h>
14 #include <sys/sysctl.h> 14 #include <sys/sysctl.h>
15 #include <sys/types.h> 15 #include <sys/types.h>
21 # include <libproc.h> 21 # include <libproc.h>
22 #endif 22 #endif
23 23
24 namespace animia::internal::unix { 24 namespace animia::internal::unix {
25 25
26 /* this is a cleaned up version of a function from... Apple? 26 static bool GetProcessName(pid_t pid, std::string& result) {
27 ...anyway, what it essentially does is gets the size and stuff from
28 sysctl() and reserves the space in a vector to store the PIDs
29
30 TODO: https://kaashif.co.uk/2015/06/18/how-to-get-a-list-of-processes-on-openbsd-in-c/ */
31 bool UnixFdTools::GetAllPids(std::set<pid_t>& pids) {
32 struct kinfo_proc* result = NULL;
33 size_t length = 0;
34 static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
35
36 /* get appropriate length from sysctl()
37 note: the reason this isn't checked is actually because this will
38 *always* return an error on OS X (or... maybe I'm doing it wrong :) ) */
39 sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0);
40
41 result = (struct kinfo_proc*)malloc(length);
42 if (result == NULL)
43 return std::vector<int>();
44
45 /* TODO: this might actually return ENOMEM if the amount of file handles changes between the
46 original sysctl() call and this one, which is technically possible */
47 if (sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, result, &length, NULL, 0) == ENOMEM) {
48 assert(result != NULL);
49 free(result);
50 throw std::bad_alloc();
51 }
52
53 /* add pids to our vector */
54 pids.reserve(length / sizeof(*result));
55 for (int i = 0; i < length / sizeof(*result); i++)
56 pids.insert(result[i].kp_proc.p_pid);
57 }
58
59 bool UnixFdTools::GetProcessName(pid_t pid, std::string& result) {
60 #ifdef __FreeBSD__ 27 #ifdef __FreeBSD__
61 struct kinfo_proc* proc = kinfo_getproc(pid); 28 struct kinfo_proc* proc = kinfo_getproc(pid);
62 if (!proc) 29 if (!proc)
63 return false; 30 return false;
64 result = proc->ki_comm; 31 result = proc->ki_comm;
81 result = proc.pbi_name; 48 result = proc.pbi_name;
82 return true; 49 return true;
83 #endif 50 #endif
84 } 51 }
85 52
53 /* this is a cleaned up version of a function from... Apple?
54 ...anyway, what it essentially does is gets the size and stuff from
55 sysctl() and reserves the space in a vector to store the PIDs
56
57 TODO: https://kaashif.co.uk/2015/06/18/how-to-get-a-list-of-processes-on-openbsd-in-c/ */
58 bool UnixFdTools::EnumerateOpenProcesses(process_proc_t process_proc) {
59 struct kinfo_proc* result = NULL;
60 size_t length = 0;
61 static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
62
63 /* get appropriate length from sysctl()
64 note: the reason this isn't checked is actually because this will
65 *always* return an error on OS X (or... maybe I'm doing it wrong :) ) */
66 sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0);
67
68 result = (struct kinfo_proc*)malloc(length);
69 if (result == NULL)
70 return std::vector<int>();
71
72 /* TODO: this might actually return ENOMEM if the amount of file handles changes between the
73 original sysctl() call and this one, which is technically possible */
74 if (sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, result, &length, NULL, 0) == ENOMEM) {
75 assert(result != NULL);
76 free(result);
77 throw std::bad_alloc();
78 }
79
80 for (int i = 0; i < length / sizeof(*result); i++) {
81 const pid_t pid = result[i].kp_proc.p_pid;
82 if (!process_proc({pid, GetProcessName(pid)}))
83 return false;
84 }
85 }
86
86 /* this only works on OS X :( */ 87 /* this only works on OS X :( */
87 bool UnixFdTools::EnumerateOpenFiles(const std::set<pid_t>& pids, std::vector<std::pair<pid_t, std::string>>& files) { 88 bool UnixFdTools::EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) {
89 if (!open_file_proc)
90 return false;
91
88 for (const auto& pid : pids) { 92 for (const auto& pid : pids) {
89 int bufsz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); 93 int bufsz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
90 if (bufsz == -1) 94 if (bufsz == -1)
91 return false; 95 return false;
92 96
107 /* this doesn't work! 111 /* this doesn't work!
108 if (vnodeInfo.pfi.fi_openflags & O_WRONLY || vnodeInfo.pfi.fi_openflags & O_RDWR) 112 if (vnodeInfo.pfi.fi_openflags & O_WRONLY || vnodeInfo.pfi.fi_openflags & O_RDWR)
109 continue; 113 continue;
110 */ 114 */
111 115
112 files.push_back({pid, vnodeInfo.pvip.vip_path}); 116 if (!open_file_proc({pid, vnodeInfo.pvip.vip_path}))
117 return false;
113 } 118 }
114 } 119 }
115 } 120 }
116 return true; 121 return true;
117 } 122 }