master ohmu/fastfetch-openbsd / src / detection / diskio / diskio.c
ohmu  ·  2026-10-15
 1#include "diskio.h"
 2
 3#include "common/time.h"
 4
 5const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options);
 6
 7static FFlist ioCounters1;
 8static double time1;
 9
10void ffPrepareDiskIO(FFDiskIOOptions* options) {
11    if (options->detectTotal) {
12        return;
13    }
14
15    if (time1 != 0) {
16        return; // Already prepared
17    }
18
19    // The options cannot change between this call and `ffDetectDiskIO`: `ffPrepareCommandOption`
20    // and `parseStructureCommand` both build them through `initStructureModuleOptions`, which
21    // merges the module object from the JSON config. So the baseline always matches the second
22    // snapshot and needs no re-validation.
23    ffListInit(&ioCounters1);
24    ffDiskIOGetIoCounters(&ioCounters1, options);
25    time1 = ffTimeGetTick();
26}
27
28const char* ffDetectDiskIO(FFlist* result, FFDiskIOOptions* options) {
29    const char* error = nullptr;
30
31    if (options->detectTotal) {
32        error = ffDiskIOGetIoCounters(result, options);
33        if (error) {
34            return error;
35        }
36        return nullptr;
37    }
38
39    if (time1 == 0) {
40        ffPrepareDiskIO(options);
41    }
42
43    if (ioCounters1.length == 0) {
44        return "No physical disk found";
45    }
46
47    double time2 = ffTimeGetTick();
48    while (time2 - time1 < (double) options->waitTime) {
49        ffTimeSleep((uint32_t) (options->waitTime - (time2 - time1)));
50        time2 = ffTimeGetTick();
51    }
52
53    error = ffDiskIOGetIoCounters(result, options);
54    if (error) {
55        return error;
56    }
57
58    if (result->length != ioCounters1.length) {
59        return "Different number of physical disks. Hardware change?";
60    }
61
62    for (uint32_t i = 0; i < result->length; ++i) {
63        FFDiskIOResult* icPrev = FF_LIST_GET(FFDiskIOResult, ioCounters1, i);
64        FFDiskIOResult* icCurr = FF_LIST_GET(FFDiskIOResult, *result, i);
65        if (!ffStrbufEqual(&icPrev->devPath, &icCurr->devPath)) {
66            return "Physical disk device path changed";
67        }
68
69        static_assert(sizeof(FFDiskIOResult) - offsetof(FFDiskIOResult, bytesRead) == sizeof(uint64_t) * 4, "Unexpected struct FFDiskIOResult layout");
70        for (size_t off = offsetof(FFDiskIOResult, bytesRead); off < sizeof(FFDiskIOResult); off += sizeof(uint64_t)) {
71            uint64_t* prevValue = (uint64_t*) ((uint8_t*) icPrev + off);
72            uint64_t* currValue = (uint64_t*) ((uint8_t*) icCurr + off);
73            uint64_t temp = *currValue;
74            *currValue = (uint64_t) ((double) (*currValue - *prevValue) * 1000.0 / (time2 - time1)); // Calculate per second
75
76            // For next function call
77            *prevValue = temp;
78        }
79    }
80
81    // For next function call
82    time1 = time2;
83    // Leak ioCounters1 here
84
85    return nullptr;
86}