Mercurial > minori
view 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 |
line wrap: on
line source
#include <algorithm> #include <fcntl.h> #include <filesystem> #include <fstream> #include <iostream> #include <sstream> #include <string> #include <sys/stat.h> #include <unistd.h> #include <unordered_map> #include <vector> #include <cstring> #include <dirent.h> #define PROC_LOCATION "/proc" namespace Animia { namespace Linux { std::vector<std::string> get_all_files_in_dir(const std::string& _dir) { std::vector<std::string> ret; DIR* dir = opendir(_dir.c_str()); if (!dir) return ret; struct dirent* dp; while ((dp = readdir(dir)) != NULL) { if (!(!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))) ret.push_back(_dir + "/" + dp->d_name); } closedir(dir); return ret; } std::string basename(const std::string& path) { return path.substr(path.find_last_of("/") + 1, path.length()); } std::string stem(const std::string& path) { std::string bn = basename(path); return bn.substr(0, path.find_last_of(".")); } std::vector<int> get_all_pids() { std::vector<int> ret; for (const auto& dir : get_all_files_in_dir(PROC_LOCATION)) { int pid; try { pid = std::stoi(basename(dir)); } catch (std::invalid_argument) { continue; } ret.push_back(pid); } return ret; } std::string get_process_name(int pid) { std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/comm"; std::ifstream t(path); std::stringstream buf; buf << t.rdbuf(); std::string str = buf.str(); str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); return str; } static bool is_regular_file(std::string link) { struct stat sb; if (stat(link.c_str(), &sb) == -1) return false; return S_ISREG(sb.st_mode); } static bool are_flags_ok(int pid, int fd) { std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/fdinfo/" + std::to_string(fd); std::ifstream t(path); std::stringstream buffer; buffer << t.rdbuf(); std::string raw; int flags = 0; while (std::getline(buffer, raw)) { if (raw.rfind("flags:", 0) == 0) { flags = std::stoi(raw.substr(raw.find_last_not_of("0123456789") + 1)); } } if (flags & O_WRONLY || flags & O_RDWR) return false; return true; } static std::string get_name_from_fd(std::string link) { size_t exe_size = 1024; ssize_t exe_used; std::string ret; while (1) { ret = std::string(exe_size, '\0'); exe_used = readlink(link.c_str(), &ret.front(), ret.length()); if (exe_used == (ssize_t)-1) return NULL; if (exe_used < (ssize_t)1) { errno = ENOENT; return NULL; } if (exe_used < (ssize_t)(exe_size - 1)) break; exe_size += 1024; } return ret.c_str(); } std::vector<std::string> get_open_files(int pid) { std::vector<std::string> ret; std::string path = PROC_LOCATION "/" + std::to_string(pid) + "/fd"; for (const auto& dir : get_all_files_in_dir(path)) { if (!are_flags_ok(pid, std::stoi(basename(dir)))) continue; std::string buf = get_name_from_fd(dir); if (!is_regular_file(buf)) continue; ret.push_back(buf); } return ret; } std::unordered_map<int, std::vector<std::string>> get_all_open_files() { std::unordered_map<int, std::vector<std::string>> map; std::vector<int> pids = get_all_pids(); for (int i : pids) map[i] = get_open_files(i); return map; } } // namespace Linux } // namespace Animia