comparison dep/animia/src/fd/proc.cc @ 202:71832ffe425a

animia: re-add kvm fd source this is all being merged from my wildly out-of-date laptop. SORRY! in other news, I edited the CI file to install the wayland client as well, so the linux CI build might finally get wayland stuff.
author Paper <paper@paper.us.eu.org>
date Tue, 02 Jan 2024 06:05:06 -0500
parents bc1ae1810855
children 031a257ee019
comparison
equal deleted inserted replaced
201:8f6f8dd2eb23 202:71832ffe425a
14 #include <dirent.h> 14 #include <dirent.h>
15 #include <fcntl.h> 15 #include <fcntl.h>
16 #include <sys/stat.h> 16 #include <sys/stat.h>
17 #include <unistd.h> 17 #include <unistd.h>
18 18
19 #ifdef FREEBSD 19 static constexpr std::string_view PROC_LOCATION = "/proc";
20 # include <sys/types.h>
21 # include <sys/user.h>
22 # include <libutil.h>
23 #endif
24
25 #define PROC_LOCATION "/proc"
26 20
27 namespace animia::internal::proc { 21 namespace animia::internal::proc {
28 22
29 /* this uses dirent instead of std::filesystem; it would make a bit 23 /* this uses dirent instead of std::filesystem; it would make a bit
30 more sense to use the latter, but this is platform dependent already :) */ 24 more sense to use the latter, but this is platform dependent already :) */
55 return false; 49 return false;
56 return S_ISREG(sb.st_mode); 50 return S_ISREG(sb.st_mode);
57 } 51 }
58 52
59 static bool AreFlagsOk(pid_t pid, int fd) { 53 static bool AreFlagsOk(pid_t pid, int fd) {
60 const std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/fdinfo/" + std::to_string(fd); 54 const std::string path = std::string(PROC_LOCATION) + "/" + std::to_string(pid) + "/fdinfo/" + std::to_string(fd);
61 55
62 std::ifstream file(path.c_str()); 56 std::ifstream file(path.c_str());
63 if (!file) 57 if (!file)
64 return false; 58 return false;
65 59
73 return true; 67 return true;
74 } 68 }
75 69
76 static bool GetFilenameFromFd(std::string link, std::string& out) { 70 static bool GetFilenameFromFd(std::string link, std::string& out) {
77 /* gets around stupid linux limitation where /proc doesn't 71 /* gets around stupid linux limitation where /proc doesn't
78 give actual filesize readings */ 72 * give actual size readings of the string
73 */
79 constexpr size_t OUT_MAX = (1 << 15); // 32KiB 74 constexpr size_t OUT_MAX = (1 << 15); // 32KiB
80 out.resize(1024); 75 out.resize(1024);
81 76
82 for (ssize_t exe_used = 0; 77 for (ssize_t exe_used = 0;
83 out.length() < OUT_MAX && exe_used >= (ssize_t)(out.length() - 1); 78 out.length() < OUT_MAX && exe_used >= (ssize_t)(out.length() - 1);
84 out.resize(out.length() * 2)) { 79 out.resize(out.length() * 2)) {
85 exe_used = readlink(link.c_str(), &out.front(), out.length()); 80 exe_used = readlink(link.c_str(), &out.front(), out.length());
86 if (exe_used == (ssize_t)-1 || exe_used < (ssize_t)1) 81 if (exe_used == (ssize_t)-1 || exe_used < (ssize_t)1)
87 return false; 82 return false; // we got a bad result, i think
88 } 83 }
84
85 out.resize(out.find('\0'));
86
87 return true;
89 } 88 }
90 89
91 static std::string GetProcessName(pid_t pid) { 90 static std::string GetProcessName(pid_t pid) {
92 std::string result; 91 std::string result;
93 92
94 #ifdef FREEBSD 93 const std::string path = std::string(PROC_LOCATION) + "/" + std::to_string(pid) + "/comm";
95 struct kinfo_proc* proc = kinfo_getproc(pid);
96 if (!proc)
97 return "";
98 result = proc->ki_comm;
99 free(proc);
100 #elif defined(LINUX)
101 const std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/comm";
102 94
103 if (!util::ReadFile(path, result)) 95 if (!util::ReadFile(path, result))
104 return ""; 96 return "";
105 97
106 result.erase(std::remove(result.begin(), result.end(), '\n'), result.end()); 98 result.erase(std::remove(result.begin(), result.end(), '\n'), result.end());
107 #endif
108 99
109 return result; 100 return result;
110 } 101 }
111 102
112 bool ProcFdTools::EnumerateOpenProcesses(process_proc_t process_proc) { 103 bool EnumerateOpenProcesses(process_proc_t process_proc) {
113 bool success = false; 104 bool success = false;
114 for (const auto& dir : GetAllFilesInDir(PROC_LOCATION)) { 105 for (const auto& dir : GetAllFilesInDir(std::string(PROC_LOCATION))) {
115 pid_t pid; 106 pid_t pid;
116 try { 107 try {
117 pid = std::stoul(Basename(dir)); 108 pid = std::stoul(Basename(dir));
118 success = true; 109 success = true;
119 } catch (std::invalid_argument) { 110 } catch (std::invalid_argument) {
123 return false; 114 return false;
124 } 115 }
125 return success; 116 return success;
126 } 117 }
127 118
128 bool ProcFdTools::EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { 119 bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) {
129 if (!open_file_proc) 120 if (!open_file_proc)
130 return false; 121 return false;
131 122
132 for (const auto& pid : pids) { 123 for (const auto& pid : pids) {
133 const std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/fd"; 124 const std::string path = std::string(PROC_LOCATION) + "/" + std::to_string(pid) + "/fd";
134 125
135 for (const auto& dir : GetAllFilesInDir(path)) { 126 for (const auto& dir : GetAllFilesInDir(path)) {
136 if (!AreFlagsOk(pid, std::stoi(Basename(dir)))) 127 if (!AreFlagsOk(pid, std::stoi(Basename(dir))))
137 continue; 128 continue;
138 129
139 std::string name = GetFilenameFromFd(dir); 130 std::string name;
131 if (!GetFilenameFromFd(dir, name))
132 continue;
140 133
141 if (!IsRegularFile(name)) 134 if (!IsRegularFile(name))
142 continue; 135 continue;
143 136
144 if (!open_file_proc({pid, name})) 137 if (!open_file_proc({pid, name}))