master ohmu/fastfetch-openbsd / src / detection / diskio / diskio_bsd.c
ohmu  ·  2026-10-15
  1#include "diskio.h"
  2
  3#if __has_include(<libgeom.h>)
  4
  5    #include "common/debug.h"
  6    #include "common/strutil.h"
  7
  8    #include <devstat.h>
  9    #include <memory.h>
 10    #include <fcntl.h>
 11    #include <sys/ioctl.h>
 12    #include <sys/disk.h>
 13    #include <libgeom.h>
 14
 15    #include <errno.h>
 16    #include <string.h>
 17
 18const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) {
 19    [[gnu::cleanup(geom_deletetree)]] struct gmesh geomTree = {};
 20    if (geom_gettree(&geomTree) < 0) {
 21        FF_DEBUG("geom_gettree() failed: %s", strerror(errno));
 22        return "geom_gettree() failed";
 23    }
 24
 25    if (geom_stats_open() < 0) {
 26        FF_DEBUG("geom_stats_open() failed: %s", strerror(errno));
 27        return "geom_stats_open() failed";
 28    }
 29
 30    void* snap = geom_stats_snapshot_get();
 31    if (!snap) {
 32        FF_DEBUG("geom_stats_snapshot_get() returned null");
 33        return "geom_stats_snapshot_get() failed";
 34    }
 35
 36    struct devstat* snapIter;
 37    while ((snapIter = geom_stats_snapshot_next(snap)) != nullptr) {
 38        if (snapIter->device_type & DEVSTAT_TYPE_PASS) {
 39            continue;
 40        }
 41        struct gident* geomId = geom_lookupid(&geomTree, snapIter->id);
 42        if (geomId == nullptr) {
 43            continue;
 44        }
 45        if (geomId->lg_what != ISPROVIDER) {
 46            continue;
 47        }
 48        struct gprovider* provider = (struct gprovider*) geomId->lg_ptr;
 49        if (provider->lg_geom->lg_rank != 1) {
 50            continue;
 51        }
 52
 53        FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
 54        for (struct gconfig* ptr = provider->lg_config.lh_first; ptr; ptr = ptr->lg_config.le_next) {
 55            if (ffStrEquals(ptr->lg_name, "descr")) {
 56                ffStrbufSetS(&name, ptr->lg_val);
 57            }
 58        }
 59        if (name.length == 0) {
 60            ffStrbufSetS(&name, provider->lg_name);
 61        }
 62
 63        if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix)) {
 64            continue;
 65        }
 66
 67        FFDiskIOResult* device = FF_LIST_ADD(FFDiskIOResult, *result);
 68        ffStrbufInitF(&device->devPath, "/dev/%s", provider->lg_name);
 69        device->bytesRead = snapIter->bytes[DEVSTAT_READ];
 70        device->readCount = snapIter->operations[DEVSTAT_READ];
 71        device->bytesWritten = snapIter->bytes[DEVSTAT_WRITE];
 72        device->writeCount = snapIter->operations[DEVSTAT_WRITE];
 73        ffStrbufInitMove(&device->name, &name);
 74    }
 75
 76    geom_stats_snapshot_free(snap);
 77    geom_stats_close();
 78
 79    return nullptr;
 80}
 81
 82#else
 83
 84    #include "common/debug.h"
 85
 86    #include <devstat.h>
 87    #include <memory.h>
 88    #include <errno.h>
 89
 90const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) {
 91    if (checkversion() < 0) {
 92        FF_DEBUG("checkversion() failed: %s", strerror(errno));
 93        return "checkversion() failed";
 94    }
 95
 96    struct statinfo stats = {
 97        .dinfo = (struct devinfo*) calloc(1, sizeof(struct devinfo)),
 98    };
 99    if (getdevs(&stats) < 0) {
100        FF_DEBUG("getdevs() failed: %s", strerror(errno));
101        return "getdevs() failed";
102    }
103
104    for (int i = 0; i < stats.dinfo->numdevs; i++) {
105        struct devstat* current = &stats.dinfo->devices[i];
106        if (current->device_type & DEVSTAT_TYPE_PASS) {
107            continue;
108        }
109
110        char deviceName[128];
111        snprintf(deviceName, sizeof(deviceName), "%s%d", current->device_name, current->unit_number);
112
113        if (options->namePrefix.length && strncmp(deviceName, options->namePrefix.chars, options->namePrefix.length) != 0) {
114            continue;
115        }
116
117        FFDiskIOResult* device = FF_LIST_ADD(FFDiskIOResult, *result);
118        ffStrbufInitS(&device->name, deviceName);
119        ffStrbufInitF(&device->devPath, "/dev/%s", deviceName);
120        device->bytesRead = current->bytes_read;
121        device->readCount = current->num_reads;
122        device->bytesWritten = current->bytes_written;
123        device->writeCount = current->num_writes;
124    }
125
126    free(stats.dinfo->mem_ptr);
127    free(stats.dinfo);
128
129    return nullptr;
130}
131
132#endif