Mercurial > minori
comparison dep/animia/src/platform/linux/fd.cc @ 137:69db40272acd
dep/animia: [WIP] huge refactor
this WILL NOT compile, because lots of code has been changed
and every API in the original codebase has been removed.
note that this api setup is not exactly permanent...
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Fri, 10 Nov 2023 13:52:47 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
136:7d3ad9529c4c | 137:69db40272acd |
---|---|
1 #include <algorithm> | |
2 #include <fcntl.h> | |
3 #include <filesystem> | |
4 #include <fstream> | |
5 #include <iostream> | |
6 #include <sstream> | |
7 #include <string> | |
8 #include <sys/stat.h> | |
9 #include <unistd.h> | |
10 #include <unordered_map> | |
11 #include <vector> | |
12 #include <cstring> | |
13 #include <dirent.h> | |
14 | |
15 #define PROC_LOCATION "/proc" | |
16 | |
17 namespace Animia { namespace Linux { | |
18 | |
19 std::vector<std::string> get_all_files_in_dir(const std::string& _dir) { | |
20 std::vector<std::string> ret; | |
21 | |
22 DIR* dir = opendir(_dir.c_str()); | |
23 if (!dir) | |
24 return ret; | |
25 | |
26 struct dirent* dp; | |
27 while ((dp = readdir(dir)) != NULL) { | |
28 if (!(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))) | |
29 ret.push_back(_dir + "/" + dp->d_name); | |
30 } | |
31 | |
32 closedir(dir); | |
33 return ret; | |
34 } | |
35 | |
36 std::string basename(const std::string& path) { | |
37 return path.substr(path.find_last_of("/") + 1, path.length()); | |
38 } | |
39 | |
40 std::string stem(const std::string& path) { | |
41 std::string bn = basename(path); | |
42 return bn.substr(0, path.find_last_of(".")); | |
43 } | |
44 | |
45 std::vector<int> get_all_pids() { | |
46 std::vector<int> ret; | |
47 | |
48 for (const auto& dir : get_all_files_in_dir(PROC_LOCATION)) { | |
49 int pid; | |
50 try { | |
51 pid = std::stoi(basename(dir)); | |
52 } catch (std::invalid_argument) { | |
53 continue; | |
54 } | |
55 ret.push_back(pid); | |
56 } | |
57 | |
58 return ret; | |
59 } | |
60 | |
61 std::string get_process_name(int pid) { | |
62 std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/comm"; | |
63 std::ifstream t(path); | |
64 std::stringstream buf; | |
65 buf << t.rdbuf(); | |
66 | |
67 std::string str = buf.str(); | |
68 str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); | |
69 return str; | |
70 } | |
71 | |
72 static bool is_regular_file(std::string link) { | |
73 struct stat sb; | |
74 if (stat(link.c_str(), &sb) == -1) | |
75 return false; | |
76 return S_ISREG(sb.st_mode); | |
77 } | |
78 | |
79 static bool are_flags_ok(int pid, int fd) { | |
80 std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/fdinfo/" + std::to_string(fd); | |
81 std::ifstream t(path); | |
82 std::stringstream buffer; | |
83 buffer << t.rdbuf(); | |
84 std::string raw; | |
85 int flags = 0; | |
86 while (std::getline(buffer, raw)) { | |
87 if (raw.rfind("flags:", 0) == 0) { | |
88 flags = std::stoi(raw.substr(raw.find_last_not_of("0123456789") + 1)); | |
89 } | |
90 } | |
91 if (flags & O_WRONLY || flags & O_RDWR) | |
92 return false; | |
93 return true; | |
94 } | |
95 | |
96 static std::string get_name_from_fd(std::string link) { | |
97 size_t exe_size = 1024; | |
98 ssize_t exe_used; | |
99 std::string ret; | |
100 while (1) { | |
101 ret = std::string(exe_size, '\0'); | |
102 exe_used = readlink(link.c_str(), &ret.front(), ret.length()); | |
103 if (exe_used == (ssize_t)-1) | |
104 return NULL; | |
105 | |
106 if (exe_used < (ssize_t)1) { | |
107 errno = ENOENT; | |
108 return NULL; | |
109 } | |
110 | |
111 if (exe_used < (ssize_t)(exe_size - 1)) | |
112 break; | |
113 | |
114 exe_size += 1024; | |
115 } | |
116 | |
117 return ret.c_str(); | |
118 } | |
119 | |
120 std::vector<std::string> get_open_files(int pid) { | |
121 std::vector<std::string> ret; | |
122 std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/fd"; | |
123 | |
124 for (const auto& dir : get_all_files_in_dir(path)) { | |
125 if (!are_flags_ok(pid, std::stoi(basename(dir)))) | |
126 continue; | |
127 | |
128 std::string buf = get_name_from_fd(dir); | |
129 | |
130 if (!is_regular_file(buf)) | |
131 continue; | |
132 | |
133 ret.push_back(buf); | |
134 } | |
135 return ret; | |
136 } | |
137 | |
138 std::unordered_map<int, std::vector<std::string>> get_all_open_files() { | |
139 std::unordered_map<int, std::vector<std::string>> map; | |
140 std::vector<int> pids = get_all_pids(); | |
141 for (int i : pids) | |
142 map[i] = get_open_files(i); | |
143 return map; | |
144 } | |
145 | |
146 } // namespace Linux | |
147 } // namespace Animia |