From 9fee532cb684ef053155b763db13401fd3da664c Mon Sep 17 00:00:00 2001 From: apocelipes Date: Mon, 4 Dec 2023 17:36:45 +0900 Subject: [PATCH] fix(CPUUsage): fix reading procfs files and simplify data parsing --- src/detection/cpuusage/cpuusage_linux.c | 38 ++++++++++++++++--------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/detection/cpuusage/cpuusage_linux.c b/src/detection/cpuusage/cpuusage_linux.c index 784f680b5..cb6101a97 100644 --- a/src/detection/cpuusage/cpuusage_linux.c +++ b/src/detection/cpuusage/cpuusage_linux.c @@ -7,30 +7,42 @@ const char* ffGetCpuUsageInfo(FFlist* cpuTimes) { - FF_AUTO_CLOSE_FILE FILE* procStat = fopen("/proc/stat", "r"); - if(procStat == NULL) + char buf[PROC_FILE_BUFFSIZ]; + ssize_t nRead = ffReadFileData("/proc/stat", sizeof(buf) - 1, buf); + if(nRead < 0) { #ifdef __ANDROID__ return "Accessing \"/proc/stat\" is restricted on Android O+"; #else - return "fopen(\"""/proc/stat\", \"r\") == NULL"; + return "ffReadFileData(\"/proc/stat\", sizeof(buf) - 1, buf) failed"; #endif } + buf[nRead] = '\0'; + // Skip first line - if (fscanf(procStat, "cpu%*[^\n]\n") < 0) - return "fscanf() first line failed"; + char *start = NULL; + if((start = strchr(buf, '\n')) == NULL) + return "skip first line failed"; + ++start; uint64_t user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0; - while (fscanf(procStat, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7) + char *token = NULL; + while ((token = strchr(start, '\n'))) { - uint64_t inUse = user + nice + system; - uint64_t total = inUse + idle + iowait + irq + softirq; + if(sscanf(start, "cpu%*d%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%" PRIu64 "%*[^\n]\n", &user, &nice, &system, &idle, &iowait, &irq, &softirq) == 7) + { + uint64_t inUse = user + nice + system; + uint64_t total = inUse + idle + iowait + irq + softirq; - FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); - *info = (FFCpuUsageInfo) { - .inUseAll = (uint64_t)inUse, - .totalAll = (uint64_t)total, - }; + FFCpuUsageInfo* info = (FFCpuUsageInfo*) ffListAdd(cpuTimes); + *info = (FFCpuUsageInfo) { + .inUseAll = (uint64_t)inUse, + .totalAll = (uint64_t)total, + }; + } + else + break; // because we read the whole /proc/stat, we can safely quit when the line does not start with "cpuN" + start = token + 1; } return NULL;