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 }