Mercurial > minori
changeset 215:031a257ee019
dep/animia: fd/proc: use std::filesystem, etc. changes
i.e. don't use std::stoi so we don't get exceptions...
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Sun, 07 Jan 2024 11:44:40 -0500 |
parents | 8d35061e7505 |
children | 8a482049b968 |
files | dep/animia/src/animia.cc dep/animia/src/fd/proc.cc |
diffstat | 2 files changed, 39 insertions(+), 52 deletions(-) [+] |
line wrap: on
line diff
--- a/dep/animia/src/animia.cc Sun Jan 07 11:19:28 2024 -0500 +++ b/dep/animia/src/animia.cc Sun Jan 07 11:44:40 2024 -0500 @@ -58,6 +58,7 @@ results.push_back({ResultType::Process, player, process, {}, {}}); break; } + return true; };
--- a/dep/animia/src/fd/proc.cc Sun Jan 07 11:19:28 2024 -0500 +++ b/dep/animia/src/fd/proc.cc Sun Jan 07 11:44:40 2024 -0500 @@ -2,68 +2,49 @@ #include "animia.h" #include "animia/util.h" -#include <algorithm> -#include <cstring> #include <filesystem> #include <fstream> #include <sstream> #include <string> -#include <unordered_map> -#include <vector> -#include <dirent.h> +#include <sys/stat.h> #include <fcntl.h> -#include <sys/stat.h> #include <unistd.h> static constexpr std::string_view PROC_LOCATION = "/proc"; namespace animia::internal::proc { -/* this uses dirent instead of std::filesystem; it would make a bit - more sense to use the latter, but this is platform dependent already :) */ -static std::vector<std::string> GetAllFilesInDir(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; -} - -static std::string Basename(const std::string& path) { - return path.substr(path.find_last_of("/") + 1, path.length()); +template<typename T = int> +static T StringToInt(const std::string& str, T def = 0) { + std::istringstream s(str); + s >> def; + return def; } static bool IsRegularFile(std::string link) { struct stat sb; if (stat(link.c_str(), &sb) == -1) return false; + return S_ISREG(sb.st_mode); } static bool AreFlagsOk(pid_t pid, int fd) { - const std::string path = std::string(PROC_LOCATION) + "/" + std::to_string(pid) + "/fdinfo/" + std::to_string(fd); + const std::filesystem::path path = std::filesystem::path(PROC_LOCATION) / std::to_string(pid) / "fdinfo" / std::to_string(fd); - std::ifstream file(path.c_str()); + std::ifstream file(path); if (!file) return false; int flags = 0; for (std::string line; std::getline(file, line); ) if (line.find("flags:", 0) == 0) - flags = std::stoi(line.substr(line.find_last_not_of("0123456789") + 1)); + flags = StringToInt(line.substr(line.find_last_not_of("0123456789") + 1)); if (flags & O_WRONLY || flags & O_RDWR) return false; + return true; } @@ -71,15 +52,16 @@ /* gets around stupid linux limitation where /proc doesn't * give actual size readings of the string */ - constexpr size_t OUT_MAX = (1 << 15); // 32KiB - out.resize(1024); + constexpr size_t OUT_MAX = (1ul << 15); // 32KiB + out.resize(32); - for (ssize_t exe_used = 0; - out.length() < OUT_MAX && exe_used >= (ssize_t)(out.length() - 1); - out.resize(out.length() * 2)) { + ssize_t exe_used = 0; + while (out.length() < OUT_MAX && exe_used >= static_cast<ssize_t>(out.length())) { + out.resize(out.length() * 2); + exe_used = readlink(link.c_str(), &out.front(), out.length()); if (exe_used == (ssize_t)-1 || exe_used < (ssize_t)1) - return false; // we got a bad result, i think + return false; // we got a bad result. SAD! } out.resize(out.find('\0')); @@ -87,32 +69,36 @@ return true; } -static std::string GetProcessName(pid_t pid) { - std::string result; - - const std::string path = std::string(PROC_LOCATION) + "/" + std::to_string(pid) + "/comm"; +static bool GetProcessName(pid_t pid, std::string& result) { + const std::filesystem::path path = std::filesystem::path(PROC_LOCATION) / std::to_string(pid) / "comm"; if (!util::ReadFile(path, result)) - return ""; + return false; result.erase(std::remove(result.begin(), result.end(), '\n'), result.end()); - - return result; + return true; } bool EnumerateOpenProcesses(process_proc_t process_proc) { bool success = false; - for (const auto& dir : GetAllFilesInDir(std::string(PROC_LOCATION))) { - pid_t pid; + + for (const auto& dir : std::filesystem::directory_iterator{PROC_LOCATION}) { + Process proc; + try { - pid = std::stoul(Basename(dir)); + proc.pid = StringToInt(dir.path().stem()); success = true; - } catch (std::invalid_argument) { + } catch (std::invalid_argument const& ex) { continue; } - if (!process_proc({pid, GetProcessName(pid)})) + + if (!GetProcessName(proc.pid, proc.name)) + continue; + + if (!process_proc(proc)) return false; } + return success; } @@ -121,14 +107,14 @@ return false; for (const auto& pid : pids) { - const std::string path = std::string(PROC_LOCATION) + "/" + std::to_string(pid) + "/fd"; + const std::filesystem::path path = std::filesystem::path(PROC_LOCATION) / std::to_string(pid) / "fd"; - for (const auto& dir : GetAllFilesInDir(path)) { - if (!AreFlagsOk(pid, std::stoi(Basename(dir)))) + for (const auto& dir : std::filesystem::directory_iterator{path}) { + if (!AreFlagsOk(pid, StringToInt(dir.path().stem()))) continue; std::string name; - if (!GetFilenameFromFd(dir, name)) + if (!GetFilenameFromFd(dir.path(), name)) continue; if (!IsRegularFile(name))