Mercurial > minori
comparison dep/animia/src/linux.cpp @ 56:6ff7aabeb9d7
deps: add animia for open files detection
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Thu, 28 Sep 2023 12:35:21 -0400 |
parents | |
children | 4c6dd5999b39 |
comparison
equal
deleted
inserted
replaced
54:466ac9870df9 | 56:6ff7aabeb9d7 |
---|---|
1 #include <string> | |
2 #include <vector> | |
3 #include <fstream> | |
4 #include <filesystem> | |
5 #include <unordered_map> | |
6 #include <iostream> | |
7 #include <sstream> | |
8 #include <unistd.h> | |
9 #include <sys/stat.h> | |
10 #include <fcntl.h> | |
11 #include <algorithm> | |
12 | |
13 #define PROC_LOCATION "/proc" | |
14 | |
15 namespace Animia::Linux { | |
16 | |
17 std::vector<int> get_all_pids() { | |
18 std::vector<int> ret; | |
19 for (const auto& dir : std::filesystem::directory_iterator(PROC_LOCATION)) { | |
20 int pid; | |
21 try { | |
22 pid = std::stoi(dir.path().stem()); | |
23 } catch (std::invalid_argument) { | |
24 continue; | |
25 } | |
26 ret.push_back(pid); | |
27 } | |
28 return ret; | |
29 } | |
30 | |
31 std::string get_process_name(int pid) { | |
32 std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/comm"; | |
33 std::ifstream t(path); | |
34 std::stringstream buf; | |
35 buf << t.rdbuf(); | |
36 std::string str = buf.str(); | |
37 str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); | |
38 return str; | |
39 } | |
40 | |
41 static bool is_regular_file(std::string link) { | |
42 struct stat sb; | |
43 if (stat(link.c_str(), &sb) == -1) | |
44 return false; | |
45 return S_ISREG(sb.st_mode); | |
46 } | |
47 | |
48 static bool are_flags_ok(int pid, int fd) { | |
49 std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/fdinfo/" + std::to_string(fd); | |
50 std::ifstream t(path); | |
51 std::stringstream buffer; | |
52 buffer << t.rdbuf(); | |
53 std::string raw; | |
54 int flags = 0; | |
55 while (std::getline(buffer, raw)) { | |
56 if (raw.rfind("flags:", 0) == 0) { | |
57 flags = std::stoi(raw.substr(raw.find_last_not_of("0123456789") + 1)); | |
58 } | |
59 } | |
60 if (flags & O_WRONLY || flags & O_RDWR) | |
61 return false; | |
62 return true; | |
63 } | |
64 | |
65 static int get_size_of_link(std::string link) { | |
66 struct stat sb; | |
67 if (lstat(link.c_str(), &sb) == -1) | |
68 return -1; | |
69 return sb.st_size + 1; | |
70 } | |
71 | |
72 std::vector<std::string> get_open_files(int pid) { | |
73 std::vector<std::string> ret; | |
74 std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/fd"; | |
75 try { | |
76 for (const auto& dir : std::filesystem::directory_iterator(path)) { | |
77 if (!are_flags_ok(pid, std::stoi(dir.path().stem()))) | |
78 continue; | |
79 /* get filename size */ | |
80 int size = get_size_of_link(dir.path().string()); | |
81 /* allocate buffer */ | |
82 char* buf = (char*)calloc(size, sizeof(char)); | |
83 //std::string buf('\0', size); | |
84 /* read filename to buffer */ | |
85 int r = readlink(dir.path().c_str(), buf, size); | |
86 | |
87 if (r < 0) | |
88 continue; | |
89 if (!is_regular_file(buf)) | |
90 continue; | |
91 ret.push_back(buf); | |
92 free(buf); | |
93 } | |
94 } catch (std::filesystem::filesystem_error const& ex) { | |
95 if (ex.code().value() != 13) // 13 == permissions error, common with /proc, ignore | |
96 throw; | |
97 } | |
98 return ret; | |
99 } | |
100 | |
101 std::unordered_map<int, std::vector<std::string>> get_all_open_files() { | |
102 std::unordered_map<int, std::vector<std::string>> map; | |
103 std::vector<int> pids = get_all_pids(); | |
104 for (int i: pids) | |
105 map[i] = get_open_files(i); | |
106 return map; | |
107 } | |
108 | |
109 } |