comparison dep/animia/src/bsd.cpp @ 62:4c6dd5999b39

*: update 1. updated animia 2. use widestrings for filesystem on Windows
author Paper <mrpapersonic@gmail.com>
date Sun, 01 Oct 2023 06:16:06 -0400
parents 6ff7aabeb9d7
children 1ce00c1c8ddc
comparison
equal deleted inserted replaced
61:327568ad9be9 62:4c6dd5999b39
1 /** 1 /**
2 * bsd.cpp 2 * bsd.cpp
3 * - provides support for most* versions of BSD 3 * - provides support for most* versions of BSD
4 * - this *should* also work for OS X 4 * - this also works for OS X :)
5 * more technical details: this is essentially a wrapper 5 * more technical details: this is essentially a wrapper
6 * around the very C-like BSD system functions that are... 6 * around the very C-like BSD system functions that are...
7 * kind of unnatural to use in modern C++. 7 * kind of unnatural to use in modern C++.
8 **/ 8 **/
9 #include <vector>
10 #include <string>
11 #include <unordered_map>
12 #include <sys/types.h>
13 #include <sys/sysctl.h>
14 #include <sys/user.h>
15 #include <fcntl.h> 9 #include <fcntl.h>
16 #include <iostream> 10 #include <iostream>
11 #include <string>
12 #include <sys/sysctl.h>
13 #include <sys/types.h>
14 #include <sys/user.h>
15 #include <unordered_map>
16 #include <vector>
17 #ifdef __FreeBSD__ 17 #ifdef __FreeBSD__
18 #include <libutil.h> 18 # include <libutil.h>
19 #elif defined(__APPLE__) 19 #elif defined(__APPLE__)
20 #include <libproc.h> 20 # include <libproc.h>
21 #endif 21 #endif
22 22
23 namespace Animia::Unix { 23 namespace Animia::Unix {
24 24
25 /* this is a cleaned up version of a function from... Apple? 25 /* this is a cleaned up version of a function from... Apple?
26 ...anyway, what it essentially does is gets the size and stuff from 26 ...anyway, what it essentially does is gets the size and stuff from
27 sysctl() and reserves the space in a vector to store the PIDs */ 27 sysctl() and reserves the space in a vector to store the PIDs */
28 std::vector<int> get_all_pids() { 28 std::vector<int> get_all_pids() {
29 std::vector<int> ret; 29 std::vector<int> ret;
30 struct kinfo_proc* result = NULL; 30 struct kinfo_proc* result = NULL;
31 size_t length = 0; 31 size_t length = 0;
32 static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; 32 static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
33 33
34 /* get appropriate length from sysctl() */ 34 /* get appropriate length from sysctl()
35 sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0); 35 note: the reason this isn't checked is actually because this will
36 *always* return an error on OS X (or... maybe I'm doing it wrong :) ) */
37 sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, NULL, &length, NULL, 0);
36 38
37 result = (struct kinfo_proc*)malloc(length); 39 result = (struct kinfo_proc*)malloc(length);
38 if (result == NULL) 40 if (result == NULL)
39 return std::vector<int>(); 41 return std::vector<int>();
40 42
41 /* actually get our results */ 43 /* actually get our results */
42 if (sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, result, &length, NULL, 0) == ENOMEM) { 44 if (sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, result, &length, NULL, 0) == ENOMEM) {
43 assert(result != NULL); 45 assert(result != NULL);
44 free(result); 46 free(result);
45 throw std::bad_alloc(); 47 throw std::bad_alloc();
46 } 48 }
47 49
48 /* add pids to our vector */ 50 /* add pids to our vector */
49 ret.reserve(length/sizeof(*result)); 51 ret.reserve(length / sizeof(*result));
50 for (int i = 0; i < length/sizeof(*result); i++) 52 for (int i = 0; i < length / sizeof(*result); i++)
51 ret.push_back(result[i].kp_proc.p_pid); 53 ret.push_back(result[i].kp_proc.p_pid);
52 54
53 return ret; 55 return ret;
54 } 56 }
55 57
56 std::string get_process_name(int pid) { 58 std::string get_process_name(int pid) {
57 std::string ret; 59 std::string ret;
58 #ifdef __FreeBSD__ 60 #ifdef __FreeBSD__
59 struct kinfo_proc* proc = kinfo_getproc(pid); 61 struct kinfo_proc* proc = kinfo_getproc(pid);
60 if (!proc) { 62 if (!proc)
61 return ""; 63 return "";
62 ret = proc->ki_comm; 64 ret = proc->ki_comm;
63 free(proc); 65 free(proc);
64 #elif defined(__APPLE__) 66 #elif defined(__APPLE__)
65 struct proc_bsdinfo proc; 67 struct proc_bsdinfo proc;
66 68
67 int st = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc, PROC_PIDTBSDINFO_SIZE); 69 int st = proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &proc, PROC_PIDTBSDINFO_SIZE);
68 if (st != PROC_PIDTBSDINFO_SIZE) 70 if (st != PROC_PIDTBSDINFO_SIZE)
69 return ""; 71 return "";
70 return proc.pbi_comm; 72 ret = proc.pbi_comm;
71 #endif 73 #endif
72 return ret; 74 return ret;
73 } 75 }
74 76
75 std::vector<std::string> get_open_files(int pid) { 77 std::vector<std::string> get_open_files(int pid) {
76 // initialize buffer 78 /* note: this is OS X only right now. eventually, I'll find a way
77 std::vector<std::string> ret; 79 to do this in FreeBSD, OpenBSD and the like */
78 int bufsz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); 80 std::vector<std::string> ret;
79 struct proc_fdinfo *info = (struct proc_fdinfo *)malloc(bufsz); 81 int bufsz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
80 proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info, bufsz); 82 struct proc_fdinfo* info = (struct proc_fdinfo*)malloc(bufsz);
83 proc_pidinfo(pid, PROC_PIDLISTFDS, 0, info, bufsz);
81 84
82 // iterate over stuff 85 // iterate over stuff
83 for (int i = 0; i < bufsz/sizeof(info[0]); i++) { 86 ret.reserve(bufsz / sizeof(info[0]));
84 if (info[i].proc_fdtype == PROX_FDTYPE_VNODE) { 87 for (int i = 0; i < bufsz / sizeof(info[0]); i++) {
85 struct vnode_fdinfowithpath vnodeInfo; 88 if (info[i].proc_fdtype == PROX_FDTYPE_VNODE) {
86 proc_pidfdinfo(pid, info[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, PROC_PIDFDVNODEPATHINFO_SIZE); 89 struct vnode_fdinfowithpath vnodeInfo;
87 ret.push_back(vnodeInfo.pvip.vip_path); 90 proc_pidfdinfo(pid, info[i].proc_fd, PROC_PIDFDVNODEPATHINFO, &vnodeInfo, PROC_PIDFDVNODEPATHINFO_SIZE);
88 } 91 ret.push_back(vnodeInfo.pvip.vip_path);
89 } 92 }
90 return ret; 93 }
94 return ret;
91 } 95 }
92 96
93 std::unordered_map<int, std::vector<std::string>> get_all_open_files() { 97 std::unordered_map<int, std::vector<std::string>> get_all_open_files() {
94 std::unordered_map<int, std::vector<std::string>> map; 98 std::unordered_map<int, std::vector<std::string>> map;
95 std::vector<int> pids = get_all_pids(); 99 std::vector<int> pids = get_all_pids();
96 for (int i: pids) { 100 for (int i : pids) {
97 map[i] = get_open_files(i); 101 map[i] = get_open_files(i);
98 } 102 }
99 return map; 103 return map;
100 } 104 }
101 105
102 } 106 } // namespace Animia::Unix