137
|
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 |