Mercurial > minori
diff dep/animone/src/fd/proc.cc @ 301:b1f625b0227c
*: convert all files CRLF -> LF
some files were in DOS format, others were in unix. now everything
(that at least is under our control) should all be the same format
author | Paper <paper@paper.us.eu.org> |
---|---|
date | Mon, 13 May 2024 15:04:51 -0400 |
parents | 0718f538c5f9 |
children | bf89fbf7ff38 |
line wrap: on
line diff
--- a/dep/animone/src/fd/proc.cc Mon May 13 14:56:37 2024 -0400 +++ b/dep/animone/src/fd/proc.cc Mon May 13 15:04:51 2024 -0400 @@ -1,138 +1,138 @@ -#include "animone/fd/proc.h" -#include "animone.h" -#include "animone/util.h" - -#include <filesystem> -#include <fstream> -#include <sstream> -#include <string> - -#include <fcntl.h> -#include <sys/stat.h> -#include <unistd.h> - -static constexpr std::string_view PROC_LOCATION = "/proc"; - -namespace animone::internal::proc { - -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::filesystem::path path = - std::filesystem::path(PROC_LOCATION) / std::to_string(pid) / "fdinfo" / std::to_string(fd); - - 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 = util::StringToInt(line.substr(line.find_last_not_of("0123456789") + 1)); - - /* check if the file was opened in a write mode */ - int accflags = flags & O_ACCMODE; - if (accflags == O_WRONLY || accflags == O_RDWR) - return false; - - return true; -} - -static bool GetFilenameFromFd(std::string link, std::string& out) { - /* /proc is a "virtual filesystem", so we have to guess the path size. yippee! */ - constexpr size_t OUT_MAX = (1ul << 15); // 32KiB - out.resize(32); - - ssize_t exe_used = 0; - do { - 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. SAD! - } while (out.length() < OUT_MAX && exe_used >= static_cast<ssize_t>(out.length())); - - out.resize(out.find('\0')); - - return true; -} - -static bool IsSystemFile(const std::string& path) { - static constexpr std::array<std::string_view, 9> invalid_paths = {"/boot", "/dev", "/bin", "/usr", "/opt", - "/proc", "/var", "/etc", "/dev"}; - - for (const auto& invalid_path : invalid_paths) - if (!path.rfind(invalid_path, 0)) - return true; - - return false; -} - -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 false; - - result.erase(std::remove(result.begin(), result.end(), '\n'), result.end()); - return true; -} - -bool EnumerateOpenProcesses(process_proc_t process_proc) { - bool success = false; - - for (const auto& dir : std::filesystem::directory_iterator{PROC_LOCATION}) { - Process proc; - - try { - proc.pid = util::StringToInt(dir.path().stem()); - success = true; - } catch (std::invalid_argument const& ex) { - continue; - } - - if (!GetProcessName(proc.pid, proc.name)) - continue; - - if (!process_proc(proc)) - return false; - } - - return success; -} - -bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { - if (!open_file_proc) - return false; - - for (const auto& pid : pids) { - const std::filesystem::path path = std::filesystem::path(PROC_LOCATION) / std::to_string(pid) / "fd"; - - for (const auto& dir : std::filesystem::directory_iterator{path}) { - if (!AreFlagsOk(pid, util::StringToInt(dir.path().stem()))) - continue; - - std::string name; - if (!GetFilenameFromFd(dir.path(), name)) - continue; - - if (!IsRegularFile(name)) - continue; - - if (IsSystemFile(name)) - continue; - - if (!open_file_proc({pid, name})) - return false; - } - } - return true; -} - -} // namespace animia::internal::proc +#include "animone/fd/proc.h" +#include "animone.h" +#include "animone/util.h" + +#include <filesystem> +#include <fstream> +#include <sstream> +#include <string> + +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> + +static constexpr std::string_view PROC_LOCATION = "/proc"; + +namespace animone::internal::proc { + +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::filesystem::path path = + std::filesystem::path(PROC_LOCATION) / std::to_string(pid) / "fdinfo" / std::to_string(fd); + + 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 = util::StringToInt(line.substr(line.find_last_not_of("0123456789") + 1)); + + /* check if the file was opened in a write mode */ + int accflags = flags & O_ACCMODE; + if (accflags == O_WRONLY || accflags == O_RDWR) + return false; + + return true; +} + +static bool GetFilenameFromFd(std::string link, std::string& out) { + /* /proc is a "virtual filesystem", so we have to guess the path size. yippee! */ + constexpr size_t OUT_MAX = (1ul << 15); // 32KiB + out.resize(32); + + ssize_t exe_used = 0; + do { + 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. SAD! + } while (out.length() < OUT_MAX && exe_used >= static_cast<ssize_t>(out.length())); + + out.resize(out.find('\0')); + + return true; +} + +static bool IsSystemFile(const std::string& path) { + static constexpr std::array<std::string_view, 9> invalid_paths = {"/boot", "/dev", "/bin", "/usr", "/opt", + "/proc", "/var", "/etc", "/dev"}; + + for (const auto& invalid_path : invalid_paths) + if (!path.rfind(invalid_path, 0)) + return true; + + return false; +} + +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 false; + + result.erase(std::remove(result.begin(), result.end(), '\n'), result.end()); + return true; +} + +bool EnumerateOpenProcesses(process_proc_t process_proc) { + bool success = false; + + for (const auto& dir : std::filesystem::directory_iterator{PROC_LOCATION}) { + Process proc; + + try { + proc.pid = util::StringToInt(dir.path().stem()); + success = true; + } catch (std::invalid_argument const& ex) { + continue; + } + + if (!GetProcessName(proc.pid, proc.name)) + continue; + + if (!process_proc(proc)) + return false; + } + + return success; +} + +bool EnumerateOpenFiles(const std::set<pid_t>& pids, open_file_proc_t open_file_proc) { + if (!open_file_proc) + return false; + + for (const auto& pid : pids) { + const std::filesystem::path path = std::filesystem::path(PROC_LOCATION) / std::to_string(pid) / "fd"; + + for (const auto& dir : std::filesystem::directory_iterator{path}) { + if (!AreFlagsOk(pid, util::StringToInt(dir.path().stem()))) + continue; + + std::string name; + if (!GetFilenameFromFd(dir.path(), name)) + continue; + + if (!IsRegularFile(name)) + continue; + + if (IsSystemFile(name)) + continue; + + if (!open_file_proc({pid, name})) + return false; + } + } + return true; +} + +} // namespace animia::internal::proc