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))